/* cocktails — page-specific styles. Shared fonts/colors/reset live in base.css. */

  :root {
    /* Premium dark charcoal + warm cream + muted copper.
       Boutique hotel bar meets premium editorial spirits brand. */
    --transition-slow: 950ms cubic-bezier(0.7, 0, 0.2, 1);

    /* === Stage placement (tweak these if alignment looks off) ===
       Bottle and cocktail are CENTER-ANCHORED as a side-by-side pair
       on the table (see .bottle and .cocktail-stack rules below).
       Only the vertical position is tunable here. */
    --table-bottom: 5%;        /* table image distance from floor */
    /* Both bottle and cocktail anchor to the SAME % so they sit on the
       same wood surface. Table size tuned so wood top lands here.
       Tune in 1-2% increments if either floats or sinks. */
    --bottle-bottom: 48%;
    --cocktail-bottom: 48%;

    /* === Stage zoom (close-up dial) ===
       ONE number controls how big the table + bottle + cocktail render
       on the page. 1.0 = original sizing. 1.5 = close-up.
       Dropped from 1.5 → 1.0 — at 1.5 the bottle was 450px+ tall and
       clipping above the viewport. Re-raise carefully (1.1, 1.2…)
       and check that the bottle top stays in the visible stage. */
    --stage-scale: 1.0;

    /* === Gap between bottle and cocktail (single knob) ===
       Tune how close the bottle sits to the cocktail glass.
       POSITIVE = visible gap between the two containers.
       NEGATIVE = containers OVERLAP (useful when the bottle PNG has
       lots of transparent horizontal padding pushing the visible
       bottle into the middle of its container — overlapping pulls
       the visible items closer).
         12px  = original spacing
         0     = containers touch
        -60px  = visible bottle and cocktail look adjacent
        -100px = they nearly touch / slight overlap of glass + bottle
       Try -60 first; nudge in 20px increments.
       Reset to a small POSITIVE gap (12px) now that the bottle PNG is
       tightly cropped — the visible bottle is at the container edge,
       so no overlap compensation needed. */
    --pair-gap: 12px;
  }

  html, body {
    height: 100%;
    overflow: hidden;
    background: #000;
    color: var(--cream);
    font-family: 'Helvetica Neue LT Std', sans-serif;
    font-weight: 300;
    -webkit-font-smoothing: antialiased;
  }

  /* ================ STAGE ================ */
  .stage {
    position: relative;
    width: 100%;
    height: 100vh;
    background:
      radial-gradient(ellipse at 35% 45%, rgba(216, 184, 138, 0.10) 0%, transparent 50%),
      radial-gradient(ellipse at 70% 60%, rgba(216, 184, 138, 0.05) 0%, transparent 45%),
      linear-gradient(180deg, #050403 0%, #0d0a07 60%, #000 100%);
    overflow: hidden;
  }

  /* Film grain — adds tactile boutique-bar character */
  .texture-grain {
    position: absolute; inset: 0;
    pointer-events: none;
    z-index: 1;
    opacity: 0.18;
    mix-blend-mode: screen;
    background-image: url('../images/texture-grain.png');
    background-size: 256px 256px;
    background-repeat: repeat;
  }

  .dust {
    position: absolute; inset: 0;
    pointer-events: none;
    background-image:
      radial-gradient(1px 1px at 20% 30%, rgba(216, 184, 138, 0.5), transparent),
      radial-gradient(1px 1px at 80% 70%, rgba(216, 184, 138, 0.35), transparent),
      radial-gradient(1px 1px at 60% 20%, rgba(216, 184, 138, 0.4), transparent),
      radial-gradient(1px 1px at 40% 80%, rgba(216, 184, 138, 0.3), transparent),
      radial-gradient(1px 1px at 90% 40%, rgba(216, 184, 138, 0.4), transparent);
    opacity: 0.55;
    animation: drift 22s linear infinite;
  }
  @keyframes drift {
    0%, 100% { transform: translate3d(0,0,0); }
    50%      { transform: translate3d(-10px, -8px, 0); }
  }

  /* ================ HEADER ================ */
  header {
    position: absolute;
    top: 0; left: 0; right: 0;
    padding: 32px 56px;
    display: flex; align-items: center; justify-content: space-between;
    z-index: 30;
  }
  .brand {
    height: 36px;
    width: auto;
    display: block;
    /* superfly-logo.png is now a true transparent PNG (RGBA, 2828×411) —
       mix-blend-mode hack no longer needed and was causing subtle edge
       artifacts on retina. */
    filter: drop-shadow(0 1px 0 rgba(0,0,0,0.4));
  }
  .header-tagline {
    font-family: 'Helvetica Neue LT Std', sans-serif;
    font-weight: 500;
    font-size: 11px;
    letter-spacing: 0.4em;
    text-transform: uppercase;
    color: var(--cream-dim);
    padding-bottom: 6px;
    border-bottom: 1px solid var(--gold);
  }

  /* ============ DESKTOP NAV (hidden on mobile — see media query) ============ */
  .header-nav {
    display: flex;
    align-items: center;
    gap: 26px;
  }
  .header-nav a {
    font-family: 'Helvetica Neue LT Std', sans-serif;
    font-weight: 400;
    font-size: 10.5px;
    letter-spacing: 0.25em;
    text-transform: uppercase;
    color: var(--cream-dim);
    text-decoration: none;
    transition: color 200ms;
  }
  .header-nav a:hover,
  .header-nav a.active { color: var(--gold); }
  .header-nav a.btn {
    border: 1px solid var(--gold);
    color: var(--gold);
    padding: 10px 20px;
  }
  .header-nav a.btn:hover { background: var(--gold); color: #0d0a07; }

  /* ============ MOBILE HAMBURGER MENU ============
     Hidden on desktop (cocktail page header just shows logo + tagline);
     shown on mobile so users can navigate away from the page.
     site.js's initMobileNav auto-wires open/close behavior. */
  .nav-toggle {
    display: none;
    background: transparent;
    border: 1px solid rgba(243, 234, 216, 0.25);
    width: 42px; height: 42px;
    padding: 0;
    cursor: pointer;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 5px;
    transition: border-color 200ms;
  }
  .nav-toggle:hover { border-color: var(--gold); }
  .nav-toggle span {
    display: block;
    width: 18px; height: 1.5px;
    background: var(--cream);
    transition: transform 250ms, opacity 250ms;
  }
  body.nav-open .nav-toggle span:nth-child(1) { transform: translateY(6.5px) rotate(45deg); }
  body.nav-open .nav-toggle span:nth-child(2) { opacity: 0; }
  body.nav-open .nav-toggle span:nth-child(3) { transform: translateY(-6.5px) rotate(-45deg); }

  .mobile-drawer {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(5, 4, 3, 0.97);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    z-index: 60;
    opacity: 0;
    pointer-events: none;
    transition: opacity 350ms;
  }
  body.nav-open .mobile-drawer {
    opacity: 1;
    pointer-events: auto;
  }
  .mobile-drawer-inner {
    height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: 28px;
    padding: 80px 24px;
  }
  .mobile-drawer a {
    font-family: 'Helvetica Neue LT Std', sans-serif;
    font-weight: 400;
    font-size: 14px;
    letter-spacing: 0.3em;
    text-transform: uppercase;
    color: var(--cream);
    text-decoration: none;
    padding: 12px 18px;
    transition: color 200ms;
  }
  .mobile-drawer a:hover, .mobile-drawer a:focus,
  .mobile-drawer a.active { color: var(--gold); }
  .mobile-drawer a.btn {
    border: 1px solid var(--gold);
    color: var(--gold);
    padding: 14px 32px;
    margin-top: 18px;
  }

  /* ================ MAIN LAYOUT ================ */
  .scene {
    position: absolute;
    inset: 0;
    display: grid;
    grid-template-columns: 60% 40%;
    z-index: 5;
  }

  /* ============ VISUAL STAGE (table + bottle + cocktail) ============ */
  .visual-stage {
    position: relative;
    overflow: visible;
    height: 100%;
  }

  /*
    POSITIONING NOTES — every value is relative to the visual-stage height.
    The table image is 360×360 (square). The wooden TOP-SURFACE sits at
    ~87.5% UP from the bottom of the image (12.5% from the top).

    Layout from bottom of stage (with table size = min(50%, 50vh)):
      0%   ................ floor
      5%   ................ table image starts (gold base at bottom)
      ~48.75% ............. wooden table-top surface (bottle/cocktail land here)
      ~55% ................ table image ends (top of the wood circle)
  */

  /* Table — sized to roughly fill the lower half of the visual stage,
     leaving room for bottle + cocktail to stand above it. */
  .table {
    position: absolute;
    left: 50%;
    bottom: var(--table-bottom);
    transform: translateX(-50%);
    /* PURE 50vh sizing — width and (via aspect-ratio) height are both tied
       to viewport HEIGHT, so the wood top always lands at a constant
       percentage of the stage (5% table-bottom + 87.5% × 50vh = 48.75% from
       stage bottom). The bottle/cocktail are anchored at bottom: 48%, so
       they always plant on the wood top regardless of viewport size.
       Earlier formulas mixed width-based (50% / 500px max) and height-based
       (50vh) constraints — on TALL viewports the 500px width cap won, the
       table got shorter relative to the stage, and the bottle floated. */
    width: calc(50vh * var(--stage-scale));
    aspect-ratio: 1 / 1;
    z-index: 2;
    pointer-events: none;
  }
  .table img {
    width: 100%; height: 100%;
    object-fit: contain;
    object-position: bottom center;
    display: block;
    mix-blend-mode: lighten;
    filter: drop-shadow(0 30px 30px rgba(0,0,0,0.7));
  }
  /* Soft halo behind the table */
  .table-halo {
    position: absolute;
    left: 50%;
    bottom: var(--table-bottom);
    transform: translateX(-50%);
    width: calc(clamp(440px, 68%, 700px) * var(--stage-scale));
    height: calc(55% * var(--stage-scale));
    background: radial-gradient(ellipse at center 60%,
      rgba(216, 184, 138, 0.14) 0%,
      rgba(216, 184, 138, 0.05) 30%,
      transparent 65%);
    z-index: 1;
    filter: blur(12px);
    pointer-events: none;
  }

  /* Bottle — sits on the LEFT half of the table top.
     Width clamp tuned for the new portrait-crop bottle WebP (1:3.92). The
     previous clamp was sized for a 1:1 image where ~64% of the canvas was
     empty space; with the new image filling the frame, the same container
     would render the bottle ~3x larger. These values bring it back close
     to the old visual size while keeping the new image's proper proportions. */
  .bottle {
    position: absolute;
    bottom: var(--bottle-bottom);
    /* Center-anchor the PAIR (bottle + cocktail) on the table.
       Bottle sits LEFT of dead-center; cocktail sits RIGHT of center.
       --pair-gap (set in :root) controls the visual distance between
       them. Negative values overlap the containers (helpful when the
       bottle PNG has transparent horizontal padding pushing the
       visible bottle into the middle of its container). */
    left: 50%;
    right: auto;
    transform: translateX(calc(-100% - (var(--pair-gap) / 2)));
    /* Bottle reverted to clamp(31, 4.8%, 48) — bottle was fine, cocktail
       was the problem. Bottle here is the dominant element. */
    width: calc(clamp(31px, 4.8%, 48px) * var(--stage-scale));
    aspect-ratio: 328 / 1500;
    z-index: 5;
    pointer-events: none;
  }
  @keyframes bottleIdle {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-3px); }
  }
  .bottle img {
    width: 100%; height: 100%;
    object-fit: contain;
    object-position: bottom center;
    display: block;
    /* mix-blend-mode removed: the new bottle WebP has a real alpha channel and
       'lighten' would draw a faint box around the image bounds. */
    filter: drop-shadow(0 18px 14px rgba(0,0,0,0.65));
  }

  /* Cocktail frames — sit right beside the bottle on the table top, animated.
     Center-anchored alongside the bottle. --pair-gap (set in :root)
     controls the visual distance between bottle and cocktail. */
  .cocktail-stack {
    position: absolute;
    /* lower than bottle to compensate for empty space below glass in photos */
    bottom: var(--cocktail-bottom);
    left: 50%;
    right: auto;
    transform: translateX(calc(var(--pair-gap) / 2));
    /* Cocktail container aspect set to TALLEST cocktail (kiwi-spritz 291/578)
       after auto-crop. Other glasses are shorter and sit anchored at bottom
       with empty space at top — realistic since glass shapes differ.
       Width clamp SHRUNK from (42, 6.6%, 66) to compensate for the auto-crop:
       previously, the PNG had ~28% transparent horizontal padding so the
       visible glass was only ~72% of container width (e.g., 47.5px visible
       in a 66px container). After tight crop, container width = visible
       width, so the container must be ~72% as wide to keep the visible
       glass at the previously-tuned size. */
    width: calc(clamp(42px, 6.4%, 64px) * var(--stage-scale));
    aspect-ratio: 291 / 578;
    z-index: 6;
    pointer-events: none;
  }
  .cocktail-frame {
    position: absolute;
    inset: 0;
    opacity: 0;
    transform: translateX(60px) scale(0.92);
    transition: opacity var(--transition-slow), transform var(--transition-slow);
  }
  .cocktail-frame.active {
    opacity: 1;
    transform: translateX(0) scale(1);
  }
  /* SAFETY-NET: if JS hasn't applied .active to the first frame yet
     (or fails entirely), make the first child of .cocktail-stack
     visible by default. Without this, cocktails are invisible when
     the page loads via file:// (CORS blocks fetch) or if cocktails.js
     hits an error.
     :not(.exit-left) is critical — without it, the safety-net's higher
     specificity (0,2,1 vs 0,2,0) overrode the .exit-left rule, so the
     Vesper (first child) never animated out and stayed visible behind
     subsequent cocktails. */
  .cocktail-stack > .cocktail-frame:first-child:not(.exit-left) {
    opacity: 1;
    transform: translateX(0) scale(1);
  }
  .cocktail-frame.exit-left {
    opacity: 0;
    transform: translateX(-60px) scale(0.92);
  }
  .cocktail-frame img {
    width: 100%; height: 100%;
    object-fit: contain;
    object-position: bottom center;
    display: block;
    /* mix-blend-mode removed — was needed for the OLD cocktail PNGs
       that had dark glass shadows blending into the page bg. New
       PNGs are tightly cropped with proper alpha, so they render
       naturally. Adding it back made the new cocktails invisible
       because any pixel darker than the dark page bg got erased. */
    filter: drop-shadow(0 18px 18px rgba(0,0,0,0.65));
  }

  /* Newer batch of cocktail photos (Aug 2026) are all 500×600 (0.83 ratio) —
     wider/shorter than the ~0.5 portrait ratio the frame is tuned for, so
     object-fit: contain shrinks them more than the older glass cutouts.
     Same fix as Moscow Mule above, just a smaller bump since these aren't
     as extreme a mismatch. */
  .cocktail-frame img[src*="cocktail-cucumber-mint"],
  .cocktail-frame img[src*="cocktail-berry-bliss"],
  .cocktail-frame img[src*="cocktail-classic-martini"],
  .cocktail-frame img[src*="cocktail-dirty-martini"],
  .cocktail-frame img[src*="cocktail-lime-drop"],
  .cocktail-frame img[src*="cocktail-basil-lemon-drop"],
  .cocktail-frame img[src*="cocktail-strawberry-lemon-drop"],
  .cocktail-frame img[src*="cocktail-lavender-lemon-drop"],
  .cocktail-frame img[src*="cocktail-blueberry-basil-lemon-drop"],
  .cocktail-frame img[src*="cocktail-pom-pom"],
  .cocktail-frame img[src*="cocktail-chocolate-martini"],
  .cocktail-frame img[src*="cocktail-dresden"],
  .cocktail-frame img[src*="cocktail-cuban-missile-crisis"],
  .cocktail-frame img[src*="cocktail-oregon-ass"],
  .cocktail-frame img[src*="cocktail-superfly-press"],
  .cocktail-frame img[src*="cocktail-sexy-beach"],
  .cocktail-frame img[src*="cocktail-screwberry"],
  .cocktail-frame img[src*="cocktail-starburst"],
  .cocktail-frame img[src*="cocktail-dreamsicle"],
  .cocktail-frame img[src*="cocktail-raspberry-sherbet"],
  .cocktail-frame img[src*="cocktail-hibiscus-fizz"],
  .cocktail-frame img[src*="cocktail-maui-wowie"] {
    transform: scale(1.2);
    transform-origin: bottom center;
  }

  /* ============ TEXT STAGE (right side) ============ */
  .text-stage {
    position: relative;
    overflow: hidden;
    padding: 130px 80px 100px 0;
    display: flex;
    align-items: center;
  }

  .slides-wrap {
    position: relative;
    width: 100%;
    height: 100%;
  }

  .slide {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    justify-content: center;
    opacity: 0;
    transform: translateX(70px);
    transition: opacity var(--transition-slow), transform var(--transition-slow);
    pointer-events: none;
  }
  .slide.active {
    opacity: 1;
    transform: translateX(0);
    pointer-events: auto;
  }
  .slide.exit-left {
    opacity: 0;
    transform: translateX(-70px);
  }

  .step-label {
    font-family: 'Helvetica Neue LT Std', sans-serif;
    font-weight: 500;
    font-size: 10px;
    letter-spacing: 0.5em;
    color: var(--gold);
    text-transform: uppercase;
    margin-bottom: 18px;
    display: flex; align-items: center; gap: 14px;
  }
  .step-label::before {
    content: '';
    width: 36px; height: 1px;
    background: var(--gold);
  }
  .cocktail-name {
    font-family: 'Whiskey Jill', 'neue-haas-grotesk-display', 'Neue Haas Grotesk Display Pro', serif;
    font-size: clamp(48px, 6vw, 84px);
    line-height: 1.0;
    font-weight: 400;
    margin-bottom: 14px;
    letter-spacing: 0.005em;
  }
  .cocktail-name em {
    font-family: 'Whiskey Jill', 'neue-haas-grotesk-display', 'Neue Haas Grotesk Display Pro', serif;
    font-style: normal;
    font-weight: 400;
    color: var(--gold);
  }
  .cocktail-name em {
    font-style: italic;
    font-weight: 700;
    color: var(--gold);
  }
  .tagline {
    font-family: 'Helvetica Neue LT Std', sans-serif;
    font-style: italic;
    font-size: 18px;
    color: var(--cream-dim);
    margin-bottom: 26px;
    font-weight: 300;
    letter-spacing: 0.005em;
  }
  .description {
    font-family: 'Helvetica Neue LT Std', sans-serif;
    font-weight: 300;
    font-size: 14px;
    line-height: 1.75;
    color: var(--cream-dim);
    margin-bottom: 26px;
    max-width: 440px;
  }
  .ingredients { list-style: none; margin-bottom: 22px; }
  .ingredients li {
    font-family: 'Helvetica Neue LT Std', sans-serif;
    font-weight: 300;
    font-size: 13px;
    letter-spacing: 0.06em;
    padding: 9px 0;
    border-bottom: 1px solid rgba(244, 239, 230, 0.08);
    display: flex; justify-content: space-between;
    color: var(--cream);
  }
  .ingredients li span:last-child {
    font-family: 'Helvetica Neue LT Std', sans-serif;
    font-style: italic;
    font-weight: 300;
    color: var(--gold);
    font-size: 15px;
    letter-spacing: 0;
  }
  .recipe-toggle {
    background: transparent;
    border: 1px solid var(--gold);
    color: var(--gold);
    padding: 12px 26px;
    font-size: 10px;
    letter-spacing: 0.3em;
    text-transform: uppercase;
    cursor: pointer;
    transition: all 200ms;
    font-family: 'Helvetica Neue LT Std', sans-serif;
    font-weight: 500;
    align-self: flex-start;
    margin-top: 6px;
  }
  .recipe-toggle:hover {
    background: var(--gold);
    color: #0d0a07;
  }

  /* ============ NAV CONTROLS ============ */
  .nav-controls {
    position: absolute;
    bottom: 5vh;
    right: 60px;
    display: flex;
    align-items: center;
    gap: 24px;
    z-index: 25;
  }
  .arrow-btn {
    width: 50px; height: 50px;
    border-radius: 50%;
    border: 1px solid rgba(244, 239, 230, 0.25);
    background: rgba(0,0,0,0.3);
    color: var(--cream);
    cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    transition: all 250ms;
    backdrop-filter: blur(4px);
  }
  .arrow-btn:hover {
    border-color: var(--gold);
    color: var(--gold);
    transform: scale(1.06);
  }
  .arrow-btn:disabled { opacity: 0.25; cursor: not-allowed; }
  .arrow-btn svg { width: 17px; height: 17px; }

  .progress {
    display: flex; align-items: center; gap: 8px;
    margin-right: 4px;
  }
  .progress-current {
    font-family: 'neue-haas-grotesk-display', 'Neue Haas Grotesk Display Pro', sans-serif;
    font-style: italic;
    font-size: 32px;
    color: var(--gold);
    font-weight: 700;
    line-height: 1;
  }
  .progress-divider {
    width: 28px; height: 1px;
    background: var(--cream-dim);
    margin: 0 4px;
  }
  .progress-total {
    font-family: 'Helvetica Neue LT Std', sans-serif;
    font-weight: 300;
    font-size: 13px;
    color: var(--cream-dim);
  }

  /* ============ NAV RAIL (category tabs + dot nav) ============
     Grew from 8 cocktails to 30 (Aug 2026) — grouped into categories
     (Originals / Martinis / Pints & Refreshers) with tabs above the dot
     column so picking a category filters the dots down to a manageable
     handful instead of one long scrolling list of 30. */
  .nav-rail {
    position: absolute;
    left: 32px;
    top: 50%;
    transform: translateY(-50%);
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 16px;
    z-index: 20;
    max-height: 76vh;
  }
  .category-tabs {
    display: flex;
    flex-direction: column;
    gap: 10px;
  }
  .category-tab {
    background: rgba(244, 239, 230, 0.06);
    border: 1.5px solid rgba(244, 239, 230, 0.4);
    border-radius: 999px;
    color: var(--cream);
    font-family: 'Helvetica Neue LT Std', sans-serif;
    font-weight: 700;
    font-size: 13px;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    text-align: left;
    padding: 12px 26px;
    cursor: pointer;
    transition: all 250ms;
    white-space: nowrap;
  }
  .category-tab:hover {
    border-color: var(--gold);
    color: var(--gold);
    background: rgba(216, 184, 138, 0.1);
  }
  .category-tab.active {
    background: var(--gold);
    border-color: var(--gold);
    color: var(--bg-1);
    box-shadow: 0 0 0 4px rgba(216, 184, 138, 0.18);
  }
  .dot-nav {
    display: flex;
    flex-direction: column;
    gap: 10px;
    overflow-y: auto;
    max-height: 60vh;
    padding: 4px 0;
    scrollbar-width: none;
  }
  .dot-nav::-webkit-scrollbar { display: none; }
  .dot {
    width: 8px; height: 8px;
    flex-shrink: 0;
    border-radius: 50%;
    background: rgba(244, 239, 230, 0.2);
    border: none;
    cursor: pointer;
    transition: all 300ms;
    position: relative;
  }
  .dot::after {
    content: attr(data-label);
    position: absolute;
    left: 22px; top: 50%;
    transform: translateY(-50%);
    font-family: 'Helvetica Neue LT Std', sans-serif;
    font-weight: 500;
    font-size: 9px;
    letter-spacing: 0.3em;
    text-transform: uppercase;
    color: var(--cream-dim);
    white-space: nowrap;
    opacity: 0;
    transition: opacity 200ms;
    pointer-events: none;
  }
  .dot:hover::after { opacity: 1; }
  .dot:hover { background: var(--gold); }
  .dot.active {
    background: var(--gold);
    transform: scale(1.4);
    box-shadow: 0 0 0 4px rgba(216, 184, 138, 0.15);
  }

  /* ============ MODAL ============ */
  .modal-backdrop {
    position: fixed; inset: 0;
    background: rgba(0,0,0,0.85);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    opacity: 0;
    pointer-events: none;
    transition: opacity 350ms;
    z-index: 100;
    display: flex; align-items: center; justify-content: center;
    padding: 60px;
  }
  .modal-backdrop.open { opacity: 1; pointer-events: auto; }
  .modal {
    max-width: 560px; width: 100%;
    background: linear-gradient(180deg, #1a140e 0%, #0a0807 100%);
    border: 1px solid rgba(216, 184, 138, 0.3);
    padding: 60px 56px;
    position: relative;
    transform: translateY(30px);
    opacity: 0;
    transition: all 400ms cubic-bezier(0.2, 0.8, 0.2, 1);
  }
  .modal-backdrop.open .modal {
    transform: translateY(0); opacity: 1;
  }
  .modal-close {
    position: absolute;
    top: 18px; right: 18px;
    width: 36px; height: 36px;
    border: none; background: transparent;
    color: var(--cream-dim);
    font-size: 24px; cursor: pointer;
  }
  .modal-close:hover { color: var(--gold); }
  .modal h3 {
    font-family: 'neue-haas-grotesk-display', 'Neue Haas Grotesk Display Pro', sans-serif;
    font-size: 38px;
    margin-bottom: 26px;
    font-weight: 700;
    letter-spacing: -0.02em;
  }
  .modal h3 em {
    color: var(--gold);
    font-style: italic;
    font-weight: 700;
  }
  .modal ol { list-style: none; counter-reset: step; }
  .modal ol li {
    counter-increment: step;
    padding: 16px 0 16px 50px;
    position: relative;
    border-top: 1px solid rgba(244, 239, 230, 0.08);
    font-family: 'Helvetica Neue LT Std', sans-serif;
    font-weight: 300;
    font-size: 14px;
    line-height: 1.7;
  }
  .modal ol li::before {
    content: counter(step, decimal-leading-zero);
    position: absolute;
    left: 0; top: 14px;
    font-family: 'neue-haas-grotesk-display', 'Neue Haas Grotesk Display Pro', sans-serif;
    font-style: italic;
    font-size: 22px;
    color: var(--gold);
    font-weight: 500;
  }

  /* ============ DEBUG ALIGNMENT GUIDES (press D to toggle) ============ */
  .debug-guide {
    position: absolute;
    left: 0; right: 0;
    height: 1px;
    z-index: 50;
    pointer-events: none;
    display: none;
  }
  .debug-guide::after {
    content: attr(data-label);
    position: absolute;
    right: 8px; top: -16px;
    font-family: monospace;
    font-size: 10px;
    letter-spacing: 0.1em;
    padding: 2px 6px;
    border-radius: 2px;
  }
  .debug-guide.bottle {
    bottom: var(--bottle-bottom);
    background: #ff5757;
  }
  .debug-guide.bottle::after {
    background: #ff5757; color: #000;
  }
  .debug-guide.cocktail {
    bottom: var(--cocktail-bottom);
    background: #57c8ff;
  }
  .debug-guide.cocktail::after {
    background: #57c8ff; color: #000;
  }
  body.debug .debug-guide { display: block; }

  /* ============ HINT ============ */
  .hint {
    position: absolute;
    bottom: 5vh;
    left: 50%;
    transform: translateX(-50%);
    font-family: 'Helvetica Neue LT Std', sans-serif;
    font-weight: 500;
    font-size: 10px;
    letter-spacing: 0.4em;
    text-transform: uppercase;
    color: var(--cream-dim);
    z-index: 6;
    animation: hintBlink 2.4s ease-in-out infinite;
    pointer-events: none;
  }
  @keyframes hintBlink {
    0%, 100% { opacity: 0.4; }
    50% { opacity: 0.9; }
  }

  /* ============ RESPONSIVE ============ */
  @media (max-width: 1100px) {
    .scene { grid-template-columns: 55% 45%; }
    .text-stage { padding: 130px 40px 100px 0; }
  }
  @media (max-width: 860px) {
    :root {
      /* Override vertical placement so bottle/glass sit on the WOOD
         surface of the (larger) mobile table.
         Theoretical math said 80% (table-bottom 2vh + wood-fraction 0.875
         × table-width 38vh = 35.25vh / 44vh stage height), but the actual
         rendered table came out shorter than that formula predicted —
         70%/69% is the value that actually matched the real device.
         Cocktail anchored 1% lower to seat glass naturally on the wood.
         (Table bumped 32vh → 38vh since it read too small next to the
         bottle — see .table below. --scene padding-top tuned to match,
         see .scene comment, so the bottle still clears the header.) */
      /* VERIFIED IN LIVE MOBILE VIEWPORTS AT BOTH 375×745 (an iPhone's real
         page height with Safari's URL bar showing) AND 375×812 — measured,
         not guessed: with row 42svh / padding 120px / table 30svh / bottle
         4.2svh, the bottle base lands within 1px of the wood surface and
         the title bottom clears the text box by 40px+ at both heights.
         All five values (row, padding, table, bottle, anchors) are
         coupled: change one, re-derive AND re-measure the rest. */
      --bottle-bottom: 67%;
      --cocktail-bottom: 66%;
      /* ONE DIAL for the whole mobile composition. Every part of the
         visual (grid row, table, halo, bottle, glass) is a fixed fraction
         of --stage-h, so they scale together and the bottle stays seated
         on the wood at ANY size. The min() caps it by the space actually
         left over (100svh − 120px header padding − ~150px text content −
         195px nav zone − 8px gap = 100svh − 473px), so on short phones the
         composition shrinks instead of colliding with the bottom-anchored
         text. Verified live at 660/700/850 viewport heights. */
      --stage-h: min(38vh, 100vh - 473px);
      /* No more horizontal anchor overrides — bottle and cocktail are
         center-anchored as a pair (see .bottle / .cocktail-stack above),
         so the SAME centering applies on every breakpoint automatically. */
    }
    /* svh version where supported. NOTE: a custom property can't use the
       usual two-declaration unit fallback — an unsupported unit inside a
       variable only fails at use time and poisons every calc() reading it,
       so the override must be gated behind @supports instead. */
    @supports (height: 1svh) {
      :root { --stage-h: min(38svh, 100svh - 473px); }
    }

    /* Pin the whole stage to the SMALL viewport too, so its bottom edge
       (where nav-rail/arrows/cart anchor) is never buried under Safari's
       expanded URL bar. */
    .stage { height: 100svh; }

    .scene {
      grid-template-columns: 1fr;
      /* Row height IS --stage-h (see :root) — everything in the visual
         scales from that one variable. */
      grid-template-rows: var(--stage-h) 1fr;
      /* 120px puts the bottle top at y≈80 on a 745px page (header bottom
         y=84 — bottle tucks 4px into the header's transparent fade, fine).
         Measured, not derived. */
      padding-top: 120px;
    }

    /* Header gets a soft black-to-transparent fade so the bottle
       behind it gets masked instead of awkwardly cropped by the logo. */
    header {
      padding: 14px 18px 28px 18px;
      background: linear-gradient(to bottom,
        rgba(0,0,0,0.92) 0%,
        rgba(0,0,0,0.7) 55%,
        rgba(0,0,0,0) 100%);
      z-index: 30;
    }
    .brand { height: 26px; }
    .header-tagline { display: none; }
    /* Mobile-only: hide desktop nav, show hamburger, enable drawer */
    .header-nav { display: none; }
    .nav-toggle { display: flex; }
    .mobile-drawer { display: block; }

    /* Stage props sized in vh so they scale together with the visual-stage.
       All widths multiplied by --stage-scale so the close-up dial works on
       mobile too. min-width: 0 overrides desktop clamp() floors that are
       wider than phone viewports. */
    .table {
      /* 38vh made the wood surface ride so high the bottle couldn't sit on
         it without going under the header (bottle is ~20.6vh tall — the
         geometry simply didn't fit). 32vh table + 4.5vh bottle keeps a
         BETTER table:bottle ratio (7.1:1) than the old "dwarfed" 32/5
         (6.4:1) while everything physically fits. */
      /* 0.71 of --stage-h = the old 27svh-in-a-38svh-row proportion; the
         0.053 bottom anchor = the old 2svh. Keeping every part a fraction
         of the same variable is what keeps the bottle seated at any size. */
      width: calc(var(--stage-h) * 0.71 * var(--stage-scale));
      min-width: 0;
      max-width: 90vw;   /* hard ceiling — don't let scale push past viewport */
      bottom: calc(var(--stage-h) * 0.053);
      max-height: none;
    }
    .table-halo {
      width: calc(var(--stage-h) * var(--stage-scale));
      min-width: 0;
      max-width: 96vw;
    }
    /* Bottle and cocktail use the SAME width (5vh) — same approach as
       desktop. Bottle stays visually dominant because its aspect
       (1:4.57) is much taller than the cocktail's (~1:1.64 visible).
       Cocktail was previously 12vh which made it look gigantic on
       phones — now matches bottle width for a balanced composition. */
    .bottle {
      width: calc(var(--stage-h) * 0.103 * var(--stage-scale));
      min-width: 0;
      max-width: calc(40px * var(--stage-scale));
    }
    .cocktail-stack {
      width: calc(var(--stage-h) * 0.145 * var(--stage-scale));
      min-width: 0;
      max-width: calc(50px * var(--stage-scale));
    }

    /* Text panel anchored to the top so the cocktail name is the first
       thing visible — was being centered and pushed off-screen.
       Bottom padding bumped from 90px → 170px: the nav-rail below now
       stacks category tabs ABOVE the dot row (was just one row of dots),
       roughly doubling its height, so the old 90px clearance let the
       description text run underneath it. */
    /* Pulled OUT of the grid's shared 1fr row entirely and pinned with a
       hard top AND bottom edge instead. The old approach (grid row + a big
       padding-bottom) kept breaking: padding-bottom only adds trailing
       space once you scroll near the end of the content — it never
       stopped the FIRST screen's worth of text (heading/tagline) from
       rendering wherever its box naturally landed, which kept ending up
       under the tabs. With a hard `bottom` value here, the box's visible
       area can never reach into the nav-rail/dots/arrows zone at all,
       regardless of how .scene's padding-top or the table size changes
       later — text just scrolls inside this fixed box instead. */
    .text-stage {
      position: absolute;
      /* BOTTOM-ANCHORED, height from content — deliberately NOT computed
         from the top. Every top-computed formula (157px+44vh, 140px+42svh,
         120px+36svh...) broke on some real device because viewport heights
         vary more than any fixed math survives; anchoring to the bottom
         (where the fixed-height nav UI lives) guarantees the title, tagline
         and recipe button are ALWAYS fully on screen, and any slack ends up
         as harmless space above the text instead of clipping below it.
         Verified live at 700/745/850 viewport heights. */
      top: auto;
      left: 0;
      right: 0;
      /* Ends just above the nav-rail (tabs top ≈ 182px from page bottom);
         verified: title bottom clears this edge by 40px+ even on a 745px
         page. */
      bottom: 195px;
      /* Top padding: 'Whiskey Jill' at line-height:1.0 has cap-height
         overshoot (glyph tops paint above the line box) and was clipping
         at 18px; 26px verified clear at the 34px mobile title size. */
      padding: 26px 24px 24px 24px;
      align-items: flex-start;
      overflow-y: auto;
    }
    .slide { justify-content: flex-start; }
    /* NO SCROLLING REQUIRED on mobile: the slide shows only label + title +
       tagline + the recipe button — all visible at once. Description,
       ingredients and steps live in the recipe card (the modal), which now
       lists ingredients too. A buried, scroll-to-reach button is a button
       nobody finds on a phone. */
    .text-stage .description,
    .text-stage .ingredients { display: none; }
    /* Safety net: if a long title/tagline still overflows on a short phone,
       let the box actually scroll — the active slide must be in normal flow
       (position:relative) so the scroll container's content height is real;
       with all slides position:absolute the box could NEVER scroll
       (scrollHeight always equalled clientHeight). */
    .slides-wrap { height: auto; min-height: 100%; }
    .slide.active { position: relative; inset: auto; }

    .step-label { margin-bottom: 6px; font-size: 9px; }
    .cocktail-name { font-size: 34px; margin-bottom: 6px; }
    .tagline { font-size: 16px; margin-bottom: 12px; }
    .recipe-toggle { padding: 11px 22px; font-size: 9px; margin-top: 0; }

    /* Recipe card sized for phones: near-full-width, internal scroll. */
    .modal-backdrop { padding: 16px; }
    .modal {
      padding: 44px 24px 32px;
      max-height: calc(100svh - 32px);
      overflow-y: auto;
    }
    .modal h3 { font-size: 26px; margin-bottom: 18px; }

    /* Compact nav controls so they don't crowd the small viewport */
    /* Move dot-nav to bottom-center on mobile so it doesn't crowd the
       headline/cards on the left edge. Hide the hover labels (touch can't
       hover, and they were overlapping the drink title text). */
    .nav-rail {
      left: 50%;
      top: auto;
      bottom: 112px;
      transform: translateX(-50%);
      align-items: center;
      gap: 14px;
      max-height: none;
      max-width: 92vw;
    }
    .category-tabs {
      flex-direction: row;
      gap: 10px;
      max-width: 92vw;
      overflow-x: auto;
      scrollbar-width: none;
    }
    .category-tabs::-webkit-scrollbar { display: none; }
    .category-tab { padding: 8px 16px; font-size: 10px; }
    .dot-nav {
      flex-direction: row;
      gap: 12px;
      max-height: none;
      max-width: 90vw;
      overflow-x: auto;
      overflow-y: visible;
      padding: 4px 6px;
    }
    .dot::after { display: none; }
    /* Lift the arrows well clear of the Big Thirst cart toggle, which owns
       a fixed pill in the bottom-right corner (see bt-overrides.css) —
       at the old 48px offset the two were landing on top of each other. */
    .nav-controls {
      right: 16px;
      bottom: calc(96px + env(safe-area-inset-bottom, 0px));
      gap: 14px;
    }
    .arrow-btn { width: 40px; height: 40px; }
    /* "01 — 22" duplicated what the dots already show, and looked like a
       second, unrelated counter next to the cart badge — dropped it on
       mobile; the dot row is the only position indicator now. */
    .progress { display: none; }

    /* Hint hidden on mobile — it was wrapping into two lines behind the
       Big Thirst cart pill (bottom-right), and swipe/dots are
       self-explanatory on touch anyway. */
    .hint { display: none; }
  }
