/* ════════════════════════════════════════════════════════════════════════
   COCKTAIL LIBRARY — landing page (index.html)
   An editorial, motion-forward home. Kinetic serif masthead over a living
   light field (three.js), scroll-choreographed sections, animated data beats.

   Craft rules honored from the design system:
   • Warm paper, 1px hairlines, 0–2px radii, no drop-shadows, no ornament.
   • Two families only (Playfair Display / Work Sans), all values from tokens.
   • Motion is *seasoning*: the page is complete and legible with no JS and
     under prefers-reduced-motion. Pre-animation hidden states apply ONLY when
     .cl-js is present on <html> (set before paint, motion-allowed only), and a
     failsafe (.cl-reveal-all) force-shows everything if the script never runs.
   ════════════════════════════════════════════════════════════════════════ */

/* ── Reveal scaffolding ──────────────────────────────────────────────────
   Base (no JS / reduced motion): everything visible. When .cl-js is set the
   reveal targets start hidden; GSAP animates them in; .cl-reveal-all is the
   failsafe that guarantees content regardless of script failure. (will-change
   is intentionally NOT set here — GSAP promotes layers only during the tween,
   so we don't leave ~10 permanent compositor layers behind.) */
.cl-js [data-reveal] { opacity: 0; }
.cl-js [data-reveal="up"]    { transform: translateY(26px); }
.cl-js [data-reveal="rise"]  { transform: translateY(40px); }
.cl-js [data-reveal="fade"]  { transform: none; }
.cl-reveal-all [data-reveal] { opacity: 1 !important; transform: none !important; }

/* Masked word reveal for the masthead. The words are hidden pre-animation by
   fading the whole title (opacity), NOT by a CSS transform: GSAP reads a CSS
   translateY(%) back as resolved pixels, which would fight the yPercent tween
   that lifts each word out of its clip box. So JS owns the transform outright.
   The small padding/negative-margin pair keeps the overflow:hidden clip box
   clear of serif descenders (the 'y' in Library) without shifting the line. */
.lp-word { display: inline-block; overflow: hidden; vertical-align: top; padding-bottom: .1em; margin-bottom: -.1em; }
.lp-word > i { display: inline-block; font-style: inherit; }
.cl-js [data-hero-title] { opacity: 0; }
.cl-reveal-all [data-hero-title] { opacity: 1 !important; }
.cl-reveal-all .lp-word > i { transform: none !important; }

/* Lenis smooth-scroll base styles (vendored — the CSP blocks the package's own
   stylesheet). We only ever instantiate Lenis with smoothWheel on, so forcing
   native scroll-behavior to auto whenever the .lenis class is present keeps the
   browser's smooth-scroll from fighting Lenis (this build tags <html> with
   `lenis` but not always `lenis-smooth`). */
html.lenis, html.lenis body { height: auto; }
html.lenis { scroll-behavior: auto !important; }
.lenis.lenis-smooth [data-lenis-prevent] { overscroll-behavior: contain; }
.lenis.lenis-stopped { overflow: hidden; }
.lenis.lenis-smooth iframe { pointer-events: none; }

/* Screen-reader label for the data beats — the animated numeral is aria-hidden,
   so AT always reads the real figure (see index.html). */
.lp-beat-sr {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ════════════════════════════════════════════════════════════════════════
   HERO
   Layer order (bottom→top): photographic plate → paper scrim (the contrast
   guarantee) → WebGL light canvas (soft-light, masked away from the title) →
   content. Text contrast is governed by the scrim, so the living light never
   threatens legibility.
   ════════════════════════════════════════════════════════════════════════ */
.lp-hero {
  position: relative;
  min-height: min(92vh, 860px);
  display: flex;
  /* Column, explicitly: the hero stacks .lp-hero-inner over .lp-scrollcue.
     The row default laid them side by side, centering the PAIR — which shoved
     the title ~90px left of viewport center and beached the scroll cue at the
     right edge. */
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: clamp(4rem, 10vh, 8rem) 2.5rem clamp(3.5rem, 8vh, 6rem);
  overflow: hidden;
  border-bottom: 1px solid var(--rule);
  isolation: isolate;                 /* contain the canvas blend mode */
}

/* Plate — the LCP image, kept from the previous hero. */
.lp-hero-plate {
  position: absolute; inset: 0; z-index: 0;
  /* Plain JPG for browsers without image-set; the image-set line below wins
     wherever it is understood, upgrading to WebP. */
  background-image: url("images/photo-1769623437237-850a0ecc0c4c-2000.jpg");
  background-image:
    image-set(
      url("images/photo-1769623437237-850a0ecc0c4c-2000.webp") type("image/webp"),
      url("images/photo-1769623437237-850a0ecc0c4c-2000.jpg")  type("image/jpeg"));
  background-size: cover; background-position: center;
  transform: scale(1.06);             /* headroom for parallax */
  transform-origin: center;
}
@media (max-width: 720px) {
  .lp-hero-plate {
    background-image:
      image-set(
        url("images/photo-1769623437237-850a0ecc0c4c-1200.webp") type("image/webp"),
        url("images/photo-1769623437237-850a0ecc0c4c-1200.jpg")  type("image/jpeg"));
  }
}

/* Paper scrim — lighter than the old 88% flat veil so the plate reads with
   depth, but still a firm AA backdrop for the dark serif. A gentle radial
   keeps the centre (where the title sits) the most opaque. */
.lp-hero-scrim {
  position: absolute; inset: 0; z-index: 1;
  background:
    radial-gradient(120% 90% at 50% 42%,
      rgba(251,249,245,.74) 0%,
      rgba(251,249,245,.82) 45%,
      rgba(251,249,245,.9) 100%),
    linear-gradient(rgba(251,249,245,.28), rgba(243,239,231,.5));
}
html[data-theme="dark"] .lp-hero-scrim {
  background:
    radial-gradient(120% 90% at 50% 42%,
      rgba(22,19,16,.72) 0%,
      rgba(22,19,16,.82) 45%,
      rgba(22,19,16,.92) 100%),
    linear-gradient(rgba(22,19,16,.3), rgba(20,17,14,.55));
}

/* Living light — a slow caustic field. Soft-light lets it modulate the plate
   without adding contrast; the radial mask fades it out of the title zone. */
.lp-hero-gl {
  position: absolute; inset: 0; z-index: 2;
  width: 100%; height: 100%;
  opacity: 0;                          /* faded in by JS once the first frame is ready */
  mix-blend-mode: soft-light;
  -webkit-mask-image: radial-gradient(115% 80% at 50% 44%, transparent 0%, transparent 30%, #000 72%);
          mask-image: radial-gradient(115% 80% at 50% 44%, transparent 0%, transparent 30%, #000 72%);
  pointer-events: none;
  transition: opacity 1.2s var(--ease);
}
html[data-theme="dark"] .lp-hero-gl { mix-blend-mode: screen; opacity: 0; }

.lp-hero-inner {
  position: relative; z-index: 3;
  max-width: 1180px; width: 100%;
  text-align: center;
}

.lp-eyebrow {
  font-family: var(--font-sans); font-weight: var(--w-medium);
  font-size: var(--fs-2xs); letter-spacing: var(--track-2); text-transform: uppercase;
  color: var(--ink-mute);
  margin-bottom: 1.75rem;
  display: flex; align-items: center; justify-content: center; gap: .8rem;
  flex-wrap: wrap;
}
.lp-eyebrow .dot { color: var(--accent); opacity: .8; }
.lp-eyebrow span.word { white-space: nowrap; display: inline-block; }

.lp-title {
  font-family: var(--font-serif); font-weight: var(--w-semibold);
  font-size: clamp(2.9rem, 9vw, 5.4rem);
  line-height: .96;
  letter-spacing: -.02em;
  color: var(--ink);
  margin: 0;
}
.lp-title .lp-word { margin: 0 .12em; }
.lp-title .lp-word:first-child { margin-left: 0; }
.lp-title .lp-word:last-child { margin-right: 0; }

.lp-hero-sub {
  font-family: var(--font-sans); font-style: normal;
  font-size: var(--fs-lg); line-height: 1.5;
  color: var(--ink-soft);
  max-width: 640px; margin: 1.9rem auto 0;
}

/* Scroll cue — a hairline that "pours" downward. */
.lp-scrollcue {
  position: relative; z-index: 3;
  margin: clamp(2.5rem, 6vh, 4rem) auto 0;
  width: 1px; height: 54px;
  background: linear-gradient(var(--ink-mute), transparent);
  opacity: .55;
  overflow: hidden;
}
.lp-scrollcue::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(var(--accent), transparent);
  transform: translateY(-100%);
  animation: lp-pour 2.4s var(--ease) infinite;
}
@keyframes lp-pour {
  0%   { transform: translateY(-100%); }
  60%  { transform: translateY(100%); }
  100% { transform: translateY(100%); }
}

/* ════════════════════════════════════════════════════════════════════════
   INDEX — the three sections as an unfolding printed contents page.
   ════════════════════════════════════════════════════════════════════════ */
.lp-body { max-width: 1180px; margin: 0 auto; padding: clamp(3.5rem, 8vh, 6rem) 2.5rem 0; }

.lp-index-head {
  display: grid; grid-template-columns: 1fr auto; align-items: end; gap: 1.5rem;
  padding-bottom: 1.5rem; margin-bottom: 2.75rem;
  border-bottom: 1px solid var(--rule);
}
.lp-index-kicker {
  font-family: var(--font-sans); font-weight: var(--w-medium);
  font-size: var(--fs-2xs); letter-spacing: var(--track-2); text-transform: uppercase;
  color: var(--ink-mute);
}
.lp-index-title {
  font-family: var(--font-serif); font-weight: var(--w-semibold);
  font-size: var(--fs-2xl); line-height: 1; color: var(--ink); margin: .5rem 0 0;
}
.lp-index-note {
  font-family: var(--font-sans); font-style: normal;
  font-size: var(--fs-md); line-height: 1.5; color: var(--ink-soft); text-align: right; max-width: 22rem;
}

.lp-grid {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.75rem;
}

.lp-card {
  --card-accent: var(--accent);
  position: relative;
  background: var(--paper-deep);
  border: 1px solid var(--rule);
  padding: 2.5rem 2rem 2.25rem;
  text-decoration: none;
  display: flex; flex-direction: column;
  min-height: 440px;
  overflow: hidden;
  transition: border-color var(--dur-slow) var(--ease), transform var(--dur-slow) var(--ease);
}
/* A hairline that draws across the card top on hover — the "letterpress rule". */
.lp-card::before {
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 2px;
  background: var(--card-accent);
  transform: scaleX(0); transform-origin: left;
  transition: transform .5s var(--ease);
}
.lp-card:hover, .lp-card:focus-visible { border-color: var(--card-accent); }
.lp-card:hover::before, .lp-card:focus-visible::before { transform: scaleX(1); }

.lp-card-num {
  font-family: var(--font-serif); font-weight: var(--w-regular);
  font-size: var(--fs-4xl); line-height: 1; color: var(--card-accent);
  margin-bottom: .75rem; letter-spacing: -.02em;
}
.lp-card-eyebrow {
  font-family: var(--font-sans); font-weight: var(--w-medium);
  font-size: var(--fs-2xs); letter-spacing: var(--track-2); text-transform: uppercase;
  color: var(--card-accent); margin-bottom: .9rem;
}
.lp-card-title {
  font-family: var(--font-serif); font-weight: var(--w-semibold);
  font-size: var(--fs-3xl); line-height: 1; color: var(--ink); margin-bottom: 1rem;
}
.lp-card-sub {
  font-family: var(--font-sans); font-style: normal;
  font-size: var(--fs-md); line-height: 1.6; color: var(--ink-soft); margin-bottom: 1.5rem;
}
.lp-card-list { list-style: none; margin: auto 0 0; padding: 0; }
.lp-card-list li {
  display: flex; gap: .75rem; align-items: baseline;
  padding: .55rem 0; border-bottom: 1px solid var(--rule);
  font-size: var(--fs-xs); color: var(--ink-soft); font-family: var(--font-sans);
}
.lp-card-list li:last-child { border-bottom: none; }
.lp-card-list .ct {
  font-family: var(--font-sans); font-weight: var(--w-medium);
  font-size: var(--fs-2xs); letter-spacing: var(--track-2);
  color: var(--card-accent); min-width: 24px; flex-shrink: 0;
}
.lp-card-link {
  margin-top: 1.5rem;
  font-family: var(--font-sans); font-weight: var(--w-medium);
  font-size: var(--fs-2xs); letter-spacing: var(--track-2); text-transform: uppercase;
  color: var(--card-accent); display: flex; align-items: center; gap: .5rem;
}
.lp-card-link .arw { transition: transform var(--dur-slow) var(--ease); }
.lp-card:hover .lp-card-link .arw, .lp-card:focus-visible .lp-card-link .arw { transform: translateX(5px); }

.lp-card[href*="recipes"]   { --card-accent: var(--accent-recipes);   background: var(--wash-recipes); }
.lp-card[href*="spirits"]   { --card-accent: var(--accent-spirits);   background: var(--wash-spirits); }
.lp-card[href*="technique"] { --card-accent: var(--accent-technique); background: var(--wash-technique); }
html[data-theme="dark"] .lp-card { background: var(--paper-deep); }

/* ════════════════════════════════════════════════════════════════════════
   DATA BEATS — the library, counted. Numerals count up on scroll-in.
   ════════════════════════════════════════════════════════════════════════ */
.lp-beats {
  max-width: 1180px; margin: clamp(3rem, 7vh, 5rem) auto 0;
  padding: clamp(2.5rem, 6vh, 4rem) 2.5rem;
  border-top: 1px solid var(--rule); border-bottom: 1px solid var(--rule);
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 2rem;
  text-align: center;
}
.lp-beat { position: relative; }
.lp-beat + .lp-beat::before {
  content: ""; position: absolute; left: -1rem; top: 12%; bottom: 12%;
  width: 1px; background: var(--rule);
}
.lp-beat-num {
  font-family: var(--font-serif); font-weight: var(--w-semibold);
  font-size: clamp(2.4rem, 6vw, 3.6rem); line-height: 1; color: var(--ink);
  letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
}
.lp-beat-label {
  font-family: var(--font-sans); font-weight: var(--w-medium);
  font-size: var(--fs-2xs); letter-spacing: var(--track-2); text-transform: uppercase;
  color: var(--ink-mute); margin-top: .75rem;
}

/* ════════════════════════════════════════════════════════════════════════
   TOOL CALLOUTS  (Menu Builder / Batched) — kept from the prior home, re-hung.
   ════════════════════════════════════════════════════════════════════════ */
.lp-tool {
  max-width: 1180px; margin: 1.5rem auto 0;
  padding: 1.75rem 2rem;
  background: var(--paper-deep); border: 1px solid var(--rule);
  border-left: 4px solid var(--accent-recipes);
  display: grid; grid-template-columns: auto 1fr auto; gap: 1.5rem; align-items: center;
}
.lp-tool:first-of-type { margin-top: clamp(2.5rem, 6vh, 4rem); }
.lp-tool .tool-eyebrow {
  font-family: var(--font-sans); font-weight: var(--w-medium);
  font-size: var(--fs-2xs); letter-spacing: var(--track-2); text-transform: uppercase;
  color: var(--accent-recipes);
}
.lp-tool .tool-title {
  font-family: var(--font-serif); font-weight: var(--w-semibold);
  font-size: var(--fs-xl); line-height: 1; color: var(--ink); margin-top: .25rem;
}
.lp-tool .tool-sub {
  font-family: var(--font-sans); font-style: normal;
  font-size: var(--fs-md); line-height: 1.5; color: var(--ink-soft); margin: 0;
}
.lp-tool a.tool-link {
  font-family: var(--font-sans); font-weight: var(--w-medium);
  font-size: var(--fs-2xs); letter-spacing: var(--track-2); text-transform: uppercase;
  color: var(--accent-recipes); text-decoration: none;
  border: 1px solid var(--accent-recipes); padding: .7rem 1rem;
  transition: color .15s, background .15s; white-space: nowrap;
}
.lp-tool a.tool-link:hover { background: var(--accent-recipes); color: var(--paper); }
.lp-tool--batched { border-left-color: var(--accent-batched); }
.lp-tool--batched .tool-eyebrow { color: var(--accent-batched); }
.lp-tool--batched a.tool-link { color: var(--accent-batched); border-color: var(--accent-batched); }
.lp-tool--batched a.tool-link:hover { background: var(--accent-batched); color: var(--paper); }

/* ── Coda ─────────────────────────────────────────────────────────────── */
.lp-coda {
  max-width: 720px; margin: clamp(3rem, 7vh, 5rem) auto 0;
  padding: 2.5rem 2rem; text-align: center;
  border-top: 1px solid var(--rule);
  font-family: var(--font-serif); font-style: italic;
  font-size: var(--fs-lg); color: var(--ink-mute); line-height: 1.55;
}
.lp-coda .flare {
  /* Plain inline, NOT inline-block: browsers may break lines around atomic
     inlines even across a &nbsp;, which orphaned the closing ~ on narrow
     phones. The optical lift uses relative positioning (valid on inlines)
     instead of transform (which isn't). */
  display: inline; position: relative; top: -.05em;
  margin: 0 1.25em; font-style: normal;
  font-size: var(--fs-lg); color: var(--accent); opacity: .7;
}

/* ════════════════════════════════════════════════════════════════════════
   RESPONSIVE
   ════════════════════════════════════════════════════════════════════════ */
@media (max-width: 1020px) {
  .lp-grid { grid-template-columns: 1fr; }
  .lp-beats { grid-template-columns: repeat(2, 1fr); gap: 2rem 1rem; }
  .lp-beat:nth-child(3)::before, .lp-beat:nth-child(2)::before { content: none; }
}
@media (max-width: 720px) {
  .lp-hero { min-height: 84vh; padding: 3.5rem 1.5rem 3rem; }
  .lp-body { padding: 2.75rem 1.5rem 0; }
  .lp-index-head { grid-template-columns: 1fr; }
  .lp-index-note { text-align: left; }
  .lp-card { min-height: 0; padding: 2rem 1.5rem; }
  .lp-tool { grid-template-columns: 1fr; padding: 1.5rem 1.25rem; }
  .lp-tool a.tool-link { justify-self: start; }
  .lp-beats { padding: 2.25rem 1.5rem; }
  .lp-coda { padding: 2rem 1.5rem; font-size: var(--fs-md); }
  /* Tight flare margins on phones — with the &nbsp; binds in the markup this
     keeps "~ text ~" on one line at common widths, and when it must wrap the
     ornament travels with its word instead of orphaning. */
  .lp-coda .flare { margin: 0 .35em; }
}

/* ── Reduced motion: no infinite pour, no blend cost, static & complete. ── */
@media (prefers-reduced-motion: reduce) {
  .lp-scrollcue::after { animation: none; display: none; }
  .lp-hero-gl { display: none; }
  .lp-hero-plate { transform: none; }
  /* theme.css sets html{scroll-behavior:smooth} globally; loaded before this
     file, so this later rule wins. Honor the motion opt-out for the skip link
     and in-page anchor jumps on the landing page. */
  html { scroll-behavior: auto; }
}
