/* ============================================================
   EMBURY — design system (v81 multi-theme)
   ============================================================
   Four bindings, each evoking a distinct bar mood without
   borrowing any specific trademarked establishment's identity.
   Each binding re-skins the entire app: color, accent, hairline
   strategy, display face, geometry, ornamental divider, dropcap.

      walnut    — Gilded book. Leather + 24kt gold leaf.
                  Walnut + gold + oxblood + cream.
                  Default binding. Embossed minimal radius.
                  Display: Bodoni 72. Ornament: ❦ (fleuron).

      platinum  — Mirror salon. Deco silver.
                  Midnight + platinum + Bristol blue.
                  Sharp Deco geometry. Display: Didot.
                  Ornament: ◇ (Deco lozenge).

      verdant   — Absinthe garden. Antique brass + sage.
                  Sage + antique brass + oxblood + champagne.
                  Belle Époque flourish. Display: Big Caslon.
                  Ornament: ❀ (laurel flower).

      amber     — Rum hold. Nautical teal + rum amber.
                  Deep teal + rum amber + doubloon gold.
                  Weathered wood mood. Display: Bodoni 72.
                  Ornament: ✦ (compass star).

   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 to avoid a flash. theme.js exposes the
   read/write API; settings-view.js renders the picker.

   Add a new binding by adding a [data-theme="X"] block below and
   registering its name in theme.js THEMES. Every block must
   provide the full token surface; 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 10 dark
     themes but overpowering on the 2 light themes (Pineapple +
     Aperitivo) — a near-opaque black wash on a sand-cream UI
     reads as broken, not focused. --scrim is the modal/sheet
     dimming token; light themes override it to a warm-dark
     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). Themes pick: gold (Walnut), palm
                       (Pineapple), oxblood-shifted-terracotta
                       (Mezcal), amber (Ember), Riviera coral,
                       Campari red (Aperitivo), cabaret crimson
                       (Velvet), cinnabar (Habana), bone (Onyx), rose
                       gold (Boudoir), brass (Fireside, Amber).

     --maraschino    — Secondary warm-red / warning / cherry-mood
                       accent. Used by alert/error UI (devices-error,
                       admin row-error background, comment delete
                       state). Each theme interprets in its own
                       material: oxblood (Walnut), claret (Boudoir,
                       Velvet), terracotta (Mezcal), sunset coral
                       (Pineapple, Amber, Riviera), terrazzo plum
                       (Aperitivo), cinnabar (Habana), hot cocoa
                       (Fireside), graphite mid (Onyx — no red in the
                       palette, falls back to neutral). 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.
   ============================================================ */

/* ============================================================
   THEME — PINEAPPLE (v320, was Tokyo / was Platinum)
   Beach bar at noon. Sand-cream ground, dark pineapple-skin
   brown for the text, deepened palm green + sunset coral for
   the mood notes. The bright pineapple gold lives on as
   button/chip fill with the dark brown sitting on it.
   The FIRST light theme in Embury — distinct from Aperitivo's
   travertine cafe (which is cooler stone) by being warmer and
   sandier, with the pineapple-gold accent role.
   ============================================================ */
[data-theme="platinum"] {
  /* v320 — REBUILT as PINEAPPLE. Three iterations to land here:
     pass 1 used ocean-teal (rejected — blue belongs to Riviera);
     pass 2 went pineapple-skin dark cocoa (still too dark for
     "tropical pineapple"); pass 3 (this one) inverts to a LIGHT
     theme — sand-cream ground that reads as wet sand at the tide
     line in afternoon sun. Dark pineapple-skin brown becomes the
     INK rather than the bg. The ripe yellow flesh stays bright but
     shifts role from primary accent (legible against dark) to
     fill chip color (with dark ink sitting on it); the primary
     accent token deepens to caramelized pineapple for legibility
     against the cream ground. Palm green and sunset coral also
     deepen so they don't wash out on cream.
     Internal id stays "platinum" so users who had Tokyo selected
     keep their slot (they just see the new look on next paint). */

  /* Surfaces — sand cream. Warm, NO blue, NO gray. Distinct from
     Aperitivo's travertine (which has cool stone undertones). */
  --bg:           #f5e8c8;            /* warm sand cream */
  --bg-2:         #fbeed0;            /* lifted sand */
  --bg-deep:      #e8d8b0;            /* compressed sand / wet tide line */
  --surface:      #fdf3d8;            /* sunlit panel */
  --surface-2:    #fff8e0;            /* highest noon light */
  --surface-3:    #f0e0b8;            /* shaded panel */
  --paper:        #ffffff;            /* clean printed menu */

  /* Type — pineapple-skin brown on sand. AA 9.5:1 on bg.
     v320 pass-4: ink-dim + ink-faint darkened so captions, hints,
     and timestamps stop fading into the cream. Old ink-faint
     (#7a6a52) sat right at AA borderline; new one is 6:1. */
  --ink:          #2a1f10;            /* pineapple-skin brown */
  --ink-bright:   #160a04;            /* deepest for emphasis */
  --ink-dim:      #3a2d18;            /* captions — AA 8:1 */
  --ink-faint:    #5a4a30;            /* hints — AA 6:1, was 4.1 */

  /* Hairlines — caramel-pineapple on sand. Visible enough to
     organize, never enough to interrupt. v320 pass-4: stronger
     opacity so dividers don't disappear. */
  --rule:         #e0cc94;            /* sand fade with more body */
  --rule-strong:  #b89860;            /* darker, scannable divider */
  --rule-faint:   rgba(196, 86, 28, 0.28);
  --rule-gold:    rgba(196, 86, 28, 0.60);

  /* Accents — v320 pass-5: PRIMARY FLIPS TO PALM LEAF GREEN.
     User feedback + Chief Designer Maya Lin-Okonkwo verdict:
     "A pineapple is 70% leaf by volume; the crown is what makes
     the silhouette legible at a glance. Orange-as-primary was
     reading 'sunset cocktail,' not 'pineapple.' Green-as-primary
     plus orange-as-accent is the actual fruit." So the hero
     accent becomes deep palm leaf (#2a8a1f — Maya's exact pick:
     warm enough to read 'sun-hit crown,' deep enough to hold
     legibility on cream).
     Sunset orange (#c4561c) demoted from primary → secondary
     atmospheric highlight (favorite stars, incidental pops).
     --brass-light / --brass stay bright pineapple flesh
     (#f5c842) for chip + button fills.
     --on-accent flips to cream for text on the new green primary
     button surface; compass-chip warm-fill gets a one-line
     override below the block since it was the only consumer
     that needed dark text on yellow. */
  --brass-light:  #f5c842;            /* bright pineapple — fill chips */
  --accent:       #2a8a1f;            /* deep palm leaf — primary */
  --accent-2:     #3aa024;            /* sunlit palm */
  --accent-soft:  #d8eed0;            /* pale palm halo */
  --brass:        #f5c842;
  --brass-deep:   #a87810;            /* deep caramel */
  /* Gradient stays gilt (the gold-foil metaphor matters across
     themes); represents the pineapple flesh + caramelized edge. */
  --gold-foil:    linear-gradient(135deg, #fdd668 0%, #f5c842 30%, #a87810 70%, #fbeec0 100%);

  /* Mood — v320 pass-5: GREEN OWNS THE ATMOSPHERE.
     Bottle is a slightly cooler palm (variety against accent).
     Sunset coral lives in maraschino/copper for that single pop
     against the leaf hero. */
  --maraschino:   #c4561c;            /* sunset coral — secondary highlight */
  --maraschino-2: #e26a28;            /* lifted sunset */
  --burgundy:     #7a2810;            /* deep sunset shadow */
  --bottle:       #1f7014;            /* deep frond — varies the palm */
  --bottle-2:     #3aa024;            /* sunlit frond — matches accent-2 */
  --absinthe:     #a8c818;            /* saturated lime */
  --copper:       #e8542a;            /* vivid sunset orange */
  --rose-gold:    #e87a4a;            /* hibiscus blush */
  --neon-amber:   #f5b81c;            /* pineapple glow */
  --red:          #c8281c;            /* vivid hibiscus red */

  /* Spirit-coded bands — Pineapple retune, palm-primary edition.
     Gin gets the hero palm-leaf accent (palette match). Rum +
     aperitif own the sunset/coral band. Whiskey stays gold but
     a real amber (not the bright pineapple flesh) so it doesn't
     blur with the brass chip fills. */
  --spirit-whiskey:   #c89018;        /* deep amber whiskey */
  --spirit-gin:       #2a8a1f;        /* palm leaf — palette match */
  --spirit-rum:       #c4561c;        /* cane-sugar sunset — tiki's home spirit */
  --spirit-agave:     #a8c818;        /* saturated agave lime */
  --spirit-brandy:    #a8581c;        /* coconut husk */
  --spirit-vodka:     #6a5e48;        /* warm gray */
  --spirit-liqueur:   #b8385c;        /* vivid hibiscus pink */
  --spirit-aperitif:  #e8542a;        /* sunset coral */
  --spirit-vermouth:  #9a2c4a;        /* rose-hibiscus */
  --spirit-wine:      #7a1c1c;        /* tropical claret */
  --spirit-multi:     #2a8a1f;        /* palm — palette match */

  /* Display face + geometry — Iowan Old Style with a Georgia/Cambria
     fallback chain. Friendlier and slightly hand-set, matching a
     Polynesian-menu feel without going into novelty-tiki territory.
     Slightly rounder corners than Tokyo's lacquer-sharp 1px — a
     softer tropical feel, but still book-like. */
  --serif-display: "Iowan Old Style", "Georgia", "Cambria", "Times New Roman", serif;
  --radius:        4px;

  /* Ornament — hibiscus glyph. The single flower on the bartender's
     ear. Distinct from Tokyo's enso ring and Onyx's mid-dot. */
  --ornament-divider: "❁";
  --ornament-section: "✿";
  --dropcap-color:    #2a8a1f;        /* palm leaf */
  --dropcap-shadow:   0 1px 0 rgba(245, 232, 200, 0.65);

  /* Illuminated initial frame — palm leaf rim. */
  --dropcap-frame-bg:      rgba(42, 138, 31, 0.08);
  --dropcap-frame-border:  1px solid rgba(42, 138, 31, 0.50);
  --dropcap-frame-radius:  4px;
  --dropcap-ornament-pre:  "";
  --dropcap-ornament-post: "";

  /* Atmosphere RGB tokens — palm leaf primary, sunset secondary. */
  --accent-rgb:    42, 138, 31;      /* palm leaf — hero */
  --maraschino-rgb: 196, 86, 28;     /* sunset coral — secondary */
  --brass-rgb:     245, 200, 66;     /* bright pineapple (fills) */
  --bottle-rgb:    31, 112, 20;      /* deep frond */

  /* --on-accent — text on the palm-leaf primary surface (buttons,
     pills, etc.). Cream-on-leaf hits AA 4.7:1. The bright pineapple
     chip fill (--brass-light) still wants DARK brown text on top —
     handled by the .compass-chip override below the block since it
     was the only consumer of --on-accent against --brass-light. */
  --on-accent:     #f5e8c8;

  /* v320 — Scrim overrides for Pineapple (light theme). The dark-
     theme default rgba(0,0,0,0.78) overpowers a sand-cream UI;
     use a warm dark-brown semi-translucent that focuses attention
     on the sheet without nuking the page. */
  --scrim:        rgba(42, 31, 16, 0.62);
  --scrim-soft:   rgba(42, 31, 16, 0.22);
  /* Vignette — warm low-alpha tint instead of black wash. */
  --vignette:     radial-gradient(ellipse 130% 100% at 50% 50%, transparent 55%, rgba(168, 120, 16, 0.10) 100%);

  --print-edition-name: "Pineapple";

  /* Section plate — hibiscus marker against palm green rim. Maya:
     "coral-on-leaf is the most tropical color pairing in existence.
     The hibiscus earns its pop precisely because the hero is green." */
  --section-plate-glyph:  "✿";
  --section-plate-bg:     rgba(42, 138, 31, 0.08);
  --section-plate-border: 1px solid rgba(42, 138, 31, 0.50);
  --section-plate-radius: 4px;
  --section-plate-color:  #c4561c;     /* hibiscus on a leaf rim */

  /* Page-edge gilding — palm leaf hairline on cocktail cards. */
  --page-edge-color:      rgba(42, 138, 31, 0.55);

  /* Texture — palm-frond grain on sand. Palm-green strokes
     dominate (it's the hero color now); sunset coral flecks
     add the secondary pop. */
  --texture-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='200' height='200'><g stroke='%232a8a1f' stroke-width='0.3' opacity='0.12'><line x1='0' y1='200' x2='200' y2='0'/><line x1='-40' y1='160' x2='160' y2='-40'/><line x1='40' y1='240' x2='240' y2='40'/><line x1='80' y1='280' x2='280' y2='80'/><line x1='-80' y1='120' x2='120' y2='-80'/></g><g fill='%232a8a1f' opacity='0.18'><circle cx='28' cy='44' r='0.5'/><circle cx='92' cy='22' r='0.4'/><circle cx='146' cy='66' r='0.5'/><circle cx='178' cy='34' r='0.4'/><circle cx='56' cy='102' r='0.5'/><circle cx='128' cy='128' r='0.4'/><circle cx='172' cy='170' r='0.5'/><circle cx='40' cy='176' r='0.4'/><circle cx='104' cy='150' r='0.5'/><circle cx='162' cy='94' r='0.4'/></g><g fill='%23c4561c' opacity='0.20'><circle cx='66' cy='30' r='0.5'/><circle cx='140' cy='98' r='0.4'/><circle cx='30' cy='130' r='0.5'/><circle cx='184' cy='124' r='0.4'/></g></svg>");
  --texture-size: 200px 200px;
}

/* v320 pass-5 — Compass chip override for Pineapple.
   The .compass-chip.on[data-group="warm"] fill uses --brass-light
   (#f5c842 bright pineapple) with text color set to var(--on-accent).
   For all other themes that's fine (their --on-accent is a dark
   surface color). For Pineapple, --on-accent is now CREAM (designed
   for the palm-green button surface), and cream-on-yellow is
   unreadable. Override to dark pineapple-skin brown here. */
[data-theme="platinum"] .compass-chip.on[data-group="warm"] {
  color: #2a1f10;
}

/* v320 pass-6 — Pineapple-anatomy header. User insight: "why not
   change the header to pineapple brown and golden yellow?" — much
   sharper than the cream-on-cream first attempt. Plays the actual
   fruit's anatomy: rough golden-brown skin wraps the top, bright
   sand-cream flesh fills the body below. Brand wordmark, tab
   labels, nav glyphs all render in golden pineapple flesh on
   the skin-brown header strip. Inactive tabs use a muted gold
   so the active tab pops; active tab gets the brighter flesh
   color with a palm-leaf underline.

   The global .app-header rule hardcodes a near-black gradient
   that works for the 11 dark themes but reads as a jarring
   strip on light themes. Override block below pins Pineapple's
   header to the pineapple-skin palette + flesh-gold typography. */
[data-theme="platinum"] .app-header {
  /* v330 — Pineapple skin cross-hatch texture.
     ----------------------------------------------------------
     v329 attempted this with `background:` shorthand; the SVG
     layer was silently dropped by the cascade (proven by inline-
     style test that confirmed the SVG renders correctly). Rewrote
     using `background-color` + `background-image` longhand which
     splits responsibilities cleanly and gives our two-layer image
     stack its own dedicated property without competing with any
     parent .app-header background: shorthand reset later in the
     cascade. Same diamond cross-hatch overlay (caramel #c8a45c
     stroke at 0.20 alpha) over the brown skin gradient.
  */
  background-color: #2a1f10;
  background-image:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='18' height='18'><g stroke='%23c8a45c' stroke-width='0.5' opacity='0.20' fill='none'><line x1='0' y1='0' x2='18' y2='18'/><line x1='18' y1='0' x2='0' y2='18'/></g></svg>"),
    linear-gradient(180deg, #3a2d18 0%, #2a1f10 100%);
  background-size: 18px 18px, auto;
  background-repeat: repeat, no-repeat;
  box-shadow:
    0 1px 0 rgba(42, 138, 31, 0.35),
    0 2px 0 rgba(245, 200, 66, 0.10),
    0 8px 20px rgba(20, 14, 6, 0.20);
}
/* Brand block — wordmark + tagline in pineapple gold on the skin. */
[data-theme="platinum"] .app-header .brand-name {
  color: #f5c842;
}
[data-theme="platinum"] .app-header .brand-tagline {
  color: #c89018;
}
[data-theme="platinum"] .app-header .brand-chevron {
  color: #c89018;
}
[data-theme="platinum"] .app-header .brand-mark {
  color: #f5c842;
  border-color: rgba(245, 200, 66, 0.65);
}
/* Top-nav tabs — muted gold inactive, bright gold active, with
   palm-leaf underline reused from the global .tab.active rule
   (which uses --accent — already palm-green for Pineapple). */
[data-theme="platinum"] .app-header .tab {
  color: #c89018;
}
[data-theme="platinum"] .app-header .tab:hover {
  color: #fdd668;
}
[data-theme="platinum"] .app-header .tab.active {
  color: #f5c842;
}
/* Settings gear icon — same gold treatment, palm green on focus. */
[data-theme="platinum"] .app-header .tab-settings {
  color: #c89018;
}
[data-theme="platinum"] .app-header .tab-settings:hover {
  color: #f5c842;
}

/* v320 pass-7 — Aperitivo header override (same pattern as Pineapple).
   Aperitivo is Embury's other light theme — travertine cream ground
   with Campari-red accent and terrazzo-plum secondary. The global
   .app-header rule hardcodes a near-black gradient that lands as
   a jarring strip above the cream body, identical to the Pineapple
   problem. Pineapple's anatomy metaphor (pineapple skin wrapping the
   crown-flesh) translates here as "Negroni glass against travertine"
   — a deep amaro-brown header strip above the cream cafe interior.
   Cream wordmark on the deep ground, muted terracotta tabs, lifted
   coral on active. */
[data-theme="ivory"] .app-header {
  /* v330 — Aperitivo: Negroni-glass crystal-cut striations.
     ----------------------------------------------------------
     Same shorthand-vs-longhand fix as Pineapple. Pairing texture
     overlay (vertical etched lines evoking cut-crystal Negroni
     glass) over the dark amaro-brown gradient. Caramel-tan
     stroke at 0.18 alpha — felt, not seen. */
  background-color: #2c0e08;
  background-image:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='28' height='12'><g stroke='%23e89a5a' stroke-width='0.4' opacity='0.18' fill='none'><line x1='5' y1='0' x2='5' y2='12'/><line x1='13' y1='0' x2='13' y2='12'/><line x1='23' y1='0' x2='23' y2='12'/></g></svg>"),
    linear-gradient(180deg, #4a1c12 0%, #2c0e08 100%);
  background-size: 28px 12px, auto;
  background-repeat: repeat, no-repeat;
  box-shadow:
    0 1px 0 rgba(168, 56, 32, 0.35),
    0 2px 0 rgba(244, 236, 214, 0.08),
    0 8px 20px rgba(20, 10, 6, 0.22);
}
[data-theme="ivory"] .app-header .brand-name {
  color: #f4ecd6;
}
[data-theme="ivory"] .app-header .brand-tagline {
  color: #c89880;
}
[data-theme="ivory"] .app-header .brand-chevron {
  color: #c89880;
}
[data-theme="ivory"] .app-header .brand-mark {
  color: #f4ecd6;
  border-color: rgba(244, 236, 214, 0.55);
}
[data-theme="ivory"] .app-header .tab {
  color: #c89880;
}
[data-theme="ivory"] .app-header .tab:hover {
  color: #f4ecd6;
}
[data-theme="ivory"] .app-header .tab.active {
  color: #e8a888;
}
[data-theme="ivory"] .app-header .tab-settings {
  color: #c89880;
}
[data-theme="ivory"] .app-header .tab-settings:hover {
  color: #f4ecd6;
}

/* ============================================================
   v336 — Header textures for Ember + Mezcal
   ============================================================
   Continuing the material-identity work that started with
   Pineapple (cross-hatch skin) and Aperitivo (Negroni glass
   striations). Each theme's app-header gets a subtle texture
   overlay that reinforces its name. Same pattern: 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.

   MEZCAL: warm gray concrete speckle. Mezcal's metaphor is the
   smoke-cellar concrete walls; this texture suggests rough-poured
   concrete grit under the dark header bar.
   ============================================================ */
[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;
}
[data-theme="verdant"] .app-header {
  background-image:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='50' height='50'><g fill='%23a09080' opacity='0.08'><circle cx='6' cy='10' r='0.7'/><circle cx='18' cy='22' r='0.5'/><circle cx='32' cy='14' r='0.6'/><circle cx='40' cy='38' r='0.5'/><circle cx='12' cy='38' r='0.6'/><circle cx='28' cy='4' r='0.5'/><circle cx='44' cy='28' r='0.6'/><circle cx='22' cy='44' r='0.5'/><circle cx='38' cy='8' r='0.4'/></g></svg>"),
    linear-gradient(180deg, rgba(14,13,12,0.98) 0%, rgba(10,9,8,0.96) 100%);
  background-size: 50px 50px, auto;
  background-repeat: repeat, no-repeat;
}

/* ============================================================
   v337 — Header textures for remaining dark themes
   ============================================================
   Onyx intentionally skipped — industrial monochrome means no
   texture by design. Habana, Amber, Boudoir, Fireside, Velvet
   each get a material-identity overlay matching their metaphor.
   ============================================================ */

/* AMBER — rum hold ship's deck. Horizontal cask-stave hairlines
   in amber, evoking the planks of a rum hold. */
[data-theme="amber"] .app-header {
  background-image:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='80' height='12'><g stroke='%23d6843d' stroke-width='0.3' opacity='0.10' fill='none'><line x1='0' y1='3' x2='80' y2='3'/><line x1='0' y1='9' x2='80' y2='9'/></g></svg>"),
    linear-gradient(180deg, rgba(14,13,12,0.98) 0%, rgba(10,9,8,0.96) 100%);
  background-size: 80px 12px, auto;
  background-repeat: repeat, no-repeat;
}

/* BOUDOIR — black satin wall. Single-direction diagonal sheen
   lines in rose-gold, evoking the directional luster of satin. */
[data-theme="rose"] .app-header {
  background-image:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='40' height='40'><g stroke='%23d4906a' stroke-width='0.25' opacity='0.10' fill='none'><line x1='0' y1='40' x2='40' y2='0'/><line x1='0' y1='20' x2='20' y2='0'/><line x1='20' y1='40' x2='40' y2='20'/></g></svg>"),
    linear-gradient(180deg, rgba(14,13,12,0.98) 0%, rgba(10,9,8,0.96) 100%);
  background-size: 40px 40px, auto;
  background-repeat: repeat, no-repeat;
}

/* FIRESIDE — pine paneling. Vertical wood-grain hairlines in
   brass, evoking the pine planks of a ski-lodge bar. */
[data-theme="lodge"] .app-header {
  background-image:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='50' height='20'><g stroke='%23c89a52' stroke-width='0.2' opacity='0.10' fill='none'><line x1='8' y1='0' x2='8' y2='20'/><line x1='22' y1='0' x2='22' y2='20'/><line x1='35' y1='0' x2='35' y2='20'/><line x1='44' y1='0' x2='44' y2='20'/></g></svg>"),
    linear-gradient(180deg, rgba(14,13,12,0.98) 0%, rgba(10,9,8,0.96) 100%);
  background-size: 50px 20px, auto;
  background-repeat: repeat, no-repeat;
}

/* VELVET — cabaret curtain. Dense vertical pile lines in
   crimson, evoking the directional pile of stage velvet. */
[data-theme="velvet"] .app-header {
  background-image:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='20' height='12'><g stroke='%23e8385e' stroke-width='0.2' opacity='0.10' fill='none'><line x1='3' y1='0' x2='3' y2='12'/><line x1='7' y1='0' x2='7' y2='12'/><line x1='11' y1='0' x2='11' y2='12'/><line x1='15' y1='0' x2='15' y2='12'/></g></svg>"),
    linear-gradient(180deg, rgba(14,13,12,0.98) 0%, rgba(10,9,8,0.96) 100%);
  background-size: 20px 12px, auto;
  background-repeat: repeat, no-repeat;
}

/* HABANA — tropical poster bar. Rattan crossweave in red
   leather + brass, evoking the woven wicker of a Caribbean bar. */
[data-theme="copper"] .app-header {
  background-image:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='30' height='30'><g stroke='%23cc3a30' stroke-width='0.3' opacity='0.09' fill='none'><line x1='0' y1='8' x2='30' y2='8'/><line x1='0' y1='22' x2='30' y2='22'/><line x1='8' y1='0' x2='8' y2='30'/><line x1='22' y1='0' x2='22' y2='30'/></g></svg>"),
    linear-gradient(180deg, rgba(14,13,12,0.98) 0%, rgba(10,9,8,0.96) 100%);
  background-size: 30px 30px, auto;
  background-repeat: repeat, no-repeat;
}

/* ============================================================
   THEME — MEZCAL (v265, was Verdant)
   Oaxacan smoke cellar. Concrete walls, oxblood drape, obsidian
   glassware, agave in clay pots. The opposite of Habana's bright
   tropical poster bar — this is urban, smoky, grittier.
   ============================================================ */
[data-theme="verdant"] {
  /* Surfaces — smoke-stained charcoal with a warm olive undertone.
     Distinct from Onyx's cool near-black: this is WARM and slightly
     organic, like concrete that's absorbed years of mezcal smoke. */
  --bg:           #1a1612;            /* smoke-stained charcoal */
  --bg-2:         #221d18;            /* lifted */
  --bg-deep:      #100b08;            /* the cellar shadow */
  --surface:      #2a221c;            /* concrete panel */
  --surface-2:    #34291f;            /* lit concrete */
  --surface-3:    #3e3225;            /* top-lit */
  --paper:        #ede0c4;            /* old menu paper, sun-yellowed */

  /* Type — bone-cream on smoke. Warmer than Onyx. */
  --ink:          #ece0c4;            /* parchment, slight tobacco */
  --ink-bright:   #f4ead0;            /* lifted */
  --ink-dim:      #a0907a;            /* dim */
  --ink-faint:    #7a6c58;            /* faded, AA 5.5:1 on bg */

  /* Hairlines — oxblood-tinged, very faint */
  --rule:         #2a221c;
  --rule-strong:  #3e3225;
  --rule-faint:   rgba(224, 90, 68, 0.20);
  --rule-gold:    rgba(224, 90, 68, 0.55);

  /* Accents — OXBLOOD-LEANING TERRACOTTA, lifted from the
     original-cellar oxblood (#a83a30) to hit AA contrast on the
     smoke-charcoal bg. The wine-blood mood is preserved at the
     base of the gradient (--brass-deep, --accent-soft) but the
     hero hue is lifted for legibility — eyebrows and links in
     accent color now read AA 4.9:1 on bg. Distinct from Habana's
     poster red (brighter, cleaner) — this is deeper, dusted with
     smoke. */
  --brass-light:  #f08068;            /* lifted terracotta */
  --accent:       #e05a44;            /* lifted oxblood — AA 4.86:1 */
  --accent-2:     #f08068;
  --accent-soft:  #401412;
  --brass:        #e05a44;
  --brass-deep:   #8a2820;            /* original oxblood, kept for shadow */
  --gold-foil:    linear-gradient(135deg, #f08068 0%, #e05a44 30%, #8a2820 60%, #f4a08c 100%);

  /* Mood — agave green, terracotta, smoke. The Oaxaca palette. */
  --maraschino:   #7a3a2a;            /* terracotta */
  --maraschino-2: #94483a;
  --burgundy:     #4a1c14;            /* deep terracotta */
  --bottle:       #5a6b3e;            /* agave green */
  --bottle-2:     #748450;
  --absinthe:     #8a9a4a;            /* lighter agave */
  --copper:       #b87a3a;            /* copper still */
  --rose-gold:    #c88260;
  --neon-amber:   #d8a868;            /* glow off a copal candle */
  --red:          #e05a44;            /* oxblood-terracotta, palette match */

  /* Spirit-coded bands — Mezcal retune. Agave/mezcal gets the
     hero color treatment. Whiskey deeper-amber. */
  --spirit-whiskey:   #b87440;
  --spirit-gin:       #6a8a4a;        /* fresh agave herb */
  --spirit-rum:       #b08850;
  --spirit-agave:     #8aa050;        /* sage-agave, palette match */
  --spirit-brandy:    #b07050;
  --spirit-vodka:     #a8a098;        /* warm grey */
  --spirit-liqueur:   #9060a0;
  --spirit-aperitif:  #c85a50;
  --spirit-vermouth:  #a04848;
  --spirit-wine:      #6a1f1a;        /* deep red */
  --spirit-multi:     #e05a44;        /* lifted oxblood, palette match */

  /* Display face — Hoefler Text. Heavy serif with editorial weight,
     suits a smoke-cellar with gravitas. Distinct from Habana's Caslon
     (lighter / sun-poster) and Walnut's Iowan (refined-warm). */
  --serif-display: "Hoefler Text", "Iowan Old Style", "Source Serif Pro", Georgia, serif;
  --radius:        3px;               /* slightly handmade / irregular */

  /* Ornament — ✼ eight-pointed asterism. Evokes an agave bloom or a
     copal-incense star. Distinct from every other theme. */
  --ornament-divider: "✼";
  --ornament-section: "✼";
  --dropcap-color:    #e05a44;
  --dropcap-shadow:   0 1px 0 rgba(0,0,0,0.55);

  /* Dropcap frame — terracotta brick edge */
  --dropcap-frame-bg:      rgba(224, 90, 68, 0.10);
  --dropcap-frame-border:  1px solid rgba(224, 90, 68, 0.55);
  --dropcap-frame-radius:  3px;
  --dropcap-ornament-pre:  "";
  --dropcap-ornament-post: "";

  /* RGB tokens */
  --accent-rgb:    224, 90, 68;
  --maraschino-rgb: 122, 58, 42;
  --brass-rgb:     224, 90, 68;
  --bottle-rgb:    90, 107, 62;

  --on-accent:     #ece0c4;           /* cream on terracotta */

  --print-edition-name: "Mezcal";

  --section-plate-glyph:  "✼";
  --section-plate-bg:     rgba(224, 90, 68, 0.12);
  --section-plate-border: 1px solid rgba(224, 90, 68, 0.50);
  --section-plate-radius: 3px;
  --section-plate-color:  #f08068;

  --page-edge-color:      rgba(224, 90, 68, 0.55);

  /* Texture — concrete pour. Irregular specks at varying sizes,
     no straight lines. Distinct from any other theme's pattern. */
  --texture-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='180' height='180'><g fill='%23e05a44' opacity='0.10'><circle cx='18' cy='22' r='0.8'/><circle cx='52' cy='36' r='0.5'/><circle cx='88' cy='14' r='1.0'/><circle cx='122' cy='44' r='0.7'/><circle cx='156' cy='28' r='0.5'/><circle cx='30' cy='62' r='0.9'/><circle cx='72' cy='84' r='0.6'/><circle cx='110' cy='72' r='1.1'/><circle cx='144' cy='96' r='0.7'/><circle cx='168' cy='66' r='0.5'/><circle cx='14' cy='118' r='0.6'/><circle cx='48' cy='132' r='0.9'/><circle cx='86' cy='118' r='0.5'/><circle cx='124' cy='148' r='1.0'/><circle cx='158' cy='128' r='0.6'/><circle cx='24' cy='162' r='0.8'/><circle cx='62' cy='168' r='0.5'/><circle cx='100' cy='158' r='0.7'/><circle cx='138' cy='172' r='0.9'/></g><g fill='%235a6b3e' opacity='0.07'><circle cx='36' cy='44' r='0.6'/><circle cx='100' cy='28' r='0.7'/><circle cx='62' cy='106' r='0.5'/><circle cx='134' cy='90' r='0.6'/><circle cx='34' cy='140' r='0.7'/><circle cx='112' cy='138' r='0.5'/></g></svg>");
  --texture-size: 180px 180px;
}

/* ============================================================
   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.
   ============================================================ */
[data-theme="amber"] {
  /* Surfaces — nautical teal-wood */
  --bg:           #0f2230;            /* deep nautical teal */
  --bg-2:         #1a3142;            /* lifted teal-wood */
  --bg-deep:      #061521;            /* deepest hold shadow */
  --surface:      #2a4555;            /* foliage teal */
  --surface-2:    #34556a;            /* lit teal */
  --surface-3:    #426a82;            /* top-lit teal */
  --paper:        #fff2d8;            /* candle cream */

  /* Type — rum-soaked parchment on hold-dark */
  --ink:          #f3e3c5;            /* rum-soaked parchment */
  --ink-bright:   #fff2d8;            /* candle cream */
  --ink-dim:      #c4ad88;            /* aged sail */
  --ink-faint:    #957f5e;            /* faded ink, AA 5.5:1 */

  /* Hairlines — rum amber rules */
  --rule:         #2a4555;            /* foliage rule */
  --rule-strong:  #426a82;            /* lifted rule */
  --rule-faint:   rgba(214, 132, 61, 0.20);
  --rule-gold:    rgba(212, 165, 52, 0.50);

  /* Accents — rum amber + sunset coral + doubloon gold */
  --brass-light:  #e89a55;            /* light amber */
  --accent:       #d6843d;            /* rum amber */
  --accent-2:     #e89a55;            /* light amber echo */
  --accent-soft:  #5a3018;            /* amber shadow */
  --brass:        #d4a534;            /* doubloon gold */
  --brass-deep:   #8a6a1a;            /* dark gold */
  --gold-foil:    linear-gradient(135deg, #e89a55 0%, #d6843d 30%, #d4a534 60%, #f0b878 100%);

  /* Mood — sunset coral + palm green */
  --maraschino:   #c54a3f;            /* sunset coral */
  --maraschino-2: #d8604a;            /* lit coral */
  --burgundy:     #6b1a1a;            /* deep ember */
  --bottle:       #2d6e60;            /* palm green */
  --bottle-2:     #4a8a76;            /* lifted palm */
  --absinthe:     #d4a534;            /* doubloon gold */
  --copper:       #d6843d;            /* rum amber */
  --rose-gold:    #e89a78;            /* rose gold */
  --neon-amber:   #d4a534;            /* doubloon */
  --red:          #c54a3f;            /* coral, palette match */

  /* Spirit-coded bands — Smuggler's Cove retune. Rum gets the
     richest treatment (this is the rum den), spirits feel
     candlelit + sun-baked. */
  --spirit-whiskey:   #d6843d;        /* rum amber, palette match */
  --spirit-gin:       #5db89a;        /* emerald */
  --spirit-rum:       #e8b56a;        /* golden caramel — featured spirit */
  --spirit-agave:     #7cc068;        /* palm */
  --spirit-brandy:    #d8704a;        /* rose-gold */
  --spirit-vodka:     #a8c4d8;        /* silver-blue */
  --spirit-liqueur:   #b06ac8;        /* violet */
  --spirit-aperitif:  #d85a72;        /* coral pink */
  --spirit-vermouth:  #d8607a;        /* cherry rose */
  --spirit-wine:      #c0506a;        /* cherry */
  --spirit-multi:     #d4a534;        /* doubloon, palette match */

  /* Display face + geometry */
  --serif-display: "Bodoni 72", "Didot", "Hoefler Text", "Iowan Old Style", Georgia, serif;
  --radius:        3px;               /* weathered wood softness */

  /* Ornament — compass star */
  --ornament-divider: "✦";
  --ornament-section: "✦";
  --dropcap-color:    #d6843d;        /* rum amber */
  --dropcap-shadow:   0 1px 0 rgba(0,0,0,0.5);

  /* v66 — illuminated initial frame. Smuggler's Cove gets a
     compass-rose stamp: weathered amber border, full pill radius
     (50%) so the frame reads as a ship's seal/oval, with four-point
     compass-star glyphs (✦) at top-left and bottom-right. */
  --dropcap-frame-bg:      rgba(214, 132, 61, 0.10);
  --dropcap-frame-border:  1.5px solid rgba(214, 132, 61, 0.60);
  --dropcap-frame-radius:  50%;
  --dropcap-ornament-pre:  "✦";
  --dropcap-ornament-post: "✦";

  /* Atmosphere RGB tokens — rum amber sun + sunset coral + palm tints */
  --accent-rgb:  214, 132, 61;     /* rum amber */
  --maraschino-rgb:197, 74, 63;      /* sunset coral */
  --brass-rgb:   212, 165, 52;     /* doubloon gold */
  --bottle-rgb:  45, 110, 96;      /* palm green */

  /* Ink-on-amber — rum amber is bright/warm, deep teal reads well */
  --on-accent:        #0f2230;        /* nautical teal */

  /* v65 — printed spec card edition name. */
  --print-edition-name: "Amber";

  /* v74 — section-head plate. Smuggler's Cove gets a compass medallion:
     four-point compass star in a weathered amber oval (pill radius). */
  --section-plate-glyph:  "✦";
  --section-plate-bg:     rgba(214, 132, 61, 0.12);
  --section-plate-border: 1px solid rgba(214, 132, 61, 0.55);
  --section-plate-radius: 50%;
  --section-plate-color:  #e89a55;

  /* v74 — page-edge gilding. Doubloon gold on the right edge of
     cocktail cards — the brass-bound edge of a ship's logbook. */
  --page-edge-color:      rgba(212, 165, 52, 0.60);

  /* v74 — per-binding background texture. Smuggler's Cove gets weathered
     wood grain: anisotropic turbulence stretched horizontally, tinted
     rum amber. Ship's hold planking, very low alpha. */
  --texture-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='400' height='140'><filter id='w'><feTurbulence type='turbulence' baseFrequency='0.006 0.5' numOctaves='2' seed='5' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0.84  0 0 0 0 0.52  0 0 0 0 0.24  0 0 0 0.07 0'/></filter><rect width='100%' height='100%' filter='url(%23w)'/></svg>");
  --texture-size: 400px 140px;
}

/* ============================================================
   THEME — Onyx (v109, Wave 44)
   Monochromatic. Charcoal + bone + graphite + smoke.
   Brutalist precision. Display face is a clean grotesque, not
   a serif — the only binding without ornament-as-decoration.
   The ornament IS the typography (the discipline IS the mood).
   Mid-dot · for divider/section so the page reads as
   typographic restraint, not editorial flourish.
   ============================================================ */
[data-theme="onyx"] {
  /* v124 Wave 75 — refined Onyx. The v109 version skewed warm (#161614 has
     more red than blue in the channel) which made "monochrome" read as
     "dimly-lit walnut" on OLED screens. This rebuild commits to a cool
     near-black core (#121417) with slightly bluer graphites and a brighter,
     less yellow bone for ink. Inspired by Tom Sachs / muji / Aesop —
     industrial monochrome, not muddy darkroom. */

  /* Surfaces — onyx core, cool graphite lift */
  --bg:           #121417;            /* cool near-black, slight blue */
  --bg-2:         #1a1d21;            /* lifted graphite */
  --bg-deep:      #08090b;            /* deepest shadow */
  --surface:      #1f2329;            /* card panel */
  --surface-2:    #2a2f36;            /* lit panel */
  --surface-3:    #3a4048;            /* top-lit panel */
  --paper:        #f0eee8;            /* cool bone paper */

  /* Type — cool bone on onyx. Brighter top end for OLED-pop legibility. */
  --ink:          #ebe9e2;            /* cool bone */
  --ink-bright:   #ffffff;            /* pure white for emphasis */
  --ink-dim:      #9b9aa0;            /* mid graphite, slightly cool */
  --ink-faint:    #6c6e74;            /* faded graphite, AA 5.4:1 on bg */

  /* Hairlines — graphite seam at low alpha so they don't crowd */
  --rule:         #2a2f36;            /* graphite seam */
  --rule-strong:  #4a505a;            /* highlighted seam */
  --rule-faint:   rgba(235, 233, 226, 0.08);
  --rule-gold:    rgba(235, 233, 226, 0.36);   /* "gold" = bone here */

  /* Accents — pure bone, no warm cast. Two-step contrast for hierarchy. */
  --brass-light:  #ffffff;            /* pure white */
  --accent:       #ebe9e2;            /* cool bone — primary */
  --accent-2:     #b8b7b0;            /* mid bone */
  --accent-soft:  #1f2329;            /* graphite shadow */
  --brass:        #ebe9e2;            /* cool bone */
  --brass-deep:   #7a7d83;            /* deep graphite */
  --gold-foil:    linear-gradient(135deg, #ffffff 0%, #ebe9e2 30%, #7a7d83 60%, #ffffff 100%);

  /* Mood — true greyscale family. Warm-red maraschino becomes a graphite
     pulse; bottle green becomes blue-slate. No color, no warmth bleed. */
  --maraschino:   #5a606a;            /* mid graphite */
  --maraschino-2: #6e757f;            /* lit graphite */
  --burgundy:     #2a2f36;            /* deep graphite */
  --bottle:       #3e444d;            /* cool slate */
  --bottle-2:     #5a606a;            /* lifted slate */
  --absinthe:     #8a8c92;            /* mid bone-gray */
  --copper:       #82847a;            /* pewter (not warm copper) */
  --rose-gold:    #c4c2bc;            /* light cool gray */
  --neon-amber:   #b8b7b0;            /* mid bone */
  --red:          #7a7d83;            /* deep graphite (no red) */

  /* Spirit bands — true grayscale with the slightest hint of differentiation
     by temperature (whiskey/rum slightly warm, gin/agave slightly cool).
     Saturation kept under 8% so the eye reads them as gray + tone. */
  --spirit-whiskey:   #aaa49a;        /* warm gray, just barely */
  --spirit-gin:       #9aa4ac;        /* cool gray */
  --spirit-rum:       #a8a094;        /* sand gray */
  --spirit-agave:     #98a89c;        /* olive gray */
  --spirit-brandy:    #aaa098;        /* dust gray */
  --spirit-vodka:     #c4c2bc;        /* bright silver */
  --spirit-liqueur:   #a098a4;        /* lavender gray */
  --spirit-aperitif:  #aa9aa0;        /* mauve gray */
  --spirit-vermouth:  #a89aa6;        /* violet gray */
  --spirit-wine:      #8e7e82;        /* wine gray */
  --spirit-multi:     #b8b7b0;        /* mid bone */

  /* Display face + geometry — clean grotesque, near-zero radius */
  --serif-display: "Inter", "Helvetica Neue", "Akzidenz-Grotesk", -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
  --radius:        1px;               /* sharp, but a hair softer than Deco */

  /* Ornament — minimalist mid-dot. No fleuron, no flower, no compass. */
  --ornament-divider: "·";
  --ornament-section: "·";
  --dropcap-color:    #e8e6df;        /* bone */
  --dropcap-shadow:   0 1px 0 rgba(0,0,0,0.4);

  /* Illuminated initial frame — bare-bones thin box, no ornament */
  --dropcap-frame-bg:      rgba(232, 230, 223, 0.05);
  --dropcap-frame-border:  1px solid rgba(232, 230, 223, 0.45);
  --dropcap-frame-radius:  1px;
  --dropcap-ornament-pre:  "";
  --dropcap-ornament-post: "";

  /* Atmosphere — cool bone glow on onyx, no warm tint */
  --accent-rgb:    235, 233, 226;
  --maraschino-rgb: 90, 96, 106;
  --brass-rgb:     235, 233, 226;
  --bottle-rgb:    62, 68, 77;

  /* Ink-on-bone — bone accent is light, onyx reads well */
  --on-accent:        #121417;

  --print-edition-name: "Onyx";

  /* Section-head plate — minimalist square. Hair-line bone stroke. */
  --section-plate-glyph:  "·";
  --section-plate-bg:     rgba(232, 230, 223, 0.06);
  --section-plate-border: 1px solid rgba(232, 230, 223, 0.40);
  --section-plate-radius: 1px;
  --section-plate-color:  #e8e6df;

  --page-edge-color:      rgba(232, 230, 223, 0.45);

  /* Texture — very faint paper grain, no warm tint. Bone particles at low
     alpha so the surface reads as matte cardstock, not glossy. */
  --texture-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><g fill='%23e8e6df' opacity='0.06'><circle cx='10' cy='14' r='0.5'/><circle cx='42' cy='10' r='0.4'/><circle cx='72' cy='22' r='0.55'/><circle cx='98' cy='12' r='0.4'/><circle cx='128' cy='28' r='0.5'/><circle cx='150' cy='8' r='0.45'/><circle cx='22' cy='42' r='0.4'/><circle cx='52' cy='54' r='0.55'/><circle cx='82' cy='40' r='0.45'/><circle cx='108' cy='58' r='0.5'/><circle cx='138' cy='48' r='0.4'/><circle cx='6' cy='72' r='0.55'/><circle cx='44' cy='80' r='0.4'/><circle cx='74' cy='68' r='0.5'/><circle cx='104' cy='82' r='0.45'/><circle cx='132' cy='74' r='0.55'/><circle cx='154' cy='86' r='0.4'/><circle cx='26' cy='102' r='0.5'/><circle cx='58' cy='110' r='0.45'/><circle cx='86' cy='98' r='0.55'/><circle cx='114' cy='114' r='0.4'/><circle cx='142' cy='106' r='0.5'/><circle cx='14' cy='130' r='0.45'/><circle cx='48' cy='138' r='0.55'/><circle cx='78' cy='128' r='0.4'/><circle cx='106' cy='144' r='0.5'/><circle cx='134' cy='134' r='0.45'/><circle cx='156' cy='150' r='0.55'/></g></svg>");
  --texture-size: 160px 160px;
}

/* ============================================================
   THEME — BOUDOIR (v265, was Rosé)
   Private members-only nightclub at 2am. Black satin walls,
   rose-gold trim, claret velvet banquette, gilded mirrors,
   pendant lamp burning low. Distinct from Velvet's burlesque
   stage (which is theatrical / shouty) — Boudoir is intimate,
   whispered. The femme jewel-box audience but with bite.
   Display: Didot upright. Ornament: ❦ (fleuron heart).
   ============================================================ */
[data-theme="rose"] {
  /* Surfaces — matte ink black, not wine plum. The deep-shadow
     palette of an after-hours lounge where the walls disappear
     and only the rose-gold trim catches the light. */
  --bg:           #0a0608;            /* matte ink — the after-hours lounge */
  --bg-2:         #14090e;            /* lifted ink */
  --bg-deep:      #050203;            /* pure shadow */
  --surface:      #1a0e14;            /* claret-tinted panel */
  --surface-2:    #221318;            /* lit claret */
  --surface-3:    #2c1a22;            /* top-lit */
  --paper:        #f0e8dc;            /* warm ivory menu card */

  /* Type — warm ivory on ink. The shimmer of a pendant lamp on a
     printed cocktail list. */
  --ink:          #f0e8dc;            /* warm ivory */
  --ink-bright:   #faf2e6;
  --ink-dim:      #b09a8a;            /* dusk */
  --ink-faint:    #807060;            /* faded ivory, AA 5.4:1 */

  /* Hairlines — rose-gold trim seam, almost invisible */
  --rule:         #1a0e14;
  --rule-strong:  #2c1a22;
  --rule-faint:   rgba(212, 144, 106, 0.18);
  --rule-gold:    rgba(212, 144, 106, 0.55);

  /* Accents — true rose gold + claret. The whole binding turns on the
     rose-gold reading off black satin, like a champagne flute caught
     in a sliver of light. */
  --brass-light:  #e8a886;            /* lit rose gold */
  --accent:       #d4906a;            /* rose gold — the hero */
  --accent-2:     #e8a886;
  --accent-soft:  #2c1a22;
  --brass:        #d4906a;
  --brass-deep:   #8a5238;            /* deep rose copper */
  /* Polished gradient — rose gold leaf, more metallic than Walnut's */
  --gold-foil:    linear-gradient(135deg, #f4cdae 0%, #e8a886 25%, #d4906a 50%, #8a5238 80%, #f4cdae 100%);

  /* Mood — claret velvet, smoke, mauve. Deep saturated jewel tones. */
  --maraschino:   #8a2840;            /* claret */
  --maraschino-2: #a4385a;            /* lit claret */
  --burgundy:     #4a0c1c;            /* deep claret */
  --bottle:       #5a3a3a;            /* smoke gray with warm undertone */
  --bottle-2:     #745050;
  --absinthe:     #d4906a;            /* rose gold */
  --copper:       #c0784a;
  --rose-gold:    #d4906a;            /* primary rose gold */
  --neon-amber:   #e8a886;            /* lit rose gold */
  --red:          #8a2840;            /* claret, palette match */

  /* Spirit bands — anchored on rose-gold + claret. Whiskey takes rose
     gold (palette match). Wine is claret. Gin leans dusty olive for
     contrast without breaking the jewel-tone mood. */
  --spirit-whiskey:   #d4906a;        /* rose gold, palette match */
  --spirit-gin:       #98a890;        /* dusty olive */
  --spirit-rum:       #d08868;        /* warm rose copper */
  --spirit-agave:     #a8a890;        /* warm olive */
  --spirit-brandy:    #c08068;
  --spirit-vodka:     #d0b8a8;        /* champagne silver */
  --spirit-liqueur:   #a070a0;        /* mauve lavender */
  --spirit-aperitif:  #c84878;        /* claret blush */
  --spirit-vermouth:  #a85870;        /* dusty mauve */
  --spirit-wine:      #4a0c1c;        /* deep claret */
  --spirit-multi:     #e8a886;        /* lit rose gold */

  /* Display face — Didot, the natural typeface for fashion editorial.
     Upright (not italic — Velvet keeps the italic for cabaret theatrics).
     Boudoir is composed; Velvet is performing. */
  --serif-display: "Didot", "Bodoni 72", "Cormorant Garamond", "Hoefler Text", Georgia, serif;
  --radius:        2px;               /* sharp jewelers' edges */

  /* Ornament — ❦ fleuron heart. Letterpress / printer's mark, NOT a
     pastel flower. Distinct from Verdant's old ❀ and from any other
     theme's ornament. Reads as an old book's chapter divider. */
  --ornament-divider: "❦";
  --ornament-section: "❦";
  --dropcap-color:    #d4906a;        /* rose gold */
  --dropcap-shadow:   0 1px 0 rgba(0,0,0,0.65);

  /* Dropcap frame — thin rose-gold rim */
  --dropcap-frame-bg:      rgba(212, 144, 106, 0.08);
  --dropcap-frame-border:  1px solid rgba(212, 144, 106, 0.55);
  --dropcap-frame-radius:  2px;
  --dropcap-ornament-pre:  "";
  --dropcap-ornament-post: "";

  /* RGB tokens */
  --accent-rgb:    212, 144, 106;
  --maraschino-rgb: 138, 40, 64;
  --brass-rgb:     212, 144, 106;
  --bottle-rgb:    90, 58, 58;

  --on-accent:     #0a0608;           /* ink on rose gold */

  --print-edition-name: "Boudoir";

  /* Section-head plate — small fleuron-marked rectangle */
  --section-plate-glyph:  "❦";
  --section-plate-bg:     rgba(212, 144, 106, 0.10);
  --section-plate-border: 1px solid rgba(212, 144, 106, 0.50);
  --section-plate-radius: 2px;
  --section-plate-color:  #e8a886;

  --page-edge-color:      rgba(212, 144, 106, 0.55);

  /* Texture — silk weave. Crossed diagonal hairlines very faint to
     suggest woven satin. Distinct from every other theme. */
  --texture-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='40' height='40'><g stroke='%23d4906a' stroke-width='0.25' opacity='0.10'><line x1='0' y1='0' x2='40' y2='40'/><line x1='40' y1='0' x2='0' y2='40'/></g></svg>");
  --texture-size: 40px 40px;
}

/* 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 — FIRESIDE (v265, was Lodge/Chesterfield)
   Vermont ski-lodge bar at après-ski. The bar attached to a
   country inn at 9pm with snow falling outside. Pine paneling,
   hunter green carpet, brass lamps, hot-cocoa cups, a wood-
   burning stove. Cold-night warmth where Walnut is gilded-formal.
   ============================================================ */
[data-theme="lodge"] {
  /* v265 — REBUILT as FIRESIDE. Was "Chesterfield / Library club" —
     conceptually overlapped Walnut (both refined wood-paneled book
     rooms). Reframed as the bar attached to a Vermont ski-lodge inn
     at après-ski. Pine paneling, hunter green carpet, brass lamps,
     hot-cocoa cups, a wood-burning stove. Cold-night warmth where
     Walnut is gilded-formal. */

  /* Surfaces — pine-needle dark. Cool green-black, distinct from
     Walnut's warm brown. A bar attached to a country inn at 9pm
     with snow falling outside. */
  --bg:           #0e1a14;            /* pine-needle dark */
  --bg-2:         #14241c;            /* lifted pine */
  --bg-deep:      #060c08;
  --surface:      #1c2e22;            /* lit pine */
  --surface-2:    #243a2c;
  --surface-3:    #2e4a38;
  --paper:        #f0e6cc;            /* aged inn-menu paper */

  /* Type — cream linen on pine. */
  --ink:          #f0e6cc;
  --ink-bright:   #f8eed4;
  --ink-dim:      #b8a48c;
  --ink-faint:    #82725c;            /* AA 5.5:1 on bg */

  /* Hairlines — brass-on-pine seam */
  --rule:         #1c2e22;
  --rule-strong:  #2e4a38;
  --rule-faint:   rgba(200, 154, 82, 0.18);
  --rule-gold:    rgba(200, 154, 82, 0.55);

  /* Accents — BRASS-ON-PINE. Warmer than Walnut's gold-leaf (which
     is yellower) so the two warm themes don't blur. Reads as the
     glow of a brass lamp through pine-paneled walls. */
  --brass-light:  #e0b870;            /* lifted brass */
  --accent:       #c89a52;            /* brass-on-pine — hero */
  --accent-2:     #e0b870;
  --accent-soft:  #3a2a18;
  --brass:        #c89a52;
  --brass-deep:   #8a6a30;
  --gold-foil:    linear-gradient(135deg, #e8c684 0%, #e0b870 25%, #c89a52 50%, #8a6a30 80%, #e8c684 100%);

  /* Mood — hot cocoa, hunter green, snow */
  --maraschino:   #6a3a28;            /* hot cocoa brown */
  --maraschino-2: #844a35;
  --burgundy:     #401e14;
  --bottle:       #2c4a35;            /* hunter green */
  --bottle-2:     #406854;
  --absinthe:     #5c7a52;            /* mossy pine */
  --copper:       #b07840;            /* warm brass */
  --rose-gold:    #c8946a;
  --neon-amber:   #e0b056;            /* lamp glow */
  --red:          #8a2c20;            /* lacquer-red drink */

  /* Spirit bands — Fireside palette: warm bourbon-and-pine */
  --spirit-whiskey:   #c89a52;        /* brass, palette match */
  --spirit-gin:       #6a8a6a;        /* pine-leaning */
  --spirit-rum:       #c89060;
  --spirit-agave:     #80a070;
  --spirit-brandy:    #c87a50;
  --spirit-vodka:     #c0bcb0;        /* snow */
  --spirit-liqueur:   #9070a8;
  --spirit-aperitif:  #d06c50;
  --spirit-vermouth:  #a06458;
  --spirit-wine:      #6a1a18;
  --spirit-multi:     #c89a52;        /* brass, palette match */

  /* Display face — Charter. Humanist semi-slab, sturdy lodge feel.
     Distinct from Walnut's Iowan (more refined) and from Habana's
     Caslon (lighter). */
  --serif-display: "Charter", "Iowan Old Style", "Source Serif Pro", Georgia, serif;
  --radius:        4px;               /* hand-planed wood softness */

  /* Ornament — ✺ sun/flower starburst. Reads as a fire-spark, the
     scattered glow of the wood stove. Distinct from every other
     theme. */
  --ornament-divider: "✺";
  --ornament-section: "✺";
  --dropcap-color:    #c89a52;
  --dropcap-shadow:   0 1px 0 rgba(0,0,0,0.55);

  /* Dropcap frame — brass-rim plate */
  --dropcap-frame-bg:      rgba(200, 154, 82, 0.08);
  --dropcap-frame-border:  1px solid rgba(200, 154, 82, 0.55);
  --dropcap-frame-radius:  4px;
  --dropcap-ornament-pre:  "";
  --dropcap-ornament-post: "";

  /* RGB tokens */
  --accent-rgb:    200, 154, 82;
  --maraschino-rgb: 106, 58, 40;
  --brass-rgb:     200, 154, 82;
  --bottle-rgb:    44, 74, 53;

  --on-accent:     #0e1a14;           /* pine on brass */

  --print-edition-name: "Fireside";

  --section-plate-glyph:  "✺";
  --section-plate-bg:     rgba(200, 154, 82, 0.10);
  --section-plate-border: 1px solid rgba(200, 154, 82, 0.50);
  --section-plate-radius: 4px;
  --section-plate-color:  #e0b870;

  --page-edge-color:      rgba(200, 154, 82, 0.55);

  /* Texture — pine plank grain. Long horizontal pine-grain ovals
     (taller and thinner than Walnut's mahogany) to evoke vertical
     pine paneling rotated horizontally. */
  --texture-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='220' height='220'><g fill='%23c89a52' opacity='0.06'><ellipse cx='40' cy='28' rx='32' ry='0.6'/><ellipse cx='150' cy='34' rx='45' ry='0.55'/><ellipse cx='60' cy='58' rx='38' ry='0.65'/><ellipse cx='180' cy='66' rx='34' ry='0.55'/><ellipse cx='30' cy='90' rx='30' ry='0.6'/><ellipse cx='140' cy='98' rx='44' ry='0.65'/><ellipse cx='52' cy='122' rx='36' ry='0.55'/><ellipse cx='158' cy='130' rx='40' ry='0.6'/><ellipse cx='42' cy='154' rx='34' ry='0.55'/><ellipse cx='150' cy='162' rx='42' ry='0.65'/><ellipse cx='84' cy='186' rx='40' ry='0.55'/><ellipse cx='180' cy='194' rx='36' ry='0.6'/></g></svg>");
  --texture-size: 220px 220px;
}

/* ============================================================
   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"] {
  /* v265 — PUSHED. Was "Aperitivo" with a generic-cream bg and a soft
     Negroni orange accent — felt like a notebook, not specifically
     Italian aperitivo. This pass commits to the Milanese cafe at 6pm:
     travertine marble walls (warmer cream), true Campari red (deeper),
     terrazzo plum chips (existing), AND a real olive-leaf green
     (new) so the palette has 4 distinct colors that read together as
     a specific bar mood, not abstract "warm light." */

  /* Surfaces — travertine marble, warmer than the previous bone-white */
  --bg:           #f4ecd6;            /* travertine */
  --bg-2:         #ebe0c4;            /* lifted */
  --bg-deep:      #ddd0b2;
  --surface:      #faf2dc;            /* lit travertine */
  --surface-2:    #f6ecd0;
  --surface-3:    #ebe0c4;
  --paper:        #ffffff;            /* print-fidelity white */

  /* Ink stays charcoal — distinct text from the warm cream is what
     gives Aperitivo readability. */
  --ink:          #1c1814;
  --ink-bright:   #0e0a06;
  --ink-dim:      #5a4e3e;
  --ink-faint:    #6e5e48;

  --rule:         rgba(28, 24, 20, 0.14);
  --rule-strong:  rgba(28, 24, 20, 0.32);
  --rule-faint:   rgba(168, 56, 32, 0.24);
  --rule-gold:    rgba(168, 56, 32, 0.58);

  /* Accents — TRUE CAMPARI RED. Pushed from the v239 #b8421e
     (Negroni-orange leaning) to #a83820 (deeper, more wine-toned
     red — the actual Campari bottle color, not the diluted spritz).
     Still AA-compliant on travertine. */
  --brass-light:  #c84838;
  --accent:       #a83820;            /* Campari red — the hero */
  --accent-2:     #c84838;
  --accent-soft:  #fadfd0;
  --brass:        #a83820;
  --brass-deep:   #6c1c0a;
  --gold-foil:    linear-gradient(135deg, #c84838 0%, #a83820 30%, #6c1c0a 60%, #d05a40 100%);

  /* Mood — terrazzo plum + Italian olive (NEW). The olive is the
     differentiator — it's what makes the palette feel specifically
     Italian-aperitivo (olive-and-Campari-color combo) rather than
     generic warm-light. */
  --maraschino:   #5a2845;            /* terrazzo plum */
  --maraschino-2: #7a3a5c;
  --burgundy:     #401a30;
  --bottle:       #7a8a3a;            /* olive leaf — NEW HERO support */
  --bottle-2:     #94a44e;
  --absinthe:     #5a2845;
  --copper:       #a83820;
  --rose-gold:    #de8a64;
  --neon-amber:   #d4a234;
  --red:          #a83820;

  /* Spirit bands — Aperitivo palette, anchored on Campari red */
  --spirit-whiskey:   #a06038;
  --spirit-gin:       #4a6638;        /* olive-leaning */
  --spirit-rum:       #a05a32;
  --spirit-agave:     #6a7a3a;
  --spirit-brandy:    #a05230;
  --spirit-vodka:     #6a7080;
  --spirit-liqueur:   #5a2845;
  --spirit-aperitif:  #a83820;        /* Campari, palette match */
  --spirit-vermouth:  #983a48;
  --spirit-wine:      #6a1828;
  --spirit-multi:     #a83820;        /* Campari, palette match */

  /* Display — Cochin. Italian-Renaissance-feeling French serif,
     iOS-bundled. Distinct from Amber's Bodoni and Walnut's Iowan. */
  --serif-display: "Cochin", "Bodoni 72", "Didot", "Hoefler Text", Georgia, serif;
  --radius:        4px;

  /* Ornament — ✶ six-pointed star, terrazzo-chip motif */
  --ornament-divider: "✶";
  --ornament-section: "✶";
  --dropcap-color:    #a83820;
  --dropcap-shadow:   none;

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

  --accent-rgb:     168, 56, 32;      /* Campari red */
  --maraschino-rgb: 90, 40, 69;
  --brass-rgb:      168, 56, 32;
  --bottle-rgb:     122, 138, 58;     /* olive */

  --on-accent:        #f4ecd6;        /* travertine on Campari */

  /* v320 — Scrim override for Aperitivo (light theme). Same fix
     as Pineapple: dark-theme default rgba(0,0,0,0.78) overpowers
     travertine. Use a warm terracotta-tinted scrim instead. */
  --scrim:        rgba(58, 24, 20, 0.55);
  --scrim-soft:   rgba(58, 24, 20, 0.20);
  /* Vignette — terracotta low-alpha tint. */
  --vignette:     radial-gradient(ellipse 130% 100% at 50% 50%, transparent 55%, rgba(90, 40, 32, 0.10) 100%);

  --print-edition-name: "Aperitivo";

  --section-plate-glyph:  "✶";
  --section-plate-bg:     rgba(168, 56, 32, 0.12);
  --section-plate-border: 1px solid rgba(168, 56, 32, 0.45);
  --section-plate-radius: 50%;
  --section-plate-color:  #a83820;

  --page-edge-color:      rgba(168, 56, 32, 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='%231c1814' 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;
}

/* ============================================================
   THEME — Velvet (v206, Wave 88)
   Cabaret salon. Aubergine walls, magenta velvet curtains,
   antique-gold sconces, plum banquettes. Theatrical counterpart
   to Rosé — jewel tones, not Bordeaux warmth. Burlesque cocktail
   lounge. Display: Didot. Ornament: ✥ (Maltese heraldry).
   ============================================================ */
[data-theme="velvet"] {
  /* v232 — Velvet kept, palette rebuilt for burlesque-cabaret mood.
     Magenta curtain + saturated theatre purple + true gold gilt.
     v239 — bg shifted from v238's #261028 to #1c0830, fully into deep
     aubergine/eggplant. Was bg-distance 11 from Rosé (#2a1620) — both
     read as "dark with pink-wine accent" on a phone. Now bg-distance
     ~30+ from Rosé, clearly the purple-theater theme. */
  /* v265 — PUSHED HARDER. Velvet had the right idea (burlesque
     cabaret) but was half-committed. The hero was a muted gilt that
     read as "Walnut's-cousin-with-purple-bg"; the magenta played
     support. Pushed: magenta becomes the HERO accent, gilt the
     secondary. Saturation +20% across the board. The whole binding
     now reads as a theatre poster — saturated, theatrical, loud. */

  --bg:           #180428;            /* deeper stage aubergine */
  --bg-2:         #260840;
  --bg-deep:      #0c0214;
  --surface:      #381038;            /* magenta-tinged panel */
  --surface-2:    #481648;
  --surface-3:    #581c58;
  --paper:        #f6e8d4;

  --ink:          #f6e8d4;
  --ink-bright:   #fbf0e0;
  --ink-dim:      #c0a098;
  --ink-faint:    #a08488;

  --rule:         #381038;
  --rule-strong:  #581c58;
  --rule-faint:   rgba(232, 56, 94, 0.22);
  --rule-gold:    rgba(232, 56, 94, 0.60);

  /* Accents — CABARET CRIMSON-PINK as the new hero. Pushed from a
     muted #c4327a to a saturated #e8385e — the theatre-poster pink
     that catches the spotlight. True gilt #f0c038 (also brighter)
     plays accent-2 / secondary. */
  --brass-light:  #f44e74;
  --accent:       #e8385e;            /* cabaret crimson — new hero */
  --accent-2:     #f0c038;            /* true gilt — secondary */
  --accent-soft:  #3a0c1c;
  --brass:        #e8385e;
  --brass-deep:   #8a1c34;
  /* Magenta-to-gilt gradient — true theatre-poster ink */
  --gold-foil:    linear-gradient(135deg, #f44e74 0%, #e8385e 30%, #8a1c34 55%, #f0c038 100%);

  /* Mood — claret velvet, gilt, magenta drape */
  --maraschino:   #a8284c;            /* claret support */
  --maraschino-2: #c83864;
  --burgundy:     #6a0e2c;
  --bottle:       #5a2440;            /* plum drape */
  --bottle-2:     #7a3856;
  --absinthe:     #f0c038;            /* gilt */
  --copper:       #c84878;            /* warm magenta */
  --rose-gold:    #f088a8;
  --neon-amber:   #f0c038;            /* gilt */
  --red:          #e8385e;            /* cabaret pink */

  /* Spirit bands — pushed saturation, jewel-tone variation */
  --spirit-whiskey:   #f0c038;        /* gilt */
  --spirit-gin:       #b8b0a4;        /* warm silver */
  --spirit-rum:       #d49058;
  --spirit-agave:     #a8a878;
  --spirit-brandy:    #d47058;
  --spirit-vodka:     #d8c4d0;
  --spirit-liqueur:   #c068d4;        /* saturated purple */
  --spirit-aperitif:  #e8385e;        /* cabaret pink, palette match */
  --spirit-vermouth:  #c84878;
  --spirit-wine:      #a8284c;        /* claret, palette match */
  --spirit-multi:     #f0c038;        /* gilt, palette match */

  /* Display + geometry — Didot theatrical, 6px curtain corners */
  --serif-display: "Didot", "Bodoni 72", "Hoefler Text", Georgia, serif;
  --radius:        6px;

  /* Ornament — ✥ Maltese cross, heraldic theatre-poster mark.
     Kept from prior Velvet — it works. Just brighter color now. */
  --ornament-divider: "✥";
  --ornament-section: "✥";
  --dropcap-color:    #e8385e;        /* cabaret pink */
  --dropcap-shadow:   0 1px 0 rgba(0,0,0,0.65);

  --dropcap-frame-bg:      rgba(232, 56, 94, 0.14);
  --dropcap-frame-border:  1px solid rgba(232, 56, 94, 0.65);
  --dropcap-frame-radius:  4px;
  --dropcap-ornament-pre:  "";
  --dropcap-ornament-post: "";

  --accent-rgb:     232, 56, 94;       /* cabaret pink */
  --maraschino-rgb: 168, 40, 76;       /* claret */
  --brass-rgb:      232, 56, 94;
  --bottle-rgb:     90, 36, 64;

  --on-accent:        #180428;         /* aubergine on cabaret pink */

  --print-edition-name: "Velvet";

  --section-plate-glyph:  "✥";
  --section-plate-bg:     rgba(232, 56, 94, 0.14);
  --section-plate-border: 1px solid rgba(232, 56, 94, 0.55);
  --section-plate-radius: 4px;
  --section-plate-color:  #f0c038;     /* gilt secondary on section plates */

  --page-edge-color:      rgba(240, 192, 56, 0.55);   /* gilt edge gilding */

  /* Texture — velvet nap with both magenta + gilt flecks. The dual-
     ink texture is what tells you this binding is theatrical, not
     monochromatic — every flicker is a different stage light. */
  --texture-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='180' height='180'><g fill='%23e8385e' opacity='0.08'><circle cx='10' cy='14' r='0.55'/><circle cx='48' cy='20' r='0.6'/><circle cx='86' cy='24' r='0.55'/><circle cx='126' cy='22' r='0.6'/><circle cx='168' cy='26' r='0.55'/><circle cx='38' cy='52' r='0.6'/><circle cx='78' cy='56' r='0.55'/><circle cx='118' cy='58' r='0.6'/><circle cx='162' cy='60' r='0.55'/><circle cx='30' cy='86' r='0.55'/><circle cx='74' cy='88' r='0.55'/><circle cx='118' cy='90' r='0.55'/><circle cx='162' cy='92' r='0.55'/><circle cx='34' cy='118' r='0.6'/><circle cx='78' cy='120' r='0.55'/><circle cx='122' cy='122' r='0.6'/><circle cx='166' cy='124' r='0.55'/><circle cx='44' cy='152' r='0.6'/><circle cx='88' cy='154' r='0.55'/><circle cx='132' cy='156' r='0.6'/><circle cx='176' cy='158' r='0.55'/></g><g fill='%23f0c038' opacity='0.07'><circle cx='28' cy='6' r='0.45'/><circle cx='66' cy='10' r='0.45'/><circle cx='106' cy='8' r='0.5'/><circle cx='148' cy='12' r='0.45'/><circle cx='18' cy='40' r='0.45'/><circle cx='58' cy='42' r='0.5'/><circle cx='98' cy='44' r='0.45'/><circle cx='140' cy='48' r='0.5'/><circle cx='6' cy='74' r='0.55'/><circle cx='52' cy='76' r='0.5'/><circle cx='96' cy='78' r='0.55'/><circle cx='140' cy='80' r='0.5'/><circle cx='14' cy='106' r='0.5'/><circle cx='56' cy='108' r='0.45'/><circle cx='100' cy='110' r='0.45'/><circle cx='144' cy='112' r='0.45'/><circle cx='22' cy='140' r='0.5'/><circle cx='66' cy='142' r='0.45'/><circle cx='110' cy='144' r='0.45'/><circle cx='154' cy='146' r='0.45'/></g></svg>");
  --texture-size: 180px 180px;
}

/* ============================================================
   THEME — Copper (v206, Wave 88)
   Apothecary cabinet. Smoked-oak shelves, hammered-copper measure
   tins, sealing-wax red labels, parchment ink. Old-pharmacy
   cocktail mood — the bartender as compounding chemist. Display:
   Big Caslon. Ornament: ⚜ (fleur-de-lis, apothecary mark).
   ============================================================ */
[data-theme="copper"] {
  /* v232 — ID "copper" repurposed as "Habana". Tropical poster-bar mood:
     red leather banquette, brass-bell yellow, palm-tile teal wall.
     v238 — bg shifted from cigar-tobacco brown #251812 (which was
     bg-distance 2 from Chesterfield and 6 from Walnut — three warm-
     brown themes when there should be one) to a deep palm-green wall.
     Now Habana reads as the TROPICAL bar it's named for, not a fourth
     wood-paneled study. Red leather + brass + tile teal stay; the WALL
     just got greener. */
  --bg:           #0e2820;
  --bg-2:         #163328;
  --bg-deep:      #061812;
  --surface:      #1f3e30;
  --surface-2:    #28493a;
  --surface-3:    #345644;
  --paper:        #ece2c0;

  --ink:          #ece2c0;
  --ink-bright:   #fbf0c8;
  --ink-dim:      #b8a684;
  --ink-faint:    #8a7858;

  --rule:         #1c3328;
  --rule-strong:  #2c4438;
  --rule-faint:   rgba(204, 58, 48, 0.22);
  --rule-gold:    rgba(204, 58, 48, 0.55);

  /* Accents — v238: red leather as primary (was gold-yellow, which
     overlapped with Velvet's true gilt). 1950s-tropical-poster red is
     the iconic Habana signature. Brass-bell yellow demoted to accent-2
     (still present, no longer the hero color). */
  --brass-light:  #e85148;
  --accent:       #cc3a30;
  --accent-2:     #e85148;
  --accent-soft:  #3a1410;
  --brass:        #cc3a30;
  --brass-deep:   #8a2218;
  --gold-foil:    linear-gradient(135deg, #e85148 0%, #cc3a30 30%, #8a2218 60%, #f06860 100%);

  /* Mood — red leather banquette + palm-tile teal trim + brass-bell yellow.
     v238: maraschino is now the SAME as accent (red is the hero color). */
  --maraschino:   #cc3a30;
  --maraschino-2: #e85148;
  --burgundy:     #6a1610;
  --bottle:       #3a7060;
  --bottle-2:     #4a8a78;
  --absinthe:     #3a7060;
  --copper:       #d8a234;
  --rose-gold:    #e88660;
  --neon-amber:   #d8a234;
  --red:          #cc3a30;

  /* Spirit bands — Havana saturation */
  --spirit-whiskey:   #d4a058;
  --spirit-gin:       #4a8878;
  --spirit-rum:       #d4905a;
  --spirit-agave:     #6a9678;
  --spirit-brandy:    #d48058;
  --spirit-vodka:     #a8a89c;
  --spirit-liqueur:   #b078a8;
  --spirit-aperitif:  #d44a40;
  --spirit-vermouth:  #c46070;
  --spirit-wine:      #6a1610;
  --spirit-multi:     #ecbe5e;

  /* Display — Caslon italic, Cuban poster feel */
  --serif-display: "Caslon", "Big Caslon", "Hoefler Text", Georgia, serif;
  --radius:        2px;

  /* Ornament — rosette, tropical bloom */
  --ornament-divider: "❋";
  --ornament-section: "❋";
  --dropcap-color:    #cc3a30;
  --dropcap-shadow:   0 1px 0 rgba(0,0,0,0.55);

  --dropcap-frame-bg:      rgba(204, 58, 48, 0.12);
  --dropcap-frame-border:  1px solid rgba(204, 58, 48, 0.55);
  --dropcap-frame-radius:  2px;
  --dropcap-ornament-pre:  "";
  --dropcap-ornament-post: "";

  --accent-rgb:     204, 58, 48;
  --maraschino-rgb: 204, 58, 48;
  --brass-rgb:      216, 162, 52;
  --bottle-rgb:     58, 112, 96;

  --on-accent:        #f6e8d4;

  --print-edition-name: "Habana";

  --section-plate-glyph:  "❋";
  --section-plate-bg:     rgba(204, 58, 48, 0.12);
  --section-plate-border: 1px solid rgba(204, 58, 48, 0.45);
  --section-plate-radius: 2px;
  --section-plate-color:  #cc3a30;

  --page-edge-color:      rgba(204, 58, 48, 0.55);

  /* Texture — tropical tile pattern. v238 — re-tinted to brass-bell
     yellow (secondary accent) so the wall still has gold sparkle even
     though the primary accent is now red leather. The dimpled ellipses
     read as gold-bell glints on the palm-green wall. */
  --texture-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='200' height='200'><g fill='%23d8a234' opacity='0.06'><ellipse cx='14' cy='18' rx='3' ry='1' transform='rotate(20 14 18)'/><ellipse cx='44' cy='28' rx='3.2' ry='1.1' transform='rotate(-30 44 28)'/><ellipse cx='74' cy='16' rx='2.8' ry='0.9' transform='rotate(40 74 16)'/><ellipse cx='106' cy='30' rx='3.4' ry='1' transform='rotate(-20 106 30)'/><ellipse cx='138' cy='20' rx='3' ry='1.1' transform='rotate(35 138 20)'/><ellipse cx='168' cy='32' rx='3.2' ry='1' transform='rotate(-15 168 32)'/><ellipse cx='24' cy='58' rx='3.6' ry='1.2' transform='rotate(50 24 58)'/><ellipse cx='58' cy='68' rx='3' ry='1' transform='rotate(-40 58 68)'/><ellipse cx='90' cy='58' rx='3.4' ry='1.1' transform='rotate(25 90 58)'/><ellipse cx='122' cy='72' rx='3.2' ry='1' transform='rotate(-50 122 72)'/><ellipse cx='154' cy='60' rx='3.6' ry='1.2' transform='rotate(15 154 60)'/><ellipse cx='184' cy='74' rx='3' ry='1' transform='rotate(-25 184 74)'/><ellipse cx='12' cy='98' rx='3.2' ry='1.1' transform='rotate(45 12 98)'/><ellipse cx='42' cy='108' rx='3.6' ry='1.2' transform='rotate(-30 42 108)'/><ellipse cx='74' cy='98' rx='3' ry='1' transform='rotate(40 74 98)'/><ellipse cx='108' cy='112' rx='3.4' ry='1.1' transform='rotate(-15 108 112)'/><ellipse cx='140' cy='100' rx='3.2' ry='1' transform='rotate(35 140 100)'/><ellipse cx='172' cy='114' rx='3.6' ry='1.2' transform='rotate(-45 172 114)'/><ellipse cx='22' cy='138' rx='3' ry='1' transform='rotate(20 22 138)'/><ellipse cx='54' cy='148' rx='3.4' ry='1.1' transform='rotate(-25 54 148)'/><ellipse cx='86' cy='138' rx='3.2' ry='1' transform='rotate(50 86 138)'/><ellipse cx='118' cy='152' rx='3.6' ry='1.2' transform='rotate(-40 118 152)'/><ellipse cx='150' cy='140' rx='3' ry='1' transform='rotate(15 150 140)'/><ellipse cx='182' cy='154' rx='3.4' ry='1.1' transform='rotate(-20 182 154)'/><ellipse cx='14' cy='178' rx='3.2' ry='1' transform='rotate(45 14 178)'/><ellipse cx='46' cy='188' rx='3.6' ry='1.2' transform='rotate(-35 46 188)'/><ellipse cx='78' cy='178' rx='3' ry='1' transform='rotate(30 78 178)'/><ellipse cx='110' cy='192' rx='3.4' ry='1.1' transform='rotate(-50 110 192)'/><ellipse cx='142' cy='180' rx='3.2' ry='1' transform='rotate(10 142 180)'/><ellipse cx='174' cy='194' rx='3.6' ry='1.2' transform='rotate(-25 174 194)'/></g></svg>");
  --texture-size: 200px 200px;
}

* { 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="platinum"] .input[type=date],
[data-theme="platinum"] .input[type=time],
[data-theme="platinum"] .input[type=datetime-local],
[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="platinum"] .view-header::after,
[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="platinum"] .view-title,
[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="platinum"] .ingredient-list .amount,
[data-theme="ivory"] .ingredient-list .amount,
[data-theme="platinum"] .brand-mark,
[data-theme="ivory"] .brand-mark,
[data-theme="platinum"] .brand-name,
[data-theme="ivory"] .brand-name,
[data-theme="platinum"] .card-thumb,
[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 {
  font-size: 11px; 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;
  min-height: 36px;
}
.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;
  min-height: 28px;
  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. */
[data-theme="platinum"] .detail-section h4::before {
  font-size: 11px;
}
[data-theme="verdant"] .detail-section h4::before {
  font-size: 8px;
}
[data-theme="amber"] .detail-section h4::before {
  font-size: 10px;
}
/* v109 — Onyx mid-dot is thin and centered already; bump up so it reads
   as a deliberate mark, not a typo. Rosé flower needs a downscale like
   Verdant's laurel — same glyph family. */
[data-theme="onyx"] .detail-section h4::before {
  font-size: 14px;
  line-height: 1;
}
[data-theme="rose"] .detail-section h4::before {
  font-size: 8px;
}
/* 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="lodge"] .detail-section h4::before {
  font-size: 9px;
}
[data-theme="ivory"] .detail-section h4::before {
  font-size: 8px;
}
[data-theme="velvet"] .detail-section h4::before {
  font-size: 10px;
}
[data-theme="copper"] .detail-section h4::before {
  font-size: 10px;
}
.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 {
  font-size: 9px; letter-spacing: 0.22em; text-transform: uppercase;
  color: var(--ink-faint);
  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);
  font-size: 10px;
  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);
  font-size: 10.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-faint);
  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;
  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. */
[data-theme="platinum"] .section-mark {
  letter-spacing: 8px;
  font-size: 14px;
}

/* Maison Premiere: laurel-flower ornament reads bigger; tone it down. */
[data-theme="verdant"] .section-mark {
  font-size: 16px;
  letter-spacing: 6px;
}

/* Smuggler's Cove: compass star reads loud — keep tight. */
[data-theme="amber"] .section-mark {
  font-size: 17px;
  letter-spacing: 6px;
}

/* v109 — Onyx mid-dot is a thin glyph; bump size and widen spacing so
   the section mark reads as deliberate punctuation, not a flyspeck. */
[data-theme="onyx"] .section-mark {
  font-size: 20px;
  letter-spacing: 12px;
  line-height: 1;
}

/* v109 — Rosé pressed-flower: same family as Verdant's laurel,
   downscale to match. */
[data-theme="rose"] .section-mark {
  font-size: 15px;
  letter-spacing: 7px;
}

/* 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="lodge"] .section-mark {
  font-size: 16px;
  letter-spacing: 7px;
}
[data-theme="ivory"] .section-mark {
  font-size: 15px;
  letter-spacing: 7px;
}
[data-theme="velvet"] .section-mark {
  font-size: 18px;
  letter-spacing: 9px;
}
[data-theme="copper"] .section-mark {
  font-size: 16px;
  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 */
  .chip {
    min-height: 36px;
  }
}

/* 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; }
