/* ============================================================================
   Trang & Robert — wedding site
   Palette: Blush & Sage on an off-white yellow ground. Single committed light theme (this is stationery,
   not an app), so color-scheme is pinned to light and form controls follow.
   ========================================================================== */

:root {
  --ground:     #FDF9EC;   /* off-white yellow */
  --ground-alt: #FFFDF5;   /* cards, a shade lighter than the ground */
  --blush:      #F4C7CE;
  --blush-sub:  #FBEDE8;   /* pink tint band, warmed to sit on the yellow */
  --sage:       #9CAF88;
  --sage-deep:  #5A6E4B;   /* AA on all three surfaces: 5.29 ground, 4.88 tint, 5.47 card */
  --rosewood:   #A8465C;
  --rose-deep:  #8A3247;
  --bloom:      #F2C3CB;   /* petals */
  --bloom-line: #D98FA0;   /* petal outline — gives the blossom an edge */
  --bloom-heart:#E0B85F;   /* stamens — picks up the yellow ground */
  --branch:     #8A6A55;   /* peach blossom flowers on bare wood */
  --ink:        #3E3336;
  --ink-soft:   #6A5B5F;
  --line:       #E9DFC7;   /* hairlines, warmed to match */
  --field-line: #D9CBA9;   /* form fields sit on the page colour now, so their
                              edge has to carry more of the work than a hairline */

  /* Both script faces ship a Vietnamese subset — verified before choosing.
     Great Vibes is display-only: it's beautiful for the names and unreadable
     for a sentence of Vietnamese. Dancing Script carries the headings. */
  --font-display: "Great Vibes", "Snell Roundhand", "Apple Chancery", cursive;
  --font-script: "Dancing Script", "Snell Roundhand", "Segoe Script", cursive;
  --font-body: "Be Vietnam Pro", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
               "Helvetica Neue", Arial, sans-serif;

  --wrap: 68rem;
  --wrap-narrow: 40rem;
  --radius: 14px;
  --shadow: 0 1px 2px rgba(62, 51, 54, .05), 0 8px 24px -12px rgba(62, 51, 54, .18);
}

*, *::before, *::after { box-sizing: border-box; }

/* The `hidden` attribute must win. It only comes from the UA stylesheet, so ANY
   author rule that sets display beats it — which silently broke .field
   (display:grid) and the two framed images (display:block). Anything toggled
   with el.hidden in app.js depends on this line. */
[hidden] { display: none !important; }

html {
  color-scheme: light;
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: var(--font-body);
  font-weight: 400;
  /* Vietnamese stacks two diacritics on one vowel; tight leading clips them. */
  line-height: 1.7;
  font-size: 1rem;
  -webkit-font-smoothing: antialiased;
}

/* ── Language switching ───────────────────────────────────────────────────
   Both languages ship in the DOM; CSS hides the one we're not showing.
   Flash-free and works with JS disabled.                                    */
html[lang="en"] [data-lang="vi"],
html[lang="vi"] [data-lang="en"] { display: none !important; }

img, svg { max-width: 100%; }

h1, h2, h3 {
  font-family: var(--font-script);
  font-weight: 600;
  /* Script faces have tall ascenders AND Vietnamese stacks two diacritics on
     one vowel. Both want headroom; anything tighter clips ế, ằ, ữ. */
  line-height: 1.4;
  margin: 0 0 .5em;
  color: var(--rosewood);
  overflow-wrap: break-word;
}

p { margin: 0 0 1em; }
p:last-child { margin-bottom: 0; }

a { color: var(--rose-deep); text-underline-offset: .18em; }
a:hover { color: var(--rosewood); }

:focus-visible {
  outline: 3px solid var(--rose-deep);
  outline-offset: 2px;
  border-radius: 4px;
}

.wrap { width: 100%; max-width: var(--wrap); margin-inline: auto; padding-inline: 1.25rem; }
.wrap-narrow { max-width: var(--wrap-narrow); }
.center { text-align: center; }

.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  clip-path: inset(50%);
  overflow: hidden; white-space: nowrap;
}

.skip-link {
  position: absolute; left: 50%; top: 0;
  transform: translate(-50%, -120%);
  background: var(--rosewood); color: #fff;
  padding: .6rem 1.1rem; border-radius: 0 0 8px 8px;
  text-decoration: none; z-index: 100;
}
.skip-link:focus { transform: translate(-50%, 0); color: #fff; }

/* ── Header ───────────────────────────────────────────────────────────── */
.site-header {
  position: sticky; top: 0; z-index: 50;
  background: rgba(253, 247, 245, .92);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--line);
}
.header-inner {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; min-height: 3.75rem;
}
.monogram {
  font-family: var(--font-display);
  font-size: 1.6rem;
  letter-spacing: .04em; line-height: 1.9;
  color: var(--rosewood); text-decoration: none; white-space: nowrap;
  /* Truncate rather than shove the language toggle off a narrow screen. */
  min-width: 0; overflow: hidden; text-overflow: ellipsis;
}
/* The toggle is the one control a guest must always be able to reach. */
.header-actions { display: flex; align-items: center; gap: .6rem; flex: none; }

.lang-toggle {
  display: inline-flex;
  background: var(--ground-alt);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 2px;
}
.lang-btn {
  display: inline-flex; align-items: center; gap: .4rem;
  border: 0; background: transparent; cursor: pointer;
  font: inherit; font-size: .82rem; color: var(--ink-soft);
  padding: .34rem .7rem; border-radius: 999px;
  white-space: nowrap;
}
.lang-btn:hover { background: var(--blush-sub); color: var(--ink); }
.lang-btn[aria-pressed="true"] {
  background: var(--blush); color: var(--ink); font-weight: 500;
}
/* Flag emoji don't render on Windows Chrome — these are inline SVG instead. */
.flag { width: 1.15rem; height: auto; border-radius: 2px; display: block; flex: none; }

/* ── Buttons ──────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  font: inherit; font-weight: 500; cursor: pointer;
  padding: .8rem 1.5rem; border-radius: 999px;
  text-decoration: none; border: 1px solid transparent;
  transition: background-color .18s ease, color .18s ease, border-color .18s ease;
}
.btn-primary { background: var(--rosewood); color: #fff; }
.btn-primary:hover { background: var(--rose-deep); color: #fff; }
.btn-ghost { background: transparent; color: var(--rose-deep); border-color: var(--blush); }
.btn-ghost:hover { background: var(--blush-sub); color: var(--rose-deep); }
.btn-sm { padding: .45rem 1rem; font-size: .85rem; }
.btn-block { width: 100%; padding-block: .95rem; font-size: 1.02rem; }
.btn[disabled] { opacity: .6; cursor: progress; }

/* ── Hero ─────────────────────────────────────────────────────────────── */
.hero {
  /* One flat ground the whole way down the page — no gradient, no tinted
     bands. The floral dividers under each title do the separating instead. */
  padding: clamp(3rem, 9vw, 6rem) 0 clamp(2.5rem, 7vw, 4.5rem);
  text-align: center;
}
.eyebrow {
  font-size: .82rem; letter-spacing: .16em; text-transform: uppercase;
  color: var(--sage-deep); max-width: 34rem; margin-inline: auto;
  line-height: 1.9;
}
.names {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(3.2rem, 12vw, 6.5rem);
  line-height: 1.45;          /* Great Vibes swashes need the room */
  margin: .15em 0 .1em;
  display: flex; flex-wrap: wrap; align-items: baseline;
  justify-content: center; gap: 0 .3em;
}
.names .amp { color: var(--sage); font-size: .8em; }
.hero-meta {
  font-size: clamp(1rem, 2.4vw, 1.2rem);
  color: var(--ink-soft); letter-spacing: .03em;
}
.hero-cta {
  display: flex; flex-wrap: wrap; gap: .75rem;
  justify-content: center; margin-top: 2rem;
}

/* ── Countdown ────────────────────────────────────────────────────────────
   A sentence, not a row of boxes. Numbers cross-fade into the next value on a
   sine ease so the change reads as a merge rather than a flick.               */
.countdown { margin-top: 2rem; }

.countdown-sentence {
  max-width: 32rem;
  margin: 0 auto;
  font-size: clamp(1rem, 2.5vw, 1.2rem);
  /* Generous leading: the numerals are set larger than the words around them,
     and Vietnamese stacks diacritics on top of that. */
  line-height: 2.15;
  color: var(--ink-soft);
  text-wrap: balance;
}

.cd-roll {
  position: relative;
  display: inline-block;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 1.5em;
  line-height: 1;
  color: var(--rosewood);
  /* Tabular figures plus a right-aligned minimum width: when a value loses a
     digit the gap before it grows instead of the rest of the sentence jumping. */
  font-variant-numeric: tabular-nums;
  min-width: 2ch;
  text-align: right;
  vertical-align: baseline;
}
.cd-roll-days { min-width: 3ch; }

.cd-now { display: inline-block; }
/* The outgoing value is taken out of flow so the two never push each other. */
.cd-was {
  position: absolute;
  right: 0;
  top: 0;
  display: inline-block;
  pointer-events: none;
}

/* Binds a number to its unit so a line break can never fall between them. */
.cd-pair { display: inline-block; white-space: nowrap; }
.cd-unit { color: var(--ink-soft); }
.cd-sep  { margin-left: -.15em; }        /* keep the comma tight to its word */
.cd-tail { color: var(--ink); }

.countdown-today, .countdown-past {
  font-family: var(--font-script); font-weight: 600;
  font-size: clamp(1.4rem, 4.5vw, 2rem);
  color: var(--rosewood);
  margin: 0;
}
.countdown-today { margin-bottom: 1rem; }

/* ── Sections ─────────────────────────────────────────────────────────── */
.section { padding: clamp(3rem, 8vw, 5rem) 0; }
.section-title {
  font-size: clamp(2.1rem, 6vw, 3rem);
  text-align: center; margin-bottom: .15em;
}
.section-intro {
  text-align: center; max-width: 38rem; margin: -0.2rem auto 2.5rem;
  color: var(--ink-soft);
}

.card {
  background: var(--ground-alt);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.5rem;
  box-shadow: var(--shadow);
}
.card h3 {
  font-size: 1.02rem; letter-spacing: .1em; text-transform: uppercase;
  font-family: var(--font-body); font-weight: 600;
  color: var(--sage-deep);
  margin-bottom: .9em;
}
.lede { font-family: var(--font-script); font-weight: 600; font-size: 1.45rem; color: var(--ink); }

.detail-grid {
  display: grid; gap: 1.25rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr));
}

/* Four cards in an auto-fit grid go 3-then-1 on a wide screen. Pin to 2x2. */
@media (min-width: 58rem) {
  .detail-grid-2up { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.schedule { margin: 1rem 0 0; display: grid; grid-template-columns: auto 1fr; gap: .45rem 1rem; }
.schedule dt { color: var(--ink-soft); font-size: .9rem; }
.schedule dd { margin: 0; font-weight: 500; }

.venue-address { font-style: normal; color: var(--ink-soft); margin-bottom: 1rem; }

.map-placeholder {
  display: grid; place-items: center;
  aspect-ratio: 16 / 9;
  background: repeating-linear-gradient(45deg, var(--blush-sub) 0 12px, var(--ground) 12px 24px);
  border: 1px dashed var(--blush);
  border-radius: 10px;
  margin-bottom: 1rem;
}
.map-placeholder .pin { width: 2.5rem; height: 2.5rem; fill: var(--rosewood); opacity: .55; }
.map-links { display: flex; flex-wrap: wrap; gap: .5rem; }

/* ── Where to stay ────────────────────────────────────────────────────── */
.stay-grid {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: 1.25rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
}
.stay-card { display: flex; flex-direction: column; }
.stay-head { display: flex; align-items: baseline; justify-content: space-between; gap: .75rem; }
.stay-head h3 { min-width: 0; overflow-wrap: anywhere; }
.stay-head h3 {
  font-family: var(--font-script); font-weight: 600; font-size: 1.4rem;
  text-transform: none; letter-spacing: 0; color: var(--rosewood);
  margin-bottom: .25em;
}
.price-tier {
  font-size: .85rem; font-weight: 600; color: var(--sage-deep);
  background: var(--blush-sub); border-radius: 999px; padding: .1rem .55rem;
  /* Real values are "$".."$$$", but don't let an over-long one push the card
     wider than the page — shrink and wrap rather than force a scrollbar. */
  flex: 0 1 auto; min-width: 0; overflow-wrap: anywhere;
}
.stay-distance { font-size: .88rem; color: var(--ink-soft); margin-bottom: .6em; }
.stay-link { margin-top: auto; padding-top: .75rem; font-weight: 500; font-size: .92rem; }

/* ── RSVP form ────────────────────────────────────────────────────────── */
.rsvp-form { display: grid; gap: 1.15rem; }
.field { display: grid; gap: .4rem; border: 0; padding: 0; margin: 0; min-width: 0; }
.field > label, .field > legend {
  font-size: .92rem; font-weight: 500; color: var(--ink); padding: 0;
}
.req { color: var(--rosewood); margin-left: .15em; }

input[type="text"], input[type="email"], input[type="number"], select, textarea {
  font: inherit;
  width: 100%;
  padding: .75rem .9rem;
  color: var(--ink);
  background: var(--ground-alt);
  border: 1px solid var(--field-line);
  border-radius: 10px;
}
input:focus-visible, select:focus-visible, textarea:focus-visible { border-color: var(--rosewood); }
/* A short numeric dropdown shouldn't stretch the full width of the form. */
select {
  max-width: 9rem;
  appearance: none;
  /* Chevron drawn in the ink colour; single-quoted attrs so the url() survives. */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5' fill='none' stroke='%236A5B5F' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right .85rem center;
  padding-right: 2.2rem;
}
textarea { resize: vertical; }
input[aria-invalid="true"] { border-color: var(--rose-deep); background: #FFF7F8; }

.radio-row { display: grid; gap: .6rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr)); }
.radio-card {
  display: flex; align-items: center; gap: .6rem;
  padding: .85rem 1rem; cursor: pointer;
  background: var(--ground-alt);
  border: 1px solid var(--line); border-radius: 10px;
  font-size: .95rem;
}
.radio-card:hover { border-color: var(--blush); background: var(--blush-sub); }
.radio-card:has(input:checked) {
  border-color: var(--rosewood);
  background: var(--blush-sub);
  box-shadow: inset 0 0 0 1px var(--rosewood);
}
.radio-card input { accent-color: var(--rosewood); width: 1.1rem; height: 1.1rem; flex: none; }

.field-error { font-size: .85rem; color: var(--rose-deep); margin: 0; }
.form-note { font-size: .85rem; color: var(--ink-soft); text-align: center; margin: 0; }

/* Honeypot — off-screen, not display:none (some bots skip hidden fields). */
.hp {
  position: absolute; left: -9999px; top: auto;
  width: 1px; height: 1px; overflow: hidden;
}

.rsvp-result {
  border-radius: var(--radius);
  padding: 1.5rem;
  margin-bottom: 1.5rem;
  border: 1px solid var(--line);
  background: var(--ground-alt);
}
.rsvp-result h3 { font-size: 1.35rem; }
.rsvp-success { border-color: var(--sage); }
.rsvp-error { border-color: var(--rosewood); background: #FFF7F8; }

/* ── Contact + footer ─────────────────────────────────────────────────── */
.contact-phone { margin-top: 1.5rem; }
/* A phone number has to be transcribable at a glance — body face, not script. */
.phone-link {
  font-family: var(--font-body); font-weight: 500;
  font-size: clamp(1.4rem, 4.5vw, 1.9rem);
  text-decoration: none;
  border-bottom: 2px solid var(--blush);
  padding-bottom: .05em;
}
.phone-link:hover { border-color: var(--rosewood); }
.phone-local { display: block; font-size: .9rem; color: var(--ink-soft); margin-top: .6rem; }

/* The footer IS the thank-you now — the names were otherwise printed twice
   within a screen of each other. No top border: the page is one flat colour
   and the sprig does the separating. */
.site-footer {
  padding: clamp(3rem, 8vw, 5rem) 0 4rem;
}
.footer-date { color: var(--ink-soft); font-size: .92rem; margin-top: 1rem; }

/* ── Floral page edges ────────────────────────────────────────────────────
   Two fixed vines running the height of the window. The flowers are a data:
   URI, so their colours are baked in rather than read from the custom
   properties above — change them together if the palette moves.
   Only shown once the viewport is wide enough that they can't reach the
   content column (68rem of content + a gutter each side).                    */
.page-edge {
  position: fixed;
  top: 0; bottom: 0;
  width: 60px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='60' height='200' viewBox='0 0 60 200'%3E%3Cpath fill='%238A6A55' d='M30 0 C 43 32 17 68 30 100 C 43 132 17 168 30 200 L27.4 200 C 14.6 168 40.6 132 27.4 100 C 14.2 68 40.2 32 27.4 0 Z'/%3E%3Cpath fill='%238A6A55' d='M29 42 C 36 38 42 37 47 38 L47 35.8 C 41 34.8 34 36.2 27.6 40.4 Z'/%3E%3Cpath fill='%238A6A55' d='M29 148 C 22 144 16 143 11 144 L11 141.8 C 17 140.8 24 142.2 30.4 146.4 Z'/%3E%3Cellipse cx='46' cy='36' rx='7' ry='2.7' fill='%239CAF88' transform='rotate(-20 46 36)'/%3E%3Cellipse cx='12' cy='143' rx='6.5' ry='2.5' fill='%239CAF88' transform='rotate(20 12 143)'/%3E%3Cg transform='translate(30.56,12.56) scale(0.620)'%3E%3Cg fill='%23F2C3CB' stroke='%23D98FA0' stroke-width='.5'%3E%3Cpath d='M12 12.4 C 8.4 11.6 6.7 8.6 7.7 6 C 8.4 4.2 10.1 3.5 11.3 4.8 C 11.7 5.2 12.3 5.2 12.7 4.8 C 13.9 3.5 15.6 4.2 16.3 6 C 17.3 8.6 15.6 11.6 12 12.4 Z' transform='rotate(0 12 12)'/%3E%3Cpath d='M12 12.4 C 8.4 11.6 6.7 8.6 7.7 6 C 8.4 4.2 10.1 3.5 11.3 4.8 C 11.7 5.2 12.3 5.2 12.7 4.8 C 13.9 3.5 15.6 4.2 16.3 6 C 17.3 8.6 15.6 11.6 12 12.4 Z' transform='rotate(72 12 12)'/%3E%3Cpath d='M12 12.4 C 8.4 11.6 6.7 8.6 7.7 6 C 8.4 4.2 10.1 3.5 11.3 4.8 C 11.7 5.2 12.3 5.2 12.7 4.8 C 13.9 3.5 15.6 4.2 16.3 6 C 17.3 8.6 15.6 11.6 12 12.4 Z' transform='rotate(144 12 12)'/%3E%3Cpath d='M12 12.4 C 8.4 11.6 6.7 8.6 7.7 6 C 8.4 4.2 10.1 3.5 11.3 4.8 C 11.7 5.2 12.3 5.2 12.7 4.8 C 13.9 3.5 15.6 4.2 16.3 6 C 17.3 8.6 15.6 11.6 12 12.4 Z' transform='rotate(216 12 12)'/%3E%3Cpath d='M12 12.4 C 8.4 11.6 6.7 8.6 7.7 6 C 8.4 4.2 10.1 3.5 11.3 4.8 C 11.7 5.2 12.3 5.2 12.7 4.8 C 13.9 3.5 15.6 4.2 16.3 6 C 17.3 8.6 15.6 11.6 12 12.4 Z' transform='rotate(288 12 12)'/%3E%3C/g%3E%3Cpath d='M12 12 L12 7.4M12 12 L15.6 9.2M12 12 L14.6 15.2M12 12 L9.4 15.2M12 12 L8.4 9.2' stroke='%23E0B85F' stroke-width='.7' stroke-linecap='round' fill='none'/%3E%3Ccircle cx='12' cy='7.1' r='.85' fill='%23E0B85F'/%3E%3Ccircle cx='15.9' cy='9' r='.85' fill='%23E0B85F'/%3E%3Ccircle cx='14.8' cy='15.5' r='.85' fill='%23E0B85F'/%3E%3Ccircle cx='9.2' cy='15.5' r='.85' fill='%23E0B85F'/%3E%3Ccircle cx='8.1' cy='9' r='.85' fill='%23E0B85F'/%3E%3C/g%3E%3Cg transform='translate(11.36,65.36) scale(0.720)'%3E%3Cg fill='%23F2C3CB' stroke='%23D98FA0' stroke-width='.5'%3E%3Cpath d='M12 12.4 C 8.4 11.6 6.7 8.6 7.7 6 C 8.4 4.2 10.1 3.5 11.3 4.8 C 11.7 5.2 12.3 5.2 12.7 4.8 C 13.9 3.5 15.6 4.2 16.3 6 C 17.3 8.6 15.6 11.6 12 12.4 Z' transform='rotate(0 12 12)'/%3E%3Cpath d='M12 12.4 C 8.4 11.6 6.7 8.6 7.7 6 C 8.4 4.2 10.1 3.5 11.3 4.8 C 11.7 5.2 12.3 5.2 12.7 4.8 C 13.9 3.5 15.6 4.2 16.3 6 C 17.3 8.6 15.6 11.6 12 12.4 Z' transform='rotate(72 12 12)'/%3E%3Cpath d='M12 12.4 C 8.4 11.6 6.7 8.6 7.7 6 C 8.4 4.2 10.1 3.5 11.3 4.8 C 11.7 5.2 12.3 5.2 12.7 4.8 C 13.9 3.5 15.6 4.2 16.3 6 C 17.3 8.6 15.6 11.6 12 12.4 Z' transform='rotate(144 12 12)'/%3E%3Cpath d='M12 12.4 C 8.4 11.6 6.7 8.6 7.7 6 C 8.4 4.2 10.1 3.5 11.3 4.8 C 11.7 5.2 12.3 5.2 12.7 4.8 C 13.9 3.5 15.6 4.2 16.3 6 C 17.3 8.6 15.6 11.6 12 12.4 Z' transform='rotate(216 12 12)'/%3E%3Cpath d='M12 12.4 C 8.4 11.6 6.7 8.6 7.7 6 C 8.4 4.2 10.1 3.5 11.3 4.8 C 11.7 5.2 12.3 5.2 12.7 4.8 C 13.9 3.5 15.6 4.2 16.3 6 C 17.3 8.6 15.6 11.6 12 12.4 Z' transform='rotate(288 12 12)'/%3E%3C/g%3E%3Cpath d='M12 12 L12 7.4M12 12 L15.6 9.2M12 12 L14.6 15.2M12 12 L9.4 15.2M12 12 L8.4 9.2' stroke='%23E0B85F' stroke-width='.7' stroke-linecap='round' fill='none'/%3E%3Ccircle cx='12' cy='7.1' r='.85' fill='%23E0B85F'/%3E%3Ccircle cx='15.9' cy='9' r='.85' fill='%23E0B85F'/%3E%3Ccircle cx='14.8' cy='15.5' r='.85' fill='%23E0B85F'/%3E%3Ccircle cx='9.2' cy='15.5' r='.85' fill='%23E0B85F'/%3E%3Ccircle cx='8.1' cy='9' r='.85' fill='%23E0B85F'/%3E%3C/g%3E%3Cg transform='translate(34.04,109.04) scale(0.580)'%3E%3Cg fill='%23F2C3CB' stroke='%23D98FA0' stroke-width='.5'%3E%3Cpath d='M12 12.4 C 8.4 11.6 6.7 8.6 7.7 6 C 8.4 4.2 10.1 3.5 11.3 4.8 C 11.7 5.2 12.3 5.2 12.7 4.8 C 13.9 3.5 15.6 4.2 16.3 6 C 17.3 8.6 15.6 11.6 12 12.4 Z' transform='rotate(0 12 12)'/%3E%3Cpath d='M12 12.4 C 8.4 11.6 6.7 8.6 7.7 6 C 8.4 4.2 10.1 3.5 11.3 4.8 C 11.7 5.2 12.3 5.2 12.7 4.8 C 13.9 3.5 15.6 4.2 16.3 6 C 17.3 8.6 15.6 11.6 12 12.4 Z' transform='rotate(72 12 12)'/%3E%3Cpath d='M12 12.4 C 8.4 11.6 6.7 8.6 7.7 6 C 8.4 4.2 10.1 3.5 11.3 4.8 C 11.7 5.2 12.3 5.2 12.7 4.8 C 13.9 3.5 15.6 4.2 16.3 6 C 17.3 8.6 15.6 11.6 12 12.4 Z' transform='rotate(144 12 12)'/%3E%3Cpath d='M12 12.4 C 8.4 11.6 6.7 8.6 7.7 6 C 8.4 4.2 10.1 3.5 11.3 4.8 C 11.7 5.2 12.3 5.2 12.7 4.8 C 13.9 3.5 15.6 4.2 16.3 6 C 17.3 8.6 15.6 11.6 12 12.4 Z' transform='rotate(216 12 12)'/%3E%3Cpath d='M12 12.4 C 8.4 11.6 6.7 8.6 7.7 6 C 8.4 4.2 10.1 3.5 11.3 4.8 C 11.7 5.2 12.3 5.2 12.7 4.8 C 13.9 3.5 15.6 4.2 16.3 6 C 17.3 8.6 15.6 11.6 12 12.4 Z' transform='rotate(288 12 12)'/%3E%3C/g%3E%3Cpath d='M12 12 L12 7.4M12 12 L15.6 9.2M12 12 L14.6 15.2M12 12 L9.4 15.2M12 12 L8.4 9.2' stroke='%23E0B85F' stroke-width='.7' stroke-linecap='round' fill='none'/%3E%3Ccircle cx='12' cy='7.1' r='.85' fill='%23E0B85F'/%3E%3Ccircle cx='15.9' cy='9' r='.85' fill='%23E0B85F'/%3E%3Ccircle cx='14.8' cy='15.5' r='.85' fill='%23E0B85F'/%3E%3Ccircle cx='9.2' cy='15.5' r='.85' fill='%23E0B85F'/%3E%3Ccircle cx='8.1' cy='9' r='.85' fill='%23E0B85F'/%3E%3C/g%3E%3Cg transform='translate(11.08,168.08) scale(0.660)'%3E%3Cg fill='%23F2C3CB' stroke='%23D98FA0' stroke-width='.5'%3E%3Cpath d='M12 12.4 C 8.4 11.6 6.7 8.6 7.7 6 C 8.4 4.2 10.1 3.5 11.3 4.8 C 11.7 5.2 12.3 5.2 12.7 4.8 C 13.9 3.5 15.6 4.2 16.3 6 C 17.3 8.6 15.6 11.6 12 12.4 Z' transform='rotate(0 12 12)'/%3E%3Cpath d='M12 12.4 C 8.4 11.6 6.7 8.6 7.7 6 C 8.4 4.2 10.1 3.5 11.3 4.8 C 11.7 5.2 12.3 5.2 12.7 4.8 C 13.9 3.5 15.6 4.2 16.3 6 C 17.3 8.6 15.6 11.6 12 12.4 Z' transform='rotate(72 12 12)'/%3E%3Cpath d='M12 12.4 C 8.4 11.6 6.7 8.6 7.7 6 C 8.4 4.2 10.1 3.5 11.3 4.8 C 11.7 5.2 12.3 5.2 12.7 4.8 C 13.9 3.5 15.6 4.2 16.3 6 C 17.3 8.6 15.6 11.6 12 12.4 Z' transform='rotate(144 12 12)'/%3E%3Cpath d='M12 12.4 C 8.4 11.6 6.7 8.6 7.7 6 C 8.4 4.2 10.1 3.5 11.3 4.8 C 11.7 5.2 12.3 5.2 12.7 4.8 C 13.9 3.5 15.6 4.2 16.3 6 C 17.3 8.6 15.6 11.6 12 12.4 Z' transform='rotate(216 12 12)'/%3E%3Cpath d='M12 12.4 C 8.4 11.6 6.7 8.6 7.7 6 C 8.4 4.2 10.1 3.5 11.3 4.8 C 11.7 5.2 12.3 5.2 12.7 4.8 C 13.9 3.5 15.6 4.2 16.3 6 C 17.3 8.6 15.6 11.6 12 12.4 Z' transform='rotate(288 12 12)'/%3E%3C/g%3E%3Cpath d='M12 12 L12 7.4M12 12 L15.6 9.2M12 12 L14.6 15.2M12 12 L9.4 15.2M12 12 L8.4 9.2' stroke='%23E0B85F' stroke-width='.7' stroke-linecap='round' fill='none'/%3E%3Ccircle cx='12' cy='7.1' r='.85' fill='%23E0B85F'/%3E%3Ccircle cx='15.9' cy='9' r='.85' fill='%23E0B85F'/%3E%3Ccircle cx='14.8' cy='15.5' r='.85' fill='%23E0B85F'/%3E%3Ccircle cx='9.2' cy='15.5' r='.85' fill='%23E0B85F'/%3E%3Ccircle cx='8.1' cy='9' r='.85' fill='%23E0B85F'/%3E%3C/g%3E%3Cg transform='translate(39.04,53.04) scale(0.620)'%3E%3Cpath d='M8 15 C 4.6 13.4 3.4 9.6 5.2 6.6 C 6.2 4.9 9.8 4.9 10.8 6.6 C 12.6 9.6 11.4 13.4 8 15 Z' fill='%239CAF88'/%3E%3Cpath d='M8 4.2 C 6.4 4.2 5.3 5.6 5.6 7 C 6.8 5.9 9.2 5.9 10.4 7 C 10.7 5.6 9.6 4.2 8 4.2 Z' fill='%23F2C3CB'/%3E%3C/g%3E%3Cg transform='translate(10.60,99.60) scale(0.550)'%3E%3Cpath d='M8 15 C 4.6 13.4 3.4 9.6 5.2 6.6 C 6.2 4.9 9.8 4.9 10.8 6.6 C 12.6 9.6 11.4 13.4 8 15 Z' fill='%239CAF88'/%3E%3Cpath d='M8 4.2 C 6.4 4.2 5.3 5.6 5.6 7 C 6.8 5.9 9.2 5.9 10.4 7 C 10.7 5.6 9.6 4.2 8 4.2 Z' fill='%23F2C3CB'/%3E%3C/g%3E%3C/svg%3E");
  background-repeat: repeat-y;
  background-position: center top;
  background-size: 60px 200px;
  opacity: .5;
  pointer-events: none;
  z-index: 1;
}
.page-edge-left  { left: 0; }
.page-edge-right { right: 0; transform: scaleX(-1); }

@media (max-width: 80rem) {
  /* Not enough gutter to sit clear of the text — better none than crowding. */
  .page-edge { display: none; }
}

/* ── Flowers ──────────────────────────────────────────────────────────────
   One SVG sprite at the top of <body>; every instance is aria-hidden and
   purely decorative, so nothing here reaches the accessibility tree.        */
.sprite { display: none; }

.petals path {
  fill: var(--bloom);
  stroke: var(--bloom-line);
  stroke-width: .5;
}
.stamens path  { stroke: var(--bloom-heart); stroke-width: .7; stroke-linecap: round; fill: none; }
.stamens circle { fill: var(--bloom-heart); }
.bud-case { fill: var(--sage); }
.bud-tip  { fill: var(--bloom); }
.leaf ellipse { fill: var(--sage); }
/* Filled tapering path, not a uniform stroke — the taper is the whole point. */
.branch { fill: var(--branch); }

/* 囍 on the envelope: gold on red, which is exactly where it belongs. */
.envelope-xi {
  font-family: "Noto Serif SC", "PingFang SC", "Hiragino Sans GB", "Songti SC",
               "Microsoft YaHei", SimSun, serif;
  font-weight: 500;
  font-size: 34px;
  fill: #D8A24C;
}

/* The page's opening seal. The hero is the one place that gets this instead of
   the floral rule, so it reads as a mark rather than more decoration. */
.hero-xi {
  font-family: "Noto Serif SC", "PingFang SC", "Hiragino Sans GB", "Songti SC",
               "Microsoft YaHei", SimSun, serif;
  font-weight: 500;
  font-size: clamp(2rem, 5.5vw, 2.9rem);
  line-height: 1;
  color: var(--rosewood);
  margin: .5rem 0 1.1rem;
  /* Tight tracking would crowd the two halves of the character. */
  letter-spacing: 0;
}

/* Small floral rule under each section title. */
.divider {
  display: block;
  width: clamp(120px, 26vw, 180px);
  height: auto; aspect-ratio: 180 / 26;
  margin: .35rem auto 1.6rem;
  overflow: visible;
}

/* Corner sprays framing the hero. Sized off the viewport so they scale with
   the names rather than crowding them. */
.hero { position: relative; overflow: hidden; }
.hero-sprig {
  position: absolute;
  width: clamp(150px, 26vw, 320px);
  height: auto; aspect-ratio: 200 / 130;
  opacity: .5;
  pointer-events: none;
}
.hero-sprig-left  { left: -1.5rem; top: 1rem; transform: rotate(-6deg); }
.hero-sprig-right { right: -1.5rem; top: 1rem; transform: scaleX(-1) rotate(-6deg); }
@media (max-width: 46rem) {
  /* Behind the text at phone widths, so they frame rather than collide. */
  .hero-sprig { opacity: .32; top: -.5rem; }
  .hero-sprig-left  { left: -3.5rem; }
  .hero-sprig-right { right: -3.5rem; }
}

/* ── Photo ────────────────────────────────────────────────────────────── */
.photo-band { padding: 0 0 clamp(2.5rem, 7vw, 4rem); }

.photo-figure { margin: 0; display: inline-block; max-width: 100%; }

.photo-frame {
  /* Round portrait, the classic on wedding stationery, with a thin ring of the
     page colour inside a sage hairline so it reads as a frame not a crop.
     --photo-focus nudges which part of the picture survives the square crop:
     50% 50% is dead centre, lower percentages pull the crop upward. */
  /* The current photo is already square, so this has nothing to crop and no
     visible effect — it only matters if a non-square image is dropped in later. */
  /* A free-form cutout, so no fixed aspect ratio, no circle, no card. The
     picture's own silhouette is the shape; the page shows through around it. */
  width: clamp(250px, 70vw, 400px);
  margin-inline: auto;
}
.photo-frame img {
  width: 100%;
  height: auto;          /* free-form cutout: never crop it */
  display: block;
}

/* Shown through the frame if the photo is missing — app.js hides
   the broken <img> so this reads as intentional rather than as an error. */
.photo-frame.is-empty {
  aspect-ratio: 1;
  border-radius: 50%;
  background: repeating-linear-gradient(45deg, var(--blush-sub) 0 14px, var(--ground) 14px 28px);
}
.photo-figure figcaption {
  margin-top: 1rem;
  font-size: .9rem;
  color: var(--ink-soft);
  font-style: italic;
}

/* ── Lunar date ───────────────────────────────────────────────────────── */
.hero-lunar {
  margin-top: .35rem;
  font-size: .95rem;
  color: var(--sage-deep);
  font-style: italic;
}
.lunar-line {
  margin-top: -.4em;
  font-size: .9rem;
  color: var(--sage-deep);
  font-style: italic;
}

/* ── Mừng cưới / gift ─────────────────────────────────────────────────── */
.gift-card {
  display: grid;
  gap: 1.5rem;
  justify-items: center;
  background: var(--ground-alt);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 2rem 1.5rem;
  box-shadow: var(--shadow);
  margin-bottom: 1.25rem;
}
/* ── Envelope with the QR drawn out of it ─────────────────────────────────
   The envelope is painted OVER the QR, so at progress 0 the card is simply
   concealed behind it. As the section rises up the viewport the QR travels
   upward out of the top. The envelope is sized to be wider than the QR — if it
   weren't, the corners would poke out either side while "inside".            */
.envelope-stage {
  --qr-progress: 1;              /* default: fully out (no JS, or reduced motion) */
  position: relative;
  width: clamp(210px, 58vw, 250px);
  /* Headroom for the QR to rise into. */
  padding-top: clamp(180px, 46vw, 215px);
  margin-inline: auto;
}
.envelope {
  position: relative;
  z-index: 2;                    /* over the QR, so "inside" really is hidden */
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 120 / 160;
}

.qr-slide {
  position: absolute;
  z-index: 1;
  left: 50%;
  bottom: 14%;                   /* tucked down inside the envelope body */
  width: 76%;
  display: grid;
  justify-items: center;
  gap: .5rem;
  transform: translateX(-50%)
             translateY(calc(var(--qr-progress) * -100% - var(--qr-progress) * 42px));
  /* The caption is meaningless while the card is still in the envelope. */
  opacity: calc(.25 + var(--qr-progress) * .75);
}
.qr-frame {
  width: 100%;
  aspect-ratio: 1;
  display: grid; place-items: center;
  padding: 10px;
  background: #fff;                 /* scanners want maximum contrast */
  box-shadow: 0 6px 18px -8px rgba(62, 51, 54, .35);
  border: 1px solid var(--line);
  border-radius: 10px;
}
.qr-frame img { width: 100%; height: 100%; object-fit: contain; display: block; }
.qr-frame.is-empty {
  background: repeating-linear-gradient(45deg, var(--blush-sub) 0 10px, #fff 10px 20px);
}
.qr-caption { font-size: .85rem; color: var(--ink-soft); margin: 0; }

.pay-details {
  margin: 0; width: 100%; max-width: 22rem;
  display: grid; gap: .2rem .9rem;
  text-align: left;
}
.pay-details dt {
  font-size: .72rem; letter-spacing: .12em; text-transform: uppercase;
  color: var(--sage-deep); margin-top: .7rem;
}
.pay-details dd { margin: 0; }
/* Account numbers get copied by hand — keep them monospaced and selectable. */
.pay-value {
  display: block;
  font-variant-numeric: tabular-nums;
  font-size: 1.05rem; font-weight: 600; letter-spacing: .04em;
  color: var(--ink);
  user-select: all;
}
.pay-name { display: block; font-size: .85rem; color: var(--ink-soft); }

/* ── Travel (English only) ────────────────────────────────────────────── */
.travel-caveat {
  max-width: 42rem;
  margin: 1.75rem auto 0;
  text-align: center;
  font-size: .85rem;
  line-height: 1.75;
  color: var(--ink-soft);
}

/* ── Wishes ───────────────────────────────────────────────────────────── */
.wishes-grid {
  list-style: none; margin: 0 0 1.5rem; padding: 0;
  display: grid; gap: 1rem;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 17rem), 1fr));
}
.wish {
  background: var(--ground-alt);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.25rem;
  box-shadow: var(--shadow);
  break-inside: avoid;
}
.wish-text {
  font-family: var(--font-script); font-weight: 500;
  font-size: 1.15rem; line-height: 1.6;
  color: var(--ink);
  margin: 0 0 .75rem;
}
.wish-name {
  font-size: .82rem; letter-spacing: .1em; text-transform: uppercase;
  color: var(--sage-deep); margin: 0;
}
.wishes-empty { text-align: center; color: var(--ink-soft); margin-bottom: 1.5rem; }

/* ── Thank you ────────────────────────────────────────────────────────── */
.thanks { position: relative; overflow: hidden; }
.thanks-names { font-family: var(--font-display); }
.thanks-sprig {
  width: clamp(120px, 22vw, 190px);
  height: auto; aspect-ratio: 200 / 130;
  opacity: .45;
  margin: 0 auto .5rem;
  display: block;
}
.thanks-title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(2.6rem, 9vw, 4.2rem);
  line-height: 1.45;
  margin: 0 0 .2em;
  color: var(--rosewood);
}
.thanks-body { max-width: 34rem; margin-inline: auto; color: var(--ink); }
.thanks-sign { margin-top: 1.5rem; color: var(--ink-soft); font-style: italic; }
.thanks-names {
  font-family: var(--font-display);
  font-size: 2.4rem; line-height: 1.6;
  color: var(--rosewood); margin: 0;
}

.field-note { font-size: .82rem; color: var(--ink-soft); margin: 0; }

/* ── Narrow screens ───────────────────────────────────────────────────── */
@media (max-width: 40rem) {
  .countdown-sentence { line-height: 2.3; }
  .lang-btn span:not(.flag) { display: none; }   /* flags only; names return ≥40rem */
  .lang-btn { padding: .4rem .55rem; }
  .header-rsvp { display: none; }                /* hero CTA is right there */
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .cd-was { display: none !important; }
  .envelope-stage { --qr-progress: 1 !important; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    transition-duration: .001ms !important;
  }
}

/* ── Print ────────────────────────────────────────────────────────────────
   Guests do print these. Show BOTH languages, drop the chrome.             */
@media print {
  html[lang] [data-lang] { display: inline !important; }
  html[lang] p[data-lang], html[lang] div[data-lang] { display: block !important; }
  [data-lang="vi"] { font-style: italic; }

  .site-header, .hero-cta, .countdown, .rsvp-form, .rsvp-result,
  .skip-link, .map-placeholder, .map-links, .stay-link,
  .hero-sprig, .divider, .photo-band, .thanks-sprig, .envelope, .qr-frame,
  .wishes-grid, .wishes-empty, .page-edge { display: none !important; }

  body { background: #fff; color: #000; font-size: 11pt; }
  .section, .hero { padding: .75rem 0; border: 0; }
  .card { box-shadow: none; border-color: #ccc; break-inside: avoid; }
  h1, h2, h3, .phone-link { color: #000; }
  a { text-decoration: none; color: #000; }
}
