/*
  Eternal Bloom — "Modern Pakistani Royal × Cinematic × Editorial Luxury"
  Template-only styles. Self-contained: does NOT depend on the root
  /assets/css/style.css or pages.css, and nothing else in the project
  depends on this file.

  This is a STATIC invitation experience — no RSVP/response system and no
  social-share feature exist anywhere in this file. Don't reintroduce
  either without a fresh decision to do so.

  Structural model: every major scene is a full-viewport, scroll-snapped
  "page" — see §3's ".eb-scene" base rule. That one rule (min-height:100svh
  + flex-centering + scroll-snap-align) is what makes every scene
  full-screen; individual scenes should only add background/atmosphere,
  never their own height or centering overrides. Content width is equally
  centralized — see §1's --eb-container-text / --eb-container-wide and the
  ".eb-scene-inner" width formula in §3. Reuse these two systems for any
  new content instead of a one-off max-width, padding value, or transform
  offset.

  Contents:
    1. Tokens & base (container/gutter system)
    2. Motion utilities (mask, stagger, draw-line, particles, seal-ring motif)
    3. Scene shell — full-viewport + scroll-snap
    4. Scene 01 — The Sealed Invitation (gate + seal)
    5. Scene 02 — The Couple Reveal
    6. Scene 03 — Scratch to Reveal the Date (+ celebration)
    7. Scene 04 — The Countdown
    8. Scene 05 — The Wedding Journey (chapter index)
    9. Scenes 06–08 — Event chapters (mood "worlds")
    10. Scene 09 — A Glimpse of Our Story (photo carousel)
    11. Scene 10 — Guest Information (static, no response action)
    12. Final Scene — The Closing (static, no interaction)
    13. Fixed UI (music toggle, grain overlay)
    14. Motion & responsiveness
*/

/* ============ 1. Tokens & base ============ */
:root {
    --eb-midnight: #0b0d12;
    --eb-charcoal: #15171e;
    --eb-oxblood: #2c0f12;
    --eb-ink: #f2e9d8;
    --eb-ink-soft: rgba(242, 233, 216, 0.68);
    --eb-gold: #c6a15b;
    --eb-gold-bright: #e6c07a;
    --eb-gold-soft: rgba(198, 161, 91, 0.45);
    --eb-ivory: #f6efe3;
    --eb-ivory-deep: #ece1cb;
    --eb-charcoal-text: #29231a;
    --eb-charcoal-text-soft: rgba(41, 35, 26, 0.62);

    --eb-font-display: 'Bodoni Moda', Georgia, 'Times New Roman', serif;
    --eb-font-serif: 'Cormorant Garamond', Georgia, serif;
    --eb-font-ui: 'Jost', 'Segoe UI', sans-serif;

    --eb-ease: cubic-bezier(0.22, 1, 0.36, 1);
    --eb-dur-fast: 0.5s;
    --eb-dur-med: 0.95s;
    --eb-dur-slow: 1.3s;
    --eb-dur-cinematic: 1.7s;

    /* One container system for the whole page — see the header comment.
       Don't add a third max-width; reuse one of these two. */
    --eb-container-text: 640px;
    --eb-container-wide: 1160px;
    --eb-gutter: 24px;
}

html {
    scroll-behavior: smooth;
    scroll-snap-type: y mandatory;
}
html.eb-locked,
html.eb-locked body {
    overflow: hidden;
    height: 100%;
}

* { box-sizing: border-box; }

body {
    margin: 0;
    background: var(--eb-midnight);
    color: var(--eb-ink);
    font-family: var(--eb-font-ui);
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
}

.eb h1, .eb h2, .eb h3 { margin: 0; font-weight: 500; }

/* ============ 2. Motion utilities ============ */

/* Mask reveal — the "title sequence" text treatment used for the couple's
   names and chapter headings: content slides up from behind a clipped
   window rather than simply fading. */
.eb-mask { display: inline-block; overflow: hidden; vertical-align: top; }
.eb-mask--block { display: block; }
.eb-mask-inner {
    display: inline-block;
    transform: translateY(115%);
    transition: transform var(--eb-dur-slow) var(--eb-ease);
    will-change: transform;
}
.eb-mask--block .eb-mask-inner { display: block; }

/* Stagger — any element carrying this class fades/lifts in once its
   nearest ".eb-reveal.is-visible" ancestor is triggered, ordered purely by
   a "--stagger" custom property (index-based, not DOM-position-based) so
   markup order doesn't have to match reveal order. */
.eb-stagger-item {
    opacity: 0;
    transform: translateY(28px);
    transition: opacity var(--eb-dur-med) var(--eb-ease), transform var(--eb-dur-med) var(--eb-ease);
    transition-delay: calc(var(--stagger, 0) * 0.16s);
}
.is-visible .eb-stagger-item { opacity: 1; transform: translateY(0); }

/* A thin decorative line that draws itself in (scaleX) rather than fades. */
.eb-draw-line {
    display: block;
    width: 64px;
    height: 1px;
    margin: 0 auto 26px;
    background: var(--eb-gold);
    opacity: 0;
    transform: scaleX(0);
    transform-origin: center;
    transition: opacity var(--eb-dur-med) var(--eb-ease), transform var(--eb-dur-slow) var(--eb-ease);
    transition-delay: calc(var(--stagger, 0) * 0.16s);
}
.is-visible .eb-draw-line { opacity: 1; transform: scaleX(1); }
body.is-opened .eb-name-rule { opacity: 1; transform: scaleX(1); transition-delay: 1.7s; }

/* Particle burst — see assets/js/particles.js. The field element must be
   the positioned ancestor particles are centered against. */
.eb-particle-field { position: absolute; inset: 0; overflow: visible; pointer-events: none; z-index: 5; }
.eb-particle {
    position: absolute;
    left: 50%;
    top: 50%;
    border-radius: 50%;
    background: var(--eb-gold-bright);
    box-shadow: 0 0 7px 1px rgba(230, 180, 90, 0.85);
    opacity: 0;
    animation-name: eb-particle-rise;
    animation-timing-function: cubic-bezier(0.22, 1, 0.36, 1);
    animation-fill-mode: forwards;
}
@keyframes eb-particle-rise {
    0% { opacity: 0; transform: translate(-50%, -50%) translate(0, 0) scale(0.4); }
    18% { opacity: 1; }
    100% { opacity: 0; transform: translate(-50%, -50%) translate(var(--dx), var(--dy)) scale(1); }
}

/* Shared "seal" ring motif (two rotated squares = an 8-point star), echoing
   the opening seal (Scene 01). Used today on the closing scene's small
   decorative motif — a deliberate visual bookend. */
.eb-token-ring { position: absolute; inset: 0; border-radius: 50%; }
.eb-token-ring::before, .eb-token-ring::after {
    content: '';
    position: absolute;
    inset: 10%;
    border: 1px solid var(--eb-gold-soft);
}
.eb-token-ring::before { transform: rotate(0deg); }
.eb-token-ring::after { transform: rotate(45deg); }

/* ============ 3. Scene shell — full-viewport + scroll-snap ============ */
.eb-scene {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
    min-height: 100svh;
    padding-block: clamp(56px, 9vh, 110px);
    text-align: center;
    overflow: hidden;
    scroll-snap-align: start;
    scroll-snap-stop: always;
}

/* The one content-width formula every scene's inner wrapper should use —
   a fluid width bounded by a container cap, with the gutter baked in so
   nothing needs its own padding/margin math. */
.eb-scene-inner {
    position: relative;
    z-index: 2;
    width: min(100% - (var(--eb-gutter) * 2), var(--eb-container-text));
    margin-inline: auto;
}

/* Applied to scenes whose visible motion comes entirely from internal
   ".eb-stagger-item"/mask children — the outer section itself stays put
   (opacity:1) and only exists as the IntersectionObserver target. */
.eb-reveal.eb-reveal--bare { opacity: 1; transform: none; }

.eb-kicker {
    display: block;
    font-family: var(--eb-font-ui);
    font-size: 0.76rem;
    letter-spacing: 0.32em;
    text-transform: uppercase;
    color: var(--eb-gold);
    margin-bottom: 22px;
}
.eb-scene-title {
    font-family: var(--eb-font-display);
    font-style: italic;
    font-size: clamp(1.9rem, 5vw, 2.6rem);
    line-height: 1.25;
    margin-bottom: 20px;
}

.eb-reveal {
    opacity: 0;
    transform: translateY(40px);
    transition: opacity var(--eb-dur-slow) var(--eb-ease), transform var(--eb-dur-slow) var(--eb-ease);
}
.eb-reveal.is-visible { opacity: 1; transform: translateY(0); }

/* Ambient environment layers shared across scenes: soft blurred "drift"
   blobs. Kept generic here; each scene picks its own colors/positions. */
.eb-drift {
    position: absolute;
    border-radius: 50%;
    filter: blur(40px);
    opacity: 0.55;
    pointer-events: none;
    animation: eb-drift-move 24s ease-in-out infinite alternate;
}
@keyframes eb-drift-move {
    0% { transform: translate(0, 0) scale(1); }
    100% { transform: translate(3%, -4%) scale(1.12); }
}

/* ============ 4. Scene 01 — The Sealed Invitation ============ */
.eb-gate {
    position: fixed;
    inset: 0;
    z-index: 100;
    display: flex;
    align-items: center;
    justify-content: center;
    background: radial-gradient(ellipse at 50% 38%, var(--eb-charcoal) 0%, var(--eb-midnight) 72%);
    overflow: hidden;
    perspective: 900px;
}
.eb-gate[hidden] { display: none; }

.eb-gate-atmosphere {
    position: absolute;
    inset: 0;
    z-index: 0;
    opacity: 0.5;
    background-image:
        linear-gradient(180deg, transparent 60%, rgba(0,0,0,0.5) 100%),
        radial-gradient(circle at 18% 88%, rgba(198,161,91,0.12), transparent 40%),
        radial-gradient(circle at 84% 14%, rgba(198,161,91,0.08), transparent 45%);
    pointer-events: none;
    animation: eb-atmosphere-drift 26s ease-in-out infinite alternate;
}
@keyframes eb-atmosphere-drift {
    0% { transform: scale(1) translate(0, 0); }
    100% { transform: scale(1.06) translate(-1.5%, 1.5%); }
}

.eb-gate-arch-silhouette {
    position: absolute;
    inset: -10% -10%;
    z-index: 0;
    opacity: 0.35;
    background-image:
        radial-gradient(ellipse 42% 60% at 10% 100%, rgba(0,0,0,0.55), transparent 70%),
        radial-gradient(ellipse 42% 60% at 90% 100%, rgba(0,0,0,0.55), transparent 70%),
        linear-gradient(115deg, transparent 30%, rgba(198,161,91,0.08) 48%, transparent 66%);
    background-size: 100% 100%, 100% 100%, 220% 220%;
    animation: eb-lightleak 34s linear infinite;
    pointer-events: none;
}
@keyframes eb-lightleak {
    0% { background-position: 0 0, 0 0, 0% 0%; }
    100% { background-position: 0 0, 0 0, -140% 60%; }
}

.eb-gate-spotlight {
    position: absolute;
    inset: 0;
    z-index: 1;
    opacity: 0;
    background: radial-gradient(circle at var(--mx, 50%) var(--my, 50%), rgba(230, 180, 90, 0.14), transparent 45%);
    transition: opacity 0.4s ease;
    pointer-events: none;
}

.eb-gate-panel {
    position: absolute;
    top: 0;
    height: 100%;
    width: 50%;
    background: linear-gradient(165deg, var(--eb-charcoal) 0%, var(--eb-midnight) 85%);
    transition: transform var(--eb-dur-cinematic) var(--eb-ease);
    z-index: 2;
}
.eb-gate-panel::after {
    content: '';
    position: absolute;
    inset: 0;
    opacity: 0.5;
    transition: opacity var(--eb-dur-cinematic) var(--eb-ease) 0.15s;
}
.eb-gate-panel--left { left: 0; box-shadow: inset -1px 0 0 var(--eb-gold-soft); }
.eb-gate-panel--left::after { background: radial-gradient(circle at 100% 50%, rgba(198,161,91,0.16), transparent 60%); }
.eb-gate-panel--right { right: 0; box-shadow: inset 1px 0 0 var(--eb-gold-soft); }
.eb-gate-panel--right::after { background: radial-gradient(circle at 0% 50%, rgba(198,161,91,0.16), transparent 60%); }
.eb-gate.is-opening .eb-gate-panel--left { transform: translateX(-100%); }
.eb-gate.is-opening .eb-gate-panel--right { transform: translateX(100%); }
.eb-gate.is-opening .eb-gate-panel::after { opacity: 0; }

.eb-gate-glow {
    position: absolute;
    left: 50%;
    top: 50%;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(198,161,91,0.95), rgba(198,161,91,0) 70%);
    transform: translate(-50%, -50%) scale(0);
    opacity: 0;
    transition: transform 1.3s var(--eb-ease), opacity 1.3s var(--eb-ease);
    pointer-events: none;
    z-index: 3;
}
.eb-gate.is-anticipating .eb-gate-glow { transform: translate(-50%, -50%) scale(5); opacity: 0.4; }
.eb-gate.is-opening .eb-gate-glow { transform: translate(-50%, -50%) scale(170); opacity: 1; transition-duration: 1.5s; }

.eb-gate-particles { position: absolute; inset: 0; z-index: 4; pointer-events: none; overflow: visible; }

.eb-seal-tilt {
    position: relative;
    z-index: 5;
    display: inline-flex;
    transform-style: preserve-3d;
    transition: transform 0.35s ease-out;
}

.eb-seal {
    position: relative;
    width: clamp(150px, 34vw, 216px);
    height: clamp(150px, 34vw, 216px);
    background: transparent;
    border: none;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--eb-gold);
    -webkit-tap-highlight-color: transparent;
    transition: transform var(--eb-dur-fast) var(--eb-ease);
}
.eb-seal.is-pressed { transform: scale(0.94); }

.eb-seal::before, .eb-seal::after {
    content: '';
    position: absolute;
    inset: 8%;
    border: 1px solid var(--eb-gold-soft);
    transition: transform var(--eb-dur-cinematic) var(--eb-ease), opacity var(--eb-dur-cinematic) var(--eb-ease);
}
.eb-seal::before { transform: rotate(0deg); }
.eb-seal::after { transform: rotate(45deg); }

.eb-seal-ring {
    position: absolute;
    inset: 0;
    border-radius: 50%;
    border: 1px solid var(--eb-gold-soft);
    animation: eb-rotate-slow 44s linear infinite;
    transition: opacity var(--eb-dur-med) var(--eb-ease), transform var(--eb-dur-med) var(--eb-ease);
}
.eb-seal-ring--outer { inset: -16px; opacity: 0.5; animation-duration: 64s; animation-direction: reverse; }
@keyframes eb-rotate-slow { to { transform: rotate(360deg); } }

.eb-seal-mark {
    position: relative;
    z-index: 1;
    font-family: var(--eb-font-display);
    font-style: italic;
    font-size: 1.9rem;
    letter-spacing: 0.02em;
    transition: opacity var(--eb-dur-fast) ease;
}
.eb-seal-amp { display: inline-block; margin: 0 5px; opacity: 0.85; }

.eb-seal-instruction {
    position: absolute;
    bottom: -44px;
    left: 0;
    right: 0;
    font-family: var(--eb-font-ui);
    font-size: 0.66rem;
    letter-spacing: 0.3em;
    text-transform: uppercase;
    color: var(--eb-ink-soft);
    animation: eb-instruction-pulse 2.6s ease-in-out infinite;
}
@keyframes eb-instruction-pulse { 0%, 100% { opacity: 0.55; } 50% { opacity: 1; } }

.eb-seal.is-breaking { transform: scale(1); }
.eb-seal.is-breaking::before { transform: rotate(-42deg) scale(1.8); opacity: 0; }
.eb-seal.is-breaking::after { transform: rotate(88deg) scale(1.8); opacity: 0; }
.eb-seal.is-breaking .eb-seal-ring { opacity: 0; transform: scale(2.1); }
.eb-seal.is-breaking .eb-seal-mark,
.eb-seal.is-breaking .eb-seal-instruction { opacity: 0; transition: opacity 0.35s ease; animation: none; }

/* ============ 5. Scene 02 — The Couple Reveal ============ */
.eb-reveal-scene {
    background: radial-gradient(ellipse at 50% 28%, var(--eb-charcoal) 0%, var(--eb-midnight) 75%);
    background-size: 130% 130%;
    animation: eb-atmosphere-shift 30s ease-in-out infinite alternate;
}
@keyframes eb-atmosphere-shift {
    0% { background-position: 50% 30%; }
    100% { background-position: 46% 36%; }
}

.eb-reveal-atmosphere { position: absolute; inset: 0; z-index: 0; overflow: hidden; pointer-events: none; }
.eb-drift--1 { width: 38vw; height: 38vw; top: 4%; left: -10%; background: radial-gradient(circle, rgba(198,161,91,0.32), transparent 70%); }
.eb-drift--2 { width: 30vw; height: 30vw; bottom: 2%; right: -8%; background: radial-gradient(circle, rgba(198,161,91,0.24), transparent 70%); animation-duration: 30s; animation-delay: -6s; }
.eb-drift--3 { width: 20vw; height: 20vw; top: 44%; left: 62%; background: radial-gradient(circle, rgba(230,192,122,0.2), transparent 70%); animation-duration: 20s; animation-delay: -12s; }

.eb-reveal-line {
    opacity: 0;
    transform: translateY(24px);
    transition: opacity var(--eb-dur-slow) var(--eb-ease), transform var(--eb-dur-slow) var(--eb-ease);
}
body.is-opened .eb-kicker-line { transition-delay: 0.2s; }
body.is-opened .eb-hero-teaser { transition-delay: 2.05s; }
body.is-opened .eb-reveal-cue { transition-delay: 2.55s; }
body.is-opened .eb-reveal-line { opacity: 1; transform: translateY(0); }

.eb-monogram {
    position: relative;
    z-index: 1;
    font-family: var(--eb-font-display);
    font-size: clamp(2.6rem, 11vw, 6.4rem);
    line-height: 1;
    letter-spacing: 0.01em;
    margin-bottom: 20px;
    text-shadow: 0 8px 60px rgba(0, 0, 0, 0.5);
}
body.is-opened .eb-monogram .eb-mask-inner { transform: translateY(0); }
.eb-monogram .eb-mask:first-of-type .eb-mask-inner { transition-delay: 0.65s; }
.eb-monogram .eb-mask:last-of-type .eb-mask-inner { transition-delay: 1.4s; }

.eb-name-amp {
    display: inline-block;
    font-style: italic;
    font-size: 0.55em;
    color: var(--eb-gold);
    margin: 0 10px;
    opacity: 0;
    transform: scale(0.4);
    transition: opacity var(--eb-dur-med) ease, transform var(--eb-dur-med) var(--eb-ease);
    transition-delay: 1.05s;
    text-shadow: 0 0 0 rgba(198,161,91,0);
}
body.is-opened .eb-name-amp {
    opacity: 1;
    transform: scale(1);
    text-shadow: 0 0 18px rgba(230, 192, 122, 0.55);
}

.eb-name-rule { opacity: 0; margin: 26px auto 30px; }

.eb-hero-teaser {
    position: relative;
    z-index: 1;
    font-family: var(--eb-font-serif);
    font-style: italic;
    font-size: 1.05rem;
    color: var(--eb-ink-soft);
    max-width: 380px;
    margin: 0 auto;
    line-height: 1.6;
}

.eb-reveal-cue {
    position: absolute;
    bottom: max(28px, env(safe-area-inset-bottom));
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    color: var(--eb-ink-soft);
    font-size: 0.64rem;
    letter-spacing: 0.3em;
    text-transform: uppercase;
}
.eb-reveal-cue span {
    width: 1px;
    height: 26px;
    background: var(--eb-gold-soft);
    animation: eb-pulse-line 2.2s infinite;
}
@keyframes eb-pulse-line {
    0% { opacity: 0.25; transform: scaleY(0.5); }
    50% { opacity: 1; transform: scaleY(1); }
    100% { opacity: 0.25; transform: scaleY(0.5); }
}

/* ============ 6. Scene 03 — Scratch to Reveal the Date ============ */
.eb-scratch-scene {
    background: linear-gradient(180deg, var(--eb-midnight), var(--eb-oxblood) 130%);
    isolation: isolate;
}
.eb-scratch-atmosphere {
    position: absolute;
    inset: 0;
    z-index: 0;
    background: radial-gradient(circle at 50% 70%, rgba(198,161,91,0.16), transparent 60%);
    pointer-events: none;
}
.eb-scratch-scene::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 0;
    background: radial-gradient(circle at 50% 55%, rgba(230, 180, 90, 0.16), transparent 65%);
    opacity: 0;
    transition: opacity 1.8s ease;
    pointer-events: none;
}
.eb-scratch-scene.is-celebrating::before { opacity: 1; }

.eb-scratch-scene .eb-scene-title {
    color: var(--eb-ink);
    max-width: 420px;
    margin-inline: auto;
}

.eb-scratch-widget { position: relative; width: 100%; max-width: 100%; }

/* A slow, warm pulse behind the still-sealed surface — "something magical
   is waiting underneath." Fades out once the celebration begins, since the
   burst-glow (below) takes over from there. */
.eb-scratch-hidden-glow {
    position: absolute;
    left: 50%;
    top: 50%;
    width: 70%;
    height: 70%;
    transform: translate(-50%, -50%);
    background: radial-gradient(circle, rgba(230, 180, 90, 0.35), transparent 72%);
    filter: blur(10px);
    animation: eb-hidden-pulse 3.6s ease-in-out infinite;
    pointer-events: none;
    z-index: 0;
    transition: opacity 0.8s ease;
}
.eb-scratch-widget.is-celebrating .eb-scratch-hidden-glow { opacity: 0; }
@keyframes eb-hidden-pulse {
    0%, 100% { opacity: 0.5; transform: translate(-50%, -50%) scale(0.92); }
    50% { opacity: 0.9; transform: translate(-50%, -50%) scale(1.05); }
}

/* The scratch card itself — sized against its own parent (100%), never
   the raw viewport. The parent (.eb-scene-inner) is already the one place
   that subtracts the page gutter, so re-subtracting a vw-based guess here
   double-counted (or under/over-counted) that gutter at certain widths and
   is what pushed the card past the edge of the screen on mobile. width:
   min(100%, 360px) always resolves to whatever room the parent actually
   has, capped at 360px on roomier screens — no separate mobile override
   needed, it already shrinks correctly on its own. */
.eb-scratch {
    position: relative;
    z-index: 1;
    width: min(100%, 360px);
    max-width: 100%;
    aspect-ratio: 4 / 3;
    margin: 36px auto 20px;
    overflow: visible;
    box-shadow: 0 40px 80px -30px rgba(0, 0, 0, 0.65);
    border-radius: 6px;
}

.eb-scratch-burst-glow {
    position: absolute;
    left: 50%;
    top: 50%;
    width: 40%;
    height: 40%;
    z-index: 0;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(230, 180, 90, 0.9), rgba(230, 180, 90, 0) 70%);
    transform: translate(-50%, -50%) scale(0.3);
    opacity: 0;
    pointer-events: none;
}
.eb-scratch-widget.is-celebrating .eb-scratch-burst-glow {
    animation: eb-burst-glow 1.9s var(--eb-ease) forwards;
}
@keyframes eb-burst-glow {
    0% { opacity: 0; transform: translate(-50%, -50%) scale(0.3); }
    30% { opacity: 0.95; }
    100% { opacity: 0; transform: translate(-50%, -50%) scale(4.6); }
}

.eb-scratch-answer {
    position: absolute;
    inset: 0;
    z-index: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    background: var(--eb-midnight);
    color: var(--eb-gold);
    gap: 10px;
    border-radius: 6px;
    overflow: hidden;
}
.eb-scratch-badge {
    font-family: var(--eb-font-ui);
    font-size: 0.62rem;
    letter-spacing: 0.32em;
    text-transform: uppercase;
    color: var(--eb-gold-bright);
    opacity: 0;
    transform: translateY(10px);
    transition: opacity var(--eb-dur-med) var(--eb-ease), transform var(--eb-dur-med) var(--eb-ease);
    transition-delay: 0.95s;
    margin-bottom: 2px;
}
.eb-scratch-widget.is-celebrating .eb-scratch-badge { opacity: 1; transform: translateY(0); }

.eb-scratch-days {
    font-family: var(--eb-font-display);
    font-size: clamp(1.9rem, 7vw, 2.8rem);
    letter-spacing: 0.06em;
}
.eb-scratch-widget.is-celebrating .eb-scratch-days {
    animation: eb-date-settle 1s var(--eb-ease) 0.3s both;
}
@keyframes eb-date-settle {
    0% { opacity: 0.3; transform: scale(0.82); }
    55% { opacity: 1; transform: scale(1.08); }
    100% { opacity: 1; transform: scale(1); }
}
.eb-scratch-month {
    font-family: var(--eb-font-ui);
    font-size: 0.78rem;
    letter-spacing: 0.35em;
    text-transform: uppercase;
    color: var(--eb-ink-soft);
}
.eb-scratch-answer::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(100deg, transparent 32%, rgba(255, 244, 214, 0.55) 50%, transparent 68%);
    transform: translateX(-140%);
    opacity: 0;
    pointer-events: none;
}
.eb-scratch-widget.is-celebrating .eb-scratch-answer::after {
    animation: eb-sweep 1.15s ease 0.45s 1;
}
@keyframes eb-sweep {
    0% { opacity: 0.9; transform: translateX(-140%); }
    100% { opacity: 0; transform: translateX(140%); }
}

.eb-scratch-canvas {
    /* A <canvas> is a replaced element: "inset: 0" alone does NOT stretch
       it to fill its container the way it would a normal <div> — with
       'width'/'height' left as CSS auto, browsers size a replaced element
       to its intrinsic HTML width/height attributes (300x150 by default)
       instead, letting it bleed past the card's actual frame at any size
       other than that exact one. Explicit 100%/100% is required here. */
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    z-index: 2;
    touch-action: none;
    cursor: grab;
    border-radius: 6px;
    transition: opacity 0.85s var(--eb-ease), transform 0.85s var(--eb-ease), filter 0.85s var(--eb-ease);
}
.eb-scratch-canvas.is-revealed {
    opacity: 0;
    transform: scale(1.06);
    filter: blur(6px);
    pointer-events: none;
}

.eb-scratch-particles { z-index: 3; }

.eb-scratch-hint {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    font-size: 0.72rem;
    letter-spacing: 0.26em;
    text-transform: uppercase;
    color: var(--eb-ink-soft);
    transition: opacity 0.5s ease;
}
.eb-scratch-hint i { animation: eb-hand-sway 1.7s ease-in-out infinite; }
@keyframes eb-hand-sway {
    0%, 100% { transform: translateX(-7px) rotate(0deg); }
    50% { transform: translateX(7px) rotate(10deg); }
}

.eb-scratch-fallback {
    display: block;
    margin: 16px auto 0;
    background: none;
    border: none;
    color: var(--eb-ink-soft);
    text-decoration: underline;
    text-underline-offset: 4px;
    font-family: var(--eb-font-ui);
    font-size: 0.72rem;
    letter-spacing: 0.08em;
    cursor: pointer;
    transition: opacity 0.5s ease;
}
[data-scratch-root].is-revealed .eb-scratch-hint,
[data-scratch-root].is-revealed .eb-scratch-fallback { opacity: 0; pointer-events: none; }

/* ============ 7. Scene 03 (cont.) — the countdown ============
   Lives inside #date now, not its own scroll-snap scene — it is revealed
   as a reward once the scratch surface has finished clearing (see the
   eb:scratch-revealed handler in script.js), not on scroll. Because of
   that it never receives the generic scroll-reveal observer's own
   ".is-visible" (that class lands on #date itself, long before the
   countdown should appear), so every reveal transition below is keyed off
   ".eb-inline-countdown.is-shown" instead — a class JS adds a beat after
   the surface clears, once #date's ".hidden" attribute has been lifted. */
.eb-inline-countdown {
    position: relative;
    z-index: 1;
    margin-top: clamp(30px, 6vw, 58px);
    opacity: 0;
    transform: translateY(16px);
    transition: opacity 0.9s var(--eb-ease), transform 0.9s var(--eb-ease);
}
.eb-inline-countdown.is-shown { opacity: 1; transform: translateY(0); }

.eb-countdown-row {
    position: relative;
    z-index: 1;
    display: flex;
    justify-content: center;
    align-items: baseline;
    gap: clamp(14px, 5vw, 52px);
    flex-wrap: wrap;
    margin-top: 14px;
}
.eb-countdown-unit { position: relative; display: flex; flex-direction: column; align-items: center; }
.eb-countdown-unit + .eb-countdown-unit::before {
    content: '';
    position: absolute;
    left: calc(-1 * clamp(7px, 2.6vw, 26px));
    top: 22%;
    width: 1px;
    height: 46%;
    background: var(--eb-gold-soft);
    transform: scaleY(0);
    transition: transform var(--eb-dur-slow) var(--eb-ease);
    transition-delay: calc(var(--stagger, 0) * 0.16s);
}
.eb-inline-countdown.is-shown .eb-countdown-unit + .eb-countdown-unit::before { transform: scaleY(1); }

.eb-countdown-mask { display: block; overflow: hidden; }
.eb-countdown-value {
    display: block;
    font-family: var(--eb-font-display);
    font-size: clamp(1.9rem, 8.5vw, 4.4rem);
    line-height: 1;
    font-variant-numeric: tabular-nums;
    color: var(--eb-ink);
    transform: translateY(120%);
    transition: transform var(--eb-dur-slow) var(--eb-ease);
    transition-delay: calc(var(--stagger, 0) * 0.16s);
}
.eb-inline-countdown.is-shown .eb-countdown-value { transform: translateY(0); }

.eb-countdown-row::after {
    content: '';
    position: absolute;
    inset: -10% -4%;
    background: linear-gradient(100deg, transparent 40%, rgba(255, 244, 214, 0.35) 50%, transparent 60%);
    transform: translateX(-140%);
    opacity: 0;
    pointer-events: none;
}
.eb-inline-countdown.is-shown .eb-countdown-row::after { animation: eb-sweep 1.3s ease 0.85s 1; }

.eb-countdown-label {
    margin-top: 12px;
    font-size: 0.62rem;
    letter-spacing: 0.28em;
    text-transform: uppercase;
    color: var(--eb-ink-soft);
    opacity: 0;
    transition: opacity var(--eb-dur-med) var(--eb-ease);
    transition-delay: calc(var(--stagger, 0) * 0.16s + 0.2s);
}
.eb-inline-countdown.is-shown .eb-countdown-label { opacity: 1; }

/* ============ 8. Scene 05 — The Wedding Journey ============ */
.eb-journey-scene {
    background: radial-gradient(ellipse at 50% 20%, var(--eb-charcoal) 0%, var(--eb-midnight) 68%);
}
.eb-journey-scene::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 0;
    background-image:
        radial-gradient(circle at 12% 85%, rgba(198,161,91,0.12), transparent 45%),
        radial-gradient(circle at 88% 12%, rgba(198,161,91,0.09), transparent 45%);
    pointer-events: none;
}
.eb-journey-sub {
    font-family: var(--eb-font-serif);
    font-style: italic;
    color: var(--eb-ink-soft);
    margin-bottom: 10px;
}

/* ---- The artwork: one composition, not three icons ----
   Normal document flow (never absolutely full-bleed), sized by width —
   min(100%, cap) + a fixed aspect-ratio — the same parent-relative
   formula as the scratch card, never vw, so it scales as one
   proportional unit instead of a decoration that can crop. Each group
   inside the SVG (arch, branches, mehndi medallion, couple, procession
   hint, candles, motes) reveals on its own delay once the scene's own
   ".is-visible" lands — a slow, staged "something beautiful is
   unfolding," not a burst of simultaneous motion. Every duration here is
   an ordinary transition/animation, so the global reduced-motion block
   at the bottom of this file (§14) already collapses all of it to
   ~instant with no special-casing needed here. */
.eb-journey-art {
    position: relative;
    z-index: 1;
    width: min(100%, 600px);
    aspect-ratio: 520 / 420;
    margin: 18px auto 8px;
    color: var(--eb-gold-soft);
    overflow: hidden;
}
.eb-journey-art::before {
    content: '';
    position: absolute;
    inset: -12%;
    z-index: 0;
    background: radial-gradient(ellipse at 50% 58%, rgba(198, 161, 91, 0.24), transparent 68%);
    opacity: 0;
    transition: opacity 2s var(--eb-ease);
    pointer-events: none;
}
.eb-journey-scene.is-visible .eb-journey-art::before { opacity: 1; }

.eb-journey-art svg {
    position: relative;
    z-index: 1;
    display: block;
    width: 100%;
    height: 100%;
}
.eb-journey-art svg path,
.eb-journey-art svg line { fill: none; stroke: currentColor; }

.eb-ja-arch-outer path, .eb-ja-arch-inner path, .eb-ja-threshold path {
    stroke-width: 1.1;
    stroke-dasharray: 1400;
    stroke-dashoffset: 1400;
    opacity: 0;
    transition: stroke-dashoffset 2.1s var(--eb-ease), opacity 0.5s ease;
}
.eb-ja-arch-inner path { stroke-width: 0.8; }
.eb-ja-threshold path { stroke-width: 0.7; }
.eb-journey-scene.is-visible .eb-ja-arch-outer path { stroke-dashoffset: 0; opacity: 0.85; transition-delay: 0.15s; }
.eb-journey-scene.is-visible .eb-ja-arch-inner path { stroke-dashoffset: 0; opacity: 0.45; transition-delay: 0.4s; }
.eb-journey-scene.is-visible .eb-ja-threshold path { stroke-dashoffset: 0; opacity: 0.4; transition-delay: 0.6s; }

.eb-ja-mehndi {
    opacity: 0;
    transform: scale(0.82);
    transform-origin: 90px 95px;
    transition: opacity 1.3s ease, transform 1.3s var(--eb-ease);
    transition-delay: 0.75s;
}
.eb-ja-mehndi circle, .eb-ja-mehndi line { stroke-width: 0.8; }
.eb-journey-scene.is-visible .eb-ja-mehndi { opacity: 0.55; transform: scale(1); }

.eb-ja-branches {
    opacity: 0;
    transform: scale(0.88);
    transform-origin: center;
    transition: opacity 1.4s ease, transform 1.4s var(--eb-ease);
    transition-delay: 0.9s;
}
.eb-ja-branches path { stroke-width: 0.9; }
.eb-ja-branches ellipse { fill: currentColor; stroke: none; }
.eb-journey-scene.is-visible .eb-ja-branches { opacity: 0.55; transform: scale(1); }

.eb-ja-couple {
    color: var(--eb-ink);
    opacity: 0;
    transform: translateY(14px);
    transition: opacity 1.3s ease, transform 1.3s var(--eb-ease);
    transition-delay: 1.15s;
}
.eb-ja-couple path { stroke-width: 0.9; fill: currentColor; fill-opacity: 0.14; }
.eb-journey-scene.is-visible .eb-ja-couple { opacity: 0.92; transform: translateY(0); }

.eb-ja-procession {
    opacity: 0;
    transition: opacity 1.2s ease;
    transition-delay: 1.4s;
}
.eb-ja-procession path { stroke-width: 0.7; }
.eb-journey-scene.is-visible .eb-ja-procession { opacity: 0.4; }

.eb-ja-candles {
    opacity: 0;
    transition: opacity 1.2s ease;
    transition-delay: 1.5s;
}
.eb-ja-candles path { stroke-width: 1; }
.eb-journey-scene.is-visible .eb-ja-candles { opacity: 0.5; }

.eb-ja-motes circle { fill: currentColor; opacity: 0; }
@media (prefers-reduced-motion: no-preference) {
    .eb-journey-scene.is-visible .eb-ja-motes circle {
        animation: eb-journey-mote-twinkle 5.5s ease-in-out infinite;
        animation-delay: var(--mote-delay, 0s);
    }
}
.eb-journey-scene.is-visible .eb-ja-motes circle { opacity: 0.35; }
@keyframes eb-journey-mote-twinkle {
    0%, 100% { opacity: 0.15; }
    50% { opacity: 0.65; }
}

/* ---- The list, threaded by one ornamental path instead of a straight
   line ---- */
.eb-journey-list-wrap {
    position: relative;
    width: min(100%, 340px);
    margin: 30px auto 0;
}
.eb-journey-path {
    position: absolute;
    left: 22px;
    top: 8px;
    bottom: 8px;
    width: 24px;
    transform: translateX(-12px);
    pointer-events: none;
}
.eb-journey-path svg { display: block; width: 100%; height: 100%; overflow: visible; }
.eb-journey-path-line {
    fill: none;
    stroke: var(--eb-gold-soft);
    stroke-width: 1;
    stroke-dasharray: 340;
    stroke-dashoffset: 340;
    transition: stroke-dashoffset 1.3s var(--eb-ease);
    transition-delay: 1.3s;
}
.eb-journey-path-tick {
    fill: var(--eb-gold);
    opacity: 0;
    transition: opacity 0.6s ease;
}
.eb-journey-path-tick:nth-of-type(2) { transition-delay: 1.5s; }
.eb-journey-path-tick:nth-of-type(3) { transition-delay: 1.75s; }
.eb-journey-path-tick:nth-of-type(4) { transition-delay: 2s; }
.eb-journey-scene.is-visible .eb-journey-path-line { stroke-dashoffset: 0; }
.eb-journey-scene.is-visible .eb-journey-path-tick { opacity: 0.85; }

.eb-journey-list {
    list-style: none;
    padding: 0;
    margin: 0;
    text-align: left;
}

.eb-journey-item { position: relative; padding-left: 56px; margin-bottom: 32px; }
.eb-journey-item:last-child { margin-bottom: 0; }

/* The star sits above the roman numeral in the same gutter the connecting
   path runs through — one small marker per chapter, echoing the same
   "✦" emblem the scratch surface reveals, rather than a generic dot or
   icon. */
.eb-journey-marker {
    position: absolute;
    left: 0;
    top: -2px;
    width: 44px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
}
.eb-journey-marker-star {
    font-size: 0.8rem;
    color: var(--eb-gold-bright);
    text-shadow: 0 0 10px rgba(230, 192, 122, 0.55);
}
.eb-journey-roman {
    font-family: var(--eb-font-display);
    font-style: italic;
    font-size: 1.15rem;
    color: var(--eb-gold);
}
.eb-journey-link {
    display: block;
    font-family: var(--eb-font-display);
    font-size: clamp(1.3rem, 4vw, 1.5rem);
    color: var(--eb-ink);
    text-decoration: none;
    letter-spacing: 0.01em;
    transition: color 0.3s ease, transform 0.3s ease;
}
.eb-journey-link:hover, .eb-journey-link:focus-visible { color: var(--eb-gold); transform: translateX(6px); }
.eb-journey-meta {
    display: block;
    margin-top: 6px;
    font-family: var(--eb-font-ui);
    font-size: 0.7rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--eb-ink-soft);
}
/* Mobile-only, along with ".eb-journey-time" below: this is new content
   (not just a restyle of what was already there), so both are kept off
   the desktop layout entirely — desktop's caption stays exactly "15
   November", not "15 November · 6:00 PM onwards" — rather than changing
   its established rhythm. See the mobile breakpoint below. */
.eb-journey-time { display: none; }
.eb-journey-venue {
    display: none;
    margin-top: 3px;
    font-family: var(--eb-font-serif);
    font-style: italic;
    font-size: 0.92rem;
    color: var(--eb-gold-soft);
}

/* ============ 9. Scenes 06–08 — Event chapters ("worlds") ============
   Each chapter carries ".eb-scene" in its markup (see partials/chapter.php)
   so it gets the same full-viewport/scroll-snap/centering treatment as
   every other scene for free — everything here is mood-specific
   background and decoration only. */
.eb-chapter-inner {
    position: relative;
    z-index: 3;
    width: min(100% - (var(--eb-gutter) * 2), var(--eb-container-text));
    margin-inline: auto;
}

.eb-chapter-depth {
    position: absolute;
    inset: 0;
    z-index: 1;
    background: radial-gradient(ellipse at 50% 100%, rgba(0,0,0,0.55), transparent 65%);
    opacity: 0;
    transition: opacity 1.6s ease;
    pointer-events: none;
}
.eb-chapter.is-visible .eb-chapter-depth { opacity: 1; }

.eb-chapter-roman {
    display: block;
    font-family: var(--eb-font-display);
    font-style: italic;
    font-size: 1rem;
    letter-spacing: 0.35em;
    margin-bottom: 16px;
    opacity: 0.75;
}
.eb-chapter-name {
    font-family: var(--eb-font-display);
    font-size: clamp(2.3rem, 8vw, 4.4rem);
    margin: 0 0 30px;
    line-height: 1.05;
}
.eb-chapter.is-visible .eb-chapter-name .eb-mask-inner { transition-delay: 0.25s; transform: translateY(0); }

.eb-chapter-details {
    margin: 0 auto 26px;
    width: min(100%, 360px);
    text-align: left;
    border-top: 1px solid var(--chapter-line, var(--eb-gold-soft));
}
.eb-chapter-detail {
    padding: 14px 0;
    border-bottom: 1px solid var(--chapter-line, var(--eb-gold-soft));
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 18px;
}
.eb-detail-label {
    font-family: var(--eb-font-ui);
    font-size: 0.68rem;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    opacity: 0.75;
    flex-shrink: 0;
}
.eb-detail-value { font-family: var(--eb-font-serif); font-size: 1rem; text-align: right; }
.eb-chapter-direction {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-family: var(--eb-font-ui);
    font-size: 0.72rem;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: inherit;
    text-decoration: none;
    border-bottom: 1px solid currentColor;
    padding-bottom: 5px;
    opacity: 0.85;
    transition: opacity 0.3s ease, gap 0.3s ease;
}
.eb-chapter-direction:hover { opacity: 1; gap: 14px; }
.eb-chapter-message {
    margin: 26px auto 0;
    max-width: 420px;
    font-family: var(--eb-font-serif);
    font-style: italic;
    font-size: 1.05rem;
    line-height: 1.7;
    opacity: 0.85;
}

/* --- World: Mehndi — warm, festive, alive --- */
.eb-chapter--warm {
    --chapter-line: rgba(246, 236, 217, 0.28);
    background: radial-gradient(ellipse at 28% 18%, #4a2c10 0%, #241407 78%);
    color: #f6ecd9;
}
.eb-chapter--warm::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 1;
    background: radial-gradient(ellipse at 30% 15%, rgba(230, 172, 84, 0.35), transparent 60%);
    opacity: 0;
    transform: scale(0.85);
    transition: opacity 1.6s var(--eb-ease), transform 1.6s var(--eb-ease);
    pointer-events: none;
}
.eb-chapter--warm.is-visible::before { opacity: 1; transform: scale(1); }

/* Faint festive jaali-style lattice, drawn once in an SVG data-uri so no
   image asset is needed — a repeating diagonal geometric pattern. */
.eb-chapter-pattern {
    position: absolute;
    inset: 0;
    z-index: 1;
    opacity: 0;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='84' height='84'><path d='M42 0 L84 42 L42 84 L0 42 Z' fill='none' stroke='rgba(230,180,90,0.5)' stroke-width='1'/></svg>");
    background-size: 84px 84px;
    transition: opacity 2s ease;
    animation: eb-pattern-drift 40s linear infinite;
    pointer-events: none;
}
.eb-chapter--warm.is-visible .eb-chapter-pattern { opacity: 0.16; }
@keyframes eb-pattern-drift { to { background-position: 168px 84px; } }

.eb-chapter-motes { position: absolute; inset: 0; z-index: 2; pointer-events: none; }
.eb-chapter-motes span {
    position: absolute;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: rgba(230, 172, 84, 0.55);
    filter: blur(1px);
    opacity: 0;
    animation: eb-float 13s ease-in-out infinite;
    transition: opacity 1.4s ease;
}
.eb-chapter.is-visible .eb-chapter-motes span { opacity: 1; }
.eb-chapter--soft .eb-chapter-motes span { background: rgba(198, 161, 91, 0.4); filter: blur(0.5px); }
.eb-chapter-motes span:nth-child(1) { left: 8%; top: 75%; animation-delay: 0s; }
.eb-chapter-motes span:nth-child(2) { left: 22%; top: 30%; animation-delay: 1.5s; }
.eb-chapter-motes span:nth-child(3) { left: 45%; top: 85%; animation-delay: 3s; }
.eb-chapter-motes span:nth-child(4) { left: 68%; top: 20%; animation-delay: 4.5s; }
.eb-chapter-motes span:nth-child(5) { left: 82%; top: 65%; animation-delay: 2s; }
.eb-chapter-motes span:nth-child(6) { left: 92%; top: 40%; animation-delay: 5.5s; }
.eb-chapter-motes span:nth-child(7) { left: 35%; top: 12%; animation-delay: 6.5s; }
.eb-chapter-motes span:nth-child(8) { left: 58%; top: 92%; animation-delay: 3.8s; }
@keyframes eb-float {
    0%, 100% { transform: translateY(0) translateX(0); }
    50% { transform: translateY(-70px) translateX(12px); }
}

/* --- World: Nikah & Barat — the climax, grand and architectural --- */
.eb-chapter--grand {
    --chapter-line: rgba(244, 236, 217, 0.24);
    background: radial-gradient(ellipse at 50% 10%, #3a1116 0%, #0b0d12 62%);
    background-size: 140% 140%;
    color: #f4ecd9;
    animation: eb-grand-shift 22s ease-in-out infinite alternate;
    animation-play-state: paused;
}
.eb-chapter--grand.is-visible { animation-play-state: running; }
@keyframes eb-grand-shift {
    0% { background-position: 50% 0%; }
    100% { background-position: 44% 8%; }
}
.eb-chapter--grand .eb-chapter-name {
    font-size: clamp(2.6rem, 10vw, 6.2rem);
    text-shadow: 0 2px 40px rgba(198, 161, 91, 0.25);
}
.eb-chapter-arch {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: flex-end;
    justify-content: center;
    z-index: 1;
    color: var(--eb-gold);
    pointer-events: none;
    will-change: transform;
}
.eb-chapter-arch--back { opacity: 0.6; }
.eb-chapter-arch svg {
    width: min(72vw, 460px);
    height: 92%;
    opacity: 0;
    transform: scale(0.82);
    transition: opacity 1.7s var(--eb-ease), transform 1.7s var(--eb-ease);
}
.eb-chapter-arch--back svg { width: min(88vw, 560px); transition-delay: 0.1s; }
.eb-chapter--grand.is-visible .eb-chapter-arch svg { opacity: 0.22; transform: scale(1); }
.eb-chapter--grand.is-visible .eb-chapter-arch--back svg { opacity: 0.14; }

/* A slow diagonal light sweep across the whole chapter, looping gently —
   "slow moving light" without ever feeling like a loading animation. */
.eb-chapter-lightsweep {
    position: absolute;
    inset: -20% -30%;
    z-index: 1;
    background: linear-gradient(100deg, transparent 42%, rgba(230, 180, 90, 0.08) 50%, transparent 58%);
    opacity: 0;
    transition: opacity 1.5s ease;
    animation: eb-lightsweep-drift 16s linear infinite;
    pointer-events: none;
}
.eb-chapter--grand.is-visible .eb-chapter-lightsweep { opacity: 1; }
@keyframes eb-lightsweep-drift {
    0% { transform: translateX(-30%); }
    100% { transform: translateX(30%); }
}

/* --- World: Walima — soft, pearl-like, the final chapter --- */
.eb-chapter--soft {
    --chapter-line: rgba(41, 35, 26, 0.16);
    background: linear-gradient(180deg, #f7f0e4, #ece1cb);
    color: var(--eb-charcoal-text);
}
.eb-chapter--soft .eb-chapter-roman,
.eb-chapter--soft .eb-detail-label,
.eb-chapter--soft .eb-chapter-direction { color: var(--eb-charcoal-text); }
.eb-chapter--soft .eb-chapter-message { opacity: 0.72; }
.eb-chapter--soft::after {
    content: '';
    position: absolute;
    inset: 0;
    top: 0;
    height: 45%;
    z-index: 2;
    background: linear-gradient(to bottom, var(--eb-midnight), transparent);
    opacity: 1;
    transition: opacity 2s ease;
    pointer-events: none;
}
.eb-chapter--soft.is-visible::after { opacity: 0; }

/* Pearl-like mesh gradient: several soft overlapping radial washes that
   drift almost imperceptibly, standing in for a flat cream background. */
.eb-chapter-mesh {
    position: absolute;
    inset: 0;
    z-index: 0;
    background-image:
        radial-gradient(circle at 15% 20%, rgba(255,255,255,0.75), transparent 45%),
        radial-gradient(circle at 85% 15%, rgba(230,210,180,0.5), transparent 50%),
        radial-gradient(circle at 30% 85%, rgba(198,161,91,0.18), transparent 55%),
        radial-gradient(circle at 80% 80%, rgba(255,255,255,0.6), transparent 50%);
    background-size: 160% 160%;
    animation: eb-mesh-drift 28s ease-in-out infinite alternate;
    pointer-events: none;
}
@keyframes eb-mesh-drift {
    0% { background-position: 0% 0%, 100% 0%, 0% 100%, 100% 100%; }
    100% { background-position: 6% 4%, 94% 6%, 4% 94%, 94% 92%; }
}
.eb-chapter-glow {
    position: absolute;
    left: 50%;
    top: 32%;
    width: 70vw;
    height: 70vw;
    max-width: 560px;
    max-height: 560px;
    background: radial-gradient(circle, rgba(198, 161, 91, 0.18), transparent 72%);
    transform: translate(-50%, -50%) scale(0.8);
    opacity: 0;
    z-index: 1;
    pointer-events: none;
    transition: opacity 1.8s ease, transform 1.8s var(--eb-ease);
}
.eb-chapter--soft.is-visible .eb-chapter-glow { opacity: 1; transform: translate(-50%, -50%) scale(1); }

/* ============ 10. Scene 09 — A Glimpse of Our Story (photo carousel) ============ */
.eb-carousel-scene {
    background: linear-gradient(180deg, #07080b, #0d0f14 45%, #07080b);
}
.eb-carousel-scene::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 0;
    background: radial-gradient(ellipse at 50% 0%, rgba(198,161,91,0.08), transparent 55%);
    pointer-events: none;
}
.eb-carousel-intro { margin-bottom: 8px; }

/* No prev/next buttons live here any more (auto-play + dots + swipe only
   — see carousel.js), so this is just a centered, container-relative
   wrapper around the viewport now; ".eb-carousel-nav" has been removed
   along with the markup it styled. */
.eb-carousel {
    position: relative;
    z-index: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    width: min(100% - (var(--eb-gutter) * 2), var(--eb-container-wide));
    margin: 26px auto 0;
}

.eb-carousel-viewport {
    position: relative;
    overflow: hidden;
    flex: 1 1 auto;
    min-width: 0;
    max-width: 100%;
    touch-action: pan-y;
}
.eb-carousel-track {
    display: flex;
    align-items: center;
    gap: clamp(14px, 3vw, 28px);
    transition: transform 0.65s var(--eb-ease);
    will-change: transform;
}
.eb-carousel-track.is-dragging { transition: none; }

.eb-carousel-slide {
    position: relative;
    flex: 0 0 auto;
    /* Percentage, not vw: ".eb-carousel-track" is a plain block (its width
       simply fills ".eb-carousel-viewport", which itself already resolves
       against the container-relative ".eb-carousel" formula above), so a
       slide's "%" reliably means "% of the actual carousel", not "% of
       the raw screen" — the same distinction that mattered for the
       scratch card, applied here so neighbour peeks stay proportional to
       the carousel itself at every width instead of drifting with it. */
    width: min(62%, 400px);
    aspect-ratio: 4 / 5;
    border-radius: 6px;
    overflow: hidden;
    box-shadow: 0 30px 60px -25px rgba(0, 0, 0, 0.6);
    transform: scale(0.86);
    opacity: 0.4;
    filter: blur(2px);
    transition: transform 0.6s var(--eb-ease), opacity 0.6s ease, filter 0.6s ease;
}
.eb-carousel-slide.is-active { transform: scale(1); opacity: 1; filter: blur(0); }

.eb-carousel-media {
    position: absolute;
    inset: -14% -14%;
    background-image: var(--frame-photo, none), var(--frame-gradient);
    background-size: cover, cover;
    background-position: center, center;
}
.eb-carousel-slide::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 1;
    box-shadow: inset 0 0 60px rgba(0, 0, 0, 0.35);
    pointer-events: none;
}
.eb-carousel-slide:not(.eb-frame--placeholder)::after {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 1;
    background: linear-gradient(155deg, rgba(44, 24, 10, 0.24), rgba(11, 13, 18, 0.14) 60%);
    mix-blend-mode: multiply;
    pointer-events: none;
}
.eb-carousel-slide.eb-frame--placeholder::after {
    content: '\2726';
    position: absolute;
    inset: 0;
    z-index: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: var(--eb-font-display);
    font-size: 1.6rem;
    color: rgba(255, 255, 255, 0.4);
    pointer-events: none;
}

/* Tone fallback gradients — inherited from the slide down to its
   ".eb-carousel-media" child via a plain custom property, so a broken/
   removed photo URL never leaves a slide visually blank. */
.eb-tone-warm { --frame-gradient: linear-gradient(140deg, #5c3a14, #c9812e 55%, #2f1c0a); }
.eb-tone-grand { --frame-gradient: linear-gradient(140deg, #2c0f12, #6b2028 55%, #0b0d12); }
.eb-tone-soft { --frame-gradient: linear-gradient(140deg, #f7f0e4, #d8c8a8 55%, #b79f78); }
.eb-tone-ink { --frame-gradient: linear-gradient(140deg, #05060a, #23262e 55%, #000000); }

.eb-carousel-caption {
    position: absolute;
    left: 0; right: 0; bottom: 0;
    z-index: 2;
    padding: 22px 18px 16px;
    font-family: var(--eb-font-display);
    font-style: italic;
    font-size: 1.1rem;
    color: var(--eb-ink);
    background: linear-gradient(to top, rgba(7,8,11,0.78), transparent);
    opacity: 0;
    transform: translateY(8px);
    transition: opacity 0.5s ease, transform 0.5s ease;
}
.eb-carousel-slide.is-active .eb-carousel-caption { opacity: 1; transform: translateY(0); }

.eb-carousel-dots {
    position: relative;
    z-index: 1;
    display: flex;
    justify-content: center;
    gap: 10px;
    margin-top: 28px;
}
.eb-carousel-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    border: 1px solid var(--eb-gold-soft);
    background: transparent;
    padding: 0;
    cursor: pointer;
    transition: background 0.3s ease, border-color 0.3s ease, transform 0.3s ease;
    -webkit-tap-highlight-color: transparent;
}
.eb-carousel-dot.is-active { background: var(--eb-gold); border-color: var(--eb-gold); transform: scale(1.2); }

/* ============ 11. Scene 10 — Guest Information (static, no response action) ============ */
.eb-guestinfo-scene {
    background: radial-gradient(ellipse at 50% 20%, var(--eb-charcoal) 0%, var(--eb-midnight) 68%);
}
.eb-guestinfo-atmosphere {
    position: absolute;
    inset: 0;
    z-index: 0;
    background-image:
        radial-gradient(circle at 15% 85%, rgba(198,161,91,0.1), transparent 45%),
        radial-gradient(circle at 85% 15%, rgba(198,161,91,0.08), transparent 45%);
    pointer-events: none;
}
.eb-guestinfo-message {
    position: relative;
    z-index: 1;
    font-family: var(--eb-font-serif);
    font-style: italic;
    font-size: 1.15rem;
    color: var(--eb-ink-soft);
    max-width: 420px;
    margin: 0 auto 36px;
    line-height: 1.7;
}
.eb-guestinfo-grid {
    position: relative;
    z-index: 1;
    width: min(100%, 380px);
    margin: 0 auto;
    text-align: left;
    border-top: 1px solid var(--eb-gold-soft);
}
.eb-guestinfo-row {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 18px;
    padding: 16px 0;
    border-bottom: 1px solid var(--eb-gold-soft);
}

/* ============ 12. Final Scene — The Closing (static, no interaction) ============ */
.eb-closing-scene {
    background: radial-gradient(ellipse at 50% 50%, var(--eb-charcoal) 0%, var(--eb-midnight) 82%);
}
.eb-closing-atmosphere {
    position: absolute;
    inset: 0;
    z-index: 0;
    background-image:
        radial-gradient(circle at 20% 80%, rgba(198,161,91,0.1), transparent 45%),
        radial-gradient(circle at 80% 15%, rgba(198,161,91,0.08), transparent 45%);
    pointer-events: none;
}
.eb-closing-scene::before {
    content: '';
    position: absolute;
    left: 50%;
    top: 50%;
    width: 60vw;
    height: 60vw;
    max-width: 480px;
    max-height: 480px;
    background: radial-gradient(circle, rgba(198,161,91,0.16), transparent 70%);
    transform: translate(-50%, -50%);
    animation: eb-closing-drift 18s ease-in-out infinite alternate;
    pointer-events: none;
}
@keyframes eb-closing-drift {
    0% { transform: translate(-50%, -50%) scale(0.9); }
    100% { transform: translate(-50%, -50%) scale(1.15); }
}

.eb-closing-motes { position: absolute; inset: 0; z-index: 0; pointer-events: none; }
.eb-closing-motes span {
    position: absolute;
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: rgba(230, 172, 84, 0.5);
    filter: blur(1px);
    opacity: 0;
    animation: eb-float 15s ease-in-out infinite;
    transition: opacity 1.6s ease;
}
.eb-closing-scene.is-visible .eb-closing-motes span { opacity: 1; }
.eb-closing-motes span:nth-child(1) { left: 12%; top: 20%; animation-delay: 0s; }
.eb-closing-motes span:nth-child(2) { left: 85%; top: 30%; animation-delay: 2s; }
.eb-closing-motes span:nth-child(3) { left: 22%; top: 78%; animation-delay: 4s; }
.eb-closing-motes span:nth-child(4) { left: 70%; top: 82%; animation-delay: 1s; }
.eb-closing-motes span:nth-child(5) { left: 45%; top: 15%; animation-delay: 5.5s; }
.eb-closing-motes span:nth-child(6) { left: 92%; top: 65%; animation-delay: 3s; }

.eb-closing-motif {
    position: relative;
    display: block;
    width: 44px;
    height: 44px;
    margin: 0 auto 26px;
    color: var(--eb-gold);
}
.eb-closing-motif .eb-token-ring::before,
.eb-closing-motif .eb-token-ring::after { border-color: var(--eb-gold-soft); }

.eb-closing-names {
    position: relative;
    z-index: 1;
    font-family: var(--eb-font-display);
    font-size: clamp(2.2rem, 8vw, 4rem);
    line-height: 1.1;
    margin: 0 0 8px;
}
.eb-closing-scene.is-visible .eb-closing-names .eb-mask-inner { transform: translateY(0); }
.eb-closing-names .eb-mask:first-of-type .eb-mask-inner { transition-delay: 0.1s; }
.eb-closing-names .eb-mask:last-of-type .eb-mask-inner { transition-delay: 0.35s; }
.eb-closing-amp {
    display: inline-block;
    font-style: italic;
    color: var(--eb-gold);
    margin: 0 4px;
    opacity: 0;
    transform: scale(0.5);
    transition: opacity var(--eb-dur-med) var(--eb-ease), transform var(--eb-dur-med) var(--eb-ease);
    transition-delay: calc(var(--stagger, 0) * 0.16s);
}
.is-visible .eb-closing-amp { opacity: 1; transform: scale(1); }

.eb-closing-date {
    position: relative;
    z-index: 1;
    font-family: var(--eb-font-ui);
    font-size: 0.85rem;
    letter-spacing: 0.24em;
    text-transform: uppercase;
    color: var(--eb-gold);
    margin: 26px 0 22px;
}
.eb-closing-message {
    position: relative;
    z-index: 1;
    font-family: var(--eb-font-serif);
    font-style: italic;
    font-size: 1.25rem;
    line-height: 1.7;
    color: var(--eb-ink-soft);
    max-width: 440px;
    margin: 0 auto 40px;
}

/* The one and only place "Experience DawatNama" appears — a small
   branded card in the vein of the understated promotional tag other
   premium invitation platforms tuck at the very bottom of the last
   slide: a monogram mark, a title, a subline, held in a quiet
   pill/border so it reads as one deliberate little object rather than a
   loose line of text or a loud call-to-action. */
.eb-closing-brand {
    position: relative;
    z-index: 1;
    display: inline-flex;
    align-items: center;
    gap: 12px;
    padding: 10px 22px 10px 10px;
    border: 1px solid var(--eb-gold-soft);
    border-radius: 999px;
    background: rgba(198, 161, 91, 0.06);
    text-decoration: none;
    opacity: 0.85;
    transition: opacity 0.3s ease, border-color 0.3s ease, background 0.3s ease;
}
.eb-closing-brand:hover, .eb-closing-brand:focus-visible {
    opacity: 1;
    border-color: var(--eb-gold);
    background: rgba(198, 161, 91, 0.1);
}
.eb-closing-brand-mark {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    flex-shrink: 0;
    border-radius: 50%;
    border: 1px solid var(--eb-gold-soft);
    font-family: var(--eb-font-display);
    font-style: italic;
    font-size: 0.9rem;
    color: var(--eb-gold);
}
.eb-closing-brand-text {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
    text-align: left;
}
.eb-closing-brand-title {
    font-family: var(--eb-font-ui);
    font-size: 0.66rem;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--eb-gold);
}
.eb-closing-brand-sub {
    font-family: var(--eb-font-serif);
    font-style: italic;
    font-size: 0.76rem;
    color: var(--eb-ink-soft);
}

/* =========================================================================
   7. RSVP UI
   ========================================================================= */
.rsvp-btn, .rsvp-send-btn {
  font-family: var(--eb-font-sans);
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.15em;
  padding: 1rem 2rem;
  background: transparent;
  color: var(--eb-color-text-main);
  border: 1px solid var(--eb-color-text-main);
  cursor: pointer;
  transition: all 0.3s ease;
  border-radius: 4px;
}
.rsvp-btn:hover, .rsvp-btn.active, .rsvp-send-btn:hover {
  background: var(--eb-color-text-main);
  color: var(--eb-color-surface);
}
.rsvp-counter-btn {
  background: transparent;
  border: 1px solid var(--eb-color-text-main);
  border-radius: 50%;
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  font-size: 1.2rem;
  color: var(--eb-color-text-main);
  transition: all 0.3s ease;
}
.rsvp-counter-btn:hover {
  background: var(--eb-color-text-main);
  color: var(--eb-color-surface);
}
.rsvp-send-btn {
  background: var(--eb-color-accent);
  border-color: var(--eb-color-accent);
  color: var(--eb-color-surface);
}
.rsvp-send-btn:hover {
  background: transparent;
  color: var(--eb-color-accent);
}

/* =========================================================================
   8. Animation & Reduced Motion
   ========================================================================= */
/* ============ 13. Fixed UI ============ */
.eb-music-toggle {
    position: fixed;
    bottom: calc(20px + env(safe-area-inset-bottom));
    right: calc(20px + env(safe-area-inset-right));
    width: 46px;
    height: 46px;
    border-radius: 50%;
    border: 1px solid var(--eb-gold-soft);
    background: rgba(11, 13, 18, 0.55);
    backdrop-filter: blur(6px);
    color: var(--eb-ink);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    z-index: 50;
    transition: background 0.3s ease, border-color 0.3s ease, color 0.3s ease;
    -webkit-tap-highlight-color: transparent;
}
.eb-music-toggle[aria-pressed="true"] { background: var(--eb-gold); color: var(--eb-midnight); border-color: var(--eb-gold); }

/* Two icons occupy the same spot; only one shows at a time, swapped by
   the button's own "aria-pressed" state — no separate JS-driven class
   needed for this part. */
.eb-music-icon { position: absolute; transition: opacity 0.3s ease, transform 0.3s ease; }
.eb-music-icon--off { opacity: 1; transform: scale(1); }
.eb-music-icon--on { opacity: 0; transform: scale(0.6); }
.eb-music-toggle[aria-pressed="true"] .eb-music-icon--off { opacity: 0; transform: scale(0.6); }
.eb-music-toggle[aria-pressed="true"] .eb-music-icon--on { opacity: 1; transform: scale(1); animation: eb-note-pulse 2.4s ease-in-out infinite; }
@keyframes eb-note-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.6; } }

.eb-noise {
    position: fixed;
    inset: -2px;
    z-index: 40;
    pointer-events: none;
    opacity: 0.05;
    mix-blend-mode: overlay;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='140' height='140'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
    animation: eb-grain-flicker 0.5s steps(2) infinite;
}
@keyframes eb-grain-flicker {
    0% { transform: translate(0, 0); }
    100% { transform: translate(-1px, 1px); }
}

/* ============ 14. Motion & responsiveness ============ */
@media (max-width: 760px) {
    .eb-scene { padding-block: clamp(48px, 8vh, 90px); }
    .eb-chapter-arch svg { width: min(80vw, 340px); }
    .eb-chapter-arch--back svg { width: min(92vw, 380px); }
    .eb-reveal { transform: translateY(30px); }
    .eb-stagger-item { transform: translateY(20px); }

    /* No mobile-specific ".eb-scratch" override needed any more: the base
       rule's width: min(100%, 360px) already yields the parent's actual
       (gutter-reduced) width the moment that's narrower than 360px, which
       it always is below ~408px viewports. */

    .eb-carousel-slide { width: min(84%, 320px); }

    .eb-guestinfo-grid { width: 100%; }
    .eb-closing-names { font-size: clamp(2rem, 11vw, 3rem); }

    /* A right-aligned value reads fine for a short one-line answer ("7:00
       PM"), but a venue address or a dress-code line genuinely wraps to
       2-3 lines at this width — right-aligned wrapped text is the part
       that's actually hard to read (ragged, unaligned left edges), not
       anything overflowing. Stack label-above-value and left-align
       instead, for every row, so it reads the same way regardless of how
       long any one value happens to be. */
    .eb-chapter-detail,
    .eb-guestinfo-row {
        flex-direction: column;
        align-items: flex-start;
        gap: 4px;
    }
    .eb-chapter-detail .eb-detail-value,
    .eb-guestinfo-row .eb-detail-value {
        text-align: left;
    }

    /* "Days / Hours / Minutes / Seconds" is functional information, not
       just decoration — 0.62rem (~10px) reads too small to comfortably
       label numbers people are meant to actually check on a phone. */
    .eb-countdown-label { font-size: 0.7rem; }

    /* The visible dot stays small and elegant; the tappable area around
       it grows well past 8x8px without changing how it looks. */
    .eb-carousel-dot { position: relative; }
    .eb-carousel-dot::after {
        content: '';
        position: absolute;
        inset: -10px;
    }

    /* ---- Wedding Journey ----
       The artwork becomes a quiet flourish above the timeline instead of
       a separate block competing with it for space: same artwork, scaled
       down by width only (aspect-ratio still governs height, so nothing
       letterboxes or distorts), faded back, and pulled close to the list
       so the two read as one composition rather than two stacked blocks.
       The timeline itself carries the section from here — each chapter
       gets more room to breathe and its own date/time + venue line, so
       it reads as a designed sequence, not three bare links. */
    .eb-journey-art {
        width: min(58%, 220px);
        margin: 0 auto 2px;
        opacity: 0.6;
    }
    .eb-journey-list-wrap { margin-top: 10px; }
    .eb-journey-item { margin-bottom: 42px; }
    .eb-journey-time { display: inline; }
    .eb-journey-venue { display: block; }

    /* Countdown — more air between the numbers and their labels, without
       growing the type itself. */
    .eb-countdown-label { margin-top: 15px; }
}

@media (min-width: 1440px) {
    :root { --eb-container-text: 700px; }
    .eb-carousel-slide { width: min(32%, 440px); }
}

@media (prefers-reduced-motion: reduce) {
    html { scroll-snap-type: none; }
    *, *::before, *::after {
        animation-duration: 0.001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.001ms !important;
        scroll-behavior: auto !important;
    }
}
