/* ============================================================
   EMBURY — design system (v615: two bindings)
   ============================================================
   The catalog peaked at 10 themes (v206-v335) and was consolidated
   to TWO in v615 (Joseph's call — see DECISIONS.md 2026-06-10).
   They map to the brand line "the book behind the bar":

      smoke (Ember) — THE BAR. Speakeasy basement: soot black,
                  candle amber, crimson leather. Dark, the DEFAULT,
                  and the :root token set. Display: sharp humanist
                  serif. Ornament: ✦ (flame star).

      ivory (Paper) — THE BOOK. Black ink on ivory paper, one
                  rubric-red accent, warm-graphite support. The
                  only light theme. Display: Iowan Old Style (the
                  body book face). Ornament: ❦ (printer's hedera).

   The binding is set by the data-theme attribute on <html>. The
   inline boot script in index.html applies it from localStorage
   before first paint (and migrates retired theme ids → smoke) to
   avoid a flash. theme.js exposes the read/write API;
   settings-view.js renders the picker.

   The 8 retired themes' CSS was removed in v615; the pre-removal
   stylesheet is archived at archive/pre-v615/embury-styles.css.
   A new binding needs a full [data-theme="X"] token block below,
   a THEMES entry in theme.js, AND the index.html boot whitelist;
   nothing inherits across bindings (other than the universals at
   :root, just below).
   ============================================================ */

/* ============================================================
   UNIVERSALS — never overridden by themes
   ============================================================ */
:root {
  /* Type stacks — body + italic + sans + mono are the same
     across every theme. Display face is theme-specific (defined
     in each theme block as --serif-display). */
  --serif:        "Iowan Old Style", "Iowan", "Hoefler Text", "Cormorant Garamond", "EB Garamond", Georgia, serif;
  --serif-italic: "Big Caslon", "Hoefler Text", "Iowan Old Style", "Garamond", Georgia, serif;
  --sans:         -apple-system, BlinkMacSystemFont, "SF Pro Text", "Inter", system-ui, sans-serif;
  --mono:         ui-monospace, "SF Mono", "Menlo", monospace;

  /* Cross-theme geometry constants. Per-theme corner radius
     lives in --radius (defined in each theme block). */
  --radius-md:    8px;
  --radius-lg:    12px;
  --hairline:     1px;

  /* Safe area */
  --safe-top:     env(safe-area-inset-top, 0);
  --safe-bottom:  env(safe-area-inset-bottom, 0);

  /* v320 — Marcus (CTO) add to Maya's audit. Modal backdrops were
     hardcoded rgba(0,0,0,0.78), which is correct on the dark theme
     but overpowering on Paper (ivory) — a near-opaque black wash on
     an ivory UI reads as broken, not focused. --scrim is the
     modal/sheet dimming token; the light theme overrides it to a
     warm-ink translucent that still focuses attention on the
     foreground sheet without nuking the rest of the page. */
  --scrim:        rgba(0, 0, 0, 0.78);     /* dark-theme default */
  --scrim-soft:   rgba(0, 0, 0, 0.32);     /* card-star + lighter overlays */
  /* Body vignette — edge-darken radial. Default is the original
     55% black wash; light themes override to a warm low-alpha tint. */
  --vignette:     radial-gradient(ellipse 120% 90% at 50% 50%, transparent 45%, rgba(0,0,0,0.55) 100%);
}

/* =============================================================
   v320 — DESIGN-SYSTEM SEMANTIC NOTES (for the next engineer)
   =============================================================
   This block is documentation, not styles. Keep it near :root so
   future theme edits land here first.

   TOKEN ROLES — what each shared variable MEANS across all bindings:

     --accent        — Primary brand color in the binding. The hero.
                       Used for tab indicators, focus rings, primary
                       buttons, links, eyebrows. Must AA-pass against
                       --bg in BOTH directions (it appears as text on
                       --bg AND text on --accent appears as
                       --on-accent). Ember: candle amber. Paper:
                       rubric red.

     --maraschino    — Secondary warm-red / warning / cherry-mood
                       accent. Used by alert/error UI (devices-error,
                       admin row-error background, comment delete
                       state). Ember: crimson leather. Paper: warm
                       graphite (the palette deliberately has no
                       second red — rubric is the only color, so the
                       warning role falls to a neutral, which is OK
                       per the original rule below). When picking
                       new themes: this token is the "warm second
                       voice" — never the primary, never neutral
                       (unless the palette has no warm secondary,
                       in which case mid-neutral is OK).

     --brass-light / --brass / --brass-deep
                     — The "gilt" gold ramp. Cuts across themes:
                       always a gold/amber family. Used for chip
                       fills, badges, decorative pinstripes. Light
                       themes use a darker --brass-deep for legible
                       text-on-cream; dark themes use --brass-light
                       for legible text-on-dark.

     --bottle        — Atmospheric "third color." Usually green
                       (cypress, palm frond, agave, hunter, banquette)
                       or earth (cedar, cocoa). Stays muted; the
                       "supporting cast" in scene terms.

     --on-accent     — Text color that sits ON TOP of --accent.
                       Dark themes: dark surface color. Light themes:
                       cream. Used by .btn (primary), .compass-chip
                       active fills. If you change --accent for any
                       theme, re-check --on-accent contrast.

     --scrim         — Modal/sheet backdrop dim. Dark themes default
                       to rgba(0,0,0,0.78); light themes override to
                       warm semi-translucent. Use var(--scrim), never
                       hardcoded rgba(0,0,0,...).

     --vignette      — Body edge-darken radial. Same dark-vs-light
                       polarity rule as --scrim.

   IF YOU ADD A NEW THEME:
     1. Set all seven semantic tokens above.
     2. Mind the --accent / --on-accent dual contrast.
     3. If the theme is LIGHT (bg luminance > 0.5), override --scrim
        and --vignette to warm low-alpha — otherwise modals will
        feel like a wall.
     4. Set --print-edition-name and --section-plate-* for the
        editorial print path.
     5. Set --accent-rgb / --maraschino-rgb / --brass-rgb /
        --bottle-rgb (comma-separated RGB ints) so the rgba(var(...))
        chip glow + atmosphere gradients land correctly.
     6. Pick a per-theme display face in --serif-display and a
        single ornament glyph in --ornament-divider /
        --ornament-section.
   ============================================================= */

/* ============================================================
   THEME — EMBER (default) — v335
   Speakeasy basement. Soot-black brick walls, candle-flame amber
   on glassware and brass tap handles, crimson leather banquette,
   graphite trim. GRIT aesthetic — opposite of the retired Walnut's
   gilded refinement.
   v335: Ember promoted from optional theme to :root default. Walnut
   tokens removed entirely; this block is the new baseline that
   every other theme inherits from until overriding.
   ============================================================ */
:root,
[data-theme="smoke"] {
  /* Surfaces — soot-black brick walls */
  --bg:           #0e0a08;
  --bg-2:         #1a1410;
  --bg-deep:      #050302;
  --surface:      #241c16;
  --surface-2:    #2e251e;
  --surface-3:    #3a3026;
  --paper:        #e8dcc0;

  /* Type — vellum on soot. Body ink AA 12+:1 on bg.
     v237 — --ink-faint lightened from #6c5e4c (~4.4:1, borderline AA)
     to #786a58 (~5.2:1, comfortable AA). */
  --ink:          #e8dcc0;
  --ink-bright:   #f5e8c4;
  --ink-dim:      #a0907a;
  --ink-faint:    #786a58;

  /* Hairlines — burnt seam + candle glow */
  --rule:         #2a2018;
  --rule-strong:  #4a3a2a;
  --rule-faint:   rgba(217, 115, 36, 0.20);
  --rule-gold:    rgba(217, 115, 36, 0.60);

  /* Accents — candle-flame amber */
  --brass-light:  #e8923c;
  --accent:       #d97324;
  --accent-2:     #e8923c;
  --accent-soft:  #3a200c;
  --brass:        #d97324;
  --brass-deep:   #8a4612;
  --gold-foil:    linear-gradient(135deg, #e8923c 0%, #d97324 30%, #8a4612 60%, #f5a854 100%);

  /* Mood — crimson leather banquette, graphite trim */
  --maraschino:   #8a1c1c;
  --maraschino-2: #a83030;
  --burgundy:     #5a1010;
  --bottle:       #3a3530;
  --bottle-2:     #524d48;
  --absinthe:     #d97324;
  --copper:       #d97324;
  --rose-gold:    #e8923c;
  --neon-amber:   #f5a854;
  --red:          #8a1c1c;

  /* Spirit bands — flame-warm */
  --spirit-whiskey:   #e0a050;
  --spirit-gin:       #889680;
  --spirit-rum:       #c89060;
  --spirit-agave:     #9aa080;
  --spirit-brandy:    #d68a50;
  --spirit-vodka:     #b0b0a8;
  --spirit-liqueur:   #b0788c;
  --spirit-aperitif:  #d65848;
  --spirit-vermouth:  #c87480;
  --spirit-wine:      #8a1c1c;
  --spirit-multi:     #e0a050;

  /* Display — sharp humanist serif, ornament: ✦ flame star */
  --serif-display: "Sentinel", "Hoefler Text", "Bodoni 72", Georgia, serif;
  --radius:        2px;

  --ornament-divider: "✦";
  --ornament-section: "✦";
  --dropcap-color:    #d97324;
  --dropcap-shadow:   0 1px 0 rgba(0,0,0,0.6);

  --dropcap-frame-bg:      rgba(217, 115, 36, 0.12);
  --dropcap-frame-border:  1px solid rgba(217, 115, 36, 0.55);
  --dropcap-frame-radius:  2px;
  --dropcap-ornament-pre:  "";
  --dropcap-ornament-post: "";

  --accent-rgb:     217, 115, 36;
  --maraschino-rgb: 138, 28, 28;
  --brass-rgb:      217, 115, 36;
  --bottle-rgb:     58, 53, 48;

  --on-accent:        #0e0a08;

  --print-edition-name: "Ember";

  --section-plate-glyph:  "✦";
  --section-plate-bg:     rgba(217, 115, 36, 0.12);
  --section-plate-border: 1px solid rgba(217, 115, 36, 0.50);
  --section-plate-radius: 2px;
  --section-plate-color:  #d97324;

  --page-edge-color:      rgba(217, 115, 36, 0.55);

  /* Texture — soft ember sparks. v235 — palette swap: was Smoke's
     #a06a3d amber, now Ember's #d97324 candle amber so the texture
     reads as floating sparks rather than stale ash. */
  --texture-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='220' height='220'><g fill='none' stroke='%23d97324' stroke-width='0.4' opacity='0.07'><path d='M10 30 Q40 20, 70 35 T130 40 T190 30'/><path d='M20 80 Q60 70, 90 90 T160 85 T210 95'/><path d='M5 130 Q45 120, 75 140 T140 135 T200 145'/><path d='M15 180 Q55 170, 85 190 T150 185 T215 195'/></g><g fill='%23d97324' opacity='0.06'><circle cx='32' cy='52' r='0.7'/><circle cx='74' cy='66' r='0.6'/><circle cx='108' cy='44' r='0.65'/><circle cx='146' cy='62' r='0.5'/><circle cx='184' cy='52' r='0.7'/><circle cx='28' cy='108' r='0.6'/><circle cx='62' cy='118' r='0.7'/><circle cx='94' cy='106' r='0.55'/><circle cx='128' cy='122' r='0.65'/><circle cx='168' cy='110' r='0.5'/><circle cx='200' cy='128' r='0.7'/><circle cx='20' cy='158' r='0.55'/><circle cx='56' cy='168' r='0.7'/><circle cx='100' cy='156' r='0.6'/><circle cx='140' cy='170' r='0.55'/><circle cx='178' cy='160' r='0.7'/></g></svg>");
  --texture-size: 220px 220px;
}

/* ============================================================
   v335 — Walnut theme retired entirely.
   ============================================================
   All v327-v334 Walnut-scoped overrides removed: book metaphor
   (cards as cream pages, inverted ink, sheets as cream paper),
   oxblood active state coverage, hover flash hotfix, sheet-body
   token redefinition. Walnut as a data-theme attribute no longer
   exists; legacy walnut localStorage values are migrated to smoke
   (Ember) by theme.js LEGACY_THEME_MAP. Ember (now :root default)
   inherits the gritty speakeasy mood that Walnut couldn't carry
   cleanly without conflict against the other warm-dark themes.
   ============================================================ */


















/* Settings gear icon — same gold treatment, palm green on focus. */



/* v615 — Paper header override. The global .app-header rule hardcodes
   a near-black gradient, which lands as a jarring strip above an ivory
   body. The Aperitivo-era answer was a DARK "Negroni glass" amaro strip
   with crystal striations — a themed object sitting on top of the page.
   Paper's answer is the opposite: the header IS the page. Ivory ground,
   ink wordmark, a single hairline rule below (a book's running head),
   rubric red only on the active tab. No texture, no gradient, no shadow
   theater. */
[data-theme="ivory"] .app-header {
  background-color: #f4efe2;
  background-image: none;
  box-shadow: 0 1px 0 rgba(21, 18, 13, 0.28);
}
[data-theme="ivory"] .app-header .brand-name {
  color: #15120d;
}
[data-theme="ivory"] .app-header .brand-tagline {
  color: #6a6356;
}
[data-theme="ivory"] .app-header .brand-chevron {
  color: #6a6356;
}
[data-theme="ivory"] .app-header .brand-mark {
  color: #15120d;
  border-color: rgba(21, 18, 13, 0.45);
}
[data-theme="ivory"] .app-header .tab {
  color: #4a443a;
}
[data-theme="ivory"] .app-header .tab:hover {
  color: #15120d;
}
[data-theme="ivory"] .app-header .tab.active {
  color: #8a2a1e;
}
[data-theme="ivory"] .app-header .tab-settings {
  color: #4a443a;
}
[data-theme="ivory"] .app-header .tab-settings:hover {
  color: #15120d;
}

/* ============================================================
   v336 — Header texture for Ember (v615: sole survivor)
   ============================================================
   Each theme's app-header used to get a material-identity texture
   overlay. v615 removed the retired themes' textures; Paper gets
   NO texture by design (its header is the page itself, above).
   Longhand background-image to avoid the v330 shorthand-cascade bug.

   EMBER (default): warm amber spark dots, like cinders drifting
   up from the candle flames in a speakeasy basement. Color
   matches --accent; very low alpha so it whispers.
   ============================================================ */
[data-theme="smoke"] .app-header {
  background-image:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='60' height='60'><g fill='%23d97324' opacity='0.10'><circle cx='8' cy='14' r='0.6'/><circle cx='24' cy='32' r='0.7'/><circle cx='42' cy='18' r='0.6'/><circle cx='52' cy='42' r='0.5'/><circle cx='14' cy='48' r='0.5'/><circle cx='35' cy='8' r='0.5'/><circle cx='48' cy='28' r='0.6'/><circle cx='20' cy='20' r='0.5'/></g></svg>"),
    linear-gradient(180deg, rgba(14,13,12,0.98) 0%, rgba(10,9,8,0.96) 100%);
  background-size: 60px 60px, auto;
  background-repeat: repeat, no-repeat;
}




















/* ============================================================
   THEME — Smuggler's Cove
   San Francisco. Rum den / ship's hold.
   Three-level themed bar (rum den, shipwreck, navy galleon).
   Dark wood walls, brass nautical fittings, rope, parchment,
   candlelight. Modern tiki authority — tasteful, not kitsch.
   This is the spiritual successor to the v54 Tiki Sunset palette.
   ============================================================ */








/* v335 — Standalone [data-theme="smoke"] block removed.
   Ember's tokens now live in the :root block at the top of this
   file (since v335 promoted Ember to the default theme). The old
   standalone selector still works because the :root block also
   matches [data-theme="smoke"] explicitly. */

/* ============================================================
   v335 — RIVIERA theme block (and all marine-scoped overrides
   throughout this file) removed. The Mediterranean blue + coral +
   cypress palette never differentiated cleanly from Amber's dark-
   teal + amber-coral; both occupied the "deep cool bg + warm
   secondary" slot. Legacy marine localStorage values are migrated
   to amber by theme.js LEGACY_THEME_MAP.
   ============================================================ */




/* ============================================================
   THEME — Ivory (v206, Wave 88)
   The first LIGHT binding. Day-bar — cream paper walls, sage
   wainscoting, brick-red banquette accents, charcoal ink. For
   daylight reading on a balcony or pre-shift prep. Every other
   theme is dark; this is the only mode-inverted binding.
   Display: Big Caslon. Ornament: ❁ (sun-flower variant).

   IMPORTANT: This is a light theme. Several tokens flip:
     - ink → dark (charcoal); bg → light (cream)
     - --rule uses rgba(charcoal, α) instead of a brighter color
     - --on-accent flips to cream
   The status-bar meta color tracks --bg via theme.js so iOS chrome
   stays in sync with the cream surface.
   ============================================================ */
[data-theme="ivory"] {
  /* v615 — REBUILT as PAPER (Joseph's call, theme consolidation).
     Was "Aperitivo" — Milanese cafe, travertine + Campari red +
     terrazzo plum + olive. Four-color editorial moods are exactly
     what the consolidation cut. The light theme is now literally the
     book page: black ink on ivory paper, one rubric-red accent (the
     printer's red ink used for initials and headings in old books —
     ties to Ember's warmth without importing a second palette), and
     warm-graphite support tones. If it wouldn't appear on a printed
     page, it's not in this theme. */

  /* Surfaces — ivory paper */
  --bg:           #f4efe2;            /* travertine */
  --bg-2:         #eae4d2;            /* lifted */
  --bg-deep:      #ddd6c0;
  --surface:      #faf6ea;            /* lit travertine */
  --surface-2:    #f2edde;
  --surface-3:    #eae4d2;
  --paper:        #ffffff;            /* print-fidelity white */

  /* Ink — book black. Near-black warm ink for body, true black for
     emphasis. This contrast IS the theme. */
  --ink:          #15120d;
  --ink-bright:   #000000;
  --ink-dim:      #4a443a;
  --ink-faint:    #6a6356;

  --rule:         rgba(28, 24, 20, 0.14);
  --rule-strong:  rgba(28, 24, 20, 0.32);
  --rule-faint:   rgba(138, 42, 30, 0.24);
  --rule-gold:    rgba(138, 42, 30, 0.58);

  /* Accent — RUBRIC RED. The single accent: the red ink medieval and
     fine-press printers reserved for initials, headings, and feast
     days. One color, used sparingly. AA-compliant on ivory. */
  --brass-light:  #a6392a;
  --accent:       #8a2a1e;            /* rubric red — the only accent */
  --accent-2:     #a6392a;
  --accent-soft:  #f0e0d6;
  --brass:        #8a2a1e;
  --brass-deep:   #5c1c12;
  --gold-foil:    linear-gradient(135deg, #a6392a 0%, #8a2a1e 30%, #5c1c12 60%, #a6392a 100%);

  /* Mood — warm graphite + muted ink-green. Support tones only; on a
     printed page these read as pencil and faded botanical-plate ink,
     never as a second accent. */
  --maraschino:   #3a3530;            /* warm graphite */
  --maraschino-2: #5a544c;
  --burgundy:     #2a2620;
  --bottle:       #5a6248;            /* muted ink-green */
  --bottle-2:     #6e7658;
  --absinthe:     #3a3530;
  --copper:       #8a2a1e;
  --rose-gold:    #b08a62;
  --neon-amber:   #a8842e;
  --red:          #8a2a1e;

  /* Spirit bands — printed-plate naturals: muted enough to sit on
     paper, distinct enough to still code spirits at a glance. */
  --spirit-whiskey:   #a06038;
  --spirit-gin:       #4a6638;
  --spirit-rum:       #a05a32;
  --spirit-agave:     #6a7a3a;
  --spirit-brandy:    #a05230;
  --spirit-vodka:     #6a7080;
  --spirit-liqueur:   #3a3530;
  --spirit-aperitif:  #8a2a1e;        /* Campari, palette match */
  --spirit-vermouth:  #983a48;
  --spirit-wine:      #6a1828;
  --spirit-multi:     #8a2a1e;        /* Campari, palette match */

  /* Display — Iowan Old Style: the book face. Same family as the body
     serif so the page reads as one typeset object, not a themed app.
     Palatino/Hoefler cover macOS-old + non-Apple falls to Georgia. */
  --serif-display: "Iowan Old Style", "Palatino", "Hoefler Text", Georgia, serif;
  --radius:        4px;

  /* Ornament — ❦ hedera (the classical printer's fleuron). The one
     piece of decoration a typeset page would actually carry. */
  --ornament-divider: "❦";
  --ornament-section: "❦";
  --dropcap-color:    #8a2a1e;
  --dropcap-shadow:   none;

  /* Light-theme dropcap frame */
  --dropcap-frame-bg:      rgba(138, 42, 30, 0.10);
  --dropcap-frame-border:  1px solid rgba(138, 42, 30, 0.50);
  --dropcap-frame-radius:  3px;
  --dropcap-ornament-pre:  "";
  --dropcap-ornament-post: "";

  --accent-rgb:     138, 42, 30;      /* rubric red */
  --maraschino-rgb: 58, 53, 48;
  --brass-rgb:      138, 42, 30;
  --bottle-rgb:     90, 98, 72;       /* ink-green */

  --on-accent:        #f4efe2;        /* ivory on rubric */

  /* Scrim — light-theme override (the dark-theme default
     rgba(0,0,0,0.78) overpowers ivory). Warm ink-tinted instead. */
  --scrim:        rgba(24, 20, 14, 0.55);
  --scrim-soft:   rgba(24, 20, 14, 0.20);
  /* Vignette — warm ink low-alpha tint. */
  --vignette:     radial-gradient(ellipse 130% 100% at 50% 50%, transparent 55%, rgba(40, 34, 24, 0.10) 100%);

  --print-edition-name: "Paper";

  --section-plate-glyph:  "❦";
  --section-plate-bg:     rgba(138, 42, 30, 0.12);
  --section-plate-border: 1px solid rgba(138, 42, 30, 0.45);
  --section-plate-radius: 50%;
  --section-plate-color:  #8a2a1e;

  --page-edge-color:      rgba(138, 42, 30, 0.55);

  /* Texture — laid paper grain. DARK particles on light bg (inverse
     of the dark themes' light-on-dark particles) so the surface reads
     as actual paper instead of plastic. */
  --texture-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='180' height='180'><g fill='%2315120d' opacity='0.04'><circle cx='12' cy='16' r='0.55'/><circle cx='42' cy='8' r='0.45'/><circle cx='72' cy='24' r='0.6'/><circle cx='102' cy='12' r='0.45'/><circle cx='132' cy='28' r='0.55'/><circle cx='162' cy='10' r='0.5'/><circle cx='24' cy='44' r='0.45'/><circle cx='56' cy='56' r='0.6'/><circle cx='86' cy='42' r='0.5'/><circle cx='116' cy='60' r='0.55'/><circle cx='146' cy='50' r='0.45'/><circle cx='8' cy='74' r='0.6'/><circle cx='46' cy='82' r='0.45'/><circle cx='78' cy='70' r='0.55'/><circle cx='108' cy='84' r='0.5'/><circle cx='138' cy='76' r='0.6'/><circle cx='168' cy='88' r='0.45'/><circle cx='28' cy='104' r='0.55'/><circle cx='62' cy='112' r='0.5'/><circle cx='90' cy='100' r='0.6'/><circle cx='118' cy='116' r='0.45'/><circle cx='148' cy='108' r='0.55'/><circle cx='14' cy='132' r='0.5'/><circle cx='52' cy='140' r='0.6'/><circle cx='82' cy='130' r='0.45'/><circle cx='110' cy='146' r='0.55'/><circle cx='140' cy='136' r='0.5'/><circle cx='170' cy='152' r='0.6'/></g></svg>");
  --texture-size: 180px 180px;
}







* { box-sizing: border-box; }
html,
body {
  margin: 0; padding: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
  overscroll-behavior-y: none;
}
/* Atmosphere — theme-driven gradient glow. Each theme contributes its own
   accent tint at the top and mood tints at the bottom; the bg fills the
   field. v54 baked Tiki Sunset coral/amber/pink into hardcoded literals
   here, which painted every theme orange even after switching. v55 routes
   the glow through theme tokens so Bemelmans gets gold-leaf ceiling glow,
   Connaught gets silver mirror, Maison Premiere gets brass + herb,
   Smuggler's Cove gets rum-amber + palm. The accent-rgb / maraschino-rgb /
   bottle-rgb tokens are defined per theme below. */
body {
  position: relative;
  background:
    radial-gradient(ellipse 80% 50% at 50% 0%, rgba(var(--accent-rgb), 0.18) 0%, rgba(var(--maraschino-rgb), 0.07) 40%, transparent 70%),
    radial-gradient(ellipse 70% 50% at 30% 100%, rgba(var(--brass-rgb), 0.10) 0%, transparent 60%),
    radial-gradient(ellipse 70% 50% at 70% 100%, rgba(var(--bottle-rgb), 0.10) 0%, transparent 60%),
    var(--bg);
}
body::before {
  /* Subtle paper grain — neutral white tint at very low alpha, so the
     texture reads on every theme without imposing a warm-cream cast.
     v74: stacks a per-binding texture beneath the paper grain.
     The texture is themed (leather / pinstripe / botanical / wood),
     declared via --texture-image + --texture-size per theme block.
     Each binding now feels like a different surface, not just a
     different palette over the same canvas. */
  content: "";
  position: fixed; inset: 0;
  background-image:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='240' height='240'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 1  0 0 0 0 1  0 0 0 0 1  0 0 0 0.018 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>"),
    var(--texture-image, none);
  background-size:
    240px 240px,
    var(--texture-size, 200px 200px);
  background-repeat: repeat, repeat;
  pointer-events: none;
  z-index: 0;
}
body::after {
  /* Vignette — neutral darken at the edges, spotlight at center.
     v320 — Uses --vignette token so light themes can opt out
     (a 55% black radial wash on a sand-cream UI reads as moldy
     paper, not editorial). Default = the original dark wash;
     Pineapple + Aperitivo override to a much lighter warm tint. */
  content: "";
  position: fixed; inset: 0;
  background: var(--vignette);
  pointer-events: none;
  z-index: 0;
}
#app { position: relative; z-index: 1; }
body { min-height: 100vh; min-height: 100dvh; }

input,
textarea,
select,
button { font-family: inherit; color: inherit; }
button { background: none; border: 0; padding: 0; cursor: pointer; }

/* ============================================================================
   v54 — Canonical .input style. Every <input class="input">, <textarea
   class="input">, and <select class="input"> uses this. Without it, iOS
   Safari (and a few other browsers) fall back to a white background with
   pale text — nearly unreadable on the deep teal canvas. This block also
   defeats Chrome's yellow autofill paint and gives focus a visible accent.
   ============================================================================ */
.input {
  background: var(--bg-2);
  color: var(--ink);
  border: 1px solid var(--rule-strong);
  border-radius: 6px;
  padding: 10px 12px;
  font-family: inherit;
  font-size: 15px;
  line-height: 1.4;
  width: 100%;
  outline: none;
  transition: border-color 120ms ease, background 120ms ease;
  -webkit-text-fill-color: var(--ink);  /* iOS Safari ignores `color` on
                                           inputs without this */
  caret-color: var(--accent);
  appearance: none;
  -webkit-appearance: none;
}
.input::placeholder {
  color: var(--ink-faint);
  font-style: italic;
  opacity: 1;
}
.input:focus {
  border-color: var(--accent);
  background: var(--surface);
}
.input:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}
textarea.input {
  resize: vertical;
  min-height: 60px;
  line-height: 1.5;
}
select.input {
  cursor: pointer;
  background-image:
    linear-gradient(45deg, transparent 50%, var(--ink-faint) 50%),
    linear-gradient(-45deg, transparent 50%, var(--ink-faint) 50%);
  background-position:
    calc(100% - 18px) 50%,
    calc(100% - 12px) 50%;
  background-size: 6px 6px;
  background-repeat: no-repeat;
  padding-right: 32px;
}
/* Defeat Chrome / Edge autofill yellow paint */
.input:-webkit-autofill,
.input:-webkit-autofill:hover,
.input:-webkit-autofill:focus,
.input:-webkit-autofill:active {
  -webkit-text-fill-color: var(--ink) !important;
  -webkit-box-shadow: 0 0 0 30px var(--bg-2) inset !important;
  caret-color: var(--accent);
  transition: background-color 5000s ease-in-out 0s;
}
/* Number inputs — strip the spinner buttons; bartenders use the keyboard */
.input[type=number]::-webkit-inner-spin-button,
.input[type=number]::-webkit-outer-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
.input[type=number] { -moz-appearance: textfield; }
/* Date / time inputs — keep cursor visible against dark background.
   v340: scoped — the native picker UI matches the theme bg surface.
   Dark themes get the dark native picker (default below). Light themes
   (Pineapple, Aperitivo) get the light picker so a dark native widget
   doesn't appear over cream content. */
.input[type=date],
.input[type=time],
.input[type=datetime-local] {
  color-scheme: dark;
}
[data-theme="ivory"] .input[type=date],
[data-theme="ivory"] .input[type=time],
[data-theme="ivory"] .input[type=datetime-local] {
  color-scheme: light;
}

a { color: var(--accent-2); text-decoration: none; transition: color .15s; }
a:hover { color: var(--accent); }
a:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 2px;
}

/* ============================================================
   APP SHELL
   ============================================================ */
#app {
  display: flex; flex-direction: column;
  min-height: 100vh; min-height: 100dvh;
  padding-top: var(--safe-top);
}

.app-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 22px;
  border-bottom: var(--hairline) solid var(--rule);
  background: linear-gradient(180deg, rgba(14,13,12,0.98) 0%, rgba(10,9,8,0.96) 100%);
  backdrop-filter: blur(8px);
  position: sticky; top: 0; z-index: 10;
  box-shadow: 0 2px 0 rgba(0,0,0,0.5), 0 3px 0 var(--rule-faint), 0 8px 24px rgba(0,0,0,0.3);
}
.brand { display: flex; align-items: center; gap: 12px; }

/* v104 — Brand-as-button dropdown trigger. When the brand is the menu
   trigger (the .brand-button variant), we add a small chevron after the
   wordmark and let it behave like a button. */
.brand-button {
  background: transparent;
  border: 0;
  padding: 4px 6px 4px 4px;
  margin: -4px -6px -4px -4px;
  cursor: pointer;
  border-radius: 6px;
  font-family: inherit;
  color: inherit;
  position: relative;
  transition: background 150ms ease;
}
/* v328 — Brand-button hover halo retired.
   Was: paint a soft accent-tinted rectangle behind the wordmark on
   hover. On Velvet that rendered as a bright magenta CTA-button
   rectangle behind EMBURY; on Walnut a gold rectangle; on every
   theme it read as "tacky button hover" rather than "brand mark
   you can tap." The chevron color change below + cursor: pointer
   already signal affordance; we don't need the box.
   Keyboard focus still gets a visible outline. */
.brand-button:hover { background: transparent; }
.brand-button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
/* v216 — Brand chevron bumped from 11px ink-faint to 13px ink-dim so it
   reads as a deliberate "tap for menu" affordance, not decoration.
   Previously many users didn't realize the brand mark was tappable. */
.brand-chevron {
  font-size: 13px;
  color: var(--ink-dim);
  margin-left: 4px;
  transition: transform 200ms ease, color 150ms ease;
  display: inline-block;
  line-height: 1;
}
.brand-button:hover .brand-chevron { color: var(--accent); }
.brand-button[aria-expanded="true"] .brand-chevron {
  transform: rotate(180deg);
  color: var(--accent);
}

.brand-menu {
  position: absolute;
  top: calc(100% - 6px);
  left: 12px;
  z-index: 1500;
  min-width: 220px;
  padding: 8px 0;
  background: rgba(20, 14, 8, 0.98);
  border: 1px solid var(--rule);
  border-radius: 8px;
  box-shadow: 0 12px 36px rgba(0, 0, 0, 0.55);
  opacity: 0;
  transform: translateY(-6px);
  transition: opacity 180ms ease, transform 180ms ease;
  pointer-events: none;
  backdrop-filter: blur(8px);
}
.brand-menu.is-open {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}
/* v216 — Respect the [hidden] attribute. .brand-menu-item sets
   display: flex which beats UA [hidden] { display: none } on specificity,
   so the "Sync conflicts" row (and the v215 "Sign in to sync" row when
   the user is signed in) would render anyway. Higher-specificity rule
   pins display: none when hidden, restoring the expected behavior. */
.brand-menu-item[hidden] {
  display: none !important;
}
.brand-menu-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 16px;
  color: var(--ink-dim);
  font-size: 14px;
  letter-spacing: 0.04em;
  text-decoration: none;
  transition: background 120ms ease, color 120ms ease;
  /* v109 — Wave 52: handle button variants identically to the anchor
     variants. AI Tools + Force re-sync are <button> elements so default
     UA styles (border, background, text-align) need to be neutralized. */
  background: transparent;
  border: 0;
  width: 100%;
  text-align: left;
  font-family: inherit;
  cursor: pointer;
}
.brand-menu-item svg {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  color: var(--accent);
}
.brand-menu-item:hover {
  background: var(--accent-soft, rgba(202,164,90,0.10));
  color: var(--ink);
}
.brand-menu-item:active {
  background: var(--accent-soft, rgba(202,164,90,0.18));
}
/* v88 — brand-mark redesigned as a tiny title plate (matches the new
   Spine icon). Was a circle with an italic "E"; now reads as a small
   rectangular plate with double-rule frame and an illuminated italic E
   centered — like a miniature version of the spine's title plate. */
.brand-mark {
  width: 30px; height: 36px;
  border: 1px solid var(--accent);
  border-radius: 2px;
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--serif-display); font-style: italic;
  background: transparent;
  color: var(--accent);
  font-size: 21px; line-height: 1;
  letter-spacing: 0;
  font-weight: 500;
  position: relative;
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.35);
}
.brand-mark::after {
  /* Inner double-rule frame, like the title plate on the icon */
  content: "";
  position: absolute;
  inset: 3px;
  border: 0.5px solid var(--accent);
  opacity: 0.5;
  pointer-events: none;
  border-radius: 1px;
}
.brand-name {
  font-family: var(--serif-display); font-size: 18px;
  letter-spacing: 0.32em; font-weight: 400;
  color: var(--accent-2);
  text-shadow: 0 1px 0 rgba(0,0,0,0.5);
}
/* v188 — brand stack: wordmark + small italic tagline beneath. Keeps
   header height nearly the same (~3px taller) by tightening line-height
   and using a tiny tagline. Tagline hides on the narrow mobile breakpoint
   alongside the wordmark to keep the header compact. */
.brand-stack {
  display: inline-flex;
  flex-direction: column;
  align-items: flex-start;
  line-height: 1;
  gap: 2px;
}
.brand-tagline {
  font-family: var(--serif-italic);
  font-style: italic;
  font-weight: 400;
  font-size: 10px;
  letter-spacing: 0.06em;
  color: var(--ink-faint);
  text-shadow: none;
  text-transform: none;
  white-space: nowrap;
}
/* v216 — Hide the tagline on very narrow viewports where it would either
   wrap weirdly under the wordmark or clip against the brand chevron.
   The wordmark + chevron + nav fit comfortably on phones ≤360px; the
   tagline is decoration, not navigation. */
@media (max-width: 360px) {
  .brand-tagline { display: none; }
}

.tabs { display: none; gap: 22px; align-items: center; }
.tab {
  /* v320 — Casing sweep per Sarah (CMO) voice rubric: top-nav tabs
     render Title Case ("Journal", "Recipes", "Build", "Library",
     "Profile") instead of small-caps editorial ("JOURNAL", etc.).
     The book metaphor argues for chapter-name Title Case over
     magazine-style caps. Letter-spacing eased from 0.14em to 0.03em,
     size lifted from 12 to 13 to compensate for the cap-height drop.
     Source strings in index.html still need to be re-cased; the CSS
     change defers to source casing — no more text-transform. */
  color: var(--ink-dim); font-size: 13px; font-weight: 500;
  letter-spacing: 0.03em;
  padding: 8px 4px; border-bottom: 2px solid transparent;
  transition: color .15s, border-color .15s;
}
.tab:hover { color: var(--ink); }
.tab.active {
  color: var(--accent);
  border-bottom-color: var(--accent);
}
.tab-settings {
  padding: 12px;
  min-width: 44px; min-height: 44px;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--ink-dim);
}
.tab-settings:hover { color: var(--accent); }
.tab-settings svg { display: block; }
.tab-settings:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px; border-radius: 6px;
}

.card,
.tag-chip { -webkit-touch-callout: none; }

@media (min-width: 720px) {
  .tabs { display: flex; }
}

/* ============================================================
   BOTTOM TABS (mobile)
   ============================================================ */
.bottom-tabs {
  position: fixed; bottom: 0; left: 0; right: 0;
  display: flex;
  /* v237 — was rgba(10, 9, 8, 0.96) hardcoded, which painted a near-
     black slab on Aperitivo (the only light theme) and made the cream
     UI end in a dark wall. color-mix uses the active theme's --bg so
     every theme gets a slightly-translucent version of its own surface. */
  background: color-mix(in srgb, var(--bg) 92%, transparent);
  backdrop-filter: blur(12px);
  border-top: var(--hairline) solid var(--rule);
  padding-bottom: var(--safe-bottom);
  z-index: 10;
}
.bottom-tab {
  flex: 1;
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  padding: 10px 0;
  /* v172 — idle color brightened from --ink-faint (#8a7a5e) to --ink-dim
     so the redrawn bartender-specific icons feel present rather than ghostly.
     Active state stays gold so the contrast on selection still pops. */
  color: var(--ink-dim);
  /* v320 — Casing sweep: bottom mobile nav labels render Title Case
     ("Journal / Recipes / Build / Library / Profile") to match the
     top-nav .tab rule. Size 10->11 to compensate for cap-height drop. */
  font-size: 11px; letter-spacing: 0.03em;
  transition: color .15s;
  /* v109 — Remove the 300ms tap delay AND prevent any double-tap zoom
     from re-firing the activation. Each tab also gets a hard right
     boundary so adjacent taps don't ambiguously hit both targets. */
  touch-action: manipulation;
  -webkit-tap-highlight-color: rgba(255, 255, 255, 0.05);
  position: relative;
}
/* v109 — Visual + functional 2px separator between bottom tabs. The gap
   itself isn't tappable (no flex child to receive the event), giving the
   user a clear "miss" zone between adjacent tabs that prevents accidental
   jumps to /profile when reaching for /reference (the 5th tab). */
.bottom-tab:not(:last-child)::after {
  content: "";
  position: absolute;
  right: 0; top: 14px; bottom: 14px;
  width: 1px;
  background: color-mix(in srgb, var(--rule) 60%, transparent);
  pointer-events: none;
}
.bottom-tab svg { width: 22px; height: 22px; transition: transform .18s ease-out, color .15s; }
.bottom-tab.active { color: var(--accent); }
.bottom-tab.active svg { transform: scale(1.08); }
/* Subtle hover/focus lift on desktop — gives feedback before commit on
   mouse-and-keyboard. No-op on touch via @media. */
@media (hover: hover) {
  .bottom-tab:hover { color: var(--ink); }
  .bottom-tab:hover svg { transform: translateY(-1px); }
  .bottom-tab.active:hover svg { transform: scale(1.08) translateY(-1px); }
}
.bottom-tab:active svg { transform: scale(0.94); }
.bottom-tab.active:active svg { transform: scale(1.0); }
/* v172 — Active-tab gold indicator. A small accent bar at the very top of
   the active tab makes the current section unambiguously legible at a glance,
   matching the print-aesthetic feel of a leather book bookmark. */
.bottom-tab::before {
  content: "";
  position: absolute;
  top: 0; left: 50%;
  width: 28px; height: 2px;
  background: var(--accent);
  transform: translate(-50%, -100%);
  border-radius: 0 0 2px 2px;
  transition: transform .18s ease-out, opacity .18s ease-out;
  opacity: 0;
  pointer-events: none;
}
.bottom-tab.active::before {
  transform: translate(-50%, 0);
  opacity: 1;
}

@media (min-width: 720px) { .bottom-tabs { display: none; } }

/* On the narrowest phones (≤400px), the 7-tab bottom nav gets tight. Tighten
   letter-spacing + reduce font + shrink horizontal padding so REFERENCE and
   SETTINGS still fit comfortably without truncation. The icon takes priority
   visually; the label is supportive. */
@media (max-width: 400px) {
  .bottom-tab {
    font-size: 9px;
    letter-spacing: 0.08em;
    padding: 10px 2px;
  }
  .bottom-tab svg { width: 20px; height: 20px; }
}

/* ============================================================
   VIEW
   ============================================================ */
.view {
  flex: 1;
  /* v517 — was padding-bottom: 110px. On iPhones with a home indicator
     the bottom nav is ~80px tall + ~34px safe-area = ~114px, so the last
     card got clipped by the nav (caught by Joseph on the Journal empty
     state — "House Old Fashioned" starter card cut off). Adding the
     safe-area into the calc keeps content visible above both the nav
     and the indicator on every device. */
  padding: 18px 22px calc(110px + var(--safe-bottom));
  max-width: 880px;
  width: 100%;
  margin: 0 auto;
}
@media (min-width: 720px) {
  .view { padding-bottom: 40px; }
}

.view-header {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 12px;
  /* v555 — Trimmed: margin 6/24 → 4/14, padding 8/16 → 4/10, border
     1.5px solid accent → 1px at 40% opacity. The heavy gold underline
     across every view title felt like a marquee separator from a 2010-era
     editorial template; the tighter, softer rule now reads as a subtle
     end-of-header cue instead of a billboard frame. Combined with the
     smaller view-title font (clamp 28/36 instead of 34/44), each page
     now starts ~30px earlier in the viewport. */
  margin: 4px 0 14px;
  padding: 4px 0 10px;
  border-bottom: 1px solid rgba(var(--accent-rgb), 0.4);
  position: relative;
}
/* Wave 111 — On narrow viewports, stack the view header so a long
   subtitle doesn't wrap awkwardly next to the giant view-title. The
   Profile heading was the most visible victim of this — its subtitle
   "Your bartender resume + portfolio…" used to hug the right edge,
   collapsing into 2–3 lines beside the H1. Now it sits below. */
@media (max-width: 560px) {
  .view-header {
    flex-direction: column;
    align-items: flex-start;
  }

  /* v218 — Pin the Profile gear to the top-right of the view-header on
     mobile so Profile's long subtitle can wrap under the h1, not next
     to the gear. The view-header is already position: relative (above).
     v468 — Journal action-row is NO LONGER absolute-pinned. With three
     pills (+ New entry, + New menu, AI) the 150px reservation that
     worked for two pills (v218/v264) no longer fits — pills overflow
     left, sliding over the "Journal" title. We now let the action row
     stack BELOW the title using the column flex above (set on
     `.view-header`), full-width and right-aligned. Tradeoff: takes one
     extra row of vertical space on phones, but the title stays
     readable and the action affordances stay tappable. */
  .view-header .profile-gear-link {
    position: absolute;
    top: 8px;
    right: 0;
    margin: 0;
    z-index: 1;
  }
  /* v468 — let the action row claim the full content width below the
     title so all three pills can sit on one line (right-aligned, see
     the @media ≤479px rule below). */
  .view-header .journal-header-actions {
    width: 100%;
  }
  /* Profile only needs room for a 36px gear + a small breathing margin. */
  .view-header:has(.profile-gear-link) {
    padding-right: 48px;
  }
}

/* v264 → v468 — Mobile button size + spacing fix on Journal header.
   ----------------------------------------------------------
   v263 originally stacked the action row below the title on narrow
   viewports. v218 then absolute-pinned it back up; v264 shrunk the
   pills so a 2-pill row fit in the 150px right reservation. v439
   added a third pill (+ New menu) which broke the math — three pills
   exceed 150px even at btn-sm size, so they overflowed the title.
   v468 returned to the v263 stack-below-title approach (see the
   parent @media ≤560px rule). This block continues to right-align
   the actions and shrinks the pills to keep them visually subordinate
   to the H1 — that part of v264 still applies.

   Result: the title stays the hero, the buttons sit on a single line
   right-aligned below it, no overlap regardless of pill count. */
@media (max-width: 479px) {
  .journal-header .journal-header-actions {
    justify-content: flex-end;
    gap: 8px;
    margin-top: 6px;
    margin-bottom: 4px;
  }
  .journal-header .journal-header-actions .btn-pill.btn-sm {
    /* Shrink from full mobile button size to a more compact pill */
    padding: 6px 14px !important;
    font-size: 10.5px !important;
    letter-spacing: 0.14em !important;
    min-height: 32px !important;
    line-height: 1 !important;
  }
}
/* v327 — view-header::before retired.
   --------------------------------------------------------------
   Was a tiny 8px ◆ in --accent above every view title, intended as
   an Art Deco menu marker. Failed the "doesn't need explanation"
   test — read as a UI element ("status indicator? badge? unread
   mark?") rather than as ornament. The ❦ fleuron we already
   surface in drop caps and section heads carries the
   Deco-typography signal where it belongs; view-headers don't
   need a second hat. */

.view-header::after {
  content: "";
  position: absolute; left: 0; right: 0; bottom: -4px;
  height: 1px; background: var(--rule-gold);
}

/* v327 → v328 → v328.2 — Pineapple/Aperitivo double-rule removed.
   --------------------------------------------------------------
   v327 attempted to whisper the second hairline by swapping to
   --rule-faint (18% alpha). Joseph still reported "I'm still
   seeing double in Pineapple" — at 1px a faint line is still a
   visible line, especially against bright cream. On light themes
   the Deco two-rule motif doesn't earn its keep at all; the
   single primary accent line under the view-header reads fine
   on its own. Outright remove the ::after on the actual light
   themes (Pineapple = platinum, Aperitivo = ivory) so nothing
   competes with the title's primary underline.

   v328.2 audit catch — Rose was incorrectly included here in
   v328.1 on the assumption that "champagne salon" implied a
   cream/pink light bg. Wrong: Rose's --bg is #0a0608 (near-black
   plum). It's a DARK theme — the rose-gold accent on dark plum
   is the whole point. Removed from this list so Rose keeps the
   Deco double-rule like Walnut/Verdant/Amber/etc. Read tokens,
   don't read names. */
[data-theme="ivory"] .view-header::after {
  display: none;
}

/* v329 — view-title heavy drop shadow disabled on light themes.
   --------------------------------------------------------------
   The base .view-title rule sets `text-shadow: 0 2px 0
   rgba(0, 0, 0, 0.7)` — a hard black letterpress shadow under
   every letter of every h1. Designed for dark themes (Walnut,
   Verdant, Velvet, Onyx, etc.) where black-on-dark vanishes into
   the bg and just lends a faint depth. On light themes (Pineapple
   cream, Aperitivo travertine) the same shadow is the loudest
   thing on the page — every letter reads as doubled/misprinted,
   like a 4-color press out of registration. This has been in
   production since the multi-theme split; the audit's state +
   theme matrix missed it because we never enumerated typography
   effects. Joseph spotted it. Disable the dark shadow on light
   themes; keep only the ambient accent glow so the title still
   has a soft halo. */
[data-theme="ivory"] .view-title {
  text-shadow: 0 0 40px rgba(var(--accent-rgb), 0.18);
}

/* v339 — Defensive text-shadow scoping for light themes.
   --------------------------------------------------------------
   Four other elements in the codebase use dark drop shadows that
   were designed for dark themes and would render as doubled-
   letterpress on cream. .ingredient-list .amount is the most
   visible risk — Pineapple and Aperitivo recipe-detail sheets
   render on cream bg (because .sheet uses var(--bg) which is
   cream for both light themes). The italic gold amount text
   would otherwise show a hard black drop shadow underneath each
   letter — same pathology as the v329 .view-title fix.

   .brand-mark, .brand-name, .card-thumb also have dark shadows
   but currently live on dark surrounds (the app-header is always
   dark, even on light themes; .card-thumb has its own dark inline
   bg). Defensively scoped here so any future layout change that
   moves these onto cream doesn't reintroduce the pathology. */
[data-theme="ivory"] .ingredient-list .amount,
[data-theme="ivory"] .brand-mark,
[data-theme="ivory"] .brand-name,
[data-theme="ivory"] .card-thumb {
  text-shadow: none;
}
.view-title {
  font-family: var(--serif-display);
  /* v237 — was 44px hardcoded; clamp keeps it from crashing the Profile
     gear icon on 360px narrow phones.
     v555 — Trimmed from clamp(34, 9vw, 44px) to clamp(28, 7vw, 36px).
     The 44px max was a marquee treatment that ate the whole top of every
     view; pulling it down ~20% recovers vertical for the tile grids on
     Build, the journal feed, the recipe lists, etc. The title still
     reads as Serif Display brand chrome, just no longer billboard-sized. */
  font-size: clamp(28px, 7vw, 36px);
  font-weight: 400;
  margin: 8px 0 0; letter-spacing: 0.01em; line-height: 1;
  color: var(--ink-bright);
  /* v237 — was rgba(216, 144, 89, 0.18) hardcoded Walnut-gold, which
     bled a warm halo behind every theme's titles (Vapor cyan, Aperitivo
     orange, Velvet magenta all carried a stale gold ghost). Now uses
     the active theme's --accent-rgb so the halo matches the palette. */
  text-shadow:
    0 2px 0 rgba(0, 0, 0, 0.7),
    0 0 40px rgba(var(--accent-rgb), 0.18);
}
.view-actions { display: flex; gap: 8px; }

/* ============================================================
   SEARCH
   ============================================================ */
.search { position: relative; margin: 0 0 18px; }
.search input {
  width: 100%; box-sizing: border-box;
  background: var(--bg-2);
  border: var(--hairline) solid var(--rule);
  border-radius: 999px;
  padding: 12px 16px 12px 40px;
  font-size: 15px; color: var(--ink);
  font-family: var(--sans);
  letter-spacing: 0.005em;
  transition: border-color .15s, background .15s;
}
.search input::placeholder { color: var(--ink-faint); font-style: italic; }
.search input:focus {
  outline: none;
  border-color: var(--accent);
  background: var(--surface);
}
.search::before {
  content: ""; position: absolute; left: 14px; top: 50%;
  width: 18px; height: 18px; transform: translateY(-50%);
  /* v173 — Stroke bumped 1.6→1.8 and color brightened from #8e8670 to #a89678
     so the magnifier sits cleanly with the other refreshed icons. */
  background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23a89678' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'><circle cx='11' cy='11' r='7'/><path d='m21 21-4.3-4.3'/></svg>") center/contain no-repeat;
}

/* ============================================================
   LISTS — menu-style line items
   ============================================================ */
.list { display: flex; flex-direction: column; gap: 0; }
.card {
  position: relative;
  background: transparent;
  border: 0;
  border-bottom: var(--hairline) solid var(--rule);
  padding: 16px 4px 16px 14px;
  display: flex; gap: 14px; align-items: flex-start;
  cursor: pointer;
  transition: background .2s, padding .2s, transform .15s;
  border-radius: 0;
  overflow: hidden;
}
.card:first-child { border-top: var(--hairline) solid var(--rule); }
/* Spirit-coded color band along the left edge — set via inline style on element. */
.card::before {
  content: "";
  position: absolute;
  left: 0; top: 8px; bottom: 8px;
  width: 4px;
  background: linear-gradient(180deg,
    var(--card-spirit-color, var(--rule-strong)) 0%,
    var(--card-spirit-color, var(--rule-strong)) 60%,
    color-mix(in srgb, var(--card-spirit-color, #555) 55%, black) 100%
  );
  opacity: 0.85;
  transition: opacity .2s, width .2s, box-shadow .25s;
  border-radius: 0 2px 2px 0;
}
.card:hover {
  background:
    linear-gradient(90deg,
      color-mix(in srgb, var(--card-spirit-color, var(--accent)) 12%, transparent) 0%,
      color-mix(in srgb, var(--card-spirit-color, var(--accent)) 4%, transparent) 50%,
      transparent 100%);
  padding-left: 24px;
}
.card:hover::before {
  opacity: 1;
  width: 5px;
  box-shadow: 0 0 14px var(--card-spirit-color, transparent), 0 0 4px var(--card-spirit-color, transparent);
}
.card:active { transform: scale(0.998); }

/* Numbered cocktail prefix — small italic count above the title */
.card-num {
  font-family: var(--serif-italic);
  font-style: italic;
  color: var(--brass);
  font-size: 11px;
  letter-spacing: 0.32em;
  margin-bottom: 4px;
  display: block;
  text-transform: uppercase;
}

/* Bottle silhouette card thumbnail — replaces monogram for cocktail cards.
   Background is darker than --surface-2 so the bright bottle silhouettes
   pop crisply against the dark interior of the "case." */
.bottle-thumb {
  width: 56px; height: 68px;
  border-radius: 4px;
  border: 1px solid var(--rule-strong);
  /* v55: was hardcoded teal #0a1620/#050b13 — now follows theme via
     --bg-deep + --bg, so the bottle silhouette plate inherits the
     book-spine / mirror / foliage / hold mood per theme. */
  background:
    radial-gradient(ellipse at 30% 20%, rgba(255, 245, 221, 0.05), transparent 60%),
    linear-gradient(180deg, var(--bg-deep) 0%, var(--bg) 100%);
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  box-shadow:
    inset 0 1px 0 rgba(255, 245, 221, 0.06),
    inset 0 -2px 10px rgba(0, 0, 0, 0.65),
    0 2px 6px rgba(0, 0, 0, 0.6);
  position: relative;
  overflow: hidden;
}
.bottle-thumb::after {
  /* Subtle highlight edge — like a glass reflection on the bottle */
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 30%;
  background: linear-gradient(90deg, rgba(255, 245, 221, 0.08), transparent);
  pointer-events: none;
}
.bottle-silhouette {
  width: 38px; height: 50px;
  display: flex; align-items: center; justify-content: center;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.5));
}
.bottle-silhouette svg {
  width: 100%; height: 100%; display: block;
  stroke-width: 0.6;
  opacity: 0.92;
}

.card-thumb {
  width: 56px; height: 56px;
  border-radius: 4px;
  background:
    radial-gradient(circle at 30% 30%, rgba(255, 245, 221, 0.10), transparent 60%),
    var(--surface-2);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--serif-display); font-style: italic; font-size: 28px;
  color: var(--accent-2);
  flex-shrink: 0;
  background-size: cover; background-position: center;
  border: 1px solid var(--rule-strong);
  letter-spacing: -0.02em;
  box-shadow: inset 0 1px 0 rgba(255,245,221,0.06), 0 2px 6px rgba(0,0,0,0.5);
  text-shadow: 0 1px 0 rgba(0,0,0,0.4);
}
.card-body { flex: 1; min-width: 0; }
.card-title {
  /* v320 — Maya audit catch + Anna non-negotiable: titles in lists
     must be upright serif, not italic. Italic body at small-to-medium
     sizes on dark is hard to scan with wet hands in a loud bar.
     The rule already used --serif (upright) without italic, but adding
     `font-style: normal` defensively guards against any cascade or
     theme override that re-introduces italic on a list card. */
  font-family: var(--serif); font-size: 20px; font-weight: 500;
  font-style: normal;
  margin: 0 0 4px; line-height: 1.2;
  color: var(--ink-bright);
  letter-spacing: 0.005em;
}
.card-meta {
  /* v616 — Core reading surface: list-card / journal-card byline meta
     (category · ABV · spirit) was 11px. Raised to the 12px floor for
     at-arm's-length scanning. Already --ink-dim, so no color change. */
  font-size: 12px; color: var(--ink-dim);
  letter-spacing: 0.08em; text-transform: uppercase;
  font-weight: 500;
}
/* v320 — Maya audit + Sarah (CMO) directive: kill the all-caps prose
   bodies on Library entry cards ("AMERICAN WHISKEY MADE FROM AT LEAST
   51% CORN…"). Sarah: "That's not encyclopedic, that's a Wikipedia
   infobox cosplaying as a spec sheet. Encyclopedic authority comes
   from typography and restraint, not volume." Short labels (whiskey
   category, ABV) keep uppercase via .card-meta; the prose description
   moves to .card-summary, sentence case, normal letter-spacing. */
.card-summary {
  font-size: 12px; color: var(--ink-faint);
  letter-spacing: 0; text-transform: none;
  font-weight: 400;
  line-height: 1.45;
  margin-top: 4px;
}
.card-tags {
  display: flex; gap: 6px; flex-wrap: wrap; margin-top: 8px;
}

.tag {
  display: inline-block; padding: 3px 10px;
  border: var(--hairline) solid var(--rule-strong);
  border-radius: 999px;
  font-size: 10px; color: var(--ink-dim);
  letter-spacing: 0.12em; text-transform: uppercase;
  font-weight: 500;
}
.tag.score {
  background: var(--accent-soft); color: var(--accent-2);
  border-color: var(--accent);
  font-family: var(--serif); font-size: 12px;
  padding: 2px 10px;
  letter-spacing: 0.04em; text-transform: none;
}

/* ============================================================
   EMPTY STATE
   ============================================================ */
.empty {
  text-align: center; padding: 80px 20px; color: var(--ink-dim);
}
.empty h3 {
  font-family: var(--serif-display); font-size: 24px;
  color: var(--ink); font-weight: 400;
  margin: 0 0 10px;
  letter-spacing: 0.005em;
}
.empty p {
  margin: 0 0 22px; font-size: 15px;
  font-style: italic; line-height: 1.55;
}

/* ============================================================
   SECTION HEADERS — letterpress style
   ============================================================ */
.section-header {
  font-size: 10px; letter-spacing: 0.22em;
  text-transform: uppercase; color: var(--accent);
  margin: 26px 0 12px;
  padding: 0 4px 6px;
  border-bottom: var(--hairline) solid var(--rule-faint);
  font-weight: 600;
}
.section-header:first-child { margin-top: 0; }

/* ============================================================
   FILTER CHIPS
   ============================================================ */
.chip-row {
  display: flex; gap: 8px;
  overflow-x: auto;
  padding: 0 4px 16px;
  margin: 0 -4px;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  /* v216 — Stronger fade so the right-edge cutoff reads clearly as "swipe
     for more." Was 24px which was visually too subtle on dark themes;
     bumped to 56px and the fade starts earlier (at 88%) so the last chip
     softly dims before being clipped. Mask, not overlay, so pointer
     events still hit underlying chips. */
  /* v321 — Maya second-look polish: fade was 56px which is narrower than
     one chip (Old Fashioned, Hot Drink, Sparkling are all ~100-130px),
     so the last partial chip was hard-clipping mid-word ("Sh..." instead
     of a clean fade through "Shaken"). Bumped to 120px which covers one
     full chip width — last visible chip softens gracefully to transparent,
     reads as "scroll for more" instead of a clipping bug. */
  -webkit-mask-image: linear-gradient(to right, black 0, black calc(100% - 120px), transparent 100%);
          mask-image: linear-gradient(to right, black 0, black calc(100% - 120px), transparent 100%);
}
.chip-row::-webkit-scrollbar { display: none; }

/* v218 — Variation rail (recipe-sheet "Try a variation" row) uses inline
   styles rather than .chip-row, so it doesn't inherit the scrollbar hide.
   On Chrome desktop the native horizontal scrollbar shows as a thick
   white bar below the chips. Pin scrollbar-width: none + the webkit
   pseudo-element hide so the rail reads as a clean chip strip. */
.variation-rail {
  scrollbar-width: none;
}
.variation-rail::-webkit-scrollbar { display: none; }
.chip {
  /* v320 — Casing sweep: filter chips (Any / Sour / Stirred /
     Favorites / All / etc.) used to render uppercase + 0.1em
     letter-spacing. Source labels are already Title Case; rendering
     them as-source matches Sarah's "tabs and buttons → Title Case"
     rubric and reads less shouty. Ingredient-tag chips (e.g.
     "mezcal ×") stay source-cased — those are user-content tokens. */
  display: inline-flex; align-items: center;
  padding: 11px 18px; min-height: 44px;
  border: var(--hairline) solid var(--rule-strong);
  border-radius: 999px;
  font-size: 13px; color: var(--ink-dim);
  letter-spacing: 0.02em;
  font-weight: 500;
  background: transparent;
  font-family: inherit;
  cursor: pointer;
  transition: color .15s, border-color .15s, background .15s;
  flex-shrink: 0; white-space: nowrap;
  -webkit-touch-callout: none;
  -webkit-user-select: none; user-select: none;
}
.chip:hover { color: var(--ink); border-color: var(--ink-faint); }
.chip:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px;
}
.chip.active {
  /* v320 — Maya audit catch (CEO non-negotiable, Anna):
     The hardcoded orange gradient (rgba(255, 140, 90 ...) → rgba(255, 77, 109 ...))
     applied to .chip.active in every theme. On the Pineapple binding —
     which has a palm-green primary and a sand-cream ground — the orange
     fill on the "ALL" filter pill read as an error/alert state, not a
     selected state. Bartenders would tap "FAVORITES" expecting a flip,
     not understanding why the previously-selected chip looked broken.
     Same misread on all other themes whose accent isn't orange-adjacent.
     Solution: derive the active state from --accent-rgb (set by every
     theme). Each binding's active chip now glows in its own primary
     color — Pineapple = palm green, Walnut = gold, Mezcal = oxblood,
     Riviera = sunset coral, Aperitivo = Campari red, etc. No theme
     loses, all themes gain a coherent self-color active state. */
  border-color: var(--accent);
  color: var(--ink-bright);
  background: linear-gradient(180deg,
    rgba(var(--accent-rgb), 0.28) 0%,
    rgba(var(--accent-rgb), 0.08) 100%);
  letter-spacing: 0.02em;
  box-shadow:
    0 0 0 1px rgba(var(--accent-rgb), 0.45),
    0 0 16px rgba(var(--accent-rgb), 0.25),
    inset 0 1px 0 rgba(var(--accent-rgb), 0.30);
  text-shadow: 0 0 10px rgba(var(--accent-rgb), 0.50);
}

/* ============================================================
   SUB-TABS (Encyclopedia)
   ============================================================ */
/* v216 — Sub-tabs visual hierarchy. Pre-v216 the type read at near-
   primary-nav weight (12px + 0.14em letter-spacing + 2px underline +
   44px min-height) which competed with the page title for attention.
   Downgraded across the board so it reads as an in-page section toggle,
   not a top-level nav. */
.sub-tabs {
  display: flex; gap: 10px;
  margin: 0 0 14px;
  border-bottom: var(--hairline) solid var(--rule-faint);
}
.sub-tab {
  /* v320 — Casing sweep continues. Sub-tabs (COCKTAILS / SYRUPS /
     GARNISHES / PREP, etc.) were rendering uppercase + 0.10em
     letter-spacing — same magazine-eyebrow treatment as the
     top-nav. Brought in line with Sarah's Title Case rule for tabs.
     Source strings in views.js already pass Title Case; the CSS
     change defers to source casing. Size + letter-spacing eased. */
  background: transparent; border: 0;
  color: var(--ink-faint);
  font-size: 12px;
  padding: 8px 4px;
  font-family: inherit;
  letter-spacing: 0.02em;
  font-weight: 500;
  cursor: pointer;
  border-bottom: 1px solid transparent;
  margin-bottom: -1px;
  transition: color .15s, border-color .15s;
  /* v616 — Tap-target floor. Was 36px; bartenders tap these one-handed
     in dim bars, so the underlined section toggle needs a 44px hit area.
     Text size + visual rhythm unchanged (padding/letter-spacing kept);
     only the min-height grows to meet the comfortable touch target. */
  min-height: 44px;
}
.sub-tab:hover { color: var(--ink-dim); }
.sub-tab.active {
  color: var(--accent);
  border-bottom-color: var(--accent);
}

/* ============================================================
   v223 — Library two-level navigation.
   Top-level group strip (.ref-group-tabs: Catalog | Stories) reads as
   a segmented pill — context selector. Distinct visual hierarchy from
   the child strip (.ref-child-tabs) which keeps the standard underlined
   chip rail. Together they read clearly: "context above, filter below."
   v224 — Bumped active-pill contrast (audit finding: in Ivory theme,
   --bg-2 (container) and --bg (active pill) are too close in luminance.
   The active state was relying entirely on a subtle shadow and hairline
   border, which read as ambiguous on lighter themes. Switched the active
   text color to --accent (the theme's signature hue) and strengthened
   the box-shadow + border so the active pill reads cleanly across every
   theme without depending on bg-vs-bg-2 contrast.
   v224 — Added mobile guard: max-width: 100% so a future third group
   tab can't push the strip beyond the viewport.
   ============================================================ */
.sub-tabs.ref-group-tabs {
  display: inline-flex;
  width: max-content;
  max-width: 100%;
  border-bottom: none;
  gap: 4px;
  margin: 0 0 14px;
  padding: 4px;
  background: var(--bg-2);
  border: var(--hairline) solid var(--rule-faint);
  border-radius: var(--radius-md);
}
.ref-group-tabs .sub-tab {
  font-size: 12px;
  padding: 6px 14px;
  border-radius: calc(var(--radius-md) - 4px);
  border-bottom: 0;
  margin-bottom: 0;
  /* v616 — Tap-target floor. Was 28px; this is the top-level Library
     context switcher (Catalog | Stories), a primary one-handed control.
     Raised to a comfortable 44px hit area. The pill stays visually
     compact via the rounded segment + container padding; only height
     grows to meet the touch target. */
  min-height: 44px;
  letter-spacing: 0.08em;
  color: var(--ink-dim);
  transition: color .15s, background .15s, box-shadow .15s;
}
.ref-group-tabs .sub-tab:hover:not(.active) {
  color: var(--ink);
  background: rgba(255, 255, 255, 0.04);
}
.ref-group-tabs .sub-tab.active {
  background: var(--bg);
  color: var(--accent);
  font-weight: 600;
  border-bottom: 0;
  box-shadow:
    0 1px 4px rgba(0, 0, 0, 0.18),
    0 0 0 1px var(--rule);
}

/* ============================================================
   SPIRIT SELECT (form)
   ============================================================ */
.spirit-select {
  appearance: none; -webkit-appearance: none; -moz-appearance: none;
  background: var(--bg-2);
  border: var(--hairline) solid var(--rule);
  border-radius: var(--radius-md);
  padding: 12px 32px 12px 14px;
  font-size: 15px; color: var(--ink);
  font-family: inherit;
  width: 100%; box-sizing: border-box;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8' fill='none' stroke='%23b9b09a' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'><polyline points='1,1.5 6,6.5 11,1.5'/></svg>");
  background-repeat: no-repeat; background-position: right 12px center;
  background-size: 10px;
}
.spirit-select:focus { outline: none; border-color: var(--accent); }

.filter-summary {
  font-size: 11px; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--ink-dim);
  padding: 4px 4px 12px;
  font-style: italic;
}

/* ============================================================
   KEY FEATURES (Encyclopedia / Tools detail)
   ============================================================ */
.key-features { list-style: none; padding: 0; margin: 0; }
.key-features li {
  padding: 8px 0 8px 22px;
  position: relative;
  font-size: 15px; line-height: 1.55;
  color: var(--ink);
  border-bottom: var(--hairline) solid var(--rule);
}
.key-features li:last-child { border-bottom: 0; }
.key-features li::before {
  content: "·";
  color: var(--accent);
  position: absolute; left: 6px; top: 4px;
  font-size: 24px; font-weight: 700; line-height: 1;
}

/* ============================================================
   THUMBNAILS
   ============================================================ */
.monogram-thumb {
  font-family: var(--serif-display); font-style: italic;
  font-weight: 400;
  font-size: 30px; line-height: 1;
  border: var(--hairline) solid rgba(255, 255, 255, 0.06);
  letter-spacing: 0.02em;
  /* Default tint — overridden by [data-category-tint] below. */
  color: var(--accent-2);
  background:
    linear-gradient(135deg,
      color-mix(in srgb, var(--accent-2) 28%, var(--bg)),
      color-mix(in srgb, var(--accent-2) 12%, var(--bg-deep)));
}
/* Encyclopedia category tints — derived from --spirit-* tokens so the
   monogram cards share a hue family with the Tiki Sunset palette
   (coral / peach / teal). Each tint reads its FG from var(--spirit-X)
   and builds the BG gradient via color-mix() against --bg / --bg-deep,
   keeping the ramp dark enough for the cream monogram to pop. */
.monogram-thumb[data-category-tint] {
  color: var(--cat-tint-fg, var(--accent-2));
  background: linear-gradient(135deg,
    color-mix(in srgb, var(--cat-tint-fg, var(--accent-2)) 32%, var(--bg)),
    color-mix(in srgb, var(--cat-tint-fg, var(--accent-2)) 14%, var(--bg-deep)));
}
.monogram-thumb[data-category-tint="whiskey"] { --cat-tint-fg: var(--spirit-whiskey);  }
.monogram-thumb[data-category-tint="gin"] { --cat-tint-fg: var(--spirit-gin);      }
.monogram-thumb[data-category-tint="rum"] { --cat-tint-fg: var(--spirit-rum);      }
.monogram-thumb[data-category-tint="agave"] { --cat-tint-fg: var(--spirit-agave);    }
.monogram-thumb[data-category-tint="brandy"] { --cat-tint-fg: var(--spirit-brandy);   }
.monogram-thumb[data-category-tint="vodka"] { --cat-tint-fg: var(--spirit-vodka);    }
.monogram-thumb[data-category-tint="liqueur"] { --cat-tint-fg: var(--spirit-liqueur);  }
.monogram-thumb[data-category-tint="aperitif"] { --cat-tint-fg: var(--spirit-aperitif); }
.monogram-thumb[data-category-tint="vermouth"] { --cat-tint-fg: var(--spirit-vermouth); }
.monogram-thumb[data-category-tint="wine"] { --cat-tint-fg: var(--spirit-wine);     }
.monogram-thumb[data-category-tint="multi"] { --cat-tint-fg: var(--spirit-multi);    }
.monogram-thumb[data-category-tint="neutral"] { --cat-tint-fg: var(--ink-faint);       }
.tool-thumb {
  background: linear-gradient(135deg, var(--surface-2), var(--surface));
  color: var(--accent-2);
  display: flex; align-items: center; justify-content: center;
  border: var(--hairline) solid var(--rule);
}
.tool-thumb svg { width: 32px; height: 32px; display: block; }

.tool-detail-icon {
  width: 84px; height: 84px;
  margin: 0 auto 22px;
  background: linear-gradient(135deg, var(--surface-2), var(--surface));
  border: var(--hairline) solid var(--rule);
  border-radius: 4px;
  color: var(--accent-2);
  display: flex; align-items: center; justify-content: center;
}
.tool-detail-icon svg { width: 50px; height: 50px; display: block; }

/* ============================================================
   CARD TITLE ROW (favorites + badge)
   ============================================================ */
.card-title-row {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
.card-title-row .card-title { margin: 0; }
.card-fav-mark {
  color: var(--accent); font-size: 14px; line-height: 1;
}
.card-badge {
  font-size: 9px; letter-spacing: 0.16em; text-transform: uppercase;
  background: transparent;
  color: var(--accent-2);
  padding: 3px 8px;
  border-radius: 2px;
  border: var(--hairline) solid var(--accent);
  font-weight: 600;
  line-height: 1.2;
}

/* ============================================================
   BUTTONS
   ============================================================ */
.btn {
  /* v320 — Casing sweep per Sarah (CMO) voice rubric:
     "Tool voice (buttons, labels, errors, metadata): Title Case
     verbs, sentence case nouns, no adjectives." Pre-v320 .btn
     hardcoded text-transform: uppercase + letter-spacing: 0.14em,
     which made every button shout ("BUILD WITH AI" / "OPEN THE SPEC"
     / "GET STARTED"). Rendering source-cased text (Title Case
     verbs as written) lands closer to the editorial-bartender voice
     the brand is going for. Letter-spacing eased to 0.02em — still
     a touch of breath, no shouting. Font-size bumped from 12px to
     13px since uppercase letterforms read smaller than their
     cap-height; un-shouting needs a tiny size lift to stay legible
     at the same visual weight. */
  display: inline-flex; align-items: center; gap: 8px;
  background: var(--accent); color: var(--on-accent);
  border-radius: var(--radius-md);
  padding: 11px 20px;
  font-size: 13px; font-weight: 600;
  letter-spacing: 0.02em;
  font-family: var(--sans);
  cursor: pointer;
  transition: background .15s, transform .1s;
  min-height: 44px;
}
.btn:hover { background: var(--accent-2); }
.btn:active { transform: scale(0.98); }
.btn:focus-visible {
  outline: 2px solid var(--accent-2); outline-offset: 3px;
}
.btn-ghost {
  background: transparent;
  color: var(--ink-dim);
  border: var(--hairline) solid var(--rule-strong);
}
.btn-ghost:hover {
  color: var(--ink);
  border-color: var(--accent);
  background: transparent;
}
.btn-danger {
  background: transparent;
  color: var(--red);
  border: var(--hairline) solid var(--red);
}
.btn-danger:hover { background: var(--red); color: var(--ink); }
.btn-sm { padding: 7px 14px; font-size: 11px; min-height: 36px; }
.btn-icon {
  width: 40px; height: 40px;
  padding: 0; justify-content: center;
}
.btn svg { width: 16px; height: 16px; }

/* ============================================================
   FAB
   ============================================================ */
.fab {
  position: fixed;
  right: 22px;
  bottom: calc(80px + var(--safe-bottom));
  width: 60px; height: 60px;
  border-radius: 50%;
  background: radial-gradient(circle at 30% 30%, var(--brass-light) 0%, var(--accent) 60%, var(--brass-deep) 100%);
  color: var(--on-accent);
  display: flex; align-items: center; justify-content: center;
  box-shadow:
    0 0 0 1px rgba(232, 200, 120, 0.4),
    0 0 18px rgba(199, 156, 79, 0.35),
    0 8px 28px rgba(0, 0, 0, 0.7),
    inset 0 1px 0 rgba(255, 245, 221, 0.4),
    inset 0 -2px 4px rgba(111, 79, 31, 0.4);
  z-index: 8;
  transition: transform .15s, box-shadow .2s;
  /* Welcome flourish only — fires twice on view-mount and stops, instead of
     pulsing forever (audit flagged the constant glow as distracting + GPU
     drain on long-lived pages). */
  animation: fab-glow 3s ease-in-out 2;
}
@keyframes fab-glow {
  0%, 100% {
    box-shadow:
      0 0 0 1px rgba(232, 200, 120, 0.4),
      0 0 18px rgba(199, 156, 79, 0.35),
      0 8px 28px rgba(0, 0, 0, 0.7),
      inset 0 1px 0 rgba(255, 245, 221, 0.4),
      inset 0 -2px 4px rgba(111, 79, 31, 0.4);
  }
  50% {
    box-shadow:
      0 0 0 1px rgba(232, 200, 120, 0.55),
      0 0 26px rgba(199, 156, 79, 0.55),
      0 10px 32px rgba(0, 0, 0, 0.7),
      inset 0 1px 0 rgba(255, 245, 221, 0.5),
      inset 0 -2px 4px rgba(111, 79, 31, 0.4);
  }
}
.fab:hover {
  transform: translateY(-1px) scale(1.04);
}
.fab:active { transform: scale(0.95); }
.fab svg { width: 26px; height: 26px; filter: drop-shadow(0 1px 0 rgba(0,0,0,0.3)); }

@media (min-width: 720px) {
  .fab { bottom: 32px; }
}

/* ============================================================
   SHEETS
   ============================================================ */
.sheet-backdrop {
  position: fixed; inset: 0;
  /* v320 — themed scrim (was hardcoded rgba(0,0,0,0.78), which
     overpowered the light themes Pineapple + Aperitivo). */
  background: var(--scrim);
  backdrop-filter: blur(2px);
  z-index: 100;
  display: flex; align-items: stretch; justify-content: center;
  animation: fade-in .2s ease;
}
@media (min-width: 720px) {
  .sheet-backdrop { align-items: flex-start; padding: 60px 20px; }
}
.sheet {
  background: var(--bg);
  width: 100%; max-width: 640px;
  display: flex; flex-direction: column;
  animation: sheet-up .25s cubic-bezier(.2,.8,.2,1);
  max-height: 100dvh;
  overflow: hidden;
  /* Subtle paper-grain for depth on the sheet too */
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='220' height='220'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.92' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0.78  0 0 0 0 0.62  0 0 0 0 0.31  0 0 0 0.018 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
  background-size: 220px 220px;
}
@media (min-width: 720px) {
  .sheet {
    max-height: calc(100dvh - 120px);
    border-radius: var(--radius-lg);
    border: var(--hairline) solid var(--rule-strong);
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6);
  }
}
.sheet-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 24px 22px 18px;
  border-bottom: 1.5px solid var(--accent);
  flex-shrink: 0;
  padding-top: calc(24px + var(--safe-top));
  position: relative;
  background:
    radial-gradient(ellipse 60% 100% at 50% 100%, rgba(199,156,79,0.10), transparent 70%),
    var(--bg);
}
.sheet-header::before {
  /* Tiny paired ornaments centered above the title — v341: was
     hardcoded "◆ · ◆"; now uses the theme's --ornament-divider
     so Ember shows "✦ · ✦", Pineapple "❁ · ❁", Boudoir flower
     pair, etc. The same metaphor (Art Deco menu marker centered
     above the title) survives, just glyph-themed per binding. */
  content: var(--ornament-divider, "◆") " · " var(--ornament-divider, "◆");
  position: absolute;
  top: calc(8px + var(--safe-top));
  left: 50%; transform: translateX(-50%);
  color: var(--accent);
  font-size: 8px;
  letter-spacing: 6px;
  opacity: 0.7;
}
.sheet-header::after {
  content: "";
  position: absolute; left: 22px; right: 22px; bottom: -4px;
  height: 1px;
  background: var(--rule-gold);
}
@media (min-width: 720px) {
  .sheet-header { padding-top: 24px; }
  .sheet-header::before { top: 8px; }
}
.sheet-title {
  font-family: var(--serif-display); font-size: 28px;
  margin: 0; font-weight: 400;
  letter-spacing: 0.01em; line-height: 1.15;
  color: var(--ink-bright);
  /* v240 — was rgba(199, 156, 79, 0.15) hardcoded Walnut-gold which
     bled a warm halo behind every theme's sheet title (regression from
     the v237 .view-title fix that missed this selector). Now uses
     the active theme's --accent-rgb so the halo matches the palette. */
  text-shadow:
    0 2px 0 rgba(0, 0, 0, 0.6),
    0 0 30px rgba(var(--accent-rgb), 0.15);
  flex: 1;
  padding-right: 12px;
}
.sheet-body {
  flex: 1; overflow-y: auto;
  padding: 22px 22px 28px;
  -webkit-overflow-scrolling: touch;
  /* Soft inner glow at top — like spotlight on the menu page */
  background: radial-gradient(ellipse 110% 30% at 50% 0%, rgba(199, 156, 79, 0.04), transparent 70%);
  /* v482 — themed scrollbar. Default WebKit scrollbar renders as bright
     white on dark themes (Ember, Smoke, Oxblood, etc.) which flares
     against the page. Use ink-faint for the thumb and a hairline track
     so the scroll affordance is visible but recedes. Firefox uses
     scrollbar-color; WebKit/Blink use the pseudo-elements below. */
  scrollbar-width: thin;
  scrollbar-color: var(--ink-faint, rgba(120, 106, 88, 0.6)) transparent;
}
.sheet-body::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}
.sheet-body::-webkit-scrollbar-track {
  background: transparent;
}
.sheet-body::-webkit-scrollbar-thumb {
  background-color: var(--ink-faint, rgba(120, 106, 88, 0.6));
  border-radius: 8px;
  border: 2px solid transparent;
  background-clip: content-box;
}
.sheet-body::-webkit-scrollbar-thumb:hover {
  background-color: var(--ink-dim, rgba(160, 144, 122, 0.85));
  background-clip: content-box;
}
.sheet-footer {
  display: flex; gap: 10px; justify-content: flex-end;
  padding: 14px 18px;
  padding-bottom: calc(14px + var(--safe-bottom));
  border-top: var(--hairline) solid var(--rule);
  background: var(--bg);
  flex-shrink: 0;
  /* Wave 111 — Allow horizontal scroll when the action row overflows.
     Previously `overflow-x: visible` + `flex-wrap: nowrap` caused the
     leftmost buttons (Save to Journal, Star) to render at negative x and
     become inaccessible on phones. Now the row scrolls horizontally,
     keeping every action reachable. The right-aligned justify means the
     "primary" actions (Edit, Remove) remain visible on first paint. */
  overflow-x: auto;
  scrollbar-width: none;
}
.sheet-footer::-webkit-scrollbar { display: none; }
/* v300 — Wrap the action row on narrow viewports instead of horizontal-
   scrolling it. The pre-v300 rule (flex-start + overflow-x scroll) hid
   the primary Edit action off the right edge on a 414px iPhone — the
   live audit caught a journal entry where the bartender literally
   could not see the Edit button without horizontal-scrolling the row.
   Wrapping keeps every action visible in two rows, primary still
   anchored to the right via flex-end. */
@media (max-width: 560px) {
  .sheet-footer {
    flex-wrap: wrap;
    justify-content: flex-end;
    overflow-x: visible;
    row-gap: 8px;
  }
  .sheet-footer .btn {
    flex-grow: 0;
    flex-shrink: 0;
  }
}

@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes sheet-up {
  from { transform: translateY(20px); opacity: 0.5; }
  to   { transform: translateY(0); opacity: 1; }
}

/* ============================================================
   FORMS
   ============================================================ */
.field {
  display: flex; flex-direction: column; gap: 6px;
  margin-bottom: 16px;
}
.field-row { display: flex; gap: 10px; }
.field-row .field { flex: 1; }
.field label {
  font-size: 10px; letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--ink-dim);
  font-weight: 600;
}
.field input,
.field textarea,
.field select {
  background: var(--bg-2);
  border: var(--hairline) solid var(--rule);
  border-radius: var(--radius-md);
  padding: 11px 14px;
  font-size: 15px; color: var(--ink);
  font-family: var(--sans);
  width: 100%; box-sizing: border-box;
  transition: border-color .15s, background .15s;
}
.field textarea {
  min-height: 84px; resize: vertical;
  font-family: var(--sans);
  line-height: 1.55;
}
.field input:focus,
.field textarea:focus,
.field select:focus {
  outline: none; border-color: var(--accent);
  background: var(--surface);
}
.field-help {
  font-size: 11px; color: var(--ink-faint);
  font-style: italic;
}

/* ============================================================
   INGREDIENTS EDITOR
   ============================================================ */
.ingredients { display: flex; flex-direction: column; gap: 8px; }
.ingredient-row {
  display: grid;
  grid-template-columns: 56px 80px 1fr 36px;
  gap: 6px; align-items: center;
}
.ingredient-row input,
.ingredient-row .unit-select {
  background: var(--surface-2);
  border: var(--hairline) solid var(--rule);
  border-radius: 6px;
  padding: 9px 11px; font-size: 14px;
  width: 100%; box-sizing: border-box;
  color: var(--ink);
  font-family: inherit;
}
.ingredient-row input:focus,
.ingredient-row .unit-select:focus {
  outline: none; border-color: var(--accent);
}
.ingredient-row .unit-select {
  appearance: none; -webkit-appearance: none; -moz-appearance: none;
  padding-right: 22px;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8' fill='none' stroke='%23b9b09a' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'><polyline points='1,1.5 6,6.5 11,1.5'/></svg>");
  background-repeat: no-repeat; background-position: right 8px center;
  background-size: 10px; cursor: pointer;
}
.ingredient-row .btn-icon {
  width: 36px; height: 36px;
  background: transparent; color: var(--ink-faint);
  border: var(--hairline) solid var(--rule);
  border-radius: 6px;
}
.ingredient-row .btn-icon:hover { color: var(--red); border-color: var(--red); }
.add-ingredient {
  background: transparent; color: var(--ink-dim);
  border: var(--hairline) dashed var(--rule-strong);
  border-radius: 6px; padding: 9px;
  font-size: 12px; letter-spacing: 0.06em;
}
.add-ingredient:hover {
  color: var(--accent); border-color: var(--accent);
}

/* ============================================================
   TAG EDITOR
   ============================================================ */
.tag-input-wrap {
  display: flex; flex-wrap: wrap; gap: 6px;
  background: var(--bg-2);
  border: var(--hairline) solid var(--rule);
  border-radius: var(--radius-md); padding: 8px;
  min-height: 44px;
}
.tag-input-wrap:focus-within { border-color: var(--accent); }
.tag-chip {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 4px 10px;
  background: var(--surface-2);
  border: var(--hairline) solid var(--rule-strong);
  border-radius: 999px;
  font-size: 12px; color: var(--ink);
  letter-spacing: 0.04em;
}
.tag-chip button {
  color: var(--ink-faint); font-size: 16px; line-height: 1;
}
.tag-chip button:hover { color: var(--red); }
.tag-input-wrap input {
  flex: 1; min-width: 80px;
  background: transparent; border: 0; padding: 4px;
  font-size: 14px; color: var(--ink);
}
.tag-input-wrap input:focus { outline: none; }

/* ============================================================
   STAR RATING
   ============================================================ */
.stars { display: inline-flex; gap: 4px; }
.stars button {
  width: 32px; height: 32px; padding: 0;
  display: flex; align-items: center; justify-content: center;
  color: var(--ink-faint);
  font-size: 24px; line-height: 1;
  transition: color .12s;
}
.stars button.active { color: var(--accent); }
.stars button:hover { color: var(--accent-2); }
.stars-readonly {
  display: inline-flex; gap: 2px;
  color: var(--accent);
  font-size: 14px; line-height: 1;
  letter-spacing: 1px;
}

/* ============================================================
   PHOTO INPUT
   ============================================================ */
.photo-input {
  display: block; width: 100%;
  background: var(--bg-2);
  border: var(--hairline) dashed var(--rule-strong);
  border-radius: var(--radius-md);
  padding: 22px;
  text-align: center; color: var(--ink-dim);
  font-size: 13px; letter-spacing: 0.06em;
  cursor: pointer;
  position: relative;
  transition: border-color .15s, color .15s;
}
.photo-input:hover { border-color: var(--accent); color: var(--accent); }
.photo-input.has-photo {
  padding: 0; min-height: 200px; border-style: solid;
}
.photo-input img {
  width: 100%; max-height: 300px; object-fit: cover;
  border-radius: 5px; display: block;
}
.photo-input input[type=file] {
  position: absolute; inset: 0; opacity: 0; cursor: pointer;
}
.photo-clear {
  position: absolute; top: 10px; right: 10px;
  background: rgba(0, 0, 0, 0.78);
  border: var(--hairline) solid var(--rule-strong);
  color: var(--ink);
  width: 30px; height: 30px;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 16px;
}

/* ============================================================
   DETAIL VIEW — printed-menu typography
   ============================================================ */
.detail-photo {
  width: 100%; max-height: 300px; object-fit: cover;
  border-radius: var(--radius-md);
  margin-bottom: 18px;
  border: var(--hairline) solid var(--rule);
}

/* Drop cap for the first detail section's first paragraph.
   ::first-letter only accepts a narrow subset of properties — no
   position / z-index. The frame ::before below is z-index: -1 so
   the cap (in-flow, painted normally) renders on top of it. */
.sheet-body > *:first-child + .detail-section .detail-text:first-of-type::first-letter,
.sheet-body > .detail-section:first-of-type .detail-text:first-of-type::first-letter {
  font-family: var(--serif-display);
  font-size: 3em;
  float: left;
  line-height: 0.9;
  margin: 4px 8px 0 0;
  color: var(--accent);
  font-style: italic;
}

/* v66 — illuminated initial frame.
   The drop-cap above stays as ::first-letter (floated). The frame is
   rendered as an absolutely-positioned ::before on the *paragraph*,
   sized to sit behind where the cap renders. ::after carries an
   optional decorative post-ornament glyph at the bottom-right.

   Why on the paragraph and not on ::first-letter: combining
   ::first-letter + float + a sibling ::before causes Safari to clip
   or zero-size the cap. Keeping the frame on the paragraph as a
   non-floating absolute element sidesteps the bug entirely.

   Each theme supplies five tokens:
     --dropcap-frame-bg      | fill behind the cap
     --dropcap-frame-border  | 1px solid var(--accent), or sharper
     --dropcap-frame-radius  | 0 (Connaught), 2px (Bemelmans),
                               6px (Maison), 50% (Smuggler stamp)
     --dropcap-ornament-pre  | top-left corner glyph or ""
     --dropcap-ornament-post | bottom-right corner glyph or ""
   Themes with no glyph supply "" so the pseudos render empty boxes. */
.sheet-body > *:first-child + .detail-section .detail-text:first-of-type,
.sheet-body > .detail-section:first-of-type .detail-text:first-of-type {
  position: relative;
  /* Establish a stacking context so the ::before frame can sit
     at z-index: -1 (behind the floated drop-cap) without falling
     behind the paragraph's ancestor backgrounds. */
  isolation: isolate;
}
.sheet-body > *:first-child + .detail-section .detail-text:first-of-type::before,
.sheet-body > .detail-section:first-of-type .detail-text:first-of-type::before {
  content: var(--dropcap-ornament-pre, "");
  position: absolute;
  top: 4px;
  left: -6px;
  width: 3.2em;
  height: 2.7em;
  background: var(--dropcap-frame-bg, transparent);
  border: var(--dropcap-frame-border, 0);
  border-radius: var(--dropcap-frame-radius, 0);
  /* The pre-ornament glyph (when present) sits at the top edge of
     the frame, small + accent-colored — it reads as a corner mark,
     not as text the cap is fighting with. */
  font-family: var(--serif-display, Georgia, serif);
  font-size: 0.72em;
  line-height: 1;
  color: var(--accent);
  text-align: left;
  padding: 2px 0 0 4px;
  z-index: -1;
  pointer-events: none;
}
.sheet-body > *:first-child + .detail-section .detail-text:first-of-type::after,
.sheet-body > .detail-section:first-of-type .detail-text:first-of-type::after {
  content: var(--dropcap-ornament-post, "");
  position: absolute;
  /* Bottom-right of the frame zone (frame is 3.2em × 2.7em from
     top:4 left:-6). Place the glyph just inside the bottom-right
     corner. */
  top: calc(2.7em - 0.4em);
  left: calc(3.2em - 6px - 0.9em);
  font-family: var(--serif-display, Georgia, serif);
  font-size: 0.72em;
  line-height: 1;
  color: var(--accent);
  z-index: -1;
  pointer-events: none;
}

.detail-section { margin-bottom: 30px; }
.detail-section h4 {
  font-size: 10px; letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--accent);
  margin: 0 0 14px;
  padding-bottom: 6px;
  border-bottom: 1.5px solid var(--rule-faint);
  font-weight: 600;
  position: relative;
  display: flex; align-items: center; gap: 10px;
}
.detail-section h4::before {
  /* v74 — section-head plate per binding.
     Was a flat 6px ◆ across every theme. Now a small ornamental
     cartouche carrying the theme's glyph: gilded fleuron box for
     Bemelmans, sharp Deco lozenge for Connaught, soft brass laurel
     for Maison Premiere, compass-rose medallion for Smuggler's Cove.
     Tokens live in each [data-theme] block. Falls back gracefully
     if a theme doesn't define them.
     v74-debug: shrunk plate from 22→16 so it doesn't inflate the
     header row (h4 text is just 10px). */
  content: var(--section-plate-glyph, "◆");
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--serif-display);
  font-size: 9px;
  line-height: 1;
  width: 16px;
  height: 16px;
  background: var(--section-plate-bg, transparent);
  border: var(--section-plate-border, 0);
  border-radius: var(--section-plate-radius, 0);
  color: var(--section-plate-color, var(--accent));
  letter-spacing: 0;
  flex-shrink: 0;
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.15) inset;
}
/* Per-binding plate refinements — glyph-size optimizations for
   different glyph metrics. Connaught's lozenge reads thin: bump
   the glyph a touch. Maison Premiere's laurel flower has body;
   downscale. Smuggler's compass star wants to fill the medallion. */






/* v206 — Per-theme ornament size tuning for the new bindings. Each glyph
   has different metrics; without these the cross-pattée reads heavy and
   the compass-cluster reads thin. */
[data-theme="smoke"] .detail-section h4::before {
  font-size: 9px;
}

[data-theme="ivory"] .detail-section h4::before {
  font-size: 8px;
}


.detail-text {
  font-size: 15px; line-height: 1.7;
  white-space: pre-wrap;
  color: var(--ink);
}
/* v282 — Tradition subsection. Visually softer than Notes (smaller,
   slightly faded, accent-tinted side bar) so it reads as editorial
   context rather than primary recipe content. The bartender at the rail
   should be able to glance past it to the spec; the bartender training
   a junior should be able to point to it and walk through the schools. */
.detail-section-tradition {
  border-left: 2px solid color-mix(in srgb, var(--accent) 35%, var(--rule));
  padding-left: 14px;
  margin-left: 2px;
}
.detail-section-tradition h4 {
  color: color-mix(in srgb, var(--accent) 70%, var(--ink-dim));
}
.detail-text-tradition {
  font-size: 14px;
  line-height: 1.65;
  color: var(--ink-dim);
  font-family: var(--serif, var(--sans));
  font-style: italic;
}
/* Notes section reads italic — like a printed cocktail menu's marginalia */
.detail-section:has(h4) + .detail-section h4 + .detail-text {
  /* generic */
}

/* Ornamental divider between major sections in detail view */
.detail-section + .detail-section {
  position: relative;
}

.detail-meta-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px 22px;
  margin-bottom: 22px;
  padding-bottom: 18px;
  border-bottom: var(--hairline) solid var(--rule);
  position: relative;
}
.detail-meta-grid::after {
  content: "";
  position: absolute; left: 0; right: 0; bottom: -3px;
  height: 1px; background: var(--rule-faint);
}
.detail-meta-item .label {
  /* v616 — Core reading surface: the detail-sheet meta labels
     (GLASS / METHOD / GARNISH / CITY / STATUS) were 9px in --ink-faint,
     the faintest, smallest type on a primary reading surface. Raised to
     the 12px floor and promoted to --ink-dim for these reading-critical
     rows. Tracking/uppercase eyebrow treatment kept. */
  font-size: 12px; letter-spacing: 0.22em; text-transform: uppercase;
  color: var(--ink-dim);
  margin-bottom: 4px;
  font-weight: 600;
}
.detail-meta-item .value {
  font-size: 15px; color: var(--ink);
  font-family: var(--serif);
  letter-spacing: 0.005em;
}

/* Ingredient list — printed cocktail-menu leader-dot style */
.ingredient-list { list-style: none; padding: 0; margin: 0; }
.ingredient-list li {
  display: grid;
  grid-template-columns: 60px auto 1fr;
  gap: 12px;
  padding: 11px 0;
  border-bottom: 1.5px dotted var(--rule-gold);
  font-size: 15px;
  align-items: baseline;
  transition: padding .15s, background .15s;
}
.ingredient-list li:last-child { border-bottom: 0; }
.ingredient-list li:hover {
  background: linear-gradient(90deg, rgba(199, 156, 79, 0.06), transparent 60%);
  padding-left: 6px;
}
.ingredient-list .amount {
  color: var(--accent-2);
  font-family: var(--serif-display); font-style: italic; font-weight: 400;
  font-size: 19px;
  white-space: nowrap;
  text-align: right;
  text-shadow: 0 1px 0 rgba(0,0,0,0.4);
  letter-spacing: 0.005em;
}
.ingredient-list .unit {
  color: var(--brass);
  /* v616 — Core reading surface: the unit (OZ / DASH / BARSPOON) on the
     recipe-sheet ingredient list was 10px, hard to read at arm's length.
     Raised to the 12px legibility floor; uppercase + tracking kept. */
  font-size: 12px;
  letter-spacing: 0.16em; text-transform: uppercase;
  font-weight: 600;
}
.ingredient-list .name {
  color: var(--ink);
  line-height: 1.4;
  font-family: var(--serif);
  font-size: 15px;
}

/* ============================================================
   REVERSE SUBSTITUTIONS — "this brand can replace…" on brand
   encyclopedia pages.
   ============================================================ */
.reverse-subs-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.reverse-subs-item {
  border-left: 2px solid var(--accent-2);
  padding-left: 12px;
}
.reverse-subs-target {
  font-family: var(--serif);
  font-size: 15px;
  font-weight: 600;
  color: var(--ink);
}
.reverse-subs-ratio {
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--accent);
  margin-left: 10px;
  font-variant-numeric: tabular-nums;
}
.reverse-subs-note {
  font-family: var(--serif-italic);
  font-style: italic;
  font-size: 13px;
  color: var(--ink-dim);
  line-height: 1.5;
  margin-top: 4px;
}

/* ============================================================
   POUR COST VIEW
   ============================================================ */
/* Cost view re-uses the encyclopedia sub-tab pattern for consistency
   across "section selectors inside a view." */
.cost-tabs {
  display: flex;
  gap: 4px;
  margin-bottom: 18px;
  flex-wrap: wrap;
}
.cost-tab {
  background: transparent;
  border: 1px solid var(--rule);
  border-radius: 999px;
  padding: 8px 16px;
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 600;
  /* v320 — Casing sweep: cost-tab reads as a tab role, Title Case
     per Sarah's voice rubric. */
  letter-spacing: 0.02em;
  color: var(--ink-dim);
  cursor: pointer;
  transition: color 100ms ease, border-color 100ms ease, background 100ms ease;
}
.cost-tab:hover {
  color: var(--ink);
  border-color: var(--ink-faint);
}
.cost-tab.on {
  color: var(--accent);
  border-color: var(--accent);
}
/* Cost stats panel — unified onto the canonical Bar pattern (.bar-summary):
   38px Bodoni, ink color for the primary stat, accent for the highlighted
   one. The audit flagged the three "stats panel" dialects (Bar / Cost /
   Batch) as inconsistent; selectors below alias the cost-summary classes
   onto the same .stat-* / .bar-summary-* type system. */
.cost-summary {
  display: flex;
  justify-content: space-around;
  background: var(--surface-2);
  border: var(--hairline) solid var(--rule);
  border-radius: 6px;
  padding: 18px 16px;
  margin-bottom: 20px;
}
.cost-summary-stat {
  text-align: center;
}
.cost-summary-num {
  font-family: var(--serif-display);
  font-size: 38px;
  line-height: 1;
  color: var(--ink);
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}
.cost-summary-stat-accent .cost-summary-num {
  color: var(--accent);
}
.cost-summary-label {
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-top: 6px;
}
.cost-list {
  display: flex;
  flex-direction: column;
  padding-bottom: 100px;
}
.cost-row {
  display: grid;
  grid-template-columns: 1fr auto auto;
  align-items: baseline;
  gap: 12px;
  padding: 12px 4px;
  border-bottom: var(--hairline) solid var(--rule);
}
.cost-row-name {
  font-family: var(--serif);
  font-size: 15px;
  color: var(--ink);
}
.cost-row-cost {
  font-family: var(--sans);
  font-weight: 700;
  font-size: 14px;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}
.cost-row-menu {
  font-family: var(--sans);
  font-size: 11px;
  color: var(--ink-faint);
  letter-spacing: 0.04em;
}
.cost-groups {
  display: flex;
  flex-direction: column;
  gap: 24px;
  padding-bottom: 100px;
}
.cost-group-header {
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent);
  border-bottom: var(--hairline) solid var(--rule);
  padding-bottom: 6px;
  margin-bottom: 8px;
}
.cost-price-row {
  display: grid;
  grid-template-columns: 1fr 110px;
  align-items: center;
  gap: 12px;
  padding: 8px 4px;
}
.cost-price-label {
  font-family: var(--serif);
  font-size: 14px;
  color: var(--ink);
}
.cost-price-input-wrap {
  display: flex;
  align-items: center;
  gap: 4px;
}
.cost-currency {
  font-family: var(--sans);
  font-size: 14px;
  color: var(--ink-faint);
}
.cost-price-input {
  flex: 1 1 auto;
  text-align: right;
  font-variant-numeric: tabular-nums;
  padding: 8px 10px;
  font-size: 14px;
}

/* ============================================================
   PAYWALL SHEET (Pro)
   ============================================================ */
.paywall-body {
  text-align: center;
  padding: 8px 4px 4px;
}
.paywall-eyebrow {
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.24em;
  color: var(--accent);
  margin-bottom: 8px;
}
.paywall-title {
  font-family: var(--serif-display);
  font-size: 24px;
  line-height: 1.2;
  margin: 0 0 12px;
  color: var(--ink);
}
.paywall-pitch {
  font-family: var(--serif-italic);
  font-style: italic;
  font-size: 14px;
  color: var(--ink-dim);
  line-height: 1.5;
  margin: 0 auto 24px;
  max-width: 320px;
}
.paywall-tiers {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin-bottom: 18px;
}
/* v310 audit fix — three-tier variant gets a proper 3-column layout instead
   of inheriting the 2-column default (which silently dropped Pro Unlimited
   to a second row and frequently hid it below the modal fold). */
.paywall-tiers-three {
  grid-template-columns: 1fr 1fr 1fr;
}
/* v313 — Four-tier variant adds the House Book between Working Book and
   Consultant's Book. On wide desktops we lay out 4 across; on tablets we
   wrap to a 2x2 grid; on phones we stack 1-per-row (the .paywall-tiers
   narrow-screen media query already covers this). */
.paywall-tiers-four {
  grid-template-columns: 1fr 1fr 1fr 1fr;
}
@media (max-width: 900px) {
  .paywall-tiers-four {
    grid-template-columns: 1fr 1fr;
  }
}
/* v313 — Tier tagline (who-is-this-for line under the tier name). Italic
   serif to feel like a footnote, not a banner. */
.paywall-tier-tagline {
  font-family: var(--serif-italic);
  font-style: italic;
  font-size: 11px;
  color: var(--ink-faint);
  margin-top: -4px;
  margin-bottom: 4px;
  text-align: center;
  line-height: 1.3;
  min-height: 28px;
}
/* v315 — Device-management sheet. Two states: settings (neutral) and
   at_cap (warning). List rows show device label + last-used timestamp,
   sign-out button to the right. Current device is highlighted and not
   revocable from this UI. */
.devices-sheet { padding: 0 4px; }
.devices-eyebrow {
  font-family: var(--sans);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.14em;
  color: var(--accent);
  text-align: center;
  margin-bottom: 6px;
}
.devices-eyebrow-warn {
  color: var(--maraschino, #b13c2c);
}
.devices-title {
  font-family: var(--serif-display);
  font-size: 22px;
  font-weight: 700;
  text-align: center;
  margin: 0 0 8px;
  color: var(--ink);
}
.devices-pitch {
  font-family: var(--serif-italic);
  font-style: italic;
  font-size: 14px;
  text-align: center;
  color: var(--ink-dim);
  line-height: 1.5;
  margin: 0 auto 18px;
  max-width: 480px;
}
.devices-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 6px;
}
.devices-loading,
.devices-empty,
.devices-error {
  text-align: center;
  font-family: var(--sans);
  font-size: 13px;
  color: var(--ink-dim);
  padding: 16px;
}
.devices-error { color: var(--maraschino, #b13c2c); }
.devices-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 14px;
  background: var(--surface-2);
  border: 1px solid var(--rule);
  border-radius: 8px;
  gap: 10px;
}
.devices-row-me {
  border-color: color-mix(in srgb, var(--accent) 50%, transparent);
  background: color-mix(in srgb, var(--accent) 5%, var(--surface-2));
}
.devices-row-main {
  flex: 1;
  min-width: 0;
}
.devices-row-label {
  font-family: var(--sans);
  font-size: 14px;
  font-weight: 600;
  color: var(--ink);
}
.devices-row-here {
  font-family: var(--serif-italic);
  font-style: italic;
  font-size: 12px;
  color: var(--accent);
  font-weight: 400;
}
.devices-row-meta {
  font-family: var(--sans);
  font-size: 11px;
  color: var(--ink-dim);
  margin-top: 2px;
}

/* v312 — Trial callout on the onboarding welcome screen. Subtle accent
   surround that draws the eye without competing with the auth form. */
.onboarding-trial-callout {
  margin: 14px auto 12px;
  padding: 10px 14px;
  border: 1px solid color-mix(in srgb, var(--accent) 40%, transparent);
  border-radius: 6px;
  background: color-mix(in srgb, var(--accent) 6%, transparent);
  font-family: var(--sans);
  font-size: 13px;
  color: var(--ink);
  line-height: 1.45;
  text-align: center;
}
.onboarding-trial-callout strong {
  display: block;
  color: var(--accent);
  font-weight: 700;
  margin-bottom: 3px;
}
/* v316 — Launch-deal block (replaces .paywall-founder). Same visual
   treatment; new class name reflects that it points to the EMBURYFOUNDER
   promo code instead of the now-removed founder pricing tier. The old
   .paywall-founder rules below stay for any cached HTML in flight. */
.paywall-launch-deal {
  text-align: center;
  margin: 6px auto 12px;
  max-width: 480px;
  padding: 8px 10px;
  border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
  border-radius: 6px;
  background: color-mix(in srgb, var(--accent) 4%, transparent);
}
.paywall-launch-eyebrow {
  display: block;
  font-family: var(--sans);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 3px;
}
.paywall-launch-text {
  display: block;
  font-family: var(--sans);
  font-size: 11px;
  color: var(--ink-dim);
  line-height: 1.45;
}
.paywall-launch-text strong {
  font-family: var(--sans);
  font-weight: 700;
  color: var(--ink);
  letter-spacing: 0.04em;
}

/* v310 audit fix — Founder pricing line was two adjacent <span>s with no
   whitespace; rendered as "✦ Founder pricingFirst 100…". Make the eyebrow
   a centered block above the explanation. */
.paywall-founder {
  text-align: center;
  margin: 6px auto 12px;
  max-width: 480px;
  padding: 8px 10px;
  border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
  border-radius: 6px;
  background: color-mix(in srgb, var(--accent) 4%, transparent);
}
.paywall-founder-eyebrow {
  display: block;
  font-family: var(--sans);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 3px;
}
.paywall-founder-text {
  display: block;
  font-family: var(--sans);
  font-size: 11px;
  color: var(--ink-dim);
  line-height: 1.45;
}
/* On narrow screens (mobile + small tablets), the 2-column grid wraps the
   3rd tier below and makes pricing comparison awkward. Single column is
   more scannable. Breakpoint set at 640px to also cover narrow tablet
   browsers and rotated tablets where the 2-col layout would look bad. */
@media (max-width: 640px) {
  .paywall-tiers,
.paywall-tiers-three {
    grid-template-columns: 1fr;
  }
}
.paywall-tier {
  position: relative;
  background: var(--surface-2);
  border: 1.5px solid var(--rule);
  border-radius: 8px;
  padding: 18px 12px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}
.paywall-tier-best {
  border-color: var(--accent);
}
.paywall-tier-badge {
  position: absolute;
  top: -10px;
  right: 50%;
  transform: translateX(50%);
  background: var(--accent);
  color: var(--bg);
  font-family: var(--sans);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.14em;
  padding: 3px 8px;
  border-radius: 4px;
}
.paywall-tier-price {
  font-family: var(--serif-display);
  font-size: 28px;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.paywall-tier-period {
  font-family: var(--sans);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.10em;
  color: var(--ink-faint);
  text-transform: uppercase;
  margin-bottom: 8px;
}
.paywall-tier-cta {
  width: 100%;
  margin-top: 6px;
  padding: 10px 8px;
  font-size: 12px;
}
/* v306 — Annual subtext under monthly price, and stacked CTAs (annual/monthly).
   Each tier card now displays the monthly headline price with an annual hint
   directly below it; the CTA stack shows annual as primary, monthly as ghost. */
.paywall-tier-annual-hint {
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--ink-faint);
  margin-top: -2px;
  margin-bottom: 6px;
}
.paywall-tier-cta-stack {
  display: flex;
  flex-direction: column;
  gap: 6px;
  width: 100%;
  margin-top: auto;
  padding-top: 8px;
}
.paywall-tier-cta-stack .btn {
  width: 100%;
  padding: 10px 8px;
  font-size: 12px;
}
.paywall-tier-cta-stack .paywall-tier-monthly-btn {
  font-size: 11px;
  padding: 7px 8px;
  font-weight: 500;
}
.paywall-tier-current-badge {
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent);
  margin-top: 8px;
}
.paywall-fineprint {
  font-family: var(--serif-italic);
  font-style: italic;
  font-size: 12px;
  color: var(--ink-faint);
  margin: 14px auto 12px;
  max-width: 320px;
}
.paywall-trial-banner {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent);
  border-radius: 8px;
  padding: 12px 14px;
  margin: 0 auto 18px;
  max-width: 380px;
  text-align: left;
}

/* ============================================================
   TRIAL-END REMINDER BANNER (Wave 116) — app-wide, top of view.
   Renders only when isTrialing() && daysUntilRenewal() <= 5.
   Soft-dismissable per day. Persists until trial converts.
   ============================================================ */
.trial-banner {
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  border-bottom: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
  padding: 10px 16px;
  font-family: var(--sans);
  font-size: 13px;
  color: var(--ink);
  line-height: 1.5;
}
.trial-banner-urgent {
  background: color-mix(in srgb, var(--accent) 22%, transparent);
  border-bottom-color: color-mix(in srgb, var(--accent) 60%, transparent);
}
.trial-banner-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  max-width: 920px;
  margin: 0 auto;
  flex-wrap: wrap;
}
.trial-banner-text {
  flex: 1;
  min-width: 0;
}
.trial-banner-text strong {
  color: var(--ink);
  font-weight: 700;
  margin-right: 4px;
}
.trial-banner-actions {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
}
.trial-banner-cta {
  background: var(--accent);
  color: var(--bg);
  border: none;
  border-radius: 6px;
  padding: 6px 12px;
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  letter-spacing: 0.02em;
}
.trial-banner-cta:hover {
  filter: brightness(1.08);
}
.trial-banner-dismiss {
  background: transparent;
  color: var(--ink-dim);
  border: 1px solid color-mix(in srgb, var(--ink-dim) 30%, transparent);
  border-radius: 6px;
  width: 28px;
  height: 28px;
  cursor: pointer;
  font-size: 16px;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
}
.trial-banner-dismiss:hover {
  color: var(--ink);
  border-color: var(--ink-dim);
}
/* v306 — Soft band (days 8–14): lowest visual weight, almost a hint */
.trial-banner-soft {
  background: color-mix(in srgb, var(--accent) 5%, transparent);
  border-bottom-color: color-mix(in srgb, var(--accent) 18%, transparent);
}
/* v306 — Expired state: maraschino accent, no dismiss, retention copy */
.trial-banner-expired {
  background: color-mix(in srgb, var(--maraschino, #b13c2c) 12%, transparent);
  border-bottom: 1px solid color-mix(in srgb, var(--maraschino, #b13c2c) 40%, transparent);
}
.trial-banner-expired .trial-banner-cta {
  background: var(--maraschino, #b13c2c);
  color: #fff;
}
@media (max-width: 480px) {
  .trial-banner {
    padding: 9px 12px;
    font-size: 12px;
  }
  .trial-banner-inner {
    gap: 10px;
  }
  .trial-banner-cta {
    padding: 5px 10px;
    font-size: 11px;
  }
}
.paywall-trial-icon {
  font-size: 16px;
  color: var(--accent);
  line-height: 1.4;
  flex-shrink: 0;
}
.paywall-trial-text {
  font-family: var(--sans);
  font-size: 13px;
  color: var(--ink);
  line-height: 1.45;
}
.paywall-trial-text strong {
  color: var(--ink);
  font-weight: 700;
}
.paywall-dev-row {
  border-top: var(--hairline) solid var(--rule);
  padding-top: 14px;
  margin-top: 8px;
  text-align: center;
}
.paywall-dev-label {
  font-family: var(--serif-italic);
  font-style: italic;
  font-size: 11px;
  color: var(--ink-faint);
  margin-bottom: 8px;
}

/* ============================================================
   ADMIN DASHBOARD (v308)
   Mobile-first: 2-column grid on phones, 3 on tablet, 4 on desktop.
   Each card is a flat KPI tile with title / primary number / secondary line.
   ============================================================ */
.admin-header {
  padding: 16px 14px 8px;
  border-bottom: var(--hairline) solid var(--rule);
}
.admin-title {
  font-family: var(--serif-display);
  font-size: 22px;
  font-weight: 700;
  margin: 0 0 2px;
  color: var(--ink);
}
.admin-subtitle {
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.admin-body {
  padding: 14px;
}
.admin-loading,
.admin-error {
  text-align: center;
  padding: 28px 16px;
  font-family: var(--sans);
  font-size: 13px;
  color: var(--ink-dim);
}
.admin-error strong {
  color: var(--ink);
  display: block;
  margin-bottom: 4px;
}
.admin-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}
@media (min-width: 600px) {
  .admin-grid { grid-template-columns: repeat(3, 1fr); }
}
@media (min-width: 900px) {
  .admin-grid { grid-template-columns: repeat(4, 1fr); }
}
.admin-card {
  background: var(--surface-2);
  border: 1px solid var(--rule);
  border-radius: 8px;
  padding: 12px 12px 14px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-height: 92px;
}
.admin-card-wide {
  grid-column: 1 / -1;
}
.admin-card-good {
  border-color: color-mix(in srgb, var(--accent) 60%, transparent);
  background: color-mix(in srgb, var(--accent) 6%, var(--surface-2));
}
.admin-card-warn {
  border-color: color-mix(in srgb, var(--maraschino, #b13c2c) 50%, transparent);
  background: color-mix(in srgb, var(--maraschino, #b13c2c) 6%, var(--surface-2));
}
.admin-card-title {
  font-family: var(--sans);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.admin-card-primary {
  font-family: var(--serif-display);
  font-size: 26px;
  font-weight: 700;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
  margin-top: 2px;
}
.admin-card-secondary {
  font-family: var(--sans);
  font-size: 11px;
  color: var(--ink-dim);
  line-height: 1.4;
  margin-top: auto;
}
.admin-card-empty {
  font-family: var(--serif-italic);
  font-style: italic;
  font-size: 12px;
  color: var(--ink-faint);
  padding: 8px 0 2px;
}
.admin-topusers {
  list-style: none;
  margin: 6px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
}
.admin-topuser {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 6px 0;
  border-bottom: 1px dashed color-mix(in srgb, var(--rule) 60%, transparent);
  font-family: var(--sans);
  font-size: 12px;
}
.admin-topuser:last-child {
  border-bottom: none;
}
.admin-topuser-email {
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex: 1;
  min-width: 0;
  padding-right: 10px;
}
.admin-topuser-meta {
  color: var(--ink-dim);
  font-variant-numeric: tabular-nums;
  font-size: 11px;
  flex-shrink: 0;
}
.admin-timestamp {
  text-align: center;
  font-family: var(--sans);
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-top: 14px;
}

/* v309 — Comp accounts panel below the KPI grid */
.admin-comps {
  margin-top: 28px;
  padding-top: 18px;
  border-top: 1px solid var(--rule);
}
.admin-section-header h2 {
  font-family: var(--serif-display);
  font-size: 18px;
  font-weight: 700;
  margin: 0 0 4px;
  color: var(--ink);
}
.admin-section-sub {
  font-family: var(--sans);
  font-size: 12px;
  color: var(--ink-dim);
  margin-bottom: 14px;
}
/* v319 — Added 5th column (optional expiry date) to comp grant form. */
.admin-comp-form {
  display: grid;
  grid-template-columns: 1.8fr 1.1fr 1.8fr 1fr auto;
  gap: 8px;
  align-items: center;
}
@media (max-width: 600px) {
  .admin-comp-form {
    grid-template-columns: 1fr 1fr;
  }
  .admin-comp-form .btn { grid-column: 1 / -1; }
}
.admin-input {
  width: 100%;
  padding: 9px 10px;
  border: 1px solid var(--rule);
  border-radius: 6px;
  font-family: var(--sans);
  font-size: 13px;
  background: var(--surface);
  color: var(--ink);
}
.admin-input:focus {
  outline: none;
  border-color: var(--accent);
}
.admin-form-msg {
  font-family: var(--sans);
  font-size: 12px;
  color: var(--maraschino, #b13c2c);
  min-height: 16px;
  margin: 4px 0 10px;
}
.admin-comp-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.admin-comp-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 10px 12px;
  background: var(--surface-2);
  border: 1px solid var(--rule);
  border-radius: 6px;
  gap: 10px;
}
.admin-comp-main {
  flex: 1;
  min-width: 0;
}
.admin-comp-email {
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.admin-comp-meta {
  font-family: var(--sans);
  font-size: 11px;
  color: var(--ink-dim);
  margin-top: 2px;
}

/* ============================================================
   PRINT STYLESHEET — themed cocktail-menu page (v65).

   The pitch: a bartender taps "Print" inside a recipe sheet and gets
   what looks like a page from their bound spec book — typeset, leader-
   dotted ingredients, ornament between sections, edition byline at the
   foot. Not a screenshot of an app. A printed menu page.

   How it works:
     1. The Print button in views.js adds class "printing-spec" to <body>
        and class "printing-target" to #sheet-root, then calls
        window.print().
     2. The rules below hide everything outside the printing-target and
        re-skin the recipe sheet for paper:
          - White paper ground regardless of dark theme (themes are
            normally walnut/midnight/sage/teal — on paper we INVERT so
            ink reads black-on-cream).
          - A5 portrait page (close to the 5x7 inch recipe card the
            spec asked for); 0.5 inch margins.
          - Masthead: SPEC · the {Edition} edition (theme display face
            via --serif-display, theme accent for the ornament).
          - Sub-line: family · glass · garnish (data-print-sub).
          - Drop cap on the cocktail name.
          - Leader-dotted ingredient rows preserved.
          - Ornamental divider (--ornament-divider) between sections.
          - Footer: from the {Edition} edition · spec.app, hairline
            above (matches share-card byline).
     3. Each [data-theme] block sets --print-edition-name; one rule
        below reads it into the masthead + footer ::before/::after
        content strings, so all four bindings get their own header
        without four print stylesheets.

   Tear-down happens automatically after the print dialog closes (the
   trigger removes the classes); the screen UI is never altered.
   ============================================================ */
@media print {
  /* Page setup — A5 portrait, 0.5 inch margins. Browsers that respect
     @page will honor this; the rest fall back to the user's default
     paper size (still readable). */
  @page {
    size: A5 portrait;
    margin: 0.5in;
  }

  /* INVERT the theme tokens for paper. Themes are dark-on-dark by
     default; on paper we want body type in black ink and headings in
     the theme accent. The accent and display face stay theme-driven
     so each binding's print page looks distinct (gold for Bemelmans,
     platinum for Connaught, antique brass for Maison Premiere, rum
     amber for Smuggler's Cove). */
  html,
body {
    background: white !important;
    color: #111 !important;
    -webkit-print-color-adjust: exact !important;
    print-color-adjust: exact !important;
  }

  /* Step 1: hide the entire app. Anything not inside .printing-target
     stays out of the printout. We use display:none on the top-level
     app shell rather than visibility:hidden so blank columns don't
     reserve space at the top of the page. */
  body.printing-spec > #app > .app-header,
body.printing-spec > #app > .bottom-tabs,
body.printing-spec > #app > main#view,
body.printing-spec > #app > #toast-root,
body.printing-spec .tabs,
body.printing-spec .bottom-tabs,
body.printing-spec .app-header,
body.printing-spec .fab,
body.printing-spec .search,
body.printing-spec .sub-tabs,
body.printing-spec .toast,
body.printing-spec .daily-pour,
body.printing-spec .daily-pour-backdrop,
body.printing-spec .snackbar {
    display: none !important;
  }

  /* Step 2: tame the sheet shell — backdrop + sheet element become
     a plain document container. No fixed positioning, no shadows,
     no animations; the recipe sits on white paper. */
  body.printing-spec .sheet-backdrop {
    position: static !important;
    inset: auto !important;
    background: white !important;
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
    padding: 0 !important;
    display: block !important;
    overflow: visible !important;
    height: auto !important;
  }
  body.printing-spec .sheet {
    position: static !important;
    box-shadow: none !important;
    background: white !important;
    color: #111 !important;
    border: 0 !important;
    margin: 0 !important;
    padding: 0 !important;
    max-width: none !important;
    width: 100% !important;
    height: auto !important;
    max-height: none !important;
    transform: none !important;
    animation: none !important;
    overflow: visible !important;
    display: block !important;
  }

  /* Hide app-shell chrome inside the sheet — drag handle, header
     (close button + title), footer (action buttons). The masthead
     below replaces the title; everything else is interactive and
     useless on paper. */
  body.printing-spec .sheet-drag-handle,
body.printing-spec .sheet-header,
body.printing-spec .sheet-footer {
    display: none !important;
  }

  /* The body of the sheet IS the printout. Reset its surface and
     give it a typographic frame. */
  body.printing-spec .sheet-body {
    background: white !important;
    color: #111 !important;
    padding: 0 !important;
    margin: 0 !important;
    overflow: visible !important;
    height: auto !important;
    max-height: none !important;
    font-family: var(--serif, Georgia, "Iowan Old Style", serif) !important;
  }

  /* HEADER STACK — three pseudo-elements, three different hosts, so
     all three blocks (masthead, title, subtitle/footer) can exist
     simultaneously without colliding on a single element's ::before.
       - .sheet            ::before → "SPEC · the {Edition} edition" masthead
       - .sheet-body       ::before → cocktail name (data-print-title)
       - .sheet-body       ::after  → subtitle + footer byline (one
                                       white-space:pre-line block)
     Each binding's --print-edition-name + --ornament-divider tokens
     flow through, so the printout speaks the active theme's voice
     without per-theme print rules. */

  /* Cocktail name — set big, theme display face, left-aligned. */
  body.printing-spec .sheet-body::before {
    content: attr(data-print-title) !important;
    display: block !important;
    font-family: var(--serif-display, "Bodoni 72", "Didot", Georgia, serif) !important;
    font-size: 28pt !important;
    font-weight: 400 !important;
    font-style: normal !important;
    line-height: 1.05 !important;
    letter-spacing: 0.005em !important;
    text-transform: none !important;
    color: #111 !important;
    text-align: left !important;
    margin: 0 0 4pt !important;
    padding: 0 !important;
    border: 0 !important;
    text-shadow: none !important;
    /* drop-cap on the first letter of the title */
    /* (handled via ::first-letter below — pseudo on pseudo isn't
       supported, so we approximate with letter-spacing instead) */
  }

  /* Sub-line — family · glass · garnish */
  body.printing-spec .sheet-body::after {
    content: attr(data-print-sub) "\A" var(--ornament-divider, "·") "\A from the " var(--print-edition-name, "Bemelmans") " edition  " var(--ornament-divider, "·") "  spec.app" !important;
    /* Note: the \A escapes split the string into three lines
       (subtitle, ornament, footer byline) thanks to white-space:
       pre-line below. Compact and theme-honest. */
    display: block !important;
    white-space: pre-line !important;
    margin-top: 28pt !important;
    padding-top: 0 !important;
    border-top: 0 !important;
    text-align: center !important;
    font-family: var(--serif-italic, Georgia, serif) !important;
    font-style: italic !important;
    font-size: 9pt !important;
    line-height: 1.8 !important;
    letter-spacing: 0.08em !important;
    color: var(--accent, #b8860b) !important;
    text-shadow: none !important;
  }

  /* Masthead — "SPEC · the {Edition} edition" — moved to .sheet
     ::before so it sits above the cocktail name in document order. */
  body.printing-spec .sheet::before {
    content: "SPEC  " var(--ornament-divider, "·") "  the " var(--print-edition-name, "Bemelmans") " edition" !important;
    display: block !important;
    font-family: var(--serif-display, "Bodoni 72", Georgia, serif) !important;
    font-size: 9pt !important;
    font-weight: 400 !important;
    font-style: italic !important;
    letter-spacing: 0.32em !important;
    text-transform: uppercase !important;
    color: var(--accent, #b8860b) !important;
    text-align: center !important;
    margin: 0 0 22pt !important;
    padding-bottom: 8pt !important;
    border-bottom: 0.5pt solid var(--accent, #b8860b) !important;
    text-shadow: none !important;
  }

  /* SUB-LINE under the cocktail title — small caps, accent color,
     theme ornament before. Realized as a ::before on the first
     detail-section so it sits between title and content. */
  body.printing-spec .sheet-body > .detail-section:first-of-type::before,
body.printing-spec .sheet-body > .detail-photo + .detail-section::before,
body.printing-spec .sheet-body > .detail-meta-grid + .detail-section::before {
    content: "";
    display: none;
  }

  /* The detail-meta-grid carries Glass / Garnish / Category / Base.
     For print we already render those in the sub-line, so suppress
     the grid; everything below it is the recipe proper. */
  body.printing-spec .detail-meta-grid {
    display: none !important;
  }

  /* Allergen chips — the "Contains: dairy, egg" block. Useful but
     visually noisy; render as a flat italic line. */
  body.printing-spec .detail-allergens {
    border: 0 !important;
    background: transparent !important;
    padding: 0 !important;
    margin: 0 0 14pt !important;
    font-style: italic !important;
    font-size: 9pt !important;
    color: #555 !important;
  }
  body.printing-spec .detail-allergen-chip {
    display: inline !important;
    background: transparent !important;
    border: 0 !important;
    padding: 0 4pt 0 0 !important;
    color: #555 !important;
    font-size: 9pt !important;
  }
  body.printing-spec .detail-allergens-label {
    font-weight: 600 !important;
    margin-right: 4pt !important;
    color: #555 !important;
  }

  /* SECTION HEADINGS — small caps, accent color, hairline rule
     under, no ◆ ornament dot in front (loses on paper). */
  body.printing-spec .detail-section {
    margin-bottom: 18pt !important;
    page-break-inside: avoid;
  }
  body.printing-spec .detail-section h4 {
    font-family: var(--serif-display, Georgia, serif) !important;
    font-size: 9pt !important;
    font-weight: 600 !important;
    letter-spacing: 0.24em !important;
    text-transform: uppercase !important;
    color: var(--accent, #b8860b) !important;
    margin: 0 0 8pt !important;
    padding-bottom: 4pt !important;
    border-bottom: 0.5pt solid var(--accent, #b8860b) !important;
    background: transparent !important;
    display: block !important;
    text-shadow: none !important;
  }
  body.printing-spec .detail-section h4::before {
    display: none !important;
    content: none !important;
  }

  /* INGREDIENTS — leader-dot rows, italic display-face amounts,
     small-caps units, body-face names. Reproduces the screen
     treatment, in black ink. */
  body.printing-spec .ingredient-list {
    list-style: none !important;
    padding: 0 !important;
    margin: 0 !important;
    page-break-inside: avoid;
  }
  body.printing-spec .ingredient-list li {
    display: grid !important;
    grid-template-columns: 56pt 64pt 1fr !important;
    gap: 10pt !important;
    padding: 4pt 0 !important;
    border-bottom: 0.5pt dotted #aaa !important;
    background: transparent !important;
    font-size: 11pt !important;
    line-height: 1.5 !important;
    align-items: baseline !important;
  }
  body.printing-spec .ingredient-list li:last-child {
    border-bottom: 0 !important;
  }
  body.printing-spec .ingredient-list .amount {
    font-family: var(--serif-display, Georgia, serif) !important;
    font-style: italic !important;
    font-size: 12pt !important;
    color: #111 !important;
    text-align: right !important;
    text-shadow: none !important;
  }
  body.printing-spec .ingredient-list .unit {
    font-family: var(--sans, sans-serif) !important;
    font-size: 8pt !important;
    letter-spacing: 0.18em !important;
    text-transform: uppercase !important;
    font-weight: 600 !important;
    color: #555 !important;
  }
  body.printing-spec .ingredient-list .name {
    font-family: var(--serif, Georgia, serif) !important;
    font-size: 11pt !important;
    color: #111 !important;
    line-height: 1.4 !important;
  }
  /* Encyclopedia link button — render as plain text. Underlines on
     paper read like emphasis the ingredient hasn't earned. */
  body.printing-spec .ingredient-link,
body.printing-spec .ingredient-sub-link,
body.printing-spec .technique-link {
    background: transparent !important;
    border: 0 !important;
    padding: 0 !important;
    color: #111 !important;
    font: inherit !important;
    text-decoration: none !important;
    -webkit-text-decoration: none !important;
    cursor: default !important;
  }

  /* Method + notes — the prose blocks. Body serif, comfortable
     leading, drop-cap on the first letter of method (printed-menu
     touch). */
  body.printing-spec .detail-text,
body.printing-spec .tasting-prose {
    font-family: var(--serif, Georgia, serif) !important;
    font-size: 11pt !important;
    line-height: 1.6 !important;
    color: #111 !important;
    white-space: pre-wrap !important;
    background: transparent !important;
  }

  /* Drop-cap on the cocktail name's first letter — mimics the
     editorial illuminated initial. The screen drop-cap rule
     targets the first detail-text; on paper we want it on the
     title itself, but ::first-letter on a generated content
     pseudo isn't reliable cross-browser. Apply it to the first
     detail-text instead, matching the screen treatment but
     larger + theme accent. */
  body.printing-spec .sheet-body > *:first-child + .detail-section .detail-text:first-of-type::first-letter,
body.printing-spec .sheet-body > .detail-section:first-of-type .detail-text:first-of-type::first-letter,
body.printing-spec .sheet-body .detail-section:first-of-type .detail-text:first-of-type::first-letter {
    font-family: var(--serif-display, Georgia, serif) !important;
    font-size: 3.5em !important;
    float: left !important;
    line-height: 0.9 !important;
    margin: 4pt 6pt 0 0 !important;
    color: var(--accent, #b8860b) !important;
    font-style: italic !important;
    text-shadow: none !important;
  }

  /* v66 — illuminated initial frame on paper. Mirrors the screen
     treatment but tuned for paper: skip background fill (paper
     already provides the warm tone — a fill would dirty the page),
     keep just the border + corner ornament glyphs. The frame is a
     positioned ::before on the paragraph, z-index -1 so the cap
     paints on top. (Not on ::first-letter, to dodge the Safari
     clip bug when float + sibling ::before combine.) */
  body.printing-spec .sheet-body > *:first-child + .detail-section .detail-text:first-of-type,
body.printing-spec .sheet-body > .detail-section:first-of-type .detail-text:first-of-type,
body.printing-spec .sheet-body .detail-section:first-of-type .detail-text:first-of-type {
    position: relative !important;
    isolation: isolate !important;
  }
  body.printing-spec .sheet-body > *:first-child + .detail-section .detail-text:first-of-type::before,
body.printing-spec .sheet-body > .detail-section:first-of-type .detail-text:first-of-type::before,
body.printing-spec .sheet-body .detail-section:first-of-type .detail-text:first-of-type::before {
    content: var(--dropcap-ornament-pre, "") !important;
    position: absolute !important;
    top: 2pt !important;
    left: -3pt !important;
    width: 3.5em !important;
    height: 3em !important;
    background: transparent !important;
    border: var(--dropcap-frame-border, 0) !important;
    border-radius: var(--dropcap-frame-radius, 0) !important;
    font-family: var(--serif-display, Georgia, serif) !important;
    font-size: 0.7em !important;
    line-height: 1 !important;
    color: var(--accent, #b8860b) !important;
    text-align: left !important;
    padding: 2pt 0 0 3pt !important;
    z-index: -1 !important;
    pointer-events: none !important;
    text-shadow: none !important;
  }
  body.printing-spec .sheet-body > *:first-child + .detail-section .detail-text:first-of-type::after,
body.printing-spec .sheet-body > .detail-section:first-of-type .detail-text:first-of-type::after,
body.printing-spec .sheet-body .detail-section:first-of-type .detail-text:first-of-type::after {
    content: var(--dropcap-ornament-post, "") !important;
    position: absolute !important;
    top: calc(3em - 0.4em) !important;
    left: calc(3.5em - 3pt - 0.9em) !important;
    font-family: var(--serif-display, Georgia, serif) !important;
    font-size: 0.7em !important;
    line-height: 1 !important;
    color: var(--accent, #b8860b) !important;
    z-index: -1 !important;
    pointer-events: none !important;
    text-shadow: none !important;
  }

  /* HIDE — interactive UI that has no place on paper:
     - Pre-batch handoff button (a button to navigate to a tab —
       useless once printed)
     - Batch scale chip row (×1 / ×2 / ×4 / Custom — the printout
       captured a single scale; chips are a screen affordance)
     - Substitutions accordion (long; ships separately if needed)
     - Reverse subs (brand-page artifact; out of place on a recipe)
     - Cross-link list ("More in the X family") — these are
       navigation, not content
     - Comments thread — discussion is a screen surface
     - Discussion composer
     - Photo (we want a typeset page, not a photo print) */
  body.printing-spec .detail-prebatch-row,
body.printing-spec .batch-scale-row,
body.printing-spec .your-bar-row,
body.printing-spec .subs-section,
body.printing-spec .reverse-subs-list,
body.printing-spec .cross-link-list,
body.printing-spec .comments-section,
body.printing-spec .comments-placeholder,
body.printing-spec .detail-photo {
    display: none !important;
  }

  /* "More in the X family" wrapper section — its child cross-link
     list is hidden, so the heading would orphan above empty space.
     Hide the whole section. */
  body.printing-spec .detail-section:has(.cross-link-list) {
    display: none !important;
  }

  /* Page-break hygiene — never split a heading off its body. */
  body.printing-spec h1,
body.printing-spec h2,
body.printing-spec h3,
body.printing-spec h4 {
    page-break-after: avoid;
  }

  /* Colors — force the printer to honor accent + ornament rather
     than stripping them. Some browsers print a default "ink-saving"
     mode that flattens color; this opts back in for our accents. */
  body.printing-spec .sheet,
body.printing-spec .sheet-body,
body.printing-spec .sheet-body * {
    -webkit-print-color-adjust: exact !important;
    print-color-adjust: exact !important;
  }
}

/* ============================================================
   SUBSTITUTIONS — collapsible block on cocktail detail sheet
   listing close swaps for ingredients we have sub data for.
   ============================================================ */
.subs-section summary {
  cursor: pointer;
  list-style: none;
  outline: none;
}
.subs-section summary::-webkit-details-marker {
  display: none;
}
.subs-section summary h4::after {
  content: " ▾";
  color: var(--ink-faint);
  font-size: 0.85em;
}
.subs-section[open] summary h4::after {
  content: " ▴";
}
.subs-list {
  display: flex;
  flex-direction: column;
  gap: 18px;
  padding-top: 12px;
}
.subs-item {
  border-left: 2px solid var(--accent);
  padding-left: 12px;
}
.subs-ingredient {
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: 8px;
}
.subs-row {
  margin-bottom: 10px;
  display: grid;
  grid-template-columns: auto auto;
  column-gap: 10px;
  align-items: baseline;
}
.subs-name {
  font-family: var(--serif);
  font-weight: 600;
  font-size: 15px;
  color: var(--ink);
}
.subs-ratio {
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}
.subs-note {
  grid-column: 1 / -1;
  font-family: var(--serif-italic);
  font-style: italic;
  font-size: 13px;
  color: var(--ink-dim);
  line-height: 1.5;
  margin-top: 2px;
}

/* ============================================================
   BATCH SCALING CHIPS — multiplier control above ingredient list
   on canonical cocktail detail sheets.
   ============================================================ */
.batch-scale-row {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  margin: 0 0 12px;
}
.batch-chip {
  background: transparent;
  color: var(--ink-faint);
  border: 1px solid var(--rule);
  border-radius: 4px;
  padding: 6px 12px;
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.04em;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
  transition: background 100ms ease, color 100ms ease, border-color 100ms ease;
}
.batch-chip:hover {
  color: var(--ink-dim);
  border-color: var(--ink-faint);
}
.batch-chip.on {
  background: var(--accent);
  color: var(--bg);
  border-color: var(--accent);
}
.batch-chip-custom {
  border-style: dashed;
  font-style: italic;
}
/* Wave 117 — "Your bar" chip. Same shape as batch chips but accent-tinted
   to distinguish "scale to your glass" from "make N drinks". (Kept for any
   legacy callers; v275 promoted the primary affordance to .your-bar-row.) */
.batch-chip-glass {
  border-color: color-mix(in srgb, var(--accent) 50%, var(--rule-strong));
  color: var(--accent-2, var(--accent));
}
.batch-chip-glass.on {
  background: color-mix(in srgb, var(--accent) 18%, transparent);
  border-color: var(--accent);
  color: var(--ink);
}
/* v275 / v277 — "Fit to your glass" row. Lives ABOVE the batch chip row
   on every recipe sheet. Two distinct tap targets:
     • Left (.your-bar-chooser) — opens the glass picker
     • Right (.your-bar-toggle) — switches scaling on/off
   The row itself is a layout container, not interactive.
   ============================================================ */
.your-bar-row {
  display: flex;
  align-items: stretch;
  gap: 8px;
  width: 100%;
  margin: 0 0 12px;
  background: color-mix(in srgb, var(--accent) 6%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 30%, var(--rule));
  border-radius: 8px;
  font-family: inherit;
  color: var(--ink);
  transition: background 120ms ease, border-color 120ms ease;
}
.your-bar-row.is-on {
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  border-color: var(--accent);
}
.your-bar-chooser {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 2px;
  flex: 1;
  min-width: 0;
  padding: 10px 14px;
  background: transparent;
  border: none;
  border-right: 1px solid color-mix(in srgb, var(--accent) 20%, transparent);
  border-radius: 7px 0 0 7px;
  cursor: pointer;
  font-family: inherit;
  color: var(--ink);
  text-align: left;
  transition: background 120ms ease;
  -webkit-tap-highlight-color: transparent;
}
.your-bar-chooser:hover {
  background: color-mix(in srgb, var(--accent) 6%, transparent);
}
.your-bar-eyebrow {
  font-family: var(--sans);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent-2, var(--accent));
}
.your-bar-glass-line {
  font-family: var(--serif, var(--sans));
  font-size: 15px;
  font-weight: 500;
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.your-bar-glass-info {
  font-variant-numeric: tabular-nums;
}
.your-bar-picker-hint {
  color: var(--ink-faint);
  font-size: 12px;
  margin-left: 4px;
}
.your-bar-toggle {
  position: relative;
  flex: 0 0 auto;
  align-self: center;
  width: 42px;
  height: 24px;
  margin: 0 14px 0 4px;
  border-radius: 999px;
  background: var(--rule-strong, var(--rule));
  border: none;
  padding: 0;
  cursor: pointer;
  transition: background 140ms ease;
  -webkit-tap-highlight-color: transparent;
}
.your-bar-toggle:hover {
  background: color-mix(in srgb, var(--accent) 30%, var(--rule-strong, var(--rule)));
}
.your-bar-toggle-knob {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--bg);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
  transition: transform 140ms ease, background 140ms ease;
}
.your-bar-row.is-on .your-bar-toggle {
  background: var(--accent);
}
.your-bar-row.is-on .your-bar-toggle-knob {
  transform: translateX(18px);
  background: var(--bg);
}
@media (max-width: 480px) {
  .your-bar-chooser {
    padding: 10px 12px;
  }
  .your-bar-glass-line {
    font-size: 14px;
  }
  .your-bar-toggle {
    margin: 0 12px 0 4px;
  }
}
.house-glass-notice {
  font-family: var(--serif-italic);
  font-style: italic;
  font-size: 12.5px;
  color: var(--ink-dim);
  padding: 8px 4px 10px;
  margin: 0;
  border-bottom: 1px solid color-mix(in srgb, var(--rule) 60%, transparent);
}
.ingredient-list-scaled li .amount {
  color: var(--accent-2, var(--accent));
}

/* Wave 117 — Small accent dot on whichever venue pill is currently
   the scaling-active venue (i.e. its glassware is what drives the
   "Your bar" chip on every recipe). This is independent from the .on
   selection style — a bartender can be filtering "All venues" while
   still scaling against one specific bar. */
.house-venue-pill.is-scaling {
  position: relative;
}
.house-venue-pill.is-scaling::after {
  content: "";
  position: absolute;
  top: 4px;
  right: 4px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent-2, var(--accent));
  box-shadow: 0 0 0 1.5px var(--bg, #1a1a1a);
}

/* ============================================================
   BATCH BUILDER — standalone freeform recipe scaler view
   (separate from the per-cocktail .batch-chip multiplier above).
   ============================================================ */
.batch-load-row {
  display: flex;
  gap: 8px;
  margin-bottom: 18px;
}
.batch-rows {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 6px;
}
.batch-row {
  display: grid;
  grid-template-columns: 70px 60px 1fr 32px;
  gap: 6px;
  align-items: center;
}
.input.batch-amount,
.input.batch-unit,
.input.batch-name {
  padding: 9px 10px;
  font-size: 14px;
}
.input.batch-amount {
  text-align: center;
  font-variant-numeric: tabular-nums;
}
.batch-remove {
  background: transparent;
  border: 0;
  color: var(--ink-faint);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  padding: 0;
  border-radius: 4px;
  transition: color 100ms ease, background 100ms ease;
}
.batch-remove:hover {
  color: var(--ink);
  background: var(--surface-2);
}
.batch-mode-row {
  display: flex;
  gap: 6px;
  margin: 6px 0 12px;
}
.batch-mode-chip {
  flex: 1 1 auto;
  background: var(--surface-2);
  color: var(--ink-dim);
  border: 1px solid var(--rule);
  border-radius: 6px;
  padding: 10px 8px;
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.02em;
  cursor: pointer;
  transition: background 100ms ease, color 100ms ease, border-color 100ms ease;
}
.batch-mode-chip:hover {
  border-color: var(--ink-faint);
  color: var(--ink);
}
.batch-mode-chip.on {
  background: var(--accent);
  color: var(--bg);
  border-color: var(--accent);
}
.batch-target-input {
  font-size: 18px;
  text-align: left;
  font-variant-numeric: tabular-nums;
}
.batch-output {
  margin-top: 28px;
  padding: 18px 16px;
  background: var(--surface-2);
  border: var(--hairline) solid var(--rule);
  border-radius: 6px;
}
.batch-output-empty {
  font-family: var(--serif-italic);
  font-style: italic;
  color: var(--ink-faint);
  text-align: center;
  padding: 14px 0;
  font-size: 14px;
}
.batch-output-header {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  border-bottom: var(--hairline) solid var(--rule);
  padding-bottom: 10px;
  margin-bottom: 12px;
}
/* Batch output stats — unified onto the canonical Bar pattern. The mult
   is the highlighted stat (accent color, 38px Bodoni); the vol is the
   small uppercase ink-faint label. Matches .bar-summary-num /
   .bar-summary-label so the three views read as one type system. */
.batch-output-mult {
  font-family: var(--serif-display);
  font-size: 38px;
  line-height: 1;
  color: var(--accent);
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}
.batch-output-vol {
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.batch-output-list {
  list-style: none;
  margin: 0;
  padding: 0;
}
.batch-output-row {
  display: grid;
  grid-template-columns: 70px 50px 1fr;
  gap: 8px;
  align-items: baseline;
  padding: 8px 0;
  border-bottom: var(--hairline) solid var(--rule);
  font-family: var(--serif);
  font-size: 16px;
  color: var(--ink);
}
.batch-output-row:last-child { border-bottom: 0; }
.batch-output-row .amount {
  font-family: var(--sans);
  font-weight: 700;
  color: var(--accent);
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.batch-output-row .unit {
  color: var(--ink-faint);
  font-size: 12px;
  letter-spacing: 0.04em;
}

/* Loader sheet (Load from library…) */
.loader-results {
  display: flex;
  flex-direction: column;
  margin-top: 14px;
  max-height: 60vh;
  overflow-y: auto;
}
.loader-row {
  background: transparent;
  border: 0;
  border-bottom: var(--hairline) solid var(--rule);
  padding: 14px 4px;
  text-align: left;
  cursor: pointer;
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  font-family: var(--serif);
  color: var(--ink);
  transition: background 100ms ease, padding-left 100ms ease;
}
.loader-row:hover {
  background: var(--surface-2);
  padding-left: 8px;
}
.loader-row-name {
  font-size: 16px;
  font-weight: 500;
}
.loader-row-meta {
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

/* ============================================================
   BAR — inventory checklist (Tiki Sunset palette).
   Used by pantry-view.js. Same visual language as the Specs
   chip rows but with on/off pill state and grouped headers.
   ============================================================ */
.bar-summary {
  margin: 4px 0 18px;
  padding: 18px 16px;
  background: var(--surface-2);
  border: var(--hairline) solid var(--rule);
  border-radius: 6px;
}
.bar-summary-row {
  display: flex;
  justify-content: space-around;
  align-items: baseline;
  gap: 16px;
}
.bar-summary-stat {
  text-align: center;
}
.bar-summary-num {
  font-family: var(--serif-display);
  font-size: 38px;
  line-height: 1;
  color: var(--ink);
  letter-spacing: -0.02em;
}
.bar-summary-stat-accent .bar-summary-num {
  color: var(--accent);
}
.bar-summary-stat-tap {
  background: transparent;
  border: 0;
  padding: 0;
  cursor: pointer;
  font-family: inherit;
  border-radius: 4px;
  transition: opacity 120ms ease, transform 120ms ease;
}
.bar-summary-stat-tap:not(:disabled):hover {
  opacity: 0.85;
  transform: translateY(-1px);
}
.bar-summary-stat-tap:disabled {
  cursor: default;
  opacity: 0.55;
}
.bar-summary-stat-tap:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 4px;
}
.bar-summary-cta {
  display: block;
  width: 100%;
  margin: 14px 0 0;
  background: var(--accent);
  color: var(--bg);
  border: 0;
  border-radius: 999px;
  padding: 14px 22px;
  font-family: var(--sans);
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.06em;
  cursor: pointer;
  transition: background 120ms ease, transform 80ms ease;
}
.bar-summary-cta:hover {
  background: var(--accent-2);
}
.bar-summary-cta:active {
  transform: translateY(1px);
}
.bar-summary-label {
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-top: 6px;
}
.bar-actions {
  display: flex;
  gap: 8px;
  margin-bottom: 24px;
}
.bar-groups {
  display: flex;
  flex-direction: column;
  gap: 26px;
  padding-bottom: 100px;       /* clear the bottom-tab bar */
}
.bar-group {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.bar-group-header {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  border-bottom: var(--hairline) solid var(--rule);
  padding-bottom: 6px;
}
.bar-group-name {
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent);
}
.bar-group-count {
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.10em;
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}
.bar-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.bar-chip {
  background: transparent;
  color: var(--ink-dim);
  border: 1.5px solid var(--rule-strong);
  border-radius: 999px;
  padding: 9px 14px;
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease, border-color 120ms ease;
}
.bar-chip:hover {
  border-color: var(--ink-dim);
  color: var(--ink);
}
.bar-chip.on {
  background: var(--accent);
  color: var(--bg);
  border-color: var(--accent);
  font-weight: 600;
}
.bar-chip.on:hover {
  background: var(--accent-2);
}
.bar-chip:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ============================================================
   LONG-PRESS FAVORITE FLASH — confirms the toggle visually after
   a 500ms hold on a Specs card.
   ============================================================ */
@keyframes card-fav-flash-anim {
  0%   { box-shadow: 0 0 0 0 rgba(255, 140, 90, 0.0); }
  30%  { box-shadow: 0 0 0 4px rgba(255, 140, 90, 0.55); }
  100% { box-shadow: 0 0 0 0 rgba(255, 140, 90, 0.0); }
}
.card-fav-flash {
  animation: card-fav-flash-anim 0.6s ease-out 1;
}

/* ============================================================
   PROFILE — settings row with avatar monogram + name/venue inputs.
   ============================================================ */
.profile-group { padding: 14px 16px; }
.profile-row {
  display: flex;
  align-items: flex-start;
  gap: 14px;
}
/* Profile avatar — scaled-up sibling of .brand-mark. Hairline coral
   border, transparent fill with a soft inset radial highlight, italic
   Bodoni initials in --accent-2. The 48px size keeps it as the user's
   identity glyph (vs. the 32px header brand-mark). */
.profile-avatar {
  flex: 0 0 auto;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  border: 1.5px solid var(--accent);
  background: radial-gradient(circle at 30% 30%, rgba(232, 200, 120, 0.2), transparent 60%);
  color: var(--accent-2);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--serif); font-style: italic;
  font-size: 22px;
  font-weight: 400;
  line-height: 1;
  letter-spacing: 0;
  box-shadow: 0 0 0 2px rgba(199, 156, 79, 0.12), inset 0 1px 0 rgba(232, 200, 120, 0.25);
}
.profile-fields {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.profile-fields .input {
  font-size: 14px;
  padding: 8px 10px;
}

/* ============================================================
   COMMENTS / SUBTHREADS
   Local-only discussion under each cocktail and brand. The audit
   flagged this as "Reddit-grafted" — rebuilt in editorial dialect:
   italic-serif byline (like a printed marginalia), no emoji, ↳
   glyph for replies (matches the wine-list typography vocabulary).
   ============================================================ */
.comments-list {
  list-style: none;
  padding: 0;
  margin: 0 0 16px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.comments-empty {
  font-family: var(--serif-italic);
  font-style: italic;
  color: var(--ink-faint);
  font-size: 14px;
  padding: 12px 0;
  text-align: center;
  margin: 0;
}
.comment-row {
  border-bottom: var(--hairline) solid var(--rule);
  padding: 10px 0;
  position: relative;
}
.comment-row.comment-reply {
  margin-left: 18px;
  padding-left: 18px;
  border-bottom: 0;
}
.comment-row.comment-reply::before {
  content: "↳";
  position: absolute;
  left: 0;
  top: 12px;
  color: var(--accent-2);
  font-family: var(--serif);
  font-size: 16px;
  line-height: 1;
}
.comment-meta {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin-bottom: 6px;
}
.comment-author {
  font-family: var(--serif-italic);
  font-style: italic;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.01em;
  color: var(--accent);
}
.comment-when {
  font-family: var(--sans);
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.comment-body {
  font-family: var(--serif);
  font-size: 14px;
  line-height: 1.5;
  color: var(--ink);
  white-space: pre-wrap;
}
.comment-actions {
  display: flex;
  gap: 12px;
  margin-top: 6px;
}
.comment-action-btn {
  background: transparent;
  border: 0;
  padding: 0;
  color: var(--ink-faint);
  font-family: var(--sans);
  /* v320 — Casing sweep: comment action buttons are button role,
     Title Case ("Reply / Edit / Delete") not "REPLY / EDIT / DELETE". */
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.02em;
  cursor: pointer;
}
.comment-action-btn:hover { color: var(--accent); }
.comment-action-btn.comment-delete:hover { color: #ff6b6b; }
.comments-composer {
  margin-top: 6px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.comments-textarea {
  width: 100%;
  resize: vertical;
  font-family: var(--serif);
  font-size: 14px;
  padding: 10px;
  background: var(--surface-2);
  border: var(--hairline) solid var(--rule);
  border-radius: 4px;
  color: var(--ink);
}
.comments-textarea:focus {
  outline: none;
  border-color: var(--accent);
}
.comments-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
}
.comments-noprofile {
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: flex-start;
  padding: 10px 12px;
  background: var(--surface-2);
  border: var(--hairline) solid var(--rule);
  border-radius: 4px;
  font-family: var(--serif-italic);
  font-style: italic;
  font-size: 13px;
  color: var(--ink-dim);
}

/* ============================================================
   SPECS FILTER TRIGGER — Pill button that opens the filter sheet.
   Replaces the v45-v50 inline Spirit/Profile/Era chip rows
   (which ate ~150px of chrome above the first card).
   ============================================================ */
.specs-filter-trigger {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: transparent;
  border: 1px solid var(--rule-strong);
  border-radius: 999px;
  padding: 8px 14px 8px 12px;
  color: var(--ink-dim);
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.06em;
  margin: 4px 0 14px;
  cursor: pointer;
  transition: color 100ms ease, border-color 100ms ease, background 100ms ease;
}
.specs-filter-trigger:hover {
  color: var(--ink);
  border-color: var(--ink-faint);
}
.specs-filter-trigger.has-filters {
  color: var(--accent);
  border-color: var(--accent);
}
.specs-filter-icon {
  display: inline-flex;
  width: 16px;
  height: 16px;
}
.specs-filter-icon svg { width: 100%; height: 100%; }
.specs-filter-label {
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.specs-filter-count {
  display: none;
  background: var(--accent);
  color: var(--bg);
  border-radius: 999px;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  font-size: 10px;
  font-weight: 800;
  line-height: 18px;
  text-align: center;
  font-variant-numeric: tabular-nums;
  margin-left: 2px;
}
.specs-filter-trigger.has-filters .specs-filter-count {
  display: inline-block;
}

/* Filter sheet — Spirit/Profile/Era chip rows in a labeled column. */
.filter-sheet-body {
  display: flex;
  flex-direction: column;
  gap: 22px;
}
.filter-section {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.filter-section-label {
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent);
  border-bottom: var(--hairline) solid var(--rule);
  padding-bottom: 6px;
}

/* ============================================================
   SPECS — inline "Edit my bar" link, only visible when the
   ✓ Possible filter is active. Replaces the standalone Bar tab.
   ============================================================ */
.specs-bar-hint:empty { display: none; }
.specs-bar-hint-btn {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  background: var(--surface-2);
  border: var(--hairline) solid var(--rule);
  border-radius: 6px;
  padding: 12px 16px;
  margin: 8px 0 12px;
  font-family: var(--sans);
  cursor: pointer;
  transition: background 100ms ease, border-color 100ms ease;
}
.specs-bar-hint-btn:hover {
  background: var(--surface);
  border-color: var(--accent);
}
.specs-bar-hint-label {
  color: var(--accent);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.06em;
}
.specs-bar-hint-count {
  color: var(--ink-faint);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  font-variant-numeric: tabular-nums;
}

/* ============================================================
   prefers-reduced-motion — respect users who opt out of animation.
   Covers boot splash, sheet animations, FAB glow, transitions.
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  *,
*::before,
*::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* ============================================================
   BOOT SPLASH — shown while the seed installs on first run.
   ============================================================ */
.boot-splash {
  /* Viewport-pinned so it doesn't depend on the .view container being
     laid out. On returning visits the seed runs in <50ms; the splash is
     replaced before the fade-in delay even resolves. */
  position: fixed;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  pointer-events: none;
  opacity: 0;
  background: var(--bg);
  z-index: 1;
  animation: boot-fade-in 0.25s ease 0.15s forwards;
}
@keyframes boot-fade-in { to { opacity: 1; } }
.boot-splash-mark {
  font-family: var(--serif-display);
  font-size: 56px;
  letter-spacing: 0.32em;
  color: var(--accent);
  padding-left: 0.32em;
  text-shadow: 0 0 24px rgba(255, 140, 90, 0.25);
}
.boot-splash-sub {
  font-family: var(--serif-italic);
  font-style: italic;
  font-size: 14px;
  color: var(--ink-faint);
  letter-spacing: 0.06em;
}

/* ============================================================
   STRUCTURED TASTING NOTES  (Nose / Palate / Finish / Mouthfeel)
   The deepening rounds rewrote brand tasting fields into a 4-section
   format. Render each section as a label + prose row so the bartender
   can scan instead of read a 600-char paragraph.
   ============================================================ */
.tasting-grid {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.tasting-row {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.tasting-label {
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
}
.tasting-prose {
  font-family: var(--serif);
  font-size: 15px;
  line-height: 1.55;
  color: var(--ink);
}

/* ============================================================
   CROSS-LINK LIST  (brand → cocktails, cocktail → variants)
   Each item is a button styled like a quiet menu row. Clicking
   closes the current detail sheet and opens the linked one.
   ============================================================ */
.cross-link-list {
  list-style: none;
  padding: 0;
  margin: 0;
}
.cross-link-list li {
  border-bottom: var(--hairline) solid var(--rule);
}
.cross-link-list li:last-child {
  border-bottom: 0;
}
.cross-link {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  width: 100%;
  background: transparent;
  border: 0;
  padding: 12px 0;
  text-align: left;
  cursor: pointer;
  color: var(--ink);
  font-family: var(--serif);
  font-size: 15px;
  line-height: 1.3;
  transition: color 120ms ease, padding 120ms ease;
}
.cross-link:hover {
  color: var(--accent);
  padding-left: 4px;
}
.cross-link:focus-visible {
  color: var(--accent);
  padding-left: 4px;
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 2px;
}
.cross-link-name {
  flex: 1 1 auto;
  letter-spacing: 0.01em;
}
.cross-link-name::after {
  content: " ›";
  color: var(--ink-faint);
  font-family: var(--sans);
  margin-left: 6px;
  transition: color 120ms ease, transform 120ms ease;
}
.cross-link:hover .cross-link-name::after,
.cross-link:focus-visible .cross-link-name::after {
  color: var(--accent);
}
.cross-link-meta {
  color: var(--ink-faint);
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin-left: 12px;
  flex: 0 0 auto;
}

/* ============================================================
   VERSIONS
   ============================================================ */
.versions-list { display: flex; flex-direction: column; gap: 0; }
.version-row {
  display: flex; justify-content: space-between; align-items: center;
  padding: 12px 0;
  border-bottom: var(--hairline) solid var(--rule);
  font-size: 14px;
}
.version-row.current {
  color: var(--accent);
  font-family: var(--serif); font-style: italic;
}
.version-meta {
  color: var(--ink-faint);
  font-size: 11px; letter-spacing: 0.06em;
}

/* ============================================================
   TOAST
   ============================================================ */
#toast-root {
  position: fixed; bottom: calc(92px + var(--safe-bottom));
  left: 50%; transform: translateX(-50%);
  z-index: 200; pointer-events: none;
}
@media (min-width: 720px) {
  #toast-root { bottom: 32px; }
}
.toast {
  background: var(--surface-2);
  color: var(--ink);
  border: var(--hairline) solid var(--accent);
  padding: 11px 22px;
  border-radius: 999px;
  font-size: 13px;
  letter-spacing: 0.06em;
  margin-bottom: 8px;
  animation: toast-in .2s ease, toast-out .25s ease 2.5s forwards;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.5);
  font-family: var(--serif); font-style: italic;
}
.toast-error {
  background: rgba(122, 31, 36, 0.15);
  color: var(--maraschino-2);
  border-color: var(--maraschino);
  font-style: normal;
}
@keyframes toast-in {
  from { transform: translateY(10px); opacity: 0; }
  to   { transform: translateY(0); opacity: 1; }
}
@keyframes toast-out {
  to { transform: translateY(-10px); opacity: 0; }
}

/* v111 — Wave 54: undo-toast variant. Wider than a standard toast so the
   inline Undo button has breathing room. Stays visible for 6s (vs 2.5s
   for the standard toast — see the overridden animation timing). */
.toast.toast-undo-wrap {
  display: inline-flex;
  align-items: center;
  gap: 14px;
  padding: 8px 8px 8px 18px;
  /* Override the standard toast-out timing — the undo toast lives 6s
     before fading, vs 2.5s for an info toast. */
  animation: toast-in .2s ease, toast-out .25s ease 5.5s forwards;
  /* v244 — Critical. #toast-root has pointer-events:none (so the toast
     band doesn't block taps on the UI underneath). But the undo toast
     has an interactive Undo button — without this override, the Undo
     click passes THROUGH the toast to whatever's behind it, and the
     onUndo callback never fires. Standalone .toast (info-only) keeps
     the inherited pointer-events:none — they should never absorb taps. */
  pointer-events: auto;
}
.toast-undo-wrap .toast-msg {
  font-style: italic;
  flex: 1;
}
.toast-undo {
  background: transparent;
  color: var(--accent);
  border: 1px solid var(--accent);
  border-radius: 999px;
  padding: 5px 14px;
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background 120ms ease;
}
.toast-undo:hover {
  background: color-mix(in srgb, var(--accent) 15%, transparent);
}
.toast-undo:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* v111 — Wave 61: Print paper-size picker rows. Three radio-style rows
   inside a settings-group; the active option gets a checkmark + an
   accent left-border. */
.paper-size-group {
  padding: 0 !important;
}
.paper-size-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: 12px 16px;
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--rule);
  border-left: 3px solid transparent;
  color: var(--ink);
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  transition: background 120ms ease, border-color 120ms ease;
}
.paper-size-row:last-child { border-bottom: 0; }
.paper-size-row:hover { background: color-mix(in srgb, var(--accent) 5%, transparent); }
.paper-size-row.is-active {
  border-left-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 8%, transparent);
}
.paper-size-row-label {
  font-family: var(--serif-display);
  font-size: 16px;
  color: var(--ink-bright);
}
.paper-size-row-desc {
  font-family: var(--serif-italic);
  font-style: italic;
  font-size: 12.5px;
  color: var(--ink-dim);
  margin-top: 2px;
}
.paper-size-row-check {
  color: var(--accent);
  font-size: 16px;
  font-weight: bold;
  min-width: 16px;
  text-align: right;
}

/* v111 — Wave 60: Profile discovery callout. Dismissible "quick tour"
   card shown once per device to returning users who never explored
   what Profile can do. Sits below the italic intro line. */
.profile-discovery-callout {
  position: relative;
  background: color-mix(in srgb, var(--accent) 8%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--accent) 35%, var(--rule));
  border-left: 3px solid var(--accent);
  border-radius: 0 8px 8px 0;
  padding: 16px 18px 14px;
  margin: 0 0 22px;
}
.profile-discovery-eyebrow {
  font-family: var(--sans);
  font-size: 10.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 4px;
}
.profile-discovery-title {
  font-family: var(--serif-display);
  font-size: 18px;
  color: var(--ink-bright);
  margin: 0 0 10px;
  letter-spacing: 0.2px;
}
.profile-discovery-list {
  margin: 0 0 12px;
  padding-left: 18px;
  font-family: var(--serif);
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--ink);
}
.profile-discovery-list li { margin-bottom: 4px; }
.profile-discovery-list strong {
  color: var(--accent);
  font-weight: 600;
}
.profile-discovery-dismiss {
  /* v320.1 — Maya second-look audit: this was the one stray button
     still SHOUTING after the .btn / .tab / .sub-tab / .chip casing
     sweep. Per Sarah's voice rubric (Title Case for buttons), the
     "Got it" dismiss now renders sentence-cased without letter-
     spacing. Size lifted 11->12 to compensate for cap-height drop. */
  background: transparent;
  border: 1px solid var(--accent);
  color: var(--accent);
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.02em;
  border-radius: 999px;
  padding: 5px 14px;
  cursor: pointer;
  transition: background 120ms ease;
}
.profile-discovery-dismiss:hover {
  background: color-mix(in srgb, var(--accent) 15%, transparent);
}

/* v111 — Wave 58: Spirit library sub-style section headers. When a
   family is selected (Whiskey/Agave/Rum/etc) without a specific sub-
   style filter, cards are grouped under a header strip like "Bourbon
   (25)" so a 50+-card list scans visually. */
.spirit-substyle-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  padding: 18px 4px 6px;
  margin: 8px 0 4px;
  border-bottom: 1px solid var(--rule);
}
.spirit-substyle-header:first-child {
  padding-top: 6px;
  margin-top: 0;
}
.spirit-substyle-header-name {
  font-family: var(--serif-display);
  font-size: 18px;
  letter-spacing: 0.2px;
  color: var(--ink-bright);
}
.spirit-substyle-header-count {
  font-family: var(--sans);
  font-size: 10.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

/* v111 — Wave 57: Journal favorites-only toggle.
   Pill button just below the search bar. Off = ghost, on = filled
   with the active binding's accent. Shows ☆/★ inline so the state
   is unambiguous. */
.journal-fav-toggle {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 14px;
  margin: 0 0 14px;
  background: transparent;
  border: 1px solid var(--rule);
  border-radius: 999px;
  color: var(--ink-dim);
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.04em;
  cursor: pointer;
  transition: background 120ms ease, border-color 120ms ease, color 120ms ease;
}
.journal-fav-toggle:hover {
  border-color: var(--accent);
  color: var(--ink);
}
.journal-fav-toggle.is-on {
  background: color-mix(in srgb, var(--accent) 15%, transparent);
  border-color: var(--accent);
  color: var(--accent);
}
.journal-fav-star {
  font-size: 14px;
  line-height: 1;
}

/* v111 — Wave 56: Empty Journal starter templates.
   Editorial empty state — eyebrow, title, body, then a card grid of
   three "Adopt" starters. Each card is a tappable button that opens
   the journal edit sheet pre-populated with the starter spec.
   ----------------------------------------------------------------- */
.journal-empty-starters {
  padding: 24px 4px 12px;
  text-align: left;
}
.journal-empty-eyebrow {
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: 8px;
}
.journal-empty-title {
  font-family: var(--serif-display);
  font-size: 28px;
  color: var(--ink-bright);
  margin: 0 0 12px;
  line-height: 1.15;
  letter-spacing: 0.2px;
}
.journal-empty-body {
  font-family: var(--serif);
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--ink-dim);
  margin: 0 0 24px;
  max-width: 60ch;
}
.journal-empty-blank-link {
  background: transparent;
  border: 0;
  padding: 0;
  font: inherit;
  color: var(--accent);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 2px;
}
.journal-empty-blank-link:hover { color: var(--accent-2); }
.journal-starter-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 12px;
}
@media (min-width: 720px) {
  .journal-starter-grid {
    grid-template-columns: repeat(3, 1fr);
  }
}
.journal-starter-card {
  display: block;
  width: 100%;
  text-align: left;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-left: 3px solid var(--accent);
  border-radius: 0 8px 8px 0;
  padding: 14px 16px;
  cursor: pointer;
  transition: border-color 0.12s ease, box-shadow 0.15s ease, transform 0.05s ease;
  font-family: inherit;
}
.journal-starter-card:hover {
  border-color: var(--accent);
  box-shadow: 0 4px 14px color-mix(in srgb, var(--accent) 18%, transparent);
}
.journal-starter-card:active { transform: translateY(1px); }
.journal-starter-card-title {
  font-family: var(--serif-display);
  font-size: 17px;
  color: var(--ink-bright);
  margin-bottom: 3px;
  letter-spacing: 0.15px;
}
.journal-starter-card-meta {
  font-family: var(--sans);
  /* v616 — Core reading surface: journal starter-card meta row was
     10.5px in --ink-faint. Raised to the 12px floor and promoted to
     --ink-dim for this reading-critical card metadata. */
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-dim);
  margin-bottom: 8px;
}
.journal-starter-card-ings {
  margin: 0 0 10px;
  padding: 0;
  list-style: none;
  font-family: var(--serif);
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--ink-dim);
}
.journal-starter-card-ings li { padding: 1px 0; }
.journal-starter-card-cta {
  font-family: var(--sans);
  font-size: 12.5px;
  font-weight: 600;
  /* v320 — Casing sweep: starter-card CTA reads as a button role,
     Title Case. */
  letter-spacing: 0.02em;
  color: var(--accent);
  text-align: right;
}

/* v111 — Wave 55: fuzzy fallback hint shown above the results list
   when strict AND search returned zero and we softened to a fuzzy
   pass. Italic and accent-tinted so it reads as a system note,
   not a hit count. */
.fuzzy-fallback-hint {
  background: color-mix(in srgb, var(--accent) 8%, var(--surface));
  border-left: 3px solid var(--accent);
  padding: 8px 14px;
  margin: 6px 0 10px;
  font-family: var(--serif-italic);
  font-style: italic;
  font-size: 13px;
  color: var(--ink-dim);
  border-radius: 0 6px 6px 0;
}

/* ============================================================
   SETTINGS
   ============================================================ */
.settings-group {
  background: transparent;
  border: 0;
  border-top: var(--hairline) solid var(--rule);
  border-bottom: var(--hairline) solid var(--rule);
  margin-bottom: 22px;
}
.settings-row {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 4px;
  border-bottom: var(--hairline) solid var(--rule);
  cursor: pointer;
  transition: background .12s, padding .15s;
}
.settings-row:last-child { border-bottom: 0; }
.settings-row:hover {
  background: rgba(199, 156, 79, 0.04);
  padding-left: 10px;
}
.settings-row .label {
  font-size: 15px;
  font-family: var(--serif);
}
.settings-row .value {
  font-size: 13px; color: var(--ink-dim);
  letter-spacing: 0.04em;
}
.settings-row .arrow {
  color: var(--accent); font-size: 18px;
}

.score-label {
  font-size: 11px; color: var(--ink-faint);
  margin-top: 4px; font-style: italic;
}

.confirm-text {
  font-size: 15px; color: var(--ink);
  padding: 8px 0 18px;
  line-height: 1.6;
  font-family: var(--serif);
}
.confirm-text strong { color: var(--accent-2); font-style: italic; }

/* ============================================================
   FLAVOR PAIRINGS (Create view)
   ============================================================ */
.pairing-list {
  list-style: none; padding: 0; margin: 0;
  display: flex; flex-direction: column;
  gap: 14px;
}
.pairing-row {
  border-left: 3px solid var(--accent);
  padding: 8px 0 8px 14px;
  background: transparent;
}
.pairing-list-tension .pairing-row {
  border-left-color: var(--maraschino);
}
.pairing-with {
  font-size: 14px;
  color: var(--ink);
  font-family: var(--serif); font-weight: 500;
  letter-spacing: 0.005em;
  margin-bottom: 3px;
}
.pairing-note {
  font-size: 13px;
  color: var(--ink-dim);
  line-height: 1.5;
  font-style: italic;
}

.view-intro { margin: 0; }

/* ============================================================
   ORNAMENTAL DIVIDERS — SVG flourish utility class
   Use as <div class="flourish"></div> wherever a section break feels right.
   ============================================================ */
.flourish {
  display: flex; align-items: center; justify-content: center;
  margin: 22px 0;
  color: var(--accent);
  font-family: var(--serif);
  font-size: 14px;
  letter-spacing: 0.4em;
  opacity: 0.7;
}
.flourish::before,
.flourish::after {
  content: "";
  flex: 1;
  height: 1px;
  background: linear-gradient(to right, transparent, var(--rule-faint), transparent);
  margin: 0 12px;
}
.flourish::before { background: linear-gradient(to right, transparent, var(--rule-faint)); }
.flourish::after { background: linear-gradient(to left,  transparent, var(--rule-faint)); }

/* ============================================================
   FIELD SECTION HEADER (Tasting block in Journal edit form)
   ============================================================ */
.field-section-header {
  font-family: var(--serif); font-style: italic;
  font-size: 14px !important;
  color: var(--accent) !important;
  text-transform: none !important;
  letter-spacing: 0.02em !important;
  border-top: var(--hairline) solid var(--rule-strong) !important;
  padding: 22px 0 6px !important;
  margin-top: 14px !important;
}


/* ============================================================================
   v53 — Messaging tab + Q&A board + connection points
   ============================================================================ */

/* Notification badge — used by both the top tab and bottom tab pip */
.notif-badge {
  display: none;
  position: absolute;
  top: 4px;
  right: 4px;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: 8px;
  background: var(--accent);
  color: var(--on-accent);
  font-size: 10px;
  line-height: 16px;
  text-align: center;
  font-weight: 600;
}
.notif-badge.on { display: inline-block; }
.tab { position: relative; }
.bottom-tab { position: relative; }

/* Board / Q&A list */
.board-search {
  width: 100%;
  margin-bottom: 12px;
}
.board-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 4px 0 12px;
}
.board-tag-chip {
  background: transparent;
  border: 1px solid var(--rule);
  color: var(--ink-dim);
  font-size: 12px;
  padding: 4px 10px;
  border-radius: 12px;
  cursor: pointer;
  font-family: inherit;
}
.board-tag-chip.on {
  background: var(--accent);
  color: var(--on-accent);
  border-color: var(--accent);
}
.board-new-btn {
  display: block;
  width: 100%;
  padding: 12px;
  margin: 4px 0 16px;
  background: transparent;
  border: 1px dashed var(--rule);
  color: var(--ink-dim);
  font-family: inherit;
  font-size: 14px;
  border-radius: 6px;
  cursor: pointer;
}
.board-new-btn:hover { color: var(--ink); border-color: var(--ink-faint); }
.board-list { display: flex; flex-direction: column; gap: 1px; }
.board-row {
  display: block;
  width: 100%;
  text-align: left;
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--rule);
  padding: 12px 4px;
  cursor: pointer;
  font-family: inherit;
  color: inherit;
}
.board-row:hover { background: rgba(255,255,255,0.02); }
.board-row-title {
  font-size: 15px;
  font-weight: 500;
  color: var(--ink);
  margin-bottom: 4px;
  line-height: 1.35;
}
.board-row-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  font-size: 12px;
  color: var(--ink-faint);
}
.board-row-dot { color: var(--ink-faint); }
.board-row-author { color: var(--ink-dim); }
.board-row-tags { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 6px; }
.board-row-tag {
  font-size: 11px;
  color: var(--accent);
  background: rgba(216, 73, 43, 0.08);
  padding: 2px 7px;
  border-radius: 8px;
}

/* Board / Q&A detail */
.board-back { margin-bottom: 8px; }
.board-detail-head { margin-bottom: 16px; }
.board-detail-title {
  font-size: 22px;
  font-family: var(--serif-display);
  margin: 4px 0 8px;
  line-height: 1.2;
}
.board-detail-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  font-size: 12px;
  color: var(--ink-faint);
  margin-bottom: 8px;
}
.board-detail-body {
  font-size: 14px;
  color: var(--ink-dim);
  line-height: 1.5;
  margin-top: 10px;
  white-space: pre-wrap;
}
.board-related-pill {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-top: 8px;
  background: rgba(216, 73, 43, 0.10);
  border: 1px solid rgba(216, 73, 43, 0.35);
  color: var(--accent);
  font-size: 12px;
  padding: 4px 10px;
  border-radius: 12px;
  cursor: pointer;
  font-family: inherit;
}
.board-related-pill:hover {
  background: rgba(216, 73, 43, 0.18);
}
.board-answers-h {
  font-size: 13px;
  color: var(--ink-dim);
  font-weight: 500;
  margin: 18px 0 8px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.board-answers { display: flex; flex-direction: column; gap: 10px; margin-bottom: 16px; }
.board-answer {
  padding: 10px 12px;
  background: rgba(255,255,255,0.02);
  border-radius: 6px;
}
.board-answer-reply {
  margin-left: 24px;
  border-left: 2px solid var(--rule);
}
.board-composer {
  border-top: 1px solid var(--rule);
  padding-top: 12px;
  margin-top: 8px;
}

/* Notifications row (used by both bell sheet and Activity sub-tab) */
.notif-row {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: 10px;
  align-items: baseline;
  padding: 12px 4px;
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--rule);
  text-align: left;
  cursor: pointer;
  font-family: inherit;
  color: inherit;
  width: 100%;
}
.notif-row:hover { background: rgba(255,255,255,0.02); }
.notif-row-kind {
  font-size: 10px;
  letter-spacing: 0.08em;
  color: var(--ink-faint);
  text-transform: uppercase;
  font-weight: 600;
}
.notif-row-body {
  font-size: 14px;
  color: var(--ink-dim);
  line-height: 1.4;
}
.notif-row-when { font-size: 11px; color: var(--ink-faint); white-space: nowrap; }
.notif-row.unseen .notif-row-kind { color: var(--accent); }
.notif-row.unseen .notif-row-body { color: var(--ink); }
.notif-list { display: flex; flex-direction: column; }

/* Messaging tab (Discussions + Activity sub-tabs) */
.messaging-body { display: flex; flex-direction: column; gap: 0; }
.messaging-activity-actions {
  display: flex;
  gap: 8px;
  margin-bottom: 8px;
}
.messaging-activity-list { display: flex; flex-direction: column; }
.messaging-discussion-list { display: flex; flex-direction: column; }
.messaging-discussion-row {
  display: block;
  width: 100%;
  text-align: left;
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--rule);
  padding: 14px 4px;
  cursor: pointer;
  font-family: inherit;
  color: inherit;
}
.messaging-discussion-row:hover { background: rgba(255,255,255,0.02); }
.messaging-discussion-target {
  font-size: 15px;
  font-family: var(--serif-display);
  font-weight: 500;
  color: var(--ink);
  margin-bottom: 4px;
}
.messaging-discussion-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  font-size: 12px;
  color: var(--ink-faint);
  margin-bottom: 6px;
}
.messaging-discussion-dot { color: var(--ink-faint); }
.messaging-discussion-count { color: var(--ink-dim); }
.messaging-discussion-preview {
  font-size: 13px;
  color: var(--ink-dim);
  line-height: 1.45;
}

/* Cocktail Discussion → "On the board" subsection */
.comments-related-board {
  margin-top: 16px;
  padding-top: 12px;
  border-top: 1px dashed var(--rule);
}
.comments-related-board-h {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: 8px;
  font-weight: 600;
}
.comments-related-board-ask {
  font-size: 11px;
  letter-spacing: 0;
  text-transform: none;
  font-weight: 500;
}
.comments-related-board-list {
  display: flex;
  flex-direction: column;
  list-style: none;
  padding: 0;
  margin: 0;
  gap: 1px;
}
.comments-related-board-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  width: 100%;
  text-align: left;
  background: transparent;
  border: 0;
  padding: 8px 4px;
  cursor: pointer;
  font-family: inherit;
  color: inherit;
  border-bottom: 1px solid var(--rule);
  gap: 8px;
}
.comments-related-board-row:hover { background: rgba(255,255,255,0.02); }
.comments-related-board-title {
  font-size: 13px;
  color: var(--ink);
  flex: 1;
  line-height: 1.4;
}
.comments-related-board-meta {
  font-size: 11px;
  color: var(--ink-faint);
  white-space: nowrap;
}
.comments-related-board-empty {
  font-size: 12px;
  color: var(--ink-faint);
  font-style: italic;
  padding: 6px 0;
}

/* Reference tab body — sub-tabs already styled by .sub-tabs */
.reference-body { display: flex; flex-direction: column; }

/* tab-icon: shrink the icon-only header tabs (legacy, used pre-v53). */
.tab-icon {
  padding: 8px 10px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* ============================================================================
   v53 — quick-win polish (paywall honesty, prep for visible favorite star)
   ============================================================================ */
.paywall-tier-cta-soon {
  background: transparent !important;
  border: 1px dashed var(--rule) !important;
  color: var(--ink-faint) !important;
  cursor: not-allowed;
}
.paywall-tier-cta-soon:hover { background: transparent !important; }


/* v54 — inline profile in comments composer */
.comments-inline-profile {
  background: rgba(255, 255, 255, 0.02);
  border: 1px solid var(--rule);
  border-radius: 6px;
  padding: 10px;
  margin-bottom: 10px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.comments-inline-profile-h {
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: 2px;
}

/* ============================================================================
   v54 — Friends + Collabs (Messaging tab)
   ============================================================================ */

/* "You" row at top of Friends sub-tab */
.friends-me {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px;
  background: rgba(216, 73, 43, 0.06);
  border: 1px solid rgba(216, 73, 43, 0.18);
  border-radius: 8px;
  margin-bottom: 12px;
}
.friends-me-mark {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--on-accent);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 600;
  font-size: 14px;
  flex-shrink: 0;
}
.friends-me-body { flex: 1; }
.friends-me-name {
  font-size: 14px;
  color: var(--ink);
  font-weight: 500;
}
.friends-me-venue {
  font-size: 12px;
  color: var(--ink-faint);
  margin-top: 2px;
}

.friends-add-btn {
  display: block;
  width: 100%;
  margin-bottom: 16px;
}

.friends-list {
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.friend-row {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: 12px;
  padding: 12px 4px;
  border-bottom: 1px solid var(--rule);
  align-items: center;
}
.friend-row.pinned {
  background: rgba(216, 73, 43, 0.04);
}
.friend-mark {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.06);
  color: var(--ink);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 600;
  font-size: 13px;
}
.friend-name {
  font-size: 14px;
  color: var(--ink);
  font-weight: 500;
  display: flex;
  align-items: center;
  gap: 6px;
}
.friend-pin {
  color: var(--accent);
  font-size: 11px;
}
.friend-venue {
  font-size: 12px;
  color: var(--ink-dim);
  margin-top: 2px;
}
.friend-notes {
  font-size: 12px;
  color: var(--ink-faint);
  font-style: italic;
  margin-top: 4px;
}
.friend-meta {
  font-size: 11px;
  color: var(--ink-faint);
  margin-top: 4px;
}
.friend-actions {
  display: flex;
  gap: 4px;
}
.icon-btn {
  background: transparent;
  border: 1px solid var(--rule);
  color: var(--ink-dim);
  width: 32px;
  height: 32px;
  border-radius: 4px;
  cursor: pointer;
  font-family: inherit;
  font-size: 13px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.icon-btn:hover {
  color: var(--ink);
  background: rgba(255, 255, 255, 0.04);
}

/* Collabs list */
.collab-new-btn {
  display: block;
  width: 100%;
  margin-bottom: 16px;
}
.collab-list { display: flex; flex-direction: column; }
.collab-row {
  display: block;
  width: 100%;
  text-align: left;
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--rule);
  padding: 14px 4px;
  cursor: pointer;
  font-family: inherit;
  color: inherit;
}
.collab-row:hover { background: rgba(255, 255, 255, 0.02); }
.collab-row-title {
  font-size: 15px;
  font-family: var(--serif-display);
  font-weight: 500;
  color: var(--ink);
  margin-bottom: 4px;
}
.collab-row-meta {
  font-size: 12px;
  color: var(--ink-faint);
  margin-bottom: 6px;
}
.collab-row-preview {
  font-size: 13px;
  color: var(--ink-dim);
  line-height: 1.45;
}

/* Collab detail */
.collab-back { margin-bottom: 8px; }
.collab-head { margin-bottom: 16px; }
.collab-title {
  font-size: 22px;
  font-family: var(--serif-display);
  margin: 4px 0 6px;
  line-height: 1.2;
}
.collab-friends {
  font-size: 12px;
  color: var(--ink-faint);
  margin-bottom: 8px;
}
.collab-actions {
  display: flex;
  gap: 8px;
}
.collab-items {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 16px;
}
.collab-item {
  background: rgba(255, 255, 255, 0.02);
  border-radius: 8px;
  padding: 10px 12px;
  position: relative;
}
.collab-item.mine {
  background: rgba(216, 73, 43, 0.06);
  border: 1px solid rgba(216, 73, 43, 0.18);
}
.collab-item-byline {
  font-size: 11px;
  color: var(--ink-faint);
  margin-bottom: 6px;
}
.collab-item-when { color: var(--ink-faint); }
.collab-item-ref {
  display: inline-block;
  background: transparent;
  border: 1px solid var(--rule);
  color: var(--ink);
  padding: 6px 10px;
  border-radius: 4px;
  font-family: inherit;
  font-size: 13px;
  cursor: pointer;
  margin-bottom: 6px;
}
.collab-item-ref:hover {
  background: rgba(255, 255, 255, 0.04);
}
.collab-item-body {
  font-size: 14px;
  color: var(--ink-dim);
  line-height: 1.5;
  white-space: pre-wrap;
}
.collab-item-delete {
  position: absolute;
  top: 8px;
  right: 8px;
  background: transparent;
  border: 0;
  color: var(--ink-faint);
  font-size: 11px;
  cursor: pointer;
  font-family: inherit;
}
.collab-item-delete:hover { color: var(--red); }

.collab-composer {
  border-top: 1px solid var(--rule);
  padding-top: 12px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.collab-composer-textarea { width: 100%; }

/* Friend picker tiles in new-collab sheet */
.collab-friends-picker,
.share-chooser-friend-list {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 4px;
}
.friend-pick-tile,
.share-chooser-friend-tile {
  background: transparent;
  border: 1px solid var(--rule);
  color: var(--ink-dim);
  padding: 8px 12px;
  border-radius: 20px;
  font-family: inherit;
  font-size: 13px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.friend-pick-tile.on,
.share-chooser-friend-tile.on {
  background: var(--accent);
  color: var(--on-accent);
  border-color: var(--accent);
}
.friend-pick-mark {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: rgba(255,255,255,0.1);
  color: inherit;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  font-weight: 600;
}

/* Share chooser sheet (cocktail detail → share) */
.share-chooser-btn {
  width: 100%;
  margin-bottom: 12px;
}
.share-chooser-section-h {
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin: 12px 0 6px;
  font-weight: 600;
}
.share-chooser-collab-list { display: flex; flex-direction: column; gap: 1px; }
.share-chooser-collab-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
  text-align: left;
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--rule);
  padding: 10px 4px;
  cursor: pointer;
  font-family: inherit;
  color: inherit;
}
.share-chooser-collab-row:hover {
  background: rgba(255, 255, 255, 0.02);
}
.share-chooser-collab-title {
  font-size: 14px;
  color: var(--ink);
}
.share-chooser-collab-meta {
  font-size: 11px;
  color: var(--ink-faint);
}

/* ============================================================================
   v54 design coherence pass — strengthen contrast and weight on the
   v53/v54 surfaces (Messaging, Friends, Collabs, Board, Activity, share-
   chooser, related-board card). The Tiki Sunset palette has deep teal as
   the canvas; rgba(255,255,255,0.02) row backgrounds were nearly invisible
   against #122a3a. These overrides nudge rows toward a more solid surface,
   bump small-text font weight, and tighten border definition so the UI
   reads coherent rather than washed-out.
   ============================================================================ */

/* Card / row backgrounds: lift from 2% white to a solid surface tone */
.board-row,
.notif-row,
.messaging-discussion-row,
.collab-row,
.collab-item,
.share-chooser-collab-row,
.comments-related-board-row,
.friend-row {
  background: rgba(255, 255, 255, 0.04);
}
.board-row:hover,
.notif-row:hover,
.messaging-discussion-row:hover,
.collab-row:hover,
.share-chooser-collab-row:hover,
.comments-related-board-row:hover {
  background: rgba(255, 255, 255, 0.07);
}

/* Borders: bump the v53/v54 hairlines to use the stronger rule tone so
   sections and rows have clear edges on the deep teal canvas. */
.board-row,
.notif-row,
.messaging-discussion-row,
.collab-row,
.share-chooser-collab-row,
.comments-related-board-row,
.friend-row,
.messaging-activity-list,
.notif-list,
.board-list,
.collab-list {
  border-color: var(--rule-strong);
}

/* Section headers (small caps eyebrows): bump weight + brightness */
.comments-related-board-h,
.share-chooser-section-h,
.comments-inline-profile-h,
.board-answers-h {
  color: var(--ink-dim);
  font-weight: 700;
}

/* Meta text was using --ink-faint at 11px — too thin on a saturated bg.
   Push to 12px and bump from faint to dim where the text matters. */
.board-row-meta,
.collab-row-meta,
.messaging-discussion-meta,
.notif-row-when,
.friend-meta,
.collab-item-when,
.collab-item-byline {
  font-size: 12px;
  color: var(--ink-dim);
}

/* Body text on rows: was --ink at 13px. Bump to 14px so cards feel
   substantial rather than caption-y. */
.board-row-title,
.collab-row-title,
.messaging-discussion-target,
.collab-title,
.friends-me-name,
.friend-name {
  font-size: 16px;
  font-weight: 500;
  color: var(--ink);
}

/* Preview lines should be readable — bump to ink-dim from ink-faint */
.collab-row-preview,
.messaging-discussion-preview,
.board-detail-body,
.notif-row-body,
.friend-notes,
.collab-item-body {
  color: var(--ink-dim);
  font-size: 13.5px;
  line-height: 1.5;
}

/* Notification UNSEEN rows: stronger highlight */
.notif-row.unseen {
  background: rgba(255, 140, 90, 0.10);
  border-left: 3px solid var(--accent);
  padding-left: 10px;
}
.notif-row.unseen .notif-row-kind { color: var(--accent); font-weight: 700; }
.notif-row.unseen .notif-row-body { color: var(--ink); font-weight: 500; }

/* Pinned friend: more obvious accent band on the left */
.friend-row.pinned {
  background: rgba(255, 140, 90, 0.08);
  border-left: 3px solid var(--accent);
  padding-left: 10px;
}

/* Tag chips: more solid, less ghost-y */
.board-tag-chip {
  background: rgba(255, 255, 255, 0.04);
  color: var(--ink-dim);
  font-weight: 500;
}
.board-tag-chip.on {
  background: var(--accent);
  color: var(--on-accent);
  font-weight: 600;
}
.board-row-tag {
  background: rgba(255, 140, 90, 0.14);
  color: var(--accent-2);
  font-weight: 600;
}

/* Related-cocktail pill on board question — make it read like an action */
.board-related-pill {
  background: rgba(255, 140, 90, 0.14);
  color: var(--accent-2);
  border: 1px solid rgba(255, 140, 90, 0.45);
  font-weight: 600;
  padding: 6px 12px;
}
.board-related-pill:hover {
  background: rgba(255, 140, 90, 0.22);
}

/* Icon buttons (pin / edit / +) on friend rows — more visible default */
.icon-btn {
  background: rgba(255, 255, 255, 0.04);
  color: var(--ink);
  border-color: var(--rule-strong);
  font-size: 14px;
  font-weight: 500;
}
.icon-btn:hover {
  background: rgba(255, 140, 90, 0.18);
  border-color: var(--accent);
  color: var(--ink-bright);
}

/* The ghost "Coming soon" paywall buttons inherit a slightly more visible
   dashed style under Tiki palette */
.paywall-tier-cta-soon {
  border-color: var(--rule-strong) !important;
  color: var(--ink-dim) !important;
  font-weight: 500;
}

/* Inline profile composer: tighter edges + correct accent color */
.comments-inline-profile {
  background: rgba(255, 140, 90, 0.06);
  border-color: rgba(255, 140, 90, 0.25);
}

/* Share-chooser primary CTA: full-width accent fill, not ghost */
.share-chooser-btn {
  background: var(--accent);
  color: var(--on-accent);
  border-color: var(--accent);
  font-weight: 600;
}
.share-chooser-btn:hover {
  background: var(--accent-2);
  border-color: var(--accent-2);
}

/* Messaging top-tab badge + bottom-tab badge: the v53 badge sat at top:4 right:4
   which collided with text in the slim Messaging tab. Re-anchor inline. */
#messaging-tab-badge {
  position: static;
  display: none;
  margin-left: 6px;
  vertical-align: middle;
  background: var(--accent);
  font-size: 10px;
  line-height: 16px;
  font-weight: 700;
  color: var(--on-accent);
}
#messaging-tab-badge.on { display: inline-block; }
#messaging-bottom-badge {
  background: var(--accent);
  color: var(--on-accent);
  font-weight: 700;
}

.collab-header-actions {
  display: flex;
  gap: 8px;
  align-items: center;
  margin-bottom: 16px;
}
.collab-header-actions .collab-new-btn { flex: 1; margin-bottom: 0; }

/* v54 — visible favorite star on cocktail cards. Sits absolutely in the
   top-right corner so it doesn't reflow the title row. */
.cocktail-card { position: relative; }
.card-star {
  position: absolute;
  top: 8px;
  right: 8px;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  /* v320 — themed scrim (was hardcoded rgba(0,0,0,0.32) which made
     the favorite-star button look like a tiny dark sticker on a
     sand-cream Library card). --scrim-soft adapts per theme. */
  background: var(--scrim-soft);
  border: 1px solid rgba(255, 255, 255, 0.12);
  color: var(--ink-dim);
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: inherit;
  z-index: 2;
  transition: transform 120ms ease, background 120ms ease, color 120ms ease;
}
.card-star:hover {
  background: rgba(0, 0, 0, 0.55);
  color: var(--ink);
  transform: scale(1.06);
}
.card-star.on {
  background: var(--accent);
  color: var(--on-accent);
  border-color: var(--accent);
}
.card-star.on:hover {
  background: var(--accent-2);
  border-color: var(--accent-2);
}

/* ============================================================================
   v54 — House cocktails (venue-tagged user uploads)
   ============================================================================ */
.house-venue-switcher {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 16px;
}
.house-venue-pill {
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--rule-strong);
  color: var(--ink-dim);
  font-family: inherit;
  font-size: 13px;
  font-weight: 500;
  padding: 8px 14px;
  border-radius: 20px;
  cursor: pointer;
}
.house-venue-pill:hover {
  background: rgba(255, 140, 90, 0.08);
  color: var(--ink);
}
.house-venue-pill.on {
  background: var(--accent);
  color: var(--on-accent);
  border-color: var(--accent);
  font-weight: 600;
}
.house-venue-pill-add {
  background: transparent;
  border-style: dashed;
}
/* "All venues" pill — italic editorial face that sits left of the bar
   names. Uses the same accent treatment when active so the whole strip
   reads as one switcher, not two. */
.house-venue-pill-all {
  font-family: var(--serif-italic);
  font-style: italic;
  letter-spacing: 0.01em;
}

/* Venue tag chip on cocktail cards in the All-venues view — small,
   uppercase, hairline. Marks which bar each cocktail belongs to. */
.house-cocktail-venue-tag {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--accent);
  border: 1px solid var(--rule-strong);
  border-radius: 10px;
  padding: 2px 8px;
  white-space: nowrap;
}

.house-body { display: flex; flex-direction: column; }
.house-venue-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 12px;
}
.house-venue-name {
  font-size: 24px;
  font-family: var(--serif-display);
  margin: 0 0 4px 0;
  line-height: 1.15;
  color: var(--ink);
}
.house-venue-meta {
  font-size: 13px;
  color: var(--ink-dim);
}

.house-actions {
  display: flex;
  gap: 8px;
  align-items: center;
  margin-bottom: 12px;
}
.house-actions .btn:first-child { flex: 1; }
.house-search { width: 100%; margin-bottom: 12px; }
.house-list-wrap { display: flex; flex-direction: column; gap: 1px; }

.house-cocktail-list { display: flex; flex-direction: column; gap: 1px; }
.house-cocktail-card {
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--rule-strong);
  border-radius: 6px;
  padding: 12px;
  cursor: pointer;
  margin-bottom: 8px;
}
.house-cocktail-card:hover {
  background: rgba(255, 140, 90, 0.06);
  border-color: var(--accent);
}
.house-cocktail-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 6px;
}
.house-cocktail-name {
  font-size: 16px;
  font-weight: 500;
  color: var(--ink);
}
.house-cocktail-glass {
  font-size: 11px;
  color: var(--ink-faint);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.house-cocktail-ings {
  font-size: 13px;
  color: var(--ink-dim);
  font-style: italic;
  margin-bottom: 4px;
}
.house-cocktail-notes {
  font-size: 12px;
  color: var(--ink-dim);
  line-height: 1.45;
  margin-top: 4px;
}
.house-cocktail-meta {
  font-size: 11px;
  color: var(--ink-faint);
  margin-top: 6px;
}

/* Ingredient editor rows in the house cocktail sheet */
.house-ing-rows {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.house-ing-row {
  display: grid;
  grid-template-columns: 56px 56px 1fr 32px;
  gap: 6px;
  align-items: center;
}
.house-ing-amt,
.house-ing-unit,
.house-ing-name { font-size: 13px; }
.field-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}

/* ============================================================================
   v54 — Tonight's Notes (shift handoff scratchpad) + spec-import sheet
   ============================================================================ */

/* Shift notes — running scratchpad UI */
.shiftnote-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  margin-bottom: 8px;
}
.shiftnote-eyebrow {
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--accent);
  font-weight: 700;
  margin-bottom: 2px;
}
.shiftnote-date {
  font-size: 18px;
  font-family: var(--serif-display);
  color: var(--ink);
}
.shiftnote-textarea {
  width: 100%;
  font-family: var(--mono);
  font-size: 13.5px;
  line-height: 1.6;
  background: rgba(255, 248, 232, 0.04);
  border: 1px solid var(--rule-strong);
  color: var(--ink);
  padding: 14px;
  border-radius: 6px;
  margin-bottom: 6px;
  resize: vertical;
  min-height: 180px;
}
.shiftnote-textarea::placeholder {
  color: var(--ink-faint);
  white-space: pre-line;
}
.shiftnote-saved-stamp {
  font-size: 11px;
  color: var(--accent);
  text-align: right;
  height: 14px;
  font-style: italic;
  opacity: 0;
  transition: opacity 200ms ease;
  margin-bottom: 8px;
}
.shiftnote-saved-stamp.on { opacity: 1; }

.shiftnote-chiprow {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 20px;
}
.shiftnote-chip {
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--rule-strong);
  color: var(--ink-dim);
  font-family: inherit;
  font-size: 12px;
  font-weight: 500;
  padding: 6px 10px;
  border-radius: 14px;
  cursor: pointer;
}
.shiftnote-chip:hover {
  background: rgba(255, 140, 90, 0.10);
  color: var(--ink);
  border-color: var(--accent);
}

.shiftnote-past-h {
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-faint);
  font-weight: 700;
  margin-bottom: 8px;
}
.shiftnote-past-list { display: flex; flex-direction: column; gap: 1px; }
.shiftnote-past-row {
  display: block;
  width: 100%;
  text-align: left;
  background: rgba(255, 255, 255, 0.04);
  border: 0;
  border-bottom: 1px solid var(--rule-strong);
  padding: 12px 4px;
  cursor: pointer;
  font-family: inherit;
  color: inherit;
}
.shiftnote-past-row:hover {
  background: rgba(255, 255, 255, 0.07);
}
.shiftnote-past-date {
  font-size: 13px;
  font-weight: 500;
  color: var(--ink);
  margin-bottom: 4px;
}
.shiftnote-past-preview {
  font-size: 12px;
  color: var(--ink-dim);
  line-height: 1.45;
  white-space: pre-wrap;
}

/* House view-switcher — same look as messaging sub-tabs */
.house-view-switcher { margin-top: -4px; margin-bottom: 16px; }

/* Spec-import sheet — single-spec import options */
.spec-import-section-h {
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-faint);
  font-weight: 700;
  margin-bottom: 8px;
}
.spec-import-options { display: flex; flex-direction: column; gap: 6px; }
.spec-import-option {
  display: block;
  width: 100%;
  text-align: left;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--rule-strong);
  color: var(--ink);
  padding: 12px 14px;
  border-radius: 6px;
  font-family: inherit;
  cursor: pointer;
}
.spec-import-option:hover {
  background: rgba(255, 140, 90, 0.08);
  border-color: var(--accent);
}
.spec-import-option-title {
  font-size: 14px;
  font-weight: 500;
  color: var(--ink);
  margin-bottom: 2px;
}
.spec-import-option-meta {
  font-size: 12px;
  color: var(--ink-dim);
}

/* ============================================================================
   v54 — Create rebuild (Riff / Structure / Pairings) styles
   ============================================================================ */
.create-body { display: flex; flex-direction: column; gap: 12px; }
.create-mode-h { margin-bottom: 12px; }
.create-mode-h h2 {
  font-size: 22px;
  font-family: var(--serif-display);
  margin: 0 0 4px 0;
  line-height: 1.2;
}
.create-mode-h p {
  font-size: 13px;
  color: var(--ink-dim);
  font-style: italic;
  font-family: var(--serif-italic);
  margin: 0;
  line-height: 1.45;
}

/* Drafts list at the bottom of either picker */
.create-drafts-h {
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-faint);
  font-weight: 700;
  margin: 16px 0 6px;
}
.create-drafts-list { display: flex; flex-direction: column; }
.create-draft-row {
  display: block;
  width: 100%;
  text-align: left;
  background: rgba(255,255,255,0.04);
  border: 0;
  border-bottom: 1px solid var(--rule-strong);
  padding: 10px 6px;
  font-family: inherit;
  cursor: pointer;
  color: inherit;
}
.create-draft-row:hover { background: rgba(255,140,90,0.08); }
.create-draft-name {
  font-size: 14px;
  color: var(--ink);
  font-weight: 500;
  margin-bottom: 2px;
}
.create-draft-meta {
  font-size: 11px;
  color: var(--ink-faint);
}

/* Editor head row (back button + meta) */
.create-editor-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 8px;
}
.create-editor-meta {
  font-size: 12px;
  color: var(--ink-faint);
  font-style: italic;
}
.create-editor-name {
  font-size: 18px;
  font-family: var(--serif-display);
  width: 100%;
}
.create-editor-h {
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-faint);
  font-weight: 700;
  margin: 16px 0 6px;
}

/* Riff picker */
.riff-picker-search { width: 100%; margin-bottom: 8px; }
.riff-quickpicks {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 12px;
}
.riff-quickpick-chip {
  background: rgba(255,255,255,0.04);
  border: 1px solid var(--rule-strong);
  color: var(--ink-dim);
  font-family: inherit;
  font-size: 12px;
  font-weight: 500;
  padding: 6px 12px;
  border-radius: 14px;
  cursor: pointer;
}
.riff-quickpick-chip:hover {
  background: rgba(255,140,90,0.1);
  color: var(--ink);
  border-color: var(--accent);
}

.riff-picker-list { display: flex; flex-direction: column; }
.riff-pick-row {
  display: block;
  width: 100%;
  text-align: left;
  background: rgba(255,255,255,0.04);
  border: 0;
  border-bottom: 1px solid var(--rule-strong);
  padding: 12px 6px;
  cursor: pointer;
  font-family: inherit;
  color: inherit;
}
.riff-pick-row:hover { background: rgba(255,140,90,0.08); }
.riff-pick-name {
  font-size: 15px;
  font-weight: 500;
  color: var(--ink);
  margin-bottom: 4px;
}
.riff-pick-meta {
  font-size: 12px;
  color: var(--ink-dim);
  font-style: italic;
}

/* Riff editor — ingredient swap chips */
.riff-ing-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 12px;
}
.riff-ing-row {
  display: grid;
  grid-template-columns: 70px 1fr 32px;
  gap: 6px;
  align-items: center;
}
.riff-ing-amt {
  font-family: var(--mono);
  font-size: 13px;
  color: var(--ink-dim);
  padding: 8px 6px;
  background: rgba(255,255,255,0.04);
  border-radius: 4px;
  text-align: right;
}
.riff-ing-name-btn {
  background: rgba(255,140,90,0.06);
  border: 1px dashed rgba(255,140,90,0.45);
  color: var(--ink);
  padding: 8px 12px;
  border-radius: 4px;
  font-family: inherit;
  font-size: 14px;
  text-align: left;
  cursor: pointer;
}
.riff-ing-name-btn:hover {
  background: rgba(255,140,90,0.14);
  border-color: var(--accent);
}
.riff-ing-add { margin-top: 4px; }

/* Substitution chips inside the swap sheet */
.riff-swap-subs { margin-top: 12px; }
.riff-sub-chip {
  display: flex;
  flex-direction: column;
  width: 100%;
  text-align: left;
  background: rgba(255,255,255,0.04);
  border: 1px solid var(--rule-strong);
  border-radius: 6px;
  padding: 10px 12px;
  cursor: pointer;
  font-family: inherit;
  margin-bottom: 6px;
  color: inherit;
}
.riff-sub-chip:hover {
  background: rgba(255,140,90,0.08);
  border-color: var(--accent);
}
.riff-sub-name {
  font-size: 13px;
  color: var(--ink);
  font-weight: 500;
  margin-bottom: 2px;
}
.riff-sub-note {
  font-size: 12px;
  color: var(--ink-dim);
  line-height: 1.4;
}

/* Structure mode: template grid */
.structure-template-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 8px;
  margin-bottom: 16px;
}
@media (min-width: 600px) {
  .structure-template-grid { grid-template-columns: 1fr 1fr; }
}
.structure-template-card {
  background: rgba(255,255,255,0.04);
  border: 1px solid var(--rule-strong);
  border-radius: 6px;
  padding: 14px;
  text-align: left;
  cursor: pointer;
  font-family: inherit;
  color: inherit;
}
.structure-template-card:hover {
  background: rgba(255,140,90,0.08);
  border-color: var(--accent);
}
.structure-template-name {
  font-size: 17px;
  font-family: var(--serif-display);
  color: var(--ink);
  margin-bottom: 4px;
}
.structure-template-desc {
  font-size: 12.5px;
  color: var(--ink-dim);
  line-height: 1.4;
  margin-bottom: 6px;
}
.structure-template-slots {
  font-size: 11px;
  color: var(--ink-faint);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* Structure slot rows */
.structure-slot-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 12px;
}
.structure-slot-row {
  display: grid;
  grid-template-columns: minmax(110px, 35%) 1fr;
  gap: 10px;
  align-items: center;
  padding: 10px;
  background: rgba(255,255,255,0.04);
  border-radius: 6px;
}
.structure-slot-label-text {
  font-size: 13px;
  font-weight: 500;
  color: var(--ink);
  margin-bottom: 2px;
}
.structure-slot-hint {
  font-size: 11px;
  color: var(--ink-faint);
  font-style: italic;
  line-height: 1.3;
}
.structure-slot-fields {
  display: grid;
  grid-template-columns: 56px 50px 1fr;
  gap: 6px;
  align-items: center;
}
.structure-slot-amt,
.structure-slot-unit { font-size: 13px; }
.structure-slot-pick {
  background: rgba(255,140,90,0.06);
  border: 1px dashed rgba(255,140,90,0.45);
  color: var(--ink);
  padding: 8px 10px;
  border-radius: 4px;
  font-family: inherit;
  font-size: 13px;
  cursor: pointer;
  text-align: left;
}
.structure-slot-pick:hover {
  background: rgba(255,140,90,0.14);
  border-color: var(--accent);
}
.structure-slot-empty {
  color: var(--ink-faint);
  font-style: italic;
}

/* Slot picker sheet — list of suggestions */
.slot-picker-list {
  display: flex;
  flex-direction: column;
  gap: 1px;
  margin-top: 8px;
  max-height: 320px;
  overflow-y: auto;
}
.slot-picker-row {
  display: block;
  width: 100%;
  text-align: left;
  background: rgba(255,255,255,0.04);
  border: 0;
  border-bottom: 1px solid var(--rule-strong);
  padding: 10px 8px;
  cursor: pointer;
  font-family: inherit;
  font-size: 13px;
  color: var(--ink);
}
.slot-picker-row:hover {
  background: rgba(255,140,90,0.10);
  color: var(--ink-bright);
}

/* Action row at the bottom of any draft editor */
.create-action-row {
  display: flex;
  gap: 8px;
  align-items: center;
  margin-top: 16px;
  padding-top: 12px;
  border-top: 1px solid var(--rule-strong);
}
.create-action-row .btn:first-child { flex: 1; }

/* ============================================================================
   v54 — Cost view upgrade (editable menu price + GP $ + engineering matrix)
   ============================================================================ */

/* Sort row */
.cost-sort-row {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  margin-bottom: 10px;
  font-size: 12px;
}
.cost-sort-label {
  color: var(--ink-faint);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  font-weight: 600;
  font-size: 11px;
  margin-right: 4px;
}
.cost-sort-btn {
  background: rgba(255,255,255,0.04);
  border: 1px solid var(--rule-strong);
  color: var(--ink-dim);
  font-family: inherit;
  font-size: 12px;
  padding: 4px 10px;
  border-radius: 12px;
  cursor: pointer;
}
.cost-sort-btn.on {
  background: var(--accent);
  color: var(--on-accent);
  border-color: var(--accent);
  font-weight: 600;
}

/* Per-drink table */
.cost-table-head,
.cost-table-row {
  display: grid;
  grid-template-columns: 1.7fr 0.7fr 0.9fr 0.6fr 0.7fr 0.7fr;
  gap: 6px;
  align-items: center;
  padding: 6px 4px;
}
.cost-table-head {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--ink-faint);
  font-weight: 700;
  border-bottom: 1px solid var(--rule-strong);
  padding: 8px 4px;
}
.cost-th { text-align: right; }
.cost-th:first-child { text-align: left; }

.cost-table-row {
  border-bottom: 1px solid rgba(255,255,255,0.06);
  font-size: 13px;
}
.cost-row-name {
  color: var(--ink);
  font-weight: 500;
  font-size: 14px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.cost-row-cost {
  text-align: right;
  font-family: var(--mono);
  color: var(--ink-dim);
}
.cost-row-menu {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 2px;
}
.cost-row-menu .cost-currency {
  font-size: 12px;
  color: var(--ink-faint);
  position: absolute;
  left: 6px;
}
.cost-row-price-input {
  width: 100%;
  padding: 4px 4px 4px 14px !important;
  text-align: right;
  font-family: var(--mono);
  font-size: 13px;
}
.cost-row-pourpct {
  text-align: right;
  font-family: var(--mono);
  color: var(--ink-dim);
  font-weight: 500;
}
.cost-row-pourpct.warn { color: var(--maraschino); font-weight: 700; }
.cost-row-pourpct.good { color: var(--bottle-2); font-weight: 700; }
.cost-row-gp {
  text-align: right;
  font-family: var(--mono);
  color: var(--ink);
  font-weight: 600;
}
.cost-row-velocity {
  display: flex;
  justify-content: flex-end;
}
.cost-row-vel-input {
  width: 100%;
  padding: 4px 6px !important;
  text-align: right;
  font-family: var(--mono);
  font-size: 13px;
}

/* Summary stats — accent variant for weekly GP */
.cost-summary-stat-accent .cost-summary-num { color: var(--accent); }

/* Engineering matrix */
.cost-eng-summary {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 8px;
  margin-bottom: 12px;
}
.cost-eng-stat {
  background: rgba(255,255,255,0.04);
  border: 1px solid var(--rule-strong);
  border-radius: 6px;
  padding: 10px;
  text-align: center;
}
.cost-eng-stat-accent { border-color: var(--accent); }
.cost-eng-stat-accent .cost-eng-num { color: var(--accent); }
.cost-eng-num {
  font-family: var(--serif-display);
  font-size: 22px;
  color: var(--ink);
  margin-bottom: 2px;
}
.cost-eng-label {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--ink-faint);
}

.cost-eng-matrix {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}
@media (max-width: 600px) {
  .cost-eng-matrix { grid-template-columns: 1fr; }
}
.cost-eng-bucket {
  background: rgba(255,255,255,0.04);
  border: 1px solid var(--rule-strong);
  border-radius: 8px;
  padding: 12px;
}
.cost-eng-bucket-h {
  font-size: 14px;
  font-weight: 700;
  color: var(--ink);
  margin-bottom: 4px;
}
.cost-eng-bucket-advice {
  font-size: 11px;
  color: var(--ink-faint);
  font-style: italic;
  line-height: 1.4;
  margin-bottom: 8px;
}
.cost-eng-bucket-empty {
  font-size: 12px;
  color: var(--ink-faint);
  font-style: italic;
}
.cost-eng-bucket-list {
  list-style: none;
  padding: 0;
  margin: 0;
}
.cost-eng-bucket-list li {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding: 4px 0;
  font-size: 12.5px;
  border-bottom: 1px solid rgba(255,255,255,0.06);
}
.cost-eng-bucket-list li:last-child { border-bottom: 0; }
.cost-eng-bucket-name { color: var(--ink); }
.cost-eng-bucket-meta {
  color: var(--ink-faint);
  font-family: var(--mono);
  font-size: 11px;
}

/* Settings */
.cost-settings-block {
  background: rgba(255,255,255,0.04);
  border: 1px solid var(--rule-strong);
  border-radius: 8px;
  padding: 14px;
  margin-bottom: 12px;
}
.cost-settings-label {
  font-size: 14px;
  font-weight: 600;
  color: var(--ink);
  margin-bottom: 4px;
}
.cost-settings-hint {
  font-size: 12px;
  color: var(--ink-dim);
  line-height: 1.45;
  margin-bottom: 10px;
}
.cost-settings-input-wrap {
  display: flex;
  align-items: center;
  gap: 6px;
  max-width: 140px;
}
.cost-settings-input { flex: 1; font-family: var(--mono); }
.cost-settings-suffix {
  color: var(--ink-faint);
  font-family: var(--mono);
  font-size: 14px;
}

/* ============================================================================
   v54 — Allergen flags: cocktail detail badges
   ============================================================================ */
.detail-allergens {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  margin-bottom: 12px;
  padding: 8px 10px;
  background: rgba(255, 92, 77, 0.08);
  border: 1px solid rgba(255, 92, 77, 0.30);
  border-radius: 4px;
}
.detail-allergens-label {
  font-size: 11px;
  color: var(--ink-faint);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  font-weight: 700;
  margin-right: 4px;
}
.detail-allergen-chip {
  background: var(--red);
  color: var(--on-accent);
  padding: 3px 9px;
  border-radius: 10px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.02em;
}

/* ============================================================================
   v54 — Recents row + ingredient reverse lookup + tappable ingredient name
   ============================================================================ */

/* Recents row at the top of Specs (no-filter view only) */
.recents-row {
  margin-bottom: 16px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--rule);
}
.recents-row-h {
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-faint);
  font-weight: 700;
  margin-bottom: 8px;
}
.recents-row-list {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.recents-pill {
  background: rgba(255, 140, 90, 0.10);
  border: 1px solid rgba(255, 140, 90, 0.35);
  color: var(--ink);
  padding: 7px 14px;
  border-radius: 16px;
  font-size: 13px;
  font-family: var(--serif-display);
  font-weight: 500;
  cursor: pointer;
}
.recents-pill:hover {
  background: var(--accent);
  color: var(--on-accent);
  border-color: var(--accent);
}

/* Tappable ingredient name — opens the encyclopedia entry inline.
   Subtle dashed underline in the active theme accent so the affordance
   reads as a footnote-style link in a printed cocktail book, not a
   button or a pill. Each theme tints it via var(--accent). */
.ingredient-link {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
  text-decoration: underline dashed var(--accent);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  -webkit-text-decoration: underline dashed var(--accent);
  transition: color .15s, text-decoration-color .15s;
  /* v517 — Suppress iOS Safari's default orange tap-highlight rectangle.
     Caught by Joseph 2026-05-28: a screenshot of the Oaxaca Old Fashioned
     showed an orange box around the Mezcal row (only encyclopedia-linked
     ingredients showed it — Reposado tequila didn't because Reposado
     doesn't have an encyclopedia entry and renders as .ingredient-sub-link
     which already suppresses the tap-highlight). Matching the sibling
     class so taps don't leave a stuck "selection" look. */
  -webkit-tap-highlight-color: transparent;
}
.ingredient-link:hover,
.ingredient-link:focus-visible {
  color: var(--accent);
  text-decoration-style: solid;
  outline: none;
}
/* v189 — Non-encyclopedia ingredient (e.g. "Demerara syrup", "Lemon juice").
   Renders as a plain-text-looking button so it's tap-target-sized for the
   long-press → substitutions gesture, but visually invisible as a button.
   No underline (would read as encyclopedia-link); just a tiny right-side
   subtitle on hover hints "long-press for subs." */
.ingredient-sub-link {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.ingredient-sub-link:focus-visible {
  outline: 1px solid var(--accent);
  outline-offset: 2px;
  border-radius: 2px;
}
/* v189 — Long-press cue. Brief background flash when the press registers,
   so the bartender knows the gesture took. Removed via JS 200ms later. */
.ingredient-link.long-pressed,
.ingredient-sub-link.long-pressed {
  background: color-mix(in srgb, var(--accent) 18%, transparent);
  border-radius: 3px;
  transition: background 80ms ease;
}

/* v190 — Technique keyword in method prose. Subtle dotted underline in
   ink-dim (not accent) so it reads as a marginal annotation rather than
   a primary affordance. Hover reveals the accent — same vocabulary as
   the ingredient-link footnote pattern, dialed down because there can be
   3-5 of these in a single method paragraph and we don't want it to
   feel busy. */
.technique-link {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
  text-decoration: underline dotted var(--ink-faint);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  -webkit-text-decoration: underline dotted var(--ink-faint);
  transition: color .15s, text-decoration-color .15s;
}
.technique-link:hover,
.technique-link:focus-visible {
  color: var(--accent);
  text-decoration-color: var(--accent);
  text-decoration-style: solid;
  outline: none;
}

/* Ingredient lookup sheet — list of cocktails sharing an ingredient */
.ingredient-lookup-list { display: flex; flex-direction: column; }
.ingredient-lookup-row {
  display: block;
  width: 100%;
  text-align: left;
  background: rgba(255,255,255,0.04);
  border: 0;
  border-bottom: 1px solid var(--rule-strong);
  padding: 12px 6px;
  cursor: pointer;
  font-family: inherit;
  color: inherit;
}
.ingredient-lookup-row:hover { background: rgba(255,140,90,0.08); }
.ingredient-lookup-name {
  font-size: 15px;
  font-weight: 500;
  color: var(--ink);
  margin-bottom: 4px;
}
.ingredient-lookup-meta {
  font-size: 12px;
  color: var(--ink-dim);
  font-style: italic;
}

/* v54 — Settings: Spec online account form */
.settings-supabase-form {
  display: flex;
  gap: 8px;
  align-items: center;
  padding: 12px 14px;
  background: rgba(255,255,255,0.02);
  border-bottom: 1px solid var(--rule);
}
.settings-supabase-form .input { flex: 1; }
.settings-supabase-form .btn { white-space: nowrap; }
.settings-row-info {
  padding: 10px 14px;
  border-bottom: 1px solid var(--rule);
}

/* ============================================================================
   v54 — UX polish: drag-to-dismiss, larger glove targets, type-ahead
   ============================================================================ */

/* iOS-style drag handle at the top of every sheet */
.sheet-drag-handle {
  width: 44px;
  height: 4px;
  border-radius: 2px;
  background: var(--rule-strong);
  margin: 8px auto 4px;
  flex-shrink: 0;
  opacity: 0.6;
  cursor: grab;
}
.sheet-drag-handle:active { cursor: grabbing; opacity: 0.9; }
.sheet-header { cursor: default; }
@media (pointer: coarse) {
  /* On touch devices, indicate the header is grabbable too */
  .sheet-header { cursor: grab; }
}

/* Bottom-tab glove targets: bump min-height + tap area */
.bottom-tab {
  min-height: 60px;
  padding-top: 6px;
  padding-bottom: 6px;
}
.bottom-tab svg { width: 22px; height: 22px; }

/* v54: type-ahead search suggestions — surfaces below the search box */
.specs-search-wrap {
  position: relative;
  margin-bottom: 12px;
}
.specs-search-suggestions {
  display: flex;
  flex-direction: column;
  background: var(--bg-2);
  border: 1px solid var(--rule-strong);
  border-radius: 6px;
  margin-top: 4px;
  overflow: hidden;
  max-height: 360px;
  overflow-y: auto;
  /* Empty by default; only takes space when populated */
}
.specs-search-suggestions:empty { display: none; }
.specs-search-suggestion {
  display: block;
  width: 100%;
  text-align: left;
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--rule);
  padding: 10px 12px;
  cursor: pointer;
  font-family: inherit;
  color: inherit;
}
.specs-search-suggestion:last-child { border-bottom: 0; }
.specs-search-suggestion:hover {
  background: rgba(255, 140, 90, 0.10);
}
.specs-search-sugg-name {
  font-size: 14px;
  font-weight: 500;
  color: var(--ink);
  margin-bottom: 2px;
}
.specs-search-sugg-meta {
  font-size: 12px;
  color: var(--ink-faint);
  font-style: italic;
}

/* v54 — Walkthrough sheet (Settings → How to use Spec) */
.walkthrough-body-wrap {
  text-align: center;
  padding: 12px 4px 4px;
}
.walkthrough-counter {
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
  font-weight: 700;
  margin-bottom: 12px;
}
.walkthrough-title {
  font-family: var(--serif-display);
  font-size: 28px;
  color: var(--ink);
  margin: 0 0 14px;
  line-height: 1.15;
}
.walkthrough-body {
  font-size: 15px;
  line-height: 1.55;
  color: var(--ink-dim);
  font-family: var(--serif);
  margin: 0 0 24px;
  text-align: left;
}
.walkthrough-dots {
  display: flex;
  gap: 6px;
  justify-content: center;
  margin-bottom: 4px;
}
.walkthrough-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--rule-strong);
}
.walkthrough-dot.on {
  background: var(--accent);
}

/* ============================================================================
   v54 — Create rebuild: Flavor Compass + Seasonal + refined Riff
   ============================================================================ */

/* COMPASS — descriptor grid */
.compass-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 6px;
  margin-bottom: 16px;
}
@media (max-width: 380px) {
  .compass-grid { grid-template-columns: repeat(3, 1fr); }
}
.compass-chip {
  background: rgba(255,255,255,0.04);
  border: 1px solid var(--rule-strong);
  color: var(--ink);
  font-family: inherit;
  font-size: 13px;
  font-weight: 500;
  padding: 11px 4px;
  border-radius: 8px;
  cursor: pointer;
  text-align: center;
  /* v616 — Tap-target floor. The Compass descriptor grid is tapped
     repeatedly to build a flavor query; at 11px padding the cells fell
     ~5px short of 44px. Added an explicit 44px min-height and centered
     the label so the visible chip and rhythm are unchanged but the hit
     area clears the floor. */
  min-height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform 100ms ease, background 100ms ease;
}
.compass-chip:hover {
  transform: scale(1.02);
}
/* Compass flavor groups — routed through theme tokens so the chips
   pick up each theme's vocabulary instead of fixed Tiki Sunset hues.
   warm → brass-light (gold-leaf / brass / champagne / amber)
   bright → absinthe (sun yellow / champagne / doubloon)
   aromatic → accent-2 (peach / platinum-light / brass-light / coral)
   dark → spirit-liqueur (violet — universal across themes) */
.compass-chip[data-group="warm"] { color: var(--brass-light);    border-color: var(--rule-faint); }
.compass-chip[data-group="bright"] { color: var(--absinthe);       border-color: var(--rule-gold);  }
.compass-chip[data-group="aromatic"] { color: var(--accent-2);       border-color: var(--rule-faint); }
.compass-chip[data-group="dark"] { color: var(--spirit-liqueur); border-color: var(--rule-faint); }
.compass-chip.on {
  background: var(--accent);
  color: var(--on-accent);
  border-color: var(--accent);
  font-weight: 700;
  transform: scale(1.04);
}
/* Active-state fills mirror the chip text colors so the chip looks like
   it's been "lit up" in the same hue family. Inverted ink gets routed
   through --on-accent / --bg per theme so it stays legible. */
.compass-chip.on[data-group="warm"] { background: var(--brass-light);    color: var(--on-accent); }
.compass-chip.on[data-group="bright"] { background: var(--absinthe);       color: var(--on-accent); }
.compass-chip.on[data-group="aromatic"] { background: var(--accent-2);       color: var(--on-accent); }
.compass-chip.on[data-group="dark"] { background: var(--spirit-liqueur); color: var(--ink-bright); }

/* Summary + clear */
.compass-summary {
  margin-bottom: 12px;
}
.compass-summary-empty {
  font-size: 13px;
  color: var(--ink-faint);
  font-style: italic;
  text-align: center;
  padding: 8px 0;
}
.compass-summary-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.compass-summary-label {
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-faint);
  font-weight: 700;
}

/* Compass results — bridges, matches, build CTA */
.compass-results { display: flex; flex-direction: column; gap: 14px; }
.compass-section {
  background: rgba(255,255,255,0.03);
  border: 1px solid var(--rule);
  border-radius: 8px;
  padding: 12px 14px;
}
.compass-section-h {
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--accent-2);
  font-weight: 700;
  margin-bottom: 10px;
}

/* Bridges */
.compass-bridge {
  padding: 10px 0;
  border-bottom: 1px solid var(--rule);
}
.compass-bridge:last-child { border-bottom: 0; padding-bottom: 0; }
.compass-bridge-tags {
  display: flex;
  gap: 4px;
  flex-wrap: wrap;
  margin-bottom: 6px;
}
.compass-bridge-tag {
  background: rgba(255, 140, 90, 0.14);
  color: var(--accent-2);
  padding: 2px 8px;
  border-radius: 8px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.02em;
}
.compass-bridge-text {
  font-size: 14px;
  line-height: 1.55;
  color: var(--ink-dim);
  font-family: var(--serif);
  margin: 0 0 8px;
}
.compass-bridge-tension {
  font-size: 13px;
  line-height: 1.5;
  color: var(--ink-faint);
  font-style: italic;
  font-family: var(--serif);
  margin: 0 0 8px;
}
.compass-tension-label {
  color: var(--maraschino);
  font-weight: 700;
  font-style: normal;
}
.compass-bridge-anchors,
.compass-bridge-exemplars {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  margin-top: 6px;
}
.compass-anchor-label {
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-faint);
  font-weight: 700;
  margin-right: 2px;
}
.compass-anchor-chip {
  background: rgba(255,255,255,0.06);
  color: var(--ink-dim);
  padding: 3px 8px;
  border-radius: 4px;
  font-size: 12px;
}
.compass-exemplar-chip {
  background: rgba(255, 214, 103, 0.10);
  border: 1px solid rgba(255, 214, 103, 0.40);
  color: var(--brass);
  padding: 3px 9px;
  border-radius: 4px;
  font-size: 12px;
  font-family: inherit;
  font-weight: 500;
  cursor: pointer;
}
.compass-exemplar-chip:hover {
  background: rgba(255, 214, 103, 0.20);
}
.compass-exemplar-chip.muted {
  background: rgba(255,255,255,0.03);
  border-color: var(--rule);
  color: var(--ink-faint);
  cursor: default;
}

/* Matches grid */
.compass-matches { display: flex; flex-direction: column; gap: 1px; }
.compass-match {
  display: block;
  width: 100%;
  text-align: left;
  background: rgba(255,255,255,0.04);
  border: 0;
  border-bottom: 1px solid var(--rule);
  padding: 10px 6px;
  cursor: pointer;
  font-family: inherit;
  color: inherit;
}
.compass-match:hover { background: rgba(255,140,90,0.08); }
.compass-match-name {
  font-size: 14px;
  font-weight: 500;
  color: var(--ink);
  margin-bottom: 4px;
}
.compass-match-kind {
  font-size: 11px;
  color: var(--ink-faint);
  font-style: italic;
  font-weight: 400;
}
.compass-match-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}
.compass-match-tag.on {
  background: rgba(255, 140, 90, 0.18);
  color: var(--accent-2);
  padding: 2px 7px;
  border-radius: 6px;
  font-size: 11px;
  font-weight: 600;
}

.compass-detail-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.compass-build-btn {
  width: 100%;
  margin-top: 6px;
  padding: 14px;
  font-weight: 600;
}

/* SEASONAL — month + region toggles */
.seasonal-month-row {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-bottom: 8px;
}
.seasonal-month-pill {
  background: rgba(255,255,255,0.04);
  border: 1px solid var(--rule);
  color: var(--ink-dim);
  font-family: inherit;
  font-size: 12px;
  font-weight: 500;
  padding: 6px 10px;
  border-radius: 14px;
  cursor: pointer;
  flex: 1 0 auto;
  min-width: 50px;
  text-align: center;
}
.seasonal-month-pill.on {
  background: var(--accent);
  color: var(--on-accent);
  border-color: var(--accent);
  font-weight: 700;
}

.seasonal-region-row {
  display: flex;
  gap: 6px;
  margin-bottom: 16px;
}
.seasonal-region-pill {
  background: transparent;
  border: 1px solid var(--rule-strong);
  color: var(--ink-dim);
  font-family: inherit;
  font-size: 12px;
  padding: 6px 12px;
  border-radius: 14px;
  cursor: pointer;
}
.seasonal-region-pill.on {
  background: rgba(255, 140, 90, 0.14);
  border-color: var(--accent);
  color: var(--accent-2);
  font-weight: 600;
}

.seasonal-note {
  background: rgba(255,255,255,0.04);
  border-left: 3px solid var(--accent);
  padding: 12px 14px;
  border-radius: 0 6px 6px 0;
  margin-bottom: 16px;
}
.seasonal-note-month {
  font-family: var(--serif-display);
  font-size: 22px;
  color: var(--ink);
  margin-bottom: 4px;
}
.seasonal-note-essay {
  font-size: 14px;
  line-height: 1.55;
  color: var(--ink-dim);
  font-family: var(--serif);
  margin: 0;
  font-style: italic;
}

.seasonal-section-h {
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-faint);
  font-weight: 700;
  margin: 16px 0 8px;
}

.seasonal-featured {
  display: flex;
  flex-direction: column;
}
.seasonal-featured-row {
  display: block;
  width: 100%;
  text-align: left;
  background: rgba(255, 214, 103, 0.06);
  border: 0;
  border-bottom: 1px solid var(--rule);
  padding: 10px 8px;
  cursor: pointer;
  font-family: inherit;
  color: inherit;
}
.seasonal-featured-row:hover { background: rgba(255, 214, 103, 0.14); }
.seasonal-featured-row.muted { background: rgba(255,255,255,0.02); cursor: default; }
.seasonal-featured-name {
  font-size: 14px;
  font-weight: 500;
  color: var(--ink);
  margin-bottom: 2px;
}
.seasonal-featured-meta {
  font-size: 12px;
  color: var(--ink-dim);
  font-style: italic;
}

.seasonal-ingredient-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 6px;
}
@media (min-width: 600px) {
  .seasonal-ingredient-grid { grid-template-columns: repeat(3, 1fr); }
}
.seasonal-ingredient {
  text-align: left;
  background: rgba(255,255,255,0.04);
  border: 1px solid var(--rule);
  color: var(--ink);
  font-family: inherit;
  padding: 10px;
  border-radius: 6px;
  cursor: pointer;
}
.seasonal-ingredient.peak {
  border-color: var(--accent);
  background: rgba(255, 140, 90, 0.06);
}
.seasonal-ingredient:hover {
  background: rgba(255, 140, 90, 0.10);
}
.seasonal-ingredient-name {
  font-size: 14px;
  font-weight: 500;
  margin-bottom: 2px;
}
.seasonal-ingredient-meta {
  font-size: 11px;
  color: var(--ink-faint);
  font-style: italic;
  text-transform: capitalize;
}

/* RIFF — variant detection banner + inline subs row */
.riff-variant-banner {
  margin-bottom: 12px;
  /* empty banner is invisible; populated by _maybeDetectVariant */
}
.riff-variant-banner:empty { display: none; }
.riff-variant-detected {
  background: rgba(255, 214, 103, 0.10);
  border: 1px solid rgba(255, 214, 103, 0.40);
  border-radius: 6px;
  padding: 10px 12px;
  font-size: 13px;
  color: var(--ink-dim);
  display: flex;
  align-items: center;
  gap: 8px;
  font-style: italic;
  font-family: var(--serif);
}
.riff-variant-icon {
  color: var(--brass);
  font-size: 14px;
}
.riff-variant-link {
  background: none;
  border: 0;
  color: var(--accent-2);
  font-family: inherit;
  font-style: italic;
  font-size: 13px;
  text-decoration: underline;
  cursor: pointer;
  padding: 0;
}
.riff-variant-link:hover { color: var(--accent); }

.riff-ing-block {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.riff-ing-subs-row {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-left: 76px;  /* align with the name button column */
  margin-bottom: 8px;
}
.riff-ing-sub-pill {
  background: rgba(255, 140, 90, 0.06);
  border: 1px dashed rgba(255, 140, 90, 0.35);
  color: var(--ink-dim);
  font-family: inherit;
  font-size: 11px;
  padding: 3px 8px;
  border-radius: 10px;
  cursor: pointer;
}
.riff-ing-sub-pill:hover {
  background: rgba(255, 140, 90, 0.16);
  color: var(--ink);
  border-style: solid;
}

/* ============================================================
   v55 — Theme picker tiles + ornamental glyphs per theme
   ============================================================ */

/* === Settings → Look & feel — theme picker grid === */
.theme-picker {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 12px;
  margin: 8px 0 4px;
}

.theme-tile {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 14px 14px 16px;
  background: var(--bg-2);
  border: var(--hairline) solid var(--rule);
  border-radius: var(--radius);
  cursor: pointer;
  text-align: left;
  font: inherit;
  color: var(--ink);
  transition: border-color 120ms ease, background 120ms ease;
  -webkit-tap-highlight-color: transparent;
}
.theme-tile:hover {
  border-color: var(--rule-strong);
}
.theme-tile.is-active {
  border-color: var(--accent);
  border-width: 2px;
  padding: 13px 13px 15px;        /* compensate for thicker border */
  background: var(--surface);
  box-shadow: inset 0 0 0 1px var(--rule-faint);
}

.theme-tile-swatch {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
  width: 56px;
  height: 56px;
  border-radius: var(--radius);
  overflow: hidden;
  flex-shrink: 0;
  border: var(--hairline) solid var(--rule);
}
.theme-tile-quad { width: 100%; height: 100%; }

.theme-tile-meta {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.theme-tile-name {
  font-family: var(--serif-display);
  font-size: 16px;
  letter-spacing: 0.4px;
  color: var(--ink-bright);
}
.theme-tile-bar {
  font-family: var(--serif-italic);
  font-style: italic;
  font-size: 11px;
  color: var(--accent);
  letter-spacing: 0.2px;
}
.theme-tile-mood {
  font-family: var(--serif);
  font-size: 11px;
  line-height: 1.5;
  color: var(--ink-dim);
  margin-top: 2px;
}

/* === Theme-aware ornamental dividers ===
   Section dividers can opt into the per-theme glyph by adding the
   .ornament class. Examples:
       <div class="section-mark"></div>     → fleuron / lozenge / etc.
       <hr class="ornament-rule">           → glyph centered between rules
   The actual glyph is sourced from --ornament-divider, which each
   [data-theme="X"] block sets independently. */
.section-mark {
  font-family: var(--serif-display);
  font-size: 18px;
  line-height: 1;
  text-align: center;
  color: var(--accent);
  margin: 18px 0;
  letter-spacing: 4px;
  user-select: none;
}
.section-mark::before {
  content: var(--ornament-divider);
}

.ornament-rule {
  border: 0;
  height: 18px;
  position: relative;
  margin: 22px 0;
  text-align: center;
}
.ornament-rule::before,
.ornament-rule::after {
  content: "";
  position: absolute;
  top: 50%;
  width: calc(50% - 18px);
  height: var(--hairline);
  background: var(--rule-gold);
}
.ornament-rule::before { left: 0; }
.ornament-rule::after { right: 0; }
.ornament-rule > span {
  position: relative;
  display: inline-block;
  padding: 0 12px;
  background: var(--bg);
  font-family: var(--serif-display);
  font-size: 14px;
  color: var(--accent);
  line-height: 18px;
  letter-spacing: 2px;
}
.ornament-rule > span::before {
  content: var(--ornament-divider);
}

/* === Theme-aware drop caps ===
   Apply .dropcap to the first letter of a paragraph (or use a span
   wrapper). Each theme gets its own color + shadow recipe. The
   typeface is the theme's display face, so it carries the theme
   voice without needing per-theme CSS rules. */
.dropcap {
  float: left;
  font-family: var(--serif-display);
  font-size: 3.4em;
  line-height: 0.85;
  padding: 6px 8px 0 0;
  margin-top: 4px;
  color: var(--dropcap-color);
  text-shadow: var(--dropcap-shadow);
  font-feature-settings: "lnum";
}

/* Connaught: tighter Deco geometry — the lozenge is a thin glyph,
   center it visually with extra letter-spacing on the section mark. */


/* Maison Premiere: laurel-flower ornament reads bigger; tone it down. */


/* Smuggler's Cove: compass star reads loud — keep tight. */








/* v206 — section-mark tuning for the new bindings. Per-glyph metrics:
   Smoke's cross-pattée is a heavy mark, keep it tight.
   Marine's compass cluster reads thin, open it up.
   Lodge's pine rosette is round, normal letter-spacing.
   Ivory's sun-flower is small at body size, bump like Rosé.
   Velvet's Maltese is theatrical, set it loud.
   Copper's fleur-de-lis is intricate, generous spacing. */
[data-theme="smoke"] .section-mark {
  font-size: 16px;
  letter-spacing: 8px;
}

[data-theme="ivory"] .section-mark {
  font-size: 15px;
  letter-spacing: 7px;
}



/* ============================================================
   v56 — Pre-batch row at the bottom of the recipe sheet
   ============================================================
   The button on every recipe that hands the cocktail to Batch.
   Sits flush right with a hairline above so it reads as a
   discrete action, not a continuation of the spec body. */
.detail-prebatch-row {
  display: flex;
  justify-content: flex-end;
  margin: 18px 0 4px;
  padding-top: 14px;
  border-top: var(--hairline) solid var(--rule-faint);
}
.detail-prebatch-row .btn {
  font-family: var(--serif-display);
  letter-spacing: 0.6px;
}

/* ============================================================
   v62 — CREATE rebuild: Doors row + Build slot editor
   ============================================================
   The Create tab is now structure-first. Above Build is a slim
   four-tile doors row (Structure / Compass / Seasonal / Canon).
   Build is the destination — a slot-based editor where each row
   is a printed cocktail-menu line: amount · unit · ingredient.
*/

.create-doors-row {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr 1fr;
  gap: 8px;
  padding: 6px 0 14px;
  border-bottom: var(--hairline) solid var(--rule-faint);
  margin-bottom: 14px;
}
@media (max-width: 540px) {
  .create-doors-row {
    grid-template-columns: 1fr 1fr;
  }
}
.create-door-tile {
  background: transparent;
  border: 1px solid var(--rule-faint);
  border-radius: 6px;
  padding: 10px 12px;
  text-align: left;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-family: inherit;
  color: var(--ink);
  transition: border-color 120ms ease, background 120ms ease, transform 120ms ease;
  min-height: 64px;
}
.create-door-tile:hover {
  border-color: var(--rule-gold);
  background: rgba(255, 214, 103, 0.05);
}
.create-door-tile.primary {
  border-color: var(--rule-gold);
}
.create-door-tile.on {
  border-color: var(--accent);
  background: rgba(255, 140, 90, 0.08);
}
.create-door-tile.on .create-door-label { color: var(--accent); }
.create-door-label {
  font-family: var(--serif-display);
  font-size: 14px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--ink);
}
.create-door-blurb {
  font-size: 11.5px;
  line-height: 1.35;
  color: var(--ink-dim);
  font-style: italic;
  font-family: var(--serif-italic);
}

.create-door-panel {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding-bottom: 18px;
}
.create-door-h h2 {
  font-family: var(--serif-display);
  font-size: 22px;
  margin: 4px 0 6px;
  color: var(--ink);
}
.create-door-h p {
  font-size: 13px;
  color: var(--ink-dim);
  line-height: 1.45;
  font-style: italic;
  font-family: var(--serif-italic);
  margin: 0 0 6px;
}

/* v549 — Build page tile grid. Auto-fit so the grid degrades smoothly. */
.build-tile-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 12px;
  margin: 8px 0 16px;
}

/* v554 — Three-tier Build layout. Tier 1 = hero row (3 large tiles);
   Tier 2 = discovery chips (3 inline pills); Tier 3 = beyond-a-drink
   tiles (2 tiles for Menu Writer + Pre-batch). Chief-designer pass to
   replace the v549 wall-of-identical-rectangles. */

/* Tier 1: hero row — exactly 3 columns on wide, then 2, then 1. */
.build-hero-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 14px;
  margin: 8px 0 18px;
}
@media (max-width: 900px) {
  .build-hero-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 600px) {
  .build-hero-grid { grid-template-columns: 1fr; }
}
.build-hero-grid > a:hover,
.build-hero-grid > button:hover {
  background: var(--ink-soft-hover, rgba(202, 164, 90, 0.08));
  transform: translateY(-1px);
}

/* Tier 2: discovery chips — inline pill row, wraps on small screens. */
.build-chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0 0 24px;
  padding: 0 2px;
}
.build-chip-row button:hover {
  background: var(--accent-soft, rgba(212, 160, 86, 0.08)) !important;
  border-color: var(--accent) !important;
}

/* Tier 3: beyond-a-drink — 2 equal columns, same tile chrome as Tier 1.
   v559: kept for legacy paths but no longer rendered on the Build page. */
.build-secondary-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 14px;
  margin: 8px 0 18px;
}
@media (max-width: 600px) {
  .build-secondary-grid { grid-template-columns: 1fr; }
}
.build-secondary-grid > button:hover {
  background: var(--ink-soft-hover, rgba(202, 164, 90, 0.08));
  transform: translateY(-1px);
}

/* v559 — Studio is the feature. Build page = full-width Studio hero +
   one row of three helper tiles (AI Builder, AI Menu Writer, Pre-batch).
   Helpers grid: 3-col at full width, 2-col at tablet, 1-col at phone. */
.build-helpers-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 14px;
  margin: 22px 0 18px;
}
@media (max-width: 900px) {
  .build-helpers-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 600px) {
  .build-helpers-grid { grid-template-columns: 1fr; }
}
.build-helpers-grid > a:hover,
.build-helpers-grid > button:hover {
  background: var(--ink-soft-hover, rgba(202, 164, 90, 0.08));
  transform: translateY(-1px);
}

/* v559 — Studio hero hover. Gold border lifts so it reads as the
   primary CTA on the page. */
.build-studio-hero:hover {
  border-color: #e8c275 !important;
  transform: translateY(-1px);
}

/* STRUCTURE picker — 6 editorial tiles */
.structure-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 10px;
}
@media (min-width: 720px) {
  .structure-grid { grid-template-columns: repeat(3, 1fr); }
}
.structure-tile {
  background: transparent;
  border: 1px solid var(--rule-faint);
  border-radius: 6px;
  padding: 14px 14px 12px;
  text-align: left;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-family: inherit;
  color: var(--ink);
  transition: border-color 120ms ease, background 120ms ease;
  min-height: 120px;
}
.structure-tile:hover {
  border-color: var(--accent);
  background: rgba(255, 140, 90, 0.05);
}
.structure-tile-name {
  font-family: var(--serif-display);
  font-size: 19px;
  letter-spacing: 0.5px;
  color: var(--ink);
}
.structure-tile-blurb {
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--ink-dim);
}
.structure-tile-exemplars {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 8px;
  margin-top: auto;
  padding-top: 6px;
  border-top: var(--hairline) dashed var(--rule-faint);
}
.structure-tile-ex {
  /* v244 — exemplars are now <button>s (cross-link to the canon). Reset
     browser button chrome so they read as inline italic chips, then add
     a subtle hover state so they advertise their tap affordance. */
  font-size: 11px;
  font-style: italic;
  font-family: var(--serif-italic);
  color: var(--ink-faint);
  background: transparent;
  border: none;
  padding: 1px 4px;
  margin: 0;
  cursor: pointer;
  border-radius: 3px;
  transition: color 120ms ease, background 120ms ease;
}
.structure-tile-ex:hover,
.structure-tile-ex:focus-visible {
  color: var(--accent);
  background: rgba(var(--accent-rgb, 200, 152, 88), 0.08);
  outline: none;
}

/* COMPASS — Build CTA panel */
.compass-build-cta {
  margin-top: 6px;
  padding: 12px 14px;
  border: var(--hairline) solid var(--rule-gold);
  border-radius: 6px;
  background: rgba(255, 214, 103, 0.05);
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.compass-build-cta-line {
  font-size: 13px;
  color: var(--ink);
  font-family: var(--serif);
}
.compass-build-cta-line strong {
  color: var(--accent);
  font-weight: 600;
}
.compass-build-btn {
  align-self: flex-start;
}

/* BUILD HEADER */
.build-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 0 8px;
  border-bottom: var(--hairline) solid var(--rule-faint);
  margin-bottom: 14px;
}
.build-back {
  flex-shrink: 0;
}
.build-head-meta {
  font-size: 12.5px;
  color: var(--ink-dim);
  text-align: right;
  flex: 1;
  line-height: 1.3;
}
.build-head-structure {
  font-family: var(--serif-display);
  font-size: 14px;
  color: var(--accent);
  letter-spacing: 0.6px;
  text-transform: uppercase;
}
.build-head-blurb {
  font-style: italic;
  font-family: var(--serif-italic);
  color: var(--ink-faint);
  font-size: 12px;
}
.build-head-sep { color: var(--rule-faint); }

.build-name {
  width: 100%;
  font-family: var(--serif-display);
  font-size: 22px;
  padding: 12px 8px;
  border: 0;
  border-bottom: var(--hairline) solid var(--rule-faint);
  background: transparent;
  margin-bottom: 14px;
}
.build-name:focus {
  outline: 0;
  border-bottom-color: var(--accent);
}

/* BUILD VARIANT BANNER — passive, never blocks */
.build-variant-banner { margin-bottom: 12px; }
.build-variant-banner:empty { display: none; }
.build-variant-detected {
  background: rgba(255, 214, 103, 0.10);
  border: 1px solid rgba(255, 214, 103, 0.40);
  border-radius: 6px;
  padding: 10px 12px;
  font-size: 13px;
  color: var(--ink-dim);
  display: flex;
  align-items: center;
  gap: 8px;
  font-style: italic;
  font-family: var(--serif);
}
.build-variant-icon {
  color: var(--brass);
  font-size: 14px;
}
.build-variant-link {
  background: none;
  border: 0;
  color: var(--accent-2);
  font-family: inherit;
  font-style: italic;
  font-size: 13px;
  text-decoration: underline;
  cursor: pointer;
  padding: 0;
}
.build-variant-link:hover { color: var(--accent); }

/* BUILD SLOTS — printed-menu leader-dot lines */
.build-slots {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 14px;
}
.build-section-h {
  font-family: var(--serif-display);
  font-size: 13px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--ink-dim);
  margin: 6px 0 4px;
}
.build-slot {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 8px 4px 10px;
  border-bottom: var(--hairline) dashed var(--rule-faint);
}
.build-slot:last-child { border-bottom: 0; }
.build-slot.required .build-slot-label {
  color: var(--ink);
}
.build-slot.accent .build-slot-label {
  color: var(--accent-2);
}
.build-slot-label-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  padding: 0 2px;
}
.build-slot-label {
  font-family: var(--serif-display);
  font-size: 11px;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: var(--ink-dim);
}
.build-slot-optional {
  font-size: 10.5px;
  font-style: italic;
  font-family: var(--serif-italic);
  color: var(--ink-faint);
  letter-spacing: 0.4px;
}
.build-slot-row {
  display: flex;
  align-items: baseline;
  gap: 6px;
  width: 100%;
  font-family: var(--serif);
}
.build-slot-amt,
.build-slot-unit {
  background: transparent;
  border: 0;
  border-bottom: var(--hairline) dashed var(--rule-faint);
  padding: 4px 2px;
  font-family: var(--serif);
  font-size: 15px;
  color: var(--ink);
  width: 48px;
  text-align: right;
  flex-shrink: 0;
}
.build-slot-unit {
  width: 56px;
  text-align: left;
  color: var(--ink-dim);
}
.build-slot-amt:focus,
.build-slot-unit:focus {
  outline: 0;
  border-bottom-color: var(--accent);
}
.build-slot-leader {
  flex: 1;
  border-bottom: var(--hairline) dotted var(--rule-faint);
  margin: 0 4px 6px;
  min-width: 16px;
}
.build-slot-name {
  background: transparent;
  border: 0;
  border-bottom: var(--hairline) dashed transparent;
  text-align: left;
  font-family: var(--serif);
  font-size: 15px;
  color: var(--ink);
  cursor: pointer;
  padding: 4px 6px;
  /* v517 — Was flex: 0 0 auto / max-width: 60% / white-space: nowrap with
     ellipsis. Pre-v517 long brand names got eaten ("Milk-clarified
     bourbon (Eli…" instead of "Milk-clarified bourbon (Elijah Craig)"),
     stripping the most useful part of the field. Now: name takes the
     remaining row width and wraps to a second line when needed.
     min-width: 0 lets the flex item shrink below intrinsic content
     width — without it the row would overflow instead of wrap.
     The leader's flex: 1 still claims slack on short names; on long
     names the wrap kicks in. */
  flex: 1 1 auto;
  min-width: 0;
  max-width: 100%;
  white-space: normal;
  overflow: visible;
  text-overflow: clip;
  word-break: break-word;
}
.build-slot-name:hover {
  border-bottom-color: var(--rule-gold);
  color: var(--accent);
}
.build-slot-name.filled {
  color: var(--ink);
  font-weight: 500;
}
.build-slot-name-empty {
  color: var(--ink-faint);
  font-style: italic;
  font-family: var(--serif-italic);
}
.build-slot-remove {
  background: transparent;
  border: 0;
  color: var(--ink-faint);
  font-size: 18px;
  cursor: pointer;
  padding: 0 6px;
  line-height: 1;
}
.build-slot-remove:hover { color: var(--red); }
.build-slot-add {
  align-self: flex-start;
  margin-top: 4px;
}

/* BUILD META — glass / method / ice */
.build-meta-row {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
  padding: 10px 0;
  margin-bottom: 12px;
  border-top: var(--hairline) solid var(--rule-faint);
  border-bottom: var(--hairline) solid var(--rule-faint);
}
.build-meta-item {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.build-meta-label {
  font-family: var(--serif-display);
  font-size: 10.5px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.build-meta-value {
  font-size: 13px;
  color: var(--ink);
  font-family: var(--serif);
}

/* SAVE row */
.build-save {
  background: var(--accent);
  color: var(--on-accent);
  font-family: var(--serif-display);
  letter-spacing: 1px;
  text-transform: uppercase;
}

/* SLOT PICKER sheet */
.slot-pick-list {
  display: flex;
  flex-direction: column;
  margin-top: 8px;
  max-height: 50vh;
  overflow-y: auto;
}
.slot-pick-row {
  background: transparent;
  border: 0;
  border-bottom: var(--hairline) dotted var(--rule-faint);
  text-align: left;
  padding: 10px 8px;
  font-family: var(--serif);
  font-size: 14px;
  color: var(--ink);
  cursor: pointer;
}
.slot-pick-row:hover { background: rgba(255, 140, 90, 0.06); }
.slot-pick-row.selected {
  color: var(--accent);
  font-weight: 600;
}
.slot-pick-row.custom {
  font-style: italic;
  font-family: var(--serif-italic);
  color: var(--accent-2);
}
.slot-pick-subs {
  margin-top: 8px;
  padding: 8px 0;
  border-top: var(--hairline) solid var(--rule-faint);
  border-bottom: var(--hairline) solid var(--rule-faint);
}
.slot-pick-subs-h {
  font-family: var(--serif-display);
  font-size: 11px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: 6px;
}
.slot-pick-subs-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

/* BUILD SAVE confirm strip in the promote sheet */
.build-save-confirm {
  padding: 10px 12px 12px;
  margin-bottom: 8px;
  border-radius: 6px;
  background: rgba(0, 0, 0, 0.04);
  border: var(--hairline) solid var(--rule-faint);
}
.build-save-confirm-title {
  font-family: var(--serif-display);
  font-size: 14px;
  color: var(--ink);
  margin-bottom: 4px;
}
.build-save-confirm-meta {
  font-size: 12px;
  font-style: italic;
  font-family: var(--serif-italic);
  color: var(--ink-dim);
}

/* ============================================================
   v63 — Daily Pour popup
   ============================================================
   Editorial cocktail-of-the-day card. Opens once per day on app
   launch. Feels like flipping the cocktail column in today's
   newspaper, not getting a notification. */
/* v562 — TODAY'S POUR feature card on the Recipes cocktails sub-tab.
   The pick is the same one the popup showed this morning. The popup
   fires once per day; the card is the persistent home for the pick
   for the rest of the day. Styled as an inline editorial header,
   tighter than the modal version. */
.specs-todays-pour-host {
  margin: 4px 0 14px;
}
.specs-todays-pour {
  display: block;
  width: 100%;
  text-align: left;
  background: linear-gradient(135deg, rgba(232, 194, 117, 0.06) 0%, rgba(202, 164, 90, 0.02) 100%);
  border: 1px solid var(--rule);
  border-left: 3px solid var(--accent);
  border-radius: 8px;
  padding: 14px 16px 12px;
  cursor: pointer;
  font-family: var(--serif);
  color: inherit;
  transition: border-color 0.15s ease, background 0.15s ease, transform 0.12s ease;
}
.specs-todays-pour:hover {
  border-color: var(--accent);
  transform: translateY(-1px);
}
.specs-todays-pour .tp-head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin-bottom: 4px;
}
.specs-todays-pour .tp-eyebrow {
  font-family: var(--serif-italic);
  font-style: italic;
  font-size: 11.5px;
  color: var(--ink-faint);
  letter-spacing: 0.04em;
}
.specs-todays-pour .tp-headline {
  font-size: 9.5px;
  letter-spacing: 0.20em;
  text-transform: uppercase;
  color: var(--accent);
  font-weight: 700;
  margin-left: auto;
}
.specs-todays-pour .tp-name {
  font-family: var(--serif-display);
  font-size: 22px;
  line-height: 1.15;
  font-style: italic;
  font-weight: 500;
  color: var(--ink);
  margin: 4px 0 2px;
}
.specs-todays-pour .tp-family {
  font-family: var(--serif-italic);
  font-style: italic;
  font-size: 12px;
  color: var(--ink-dim);
  margin-bottom: 8px;
}
.specs-todays-pour .tp-reason {
  font-family: var(--serif);
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--ink-dim);
  margin: 0 0 8px;
  font-style: italic;
}
.specs-todays-pour .tp-reason-label {
  font-style: normal;
  font-size: 9.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
  font-weight: 600;
  margin-right: 6px;
}
.specs-todays-pour .tp-cta {
  display: inline-block;
  font-family: var(--serif-italic);
  font-style: italic;
  font-size: 12.5px;
  color: var(--accent);
  letter-spacing: 0.02em;
}

.daily-pour {
  text-align: center;
  padding: 16px 8px 4px;
  font-family: var(--serif);
  color: var(--ink);
}
.daily-pour-eyebrow {
  font-family: var(--serif-italic);
  font-style: italic;
  font-size: 13px;
  color: var(--ink-dim);
  letter-spacing: 0.4px;
  margin-bottom: 14px;
}
.daily-pour-headline {
  font-family: var(--serif-display);
  font-size: 16px;
  letter-spacing: 4px;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 6px;
}
.daily-pour-headline::before,
.daily-pour-headline::after {
  content: "—";
  margin: 0 10px;
  color: var(--rule-gold);
}
.daily-pour-cocktail {
  font-family: var(--serif-display);
  font-size: 32px;
  line-height: 1.15;
  letter-spacing: 0.3px;
  color: var(--ink-bright);
  margin: 8px 24px 6px;
}
.daily-pour-family {
  font-family: var(--serif-italic);
  font-style: italic;
  font-size: 14px;
  color: var(--ink-dim);
  margin-bottom: 18px;
}
.daily-pour-note {
  font-family: var(--serif);
  font-size: 14px;
  line-height: 1.55;
  color: var(--ink-dim);
  margin: 0 16px 22px;
  font-style: italic;
}
/* v116 — Wave 66: "Why today?" curation reason. Slightly more prominent
   than the generic monthly note since it's tied to the specific pick.
   The "Why today:" prefix is a small accent-colored label so the
   rationale reads as a curated note, not a quote. */
.daily-pour-reason {
  font-family: var(--serif);
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--ink);
  margin: 0 16px 22px;
  padding: 10px 14px;
  background: color-mix(in srgb, var(--accent) 6%, transparent);
  border-left: 2px solid var(--accent);
  border-radius: 0 6px 6px 0;
}
.daily-pour-reason-label {
  font-family: var(--sans);
  font-size: 10.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent);
  margin-right: 2px;
}
.daily-pour-ctas {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  margin-top: 8px;
  padding-top: 18px;
  border-top: var(--hairline) solid var(--rule-faint);
}
.daily-pour-ctas .btn {
  font-family: var(--serif-display);
  letter-spacing: 0.6px;
  min-width: 200px;
}
/* v216 — Skip is a quiet link now, not a peer button. Reads as escape
   hatch instead of competing with "Open the spec" for attention. */
.daily-pour-ctas .daily-pour-skip,
.daily-pour-ctas .btn-link {
  background: transparent;
  border: 0;
  padding: 6px 10px;
  margin: 0;
  font-family: var(--serif-italic);
  font-style: italic;
  font-size: 12px;
  letter-spacing: 0.04em;
  color: var(--ink-faint);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
  min-width: 0;
  transition: color 150ms ease;
}
.daily-pour-ctas .daily-pour-skip:hover {
  color: var(--ink-dim);
}

/* ============================================================
   v67 — Wake-lock indicator + dog-ear corner
   ============================================================ */

/* #12 — Wake-lock indicator on recipe sheet.
   Renders only after holdWakeLock() resolves AND isWakeLockHeld()
   returns true (so we don't pretend on browsers without the API).
   Subtle italic line + a softly pulsing dot in the active accent.
   Lives at the bottom of sheet body; print stylesheet hides it. */
.wake-indicator {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 14px 4px 6px;
  padding: 6px 0 0;
  font-family: var(--serif-italic);
  font-style: italic;
  font-size: 12px;
  color: var(--ink-faint);
  letter-spacing: 0.2px;
  border-top: var(--hairline) dashed var(--rule-faint);
  padding-top: 10px;
}
.wake-indicator-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 0 currentColor;
  animation: wake-pulse 2.4s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
@keyframes wake-pulse {
  0%, 100% { opacity: 0.55; transform: scale(1); }
  50%      { opacity: 1;    transform: scale(1.18); }
}
.wake-indicator-text { line-height: 1; }
@media print {
  .wake-indicator { display: none !important; }
}

/* #16 — Dog-ear corner on starred cocktail cards.
   v320.1 RETIRED per Maya second-look audit. The original intent
   was a "folded page corner" affordance for favorited cards — a
   poetic match for the book metaphor. In practice it rendered as a
   naked triangle bleeding off the corner of one card, and bartenders
   already have the filled star indicator on the right edge for the
   same signal. Two icons saying "favorited" is one too many; the
   star wins because it's tappable. Rule disabled (kept the selector
   commented in case we want to revive the dog-ear as a deliberate,
   labeled feature in v2 — e.g. a key for what folded-corner means).
.cocktail-card:has(.card-star.on) {
  position: relative;
}
.cocktail-card:has(.card-star.on)::before {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  width: 0;
  height: 0;
  border-style: solid;
  border-width: 0 18px 18px 0;
  border-color: transparent var(--accent) transparent transparent;
  pointer-events: none;
  z-index: 1;
  filter: drop-shadow(-1px 1px 0 rgba(0, 0, 0, 0.18));
  opacity: 0.9;
}
*/
@media print {
  /* Don't print the dog-ear — paper has its own physical corners. */
  /* .cocktail-card:has(.card-star.on)::before { display: none !important; } */
}

/* ============================================================
   v68 — Page-turn animation + theme tile preview state
   ============================================================ */

/* #13 — Page-turn on every route change.
   Subtle slide-from-right on the view container. ~220ms, eases out so
   it lands cleanly. We skip the animation when prefers-reduced-motion
   is set so vestibular-sensitive users aren't queasied. */
@keyframes spec-page-turn {
  from { transform: translateX(14px); opacity: 0.4; }
  to   { transform: translateX(0);    opacity: 1;   }
}
.view.page-turn {
  animation: spec-page-turn 220ms cubic-bezier(0.2, 0.7, 0.3, 1);
}
@media (prefers-reduced-motion: reduce) {
  .view.page-turn { animation: none; }
}

/* #14 — Theme tile preview state.
   While a tile is being long-pressed, give it a soft scale-up + accent
   ring so the bartender feels their finger is "weighing" the binding.
   Releasing commits (handled in JS); sliding off reverts. */
.theme-tile.is-previewing {
  transform: scale(1.02);
  border-color: var(--accent);
  box-shadow:
    0 0 0 1px var(--accent),
    inset 0 0 0 1px var(--rule-faint);
  transition: transform 120ms cubic-bezier(0.2, 0.7, 0.3, 1),
              border-color 120ms ease,
              box-shadow 120ms ease;
}
@media (prefers-reduced-motion: reduce) {
  .theme-tile.is-previewing { transform: none; }
}

/* ============================================================
   v71 — Onboarding (first-run welcome / profile / binding)
   ============================================================ */
.onboarding { padding: 16px 8px 4px; font-family: var(--serif); color: var(--ink); }
.onboarding-eyebrow {
  font-family: var(--serif-italic); font-style: italic; font-size: 13px;
  color: var(--ink-dim); letter-spacing: 0.4px; text-align: center; margin-bottom: 12px;
}
.onboarding-title {
  font-family: var(--serif-display); font-size: 28px; line-height: 1.15;
  color: var(--ink-bright); text-align: center; margin: 0 16px 16px;
}
.onboarding-body {
  font-family: var(--serif); font-size: 14px; line-height: 1.6;
  color: var(--ink); margin: 0 16px 16px; text-align: left;
}
.onboarding-disclaimer {
  font-family: var(--serif); font-size: 12px; line-height: 1.55;
  color: var(--ink-faint); font-style: italic; margin: 0 16px 20px;
  border-top: var(--hairline) dashed var(--rule-faint);
  padding-top: 12px;
}
.onboarding-form {
  display: flex; flex-direction: column; gap: 10px; margin: 12px 16px 18px;
}
.onboarding-ctas {
  display: flex; flex-direction: row; gap: 8px; justify-content: center;
  flex-wrap: wrap; margin-top: 12px; padding: 12px 8px 4px;
  border-top: var(--hairline) solid var(--rule-faint);
}
.onboarding-ctas .btn {
  font-family: var(--serif-display); letter-spacing: 0.6px;
}
.onboarding-bindings {
  display: grid; grid-template-columns: 1fr 1fr; gap: 10px;
  margin: 8px 12px 18px;
}
.onboarding-binding {
  display: flex; flex-direction: column; gap: 8px;
  padding: 12px; background: var(--bg-2);
  border: var(--hairline) solid var(--rule); border-radius: var(--radius);
  cursor: pointer; text-align: left; font: inherit; color: var(--ink);
  -webkit-tap-highlight-color: transparent;
}
.onboarding-binding.is-active {
  border-color: var(--accent); border-width: 2px; padding: 11px;
  background: var(--surface);
}
.onboarding-binding-swatch {
  display: grid; grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr;
  width: 44px; height: 44px; border-radius: var(--radius); overflow: hidden;
  border: var(--hairline) solid var(--rule);
}
.onboarding-binding-quad { width: 100%; height: 100%; }
.onboarding-binding-name {
  font-family: var(--serif-display); font-size: 15px; color: var(--ink-bright);
}
.onboarding-binding-bar {
  font-family: var(--serif-italic); font-style: italic; font-size: 11px;
  color: var(--accent); letter-spacing: 0.2px;
}

/* ============================================================
   v75 — Create reframe: compact seed rail, Spirit door, feedback panel
   ============================================================
   The 4-door layout was cumbersome — tall tiles with blurbs each
   acted like a sub-tab, and every door pick swapped a big panel
   in/out of view. v75 collapses the rail to compact pills with
   labels only; the blurb lives only in the drawer header that
   opens below. Result: the seed rail reads as ONE affordance,
   not four sub-tabs.

   Canon is gone — replaced by a Spirit door (the way bartenders
   actually start a build). Canon-as-riff lives on cocktail recipe
   sheets now via "Riff this →".

   Below Build, a new feedback panel speaks in five voices (variant
   match, ratio coach, flavor bridge, missing dimension, seasonal
   pull) so Create stops being a slot-filler and starts being a
   senior bartender looking over the shoulder.
   ============================================================ */

/* Compact seed rail — overrides the v62 .create-doors-row grid.
   Was: 4 tall tiles (label + italic blurb) on a 1.4fr 1fr 1fr 1fr grid.
   Now: a horizontal pill strip, labels only, drawer-style. */
.create-doors-row {
  grid-template-columns: repeat(4, 1fr) !important;
  gap: 6px !important;
  padding: 4px 0 12px !important;
  margin-bottom: 10px !important;
}
.create-door-tile {
  min-height: 0 !important;
  padding: 8px 10px !important;
  border-radius: 999px !important;
  flex-direction: row !important;
  justify-content: center !important;
  align-items: center !important;
  gap: 0 !important;
  background: var(--bg-2) !important;
}
.create-door-tile .create-door-blurb {
  /* Blurb hidden in the pill itself — it surfaces only in the drawer
     header, where it can be readable. Keeps the rail tight. */
  display: none !important;
}
.create-door-tile .create-door-label {
  font-size: 11.5px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
}
.create-door-tile.on {
  background: rgba(var(--accent-rgb, 200, 152, 88), 0.14) !important;
}
@media (max-width: 540px) {
  .create-doors-row {
    grid-template-columns: repeat(4, 1fr) !important;
    gap: 4px !important;
  }
  .create-door-tile {
    padding: 7px 6px !important;
  }
  .create-door-tile .create-door-label {
    font-size: 10.5px;
    letter-spacing: 1px;
  }
}

/* === Spirit door (v75 — replaces Canon door) === */
.spirit-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 8px;
  margin-bottom: 16px;
}
.spirit-tile {
  background: transparent;
  border: 1px solid var(--rule-faint);
  border-radius: 6px;
  padding: 10px 12px;
  text-align: left;
  cursor: pointer;
  font-family: inherit;
  color: var(--ink);
  display: flex;
  flex-direction: column;
  gap: 3px;
  transition: border-color 120ms ease, background 120ms ease;
}
.spirit-tile:hover {
  border-color: var(--accent);
  background: rgba(var(--accent-rgb, 200, 152, 88), 0.04);
}
.spirit-tile.on {
  border-color: var(--accent);
  background: rgba(var(--accent-rgb, 200, 152, 88), 0.10);
}
.spirit-tile-name {
  font-family: var(--serif-display);
  font-size: 16px;
  color: var(--ink-bright);
  letter-spacing: 0.3px;
}
.spirit-tile-flavors {
  font-size: 11.5px;
  color: var(--ink-dim);
  font-style: italic;
  font-family: var(--serif-italic);
}

.spirit-empty {
  padding: 14px 12px;
  font-style: italic;
  font-family: var(--serif-italic);
  color: var(--ink-dim);
  font-size: 13.5px;
  text-align: center;
  border-top: var(--hairline) dashed var(--rule-faint);
  margin-top: 4px;
}
.spirit-suggest-h {
  font-family: var(--serif-italic);
  font-style: italic;
  font-size: 13.5px;
  color: var(--ink-dim);
  margin: 6px 0 8px;
}
.spirit-suggest-h strong {
  color: var(--accent);
  font-style: normal;
  font-family: var(--serif-display);
  letter-spacing: 0.3px;
}
.spirit-suggest-row {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 8px;
  margin-bottom: 14px;
}
@media (max-width: 540px) {
  .spirit-suggest-row { grid-template-columns: 1fr; }
}
.spirit-suggest-tile {
  background: transparent;
  border: 1px solid var(--rule-faint);
  border-radius: 6px;
  padding: 12px;
  cursor: pointer;
  text-align: left;
  font-family: inherit;
  color: var(--ink);
  display: flex;
  flex-direction: column;
  gap: 4px;
  transition: border-color 120ms ease, background 120ms ease;
}
.spirit-suggest-tile:hover {
  border-color: var(--accent);
  background: rgba(var(--accent-rgb, 200, 152, 88), 0.05);
}
.spirit-suggest-tile.primary {
  border-color: var(--rule-gold);
}
.spirit-suggest-name {
  font-family: var(--serif-display);
  font-size: 15px;
  color: var(--ink-bright);
}
.spirit-suggest-blurb {
  font-size: 11.5px;
  line-height: 1.4;
  color: var(--ink-dim);
  font-style: italic;
  font-family: var(--serif-italic);
}
.spirit-exemplars-h {
  font-size: 11px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin: 14px 0 8px;
  border-top: var(--hairline) dashed var(--rule-faint);
  padding-top: 12px;
}
.spirit-exemplars {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.spirit-exemplar-chip {
  background: transparent;
  border: 1px solid var(--rule-faint);
  border-radius: 999px;
  padding: 4px 10px;
  font-family: var(--serif-italic);
  font-style: italic;
  font-size: 12.5px;
  color: var(--ink);
  cursor: pointer;
  transition: border-color 120ms ease, background 120ms ease;
}
.spirit-exemplar-chip:hover {
  border-color: var(--accent);
  background: rgba(var(--accent-rgb, 200, 152, 88), 0.05);
}

/* === Feedback panel (v75 — "senior bartender voice") === */
.fb-panel {
  margin: 18px 0 14px;
  border-top: var(--hairline) solid var(--rule-faint);
  padding-top: 14px;
}
.fb-panel-h {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 10px;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 10px;
}
.fb-panel-h-mark {
  font-size: 7px;
  line-height: 1;
  color: var(--accent);
}
/* v341 — render the theme's ornament glyph (Ember ✦, Pineapple ❁, etc.)
   instead of the hardcoded ◆ that was in the JS. */
.fb-panel-h-mark::before { content: var(--ornament-divider, "✦"); }
.fb-cards {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.fb-card {
  background: rgba(var(--accent-rgb, 200, 152, 88), 0.04);
  border-left: 2px solid var(--accent);
  border-radius: 4px;
  padding: 10px 12px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.fb-card-label {
  font-size: 9.5px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--accent);
  font-weight: 600;
}
.fb-card-body {
  font-family: var(--serif);
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--ink);
}
.fb-card-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}
.fb-tag {
  font-family: var(--serif-italic);
  font-style: italic;
  font-size: 11px;
  color: var(--ink-dim);
  padding: 1px 8px;
  border: 1px solid var(--rule-faint);
  border-radius: 999px;
}
.fb-link {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  color: var(--accent);
  text-decoration: underline;
  text-decoration-color: var(--rule-gold);
  text-underline-offset: 2px;
  cursor: pointer;
}
.fb-link:hover {
  color: var(--accent-2);
}
/* Tone the cards by voice so the bartender clocks at-a-glance which
   note is firing. Variant = gold (it's praise), Ratio = warm (it's
   correction), Bridge = neutral, Missing = warning, Seasonal = sage. */
.fb-card.fb-variant { border-left-color: var(--brass); background: rgba(var(--brass-rgb, 201, 161, 77), 0.06); }
.fb-card.fb-ratio { border-left-color: var(--copper); background: rgba(var(--accent-rgb, 200, 152, 88), 0.05); }
.fb-card.fb-bridge { border-left-color: var(--accent); background: rgba(var(--accent-rgb, 200, 152, 88), 0.04); }
.fb-card.fb-missing { border-left-color: var(--maraschino); background: rgba(var(--maraschino-rgb, 153, 68, 58), 0.05); }
.fb-card.fb-seasonal { border-left-color: var(--bottle); background: rgba(var(--bottle-rgb, 107, 136, 86), 0.06); }

/* ============================================================
   v74 — Page-edge gilding on cocktail cards
   ============================================================
   The diagnosis: Connaught reads as a different world because
   you feel its cool palette everywhere — the spirit-band on the
   left edge of every card. The other bindings have palettes but
   no second "signature moment." v74 adds one: a thin gilded line
   on the RIGHT edge of every cocktail card, theme-colored. The
   spirit band still tells you what's in the drink. The page edge
   tells you what edition of the book you're reading. Subtle, but
   present on every card on every screen.

   --page-edge-color is declared per theme block. The pseudo sits
   below the dog-ear (z-index ≤ 0) so favorites still read on top.
   ============================================================ */
.cocktail-card::after {
  content: "";
  position: absolute;
  right: 0;
  top: 6px;
  bottom: 6px;
  width: 1.5px;
  background: linear-gradient(180deg,
    transparent 0%,
    var(--page-edge-color, var(--rule-gold)) 18%,
    var(--page-edge-color, var(--rule-gold)) 82%,
    transparent 100%);
  pointer-events: none;
  opacity: 0.8;
  transition: opacity 200ms ease, width 200ms ease;
}
.cocktail-card:hover::after {
  opacity: 1;
  width: 2px;
}
@media print {
  /* Page-edge is a screen affordance. Printed paper has its own
     physical edge — don't double it up with ink. */
  .cocktail-card::after { display: none !important; }
}

/* ============================================================
   v76 — RESUME / PORTFOLIO BUILDER
   ============================================================
   Career infrastructure for bartenders. Daily journaling becomes
   a living portfolio that can be exported to a 1-page resume PDF
   or multi-page portfolio PDF, themed in the active binding so
   the document is identifiably theirs.

   Two surfaces:
     1. Screen editor (.resume-stats, .resume-section, .resume-field…)
     2. Print layout  (.resume-print, .resume-print-section…)
   The print stylesheet near the bottom of this block flips display
   when body.printing-resume is set, hiding the app shell and
   showing the .resume-print-root injected into <body>.
   ============================================================ */

/* === Editor: stats panel === */
.resume-stats {
  margin: 0 0 18px;
  padding: 14px 16px;
  background: rgba(var(--accent-rgb, 200, 152, 88), 0.05);
  border: 1px solid var(--rule-faint);
  border-radius: 6px;
}
.resume-stats-h {
  display: flex; align-items: center; gap: 8px;
  font-size: 10px; letter-spacing: 1.6px; text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 10px;
}
.resume-stats-h-mark { font-size: 7px; line-height: 1; }
/* v341 — render the theme's ornament glyph (Ember ✦, Pineapple ❁,
   Aperitivo flower, etc.) instead of the hardcoded ◆ that was in JS. */
.resume-stats-h-mark::before { content: var(--ornament-divider, "✦"); }
.resume-stats-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
  margin-bottom: 8px;
}
@media (max-width: 540px) {
  .resume-stats-grid { grid-template-columns: repeat(2, 1fr); }
}
.resume-stat {
  display: flex; flex-direction: column; gap: 2px;
  padding: 6px 4px;
  border-left: 2px solid var(--rule-gold);
  padding-left: 10px;
}
.resume-stat-value {
  font-family: var(--serif-display);
  font-size: 24px;
  line-height: 1;
  color: var(--ink-bright);
  letter-spacing: 0.5px;
}
.resume-stat-label {
  font-size: 11px;
  letter-spacing: 0.5px;
  text-transform: lowercase;
  color: var(--ink-dim);
  font-family: var(--serif-italic);
  font-style: italic;
}
.resume-stat-sub {
  font-size: 10.5px;
  color: var(--ink-faint);
  font-family: var(--sans);
  margin-top: 2px;
}
.resume-stats-meta {
  font-family: var(--serif-italic);
  font-style: italic;
  font-size: 12px;
  color: var(--ink-dim);
  border-top: var(--hairline) dashed var(--rule-faint);
  padding-top: 8px;
  margin-top: 6px;
}

/* === Editor: sections === */
.resume-section-h {
  margin: 22px 0 10px;
  padding-bottom: 6px;
  border-bottom: var(--hairline) solid var(--rule-faint);
}
.resume-section-h h2 {
  font-family: var(--serif-display);
  font-size: 20px;
  color: var(--ink-bright);
  margin: 0 0 4px;
  letter-spacing: 0.3px;
}
.resume-section-blurb {
  font-family: var(--serif-italic);
  font-style: italic;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--ink-dim);
  margin: 0;
}
.resume-section {
  display: flex; flex-direction: column; gap: 10px;
}
.resume-empty {
  padding: 12px 14px;
  font-family: var(--serif-italic);
  font-style: italic;
  font-size: 13px;
  color: var(--ink-faint);
  background: rgba(var(--accent-rgb, 200, 152, 88), 0.03);
  border-left: 2px solid var(--rule-faint);
  border-radius: 4px;
}

/* === Editor: fields === */
.resume-field {
  display: flex; flex-direction: column; gap: 4px;
}
.resume-field-label {
  font-size: 10px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--ink-faint);
  font-weight: 600;
}
.resume-field-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 10px;
}

/* === Editor: chip pickers (spirit focus + techniques) === */
.resume-chip-picker {
  background: rgba(var(--accent-rgb, 200, 152, 88), 0.02);
  padding: 12px;
  border-radius: 6px;
  border: 1px solid var(--rule-faint);
}
.resume-chip-picker-h {
  font-family: var(--serif-display);
  font-size: 14px;
  color: var(--ink-bright);
  margin-bottom: 4px;
}
.resume-chip-picker-hint {
  font-family: var(--serif-italic);
  font-style: italic;
  font-size: 12px;
  color: var(--ink-dim);
  margin-bottom: 10px;
}
.resume-chip-selected {
  display: flex; flex-wrap: wrap; gap: 6px;
  margin-bottom: 10px;
  min-height: 32px;
}
.resume-chip-empty {
  font-family: var(--serif-italic);
  font-style: italic;
  font-size: 12px;
  color: var(--ink-faint);
}
.resume-chip-suggested-h {
  font-size: 10px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin: 8px 0 6px;
}
.resume-chip-suggested {
  display: flex; flex-wrap: wrap; gap: 6px;
  margin-bottom: 8px;
}
.resume-chip {
  background: transparent;
  border: 1px solid var(--rule-faint);
  border-radius: 999px;
  padding: 4px 10px;
  font-family: var(--serif-italic);
  font-style: italic;
  font-size: 12.5px;
  color: var(--ink);
  cursor: pointer;
  transition: border-color 120ms, background 120ms, color 120ms;
}
.resume-chip:hover {
  border-color: var(--accent);
  background: rgba(var(--accent-rgb, 200, 152, 88), 0.06);
}
.resume-chip.on {
  background: rgba(var(--accent-rgb, 200, 152, 88), 0.18);
  border-color: var(--accent);
  color: var(--ink-bright);
}
.resume-chip-x { opacity: 0.7; }
.resume-chip-add {
  margin-top: 4px;
  font-size: 13px;
}

/* === Editor: work history rows === */
.resume-work-list { display: flex; flex-direction: column; gap: 14px; }
.resume-work-row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 10px;
  padding: 12px;
  border: 1px solid var(--rule-faint);
  border-radius: 6px;
}
.resume-work-row-fields {
  display: flex; flex-direction: column; gap: 10px;
}
.resume-work-row-actions {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
}
.resume-current-toggle {
  display: flex; align-items: center; gap: 6px;
  font-size: 13px; color: var(--ink-dim);
  font-family: var(--serif-italic);
  font-style: italic;
}
.resume-row-remove { color: var(--maraschino); }

/* === Editor: cert / award / ref rows === */
.resume-cert-list,
.resume-award-list,
.resume-ref-list {
  display: flex; flex-direction: column; gap: 8px;
}
.resume-cert-row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 8px 14px;
  padding: 10px 12px;
  border: 1px solid var(--rule-faint);
  border-radius: 4px;
  align-items: center;
}
.resume-cert-name {
  font-family: var(--serif-display);
  font-size: 14.5px;
  color: var(--ink-bright);
}
.resume-cert-name a { color: var(--accent); }
.resume-cert-meta {
  grid-column: 1 / 2;
  font-family: var(--serif-italic);
  font-style: italic;
  font-size: 12px;
  color: var(--ink-dim);
}
.resume-cert-row > .btn { grid-row: 1 / 3; grid-column: 2; }

/* === Editor: signature cocktails === */
.resume-sig-list { display: flex; flex-direction: column; gap: 8px; }
.resume-sig-row {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border: 1px solid var(--rule-faint);
  border-radius: 6px;
  background: rgba(var(--accent-rgb, 200, 152, 88), 0.03);
}
.resume-sig-row.missing {
  display: flex; justify-content: space-between;
  color: var(--ink-faint); font-style: italic;
}
.resume-sig-rank {
  font-family: var(--serif-display);
  font-size: 22px;
  color: var(--accent);
  letter-spacing: 0;
  min-width: 28px;
  text-align: center;
}
.resume-sig-body { min-width: 0; }
.resume-sig-name {
  font-family: var(--serif-display);
  font-size: 15.5px;
  color: var(--ink-bright);
}
.resume-sig-meta {
  font-family: var(--serif-italic);
  font-style: italic;
  font-size: 12px;
  color: var(--ink-dim);
  margin-top: 2px;
}
.resume-sig-actions { display: flex; gap: 4px; }

.resume-sig-picker-list {
  display: flex; flex-direction: column; gap: 4px;
  margin-top: 8px; max-height: 60vh; overflow-y: auto;
}
.resume-sig-picker-row {
  background: transparent;
  border: 1px solid var(--rule-faint);
  border-radius: 4px;
  padding: 10px 12px;
  text-align: left;
  font-family: inherit;
  color: var(--ink);
  cursor: pointer;
}
.resume-sig-picker-row:hover {
  border-color: var(--accent);
  background: rgba(var(--accent-rgb, 200, 152, 88), 0.05);
}
.resume-sig-picker-row.selected {
  border-color: var(--accent);
  background: rgba(var(--accent-rgb, 200, 152, 88), 0.12);
}
.resume-sig-picker-name {
  font-family: var(--serif-display);
  font-size: 14.5px;
  color: var(--ink-bright);
}
.resume-sig-picker-pick {
  font-family: var(--serif-italic);
  font-style: italic;
  font-size: 12px;
  color: var(--accent);
}
.resume-sig-picker-meta {
  font-family: var(--serif-italic);
  font-style: italic;
  font-size: 11.5px;
  color: var(--ink-dim);
  margin-top: 2px;
}

/* === Editor: export row === */
.resume-export-row {
  display: flex; flex-wrap: wrap; gap: 10px;
  margin: 28px 0 36px;
  padding: 18px 0 0;
  border-top: var(--hairline) solid var(--rule-faint);
}
.resume-export-row .btn {
  font-family: var(--serif-display);
  letter-spacing: 0.4px;
}

/* ============================================================
   v76 — PRINT LAYOUT (resume + portfolio PDF)
   ============================================================
   When body has class .printing-resume, we hide everything except
   the injected .resume-print-root. The print sheet uses the theme
   tokens already on :root / [data-theme="X"] so the PDF carries
   the active binding's voice (Bemelmans walnut, Connaught Deco,
   Maison Premiere sage, Smuggler's Cove rum amber).
   ============================================================ */
.resume-print-root { display: none; }
body.printing-resume #app,
body.printing-resume #view,
body.printing-resume .bottom-tabs,
body.printing-resume .app-header,
body.printing-resume .sheet-backdrop,
body.printing-resume .sheet,
body.printing-resume .toast,
body.printing-resume .boot-splash { display: none !important; }
body.printing-resume .resume-print-root {
  display: block;
  position: relative;
  z-index: 9999;
  background: #fff;
  color: #111;
  min-height: 100vh;
}
body.printing-resume::before,
body.printing-resume::after { display: none !important; }

.resume-print {
  max-width: 8.5in;
  margin: 0 auto;
  padding: 0.5in 0.6in;
  background: #fff;
  color: #111;
  font-family: "Iowan Old Style", "Hoefler Text", "Cormorant Garamond", Georgia, serif;
  font-size: 11pt;
  line-height: 1.45;
}

.resume-print-header {
  border-bottom: 2pt solid var(--accent, #b8860b);
  padding-bottom: 14pt;
  margin-bottom: 18pt;
}
.resume-print-name {
  font-family: var(--serif-display, "Bodoni 72", "Didot", Georgia, serif);
  font-size: 32pt;
  line-height: 1;
  letter-spacing: 0.5pt;
  color: #111;
}
.resume-print-tagline {
  font-family: var(--serif-italic, "Big Caslon", Georgia, serif);
  font-style: italic;
  font-size: 13pt;
  color: #333;
  margin-top: 4pt;
}
.resume-print-line {
  font-size: 10pt;
  color: #444;
  margin-top: 8pt;
  letter-spacing: 0.2pt;
}

.resume-print-section {
  margin-bottom: 16pt;
  page-break-inside: avoid;
}
.resume-print-section h3 {
  font-family: var(--serif-display, "Bodoni 72", Georgia, serif);
  font-size: 12pt;
  letter-spacing: 2pt;
  text-transform: uppercase;
  margin: 0 0 8pt;
  color: var(--accent, #b8860b);
  border-bottom: 0.5pt solid #ccc;
  padding-bottom: 3pt;
}
.resume-print-section p {
  margin: 0 0 6pt;
  font-size: 11pt;
}

.resume-print-job {
  margin-bottom: 10pt;
  page-break-inside: avoid;
}
.resume-print-job-line1 {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font-size: 11.5pt;
}
.resume-print-job-role { font-weight: 600; }
.resume-print-job-venue { font-style: italic; }
.resume-print-job-dates {
  font-size: 10pt;
  color: #555;
}
.resume-print-job-city {
  font-size: 10pt;
  color: #666;
  font-style: italic;
}
.resume-print-job-body {
  font-size: 10.5pt;
  margin-top: 3pt;
  color: #222;
}

.resume-print-skill-line { font-size: 11pt; margin-bottom: 4pt; }
.resume-print-cert { font-size: 11pt; margin-bottom: 4pt; }

.resume-print-page-break {
  page-break-before: always;
}
.resume-print-ing-list {
  margin: 4pt 0 0 18pt;
  padding: 0;
  font-size: 11pt;
  list-style: square;
}

.resume-print-footer {
  margin-top: 24pt;
  padding-top: 10pt;
  border-top: 0.5pt solid #ccc;
  text-align: center;
  font-size: 9pt;
  color: #777;
  font-style: italic;
  letter-spacing: 0.5pt;
}
.resume-print-edition::before {
  content: var(--print-edition-name, "Bemelmans");
  font-weight: 600;
  font-style: normal;
  color: var(--accent, #b8860b);
  letter-spacing: 1pt;
}

@media print {
  @page { margin: 0.5in 0.6in; }

  /* v104 — COMPREHENSIVE PRINT RESET.
     The body has multiple stacked dark backgrounds (radial gradients, paper-
     grain ::before, vignette ::after, themed texture overlays). Without
     explicit overrides, all of these print as solid black/dark blocks behind
     the white content card. This block kills all of them when either of the
     two print modes is active (resume or menu). */
  body.printing-resume,
body.printing-menu,
html:has(body.printing-resume),
html:has(body.printing-menu) {
    background: #ffffff !important;
    background-image: none !important;
    color: #111 !important;
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }
  /* Suppress body::before (paper grain + texture overlay) and
     body::after (vignette darkening) — both render as dark blocks. */
  body.printing-resume::before,
body.printing-resume::after,
body.printing-menu::before,
body.printing-menu::after {
    display: none !important;
    background: none !important;
    content: none !important;
  }
  /* Make sure the html element doesn't carry any background color either */
  html {
    background: #ffffff !important;
  }
}

/* ============================================================
   v102 — Menu PDF export
   Two variants: .menu-print-guest (front-of-house menu) and
   .menu-print-bar (back-of-house spec book). Both use the same
   shell and root container.
   ============================================================ */
.menu-print-root { display: none; }
body.printing-menu > *:not(.menu-print-root) { display: none !important; }
body.printing-menu .menu-print-root { display: block; }
body.printing-menu {
  background: #fff !important;
  color: #111 !important;
}

.menu-print {
  max-width: 8.5in;
  margin: 0 auto;
  padding: 0.5in 0.6in;
  background: #fff;
  color: #111;
  font-family: "Iowan Old Style", "Hoefler Text", "Cormorant Garamond", Georgia, serif;
  font-size: 11pt;
  line-height: 1.5;
}
.menu-print-header {
  text-align: center;
  margin-bottom: 28pt;
  padding-bottom: 18pt;
  border-bottom: 1pt solid var(--accent, #caa45a);
}
.menu-print-eyebrow {
  font-family: var(--serif-italic, Georgia, serif);
  font-style: italic;
  font-size: 10pt;
  letter-spacing: 0.1pt;
  color: var(--accent, #caa45a);
  margin-bottom: 4pt;
}
.menu-print-title {
  font-family: var(--serif-display, "Didot", "Bodoni 72", Georgia, serif);
  font-size: 36pt;
  font-weight: 500;
  margin: 0 0 6pt;
  letter-spacing: 0.5pt;
  color: #1a1a1a;
}
.menu-print-concept {
  font-family: var(--serif-italic, Georgia, serif);
  font-style: italic;
  font-size: 12pt;
  color: #555;
  max-width: 5.5in;
  margin: 0 auto;
  line-height: 1.45;
}

.menu-print-footer {
  text-align: center;
  margin-top: 32pt;
  padding-top: 12pt;
  border-top: 0.5pt solid #ccc;
  font-size: 9pt;
  font-style: italic;
  letter-spacing: 0.5pt;
  color: #888;
}

/* --------------------------------------
   GUEST MENU — clean, readable, no recipes
-------------------------------------- */
.menu-print-guest .menu-print-list {
  display: grid;
  grid-template-columns: 1fr;
  gap: 16pt;
}
.menu-print-entry {
  page-break-inside: avoid;
}
.menu-print-entry-header {
  display: flex;
  align-items: baseline;
  gap: 8pt;
  margin-bottom: 4pt;
}
.menu-print-entry-name {
  font-family: var(--serif-display, "Didot", "Bodoni 72", Georgia, serif);
  font-size: 16pt;
  font-weight: 500;
  margin: 0;
  letter-spacing: 0.3pt;
  color: #1a1a1a;
  flex: 0 0 auto;
}
.menu-print-entry-dots {
  flex: 1 1 auto;
  border-bottom: 1pt dotted #999;
  margin-bottom: 4pt;
}
.menu-print-entry-price {
  font-family: var(--serif-display, "Didot", "Bodoni 72", Georgia, serif);
  font-size: 14pt;
  font-weight: 500;
  color: var(--accent, #caa45a);
  flex: 0 0 auto;
}
.menu-print-entry-desc {
  font-family: var(--serif-italic, Georgia, serif);
  font-style: italic;
  font-size: 11pt;
  color: #333;
  margin: 2pt 0;
  line-height: 1.45;
}
.menu-print-entry-ing {
  font-size: 10pt;
  color: #777;
  margin: 4pt 0 0;
  font-variant: small-caps;
  letter-spacing: 0.5pt;
}

/* --------------------------------------
   BAR SPEC BOOK — full recipes + notes
-------------------------------------- */
.menu-print-summary {
  margin-bottom: 24pt;
  padding: 14pt;
  border: 0.5pt solid #ccc;
  background: #f7f3eb;
}
.menu-print-metrics {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12pt;
  margin-bottom: 12pt;
  padding-bottom: 10pt;
  border-bottom: 0.5pt solid #ddd;
}
.menu-print-metric {
  text-align: center;
}
.menu-print-metric-value {
  font-family: var(--serif-display, "Didot", Georgia, serif);
  font-size: 20pt;
  font-weight: 600;
  color: var(--accent, #caa45a);
  line-height: 1;
}
.menu-print-metric-label {
  font-size: 9pt;
  text-transform: uppercase;
  letter-spacing: 0.5pt;
  color: #777;
  margin-top: 2pt;
}
.menu-print-seq,
.menu-print-skus {
  font-size: 10pt;
  line-height: 1.5;
  color: #444;
  margin-top: 6pt;
}

.menu-print-spec {
  page-break-inside: avoid;
  margin-bottom: 18pt;
  padding-bottom: 12pt;
  border-bottom: 0.5pt solid #ddd;
}
.menu-print-spec:last-child { border-bottom: none; }
.menu-print-spec-head {
  display: flex;
  align-items: baseline;
  gap: 10pt;
  margin-bottom: 4pt;
}
.menu-print-spec-num {
  font-size: 10pt;
  color: #888;
  font-family: var(--mono, "Courier New", monospace);
  flex: 0 0 auto;
  letter-spacing: 0.5pt;
}
.menu-print-spec-name {
  font-family: var(--serif-display, "Didot", "Bodoni 72", Georgia, serif);
  font-size: 14pt;
  font-weight: 500;
  margin: 0;
  letter-spacing: 0.3pt;
  color: #1a1a1a;
  flex: 1 1 auto;
}
.menu-print-spec-price {
  font-size: 12pt;
  font-weight: 600;
  color: var(--accent, #caa45a);
}
.menu-print-spec-tags {
  font-size: 9pt;
  text-transform: uppercase;
  letter-spacing: 0.5pt;
  color: #888;
  margin: 2pt 0 6pt;
}
.menu-print-spec-desc {
  font-style: italic;
  font-size: 10.5pt;
  color: #444;
  margin: 0 0 6pt;
  line-height: 1.5;
}
.menu-print-spec-ing {
  list-style: none;
  margin: 6pt 0;
  padding: 0;
  font-size: 10pt;
  line-height: 1.6;
}
.menu-print-spec-ing li {
  display: block;
}
.menu-print-spec-amount {
  display: inline-block;
  min-width: 60pt;
  color: #777;
  font-family: var(--mono, "Courier New", monospace);
  font-size: 9.5pt;
}
.menu-print-spec-iname {
  color: #1a1a1a;
}
.menu-print-spec-meta {
  font-size: 9.5pt;
  color: #555;
  margin: 4pt 0;
}
.menu-print-spec-meta span {
  margin-right: 16pt;
}
.menu-print-spec-method {
  font-size: 9.5pt;
  color: #333;
  margin: 4pt 0 2pt;
  line-height: 1.45;
}
.menu-print-spec-note {
  font-size: 9.5pt;
  color: #555;
  font-style: italic;
  margin: 4pt 0 0;
  line-height: 1.45;
}
/* v448 — Attribution line in bar spec book. Same typographic family as
   .menu-print-spec-note (italic, dimmer color) but with a left rule to
   visually separate it as "citation metadata" rather than "instructional
   note." Renders the v428 citation work (source/author/year/book) on
   the printed page where it belongs. */
.menu-print-spec-attrib {
  font-size: 9pt;
  color: #666;
  font-style: italic;
  margin: 6pt 0 0;
  padding-left: 8pt;
  border-left: 1.5pt solid #c8a368;
  line-height: 1.45;
}
.menu-print-spec-attrib strong {
  font-style: normal;
  color: #888;
  font-size: 7.5pt;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

@media print {
  @page { margin: 0.5in 0.6in; }
}

/* ============================================================
   v97 — Resume export templates: Spine, Modern
   The base .resume-print styles above are the Classic template.
   These selectors override typography, dividers, and layout for
   the two alternative templates.
   ============================================================ */

/* --------------------------------------
   SPINE — vintage book aesthetic matching the Embury icon.
   Generous serif margins, illuminated drop-cap on the name,
   ornamental fleuron dividers between sections, hairline rules
   bracketing the wordmark, single-column.
-------------------------------------- */
.resume-print.template-spine {
  font-family: "Iowan Old Style", "Hoefler Text", "Cormorant Garamond", Georgia, serif;
  padding: 0.75in 0.9in;
  color: #1f160e;
}
.resume-print.template-spine .resume-print-header {
  border-bottom: none;
  text-align: center;
  padding-bottom: 18pt;
  margin-bottom: 24pt;
  position: relative;
}
.resume-print.template-spine .resume-print-header::before,
.resume-print.template-spine .resume-print-header::after {
  content: "";
  display: block;
  height: 1px;
  background: #caa45a;
  margin: 0 auto;
}
.resume-print.template-spine .resume-print-header::before {
  width: 60%;
  margin-bottom: 4pt;
}
.resume-print.template-spine .resume-print-header::after {
  width: 30%;
  margin-top: 12pt;
}
.resume-print.template-spine .resume-print-name {
  font-family: "Didot", "Bodoni 72", "Hoefler Text", Georgia, serif;
  font-size: 36pt;
  font-weight: 500;
  font-style: italic;
  letter-spacing: 1.5pt;
  color: #2a1c14;
  text-align: center;
  margin-bottom: 8pt;
}
.resume-print.template-spine .resume-print-tagline {
  font-style: italic;
  text-align: center;
  font-size: 12pt;
  color: #5a4530;
  margin-top: 0;
}
.resume-print.template-spine .resume-print-line {
  text-align: center;
  font-size: 9.5pt;
  letter-spacing: 1pt;
  text-transform: uppercase;
  color: #6b5440;
  margin-top: 14pt;
}
.resume-print.template-spine .resume-print-section {
  margin-bottom: 22pt;
}
.resume-print.template-spine .resume-print-section h3 {
  font-family: "Didot", "Bodoni 72", Georgia, serif;
  font-size: 11pt;
  letter-spacing: 4pt;
  text-transform: uppercase;
  text-align: center;
  color: #2a1c14;
  border-bottom: none;
  margin: 0 0 12pt;
  padding-bottom: 0;
  position: relative;
}
.resume-print.template-spine .resume-print-section h3::after {
  content: "❦";
  display: block;
  text-align: center;
  font-size: 12pt;
  color: #caa45a;
  letter-spacing: 0;
  margin-top: 6pt;
  font-weight: normal;
}
.resume-print.template-spine .resume-print-section p {
  font-size: 11pt;
  line-height: 1.55;
  text-align: justify;
}
.resume-print.template-spine .resume-print-job-line1 {
  font-size: 12pt;
  font-family: "Didot", Georgia, serif;
}
.resume-print.template-spine .resume-print-job-role { font-weight: 500; }
.resume-print.template-spine .resume-print-job-venue {
  font-style: italic;
  color: #5a4530;
}
.resume-print.template-spine .resume-print-job-dates {
  font-size: 9.5pt;
  letter-spacing: 0.5pt;
  color: #6b5440;
}
.resume-print.template-spine .resume-print-job-body {
  font-size: 10.5pt;
  line-height: 1.55;
  margin-top: 6pt;
  color: #2a1c14;
}

/* --------------------------------------
   MODERN — craft-bar minimalist resume template.
   Mixed serif (display) + sans (body), two-column skills row,
   aggressive whitespace, no decorative dividers — just hairline
   rules and clean typography hierarchy.
-------------------------------------- */
.resume-print.template-modern {
  font-family: "Inter", "Helvetica Neue", -apple-system, sans-serif;
  padding: 0.6in 0.8in;
  color: #1a1a1a;
}
.resume-print.template-modern .resume-print-header {
  border-bottom: 0.5pt solid #1a1a1a;
  padding-bottom: 16pt;
  margin-bottom: 24pt;
}
.resume-print.template-modern .resume-print-name {
  font-family: "Iowan Old Style", "Hoefler Text", "Cormorant Garamond", Georgia, serif;
  font-size: 38pt;
  font-weight: 600;
  letter-spacing: -1pt;
  line-height: 1;
  color: #1a1a1a;
}
.resume-print.template-modern .resume-print-tagline {
  font-family: "Iowan Old Style", Georgia, serif;
  font-style: italic;
  font-size: 13pt;
  color: #555;
  margin-top: 6pt;
}
.resume-print.template-modern .resume-print-line {
  font-size: 9pt;
  color: #555;
  font-weight: 400;
  margin-top: 12pt;
  letter-spacing: 0;
}
.resume-print.template-modern .resume-print-section {
  margin-bottom: 20pt;
}
.resume-print.template-modern .resume-print-section h3 {
  font-family: inherit;
  font-size: 9pt;
  font-weight: 700;
  letter-spacing: 2pt;
  text-transform: uppercase;
  color: #1a1a1a;
  border-bottom: none;
  padding-bottom: 0;
  margin: 0 0 10pt;
}
.resume-print.template-modern .resume-print-section p {
  font-size: 10.5pt;
  line-height: 1.55;
  color: #1a1a1a;
}
.resume-print.template-modern .resume-print-job-line1 {
  font-size: 11pt;
  font-weight: 600;
}
.resume-print.template-modern .resume-print-job-role { font-weight: 600; }
.resume-print.template-modern .resume-print-job-venue {
  font-weight: 400;
  font-style: normal;
  color: #555;
}
.resume-print.template-modern .resume-print-job-dates {
  font-size: 9.5pt;
  color: #555;
  font-weight: 400;
}
.resume-print.template-modern .resume-print-job-body {
  font-size: 10pt;
  line-height: 1.55;
  margin-top: 4pt;
  color: #1a1a1a;
}
/* Two-column skill list when there's content for both spirits and techniques */
.resume-print.template-modern .resume-print-skill-line {
  display: inline-block;
  width: 48%;
  vertical-align: top;
  font-size: 10pt;
}

/* ============================================================
   v80 — Password auth UI (tabs + alt links + skip link)
   ============================================================
   Lives on the onboarding auth gate AND the Settings sign-in section.
   Both reuse the same affordances so the surfaces feel consistent.
   ============================================================ */
.auth-tab-strip {
  display: flex;
  gap: 0;
  border-bottom: 1px solid var(--rule-faint);
  margin: 12px 0 14px;
}
.auth-tab {
  flex: 1;
  background: transparent;
  border: 0;
  border-bottom: 2px solid transparent;
  padding: 10px 12px;
  font-family: var(--serif-display);
  font-size: 12px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--ink-dim);
  cursor: pointer;
  transition: color 120ms ease, border-color 120ms ease;
}
.auth-tab:hover { color: var(--ink); }
.auth-tab.is-active {
  color: var(--accent);
  border-bottom-color: var(--accent);
}
.auth-alt-row {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  padding: 8px 4px 0;
  flex-wrap: wrap;
}
.auth-alt-link {
  background: transparent;
  border: 0;
  padding: 4px 0;
  font-family: var(--serif-italic);
  font-style: italic;
  font-size: 12.5px;
  color: var(--ink-dim);
  text-decoration: underline;
  text-decoration-color: var(--rule-faint);
  text-underline-offset: 3px;
  cursor: pointer;
  transition: color 120ms ease;
}
.auth-alt-link:hover { color: var(--accent); }
.auth-skip-link {
  background: transparent;
  border: 0;
  padding: 6px 8px;
  font-family: var(--serif-italic);
  font-style: italic;
  font-size: 12px;
  color: var(--ink-faint);
  text-decoration: underline;
  text-decoration-color: var(--rule-faint);
  text-underline-offset: 3px;
  cursor: pointer;
  transition: color 120ms ease;
}
.auth-skip-link:hover { color: var(--ink-dim); }

/* ============================================================
   v87 — Saved pip (ambient autosave confirmation)
   ============================================================
   A small pill that flashes "✓ Saved" briefly after a user edit
   has been persisted locally. Pinned top-right under the app
   header so the user can see it without leaving the input.
   Calls coalesce via a 1.1s timer in ui.js — rapid typing
   produces one steady "Saved" that fades when the user pauses.
   ============================================================ */
.saved-pip {
  position: fixed;
  top: calc(env(safe-area-inset-top, 0px) + 70px);
  right: 16px;
  z-index: 9999;
  padding: 5px 12px;
  background: rgba(20, 14, 8, 0.92);
  color: rgba(var(--accent-rgb, 201, 161, 77), 0.95);
  border: 1px solid rgba(var(--accent-rgb, 201, 161, 77), 0.45);
  border-radius: 999px;
  font-family: var(--serif-italic);
  font-style: italic;
  font-size: 12px;
  letter-spacing: 0.3px;
  pointer-events: none;
  opacity: 0;
  transform: translateY(-6px);
  transition: opacity 220ms ease, transform 220ms ease;
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.35);
}
.saved-pip.is-visible {
  opacity: 1;
  transform: translateY(0);
}
@media (max-width: 720px) {
  /* Sit just below the app-header on mobile too (header has slightly
     different height, but the same offset reads correctly) */
  .saved-pip {
    top: calc(env(safe-area-inset-top, 0px) + 58px);
    right: 12px;
    font-size: 11.5px;
  }
}

/* Onboarding form spacing — make the password field sit cleanly below email */
.onboarding-form .input + .input { margin-top: 8px; }

/* Settings supabase form — give the password field room */
.settings-supabase-form .input + .input { margin-top: 8px; }
.settings-supabase-form .btn { margin-top: 10px; }

/* ============================================================
   v80a — Resume first-run welcome banner
   ============================================================
   Shown at the top of the resume editor when a brand-new signup
   lands here right after onboarding. Replaces the normal intro
   blurb with a richer welcome card. The export buttons at the
   bottom are also swapped for a "Done — open Embury" CTA so the
   user has a clean way out.
   ============================================================ */
.resume-firstrun-banner {
  margin: 0 4px 18px;
  padding: 18px 20px 16px;
  background:
    linear-gradient(135deg,
      rgba(var(--accent-rgb, 200, 152, 88), 0.10) 0%,
      rgba(var(--accent-rgb, 200, 152, 88), 0.04) 100%);
  border: 1px solid var(--rule-gold);
  border-radius: 8px;
  position: relative;
  overflow: hidden;
}
.resume-firstrun-banner::before {
  content: var(--ornament-section, "❦");
  position: absolute;
  top: 10px; right: 14px;
  font-family: var(--serif-display);
  font-size: 22px;
  color: var(--accent);
  opacity: 0.4;
}
.resume-firstrun-eyebrow {
  font-family: var(--serif-italic);
  font-style: italic;
  font-size: 12px;
  color: var(--ink-dim);
  letter-spacing: 0.4px;
  margin-bottom: 4px;
}
.resume-firstrun-title {
  font-family: var(--serif-display);
  font-size: 24px;
  color: var(--ink-bright);
  margin: 0 0 8px;
  letter-spacing: 0.3px;
}
.resume-firstrun-body {
  font-family: var(--serif);
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--ink);
  margin: 0;
  max-width: 60ch;
}

/* ============================================================
   v108 — AI Tools panel on Journal (Wave 32)
   Three tools: improve a spec, generate variations, write
   tasting notes. The entry-point is a pill button on the
   Journal view header; tapping opens an AI-tools sheet of
   choice cards. Each tool flow shares a picker and a loading
   state, then a result-review sheet.
   ============================================================ */

/* Header layout for Journal — title left, AI Tools pill right.
   v517 — Wrapped in min-width media so it ONLY applies at desktop widths.
   The mobile @media (max-width: 560px) rule above flips .view-header to
   flex-direction: column, where `align-items` now controls HORIZONTAL
   placement. The unscoped center rule was overriding mobile's flex-start
   and centering the Journal title horizontally — making Journal look
   centered while every other view stayed left-bound. Caught by Joseph
   on his phone 2026-05-28. */
@media (min-width: 561px) {
  .journal-header { align-items: center; }
}
.journal-ai-btn {
  display: inline-flex; align-items: center;
  font-family: var(--sans);
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0.02em;
  padding: 7px 14px;
  border-radius: 999px;
  border: 1px solid var(--accent);
  background: linear-gradient(180deg, color-mix(in srgb, var(--accent) 12%, var(--bg)),
                                       color-mix(in srgb, var(--accent) 4%, var(--bg)));
  color: var(--accent);
  cursor: pointer;
  transition: transform 0.08s ease, box-shadow 0.15s ease;
}
.journal-ai-btn:hover {
  box-shadow: 0 4px 14px color-mix(in srgb, var(--accent) 25%, transparent);
  transform: translateY(-1px);
}
.journal-ai-btn:active { transform: translateY(0); }

/* Pill variant used for inline header buttons */
.btn-pill { border-radius: 999px; padding: 6px 14px; font-size: 12px; }

/* AI Tools sheet — grid of tappable cards */
.ai-tools-blurb,
.ai-tool-blurb {
  font-family: var(--serif-italic);
  font-style: italic;
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--ink-dim);
  margin: 0 0 16px;
  max-width: 60ch;
}
.ai-tools-grid {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.ai-tool-card {
  display: block;
  width: 100%;
  text-align: left;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: 10px;
  padding: 14px 16px;
  cursor: pointer;
  transition: border-color 0.12s ease, box-shadow 0.15s ease, transform 0.06s ease;
}
.ai-tool-card:hover {
  border-color: var(--accent);
  box-shadow: 0 4px 12px color-mix(in srgb, var(--accent) 12%, transparent);
}
.ai-tool-card:active { transform: translateY(1px); }
.ai-tool-card-title {
  font-family: var(--serif-display);
  font-size: 17px;
  color: var(--ink-bright);
  margin-bottom: 4px;
  letter-spacing: 0.2px;
}
.ai-tool-card-desc {
  font-family: var(--serif);
  font-size: 13px;
  line-height: 1.5;
  color: var(--ink-dim);
}

/* Loading state during AI requests */
.ai-loading {
  display: flex; flex-direction: column; align-items: center; gap: 16px;
  padding: 32px 16px;
  font-family: var(--serif-italic);
  font-style: italic;
  color: var(--ink-dim);
  text-align: center;
}
.ai-loading .spinner {
  width: 36px; height: 36px;
  border: 3px solid color-mix(in srgb, var(--accent) 20%, transparent);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: ai-spinner 0.8s linear infinite;
}
@keyframes ai-spinner {
  to { transform: rotate(360deg); }
}

/* Picker list used by all three tool flows */
.pick-list { display: flex; flex-direction: column; gap: 8px; }
.pick-row {
  display: block; width: 100%; text-align: left;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: 8px;
  padding: 12px 14px;
  cursor: pointer;
  transition: background 0.12s ease, border-color 0.12s ease;
}
.pick-row:hover {
  background: color-mix(in srgb, var(--accent) 6%, var(--surface));
  border-color: var(--accent);
}
.pick-row-title {
  font-family: var(--serif-display);
  font-size: 16px;
  color: var(--ink-bright);
  margin-bottom: 2px;
}
.pick-row-meta {
  font-family: var(--sans);
  font-size: 11.5px;
  color: var(--ink-faint);
  letter-spacing: 0.02em;
}

/* Variation cards in the variations result sheet */
.variation-card {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-left: 3px solid var(--accent);
  border-radius: 8px;
  padding: 14px 16px;
  margin-bottom: 14px;
}
.variation-card h3 {
  font-family: var(--serif-display);
  font-size: 18px;
  color: var(--ink-bright);
  margin: 0 0 6px;
}
.variation-change {
  font-family: var(--serif-italic);
  font-style: italic;
  font-size: 13px;
  color: var(--accent-2, var(--accent));
  margin-bottom: 10px;
  line-height: 1.45;
}

/* The "what changed" callout in the refined-spec review sheet */
.ai-change-note {
  background: color-mix(in srgb, var(--accent) 8%, var(--surface));
  border-left: 3px solid var(--accent);
  padding: 10px 14px;
  border-radius: 0 6px 6px 0;
}
.ai-change-note h4 {
  color: var(--accent);
  margin-bottom: 4px !important;
}

/* ============================================================
   v108 — Mobile UX polish (Wave 33)
   The most-asked mobile pain points, fixed in one block:
     1. iOS Safari zooms the viewport whenever an input with
        font-size < 16px is focused. Several .input rules and
        .search input use 15px. On touch viewports we bump to
        16px so focus never triggers zoom.
     2. Tap targets — small buttons (.btn-sm, .btn-icon) on
        mobile bump to min 40px height/width to clear Apple's
        38pt minimum recommendation.
     3. Sheet body bottom padding on small viewports so the
        last form field isn't visually hugged against the
        sticky footer.
     4. Sheet footer iOS safe-area already accounted for via
        --safe-bottom; we also disable rubber-banding on the
        backdrop so dismiss-by-drag is the only scroll path.
   ============================================================ */

/* iOS input-zoom fix — applies only at touch-friendly widths
   so we don't bloat desktop typography. 16px is the minimum
   font-size iOS will NOT zoom in to. */
@media (max-width: 700px) {
  .input,
textarea.input,
select.input,
.search input,
input[type="text"],
input[type="search"],
input[type="email"],
input[type="password"],
input[type="tel"],
input[type="url"],
input[type="number"],
textarea {
    font-size: 16px;
  }
}

/* Tap target floor on mobile — Apple HIG says 44pt, Material says 48dp.
   We split the difference at 40px and don't constrain rounded icon
   buttons elsewhere in the app. */
@media (max-width: 700px) {
  .btn,
.btn-pill,
.btn-sm {
    min-height: 40px;
  }
  .btn-icon {
    min-width: 40px;
    min-height: 40px;
  }
  /* Chip rows (used in many filters) get the same floor */
  /* v616 — This mobile override was SHRINKING filter chips to 36px,
     below the 44px the base .chip rule already sets — exactly backwards
     for phones, the primary bar-work device. Raised to 44px so the
     touch target is preserved on small screens. Visible padding/text
     in the base rule is unchanged. */
  .chip {
    min-height: 44px;
  }
}

/* Sheet body — give the last field breathing room on phones so it's not
   visually crushed against the sticky footer.  Also prevent the body
   from being shorter than the viewport on small screens (was 60vh max,
   which made some long forms feel cramped). */
@media (max-width: 700px) {
  .sheet-body {
    padding-bottom: 40px;
  }
  .sheet {
    /* Allow the sheet to grow to nearly the full viewport on phones,
       which gives multi-field forms enough vertical room without
       requiring nested scrolling. */
    max-height: calc(100vh - var(--safe-top) - 20px);
  }
}

/* Prevent text-selection on long-press of pill/icon buttons —
   accidental selection of "AI Tools" or other header chrome when a
   tap is just a hair long. */
.journal-ai-btn,
.btn-pill,
.btn-icon,
.fab,
.chip {
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}

/* Stop iOS Safari from rubber-banding the backdrop when the user
   drags down — they should be using the drag-handle, not the body. */
.sheet-backdrop {
  overscroll-behavior: contain;
}

/* ============================================================
   v109 — Spirits hero card (Wave 41)
   Shown at the top of the Spirits list when a single category
   is selected. A richer, more editorial treatment than a regular
   card — surfaces summary + "How it's made" + key features so
   the bartender gets the category-level read before scrolling
   into sub-styles.
   ============================================================ */
.spirit-hero-card {
  background: linear-gradient(180deg,
    color-mix(in srgb, var(--accent) 12%, var(--surface)),
    color-mix(in srgb, var(--accent) 3%, var(--surface)));
  border: 1px solid color-mix(in srgb, var(--accent) 35%, var(--rule));
  border-radius: 10px;
  padding: 18px 20px 16px;
  margin-bottom: 16px;
  cursor: pointer;
  transition: border-color 0.15s ease, box-shadow 0.15s ease, transform 0.05s ease;
  position: relative;
  overflow: hidden;
}
.spirit-hero-card::before {
  /* Fleuron-style ornament in the corner to mark this as a hero, not a card */
  content: "❦";
  position: absolute;
  top: 12px; right: 14px;
  color: color-mix(in srgb, var(--accent) 60%, transparent);
  font-size: 16px;
  font-family: var(--serif-display);
  pointer-events: none;
}
.spirit-hero-card:hover {
  border-color: var(--accent);
  box-shadow: 0 8px 22px color-mix(in srgb, var(--accent) 18%, transparent);
}
.spirit-hero-card:active { transform: translateY(1px); }
.spirit-hero-eyebrow {
  font-family: var(--sans);
  font-size: 10.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 4px;
}
.spirit-hero-title {
  font-family: var(--serif-display);
  font-size: 24px;
  color: var(--ink-bright);
  margin: 0 0 10px;
  letter-spacing: 0.2px;
  line-height: 1.1;
}
.spirit-hero-summary {
  font-family: var(--serif);
  font-size: 14px;
  line-height: 1.55;
  color: var(--ink);
  margin: 0 0 12px;
}
.spirit-hero-section {
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid color-mix(in srgb, var(--accent) 18%, transparent);
}
.spirit-hero-section-label {
  font-family: var(--sans);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: 5px;
}
.spirit-hero-section-body {
  font-family: var(--serif);
  font-size: 13px;
  line-height: 1.5;
  color: var(--ink);
  margin: 0;
}
.spirit-hero-features {
  margin: 0;
  padding-left: 18px;
  font-family: var(--serif);
  font-size: 13px;
  line-height: 1.5;
  color: var(--ink);
}
.spirit-hero-features li { margin-bottom: 3px; }
.spirit-hero-footer {
  margin-top: 12px;
  font-family: var(--serif-italic);
  font-style: italic;
  font-size: 12px;
  color: var(--accent);
  text-align: right;
}

/* v109 — Spirit sub-style chip rail (Wave 43). Reads as the second level
   of the two-level filter — a hair smaller, slightly indented, with a
   thin left-border accent to suggest "narrowing within the family". */
.spirit-substyle-row {
  margin-top: 6px;
  padding-left: 10px;
  border-left: 2px solid color-mix(in srgb, var(--accent) 35%, transparent);
}
.spirit-substyle-row .chip {
  font-size: 11px;
  padding: 5px 11px;
}
/* v111 — Wave 59: "+N more" / "Less" chip for the overflow toggle. Reads
   as quieter than the regular chip so it doesn't compete with the
   actual filters. */
.spirit-substyle-more-chip {
  font-style: italic;
  border-style: dashed !important;
  color: var(--ink-faint) !important;
}
.spirit-substyle-more-chip:hover {
  color: var(--accent) !important;
  border-color: var(--accent) !important;
}

/* ============================================================
   v109 — AI Review & Finish presentation (Wave 45)
   Three blocks inside the review sheet: assessment, suggestions
   list, optional improved-build card.
   ============================================================ */
.review-eyebrow {
  font-family: var(--sans);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
  margin: 0 0 6px;
}
.review-assessment {
  background: color-mix(in srgb, var(--accent) 8%, var(--surface));
  border-left: 3px solid var(--accent);
  padding: 14px 16px;
  border-radius: 0 6px 6px 0;
  margin-bottom: 18px;
}
.review-assessment-body {
  font-family: var(--serif);
  font-size: 14px;
  line-height: 1.55;
  margin: 0;
  color: var(--ink);
}
.review-suggestions {
  margin-bottom: 18px;
}
.review-suggestions-list {
  list-style: none;
  padding: 0;
  margin: 0;
}
.review-suggestion-row {
  display: grid;
  grid-template-columns: minmax(80px, max-content) 1fr;
  gap: 12px;
  padding: 10px 0;
  border-top: 1px solid var(--rule);
  font-family: var(--serif);
  font-size: 13.5px;
  line-height: 1.5;
}
.review-suggestion-row:first-child {
  border-top: none;
  padding-top: 4px;
}
.review-suggestion-target {
  font-family: var(--sans);
  font-size: 10.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-faint);
  padding-top: 2px;
}
.review-suggestion-change {
  color: var(--ink);
}
.review-improved-block {
  margin-top: 12px;
  padding: 14px 16px;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-left: 3px solid var(--accent-2, var(--accent));
  border-radius: 0 6px 6px 0;
}
.review-improved-title {
  font-family: var(--serif-display);
  font-size: 19px;
  color: var(--ink-bright);
  margin: 0 0 4px;
}
.review-improved-change {
  font-family: var(--serif-italic);
  font-style: italic;
  font-size: 13px;
  color: var(--ink-dim);
  margin: 0 0 10px;
  line-height: 1.45;
}

/* ============================================================
   v109 — Accessibility floor (Wave 47)
   Three baseline a11y additions that should have shipped earlier:

   1. :focus-visible — keyboard users had NO visible focus ring on
      interactive elements (buttons, links, tabs). WCAG 2.4.7 violation.
      One global rule covers everything tappable.

   2. prefers-reduced-motion — 200+ transitions and keyframe animations
      across the codebase, with zero respect for the OS setting. WCAG
      2.3.3 violation. One media query zeros transition + animation
      durations sitewide; individual components don't need updates.

   3. Touch-friendly outline offset on tabs/cards — focus rings sit just
      OUTSIDE the element so they don't crowd the content.
   ============================================================ */

/* Keyboard focus — visible on every interactive element. Uses
   accent color so it adapts to the active binding (gold leaf on
   Walnut, rose gold on Rosé, bone on Onyx, etc.). */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--radius, 2px);
}
/* Inputs already have their own focus treatment via border-color —
   replace the outline with a softer offset ring so we don't double up. */
.input:focus-visible,
textarea.input:focus-visible,
select.input:focus-visible {
  outline: 2px solid color-mix(in srgb, var(--accent) 65%, transparent);
  outline-offset: 1px;
}
/* Tabs / sub-tabs / chips already have their own active state — keep the
   ring tight against the element so it doesn't fight the active fill. */
.tab:focus-visible,
.bottom-tab:focus-visible,
.sub-tab:focus-visible,
.chip:focus-visible {
  outline-offset: -2px;
}
/* Defeat the legacy non-visible focus outline on tap/mouse — keyboard
   users get :focus-visible above; tap/click users get the existing
   hover/active styles. */
button:focus:not(:focus-visible),
a:focus:not(:focus-visible) {
  outline: none;
}

/* ============================================================
   v109 — Sync status pip on the brand mark (Wave 52)
   Tiny colored dot pinned to the top-right of the "E" mark.
   Tells the bartender at a glance whether their writes are
   going through. States:
     synced  → accent color (theme-appropriate gold/silver/etc)
     syncing → amber, pulsing
     error   → red, no pulse (sticky)
     offline → gray, no pulse
   Hidden via [hidden] when sync isn't configured / signed out.
   ============================================================ */
/* v328 — Sync-status-pip hidden.
   --------------------------------------------------------------
   The 8px sync indicator on the brand-mark read as "unidentified
   green/amber/red dot" to users — they couldn't decode it as a
   sync state without being told. Worse, the synced-state color
   was hardcoded #5cb87a (a fixed green) which clashed with every
   theme palette (Aperitivo coral, Velvet purple, Walnut leather).
   Sync errors are surfaced more prominently in Settings + the
   conflict-view banner, so the brand-mark pip was decorative
   anxiety. We hide it via display: none — the rules below remain
   on disk in case we ever restore a labeled affordance, but no
   pixel renders. */
.sync-status-pip { display: none !important; }
.brand-mark { position: relative; }
/* Vestigial styling preserved for future re-enable; currently
   unreachable because of the display:none above. */
.sync-status-pip[data-state="synced"] { background: #5cb87a; }
.sync-status-pip[data-state="syncing"] {
  background: #d4a534;
  animation: sync-pip-pulse 1.4s ease-in-out infinite;
}
.sync-status-pip[data-state="error"] { background: #c54a3f; }
.sync-status-pip[data-state="offline"] { background: #8a857f; }
@keyframes sync-pip-pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.4; }
}
/* Reduced motion handled by the global @media block below */

/* ============================================================
   v109 — Journal cross-link affordances (Wave 48)
   Two surfaces:
     1. Card pip — small pencil glyph beside the title on any
        canonical recipe card that has a same-named journal entry.
        Tap opens the journal version directly.
     2. Detail banner — full-width "Your version →" callout inside
        the canon recipe detail sheet when a match exists.
   ============================================================ */
.card-journal-pip {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px;
  margin-left: 6px;
  padding: 0;
  border: 1px solid color-mix(in srgb, var(--accent) 50%, transparent);
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  color: var(--accent);
  border-radius: 50%;
  font-size: 12px;
  line-height: 1;
  cursor: pointer;
  transition: background 0.12s ease, transform 0.05s ease;
  flex-shrink: 0;
}
.card-journal-pip:hover {
  background: color-mix(in srgb, var(--accent) 22%, transparent);
}
.card-journal-pip:active { transform: scale(0.92); }

.detail-your-version {
  display: flex; align-items: center; gap: 12px;
  width: 100%;
  margin: 0 0 14px;
  padding: 12px 14px;
  background: color-mix(in srgb, var(--accent) 8%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--accent) 35%, var(--rule));
  border-left: 3px solid var(--accent);
  border-radius: 0 6px 6px 0;
  text-align: left;
  cursor: pointer;
  transition: background 0.12s ease, border-color 0.12s ease;
}
.detail-your-version:hover {
  background: color-mix(in srgb, var(--accent) 15%, var(--surface));
  border-color: var(--accent);
}
.detail-your-version-eyebrow {
  font-family: var(--sans);
  font-size: 10.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
  flex-shrink: 0;
}
.detail-your-version-body {
  flex: 1;
  font-family: var(--serif-italic);
  font-style: italic;
  font-size: 13px;
  line-height: 1.45;
  color: var(--ink);
}
.detail-your-version-arrow {
  font-family: var(--sans);
  font-size: 18px;
  color: var(--accent);
  flex-shrink: 0;
}

/* Reduced motion — respect the OS setting. Zero out durations site-wide
   without touching the keyframe definitions themselves; the elements
   simply snap to their end state. */
@media (prefers-reduced-motion: reduce) {
  *,
*::before,
*::after {
    transition-duration: 0.001ms !important;
    transition-delay: 0ms !important;
    animation-duration: 0.001ms !important;
    animation-delay: 0ms !important;
    animation-iteration-count: 1 !important;
    scroll-behavior: auto !important;
  }
  /* Page-turn slide gets fully suppressed — the visual snap is the goal. */
  .page-turn {
    animation: none !important;
  }
}

/* ============================================================
   v119 — Sync conflict review (conflict-view.js)

   Surfaces:
     • Brand-menu entry with a count badge
     • List sheet showing every open conflict as a card
     • Each card has a side-by-side field diff + three action buttons
     • Merge sheet for per-field picking

   The diff blocks deliberately use <pre> so multi-line text
   (ingredients, notes) preserves whitespace and stays scannable.
   ============================================================ */
.brand-menu-conflicts {
  /* Stand out from the rest of the brand menu — this is an alert,
     not a navigation item. Warm amber tint matches the alert SVG. */
  color: var(--ink, #f3e4cc);
}
.brand-menu-conflicts svg { color: #d4a534; }
.brand-menu-badge {
  margin-left: auto;
  min-width: 22px;
  height: 20px;
  padding: 0 6px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: #c54a3f;
  color: #fff;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.02em;
  line-height: 1;
}

/* Conflict list inside the review sheet */
.conflict-list { display: flex; flex-direction: column; gap: 16px; }
.conflict-help {
  font-size: 13px;
  color: var(--ink-dim);
  margin: 0 0 8px;
  line-height: 1.4;
}
.conflict-card {
  border: 1px solid var(--rule);
  border-radius: 8px;
  padding: 12px;
  background: var(--bg-elev, rgba(255,255,255,0.02));
}
.conflict-card-header {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin-bottom: 10px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--rule);
}
.conflict-card-table {
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent);
}
.conflict-card-name {
  font-size: 15px;
  font-weight: 600;
  color: var(--ink);
}
.conflict-diff { display: flex; flex-direction: column; gap: 10px; }
.conflict-field {
  border-radius: 6px;
  padding: 6px 0;
}
.conflict-field-changed {
  background: rgba(212, 165, 52, 0.06);
  padding: 8px;
  border-left: 2px solid #d4a534;
}
.conflict-field-label {
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-dim);
  margin-bottom: 6px;
}
.conflict-field-cols {
  display: grid;
  grid-template-columns: 1fr;
  gap: 8px;
}
@media (min-width: 600px) {
  .conflict-field-cols { grid-template-columns: 1fr 1fr; }
}
.conflict-field-col {
  border: 1px solid var(--rule);
  border-radius: 4px;
  padding: 6px 8px;
  background: rgba(0, 0, 0, 0.12);
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.conflict-field-side {
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-dim);
}
.conflict-field-value {
  margin: 0;
  font-family: inherit;
  font-size: 13px;
  line-height: 1.4;
  color: var(--ink);
  white-space: pre-wrap;
  word-break: break-word;
}
.conflict-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px solid var(--rule);
}
.conflict-merge-body { display: flex; flex-direction: column; gap: 14px; }
.conflict-merge-field {
  border-bottom: 1px solid var(--rule);
  padding-bottom: 12px;
}
.conflict-merge-field:last-child { border-bottom: 0; }
.conflict-pick {
  align-self: flex-start;
  /* Picked option gets a brighter accent so the user can scan their
     decisions at a glance before saving. */
  opacity: 0.7;
}
.conflict-pick.is-active {
  opacity: 1;
  background: var(--accent-soft, rgba(202,164,90,0.18));
  border-color: var(--accent);
  color: var(--ink);
}

/* ============================================================
   v141 Wave 95 — Profile card dashboard
   ============================================================
   Replaces the old long-form Profile editor with a grid of summary
   cards. Each card is a tappable button that opens its section in
   a modal sheet. Cards have two visual states — populated (default)
   and is-empty (lighter, more "invitation"-feeling).
   ============================================================ */
.profile-dashboard-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 10px;
  margin: 4px 4px 28px;
}
@media (min-width: 720px) {
  .profile-dashboard-grid {
    grid-template-columns: 1fr 1fr;
    gap: 12px;
  }
}
.profile-dashboard-card {
  appearance: none;
  width: 100%;
  text-align: left;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: 8px;
  padding: 14px 16px;
  cursor: pointer;
  color: var(--ink);
  font-family: inherit;
  display: flex;
  flex-direction: column;
  gap: 6px;
  transition: border-color 0.15s, background 0.15s, transform 0.05s;
}
.profile-dashboard-card:hover {
  border-color: var(--accent);
  background: var(--surface-2);
}
.profile-dashboard-card:active {
  transform: scale(0.995);
}
.profile-dashboard-card.is-empty {
  background: transparent;
  border-style: dashed;
  border-color: var(--rule-strong);
}
.profile-dashboard-card.is-empty:hover {
  background: var(--surface);
  border-color: var(--accent);
  border-style: solid;
}
.profile-dashboard-card-head {
  display: flex;
  align-items: center;
  gap: 8px;
}
.profile-dashboard-card-title {
  font-size: 15px;
  font-weight: 600;
  color: var(--ink);
  flex: 1;
  letter-spacing: 0.01em;
}
.profile-dashboard-card-badge {
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
  background: var(--surface-2);
  padding: 3px 7px;
  border-radius: 999px;
}
.profile-dashboard-card-chevron {
  color: var(--accent);
  font-size: 18px;
  line-height: 1;
  margin-left: 2px;
  opacity: 0.7;
}
.profile-dashboard-card-summary {
  font-size: 13px;
  line-height: 1.4;
  color: var(--ink-dim);
}
.profile-dashboard-card-summary.is-empty-text {
  color: var(--ink-faint);
  font-style: italic;
  font-family: var(--serif-italic, var(--serif));
}

/* Section-sheet body — give the section render a little breathing room
   when it's lifted out of the dashboard into a modal. */
.profile-section-sheet-body > * {
  margin-top: 0;
}
.profile-section-sheet-body {
  padding: 4px 0;
}

/* ============================================================
   v210 — IVORY light-theme overrides
   ============================================================
   The base stylesheet was authored against dark themes — every
   theme before Ivory (v206) was dark. The rules below were safe
   to inline as hardcoded rgba(0,0,0,...) shadows + dark backdrops.

   Ivory is the first LIGHT theme. Those assumptions read as grime
   against cream. These !important overrides flip the hardcoded
   dark-mode shadows / backdrops to warm-charcoal equivalents for
   Ivory only. Every other theme is unaffected.
   ============================================================ */

/* Page atmosphere — soft warm glow instead of dark vignette. */
[data-theme="ivory"] body::before {
  background: radial-gradient(
    ellipse 120% 90% at 50% 30%,
    rgba(255, 250, 240, 0.25) 0%,
    transparent 55%
  ) !important;
}

/* View titles + display heads + sheet titles — kill the dark text-shadow.
   v240: added .sheet-title to this rule — was carrying a heavy dark
   drop-shadow on cream that read as a muddy double-print. */
[data-theme="ivory"] .view-title,
[data-theme="ivory"] .view-header h1,
[data-theme="ivory"] .display-head,
[data-theme="ivory"] .detail-section h2,
[data-theme="ivory"] .detail-section h3,
[data-theme="ivory"] .sheet-title {
  text-shadow: 0 1px 0 rgba(28, 24, 20, 0.06) !important;
}

/* Sheet backdrop + modal dim — charcoal-toned instead of black. */
[data-theme="ivory"] .sheet-backdrop,
[data-theme="ivory"] .dialog-backdrop {
  background: rgba(28, 24, 20, 0.42) !important;
}

/* Sheet container + detail sheet drop shadow — soft warm shadow. */
[data-theme="ivory"] .sheet {
  box-shadow: 0 -8px 32px rgba(28, 24, 20, 0.18) !important;
}
[data-theme="ivory"] .recipe-sheet,
[data-theme="ivory"] .detail-sheet {
  box-shadow: 0 20px 60px rgba(28, 24, 20, 0.22) !important;
}

/* FAB — warm shadow + transparent drop-shadow filter. */
[data-theme="ivory"] .fab {
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.4),
    0 2px 6px rgba(28, 24, 20, 0.18),
    0 8px 22px rgba(28, 24, 20, 0.12) !important;
}
[data-theme="ivory"] .fab svg {
  filter: none !important;
}

/* Daily Pour pill + print-card spec name — gold-foil shadows lighten. */
[data-theme="ivory"] .daily-pour-headline,
[data-theme="ivory"] .daily-pour-name,
[data-theme="ivory"] .spec-print-name {
  text-shadow: 0 1px 0 rgba(28, 24, 20, 0.06) !important;
}

/* Primary buttons — proper highlight + lifted shadow on cream. */
[data-theme="ivory"] .btn:not(.btn-ghost):not(.btn-link) {
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.5),
    0 1px 2px rgba(28, 24, 20, 0.12) !important;
  text-shadow: none !important;
}

/* Form inputs — hairline border instead of inset shadow. */
[data-theme="ivory"] .input,
[data-theme="ivory"] input[type="text"],
[data-theme="ivory"] input[type="number"],
[data-theme="ivory"] input[type="email"],
[data-theme="ivory"] textarea {
  background: var(--surface) !important;
  border: 1px solid var(--rule-strong) !important;
  box-shadow: none !important;
}
[data-theme="ivory"] .input:focus,
[data-theme="ivory"] input:focus,
[data-theme="ivory"] textarea:focus {
  border-color: var(--accent) !important;
  box-shadow: 0 0 0 3px rgba(184, 66, 30, 0.22) !important;
}

/* Cards (Profile, Recipes, list) — visible hairline edge on cream. */
[data-theme="ivory"] .profile-dashboard-card,
[data-theme="ivory"] .card,
[data-theme="ivory"] .spec-card,
[data-theme="ivory"] .recipe-card {
  background: var(--surface) !important;
  border: 1px solid var(--rule-strong) !important;
  box-shadow: none !important;
}
[data-theme="ivory"] .profile-dashboard-card:hover,
[data-theme="ivory"] .card:hover,
[data-theme="ivory"] .spec-card:hover,
[data-theme="ivory"] .recipe-card:hover {
  border-color: var(--accent) !important;
  background: var(--surface-2) !important;
}

/* Theme tiles inside the picker sheet — soft warm shadow. */
[data-theme="ivory"] .theme-tile {
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.4),
    0 1px 2px rgba(28, 24, 20, 0.08) !important;
}
[data-theme="ivory"] .theme-tile.is-active {
  box-shadow:
    inset 0 0 0 2px var(--accent),
    0 2px 6px rgba(28, 24, 20, 0.15) !important;
}

/* Toast — invert. Dark ink on cream toast → cream toast on dark ink. */
[data-theme="ivory"] .toast {
  background: var(--ink) !important;
  color: var(--bg) !important;
  box-shadow: 0 8px 28px rgba(28, 24, 20, 0.32) !important;
}

/* Headers + bottom-tabs — keep the hairline visible on cream.
   v330: removed the `background: var(--bg) !important` from
   .app-header — was a leftover from an earlier Aperitivo design
   iteration that rendered a cream header. The v330 dark-amaro
   header with Negroni-glass striations (line ~679) is the right
   treatment; this rule was silently stomping on it via specificity
   + source order + !important. The border-bottom hairline stays. */
[data-theme="ivory"] .app-header {
  border-bottom: 1px solid var(--rule-strong) !important;
}
[data-theme="ivory"] .bottom-tabs {
  background: var(--bg) !important;
  border-top: 1px solid var(--rule-strong) !important;
}

/* ============================================================
   v215 — Pre-batch + venue chips/pips
   ============================================================
   The AI menu writer's prebatch_friendly flag and shelf-row
   venueId are both surfaced here. .card-batch-pip + .card-venue-
   badge sit on cards; .detail-batch-chip sits at the top of the
   recipe detail sheet. The ◇ glyph is rotated 45° to evoke a
   beaker silhouette without dragging in an SVG icon.
   ============================================================ */
.card-batch-pip {
  display: inline-flex;
  align-items: center;
  font-size: 9px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent);
  padding: 2px 6px;
  margin-left: 6px;
  border: var(--hairline) solid var(--accent);
  border-radius: 2px;
  font-weight: 700;
  line-height: 1.2;
  white-space: nowrap;
  background: transparent;
}
.card-venue-badge {
  display: inline-flex;
  align-items: center;
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--accent) 70%, var(--ink-faint));
  margin-left: 8px;
  font-family: var(--sans);
  white-space: nowrap;
  max-width: 140px;
  overflow: hidden;
  text-overflow: ellipsis;
}
.detail-batch-chip-row {
  display: flex;
  justify-content: flex-end;
  margin: 0 0 10px 0;
}
.detail-batch-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--accent);
  background: transparent;
  border: 1px solid var(--accent);
  border-radius: 999px;
  padding: 5px 11px;
  line-height: 1;
}
.detail-batch-chip-glyph {
  display: inline-block;
  font-size: 13px;
  transform: rotate(45deg);
  line-height: 1;
}

/* ============================================================
   v215 — Brand-menu "Sign in to sync" item
   ============================================================
   The local-only signal v211 designed but never wired. Visually
   distinct from regular menu rows so skipped users actually
   notice — but tonally soft (eyebrow + accent dot) so it reads
   as an invitation, not a nag.
   ============================================================ */
.brand-menu-signin {
  align-items: flex-start;
  padding-top: 12px !important;
  padding-bottom: 12px !important;
  background: linear-gradient(180deg, rgba(202, 164, 90, 0.06), rgba(202, 164, 90, 0.02));
  border-bottom: 1px solid var(--rule, rgba(202, 164, 90, 0.18));
  color: var(--ink, #f3e4cc);
  gap: 10px;
  display: flex;
}
.brand-menu-signin:hover {
  background: linear-gradient(180deg, rgba(202, 164, 90, 0.14), rgba(202, 164, 90, 0.06));
}
.brand-menu-signin-dot {
  width: 8px; height: 8px;
  flex-shrink: 0;
  margin-top: 6px;
  border-radius: 999px;
  background: var(--accent, #caa45a);
  box-shadow: 0 0 0 3px rgba(202, 164, 90, 0.18);
}
.brand-menu-signin-stack {
  display: flex;
  flex-direction: column;
  gap: 2px;
  line-height: 1.25;
  text-align: left;
}
.brand-menu-eyebrow {
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint, #8a7a5e);
  font-weight: 600;
}

/* v296 — Diff view styles for AI mutation surfaces (Refine, Review).
   Renders a "What changed" section above the AI's natural-language
   rationale: each row is one of + (added ingredient), − (removed),
   or ~ (modified amount/unit or method/glass/garnish field). Single
   monospace-feeling glyph at the start keeps the row scannable; the
   color (accent / dim / muted) signals the kind of change. */
.ai-diff-section {
  margin-bottom: 22px;
  padding: 12px 14px;
  background: var(--ink-soft, rgba(202,164,90,0.05));
  border-left: 2px solid var(--accent);
  border-radius: 4px;
}
.ai-diff-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-family: var(--sans);
  font-size: 13px;
  line-height: 1.45;
}
.ai-diff-row {
  display: flex;
  align-items: baseline;
  gap: 8px;
  color: var(--ink);
}
.ai-diff-glyph {
  flex-shrink: 0;
  width: 14px;
  text-align: center;
  font-family: var(--serif-display, var(--serif));
  font-weight: 700;
  font-size: 14px;
}
.ai-diff-add .ai-diff-glyph { color: var(--accent); }
.ai-diff-remove .ai-diff-glyph { color: var(--ink-faint, #8a7a5e); }
.ai-diff-change .ai-diff-glyph { color: var(--ink-dim, #6b5f48); }
.ai-diff-remove { color: var(--ink-faint, #8a7a5e); }
.ai-diff-before { color: var(--ink-faint, #8a7a5e); font-style: italic; }
.ai-diff-arrow { color: var(--ink-faint, #8a7a5e); }
.ai-diff-after { color: var(--ink); font-weight: 500; }
.ai-diff-field {
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint, #8a7a5e);
  font-weight: 600;
}

/* =============================================================
   v319 — Admin refund panel (COO #2). Sits below comps in /admin.
   ============================================================= */
.admin-refunds {
  margin-top: 28px;
  padding-top: 18px;
  border-top: 1px solid var(--rule);
}
.admin-refund-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.admin-refund-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 10px 12px;
  background: var(--surface-2);
  border: 1px solid var(--rule);
  border-radius: 6px;
  gap: 10px;
}
.admin-refund-row-done { opacity: 0.55; }
.admin-refund-main { flex: 1; min-width: 0; }
.admin-refund-email {
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.admin-refund-meta {
  font-family: var(--sans);
  font-size: 11px;
  color: var(--ink-dim);
  margin-top: 2px;
}
.admin-refund-status { font-weight: 600; letter-spacing: 0.02em; }
.admin-refund-status-good { color: var(--accent, #2a7f3f); }
.admin-refund-status-warn { color: var(--maraschino, #b13c2c); }
.admin-refund-status-muted { color: var(--ink-faint, #888); }
.admin-refund-confirm {
  background: var(--surface);
  border: 1px solid var(--accent, #2a7f3f);
  border-radius: 6px;
  padding: 12px;
  margin-bottom: 10px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.admin-refund-confirm-head {
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
}
.admin-refund-confirm-controls {
  display: grid;
  grid-template-columns: 1.5fr auto auto;
  gap: 8px;
  align-items: center;
}
@media (max-width: 600px) {
  .admin-refund-confirm-controls {
    grid-template-columns: 1fr 1fr;
  }
  .admin-refund-confirm-controls .admin-input { grid-column: 1 / -1; }
}

/* =============================================================
   v318 — Help section + in-app support sheet polish (COO #1).
   ============================================================= */
.settings-row[style*="--red"] .value,
.settings-row[style*="color: var(--red)"] .value {
  color: var(--red);
  opacity: 0.75;
}
.sheet-body a[href$=".html"]:hover,
.sheet-body a[href*=".html#"]:hover {
  color: var(--accent);
  border-bottom-color: var(--accent);
}
#brand-menu-help {
  border-top: 1px solid var(--rule);
  margin-top: 4px;
  padding-top: 12px;
}
#brand-menu-help:hover { color: var(--accent); }
#brand-menu-help svg { opacity: 0.85; }

/* =============================================================================
   v344 — BAR PROFILE
   Pickers used in onboarding (archetype + depth) and Settings (all four axes).
   Card grid for single-select; chip strip for multi-select; quiet refine card
   for the post-5-recipes nudge.
   ============================================================================= */

.bar-profile-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 8px;
  margin: 8px 0 16px;
}
@media (min-width: 480px) {
  .bar-profile-grid {
    grid-template-columns: 1fr 1fr;
  }
}

.bar-profile-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  text-align: left;
  padding: 12px 14px;
  border: 1px solid var(--rule);
  border-radius: 6px;
  background: transparent;
  color: var(--ink);
  cursor: pointer;
  transition: border-color 120ms ease, background 120ms ease;
  font-family: inherit;
  font-size: inherit;
  line-height: 1.4;
}
.bar-profile-card:hover {
  border-color: var(--accent);
  background: var(--accent-soft, rgba(202, 164, 90, 0.06));
}
/*
 * v395 — Strengthened selected-state. Joseph's audit feedback: "Bar
 * profile multi-select grid visual selection state is too subtle. The
 * 'Steakhouse / chophouse' tile only has a thin amber border — at a
 * glance, multiple tiles read as selected when only one is."
 * Pre-v395 the selected state was just border-color + light tint +
 * 1px inset shadow. Bumped to: bolder background tint, 2px solid
 * left rule (book-spine accent), stronger inset shadow, and a small
 * check glyph in the top-right corner so the selection reads at a
 * glance even on dense grids.
 */
.bar-profile-card.is-active {
  border-color: var(--accent);
  background: var(--accent-soft, rgba(202, 164, 90, 0.22));
  box-shadow: inset 4px 0 0 0 var(--accent), inset 0 0 0 1px var(--accent);
  position: relative;
}
.bar-profile-card.is-active::after {
  content: "✓";
  position: absolute;
  top: 8px;
  right: 10px;
  font-size: 12px;
  color: var(--accent);
  font-weight: 700;
  line-height: 1;
}
.bar-profile-card.is-active .bar-profile-card-label {
  color: var(--accent);
}
.bar-profile-card-label {
  font-weight: 600;
  font-size: 14px;
  margin-bottom: 4px;
  color: var(--ink);
}
.bar-profile-card-hint {
  font-size: 12px;
  color: var(--ink-dim);
  font-family: var(--serif-italic);
  font-style: italic;
}

.bar-profile-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 8px 0 16px;
}
.bar-profile-chip {
  padding: 6px 12px;
  border-radius: 999px;
  border: 1px solid var(--rule);
  background: transparent;
  color: var(--ink-dim);
  font-size: 13px;
  cursor: pointer;
  transition: all 120ms ease;
  font-family: inherit;
}
.bar-profile-chip:hover {
  color: var(--ink);
  border-color: var(--accent);
}
.bar-profile-chip.is-active {
  background: var(--accent);
  color: var(--bg);
  border-color: var(--accent);
}

.bar-profile-section-h {
  font-family: var(--serif-display, serif);
  font-size: 16px;
  font-weight: 500;
  margin: 20px 0 4px;
  letter-spacing: 0.02em;
  color: var(--ink);
}
.bar-profile-section-p {
  font-size: 13px;
  color: var(--ink-dim);
  font-family: var(--serif-italic);
  font-style: italic;
  margin: 0 0 8px;
  line-height: 1.4;
}
.bar-profile-notes-counter {
  font-size: 11px;
  color: var(--ink-faint);
  text-align: right;
  margin-top: 4px;
  font-family: var(--sans);
  letter-spacing: 0.04em;
}

.bar-profile-settings .bar-profile-section-h:first-child {
  margin-top: 4px;
}

.bar-profile-refine-card {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  margin: 12px 0;
  border: 1px solid var(--rule);
  border-left: 3px solid var(--accent);
  border-radius: 4px;
  background: var(--accent-soft, rgba(202, 164, 90, 0.06));
}
.bar-profile-refine-body {
  flex: 1;
  font-size: 13px;
  color: var(--ink);
  line-height: 1.45;
}
.bar-profile-refine-ctas {
  display: flex;
  gap: 6px;
  flex-shrink: 0;
}

/* v347 — Profile "?" tour button. Discrete circular affordance in the
   view header that opens the quick-tour sheet on demand. Replaces the
   dismissable banner that used to dominate first-paint vertical space. */
.profile-tour-btn {
  flex-shrink: 0;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 1px solid var(--rule);
  background: transparent;
  color: var(--ink-dim);
  font-family: var(--serif-italic);
  font-style: italic;
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  margin-top: 6px;
  transition: all 120ms ease;
}
.profile-tour-btn:hover {
  border-color: var(--accent);
  color: var(--accent);
}
.profile-tour-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* v347 — Share & Export sheet body. Slight padding tune so the inner
   publish-card + export-row stack reads as one panel, not two glued. */
.profile-share-export-sheet > * + * { margin-top: 0; }
.profile-share-export-sheet .resume-export-row { margin-top: 4px; }

/* ============================================================
   v348 — Settings hub-and-spoke
   ============================================================
   The Settings tab is now a 6-card hub at #/settings with each card
   routing to its own sub-page. The grid mirrors .profile-dashboard-grid
   (same column behavior, same card visuals) so the two top-level
   editorial surfaces in the app — Profile and Settings — share one
   visual language. The hub class is layered ON TOP of
   .profile-dashboard-grid in markup so changes to the Profile dashboard
   visuals propagate here for free; these rules only carry the
   Settings-specific tweaks.
   ============================================================ */
.settings-hub-grid {
  /* Pure inheritance from .profile-dashboard-grid for now. Kept as a
     declared class so future Settings-only tuning (e.g., dense layout
     at narrower breakpoints) has a hook. */
}
.settings-hub-card {
  /* Same — markup combines this with .profile-dashboard-card. Hook
     reserved for Settings-only visual adjustments. */
}
.settings-hub-search {
  /* Search input at the top of the hub. Sits above the grid so the
     filter UI is obvious without crowding the cards. The input itself
     already inherits the global .input styling; this only handles the
     spacing relative to the grid below. */
  width: 100%;
  margin-bottom: 12px;
}

/* Back affordance at the top of each sub-page. Small ghost button
   reading "← Settings" — light visual weight so the page title stays
   the focal point. Inherits .btn / .btn-ghost / .btn-sm and just adds
   a touch of bottom margin so it doesn't kiss the title. */
.settings-back-btn,
.settings-subpage-back {
  margin-bottom: 8px;
  font-size: 13px;
  color: var(--ink-dim);
}
.settings-back-btn:hover,
.settings-subpage-back:hover {
  color: var(--ink);
}

/* ============================================================================
   v574 — Menu Builder v2, Phase A: blueprint / structure-gate screen.
   All color/type/radius via theme tokens (no hardcoded color). Mobile-first;
   every interactive control ≥44px. New "blueprint-" namespace (the screen IS
   the blueprint); reuses .view-header/.view-title/.card-*/.btn*/.chip/.pick-*/
   .your-bar-toggle/.create-action-row/.ai-loading/.empty.
   ============================================================================ */
.blueprint-concept {
  font-family: var(--serif-italic, Georgia, serif);
  font-size: 14px;
  color: var(--ink-dim);
  line-height: 1.5;
  margin: 4px 0 0;
}
.blueprint-config { display: flex; flex-direction: column; gap: 16px; margin: 14px 0; }
.blueprint-field { display: flex; flex-direction: column; gap: 6px; }
.blueprint-field .card-num { display: block; }

.blueprint-titlewrap { display: flex; flex-direction: column; gap: 2px; flex: 1 1 auto; min-width: 0; }
.blueprint-title-input {
  font-family: var(--serif-display, Georgia, serif);
  font-size: clamp(26px, 6.5vw, 34px);
  line-height: 1.1;
  color: var(--ink-bright, var(--ink));
  background: transparent;
  border: 0;
  border-bottom: var(--hairline, 1px) dashed transparent;
  padding: 2px 0;
  min-height: 44px;
  width: 100%;
}
.blueprint-title-input:focus { outline: none; border-bottom-color: var(--accent); }

.blueprint-context {
  font-size: 13px;
  color: var(--ink-dim);
  margin: 6px 0 12px;
  line-height: 1.45;
}
.blueprint-context-eyebrow {
  font-size: 11px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--accent-2, var(--accent));
}
.blueprint-context-bar { color: var(--ink); font-weight: 600; }

.blueprint-reassure {
  background: var(--accent-soft, rgba(255,255,255,0.04));
  border: var(--hairline, 1px) solid var(--rule-faint, var(--rule));
  border-radius: var(--radius-md, 10px);
  padding: 10px 14px;
  font-size: 12.5px;
  color: var(--ink-dim);
  margin-bottom: 14px;
}
.blueprint-reassure-count {
  font-family: var(--serif-display, Georgia, serif);
  color: var(--accent-2, var(--accent));
  font-weight: 700;
}

.blueprint-provrow {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; padding: 6px 2px 12px;
}

.blueprint-slots { display: flex; flex-direction: column; gap: 10px; }

.blueprint-slot {
  position: relative;
  display: grid;
  grid-template-columns: auto auto 1fr auto;
  align-items: start;
  gap: 10px;
  background: var(--surface-2, var(--surface));
  border: var(--hairline, 1px) solid var(--rule);
  border-radius: var(--radius-md, 10px);
  padding: 12px 12px 12px 16px;
}
.blueprint-slot::before {
  content: "";
  position: absolute; left: 0; top: 0; bottom: 0; width: 4px;
  border-top-left-radius: var(--radius-md, 10px);
  border-bottom-left-radius: var(--radius-md, 10px);
  background: var(--card-spirit-color, var(--accent));
}
.blueprint-slot.is-locked { border-color: var(--accent); }
.blueprint-slot-num {
  font-size: 11px; letter-spacing: 0.08em; color: var(--ink-faint);
  font-family: var(--serif-display, Georgia, serif); padding-top: 12px; min-width: 18px;
}
.blueprint-slot-move { display: flex; flex-direction: column; gap: 2px; }
.blueprint-slot-move .btn-icon { min-width: 44px; min-height: 38px; font-size: 12px; }

/* v574 fix — the provenance toggle lives in .blueprint-provrow, not a
   .your-bar-row, so the shared on-state selector never matched. Style the
   on-state on the toggle itself. */
.your-bar-toggle.is-on { background: var(--accent); border-color: var(--accent); }
.your-bar-toggle.is-on .your-bar-toggle-knob { transform: translateX(18px); }

.blueprint-slot-main { min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.blueprint-slot-name {
  font-family: var(--serif-display, Georgia, serif);
  font-size: 17px; color: var(--ink-bright, var(--ink));
  background: transparent; border: 0;
  border-bottom: var(--hairline, 1px) dashed transparent;
  padding: 2px 0; min-height: 44px; width: 100%;
}
.blueprint-slot-name:focus { outline: none; border-bottom-color: var(--accent); }
.blueprint-slot-meta { display: flex; flex-wrap: wrap; gap: 6px; }
.blueprint-meta-chip { text-transform: capitalize; }
.blueprint-slot-line2 { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.blueprint-slot-price-wrap { color: var(--ink-dim); font-family: var(--serif-display, Georgia, serif); }
.blueprint-slot-price {
  width: 64px; background: transparent; border: 0;
  border-bottom: var(--hairline, 1px) dashed transparent;
  color: var(--ink); font-size: 15px; min-height: 44px; padding: 2px 0 2px 2px;
}
.blueprint-slot-price:focus { outline: none; border-bottom-color: var(--accent); }
.blueprint-slot-brand {
  flex: 1 1 140px; min-width: 120px; background: transparent; border: 0;
  border-bottom: var(--hairline, 1px) dashed transparent;
  color: var(--ink); font-size: 13px; min-height: 44px; padding: 2px 0;
}
.blueprint-slot-brand:focus { outline: none; border-bottom-color: var(--accent); }
.blueprint-slot-hero {
  font-family: var(--serif-italic, Georgia, serif);
  font-size: 12.5px; color: var(--ink-faint); margin: 2px 0 0; line-height: 1.4;
}
.blueprint-slot-hero-edit {
  width: 100%; background: transparent; border: 0;
  border-bottom: var(--hairline, 1px) dashed transparent;
  min-height: 44px; padding: 2px 0; margin: 0;
}
.blueprint-slot-hero-edit::placeholder { color: var(--ink-faint); opacity: 0.7; }
.blueprint-slot-hero-edit:focus { outline: none; border-bottom-color: var(--accent); }
.blueprint-slot-prov { margin-top: 4px; align-self: flex-start; }

.blueprint-slot-actions { display: flex; flex-direction: column; gap: 4px; }
.blueprint-slot-actions .btn-icon { min-width: 44px; min-height: 44px; }
.blueprint-slot-lock.is-locked { color: var(--accent); }
.blueprint-slot-del:hover { color: var(--red, #c0392b); }

.blueprint-add-slot {
  width: 100%; min-height: 44px; margin-top: 4px;
  background: transparent;
  border: var(--hairline, 1px) dashed var(--accent);
  border-radius: var(--radius-md, 10px);
  color: var(--accent); font-size: 14px; cursor: pointer;
}
.blueprint-add-slot:hover { background: var(--accent-soft, rgba(255,255,255,0.04)); }

@media (max-width: 480px) {
  .blueprint-slot { grid-template-columns: auto 1fr auto; }
  .blueprint-slot-move { grid-row: 1; grid-column: 1; flex-direction: row; }
  .blueprint-slot-num { display: none; }
}

/* ============================================================================
   v581 — The Mixology Lab shell (Phase 1). Theme-token driven; ≥44px targets.
   ============================================================================ */
.lab-tagline {
  font-family: var(--serif-italic, Georgia, serif);
  font-size: 14px; color: var(--ink-dim); line-height: 1.5; margin: 4px 0 18px;
}
.lab-artifact-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 12px; margin-bottom: 18px;
}
.lab-artifact-card {
  position: relative; min-height: 96px; padding: 16px 18px;
  background: var(--surface-2, var(--surface));
  border: var(--hairline, 1px) solid var(--rule);
  border-radius: var(--radius-md, 10px);
  cursor: pointer; transition: border-color .15s ease, background .15s ease;
}
.lab-artifact-card:hover { border-color: var(--accent); }
.lab-artifact-card.is-primary { border-color: var(--accent); background: var(--accent-soft, rgba(255,255,255,0.04)); }
.lab-artifact-card.is-open { border-color: var(--accent-2, var(--accent)); }
.lab-artifact-card.is-soon { opacity: 0.6; cursor: default; }
.lab-artifact-card.is-soon:hover { border-color: var(--rule); }
.lab-artifact-title {
  font-family: var(--serif-display, Georgia, serif);
  font-size: 20px; color: var(--ink-bright, var(--ink)); margin-bottom: 4px;
}
.lab-artifact-sub { font-size: 12.5px; color: var(--ink-dim); line-height: 1.4; }
.lab-soon-badge { position: absolute; top: 12px; right: 12px; }

.lab-starts { display: flex; flex-direction: column; gap: 8px; }
.lab-starts .card-num { margin-bottom: 4px; }
.lab-start-row {
  display: flex; flex-direction: column; gap: 2px; align-items: flex-start;
  width: 100%; min-height: 56px; padding: 10px 14px; text-align: left;
  background: transparent;
  border: var(--hairline, 1px) solid var(--rule);
  border-radius: var(--radius-md, 10px);
  color: var(--ink); cursor: pointer; transition: border-color .15s ease;
}
.lab-start-row:hover { border-color: var(--accent); }
.lab-start-label { font-family: var(--serif-display, Georgia, serif); font-size: 16px; color: var(--ink-bright, var(--ink)); }
.lab-start-sub { font-size: 12px; color: var(--ink-dim); }

/* v581c — Ambient Coach line on built drinks (Lab Phase 2). Quiet by design —
   a glanceable read, never a nag. */
.lab-coach-note {
  font-size: 11.5px; line-height: 1.4; margin: 4px 0 0;
  color: var(--ink-faint); font-style: italic;
  padding-left: 10px; border-left: 2px solid var(--rule-faint, var(--rule));
}

/* ── Lab cocktail bench (P1: canon search → riff → live read) ──────────────── */
.lab-cocktail-entry { display: flex; flex-direction: column; gap: 14px; }
.lab-search-wrap { position: relative; }
.lab-search { width: 100%; box-sizing: border-box; }
.lab-search-results {
  position: absolute; left: 0; right: 0; top: calc(100% + 4px); z-index: 30;
  background: var(--surface-2, var(--surface));
  border: var(--hairline, 1px) solid var(--rule); border-radius: var(--radius-md, 10px);
  overflow: hidden; max-height: 320px; overflow-y: auto;
}
.lab-search-row {
  display: flex; justify-content: space-between; align-items: center; gap: 10px;
  width: 100%; min-height: 44px; padding: 8px 14px; text-align: left;
  background: transparent; border: none; border-bottom: var(--hairline, 1px) solid var(--rule-faint, var(--rule));
  color: var(--ink); cursor: pointer; font-size: 14px;
}
.lab-search-row:last-child { border-bottom: none; }
.lab-search-row:hover,
.lab-search-row.is-hi { background: var(--accent-soft, rgba(255,255,255,0.05)); }
.lab-search-row small { color: var(--ink-dim); font-size: 11.5px; }
.lab-starts-or { margin-top: 4px; color: var(--ink-faint); }

.lab-back {
  background: transparent; border: none; color: var(--ink-dim);
  font-size: 13px; padding: 4px 0; margin-bottom: 4px; cursor: pointer; min-height: 44px;
}
.lab-back:hover { color: var(--accent); }
.lab-bench-title { display: inline; }
.lab-bench-sub { font-family: var(--serif-italic, Georgia, serif); font-size: 14px; color: var(--ink-dim); }
.lab-canon-strip {
  font-size: 12px; line-height: 1.5; color: var(--ink-dim);
  padding: 8px 12px; margin: 8px 0 14px;
  background: var(--surface-2, var(--surface)); border-radius: var(--radius-md, 10px);
}
.lab-canon-eyebrow {
  font-size: 10px; letter-spacing: .06em; text-transform: uppercase;
  color: var(--ink-faint); margin-right: 6px;
}

.lab-riff-rows { display: flex; flex-direction: column; gap: 2px; }
.lab-riff-row {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 6px 0; border-bottom: var(--hairline, 1px) solid var(--rule-faint, var(--rule));
}
.lab-riff-name { font-size: 14px; color: var(--ink); display: flex; align-items: center; gap: 8px; min-width: 0; }
.lab-delta { font-size: 11px; padding: 1px 6px; border-radius: 6px; }
.lab-delta.up { background: rgba(186,117,23,0.16); color: #BA7517; }
.lab-delta.dn { background: rgba(55,138,221,0.16); color: #378ADD; }
.lab-amt-ctl { display: flex; align-items: center; gap: 8px; flex: none; }
.lab-amt { font-size: 13px; color: var(--ink-dim); min-width: 56px; text-align: center; }
.lab-step {
  width: 44px; height: 44px; flex: none; border-radius: var(--radius-md, 10px);
  border: var(--hairline, 1px) solid var(--rule); background: var(--surface-2, var(--surface));
  color: var(--ink); font-size: 18px; line-height: 1; cursor: pointer;
}
.lab-step:hover { border-color: var(--accent); }
.lab-step:active { transform: scale(0.96); }

/* ── Live read panel (lab-read.js) ─────────────────────────────────────────── */
.lab-read-eyebrow { margin: 16px 0 6px; }
.lab-read-empty,
.lab-read-dim { font-size: 13px; color: var(--ink-faint); font-style: italic; }
.lab-seg {
  display: flex; gap: 4px; padding: 3px; border-radius: var(--radius-md, 10px);
  background: var(--surface-2, var(--surface)); margin-bottom: 12px;
}
.lab-seg-btn {
  flex: 1; min-height: 40px; border: none; border-radius: 8px; cursor: pointer;
  background: transparent; color: var(--ink-dim); font-size: 13px;
}
.lab-seg-btn[aria-selected="true"] { background: var(--surface); color: var(--ink-bright, var(--ink)); }
.lab-read-pane { display: flex; flex-direction: column; gap: 8px; }
.lab-bar-row { display: flex; align-items: center; gap: 10px; }
.lab-bar-label { font-size: 12px; color: var(--ink-dim); width: 110px; flex: none; }
.lab-bar-track { flex: 1; height: 7px; border-radius: 4px; background: var(--surface-2, var(--surface)); overflow: hidden; }
.lab-bar-fill { height: 100%; border-radius: 4px; transition: width .18s ease; }
.lab-ratio { margin-top: 6px; font-size: 12.5px; color: var(--ink-dim); }
.lab-ratio-num { font-family: var(--serif-display, Georgia, serif); font-size: 16px; color: var(--ink-bright, var(--ink)); }
.lab-read-note {
  font-size: 12.5px; line-height: 1.55; color: var(--ink); margin: 8px 0 0;
  padding-left: 10px; border-left: 2px solid var(--accent);
}
.lab-served-grid { display: flex; gap: 18px; flex-wrap: wrap; }
.lab-stat { display: flex; flex-direction: column; gap: 2px; }
.lab-stat b { font-family: var(--serif-display, Georgia, serif); font-size: 20px; font-weight: 400; color: var(--ink-bright, var(--ink)); }
.lab-stat span { font-size: 11.5px; color: var(--ink-faint); }
.lab-why-slot { display: flex; flex-direction: column; gap: 10px; }
.lab-why-block { display: flex; flex-direction: column; gap: 2px; }
.lab-why-eyebrow { font-size: 10px; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-faint); }
.lab-why-text { font-size: 13px; color: var(--ink); }

/* ── Bench add / remove / save (v586) ──────────────────────────────────────── */
.lab-row-del {
  width: 36px; height: 36px; flex: none; border-radius: var(--radius-md, 10px);
  border: none; background: transparent; color: var(--ink-faint);
  font-size: 18px; line-height: 1; cursor: pointer; margin-left: 2px;
}
.lab-row-del:hover { color: var(--red, #c0392b); background: var(--surface-2, var(--surface)); }
.lab-riff-name-input {
  width: 100%; max-width: 280px; background: transparent; color: var(--ink);
  border: none; border-bottom: var(--hairline, 1px) solid var(--rule);
  font-size: 14px; padding: 4px 0;
}
.lab-riff-name-input:focus { outline: none; border-bottom-color: var(--accent); }
.lab-add-ing {
  width: 100%; min-height: 44px; margin-top: 8px;
  background: transparent; border: 1px dashed var(--rule); border-radius: var(--radius-md, 10px);
  color: var(--ink-dim); font-size: 13px; cursor: pointer;
}
.lab-add-ing:hover { border-color: var(--accent); color: var(--accent); }
.lab-save-row { display: flex; gap: 10px; align-items: center; margin-top: 18px; }
.lab-save-name { flex: 1; min-width: 0; }
.lab-save-btn {
  flex: none; min-height: 44px; padding: 0 18px; border-radius: var(--radius-md, 10px);
  border: 1px solid var(--accent); background: var(--accent-soft, rgba(255,255,255,0.05));
  color: var(--ink-bright, var(--ink)); font-size: 14px; cursor: pointer;
}
.lab-save-btn:hover { background: var(--accent); color: var(--bg, #1a1410); }
.lab-save-btn:disabled { opacity: 0.6; cursor: default; }

/* ── Visual vessel + two-column bench (v587) ───────────────────────────────── */
.lab-bench-grid { display: grid; grid-template-columns: 1fr; gap: 20px; align-items: start; }
@media (min-width: 720px) {
  .lab-bench-grid { grid-template-columns: 240px 1fr; gap: 28px; }
  .lab-glass-col { position: sticky; top: 88px; }
}
.lab-glass-col { display: flex; flex-direction: column; align-items: center; }
.lab-glass-mount { width: 100%; max-width: 200px; }
.lab-glass-mount svg { display: block; width: 100%; height: auto; }
.lab-glass-cap {
  text-align: center; font-size: 12px; color: var(--ink-dim);
  margin-top: 6px;
}
.lab-bench-main { min-width: 0; }
