:root {
  --ink: #5a1f21;
  --ink-2: #9c5254;
  --lacquer: #8e1f19;
  --lacquer-deep: #8a4548;
  --gold: #caa14a;
  --gold-soft: #e4c988;
  --red: #ab3223;
  --jade: #3f8074;
  --jade-deep: #123f3b;
  --dancheong-blue: #2b5c8a;
  --dancheong-blue-deep: #1a3753;
  --stone: #8a8175;
  --paper: #f3ead8;
  --paper-alt: #ebdfc5;
  --paper-dim: #dccfb4;
  --ink-soft: #6e3b38;
  --gold-text: #6b5214;
  --hairline: rgba(160, 122, 48, 0.35);
  --shadow-soft: 0 1px 2px rgba(58, 20, 16, 0.06), 0 12px 32px -12px rgba(58, 20, 16, 0.28);
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);

  /* Painted eave pattern (dancheong): jade ground, red & blue lozenges, gold trim */
  --dancheong: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='64' height='28' viewBox='0 0 64 28'%3E%3Crect width='64' height='28' fill='%23123f3b'/%3E%3Crect width='64' height='3' fill='%23caa14a'/%3E%3Crect y='25' width='64' height='3' fill='%23caa14a'/%3E%3Cpath d='M32 3 46 14 32 25 18 14Z' fill='%239c2b2b' stroke='%23e4c988' stroke-width='1'/%3E%3Cpath d='M32 8 40 14 32 20 24 14Z' fill='%232b5c8a'/%3E%3Ccircle cx='32' cy='14' r='2' fill='%23efe1c3'/%3E%3Ccircle cx='0' cy='14' r='6' fill='%233f8074'/%3E%3Ccircle cx='64' cy='14' r='6' fill='%233f8074'/%3E%3Ccircle cx='0' cy='14' r='2.5' fill='%23efe1c3'/%3E%3Ccircle cx='64' cy='14' r='2.5' fill='%23efe1c3'/%3E%3C/svg%3E");
  --ornament: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='16' viewBox='0 0 160 16'%3E%3Cpath d='M0 8H66M94 8H160' stroke='%23caa14a' stroke-opacity='.7'/%3E%3Cg transform='translate(72 0) scale(.667)'%3E%3Ccircle cx='12' cy='12' r='11.5' fill='%232b5c8a' stroke='%23caa14a'/%3E%3Cpath d='M.5 12A11.5 11.5 0 0 1 23.5 12A5.75 5.75 0 0 1 12 12A5.75 5.75 0 0 0 .5 12Z' fill='%23c0392b'/%3E%3Ccircle cx='17.75' cy='12' r='1.9' fill='%232b5c8a'/%3E%3Ccircle cx='6.25' cy='12' r='1.9' fill='%23c0392b'/%3E%3C/g%3E%3C/svg%3E");
  --ornament-coin: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='16' viewBox='0 0 160 16'%3E%3Cpath d='M0 8H66M94 8H160' stroke='%23caa14a' stroke-opacity='.7'/%3E%3Ccircle cx='80' cy='8' r='7.5' fill='%23caa14a' stroke='%23f3dc9d'/%3E%3Ccircle cx='80' cy='8' r='5.6' fill='none' stroke='%237a5a1c' stroke-width='.8'/%3E%3Crect x='77' y='5' width='6' height='6' fill='%231a0a08' stroke='%237a5a1c' stroke-width='.8'/%3E%3C/svg%3E");
  --balustrade:
    linear-gradient(var(--stone), var(--stone)) top / 100% 6px no-repeat,
    repeating-linear-gradient(90deg, #6f675d 0 9px, transparent 9px 30px);

  --display: "Cormorant Garamond", "Times New Roman", serif;
  --hanzi: "Noto Serif TC", "Songti TC", "Songti SC", serif;
  --hangul: "Noto Serif KR", "AppleMyungjo", serif;
  --accent-font: "Marcellus", "Cormorant Garamond", serif;
  --body-font: "EB Garamond", Georgia, serif;
}

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  scroll-behavior: smooth;
}

body {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--body-font);
  font-size: 1.0625rem;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

::selection {
  background: rgba(202, 161, 74, 0.35);
  color: var(--ink);
}

a,
button,
input {
  -webkit-tap-highlight-color: transparent;
}

:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 3px;
}

/* --- Intro video --- */

#intro {
  position: fixed;
  inset: 0;
  z-index: 100;
  background: #000;
  overflow: hidden;
}

#intro-video {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}

#intro-fade {
  position: absolute;
  inset: 0;
  background: #000;
  opacity: 0;
  pointer-events: none;
  transition: opacity 1s ease-in;
}

#intro-fade.is-fading {
  opacity: 1;
}

#intro.is-done {
  display: none;
}

#intro-skip {
  position: absolute;
  right: 1.5rem;
  bottom: 1.5rem;
  padding: 0.5rem 1.1rem;
  background: rgba(0, 0, 0, 0.4);
  color: var(--paper);
  border: 1px solid rgba(228, 201, 136, 0.5);
  border-radius: 999px;
  font-family: var(--accent-font);
  font-size: 0.85rem;
  letter-spacing: 0.06em;
  cursor: pointer;
  transition: background 0.2s ease, border-color 0.2s ease;
}

#intro-skip:hover {
  background: rgba(0, 0, 0, 0.6);
  border-color: var(--gold-soft);
}


/* --- Site --- */

#site {
  position: relative;
  min-height: 100vh;
  overflow-x: hidden;
}

/* Sun Wukong riding his cloud across the screen when the site opens.
   The outer element flies (left to right); the image inside bobs. */
.wukong {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 20;
  width: clamp(96px, 15vw, 180px);
  pointer-events: none;
  opacity: 0;
  transform: translate(-30vw, 40vh);
}

.wukong img {
  display: block;
  width: 100%;
  height: auto;
  filter: drop-shadow(0 10px 14px rgba(0, 0, 0, 0.5));
  animation: bob 0.85s ease-in-out infinite alternate;
}

#site.is-visible .wukong {
  animation: fly 10s cubic-bezier(0.35, 0, 0.65, 1) 3s 1 forwards;
}

@keyframes fly {
  0%   { opacity: 1; transform: translate(-30vw, 48vh); }
  50%  { opacity: 1; transform: translate(42vw, 27vh); }
  100% { opacity: 1; transform: translate(130vw, 44vh); }
}

@keyframes bob {
  from { transform: translateY(-14px) rotate(-4deg); }
  to   { transform: translateY(14px) rotate(4deg); }
}

/* Click the monkey: a chaotic swarm of clones tumbles across the
   screen. Each clone gets its own random waypoints via custom
   properties set from JS, so every swarm looks different. */
.wukong {
  cursor: pointer;
  pointer-events: auto;
}

.wukong-swarm-monkey {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 25;
  width: clamp(56px, 8vw, 100px);
  pointer-events: none;
  will-change: transform, opacity;
  animation: spastic-fly var(--dur, 2.2s) cubic-bezier(0.36, 0.07, 0.19, 0.97) var(--delay, 0s) 1 forwards;
}

.wukong-swarm-monkey img {
  display: block;
  width: 100%;
  height: auto;
  filter: drop-shadow(0 8px 10px rgba(0, 0, 0, 0.4));
}

@keyframes spastic-fly {
  0%   { transform: translate(var(--x0), var(--y0)) rotate(0deg) scale(var(--s0)); opacity: 0; }
  8%   { opacity: 1; }
  20%  { transform: translate(var(--x1), var(--y1)) rotate(var(--r1)) scale(var(--s1)); }
  38%  { transform: translate(var(--x2), var(--y2)) rotate(var(--r2)) scale(var(--s2)); }
  56%  { transform: translate(var(--x3), var(--y3)) rotate(var(--r3)) scale(var(--s3)); }
  74%  { transform: translate(var(--x4), var(--y4)) rotate(var(--r4)) scale(var(--s4)); }
  92%  { opacity: 1; transform: translate(var(--x5), var(--y5)) rotate(var(--r5)) scale(var(--s5)); }
  100% { transform: translate(var(--x6), var(--y6)) rotate(var(--r6)) scale(var(--s6)); opacity: 0; }
}

/* Lacquered pillars running down both edges of the hall */
#site::before,
#site::after {
  content: "";
  position: fixed;
  top: 0;
  bottom: 0;
  width: clamp(12px, 3.4vw, 48px);
  z-index: 5;
  pointer-events: none;
  background: linear-gradient(90deg, #340908 0%, #862019 22%, #c23b2c 48%, #8e211b 74%, #300807 100%);
  box-shadow: 0 0 24px rgba(58, 20, 16, 0.35);
}

#site::before {
  left: 0;
  border-right: 2px solid var(--gold);
}

#site::after {
  right: 0;
  border-left: 2px solid var(--gold);
}

.eyebrow {
  font-family: var(--accent-font);
  text-transform: uppercase;
  letter-spacing: 0.32em;
  font-size: 0.8rem;
  color: var(--gold-text);
  text-shadow: 0 1px 8px rgba(243, 234, 216, 0.7);
}

/* Every section heading sits centered over its content, with the
   ornament centered beneath it, so each hall reads as one symmetric
   composition. */
h2 {
  font-family: var(--display);
  font-weight: 500;
  font-size: clamp(2rem, 4.6vw, 3.1rem);
  line-height: 1.15;
  letter-spacing: 0.01em;
  margin-top: 0.6rem;
  color: var(--ink);
  text-align: center;
  text-wrap: balance;
}

h2::after {
  content: "";
  display: block;
  width: 160px;
  height: 16px;
  margin: 1.1rem auto 0;
  background: var(--ornament) center / contain no-repeat;
}

.panel-inner > .dual {
  text-align: center;
}

/* Alternate the Korean taegeuk with a Chinese coin, section by section */
.panel:nth-of-type(odd) h2::after {
  background-image: var(--ornament-coin);
}

.center h2::after {
  margin-left: auto;
  margin-right: auto;
}

.body-text {
  font-size: 1.2rem;
  line-height: 1.75;
  color: var(--ink-soft);
  max-width: 38rem;
  margin-top: 1.5rem;
}

/* Chinese (Traditional) and Korean set side by side */

[lang="zh-Hant"] { font-family: var(--hanzi); }
/* Korean wraps between words (eojeol), never mid-word */
[lang="ko"] { font-family: var(--hangul); word-break: keep-all; }

.dual {
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  color: var(--gold-text);
  margin-top: 1rem;
}

/* The RSVP gate and footer stay dark lacquer boxes on the light page,
   so their bilingual lines keep the lighter gold that reads on them. */
.gate-inner .dual,
.site-footer .dual {
  color: var(--gold-soft);
}

.dual span + span::before {
  content: "\00b7";
  margin: 0 0.8em;
  color: var(--red);
}

.dual-hero {
  font-size: clamp(1.1rem, 2.6vw, 1.5rem);
  margin: 0 0 1rem;
  text-shadow: 0 1px 8px rgba(243, 234, 216, 0.7);
}

.dual-footer {
  font-size: 1.1rem;
  margin: 0 0 1rem;
}

/* --- Hero: the hall front --- */

.hero {
  /* This roof art is 3022x710 (~4.26:1) — full width comes out to
     about 23.5% of that width tall. Capped by viewport height too,
     so short laptop screens don't push the date below the fold. */
  --roof-h: clamp(110px, min(23.5vw, 30vh), 360px);

  position: relative;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: calc(var(--roof-h) + 9rem) 1.5rem 6rem;
  /* The daytime scenery lives only here, on the hero itself, with the
     default (scrolling) attachment — so it moves away with the rest
     of the hero as the page scrolls, rather than staying pinned to
     the viewport. Everything below the hero goes back to the plain
     solid panel colors. */
  background:
    linear-gradient(180deg, rgba(243, 234, 216, 0.08) 0%, rgba(243, 234, 216, 0.18) 35%, rgba(243, 234, 216, 0.42) 60%, rgba(243, 234, 216, 0.85) 100%),
    url("../image/palace-courtyard-scenery.webp") center 38% / cover no-repeat;
  overflow: hidden;
}

/* A real illustrated roof, in place of the old flat SVG silhouette,
   spanning the full width the way the SVG did. Its painted bottom
   band replaces the separate .eave-band strip the SVG version
   needed. */
.hero-roof {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: var(--roof-h);
  z-index: 6;
  filter: drop-shadow(0 8px 14px rgba(58, 20, 16, 0.3));
}

/* Hanging name plaque */
.plaque {
  position: absolute;
  top: calc(var(--roof-h) + 0.9rem);
  left: 50%;
  transform: translateX(-50%);
  z-index: 2;
  padding: 0.5rem 1.6rem;
  background: linear-gradient(180deg, #1d0605, #340a08);
  border: 2px solid var(--gold);
  outline: 1px solid rgba(202, 161, 74, 0.45);
  outline-offset: 3px;
  box-shadow: 0 8px 18px rgba(58, 20, 16, 0.32);
}

.plaque::before,
.plaque::after {
  content: "";
  position: absolute;
  bottom: 100%;
  width: 2px;
  height: 0.9rem;
  background: var(--gold);
}

.plaque::before { left: 22%; }
.plaque::after { right: 22%; }

.plaque span {
  display: block;
  font-family: var(--hanzi);
  font-size: clamp(2rem, 5vw, 3rem);
  line-height: 1.1;
  color: var(--gold-soft);
  text-shadow: 0 0 14px rgba(228, 201, 136, 0.55);
}

/* Hanging couplet banners: Chinese on the left, Korean on the right */
.couplet {
  position: absolute;
  top: calc(var(--roof-h) + 11rem);
  z-index: 1;
  padding: 1rem 0.5rem;
  writing-mode: vertical-rl;
  font-weight: 600;
  font-size: clamp(1.4rem, 2.2vw, 1.9rem);
  letter-spacing: 0.35em;
  color: var(--gold-soft);
  background: linear-gradient(90deg, #6d1712, #a32a21 50%, #6d1712);
  border: 2px solid var(--gold);
  outline: 1px solid rgba(202, 161, 74, 0.45);
  outline-offset: 3px;
  box-shadow: 0 8px 18px rgba(58, 20, 16, 0.28);
  text-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
}

.couplet-l { left: clamp(2rem, 8.6vw, 8.6rem); font-family: var(--hanzi); }

/* The Korean couplet gets its own blue-lacquer treatment (dancheong
   blue, deep-to-mid-to-deep like the red couplet's gradient) instead
   of sharing the Chinese couplet's red — a matched pair in shape and
   gold trim, split by color the same way the content is split by
   language. */
.couplet-r {
  right: clamp(2rem, 8.6vw, 8.6rem);
  font-family: var(--hangul);
  background: linear-gradient(90deg, var(--dancheong-blue-deep), var(--dancheong-blue) 50%, var(--dancheong-blue-deep));
  box-shadow: 0 8px 18px rgba(20, 45, 70, 0.32);
}

@media (max-width: 1000px) {
  .couplet { display: none; }
}

/* Silk lanterns — a real paper-lantern photo (cord, globe and tassel
   all in one image) hung from the roofline with the same sway as
   the CSS-drawn version it replaces. */
.lantern {
  position: absolute;
  top: var(--roof-h);
  z-index: 1;
  width: clamp(2.6rem, 6vw, 4.1rem);
  height: auto;
  transform-origin: top center;
  animation: sway 5.5s ease-in-out infinite alternate;
  pointer-events: none;
  filter: drop-shadow(0 0 28px rgba(240, 100, 50, 0.4));
}

.lantern-l { left: clamp(2.2rem, 9vw, 9rem); }
.lantern-r { right: clamp(2.2rem, 9vw, 9rem); animation-delay: -2.7s; }

@keyframes sway {
  from { transform: rotate(-4deg); }
  to { transform: rotate(4deg); }
}

.hero-content {
  position: relative;
  z-index: 1;
}

.eyebrow.reveal-item {
  display: inline-block;
}

.names {
  font-family: var(--display);
  font-style: italic;
  font-weight: 500;
  font-size: clamp(3.2rem, 12vw, 7rem);
  line-height: 1.05;
  color: var(--ink);
  margin: 0.4rem 0 1rem;
  text-shadow: 0 2px 16px rgba(243, 234, 216, 0.75);
}

.names .amp {
  display: inline-block;
  margin: 0 0.3em;
  color: var(--red);
  font-style: normal;
}

.hero-meta {
  text-wrap: balance;
  display: inline-flex;
  align-items: center;
  gap: 1rem;
  font-family: var(--accent-font);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-size: clamp(0.8rem, 1.6vw, 0.95rem);
  color: var(--ink);
  text-shadow: 0 1px 8px rgba(243, 234, 216, 0.7);
}

/* Hero stagger reveal, triggered by .is-visible on #site */

.reveal-item {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 0.9s ease, transform 0.9s ease;
}

/* The palace assembles first — roof drops, plaque swings down, the
   couplets slide in from the sides, lanterns fade up — then the
   couple's names arrive. All gated on #site.is-visible, same trigger
   as the reveal-item fades below. */

.hero-roof {
  opacity: 0;
  transform: translateY(-32px);
}

#site.is-visible .hero-roof {
  animation: roof-in 0.9s cubic-bezier(0.22, 1, 0.36, 1) 0.05s forwards;
}

@keyframes roof-in {
  to { opacity: 1; transform: translateY(0); }
}

.plaque {
  transform: translate(-50%, -18px) rotate(-4deg);
  opacity: 0;
}

#site.is-visible .plaque {
  animation: plaque-in 0.7s cubic-bezier(0.34, 1.56, 0.64, 1) 0.45s forwards;
}

@keyframes plaque-in {
  to { opacity: 1; transform: translate(-50%, 0) rotate(0deg); }
}

.couplet-l,
.couplet-r {
  opacity: 0;
}

.couplet-l { transform: translateX(-28px); }
.couplet-r { transform: translateX(28px); }

#site.is-visible .couplet-l {
  animation: couplet-l-in 0.65s ease-out 0.55s forwards;
}

#site.is-visible .couplet-r {
  animation: couplet-r-in 0.65s ease-out 0.6s forwards;
}

@keyframes couplet-l-in {
  to { opacity: 1; transform: translateX(0); }
}

@keyframes couplet-r-in {
  to { opacity: 1; transform: translateX(0); }
}

.lantern {
  opacity: 0;
}

#site.is-visible .lantern-l {
  animation: sway 5.5s ease-in-out infinite alternate, lantern-fade-in 0.6s ease-out 0.65s forwards;
}

#site.is-visible .lantern-r {
  animation: sway 5.5s ease-in-out infinite alternate, lantern-fade-in 0.6s ease-out 0.7s forwards;
  animation-delay: -2.7s, 0.7s;
}

@keyframes lantern-fade-in {
  to { opacity: 1; }
}

#site.is-visible .hero .reveal-item:nth-child(1),
#site.is-visible .hero-content .reveal-item:nth-child(1) {
  transition-delay: 0.85s;
}

#site.is-visible .eyebrow.reveal-item { transition-delay: 0.85s; }
#site.is-visible .names .reveal-item:nth-child(1) { transition-delay: 1s; }
#site.is-visible .names .reveal-item:nth-child(2) { transition-delay: 1.15s; }
#site.is-visible .names .reveal-item:nth-child(3) { transition-delay: 1.3s; }
#site.is-visible .dual-hero.reveal-item { transition-delay: 1.45s; }
#site.is-visible .hero-meta.reveal-item { transition-delay: 1.6s; }
#site.is-visible .scroll-cue.reveal-item { transition-delay: 1.7s; }

#site.is-visible .reveal-item {
  opacity: 1;
  transform: translateY(0);
}

/* The ampersand gets a gentle breathing glow once the names have
   landed — small ongoing motion so the hero doesn't go fully static
   after the entrance finishes. The names themselves stay a plain
   solid ink color (no shimmer). */
.names .amp {
  animation: amp-glow 3.4s ease-in-out 2.4s infinite;
}

.hero-meta::before,
.hero-meta::after {
  content: "";
  width: clamp(1.5rem, 5vw, 3.5rem);
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--gold));
}

.hero-meta::after {
  transform: scaleX(-1);
}

@media (max-width: 520px) {
  .hero-meta {
    max-width: 16rem;
    line-height: 1.7;
  }

  .hero-meta::before,
  .hero-meta::after {
    display: none;
  }
}

@keyframes amp-glow {
  0%, 100% { text-shadow: 0 2px 16px rgba(243, 234, 216, 0.75); }
  50% { text-shadow: 0 2px 22px rgba(171, 50, 35, 0.55), 0 2px 16px rgba(243, 234, 216, 0.75); }
}

.scroll-cue {
  position: absolute;
  bottom: 2.5rem;
  left: 50%;
  z-index: 3;
  transform: translateX(-50%);
  width: 1px;
  height: 3.2rem;
}

.scroll-cue span {
  display: block;
  width: 1px;
  height: 100%;
  background: linear-gradient(to bottom, transparent, var(--gold-text));
  animation: pulse-down 2.2s ease-in-out infinite;
}

@keyframes pulse-down {
  0%, 100% { opacity: 0.3; }
  50% { opacity: 1; }
}

/* --- Panels: successive halls, each under its own painted eave --- */

.panel {
  padding: clamp(5.5rem, 10vw, 8rem) clamp(1.75rem, 5vw, 3rem) clamp(4.5rem, 8vw, 7rem);
  position: relative;
  background:
    radial-gradient(ellipse 70% 40% at 50% 0%, rgba(202, 161, 74, 0.1), transparent 70%),
    repeating-linear-gradient(0deg, rgba(120, 90, 40, 0.018) 0 1px, transparent 1px 3px),
    linear-gradient(180deg, #f8f1e2, var(--paper));
}

.panel.alt {
  background:
    radial-gradient(ellipse 60% 55% at 50% 45%, rgba(142, 31, 25, 0.05), transparent 75%),
    repeating-linear-gradient(0deg, rgba(120, 90, 40, 0.022) 0 1px, transparent 1px 3px),
    var(--paper-alt);
}

.panel::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 22px;
  background: var(--dancheong) 0 0 / auto 100% repeat-x;
  border-bottom: 2px solid var(--gold);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.18);
}

.panel-inner {
  max-width: 52rem;
  margin: 0 auto;
  opacity: 0;
  transform: translateY(24px);
  transition: opacity 0.9s var(--ease-out), transform 0.9s var(--ease-out);
}

.panel-inner.center {
  text-align: center;
  margin-left: auto;
  margin-right: auto;
}

.panel-inner.center .body-text {
  margin-left: auto;
  margin-right: auto;
}

.panel-inner.in-view {
  opacity: 1;
  transform: translateY(0);
}

/* --- Details: arched lacquer doors --- */

.detail-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  justify-items: center;
  gap: clamp(1.5rem, 4vw, 2.5rem);
  margin-top: 3rem;
}

.detail-card {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
  max-width: 26rem;
  padding: 3.4rem clamp(1.4rem, 4vw, 2.2rem) 2.6rem;
  text-align: center;
  border: 2px solid var(--gold);
  border-radius: 50% 50% 0 0 / 4rem 4rem 0 0;
  background:
    radial-gradient(circle at 14px calc(100% - 14px), var(--gold-soft) 2.5px, transparent 3.5px),
    radial-gradient(circle at calc(100% - 14px) calc(100% - 14px), var(--gold-soft) 2.5px, transparent 3.5px),
    linear-gradient(180deg, #5c130f, #2c0908);
  box-shadow:
    inset 0 0 0 6px #2c0908,
    inset 0 0 0 7px rgba(202, 161, 74, 0.55),
    0 2px 4px rgba(58, 20, 16, 0.12),
    0 22px 40px -16px rgba(58, 20, 16, 0.5);
  transition: transform 0.5s var(--ease-out), box-shadow 0.5s var(--ease-out);
}

@media (hover: hover) {
  .detail-card:hover {
    transform: translateY(-4px);
    box-shadow:
      inset 0 0 0 6px #2c0908,
      inset 0 0 0 7px rgba(202, 161, 74, 0.7),
      0 2px 4px rgba(58, 20, 16, 0.12),
      0 30px 50px -18px rgba(58, 20, 16, 0.55);
  }
}

/* Reception carries the Korean dancheong blue instead of the red
   lacquer, mirroring the couplet split (Chinese=red, Korean=blue). */
#reception .detail-card {
  background:
    radial-gradient(circle at 14px calc(100% - 14px), var(--gold-soft) 2.5px, transparent 3.5px),
    radial-gradient(circle at calc(100% - 14px) calc(100% - 14px), var(--gold-soft) 2.5px, transparent 3.5px),
    linear-gradient(180deg, var(--dancheong-blue), var(--dancheong-blue-deep));
  box-shadow:
    inset 0 0 0 6px var(--dancheong-blue-deep),
    inset 0 0 0 7px rgba(202, 161, 74, 0.55),
    0 2px 4px rgba(20, 45, 70, 0.12),
    0 22px 40px -16px rgba(20, 45, 70, 0.5);
}

@media (hover: hover) {
  #reception .detail-card:hover {
    box-shadow:
      inset 0 0 0 6px var(--dancheong-blue-deep),
      inset 0 0 0 7px rgba(202, 161, 74, 0.7),
      0 2px 4px rgba(20, 45, 70, 0.12),
      0 30px 50px -18px rgba(20, 45, 70, 0.55);
  }
}

.detail-icon {
  width: 2.6rem;
  height: 2.6rem;
  color: var(--gold-soft);
  margin-bottom: 1rem;
}

.detail-card h3 {
  font-family: var(--display);
  font-size: 1.75rem;
  font-weight: 500;
  letter-spacing: 0.02em;
  margin-bottom: 0.4rem;
  color: #fbf4e4;
}

.detail-card p {
  text-wrap: balance;
  color: var(--paper-dim);
  font-size: 1.1rem;
  line-height: 1.6;
}

.detail-card p + p {
  margin-top: 0.9rem;
}

/* The bilingual line doubles as a divider: a short gold rule under it
   separates the card's title from its details. */
.detail-card .dual {
  font-size: 0.95rem;
  letter-spacing: 0.2em;
  color: var(--gold-soft);
  margin: 0 0 1.4rem;
}

.detail-card .dual::after {
  content: "";
  display: block;
  width: 2.5rem;
  height: 1px;
  margin: 1.2rem auto 0;
  background: var(--gold);
  opacity: 0.7;
}

/* The line right under the divider is the key fact (date/time), set
   in the engraved caps face so it's the first thing the eye lands on. */
.detail-card .dual + p {
  font-family: var(--accent-font);
  font-size: 1rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--gold-soft);
  line-height: 1.9;
}

.detail-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 1rem;
  margin-top: 2.5rem;
}

.map-embed {
  margin-top: 2.5rem;
  padding: 6px;
  background: #fbf6ea;
  border: 1px solid var(--gold);
  box-shadow: var(--shadow-soft);
  overflow: hidden;
}

.map-embed iframe {
  display: block;
  width: 100%;
  height: 320px;
  border: 0;
}

@media (max-width: 640px) {
  .map-embed iframe {
    height: 240px;
  }
}

/* Primary action is solid lacquer with gold lettering; the second
   is its outlined twin, so the pair reads as clearly clickable. */
.action-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 3rem;
  padding: 0.8rem 2rem;
  color: var(--gold-soft);
  text-decoration: none;
  text-transform: uppercase;
  border: 1px solid var(--gold);
  background: linear-gradient(180deg, #7a1c15, #561410);
  box-shadow: inset 0 0 0 3px #561410, inset 0 0 0 4px rgba(202, 161, 74, 0.45), var(--shadow-soft);
  font-family: var(--accent-font);
  letter-spacing: 0.16em;
  font-size: 0.85rem;
  transition: transform 0.3s var(--ease-out), background 0.3s ease, color 0.3s ease, box-shadow 0.3s ease;
}

.action-button + .action-button {
  color: var(--ink);
  background: transparent;
  box-shadow: none;
}

.action-button:hover,
.action-button:focus-visible {
  transform: translateY(-2px);
  background: var(--gold);
  color: #2c0908;
  box-shadow: inset 0 0 0 3px var(--gold), inset 0 0 0 4px rgba(90, 31, 33, 0.35), var(--shadow-soft);
}

@media (max-width: 520px) {
  .action-button {
    flex: 1 1 100%;
  }
}

.couple-names {
  margin-top: 2.2rem;
  font-family: var(--display);
  font-style: italic;
  font-size: clamp(1.6rem, 3.5vw, 2rem);
  color: var(--gold-text);
}

.couple-names span {
  margin: 0 0.3em;
  color: var(--red);
  font-style: normal;
}

.faq {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: 1.5rem;
  margin-top: 3rem;
}

/* Each question/answer pair becomes one framed card: the dt draws the
   card's top half and the dd its bottom, sharing one grid cell each. */
.faq dt,
.faq dd {
  background: rgba(251, 246, 234, 0.75);
  border: 1px solid var(--hairline);
}

.faq dt {
  grid-row: 1;
  padding: 1.8rem 1.8rem 0.4rem;
  border-bottom: 0;
  font-family: var(--display);
  font-size: 1.5rem;
  font-weight: 600;
  line-height: 1.25;
  color: var(--ink);
}

.faq dt::before {
  content: "";
  display: block;
  width: 10px;
  height: 10px;
  margin-bottom: 1rem;
  transform: rotate(45deg);
  background: linear-gradient(135deg, var(--red) 50%, var(--dancheong-blue) 50%);
  outline: 1px solid var(--gold);
  outline-offset: 2px;
}

.faq dd {
  grid-row: 2;
  margin-top: -1.5rem;
  padding: 0.4rem 1.8rem 1.8rem;
  border-top: 0;
  font-size: 1.1rem;
  line-height: 1.7;
  color: var(--ink-soft);
  box-shadow: var(--shadow-soft);
}

@media (max-width: 640px) {
  .faq {
    grid-template-columns: 1fr;
    gap: 0;
  }

  .faq dt,
  .faq dd {
    grid-row: auto;
  }

  .faq dd {
    margin: 0 0 1.25rem;
  }
}

.faq dd strong {
  color: var(--red);
  font-weight: 600;
}

.footer-mail {
  color: var(--gold-soft);
  text-decoration: none;
  letter-spacing: 0.06em;
  border-bottom: 1px solid rgba(228, 201, 136, 0.35);
  transition: border-color 0.25s ease, color 0.25s ease;
}

.footer-mail:hover {
  color: #fbf4e4;
  border-color: var(--gold-soft);
}

/* --- Timeline: a path of stepping stones --- */

.timeline {
  list-style: none;
  max-width: 29rem;
  margin: 3rem auto 0;
  padding: 2.4rem clamp(1.25rem, 4vw, 2.5rem) 0.6rem;
  background: rgba(251, 246, 234, 0.75);
  border: 1px solid var(--hairline);
  box-shadow: var(--shadow-soft);
}

/* Time on the left, a gold rail with a diamond at each stop, then the
   event name with its Chinese/Korean beneath. */
.timeline li {
  position: relative;
  display: grid;
  grid-template-columns: 8.75rem 1fr;
  column-gap: 2.2rem;
  align-items: baseline;
  padding-bottom: 1.9rem;
}

.timeline li::after {
  content: "";
  position: absolute;
  left: calc(5.5rem + 1.1rem - 0.5px);
  top: 1.1rem;
  bottom: -0.2rem;
  width: 1px;
  background: var(--hairline);
}

.timeline li:last-child::after {
  display: none;
}

.timeline li::before {
  content: "";
  position: absolute;
  left: calc(5.5rem + 1.1rem - 6px);
  top: 0.4rem;
  width: 12px;
  height: 12px;
  transform: rotate(45deg);
  /* A red/blue diagonal split, echoing the taegeuk already used in the
     heading dividers, rather than a plain solid diamond. */
  background: linear-gradient(135deg, var(--red) 50%, var(--dancheong-blue) 50%);
  border: 1.5px solid var(--gold);
  box-shadow: 0 0 0 4px #fbf6ea;
}

.timeline-time {
  grid-row: span 2;
  font-family: var(--accent-font);
  letter-spacing: 0.08em;
  font-size: 1rem;
  text-align: right;
  white-space: nowrap;
  color: var(--gold-text);
  font-variant-numeric: lining-nums tabular-nums;
}

.timeline-dual {
  grid-column: 2;
  margin-top: 0.2rem;
  font-size: 0.85rem;
  letter-spacing: 0.14em;
  color: var(--gold-text);
  opacity: 0.85;
}

.timeline-dual span + span::before {
  content: "\00b7";
  margin: 0 0.5em;
  color: var(--red);
}

.timeline-label {
  grid-column: 2;
  font-family: var(--display);
  font-size: 1.45rem;
  font-weight: 500;
  line-height: 1.2;
  color: var(--ink);
}

@media (max-width: 420px) {
  .timeline li {
    grid-template-columns: 7rem 1fr;
    column-gap: 1.8rem;
  }

  .timeline li::before { left: calc(7rem + 0.9rem - 6px); }
  .timeline li::after { left: calc(7rem + 0.9rem - 0.5px); }
  .timeline-time { font-size: 0.8rem; }
  .timeline-label { font-size: 1.3rem; }
}

/* Gentle arrival reminder, shown on the ceremony card and under the
   timeline: an italic note set off by a thin gold frame. */
.arrival-note {
  font-style: italic;
  font-size: 1rem;
  line-height: 1.6;
  color: var(--ink-soft);
}

.detail-card .arrival-note {
  margin-top: auto;
  padding-top: 1.4rem;
  font-size: 0.98rem;
  color: var(--gold-soft);
}

.detail-card .arrival-note::before {
  content: "";
  display: block;
  width: 100%;
  height: 1px;
  margin-bottom: 1.2rem;
  background: linear-gradient(90deg, transparent, rgba(202, 161, 74, 0.6), transparent);
}

.timeline + .arrival-note {
  max-width: 29rem;
  text-wrap: balance;
  margin: 1.5rem auto 0;
  padding: 0.9rem 1.4rem;
  text-align: center;
  border-top: 1px solid var(--hairline);
  border-bottom: 1px solid var(--hairline);
}

/* --- RSVP: the studded palace gate --- */

.gate {
  position: relative;
  padding: 1.6rem;
  border: 3px solid var(--gold);
  background:
    radial-gradient(circle, #f3dc9d 0 2.5px, #a8842f 3.5px, transparent 5px) 0 0 / 34px 34px,
    linear-gradient(90deg, #6d1712, #a32a21 50%, #6d1712);
  box-shadow:
    inset 0 0 0 4px #4a100d,
    0 14px 28px rgba(58, 20, 16, 0.28);
}

/* seam where the two door leaves meet */
.gate::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: calc(50% - 2px);
  width: 4px;
  background: #2a0806;
  box-shadow: 0 0 0 1px var(--gold);
}

.gate-inner {
  position: relative;
  padding: 3rem 1.6rem;
  background: linear-gradient(180deg, #1d0605, #300a08);
  border: 2px solid var(--gold);
  outline: 1px solid rgba(202, 161, 74, 0.45);
  outline-offset: -8px;
}

/* The gate stays a dark lacquer box on the light page, so its
   heading and body copy keep the light tones that read on it. */
.gate-inner {
  padding: clamp(2.4rem, 6vw, 3.6rem) clamp(1.25rem, 5vw, 3rem);
}

.gate-inner h2 {
  color: #fbf4e4;
}

.gate-inner .body-text {
  color: var(--paper-dim);
}

.rsvp-button {
  margin-top: 2rem;
  padding: 1rem 2.6rem;
  background: rgba(202, 161, 74, 0.08);
  color: var(--paper);
  border: 1px solid var(--gold);
  font-family: var(--accent-font);
  letter-spacing: 0.1em;
  font-size: 0.95rem;
  cursor: not-allowed;
  opacity: 0.7;
}

/* --- Footer: stone balustrade --- */

.site-footer {
  position: relative;
  padding: 5rem 1.5rem 3.5rem;
  text-align: center;
  background:
    radial-gradient(ellipse 60% 80% at 50% 0%, rgba(202, 161, 74, 0.12), transparent 70%),
    linear-gradient(180deg, #4a1517, #2a0b0c);
  font-family: var(--accent-font);
  letter-spacing: 0.14em;
  font-size: 0.9rem;
  line-height: 2;
  color: var(--paper-dim);
}

.balustrade {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 26px;
  background: var(--balustrade);
  border-bottom: 2px solid #a59b8c;
}

@media (max-width: 640px) {
  .panel {
    padding: 5rem 1.5rem 4rem;
  }

  .gate {
    padding: 1rem;
  }

  .gate-inner {
    padding: 2rem 1rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  .lantern,
  .scroll-cue span,
  .wukong img,
  .hero-roof,
  .plaque,
  .couplet-l,
  .couplet-r,
  .names .amp {
    animation: none;
  }

  .wukong {
    display: none;
  }

  .detail-card,
  .action-button,
  .rsvp-form-submit,
  .panel-inner {
    transition: none;
  }

  /* Without their entrance animations, these just need to sit in
     their finished state instead of the hidden/offset one used to
     animate from. */
  .hero-roof,
  .lantern {
    opacity: 1;
    transform: none;
  }

  .plaque {
    opacity: 1;
    transform: translateX(-50%);
  }

  .couplet-l,
  .couplet-r {
    opacity: 1;
    transform: none;
  }
}

/* --- Login gate: password screen guarding the whole site --- */

body.login-page {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
  background:
    radial-gradient(ellipse 60% 50% at 50% 15%, rgba(202, 161, 74, 0.12), transparent 70%),
    radial-gradient(ellipse 80% 60% at 50% 100%, rgba(171, 50, 35, 0.28), transparent 70%),
    linear-gradient(180deg, #1d0605, #300a08 55%, #180403);
}

.login-card {
  position: relative;
  width: 100%;
  max-width: 24rem;
  padding: 3rem 2.2rem 2.6rem;
  text-align: center;
  background: linear-gradient(180deg, #2a0806, #3a0f0c);
  border: 2px solid var(--gold);
  outline: 1px solid rgba(202, 161, 74, 0.45);
  outline-offset: -8px;
  box-shadow: 0 20px 50px rgba(0, 0, 0, 0.45);
}

.login-mark {
  font-family: var(--hanzi);
  font-size: 2.6rem;
  line-height: 1;
  color: var(--gold);
  text-shadow: 0 0 18px rgba(202, 161, 74, 0.5);
  margin-bottom: 0.6rem;
}

.login-title {
  font-family: var(--display);
  font-style: italic;
  font-weight: 600;
  font-size: 2.2rem;
  color: var(--paper);
}

.login-dual {
  margin-top: 0.7rem;
  font-size: 0.95rem;
  letter-spacing: 0.18em;
  color: var(--gold-soft);
}

.login-dual span + span::before {
  content: "\00b7";
  margin: 0 0.7em;
  color: var(--red);
}

.login-form {
  margin-top: 2.2rem;
  display: flex;
  flex-direction: column;
  gap: 1.1rem;
}

.login-input {
  width: 100%;
  min-height: 3.25rem;
  padding: 0.85rem 1rem;
  background: rgba(0, 0, 0, 0.28);
  border: 1px solid var(--gold);
  color: var(--paper);
  font-family: var(--body-font);
  font-size: 1.05rem;
  text-align: center;
  letter-spacing: 0.04em;
}

.login-input::placeholder {
  color: var(--paper-dim);
  opacity: 0.65;
}

.login-input:focus {
  outline: none;
  border-color: var(--gold-soft);
  box-shadow: 0 0 0 3px rgba(202, 161, 74, 0.22);
}

.login-submit {
  margin-top: 0.2rem;
  min-height: 3.25rem;
  padding: 0.9rem 2rem;
  background: linear-gradient(180deg, #d8b25c, var(--gold));
  color: #2c0908;
  border: 1px solid var(--gold-soft);
  font-family: var(--accent-font);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  font-size: 0.9rem;
  cursor: pointer;
  transition: transform 0.3s var(--ease-out), background 0.25s ease, box-shadow 0.25s ease;
}

.login-submit:hover,
.login-submit:focus-visible {
  transform: translateY(-2px);
  background: var(--gold-soft);
  box-shadow: 0 10px 24px -10px rgba(228, 201, 136, 0.55);
}

.login-error {
  margin-top: 1.3rem;
  padding: 0.6rem 0.9rem;
  background: rgba(171, 50, 35, 0.25);
  border: 1px solid var(--red);
  color: var(--gold-soft);
  font-size: 0.9rem;
  letter-spacing: 0.02em;
}

/* --- RSVP form: fields staged inside the palace gate --- */

.rsvp-form-form {
  margin-top: 2.2rem;
  max-width: 26rem;
  margin-left: auto;
  margin-right: auto;
  text-align: left;
  display: flex;
  flex-direction: column;
  gap: 1.4rem;
}

.rsvp-form-form[hidden] {
  display: none;
}

.rsvp-form-field {
  border: 0;
  padding: 0;
}

.rsvp-form-label {
  display: block;
  margin-bottom: 0.65rem;
  font-family: var(--accent-font);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-size: 0.8rem;
  color: var(--gold-soft);
}

.rsvp-form-input {
  width: 100%;
  min-height: 3rem;
  padding: 0.75rem 1rem;
  background: rgba(0, 0, 0, 0.3);
  border: 1px solid rgba(202, 161, 74, 0.55);
  color: #fbf4e4;
  font-family: var(--body-font);
  font-size: 1.1rem;
  transition: border-color 0.25s ease, box-shadow 0.25s ease, background 0.25s ease;
}

.rsvp-form-input::placeholder {
  color: var(--paper-dim);
  opacity: 0.6;
}

.rsvp-form-input:focus {
  outline: none;
  background: rgba(0, 0, 0, 0.4);
  border-color: var(--gold-soft);
  box-shadow: 0 0 0 3px rgba(202, 161, 74, 0.22);
}

/* Yes/No choices become a pair of large tap targets; the checked one
   fills with gold. The real radio stays in the DOM (visually hidden)
   so keyboard and screen-reader behavior are unchanged. */
.rsvp-form-choices {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.75rem;
}

.rsvp-form-radio {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 3rem;
  padding: 0.6rem 1rem;
  border: 1px solid rgba(202, 161, 74, 0.55);
  background: rgba(0, 0, 0, 0.3);
  color: var(--paper-dim);
  font-family: var(--accent-font);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-size: 0.85rem;
  cursor: pointer;
  transition: background 0.25s ease, color 0.25s ease, border-color 0.25s ease;
}

.rsvp-form-radio input[type="radio"] {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
  pointer-events: none;
}

.rsvp-form-radio:hover {
  border-color: var(--gold-soft);
  color: #fbf4e4;
}

.rsvp-form-radio:has(input:checked) {
  background: var(--gold);
  border-color: var(--gold);
  color: #2c0908;
}

.rsvp-form-radio:has(input:focus-visible) {
  outline: 2px solid var(--gold-soft);
  outline-offset: 3px;
}

.rsvp-form-submit {
  margin-top: 0.8rem;
  align-self: stretch;
  min-height: 3.25rem;
  padding: 1rem 2.6rem;
  background: linear-gradient(180deg, #d8b25c, var(--gold));
  color: #2c0908;
  border: 1px solid var(--gold-soft);
  font-family: var(--accent-font);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  font-size: 0.9rem;
  cursor: pointer;
  transition: transform 0.3s var(--ease-out), background 0.25s ease, box-shadow 0.25s ease;
}

.rsvp-form-submit:hover,
.rsvp-form-submit:focus-visible {
  transform: translateY(-2px);
  background: var(--gold-soft);
  box-shadow: 0 10px 24px -10px rgba(228, 201, 136, 0.55);
}

.rsvp-form-submit:disabled {
  cursor: not-allowed;
  opacity: 0.6;
}

.rsvp-form-message {
  margin-top: 1.2rem;
  text-align: center;
  font-size: 1.05rem;
  color: var(--gold-soft);
}

.rsvp-form-message.is-error {
  padding: 0.6rem 0.9rem;
  background: rgba(171, 50, 35, 0.25);
  border: 1px solid var(--red);
}

@media (max-width: 640px) {
  .login-card {
    padding: 2.4rem 1.6rem 2rem;
  }

  .rsvp-form-choices {
    gap: 1rem;
  }
}
