    /* ChenYuluoyan thin (OFL 1.1) — subset to the glyphs used (names + cover phrases) */
    @font-face {
      font-family: "ChenYuluoyan";
      src: url("/chenyuluoyan-thin.woff2?v=3") format("woff2");
      font-weight: 400;
      font-display: swap;
    }
    @font-face {
      font-family: "Noto Serif TC";
      src: url("/noto-serif-tc.woff2") format("woff2");
      font-weight: 400;
      font-display: swap;
    }
    @font-face {
      font-family: "Noto Serif TC Bold";
      src: url("/noto-serif-tc-bold.woff2") format("woff2");
      font-weight: 400;
      font-display: swap;
    }
    @font-face {
      font-family: "Great Vibes";
      src: url("/great-vibes-amp.woff2?v=2") format("woff2");
      font-weight: 400;
      font-display: swap;
    }
    /* Fraunces (OFL) — self-hosted, subset to Latin */
    @font-face {
      font-family: "Fraunces";
      src: url("/fraunces-latin.woff2") format("woff2");
      font-weight: 400 700; font-style: normal; font-display: swap;
    }
    @font-face {
      font-family: "Fraunces";
      src: url("/fraunces-latin-italic.woff2") format("woff2");
      font-weight: 400 700; font-style: italic; font-display: swap;
    }

    :root {
      --bg: #faf6ee;        /* warm cream base */
      --ink: #5f4836;       /* mocha body text */
      --muted: #a08b74;     /* taupe secondary text */
      --line: #ece0cd;      /* hairline on cream */
      --card: #fffdf8;      /* card surface */
      --ivory: #f7eddd;     /* text over dark/photo */
      --gold: #ddc1a0;      /* cream hazelnut */
      --gold-deep: #bd9b76; /* hazelnut latte */
      --coral: #df8c72;     /* heart */
      --champagne: #caa14a; /* champagne gold — music controls accent */
      --mocha-900: #1c130c; /* darkest base (gate cover only) */
      --milk: #f0e6d4;      /* milk-tea — the alternating light section tone */
      --backdrop: #e7dcc7;  /* page behind the phone card (only shows on tablet+) */
    }

    * { box-sizing: border-box; }

    html { -webkit-text-size-adjust: 100%; }
    body {
      margin: 0;
      background: var(--backdrop);
      color: var(--ink);
      font-family: "Noto Serif TC", -apple-system, system-ui, "Songti TC", serif;
      overflow-x: hidden;
    }
    body.gate-open { overflow: hidden; height: 100dvh; }
    img { display: block; max-width: 100%; }

    /* ═══════════ Entry / loading gate (photo-led) ═══════════ */
    .gate {
      position: fixed;
      inset: 0;
      z-index: 60;
      max-width: 480px;
      min-width: 365px;
      container-type: inline-size;
      margin-inline: auto;
      overflow: hidden;
      display: flex;
      flex-direction: column;
      align-items: center;
      padding-top: env(safe-area-inset-top);
      color: var(--ivory);
      background: var(--mocha-900);
      box-shadow: 0 0 70px rgba(0,0,0,.35);
      font-family: "ChenYuluoyan", "Songti TC", serif;
      transition:
        opacity .95s cubic-bezier(.4, 0, .2, 1),
        transform .95s cubic-bezier(.4, 0, .2, 1),
        filter .95s cubic-bezier(.4, 0, .2, 1),
        visibility 0s linear .95s;
    }
    .gate::before {
      content: ""; position: absolute; inset: 0;
      background: url("/cover.webp") center 30% / cover no-repeat;
      transform: scale(1.05);
      animation: drift 22s ease-in-out infinite alternate;
    }
    .gate::after {
      content: ""; position: absolute; inset: 0;
      background:
        radial-gradient(125% 70% at 72% 12%, rgba(255,226,178,.22), rgba(255,226,178,0) 55%),
        linear-gradient(to bottom, rgba(28,19,12,0) 30%, rgba(28,19,12,.14) 48%, rgba(26,18,11,.52) 72%, rgba(22,15,9,.92) 100%);
    }
    .gate__grain {
      position: absolute; inset: 0; pointer-events: none; z-index: 1;
      opacity: .08; mix-blend-mode: overlay;
      background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(/%23n)'/%3E%3C/svg%3E");
      background-size: 200px 200px;
    }
    .gate__frame {
      position: absolute; inset: 14px; pointer-events: none; z-index: 1;
      border: 1px solid rgba(221,193,160,.34); opacity: 0;
      animation: fadeFrame 1.6s ease .25s forwards;
    }
    .gate.is-done { opacity: 0; visibility: hidden; pointer-events: none; transform: scale(1.06); filter: blur(7px); }

    .gate__kicker-top {
      position: relative; z-index: 1; margin: 46px 0 0;
      font-family: "Fraunces", serif; font-style: italic; font-weight: 500;
      font-size: 14px; letter-spacing: .26em; color: var(--gold-deep);
      animation: rise 1s ease .15s both;
    }
    .gate__ask {
      position: relative; z-index: 1; width: 100%; margin-top: auto;
      display: flex; flex-direction: column; align-items: center; text-align: center;
      padding: 0 30px calc(46px + env(safe-area-inset-bottom));
    }
    .gate__ask > * { animation: rise 1s cubic-bezier(.22, 1, .36, 1) both; }
    .gate__kicker { animation-delay: .35s; }
    .gate__names  { animation-delay: .50s; }
    .gate__date   { animation-delay: .65s; }
    .gate__invite { animation-delay: .80s; }
    .gate__actions{ animation-delay: .95s; }

    .gate__kicker {
      margin: 0 0 12px; font-family: "Fraunces", serif; font-size: 13.5px; font-weight: 600;
      letter-spacing: .38em; text-indent: .38em; color: #efdcbf; text-transform: uppercase;
      text-shadow: 0 1px 8px rgba(26,16,9,.55), 0 0 2px rgba(26,16,9,.45);
    }
    .gate__names {
      align-self: stretch; width: 100%; margin: 0 0 16px; font-weight: 400;
      font-size: clamp(32px, 10.5cqw, 40px); -webkit-text-stroke: 0.6px currentColor;
      letter-spacing: .02em; text-indent: .02em; line-height: 1.15; white-space: nowrap;
      text-shadow: 0 2px 18px rgba(0,0,0,.45);
    }
    .gate__amp {
      display: inline-block; -webkit-text-stroke: 0; color: var(--coral);
      margin: 0 .44em; font-size: .6em; vertical-align: .12em;
      animation: heartbeat 1.9s ease-in-out infinite;
    }
    .heart { width: 1em; height: 1em; fill: currentColor; vertical-align: -.1em; }
    .note { width: 1em; height: 1em; vertical-align: -.18em; }
    .gate__date {
      display: flex; align-items: center; justify-content: center; gap: 12px; margin: 0 0 14px;
      font-family: "Fraunces", serif; font-size: 18px; font-weight: 500;
      letter-spacing: .3em; text-indent: .3em; color: rgba(247,237,221,.92);
    }
    .gate__rule { display: block; width: 34px; height: 1px; background: linear-gradient(to var(--dir, right), rgba(221,193,160,0), rgba(221,193,160,.8)); }
    .gate__rule:last-child { --dir: left; }
    .gate__invite { margin: 0 0 24px; font-size: 20px; letter-spacing: .14em; text-indent: .14em; color: rgba(247,237,221,.78); }
    .gate__actions { display: flex; flex-direction: column; gap: 10px; width: min(264px, 78cqw); }
    .gate__btn {
      appearance: none; cursor: pointer; width: 100%; padding: 8px; border-radius: 18px;
      font-family: "ChenYuluoyan", "Songti TC", serif; font-size: 24px; font-weight: 400;
      -webkit-text-stroke: 0.4px currentColor; letter-spacing: .16em; text-indent: .16em;
      -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
      transition: transform .28s cubic-bezier(.34,1.56,.64,1), box-shadow .3s ease, background .3s ease, border-color .3s ease;
    }
    .gate__btn:active { transform: scale(.96); }
    .gate__btn--primary {
      border: 1px solid rgba(196,166,132,.85); background: rgba(251,246,236,.82); color: #6e4f37;
      box-shadow: 0 8px 22px rgba(20,12,6,.26), inset 0 1px 0 rgba(255,255,255,.65);
    }
    .gate__btn--primary:hover { transform: translateY(-3px); background: rgba(253,249,242,.92); }
    .gate__note { display: inline-block; margin-right: .3em; font-size: .9em; vertical-align: .02em; color: var(--champagne); transform-origin: 50% 75%; animation: sway 3.6s ease-in-out infinite; }
    .gate__btn--ghost { border: 1px solid rgba(221,193,160,.5); background: rgba(255,255,255,.08); color: var(--ivory); }
    .gate__btn--ghost:hover { transform: translateY(-3px); border-color: rgba(221,193,160,.9); background: rgba(255,255,255,.14); }
    .gate__flower { width: .92em; height: .92em; margin-right: .3em; vertical-align: -.14em; color: #8fae5a; transform-origin: 50% 80%; animation: sway 3.6s ease-in-out infinite; }

    .gate__entering { position: relative; z-index: 1; margin: auto; display: none; flex-direction: column; align-items: center; gap: 20px; }
    .gate.is-entering .gate__ask, .gate.is-entering .gate__kicker-top { display: none; }
    .gate.is-entering .gate__entering { display: flex; animation: rise 1s ease both; }
    .gate__sub { margin: 0; font-family: "ChenYuluoyan", "Songti TC", serif; font-size: 25px; letter-spacing: .18em; text-indent: .18em; color: rgba(247,237,221,.9); animation: breathe 2.6s ease-in-out infinite; }
    .gate__line { width: 130px; height: 1px; background: rgba(247,237,221,.2); overflow: hidden; }
    .gate__line-fill { display: block; width: 0; height: 100%; background: linear-gradient(to right, var(--gold-deep), var(--gold)); transition: width linear; }

    /* ═══════════ Long-scroll site ═══════════ */
    .site { width: 100%; max-width: 480px; min-width: 365px; margin: 0 auto; background: var(--bg); box-shadow: 0 0 70px rgba(60,40,24,.22); container-type: inline-size; }

    /* Floating music toggle (clamped to the card, follows scroll) */
    .music-btn {
      position: fixed; z-index: 50;
      top: calc(16px + env(safe-area-inset-top));
      right: calc(50vw - min(50vw, 240px) + 16px);
      width: 30px; height: 30px; padding: 0; border: 1px solid rgba(189,155,118,.5); border-radius: 50%; cursor: pointer;
      display: flex; align-items: center; justify-content: center;
      color: var(--gold-deep);
      background: rgba(251,246,236,.42);
      -webkit-tap-highlight-color: transparent;
      opacity: 0; visibility: hidden; pointer-events: none;
      transition: opacity .6s ease .2s, visibility 0s linear .8s;
    }
    body:not(.gate-open) .music-btn { opacity: 1; visibility: visible; pointer-events: auto; transition: opacity .6s ease .2s; }
    .music-btn__icon { width: 19px; height: 19px; opacity: .5; }
    .music-btn__slash { display: none; }
    .music-btn:not(.is-playing) .music-btn__slash { display: block; }
    .music-btn:active { transform: scale(.9); }
    .music-btn.is-playing { animation: mbBreathe 2.4s ease-in-out infinite; }

    /* Hamburger menu button (top-left, mirrors the music button) */
    .menu-btn {
      position: fixed; z-index: 60;
      top: calc(10px + env(safe-area-inset-top));
      left: calc(50vw - min(50vw, 240px) + 16px);
      width: 42px; height: 42px; padding: 0; border: 0; border-radius: 50%; cursor: pointer;
      display: flex; align-items: center; justify-content: center;
      background: none;
      -webkit-tap-highlight-color: transparent;
      opacity: 0; visibility: hidden; pointer-events: none;
      transition: opacity .6s ease .2s, visibility 0s linear .8s, background .3s ease, border-color .3s ease;
    }
    body:not(.gate-open) .menu-btn { opacity: 1; visibility: visible; pointer-events: auto; transition: opacity .6s ease .2s; }
    .menu-btn__lines { position: relative; width: 18px; height: 12px; }
    .menu-btn__lines span { position: absolute; left: 0; width: 100%; height: 1.6px; border-radius: 2px; background: var(--gold-deep); transition: transform .3s ease, opacity .2s ease, background .3s ease; }
    .menu-btn__lines span:nth-child(1) { top: 0; }
    .menu-btn__lines span:nth-child(2) { top: 50%; transform: translateY(-50%); }
    .menu-btn__lines span:nth-child(3) { bottom: 0; }
    .menu-btn:active { transform: scale(.9); }
    .menu-btn.is-open { z-index: 110; }
    .menu-btn.is-open .menu-btn__lines span { background: #5f4836; }
    .menu-btn.is-open .menu-btn__lines span:nth-child(1) { top: 50%; transform: translateY(-50%) rotate(45deg); }
    .menu-btn.is-open .menu-btn__lines span:nth-child(2) { opacity: 0; }
    .menu-btn.is-open .menu-btn__lines span:nth-child(3) { bottom: auto; top: 50%; transform: translateY(-50%) rotate(-45deg); }

    /* Full-screen translucent "目次" overlay */
    body.menu-open { overflow: hidden; }
    .nav-overlay {
      position: fixed; inset: 0; z-index: 100;
      display: flex; flex-direction: column; align-items: center; justify-content: flex-start;
      padding: calc(34px + env(safe-area-inset-top)) 24px calc(34px + env(safe-area-inset-bottom));
      background: linear-gradient(180deg, rgba(250,246,239,.92), rgba(246,239,228,.95));
      -webkit-backdrop-filter: blur(12px) saturate(1.05); backdrop-filter: blur(12px) saturate(1.05);
      opacity: 0; visibility: hidden; pointer-events: none;
      transition: opacity .5s ease, visibility 0s linear .5s;
    }
    .nav-overlay.is-open { opacity: 1; visibility: visible; pointer-events: auto; transition: opacity .5s ease; }
    .nav__top { font-family: "Fraunces", serif; font-size: 12px; letter-spacing: .4em; text-indent: .4em; text-transform: uppercase; color: var(--gold); opacity: .85; }
    .nav__list { flex: none; list-style: none; margin: 20vh 0 0; padding: 0; display: flex; flex-direction: column; align-items: center; gap: 22px; }
    .nav__link { display: inline-flex; flex-direction: column; align-items: center; gap: 4px; text-decoration: none; cursor: pointer; }
    .nav__en { font-family: "Fraunces", serif; font-size: 16px; letter-spacing: .32em; text-indent: .32em; text-transform: uppercase; color: #a9824f; transition: color .25s ease; }
    .nav__zh { font-family: "Noto Serif TC", -apple-system, system-ui, "Songti TC", serif; font-size: 13px; letter-spacing: .24em; text-indent: .24em; color: rgba(95,72,54,.62); transition: color .25s ease; }
    .nav__link:hover .nav__zh, .nav__link:focus-visible .nav__zh { color: #4a3526; }
    .nav__link:hover .nav__en, .nav__link:focus-visible .nav__en { color: #8a6334; }
    .nav__date { font-family: "Fraunces", serif; font-size: 13px; letter-spacing: .3em; text-indent: .3em; color: rgba(95,72,54,.55); margin-top: 34px; }
    .nav-overlay.is-open .nav__top,
    .nav-overlay.is-open .nav__list li,
    .nav-overlay.is-open .nav__date { animation: navIn .55s ease both; animation-delay: calc(.06s + var(--i, 0) * .05s); }
    @keyframes navIn { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
    @keyframes mbBreathe { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.12); } }

    /* Full-bleed hero (landing after the gate) */
    .hero {
      position: relative; height: 100svh; min-height: 560px; overflow: hidden;
      display: flex; flex-direction: column; align-items: center; justify-content: flex-end;
      text-align: center; color: var(--ivory);
      padding: 0 30px calc(74px + env(safe-area-inset-bottom));
    }
    .hero::before { content: ""; position: absolute; inset: 0; background: url("/cover.webp") center 30% / cover no-repeat; transform: scale(1.05); animation: drift 22s ease-in-out infinite alternate; }
    .hero::after { content: ""; position: absolute; inset: 0; background: linear-gradient(to bottom, rgba(28,19,12,0) 32%, rgba(26,18,11,.5) 70%, rgba(22,15,9,.9) 100%); }
    .hero > * { position: relative; z-index: 1; }
    .hero__kick { margin: 0 0 16px; font-family: "Fraunces", serif; font-weight: 600; text-transform: uppercase; letter-spacing: .4em; text-indent: .4em; font-size: 12px; color: #efdcbf; text-shadow: 0 1px 8px rgba(26,16,9,.5); }
    .hero__names { margin: 0; font-family: "ChenYuluoyan", "Songti TC", serif; font-weight: 400; -webkit-text-stroke: .6px currentColor; font-size: clamp(32px, 10.5cqw, 40px); letter-spacing: .04em; line-height: 1.15; white-space: nowrap; text-shadow: 0 2px 18px rgba(0,0,0,.45); }
    .hero__amp { display: inline-block; -webkit-text-stroke: 0; color: var(--coral); margin: 0 .44em; font-size: .6em; vertical-align: .12em; animation: heartbeat 1.9s ease-in-out infinite; }
    .hero__title { position: relative; width: 100%; margin: 0 0 18px; display: flex; justify-content: center; align-items: center; }
    .hero__title .hero__names { position: relative; z-index: 1; }
    .hero__thread { position: absolute; top: 60%; left: 50%; transform: translate(-50%, -50%); width: 142%; max-width: none; height: auto; z-index: 0; filter: drop-shadow(0 1px 2px rgba(0,0,0,.4)); }
    .hero__date { margin: 0; font-family: "Fraunces", serif; font-weight: 500; font-size: 18px; letter-spacing: .3em; text-indent: .3em; color: rgba(247,237,221,.92); }
    .hero__scroll { position: absolute; left: 0; right: 0; bottom: calc(22px + env(safe-area-inset-bottom)); z-index: 1; color: rgba(247,237,221,.8); font-family: "Fraunces", serif; font-size: 10.5px; letter-spacing: .24em; text-indent: .24em; text-transform: uppercase; animation: bob 2s ease-in-out infinite; }
    .hero__scroll i { display: block; font-style: normal; font-size: 15px; margin-top: 3px; }

    .sec { padding: 80px 32px; position: relative; }
    .sec.alt { background: var(--milk); }       /* milk-tea alternating section (no dark) */
    .sec.tight { padding: 0; }

    .kick {
      display: flex; align-items: center; justify-content: center; gap: 14px;
      font-family: "Fraunces", serif; font-weight: 600; text-transform: uppercase;
      letter-spacing: .34em; text-indent: .34em; font-size: 16px; color: var(--gold-deep);
      margin: 0 0 30px;
    }
    .kick::before, .kick::after { content: ""; width: 28px; height: 1px; }
    .kick::before { background: linear-gradient(to right, transparent, var(--gold)); }
    .kick::after  { background: linear-gradient(to left, transparent, var(--gold)); }
    .ttl { font-family: "Fraunces", "Noto Serif TC Bold", "Noto Serif TC", "Songti TC", serif; font-weight: 700; font-size: 30px; line-height: 1.25; text-align: center; margin: 0 0 24px; }

    /* Lite / elder version (?lite): hide narrative + photo sections, leave hero → couple → details → rsvp */
    body.lite .lite-hide { display: none; }
    /* Lite hides many sections, so re-establish the milk/cream alternation: tint the welcome (主文) block */
    body.lite #welcome { background: var(--milk); }
    /* Details: enlarged date line + venue name, and the reception/banquet time line (both versions) */
    #details .detail .v .v-lead { font-size: 30px; }
    #details .detail .v small.v-time { font-size: 22px; }
    /* Lite: enlarge all RSVP form labels by 2px */
    body.lite #rsvp .field label { font-size: 20px; }
    .reveal { opacity: 0; transform: translateY(28px); transition: opacity .9s ease, transform .9s cubic-bezier(.22,1,.36,1); }
    .reveal.in { opacity: 1; transform: none; }
    .d1 { transition-delay: .08s; } .d2 { transition-delay: .16s; } .d3 { transition-delay: .24s; }

    /* Quote / 序 */
    .quote { text-align: center; }
    .quote__photo { width: 200px; height: 200px; margin: 56px auto 30px; border-radius: 50%;
      background-image: url("/img/main-05918.webp"); background-repeat: no-repeat;
      background-size: 125%;          /* 放大倍率：數字越大主體越近 */
      background-position: 50% 50%;    /* 焦點：左右% 上下%（Y 越大顯示越下方）*/
      box-shadow: 0 14px 36px rgba(60,40,24,.18); }
    .poem { font-family: "Fraunces", serif; font-style: italic; font-weight: 400; font-size: 21px; line-height: 1.75; color: var(--ink); }
    .poem b { display: block; font-weight: 500; font-size: 25px; margin-bottom: .35em; }
    .poem-zh { margin: 22px 0 0; font-size: 14px; line-height: 2; letter-spacing: .08em; color: var(--muted); }

    /* Music box — rectangular player card (toggles bgm) */
    .musicbox { margin-top: 50px; }
    .player { display: flex; align-items: stretch; gap: 14px; max-width: 380px; margin: 0 auto; padding: 14px; background: var(--card); border: 1px solid rgba(189,155,118,.22); border-radius: 16px; box-shadow: 0 14px 30px rgba(60,40,24,.13); }
    .player__main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; justify-content: center; gap: 13px; text-align: left; }
    .player__info { display: flex; align-items: center; gap: 10px; }
    .player__title { flex: 0 1 auto; min-width: 0; font-size: 16px; letter-spacing: .04em; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
    /* Cute dancing equalizer — bounces only while the track is playing,
       settles to a calm low row when paused */
    .eq { flex: 1 1 auto; display: flex; align-items: flex-end; justify-content: flex-end; gap: 3px; height: 13px; margin: 0 2px; opacity: 0; transition: opacity .3s ease; }
    .player.is-playing .eq { opacity: 1; }
    .eq span { width: 3px; height: 100%; border-radius: 2px; background: var(--gold-deep);
               transform-origin: bottom; transform: scaleY(.22); opacity: .45;
               transition: opacity .3s ease, transform .3s ease; }
    .player.is-playing .eq span { opacity: 1; animation: eqBounce .8s ease-in-out infinite; }
    .player.is-playing .eq span:nth-child(5n+1) { animation-duration: .68s; animation-delay: -.20s; }
    .player.is-playing .eq span:nth-child(5n+2) { animation-duration: .94s; animation-delay: -.55s; }
    .player.is-playing .eq span:nth-child(5n+3) { animation-duration: .56s; animation-delay: -.10s; }
    .player.is-playing .eq span:nth-child(5n+4) { animation-duration: .82s; animation-delay: -.42s; }
    .player.is-playing .eq span:nth-child(5n+5) { animation-duration: .72s; animation-delay: -.30s; }
    @keyframes eqBounce { 0%, 100% { transform: scaleY(.22); } 50% { transform: scaleY(1); } }
    .player__controls { display: flex; align-items: center; gap: 10px; }
    .player__btn { flex: none; width: 36px; height: 36px; display: grid; place-items: center; padding: 0; border: 0; border-radius: 50%; cursor: pointer; background: var(--gold-deep); color: #fff; -webkit-tap-highlight-color: transparent; transition: transform .2s ease, background .2s ease; }
    .player__btn:hover { background: #b08d68; }
    .player__btn:active { transform: scale(.92); }
    .player__btn .ic { width: 17px; height: 17px; }
    .player__btn .ic-pause { display: none; }
    .player__btn.is-playing .ic-play { display: none; }
    .player__btn.is-playing .ic-pause { display: block; }
    .player__bar { flex: 1 1 auto; height: 3px; border-radius: 3px; background: rgba(189,155,118,.28); overflow: hidden; }
    .player__bar span { display: block; height: 100%; width: 0; background: var(--gold-deep); border-radius: 3px; transition: width .25s linear; }
    .player__art { flex: none; align-self: center; width: 76px; height: 76px; border-radius: 12px; background: url("/img/main-05572.webp") 56% 16% / cover; box-shadow: 0 5px 14px rgba(20,12,6,.18); }

    /* Welcome / opening message */
    .welcome { text-align: center; }
    .welcome__title { margin: 0; font-family: "ChenYuluoyan", "Songti TC", serif; font-weight: 400; -webkit-text-stroke: .5px currentColor; font-size: 40px; letter-spacing: .14em; text-indent: .14em; color: var(--ink); }
    .welcome__en { margin: -2px 0 0; font-family: "Great Vibes", cursive; font-size: 20px; line-height: 1; letter-spacing: .02em; color: var(--gold-deep); }
    .welcome__lines { margin: 36px 0 0; }
    .welcome__line { margin: 0; font-size: 16px; line-height: 1; letter-spacing: .12em; text-indent: .12em; color: var(--ink); }
    .welcome__line + .welcome__line { margin-top: 16px; }

    /* Couple */
    .parents { margin-top: 26px; }
    .par { text-align: center; }
    /* Couple blob portraits — tweak --zoom (放大倍率) + --pos (焦點 左右% 上下%) per person */
    .par__blob { position: relative; width: 300px; height: 307px; margin: 0 auto 22px; filter: drop-shadow(0 16px 30px rgba(60,40,24,.18)); transform: translateZ(0); }
    .par__blob::before { content: ""; position: absolute; inset: -2.5px; background: rgba(189,155,118,.5); -webkit-clip-path: var(--clip); clip-path: var(--clip); } /* gold ring */
    .par__blob::after { content: ""; position: absolute; inset: 0; background-image: var(--photo); background-repeat: no-repeat; background-size: var(--zoom); background-position: var(--pos); -webkit-clip-path: var(--clip); clip-path: var(--clip); } /* photo */
    .par__blob--bride { --clip: url(#blobBride); --photo: url("/img/bride-07142.webp"); --zoom: 185%; --pos: 64% 55%; }
    .par__blob--groom { --clip: url(#blobGroom); --photo: url("/img/groom-07152.webp"); --zoom: 160%; --pos: 54% 31%; }
    .par__role { margin: 0 0 10px; font-family: "Fraunces", serif; font-weight: 600; text-transform: uppercase; letter-spacing: .28em; text-indent: .28em; font-size: 13px; color: var(--gold-deep); }
    .par__name { font-family: "ChenYuluoyan", "Songti TC", serif; font-weight: 400; -webkit-text-stroke: .4px currentColor; font-size: 56px; letter-spacing: .08em; color: var(--ink); margin: 0; }
    .par__of { margin: 0 0 12px; font-family: "Fraunces", serif; font-style: italic; font-size: 14px; color: var(--muted); }
    .par__of--tier { margin-top: 12px; }   /* separator before the second family tier */
    .par__names { margin: 0; font-family: "Noto Serif TC Bold", "Noto Serif TC", "Songti TC", serif; font-size: 26px; letter-spacing: .06em; color: var(--ink); }
    .par__names .hon { font-family: "Noto Serif TC", "Songti TC", serif; font-size: .62em; letter-spacing: .08em; color: var(--gold-deep); margin-left: .45em; }
    .par__names .amp { display: inline-block; font-family: "Great Vibes", cursive; font-size: .75em; line-height: 1; color: var(--muted); margin: 0 .6em; vertical-align: middle; transform: translateY(0.04em); }
    .par__div { position: relative; display: block; width: 64px; height: 1px; margin: 45px auto; background: linear-gradient(90deg, transparent, rgba(189,155,118,.55) 22%, rgba(189,155,118,.55) 78%, transparent); }
    .par__div::before { content: ""; position: absolute; left: 50%; top: 50%; width: 5px; height: 5px; transform: translate(-50%,-50%) rotate(45deg); background: var(--coral); }

    /* Event swap (wedding, body[data-swap]): groom-side leads — flip every
       "<name> ♥ <name>" pair (gate cover, hero, footer) and the stacked couple
       blocks. Engagement (no attr) is untouched. */
    body[data-swap] .gate__names,
    body[data-swap] .hero__names,
    body[data-swap] .foot__names { display: flex; flex-direction: row-reverse; justify-content: center; align-items: center; }
    body[data-swap] .parents { display: flex; flex-direction: column-reverse; }

    /* Full-bleed feature photo */
    .feature { position: relative; line-height: 0; }
    .feature img { width: 100%; height: auto; aspect-ratio: 2 / 3; object-fit: cover; }
    .feature figcaption { position: absolute; left: 0; right: 0; bottom: 22px; text-align: center; line-height: 1.4; color: var(--ivory); font-family: "Fraunces", serif; font-style: italic; font-size: 15px; letter-spacing: .12em; text-shadow: 0 2px 10px rgba(0,0,0,.55); }

    /* Gallery (swipeable slideshow) */
    .slider { position: relative; }
    .gallery { display: flex; overflow-x: auto; scroll-snap-type: x mandatory; scroll-behavior: smooth; border-radius: 8px; -webkit-overflow-scrolling: touch; scrollbar-width: none; box-shadow: 0 16px 36px rgba(60,40,24,.16); }
    .gallery::-webkit-scrollbar { display: none; }
    .gallery img { flex: 0 0 100%; width: 100%; aspect-ratio: 3 / 4; object-fit: cover; object-position: 50% 60%; scroll-snap-align: center; }
    .slider__btn { position: absolute; top: 50%; transform: translateY(-50%); z-index: 2; width: 46px; height: 46px; display: grid; place-items: center; padding: 0; border: 0; background: none; cursor: pointer; color: #fff; opacity: .55; -webkit-tap-highlight-color: transparent; transition: transform .2s ease, opacity .25s ease; }
    .slider__btn:hover { opacity: .85; }
    .slider__btn:active { transform: translateY(-50%) scale(.9); }
    .slider__btn svg { width: 30px; height: 30px; }
    .slider__btn--prev { left: 0; }
    .slider__btn--next { right: 0; }

    /* Moments montage (clean white, equal-width stack) */
    .moments { background: #fff; }
    .moments__cap { margin: 0 0 30px; text-align: center; font-size: 15.5px; letter-spacing: .08em; line-height: 1.95; color: var(--ink); }

    /* Date + countdown */
    .date-big { font-family: "Fraunces", serif; font-weight: 500; font-size: 48px; letter-spacing: .04em; text-align: center; margin: 6px 0 4px; color: var(--ink); }
    .date-week { text-align: center; font-family: "Fraunces", serif; font-style: italic; letter-spacing: .24em; text-indent: .24em; color: var(--gold-deep); margin: 0; }
    .countdown { display: flex; justify-content: center; gap: 10px; margin-top: 34px; }
    .cd { text-align: center; min-width: 60px; padding: 14px 6px; border: 1px solid rgba(189,155,118,.35); border-radius: 14px; }
    .cd b { display: block; font-family: "Fraunces", serif; font-weight: 500; font-size: 28px; color: var(--ink); }
    .cd span { display: block; margin-top: 6px; font-family: "Fraunces", serif; text-transform: uppercase; letter-spacing: .16em; font-size: 9.5px; color: var(--gold-deep); }

    /* Story timeline */
    .tl { display: flex; gap: 16px; padding-bottom: 26px; position: relative; }
    .tl:not(:last-child)::before { content: ""; position: absolute; left: 5px; top: 22px; bottom: -4px; width: 1px; background: var(--line); }
    .tl__dot { flex: none; width: 11px; height: 11px; margin-top: 6px; border-radius: 50%; background: var(--gold); box-shadow: 0 0 0 4px rgba(221,193,160,.25); }
    .tl__yr { font-family: "Fraunces", serif; font-style: italic; color: var(--gold-deep); font-size: 15px; }
    .tl h4 { margin: 2px 0 6px; font-size: 16px; color: var(--ink); }
    .tl p { margin: 0; font-size: 14px; line-height: 1.9; color: var(--muted); }
    /* Moments burst flipbook (DSC05752–05769 played GIF-style) */
    .flip { position: relative; width: 100%; aspect-ratio: 3 / 2; border-radius: 8px; overflow: hidden; box-shadow: 0 16px 36px rgba(60,40,24,.16); background: var(--ivory); }
    .flip__f { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0; }
    .flip__f.is-on { opacity: 1; }
    .story__photo { width: 100%; height: auto; aspect-ratio: 2 / 3; object-fit: cover; border-radius: 6px; margin-top: 30px; box-shadow: 0 16px 36px rgba(60,40,24,.16); }

    /* Details */
    .detail { text-align: center; margin-bottom: 30px; }
    .detail .t { font-family: "Fraunces", serif; text-transform: uppercase; letter-spacing: .2em; text-indent: .2em; font-size: 11.5px; color: var(--gold-deep); }
    .detail .v { font-family: "Noto Serif TC Bold", "Noto Serif TC", -apple-system, system-ui, "Songti TC", serif; font-size: 22px; margin-top: 7px; line-height: 1.6; }
    /* keep 星期日 together; on a narrow screen the whole block drops to the next line */
    .detail .v .v-day { display: inline-block; white-space: nowrap; }
    .detail .v small { display: block; font-family: "Noto Serif TC", -apple-system, system-ui, "Songti TC", serif; font-size: 17px; color: var(--muted); margin-top: 3px; }
    .det-flower { width: 1.2em; height: 1.2em; align-self: center; }   /* 入席 flower + 開席 popper, same size */
    .detail .v .v-sub { font-size: .85em; }
    .detail .v .num { font-family: "Fraunces", serif; font-weight: 700; letter-spacing: .01em; }
    .detail .v small .num { font-weight: 500; }
    .detail .v .amp { font-family: "Great Vibes", cursive; font-size: 1.15em; margin: 0 .1em; vertical-align: -.02em; }
    .detail .v small.v-time { display: flex; align-items: baseline; justify-content: center; gap: .25em; font-size: 17px; margin-top: 8px; color: var(--ink); }
    .detail .v small.v-time .det-flower:nth-of-type(2) { margin-left: .9em; }
    .pill { display: inline-block; margin-top: 6px; padding: 11px 28px; border: 1px solid var(--gold-deep); border-radius: 999px; color: var(--ink); text-decoration: none; font-family: "Fraunces", serif; letter-spacing: .12em; font-size: 14px; transition: background .25s, color .25s; }
    .pill:hover { background: var(--gold-deep); color: #fff; }
    .map { margin: 4px 0 18px; border: 1px solid rgba(189,155,118,.5); border-radius: 12px; overflow: hidden; line-height: 0; box-shadow: 0 10px 26px rgba(60,40,24,.12); }
    .map iframe { display: block; width: 100%; height: 260px; border: 0; }

    /* Form (RSVP placeholder) */
    .form { max-width: 320px; margin: 0 auto; display: flex; flex-direction: column; gap: 14px; }
    .form[hidden] { display: none; }
    #attendingFields, #hostFields, #restFields { display: flex; flex-direction: column; gap: 14px; }
    #attendingFields[hidden], #hostFields[hidden], #restFields[hidden] { display: none; }
    #sideField { display: none; }   /* 賓客類別 is preset by version (新人/主婚人), so no need to pick */
    .field { text-align: left; }
    .field label { display: block; font-size: 18px; letter-spacing: .06em; color: var(--ink); margin: 0 0 7px 2px; }
    /* Form fields use the SYSTEM font, not the subsetted Noto Serif: users type arbitrary
       characters (names, blessings) that the subset can't cover, which would otherwise mix
       serif (in-subset) + fallback (out-of-subset) glyphs in one line. System CJK serif is
       unreliable on iOS, so use the native sans for a consistent, fully-covered look. */
    .field input, .field select, .field textarea { width: 100%; padding: 13px 15px; border: 1px solid var(--line); border-radius: 13px; background: var(--card); font: inherit; font-family: -apple-system, system-ui, "PingFang TC", "Microsoft JhengHei", sans-serif; color: var(--ink); }
    .field textarea { resize: vertical; min-height: 88px; line-height: 1.6; }
    .field select { -webkit-appearance: none; appearance: none; padding-right: 42px; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23bd9b76' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 14px center; background-size: 16px; }
    .field input:focus, .field select:focus, .field textarea:focus { outline: none; border-color: var(--gold-deep); }
    .form button { margin-top: 4px; padding: 15px; border: 0; border-radius: 999px; background: linear-gradient(135deg,#e8cfa3,#cda067); color: #3c2c1c; font: inherit; font-size: 15px; letter-spacing: .1em; cursor: pointer; transition: filter .2s ease, opacity .2s ease; -webkit-tap-highlight-color: transparent; }
    .form button:hover { filter: brightness(1.04); }
    .form button:active { transform: translateY(1px); }
    .form button:disabled { cursor: default; opacity: .55; filter: none; }
    .req { color: #c2674f; font-size: .9em; }
    .hp { position: absolute !important; left: -9999px; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
    .field.error input, .field.error select, .field.error textarea { border-color: #c2674f; }
    .rsvp__err { font-size: 14px; text-align: center; color: #c2674f; margin: 4px 0 0; }
    .rsvp__err.is-info { color: var(--muted); }
    .rsvp__thanks { max-width: 320px; margin: 0 auto; text-align: center; padding: 26px 0 6px; animation: rsvpThanksIn .6s ease both; }
    .rsvp__thanks-mark { color: var(--coral); }
    .rsvp__thanks-mark .heart { width: 40px; height: 40px; animation: rsvpHeartPop .55s .12s cubic-bezier(.34,1.56,.64,1) both; }
    .rsvp__thanks-t { margin: 12px 0 0; font-size: 24px; letter-spacing: .08em; color: var(--ink); }
    .rsvp__thanks-s { margin: 8px 0 0; font-size: 14px; line-height: 1.7; color: var(--muted); }
    @keyframes rsvpThanksIn { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
    @keyframes rsvpHeartPop { 0% { transform: scale(0); } 100% { transform: scale(1); } }
    .soon { text-align: center; font-size: 14px; color: var(--muted); margin: 16px 0 0; letter-spacing: .05em; }

    /* Notes (universal) */
    .notes__title { margin: 0 0 30px; font-family: "Fraunces", serif; font-style: italic; font-weight: 600; font-size: 40px; text-align: center; color: #bf5640; }
    .notes__list { list-style: none; margin: 0 auto; padding: 0; max-width: 30em; }
    .notes__item { display: flex; align-items: flex-start; gap: 10px; }
    .notes__item + .notes__item { margin-top: 24px; }
    .notes__clover { flex: none; width: 1.15em; height: 1.9em; margin-top: .06em; color: #8fae5a; }   /* height = first-line line-height; tiny nudge down to sit closer to the text */
    .notes__item p { margin: 0; font-size: 16px; line-height: 1.9; letter-spacing: .02em; color: var(--ink); }

    /* Footer */
    .foot { text-align: center; background: var(--bg); color: var(--ink); padding: 64px 30px calc(40px + env(safe-area-inset-bottom)); }
    .foot__heart { color: var(--coral); font-size: .62em; margin: 0 .22em; }
    .foot__names { font-family: "ChenYuluoyan", "Songti TC", serif; font-size: 30px; -webkit-text-stroke: .5px currentColor; letter-spacing: .06em; }
    .foot__date { font-family: "Fraunces", serif; letter-spacing: .28em; text-indent: .28em; color: var(--gold-deep); margin-top: 12px; font-size: 13px; }
    .foot__ty { font-family: "Fraunces", serif; font-style: italic; color: var(--gold-deep); margin-top: 22px; font-size: 13px; }

    @keyframes drift { from { transform: scale(1.05) translate(0,0); } to { transform: scale(1.16) translate(-2.6%,-3.2%); } }
    @keyframes rise { from { opacity: 0; transform: translateY(16px); filter: blur(7px); } to { opacity: 1; transform: none; filter: blur(0); } }
    @keyframes fadeFrame { to { opacity: 1; } }
    @keyframes heartbeat { 0%,100% { transform: scale(1); } 14% { transform: scale(1.22); } 28% { transform: scale(1); } 42% { transform: scale(1.16); } 56% { transform: scale(1); } }
    @keyframes sway { 0%,100% { transform: rotate(-7deg); } 50% { transform: rotate(7deg); } }
    @keyframes breathe { 0%,100% { opacity: .55; } 50% { opacity: 1; } }
    @keyframes bob { 0%,100% { transform: translateY(0); } 50% { transform: translateY(6px); } }

    /* ═══════════ Procedural plant gardens (canvas, no images) ═══════════
       Each <canvas class="garden …"> sits behind its section's text
       (pointer-events:none) and is driven by the inline garden engine. The
       `:not(.garden)` lift keeps real content above the canvas without
       clobbering the canvas's own absolute positioning. */
    /* width:100% is essential — a <canvas> is a replaced element, so with only a
       CSS height it would derive its width from the 2:1 intrinsic ratio (ignoring
       right:0) and overflow the section. */
    /* translateZ(0) puts each animating canvas on its own compositing layer, so its
       per-frame repaints don't re-rasterise neighbours (e.g. the couple portraits'
       drop-shadow, which otherwise flashed a square box on scroll). */
    .garden { position: absolute; pointer-events: none; z-index: 0; display: block; width: 100%; transform: translateZ(0); }
    .garden-a { left: 0; right: 0; bottom: 0; height: 170px; }   /* footer meadow (tall enough for the 150px blooms) */
    .garden-b { left: 0; right: 0; bottom: 0; height: 118px; }   /* meadow on the welcome→photo seam */
    .garden-d { left: 0; right: 0; top: 0;    height: 300px; }   /* welcome — hanging side vines */
    .garden-e { left: 0; right: 0; top: 0;    height: 190px; }   /* save-the-date — top-corner vines */
    .garden-g { left: 0; right: 0; bottom: 0; height: 118px; }   /* meadow on the gallery→moments seam */
    .garden-c  { left: 0; right: 0; top: 0;    height: 78px; }   /* couple — short cute fringe drooping from the top */
    .garden-cb { left: 0; right: 0; bottom: 0; height: 78px; }   /* couple — matching cute meadow on the bottom seam */
    .garden-dt { left: 0; right: 0; top: 0;    height: 280px; }  /* details — sparse hanging vines (like welcome) */

    /* extra bottom room so the meadow sits BELOW the footer text, not over it */
    .foot { position: relative; overflow: hidden; padding-bottom: calc(188px + env(safe-area-inset-bottom)); }
    .foot > *:not(.garden) { position: relative; z-index: 1; }

    /* welcome holds two gardens: hanging vines at the top, and a meadow rooted on
       the SEAM where this section meets the photo below (extra padding gives room) */
    #welcome { overflow: hidden; padding-bottom: 150px; }
    #welcome > *:not(.garden) { position: relative; z-index: 1; }

    /* gallery meadow rooted on the seam where the gallery meets the moments below */
    #gallery-sec { overflow: hidden; padding-bottom: 150px; }
    #gallery-sec > *:not(.garden) { position: relative; z-index: 1; }

    /* couple — cute fringes on BOTH seams (top droops down, bottom grows up) */
    #couple { overflow: hidden; padding-top: 96px; padding-bottom: 96px; }
    #couple > *:not(.garden) { position: relative; z-index: 1; }

    /* details — sparse hanging vines from the top corners (like welcome) */
    #details { overflow: hidden; }
    #details > *:not(.garden) { position: relative; z-index: 1; }

    /* lite (elder) version: drop the welcome→couple meadow and the details-top vines,
       and reclaim the room the welcome meadow needed */
    body.lite .garden-b,
    body.lite .garden-dt { display: none; }
    /* lite welcome keeps its side vines but hides the bottom meadow; centre the title
       with a modest min-height so it isn't too short */
    body.lite #welcome {
      padding-bottom: 80px;
      min-height: 400px;
      display: flex; flex-direction: column; justify-content: center;
    }

    #date { overflow: hidden; }
    #date > *:not(.garden) { position: relative; z-index: 1; }

    @media (prefers-reduced-motion: reduce) {
      .gate::before, .hero::before, .hero__amp, .hero__scroll { animation: none; }
      .gate__ask > *, .gate__kicker-top, .gate__frame, .gate.is-entering .gate__entering,
      .gate__sub, .gate__note, .gate__flower, .gate__amp { animation: none; opacity: 1; }
      .gate__frame { opacity: 1; }
      .reveal { opacity: 1; transform: none; transition: none; }
      .music-btn.is-playing { animation: none; }
      .player.is-playing .eq span { animation: none; transform: scaleY(.55); }
      .rsvp__thanks, .rsvp__thanks-mark .heart { animation: none; }
      .nav-overlay.is-open .nav__top, .nav-overlay.is-open .nav__list li, .nav-overlay.is-open .nav__date { animation: none; }
    }
