/* Generated by Brand Engine. Do not edit by hand. */

/* ─── FONTS ───
   One variable font file serves all three CSS family references.
   Roman (wght 400) + Bold (wght 700) + MediumCn alias (wght 500).
   Note: the OTF has no width axis, so the "Cn" footer alias is
   NOT truly condensed — it's medium-weight Minion. Acceptable
   substitute until a true condensed source is acquired.
   TEMPORARY: these @font-face rules should be emitted by the
   static engine. Tracked as task #14 (font handling). */
@font-face {
  font-family: 'MinionVariableConcept-Roman';
  src: url('assets/fonts/MinionVariableConcept-Roman.woff2') format('woff2-variations');
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'MinionConceptRoman-Bold';
  src: url('assets/fonts/MinionVariableConcept-Roman.woff2') format('woff2-variations');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'MinionPro-MediumCn';
  src: url('assets/fonts/MinionVariableConcept-Roman.woff2') format('woff2-variations');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}

/* ─── RESET ───
   Universal box-sizing + margin/padding zero. Plus mobile-friendly
   defaults: no iOS tap-flash, no iOS landscape font auto-zoom, crisp
   text rendering. */

*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  -webkit-tap-highlight-color: transparent; /* kill iOS gray tap flash */
}

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%; /* no iOS landscape font auto-zoom */
}

body {
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
body { font-family: 'MinionVariableConcept-Roman', 'Minion Pro', Georgia, serif; background-color: #f5f0eb; color: #302b2b; max-width: 1440px; margin-inline: auto; }
/* ─── HERO ─── */
.site-header { background-image: url('assets/images/layer-30.png'); background-size: cover; background-position: 65% top; min-height: clamp(440px, 70vh, 541px); display: flex; align-items: flex-start; }
.logo-block { width: clamp(280px, 33%, 476px); margin-left: clamp(20px, 17.2%, 247px); margin-top: clamp(32px, 6vh, 54px); display: inline-flex; flex-direction: column; align-items: center; }
.brand { display: block; }
.brand a { display: block; }
.brand img { width: 100%; height: auto; display: block; }
.tagline { font-family: 'MinionVariableConcept-Roman', Georgia, serif; font-size: 20px; color: #5a3320; text-align: center; font-style: normal; font-weight: 400; opacity: 0.8; }
/* ─── HERO/INTRO DIVIDER ─── */
.section-divider { width: 100%; height: 51px; background-size: 100% 100%; background-repeat: no-repeat; }
.divider-hero-intro { background-image: url('assets/images/vector-smart-object-copy-3.png'); }
/* ─── INTRO SECTION ─── */
.intro-section { display: flex; align-items: stretch; padding-block: 0; background-color: #f5f0eb; }
.intro-content { flex: 0 0 50%; max-width: 50%; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; padding-block: 0; padding-inline: clamp(24px, 4vw, 80px); gap: 20px; }
.intro-emblem { width: clamp(110px, 12vw, 154px); height: auto; display: block; }
.intro-body { font-family: 'MinionVariableConcept-Roman', Georgia, serif; font-size: 19.5px; color: #585855; line-height: 1.6; font-weight: 400; }
.intro-photo { flex: 0 0 50%; max-width: 50%; width: 100%; height: auto; display: block; }
/* ─── WINE CARDS — GRID LAYOUT ─── */
.wine-card { display: grid; grid-template-columns: 1fr 1fr; grid-template-rows: auto 1fr; background-color: #f5f0eb; }
.wine-photo { grid-column: 1; grid-row: 1 / 3; width: 100%; height: auto; display: block; }
.card-top-accent { grid-column: 2; grid-row: 1; width: 100%; height: 51px; background-size: 100% 100%; background-repeat: no-repeat; }
.wine-content { grid-column: 2; grid-row: 2; padding-top: 40px; padding-bottom: 40px; padding-inline: clamp(24px, 4vw, 72px); position: relative; }
/* Per-card accent images — one bar per card from manifest */
.wine-card:nth-of-type(1) .card-top-accent { background-image: url('assets/images/vector-smart-object-copy.png'); }
.wine-card:nth-of-type(2) .card-top-accent { background-image: url('assets/images/vector-smart-object.png'); }
.wine-card:nth-of-type(3) .card-top-accent { background-image: url('assets/images/vector-smart-object-copy-2.png'); }
.wine-card:nth-of-type(4) .card-top-accent { background-image: url('assets/images/vector-smart-object-copy-4.png'); }
.wine-card:nth-of-type(5) .card-top-accent { background-image: url('assets/images/vector-smart-object-copy-5.png'); }
/* Even cards: swap columns — photo right, content left */
.wine-card:nth-of-type(even) .wine-photo { grid-column: 2; grid-row: 1 / 3; }
.wine-card:nth-of-type(even) .card-top-accent { grid-column: 1; grid-row: 1; }
.wine-card:nth-of-type(even) .wine-content { grid-column: 1; grid-row: 2; }
/* Tree decorations per card */
.wine-card:nth-of-type(1) .wine-content { background-image: url('assets/icons/tree.svg'); background-repeat: no-repeat; background-position: right bottom; background-size: 421px 499px; }
.wine-card:nth-of-type(2) .wine-content { background-image: url('assets/icons/tree.svg'); background-repeat: no-repeat; background-position: left bottom; background-size: 630px 499px; }
.wine-card:nth-of-type(3) .wine-content { background-image: url('assets/icons/tree.svg'); background-repeat: no-repeat; background-position: right bottom; background-size: 422px 499px; }
.wine-card:nth-of-type(4) .wine-content { background-image: url('assets/icons/tree.svg'); background-repeat: no-repeat; background-position: left bottom; background-size: 438px 499px; }
.wine-card:nth-of-type(5) .wine-content { background-image: url('assets/icons/tree.svg'); background-repeat: no-repeat; background-position: right bottom; background-size: 390px 499px; }
/* ─── WINE NAME ─── */
.wine-name { font-family: 'MinionVariableConcept-Roman', Georgia, serif; font-size: clamp(28px, 4vw, 41px); color: #9f4b38; font-weight: 400; text-transform: uppercase; margin-top: 0; margin-bottom: 24px; line-height: 1.1; }
/* ─── ACCORDIONS ─── */
.accordion { border-bottom: 1px solid #9f4b3b; padding-block: 12px; }
.accordion:first-of-type { border-top: 1px solid #9f4b3b; }
.accordion summary { font-family: 'MinionConceptRoman-Bold', Georgia, serif; font-size: 22px; font-weight: bold; color: #302b2b; cursor: pointer; list-style: none; display: flex; justify-content: space-between; align-items: center; padding-right: 8px; -webkit-user-select: none; user-select: none; }
.accordion summary:focus { outline: none; }
.accordion summary:focus-visible { outline: 2px solid #9f4b38; outline-offset: 2px; border-radius: 2px; }
.accordion summary::-webkit-details-marker { display: none; }
.accordion summary::after { content: ''; display: inline-block; width: 34px; height: 16px; background-image: url('assets/icons/arrow.svg'); background-size: contain; background-repeat: no-repeat; background-position: center; transition: transform 0.2s; flex-shrink: 0; }
.accordion[open] summary::after { transform: rotate(180deg); }
.tasting-note { font-family: 'MinionVariableConcept-Roman', Georgia, serif; font-size: 22px; color: #6b6b68; font-weight: 400; line-height: 1.6; margin-top: 10px; padding-bottom: 4px; }
/* ─── FOOTER ─── */
.site-footer { background-image: url('assets/images/layer-18.png'); background-size: cover; background-position: center; min-height: 259px; display: flex; align-items: center; }
.footer-inner { width: 100%; max-width: 1440px; margin-inline: auto; display: flex; justify-content: space-between; align-items: center; padding-inline: clamp(24px, 7vw, 101px); }
.footer-left, .footer-right { font-family: 'MinionPro-MediumCn', 'Minion Pro', Georgia, serif; font-size: 17px; color: #ffffff; font-weight: 500; letter-spacing: 0.04em; }
.footer-ornament { width: clamp(80px, 12vw, 154px); height: auto; display: block; }
/* ─── MOBILE RESPONSIVENESS ─── */
@media (max-width: 720px) { .site-header { justify-content: center; } .logo-block { margin-left: auto; margin-right: auto; } }
@media (max-width: 1024px) { .intro-section { flex-direction: column; } .intro-content { flex: none; max-width: 100%; padding-block: 40px; } .intro-photo { flex: none; max-width: 100%; width: 100%; } .wine-card { display: flex; flex-direction: column; } .wine-card > * { grid-column: auto; grid-row: auto; } .wine-photo { max-width: 100%; } .wine-card:nth-of-type(even) .wine-photo, .wine-card:nth-of-type(even) .card-top-accent, .wine-card:nth-of-type(even) .wine-content { grid-column: auto; grid-row: auto; } .footer-inner { flex-direction: column; gap: 16px; text-align: center; } }

/* ─── CLIENT FEEDBACK ROUND 1 ───────────────────────────────────
   Tweaks from the first client review pass. Tree-root crop is global;
   mobile-only adjustments handle logo legibility against the vineyard
   background and footer text restructuring. */

/* Desktop-only footer letter-spacing — wider on desktop so the
   tagline and "Bottled by" text balance better within the horizontal
   space. Mobile keeps its original 0.04em default (user explicitly
   said mobile footer is fine). iPad (>720, ≤1024) inherits desktop
   spacing per user's note that iPad should be "some modification of
   desktop". */
@media (min-width: 1025px) {
  .footer-left, .footer-right {
    letter-spacing: 0.3em;
  }
}

/* Tree positioning per client review round 2:
   - Anchored to the BOTTOM of .wine-content (the static engine's
     `right bottom` / `left bottom` shorthand handles this — no
     override needed).
   - OFFSET (not centered): odd cards = right-anchored, even = left.
   - On mobile (≤1024px), the tree's natural pixel size often exceeds
     the full-width .wine-content. The browser auto-clips overflow on
     the offset side — produces the "partial tree silhouette" look. */

/* ─── TREE BACKDROP — single SVG, responsive, one-knob sizing ───
 *
 * Every wine-card uses the SAME tree.svg at the same size. The static
 * engine's per-card background-image rules are cleared (override below);
 * the tree is moved to a ::before pseudo so opacity 0.1 doesn't bleed
 * into the card's text content.
 *
 * TO ADJUST SCALE: change the `--tree-h` value below.
 *   `--tree-h: 80%` → tree is 80% of the content panel's height
 *   `--tree-h: 30rem` → tree is 30rem tall regardless of panel
 *   `--tree-h: 60%` → smaller tree
 * The width auto-derives from `aspect-ratio` to maintain the SVG's
 * natural proportions (466.97 × 365.61 — wider than tall).
 *
 * Position: anchored to the bottom of the content panel, alternating
 * right (odd cards) / left (even cards). */

/* Clear the static engine's per-card background-image (matches 0,3,0
   specificity so this override wins). */
.wine-card:nth-of-type(1) .wine-content,
.wine-card:nth-of-type(2) .wine-content,
.wine-card:nth-of-type(3) .wine-content,
.wine-card:nth-of-type(4) .wine-content,
.wine-card:nth-of-type(5) .wine-content {
  background-image: none;
}

/* Clip the tree's outside overhang at the content panel's edge.
   overflow-x: clip (NOT hidden) — `hidden` would make .wine-content a
   scroll container, which breaks any view-timeline child (the lesson
   from effects iteration 3). `clip` clips the horizontal overhang
   without that side effect, and leaves the vertical axis visible. */
.wine-card .wine-content {
  overflow-x: clip;
}

/* Lift card content above the tree pseudo */
.wine-card .wine-content > * {
  position: relative;
  z-index: 1;
}

/* The tree pseudo — single knob: change `--tree-h` to scale.
   Trees peek in from the panel's outside edge — the negative margin
   shifts them 50% of panel width outward, and overflow-x: hidden on
   the parent clips the overhang. */
.wine-card .wine-content::before {
  --tree-h: 80%;
  content: '';
  position: absolute;
  bottom: 0;
  height: var(--tree-h);
  aspect-ratio: 466.97 / 365.61;
  background-image: url('assets/icons/tree.svg');
  background-size: contain;
  background-repeat: no-repeat;
  background-position: bottom;
  opacity: 0.1;
  pointer-events: none;
  z-index: 0;
}

.wine-card:nth-of-type(odd) .wine-content::before {
  right: 0;
  margin-right: -50%;
}
.wine-card:nth-of-type(even) .wine-content::before {
  left: 0;
  margin-left: -50%;
}

/* ── Stacked layout (≤1024px): uniform tree height ──
   On desktop the cards are two-up and `--tree-h: 80%` reads as the
   bliss point. Once cards stack to a single column, each .wine-content
   grows to fit its (variable-length) copy — so a percentage height
   makes longer cards (Chardonnay, Pinot Noir) sprout taller trees than
   the short ones. Lock --tree-h to a FIXED height here so every
   varietal's tree is identical regardless of how much copy it carries. */
@media (max-width: 1024px) {
  .wine-card .wine-content::before {
    --tree-h: 27rem;
  }
}

/* Mobile drop-shadow on brand/tagline was removed per client review
   round 2 — the design intent doesn't include shadows on the brand
   block. If contrast issues recur on photographic backgrounds, revisit
   with a different mechanism (e.g., a subtle backdrop panel). */

/* Mobile-only: restructure the footer so the tree sits on top, the
   tagline ("Rooted in oak. Refined by time.") sits below it, and the
   "Bottled by..." line sits below the tagline in smaller type. The
   parent already switches to flex-direction: column at <=1024px, so we
   just override the visual order via `order:` and shrink the bottled-by. */
@media (max-width: 1024px) {
  .footer-ornament { order: 1; }
  .footer-right    { order: 2; }   /* tagline — kept at default size */
  .footer-left     {
    order: 3;
    font-size: 12px;
    opacity: 0.85;
    letter-spacing: 0.06em;
  }
}

/* === effect: hero-collapse-mobile === */
/* ─── HERO COLLAPSE — MOBILE ONLY (max-width: 720px) ─── */
@media (max-width: 720px) {

  /* ── Step 1: Sticky hero base (outside @supports — always applied) ── */
  /* Fallback state = full hero visible at initial height. No collapse without scroll-timeline support. */
  .site-header {
    position: sticky;
    top: 0;
    z-index: 1;
    /* overflow: clip — clips overflow WITHOUT becoming a scroll
       container. If we used overflow: hidden here, view-timeline on
       any future child would break (subject's scroll container would
       resolve to .site-header itself rather than the document). */
    overflow: clip;

    /* CSS custom properties for collapse math */
    --hero-initial: clamp(440px, 70vh, 541px);
    --hero-target: max(calc(100vw * 9 / 16), 220px);
    --hero-collapse-distance: calc(var(--hero-initial) - var(--hero-target));

    /* Fallback: hero stays at initial height, brand visible */
    min-height: var(--hero-initial);
    margin-bottom: 0px;
  }

  /* ── Step 2: Ken-burns ambient background via ::before pseudo ── */
  /* Clear the static engine's background-image so ::before owns the imagery */
  .site-header {
    background-image: none;
  }

  .site-header::before {
    content: '';
    position: absolute;
    inset: 0;
    background-image: url('assets/images/layer-30.png');
    background-size: cover;
    background-position: 65% top;
    z-index: 0;
    transform-origin: center center;
    animation: hero-kenburns-mobile 14s ease-in-out infinite alternate;
  }

  @keyframes hero-kenburns-mobile {
    from {
      transform: scale(1.02) translate(0%, 0%);
    }
    to {
      transform: scale(1.08) translate(-1.5%, 1%);
    }
  }

  /* Ensure logo-block sits above the ::before pseudo — NO transform, NO scale, NO margin change */
  .logo-block {
    position: relative;
    z-index: 1;
  }

  /* ── Step 3: Scroll-driven collapse — JS-DRIVEN, NOT CSS ──
   *
   * The CSS `animation-timeline: scroll()` block that lived here was
   * removed 2026-05-27. iOS 18 WebKit passes the @supports test for
   * animation-timeline but ships an incomplete implementation that
   * leaves property interpolations at inconsistent intermediate values
   * during scroll. Verified glitch on iPhone 15 + iPhone 16 Pro (both
   * Safari and Chrome — Chrome on iOS uses WebKit). Works correctly
   * only on pre-iOS-18 devices where @supports returned false and the
   * static fallback held.
   *
   * The collapse is now driven by scripts.js — a tiny scroll listener
   * that updates min-height + margin-bottom inline. Universal browser
   * support, behaves identically to what the CSS animation intended,
   * and survives partial-implementation traps in any WebKit/Blink
   * release.
   *
   * The fallback values set in Step 1 (min-height: var(--hero-initial);
   * margin-bottom: 0px) are the initial state. If JS is disabled, the
   * hero just stays at full height — usable, just no collapse. That's
   * the same graceful degradation we always wanted.
   */

  /* ── Step 4: Lift subsequent content above sticky hero ── */
  /* z-index: 2 + isolation: isolate works for the simple .divider-hero-intro
     (single div, no children with animations). But .intro-section and
     .wine-card have view-timeline animations on children which create
     sub-compositor-layers that iOS WebKit handles inconsistently with the
     sticky hero's painting — even with isolation: isolate, content can
     paint UNDER the hero on iPhone 13/15/16 Pro.
     Fix: also force GPU compositing on these elements with translate3d(0,0,0).
     That promotes each block to its own composited layer at the device level,
     bypassing the sticky-vs-sibling stacking ambiguity entirely. */
  .divider-hero-intro,
  .intro-section,
  .wine-card,
  .site-footer {
    position: relative;
    z-index: 2;
    isolation: isolate;
    transform: translate3d(0, 0, 0);
  }

  /* ── Step 5: Reduced motion — disable collapse and ken-burns ── */
  @media (prefers-reduced-motion: reduce) {
    .site-header {
      animation: none;
      min-height: var(--hero-initial);
      margin-bottom: 0;
    }

    .site-header::before {
      animation: none;
    }
  }
}
/* === /effect: hero-collapse-mobile === */

/* === effect: intro-reveal-mobile === */
/* ─── INTRO SECTION STAGGERED SCROLL ENTRANCE — MOBILE ONLY (max-width: 720px) ─── */
@media (max-width: 720px) {

  /* ── Fallback = end state (Law 1) ── */
  /* If view-timeline doesn't progress, all three elements are fully visible. */
  .intro-emblem,
  .intro-body,
  .intro-photo {
    opacity: 1;
    transform: none;
  }

  /* ── Scroll-driven entrance — gated by @supports ── */
  @supports (animation-timeline: view()) {

    @keyframes intro-reveal-mobile {
      from {
        opacity: 0;
        transform: translateY(80px);
      }
      to {
        opacity: 1;
        transform: none;
      }
    }

    @keyframes intro-photo-arrive {
      from {
        opacity: 0;
        transform: translateY(100px) scale(0.96);
      }
      to {
        opacity: 1;
        transform: none;
      }
    }

    /* Emblem: already mostly visible on load — narrow range so it snaps into place quickly */
    .intro-emblem {
      animation: intro-reveal-mobile linear both;
      animation-timeline: view();
      animation-range: entry 40% entry 80%;
    }

    /* Body copy: slightly below emblem in scroll phase — completes just after emblem */
    .intro-body {
      animation: intro-reveal-mobile linear both;
      animation-timeline: view();
      animation-range: entry 50% entry 90%;
    }

    /* Photo: the headline entrance — arrives from further below with a scale pop */
    /* Wider range so the motion is perceptible as the user scrolls down to it */
    .intro-photo {
      animation: intro-photo-arrive linear both;
      animation-timeline: view();
      animation-range: entry 30% cover 20%;
    }
  }

  /* ── Reduced motion override ── */
  @media (prefers-reduced-motion: reduce) {
    .intro-emblem,
    .intro-body,
    .intro-photo {
      animation: none;
      opacity: 1;
      transform: none;
    }
  }
}
/* === /effect: intro-reveal-mobile === */

/* === effect: wine-card-cellar-mobile === */
/* ─── WINE CARD CELLAR EFFECT — MOBILE ONLY (max-width: 720px) ─── */
@media (max-width: 720px) {

  /* ══════════════════════════════════════════════════════════════
     LAYER 1 — STRUCTURAL FIX: tree fits the box
     min-height ensures the 499px tree silhouette has breathing room.
     background-size locks the tree height regardless of box height.
     DO NOT redefine background-image, background-position, or
     background-repeat — those are owned by the static engine.
  ══════════════════════════════════════════════════════════════ */
  .wine-card .wine-content {
    min-height: 540px;
    background-size: auto 499px;
  }

  /* ══════════════════════════════════════════════════════════════
     LAYER 3 — LIGHT SWEEP: .wine-card::after overlays the bottle
     Fallback = end state (Law 1): sweep invisible at rest (opacity: 0).
     position: relative + overflow: hidden already set by hero-collapse
     effect for .wine-card — we reinforce here for safety.
  ══════════════════════════════════════════════════════════════ */
  .wine-card {
    position: relative;
    /* overflow: clip (NOT hidden) — hidden makes the element a scroll
       container, which broke view-timeline on every child animation in
       iteration 3. clip visually clips overflow without that side effect.
       Supported in Chrome 90+, Firefox 81+, Safari 16+. */
    overflow: clip;
  }

  .wine-card::after {
    content: '';
    position: absolute;
    top: 51px;           /* below the .card-top-accent bar */
    left: 0;
    right: 0;
    aspect-ratio: 1 / 1; /* approximates the bottle photo region */
    pointer-events: none;
    z-index: 3;          /* above .wine-photo */
    background: linear-gradient(
      115deg,
      transparent 30%,
      rgba(255, 245, 215, 0.7) 50%,
      transparent 70%
    );
    background-size: 280% 100%;
    background-position: 200% 0;
    background-repeat: no-repeat;
    opacity: 0;
    /* No mix-blend-mode — normal alpha compositing reads on both
       cream backgrounds and dark bottle areas. */
  }

  /* ══════════════════════════════════════════════════════════════
     LAW 1 FALLBACK — outside @supports, all children are visible.
     If view-timeline never progresses, the page is fully readable.
  ══════════════════════════════════════════════════════════════ */
  .wine-card .card-top-accent,
  .wine-card .wine-photo,
  .wine-card .wine-content {
    opacity: 1;
  }

  /* ══════════════════════════════════════════════════════════════
     SCROLL-DRIVEN ANIMATIONS — gated by @supports
  ══════════════════════════════════════════════════════════════ */
  @supports (animation-timeline: view()) {

    /* ── Keyframes ── */

    /* Opacity-only entrance — no transforms, no scale, no translate.
       Eliminates background-exposure and gap artifacts from iter 1. */
    @keyframes wine-fade-in-mobile {
      from { opacity: 0; }
      to   { opacity: 1; }
    }

    /* Tree parallax — full background-position shorthand animated
       at nth-of-type specificity to beat the static engine's (0,3,0)
       rules. 200px total shift (was 80px — bumped for scroll visibility). */
    @keyframes wine-tree-parallax-mobile-right {
      from { background-position: right calc(100% - 100px); }
      to   { background-position: right calc(100% + 100px); }
    }
    @keyframes wine-tree-parallax-mobile-left {
      from { background-position: left  calc(100% - 100px); }
      to   { background-position: left  calc(100% + 100px); }
    }

    /* Light sweep across the bottle — scroll-driven, single pass.
       Sweep speed depends on user's scroll rate. */
    @keyframes wine-photo-reflection {
      0%   { background-position: 200% 0;  opacity: 0; }
      15%  { opacity: 1; }
      85%  { opacity: 1; }
      100% { background-position: -100% 0; opacity: 0; }
    }

    /* ── LAYER 3: Light sweep on ::after ── */
    .wine-card::after {
      animation: wine-photo-reflection linear both;
      animation-timeline: view();
      animation-range: entry 20% cover 30%;
    }

    /* ── LAYER 5: Per-child entrance fades ── */

    /* Accent bar: fades in first as card enters */
    .wine-card .card-top-accent {
      animation: wine-fade-in-mobile linear both;
      animation-timeline: view();
      animation-range: entry 10% entry 40%;
    }

    /* Bottle photo: fades in slightly after the bar */
    .wine-card .wine-photo {
      animation: wine-fade-in-mobile linear both;
      animation-timeline: view();
      animation-range: entry 25% entry 60%;
    }

    /* ── LAYER 2 + 5 COMBINED: .wine-content gets compound animation ──
       Must be at nth-of-type specificity (0,3,0) to match the static
       engine's background-position rules and win the cascade.
       Odd cards: tree anchored right; even cards: tree anchored left. */

    .wine-card:nth-of-type(odd) .wine-content {
      animation:
        wine-fade-in-mobile                  linear both,
        wine-tree-parallax-mobile-right      linear both;
      animation-timeline: view(), view();
      animation-range:
        entry 40% entry 80%,
        entry 0%  exit  100%;
    }

    .wine-card:nth-of-type(even) .wine-content {
      animation:
        wine-fade-in-mobile                  linear both,
        wine-tree-parallax-mobile-left       linear both;
      animation-timeline: view(), view();
      animation-range:
        entry 40% entry 80%,
        entry 0%  exit  100%;
    }

  } /* end @supports (animation-timeline: view()) */

  /* ══════════════════════════════════════════════════════════════
     REDUCED MOTION — disable all motion; keep structural layout fixes.
     min-height: 540px and background-size: auto 499px are layout,
     not motion — they remain in force.
  ══════════════════════════════════════════════════════════════ */
  @media (prefers-reduced-motion: reduce) {

    .wine-card .card-top-accent,
    .wine-card .wine-photo {
      animation: none;
      opacity: 1;
    }

    .wine-card:nth-of-type(odd) .wine-content,
    .wine-card:nth-of-type(even) .wine-content {
      animation: none;
      opacity: 1;
      /* Restore static engine's background-position values */
    }

    .wine-card:nth-of-type(odd) .wine-content {
      background-position: right bottom;
    }

    .wine-card:nth-of-type(even) .wine-content {
      background-position: left bottom;
    }

    .wine-card::after {
      animation: none;
      opacity: 0; /* sweep stays invisible at rest */
    }

  }

} /* end @media (max-width: 720px) */
/* === /effect: wine-card-cellar-mobile === */

/* === effect: accordion-content-fade-in === */
/* ─── ACCORDION CONTENT FADE — JS-DRIVEN, BIDIRECTIONAL ───
 *
 * Prior implementations tried CSS transition + @keyframes and CSS
 * transition + @starting-style. Both failed silently on iOS WebKit
 * (verified on iPhone 13 mini: no animation in either direction).
 * The display:none toggle that native <details> performs kills CSS
 * transitions, and @starting-style support in iOS 18 WebKit is
 * incomplete enough that it doesn't reliably fire on every open.
 *
 * Current approach: JS in scripts.js manages a .is-shown class on the
 * <details> element. CSS transitions run between the default hidden
 * state and the .is-shown visible state. Both open and close animate.
 * The JS handles the timing — see scripts.js for details.
 */

/* The accordion body's hidden/visible state is
   controlled by a JS-managed class (.is-shown) rather than the [open]
   attribute. JS drives the timing so transitions fire reliably on BOTH
   open and close (the [open]-toggle + display:none combo silently
   breaks transitions and @starting-style on multiple iOS WebKit
   versions — see Visibility Laws 6 and 8 in src/animate/prompts/effects.md).

   - Default state: hidden (opacity 0, slight translate).
   - .is-shown state: visible (opacity 1, no translate).
   - The transition runs in BOTH directions because we're toggling a
     class, not a display value.
*/

.accordion > *:not(summary) {
  opacity: 0;
  transform: translateY(12px);
  transition: opacity 500ms ease-out, transform 500ms ease-out;
}

.accordion.is-shown > *:not(summary) {
  opacity: 1;
  transform: translateY(0);
}

@media (prefers-reduced-motion: reduce) {
  .accordion > *:not(summary) {
    transition: opacity 200ms ease-out;
    transform: none;
  }
  .accordion.is-shown > *:not(summary) {
    opacity: 1;
    transform: none;
  }
}
/* === /effect: accordion-content-fade-in === */

/* ═══════════════════════════════════════════════════════════════════
   CLIENT FEEDBACK ROUND 3 — 2026-05-28
   Appended last so source-order cascade wins over earlier blocks.
   ═══════════════════════════════════════════════════════════════════ */

/* #6 — Registered/trademark marks render small, print-style.
   The ® is already in <sup>; this shrinks it to ~half size so it
   reads like a proper registered mark, not a full-size glyph. */
sup {
  font-size: 0.5em;
}

/* #3 — Accordions always open, no chevron, no toggle (option a).
   <details>/<summary> structure + JS retained per user; just made
   permanently open. */
.accordion summary::after {
  display: none;            /* lose the chevron */
}
.accordion summary {
  pointer-events: none;     /* can't collapse */
  cursor: default;
}
.accordion[open] > *:not(summary) {
  opacity: 1;               /* always visible — independent of the
                               .is-shown JS path (no FOUC / no JS dep) */
  transform: none;
}

/* #5 — Hero "breathe": slow continuous zoom on the vineyard image.
   Time-based @keyframes (iOS-safe — NOT animation-timeline).
   Image moved to a ::before pseudo so it doesn't fight the JS
   height-collapse on mobile. Works at all breakpoints; supersedes
   the mobile-only ken-burns. */
.site-header {
  overflow: clip;
  background-image: none;
}
.site-header::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  background-image: url('assets/images/layer-30.png');
  background-size: cover;
  background-position: 65% top;
  transform-origin: center;
  animation: hero-breathe 10s ease-in-out infinite alternate;
}
@keyframes hero-breathe {
  from { transform: scale(1); }
  to   { transform: scale(1.12); }
}
/* Desktop needs position:relative for ::before anchoring; mobile
   already has position:sticky from the collapse effect. */
@media (min-width: 721px) {
  .site-header { position: relative; }
}

/* #4 — Logo + tagline fade in on load, staggered. On the CHILDREN
   so the parent .logo-block's scroll-driven fade-out (hero JS)
   composes cleanly (parent-opacity × child-opacity). */
@keyframes brand-fade-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}
.brand img {
  animation: brand-fade-in 1s ease-out 0.2s both;
}
.tagline {
  animation: brand-fade-in 1s ease-out 0.7s both;  /* follows the logo */
}

/* #7 — Acorn + story text fade in. IntersectionObserver (scripts.js)
   adds .in-view to .intro-section when it scrolls into view — fires
   on load for larger viewports where the intro is already visible,
   on scroll for smaller. `.has-js` guard means if JS is absent the
   content is simply visible (no stuck-invisible failure mode).
   `animation: none` neutralizes the dormant view-timeline intro
   effect from an earlier round. */
.has-js .intro-emblem,
.has-js .intro-body {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 0.9s ease-out, transform 0.9s ease-out;
  animation: none;
}
.has-js .intro-section.in-view .intro-emblem {
  opacity: 1;
  transform: translateY(0);
}
.has-js .intro-section.in-view .intro-body {
  opacity: 1;
  transform: translateY(0);
  transition-delay: 0.25s;   /* story text follows the acorn */
}

/* Reduced-motion: no breathe, no fades — everything at rest, visible. */
@media (prefers-reduced-motion: reduce) {
  .site-header::before,
  .brand img,
  .tagline {
    animation: none;
  }
  .has-js .intro-emblem,
  .has-js .intro-body {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* #2 — Desktop logo at full design size (476px).
   The base rule `width: clamp(280px, 33%, 476px)` only reaches 476px
   when the container is ~1442px+; on narrower desktop/laptop widths
   the 33% resolved smaller, shrinking the logo. Fix the block to a
   flat 476px on desktop. The .brand img stays at width:100% (fills
   the block) — do NOT scale the img itself, that overflows the block
   and shifts position. Mobile (≤720px) keeps the clamp + centering,
   completely untouched. Left margin stays at the 17.2% clamp, which
   matches the comp's logo position (~17% from hero left edge). */
@media (min-width: 721px) {
  .logo-block {
    width: 476px;
  }
  /* The wordmark SVG has a viewBox but NO width/height attributes, so
     as an <img> it has an aspect ratio but no intrinsic width. With
     .logo-block's `align-items: center` (cross axis = horizontal), the
     .brand / .brand a wrappers are NOT stretched — they collapse to the
     SVG's ~300px replaced-element fallback, so `.brand img { width:100% }`
     resolved to ~300px instead of 476px. Forcing the wrappers to fill
     the block makes the img's 100% resolve against the real 476px.
     (Mobile keeps the centered clamp — untouched.) */
  .brand,
  .brand a {
    width: 100%;
  }
  /* Tagline at its full design size on desktop (mobile base is 20px). */
  .tagline {
    font-size: 26.83px;
  }
}
