/* Kijin & Meganne — wedding invitation
   Rebuilt from the original design assets (May 2026).
   Decorative art is cropped out of layered SVGs exported on a shared
   810 x 1440 canvas; see .art below. */

/* Subsetted woff2 — regenerate with ./tools/subset-fonts.sh after any
   Korean text edit, or new characters will render as empty boxes.
   The ?v= hashes are written by that script; don't edit them by hand. They
   bust the fonts' 30-day cache, without which browsers keep serving an
   older subset that lacks any newly added characters. */
@font-face {
  font-family: "Gowun Batang";
  src: url("fonts/GowunBatang-Regular.woff2?v=f887cf3f") format("woff2");
  font-weight: 400; font-display: swap;
}
@font-face {
  font-family: "Gowun Batang";
  src: url("fonts/GowunBatang-Bold.woff2?v=a2cb26f2") format("woff2");
  font-weight: 700; font-display: swap;
}
@font-face {
  font-family: "Cormorant Garamond";
  src: url("fonts/CormorantGaramond.woff2?v=c14d933a") format("woff2");
  font-weight: 300 700; font-display: swap;
}

:root {
  --navy: #15074b;      /* bottom bar, script lettering */
  --blue: #25398b;      /* page arrows */
  --ink: #1d1d1b;       /* heart outline, body copy */
  --paper: #fff;
  --muted: #55555f;

  --canvas-w: 810;      /* the shared SVG export canvas */
  --canvas-h: 1440;

  --gap: 4px;
  --pad: 7.5%;
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: #e9e7e2;
  color: var(--ink);
  /* Cormorant carries no Hangul, so Korean glyphs fall through to Gowun
     Batang automatically. app.js sets <html lang>, which flips the primary
     face so each language leads with its own typeface. */
  font-family: "Cormorant Garamond", "Gowun Batang", Georgia, serif;
  line-height: 1.5;
  /* Cormorant ships old-style figures, where 3 4 5 7 9 hang well below the
     baseline. That's for lowercase running text — here the digits sit in
     caps and beside Hangul, where they just look like they're falling off
     the line. Force lining figures everywhere. */
  font-variant-numeric: lining-nums;
  font-feature-settings: "lnum" 1;
}

html[lang="ko"] body {
  font-family: "Gowun Batang", "Cormorant Garamond", Georgia, serif;
}

/* ---------- phone frame ---------- */

.phone {
  position: relative;
  max-width: 430px;
  margin: 0 auto;
  min-height: 100svh;
  background: var(--paper);
  box-shadow: 0 0 40px rgba(0, 0, 0, .09);
  overflow: hidden;
}

/* ---------- language toggle ---------- */

.lang {
  position: absolute;
  top: 14px; left: 0; right: 0;
  z-index: 5;
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  letter-spacing: .04em;
  color: var(--muted);
}
.lang button {
  border: 0;
  background: none;
  padding: 4px 2px;
  font: inherit;
  color: inherit;
  cursor: pointer;
  border-bottom: 1px solid transparent;
}
.lang button[aria-pressed="true"] {
  color: var(--navy);
  border-bottom-color: var(--navy);
}

/* ---------- invitation ----------
   One continuous scroll. Both former pages are stacked here: the heart/script
   header runs once at the top, the couple name + car + navy bar once at the
   bottom. */

.invite {
  display: flex;
  flex-direction: column;
  min-height: 100svh;
}

/* app.js holds the page at opacity 0 until the images are in, then adds
   .revealed so everything arrives together instead of piecemeal. The
   keyframe overrides that inline opacity and settles on 1. The hidden state
   is never set in CSS, so if the script doesn't run the page still shows. */
.invite.revealed {
  animation: invite-in 650ms ease forwards;
}
@keyframes invite-in {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .invite.revealed { animation: none; }
}

/* ---------- cropped SVG art ----------
   Each source SVG is the full 810x1440 canvas with one element positioned
   on it. We window onto that element with a crop rect (--cx/--cy/--cw/--ch,
   in canvas units) so the art keeps its vector crispness. */

.art {
  position: relative;
  overflow: hidden;
  aspect-ratio: calc(var(--cw) / var(--ch));
  flex: none;
}
/* `> svg` covers the heart once app.js swaps the <img> for an inline SVG. */
.art img,
.art > svg {
  position: absolute;
  max-width: none;
  width: calc(var(--canvas-w) / var(--cw) * 100%);
  height: calc(var(--canvas-h) / var(--ch) * 100%);
  left: calc(-1 * var(--cx) / var(--cw) * 100%);
  top: calc(-1 * var(--cy) / var(--ch) * 100%);
}

/* ---------- header animation ----------
   The heart draws itself anti-clockwise (the path's own direction) while the
   script lettering fades in behind it. Starting values are set inline by
   app.js; these rules only run the animation. Nothing is hidden by CSS alone,
   so a failed SVG swap still leaves a fully visible header. */

.header-art.play > svg.heart {
  animation: heart-appear 700ms ease forwards;
}
.header-art.play > svg.heart path[stroke] {
  animation: heart-draw 2600ms cubic-bezier(.42, .02, .35, 1) forwards;
}
.header-art.play .script {
  animation: script-fade 1300ms ease 900ms forwards;
}

@keyframes heart-appear { from { opacity: .2; } to { opacity: 1; } }
@keyframes heart-draw   { to { stroke-dashoffset: 0; } }
@keyframes script-fade  { to { opacity: 1; } }

@media (prefers-reduced-motion: reduce) {
  .header-art.play > svg.heart,
  .header-art.play > svg.heart path[stroke],
  .header-art.play .script {
    animation: none;
  }
}

/* header: heart outline + "We have Just Married" script, two stacked layers.
   The top margin clears the absolutely-positioned language toggle with room
   to spare — the heart's first stroke starting right under it looked cramped. */
.header-art {
  --cx: 155; --cy: 82; --cw: 552; --ch: 385;
  width: 84%;
  margin: 92px auto 0;
}

@media (max-width: 380px) {
  .header-art { margin-top: 78px; }
}

/* ---------- directions ----------
   A button through to the venue's own location page, with the map apps
   beneath it. Replaced the embedded map: the venue's widget is http-only
   with an expired certificate, so it could not be framed here. */

.directions {
  margin: 26px 0 0;
  text-align: center;
}

.btn {
  display: inline-block;
  padding: 11px 26px;
  border: 1px solid var(--navy);
  border-radius: 999px;
  color: var(--navy);
  font-size: 16px;
  letter-spacing: .02em;
  text-decoration: none;
  transition: background-color .18s ease, color .18s ease;
}
.btn:hover,
.btn:focus-visible {
  background: var(--navy);
  color: #fff;
}

/* RSVP — the one thing on the page we're asking guests to act on, so it's
   filled rather than outlined. English only. */
.rsvp {
  margin: 30px 0 0;
  text-align: center;
}
.btn-primary {
  background: var(--navy);
  color: #fff;
  padding: 13px 40px;
  font-size: 17px;
  letter-spacing: .06em;
}
.btn-primary:hover,
.btn-primary:focus-visible {
  background: #0d0430;
  color: #fff;
}

.mapapps {
  display: flex;
  justify-content: center;
  gap: 30px;
  margin: 20px 0 0;
}
.mapapps a {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 7px;
  color: var(--muted);
  font-size: 13px;
  text-decoration: none;
  letter-spacing: .01em;
}
.mapapps img {
  display: block;
  width: 30px;
  height: 30px;
  object-fit: contain;
}
.mapapps a:hover span,
.mapapps a:focus-visible span { color: var(--navy); }

@media (prefers-reduced-motion: reduce) {
  .btn { transition: none; }
}

.car-art {
  --cx: 542; --cy: 1216.5; --cw: 187; --ch: 113.5;
  width: 33%;
  margin-left: auto;
  margin-right: 6%;
}

/* ---------- greeting ----------
   Sits between the header art and the first photo strip. Generous leading —
   it's three lines of verse, not body copy, and the Korean especially wants
   the air. */

.greeting {
  margin: 34px auto 4px;
  padding: 0 var(--pad);
  text-align: center;
  font-size: 16px;
  line-height: 2;
  color: var(--muted);
  text-wrap: balance;
}

html[lang="ko"] .greeting { font-size: 15px; }

@media (max-width: 380px) {
  .greeting { font-size: 15px; line-height: 1.9; }
  html[lang="ko"] .greeting { font-size: 14px; }
}

/* ---------- photo strip ----------
   Source widths 250 / 304 / 212 at a shared height of 304, so proportional
   flex on a zero basis reproduces the original ribbon exactly. */

.photos {
  display: flex;
  gap: var(--gap);
  margin: 40px 0 0;
}
.photos img {
  display: block;
  height: auto;
  min-width: 0;
}
.photos img:nth-child(1) { flex: 250 1 0; }
.photos img:nth-child(2) { flex: 304 1 0; }
.photos img:nth-child(3) { flex: 212 1 0; }

/* ---------- body copy ---------- */

.body {
  flex: 1;
  padding: 0 var(--pad);
  text-align: center;
}

.when {
  margin: 42px 0 0;
  font-size: 20px;
  line-height: 1.45;
  letter-spacing: .01em;
}
.when .stamp {
  display: block;
  margin-top: 6px;
  font-size: 18px;
  color: var(--muted);
}

.where {
  margin: 38px 0 0;
  font-size: 19px;
  line-height: 1.5;
}
.where .label {
  display: block;
  margin-bottom: 4px;
  letter-spacing: .06em;
}
.where .hall { display: block; }
.where .addr {
  display: block;
  color: var(--muted);
}

/* Parents. The two names stack; the relation line sits vertically centred
   beside them. The groom and bride blocks stack rather than sitting side by
   side — the relation line is too long now to fit two across on a phone. */
.parents {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  margin: 40px 0 0;
  font-size: 17px;
}
.parent {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
}
.parent .relation {
  color: var(--muted);
  font-size: 15px;
  white-space: nowrap;
}
.parent .child { white-space: nowrap; }
.parent .names {
  display: flex;
  flex-direction: column;
  line-height: 1.35;
  white-space: nowrap;
  text-align: left;
}

.couple {
  margin: 46px 0 0;
  font-size: 30px;
  letter-spacing: .02em;
}

/* ---------- page 2 blocks ---------- */

/* <h2> defaults to bold, which on Cormorant's 300–700 axis lands far heavier
   than the body and reads as a different typeface. Match the body weight and
   let size and tracking carry the heading instead.
   Korean keeps the bold — Gowun ships a real Bold cut, and it sits right. */
.section-title {
  margin: 40px 0 16px;
  font-family: inherit;
  font-weight: 400;
  font-size: 19px;
  letter-spacing: .08em;
}

html[lang="ko"] .section-title {
  font-weight: 700;
  letter-spacing: .04em;
}

.accounts {
  display: flex;
  flex-direction: column;
  gap: 12px;
  font-size: 17px;
}
.account {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  flex-wrap: wrap;
}
.accounts .who { font-weight: 700; }
/* Both keywords: font-variant-numeric isn't additive, so declaring only
   tabular-nums here would drop the inherited lining-nums and bring the
   old-style figures back on exactly the numbers that matter most. */
.accounts .num { font-variant-numeric: lining-nums tabular-nums; }

.copy {
  border: 1px solid #d3d1cb;
  border-radius: 999px;
  background: none;
  padding: 3px 11px;
  font: inherit;
  font-size: 12px;
  line-height: 1.5;
  color: var(--muted);
  cursor: pointer;
  white-space: nowrap;
  transition: border-color .18s ease, color .18s ease;
}
.copy:hover,
.copy:focus-visible { border-color: var(--navy); color: var(--navy); }
.copy.copied {
  border-color: var(--navy);
  background: var(--navy);
  color: #fff;
}

@media (prefers-reduced-motion: reduce) {
  .copy { transition: none; }
}

.note {
  margin: 18px 0 0;
  font-size: 16px;
  line-height: 1.55;
  color: var(--muted);
}

/* Centred and flush to its heading — it used to be a left-aligned orphan
   paragraph with its own top margin, which read as unbalanced once a centred
   Dress Code heading sat above it. */
.dress {
  margin: 0;
  font-size: 16px;
  line-height: 1.55;
  text-align: center;
  text-wrap: balance;
}

/* ---------- footer / navigation ---------- */

.foot {
  position: relative;
  margin-top: 52px;
  padding: 0 var(--pad);
}

/* The couple name is the closing line now that the page arrows are gone,
   so it centres rather than sharing a row with a nav control. */
.foot .couple {
  margin-top: 0;
  text-align: center;
}

.bar {
  height: 15px;
  background: var(--navy);
  margin-top: 10px;
}

@media (max-width: 380px) {
  .when { font-size: 18px; }
  .where { font-size: 17px; }
  .couple { font-size: 26px; }
  .parents { gap: 22px; }
}
