/* =========================================================================
   Rossa & Augustine — round 4
   Chunk 1/6 — tokens, reset, base type, utilities

   Round 4 DAY palette: paper gold + sunlit wisteria on warm cream paper,
   with soft-sky bands for countdown and colophon. Corona kingdom by day:
   nothing emits light, everything is lit. Sage recedes to a supporting
   botanical tint inside artwork only. Every text/background pair below was
   measured; ratios are recorded in DAY-NOTES.md.
   ========================================================================= */

:root{
  /* Wisteria takes the structural accent role sage used to hold.
     The token names stay put so the whole sheet does not have to churn. */
  --sage:#6b53a0;        /* wisteria in sun     5.62:1 on cream */
  --sage-deep:#4f3d7a;   /* lilac shade         8.31:1 on cream */
  --sage-soft:#ece5f7;   /* lilac wash — SURFACE tint, never text */
  --sage-line:#c3b2dd;   /* lilac hairline, decorative only */
  --cream:#f6f3ec;
  --cream-2:#efe9dd;
  --ink:#332f3a;         /* ink, warmed toward violet 11.78:1 on cream */
  --ink-soft:#514761;    /*                      7.82:1 on cream */
  --white:#fffdf9;
  --line:#ded5cb;
  --accent:#8c5a0f;      /* paper gold, text-safe    5.29:1 on cream */
  --accent-glow:#e8c98a; /* sunlit gold, light-only (never text) */
  --lantern:#7a5410;     /* paper gold on sky        5.35:1 on --dusk */

  /* Soft daylight sky — the midday band. Countdown + colophon.
     Token names retained so the sheet does not churn. */
  --dusk:#dbe6f2;
  --dusk-2:#e8eef5;

  /* Checked pairs; see DAY-NOTES.md. */
  --on-sage:#fffdf9;     /* 9.06:1 on --sage-deep */
  --on-deep:#332f3a;     /* 11.18:1 on --dusk-2   */

  --serif:'Cormorant Garamond','Apple Garamond',Garamond,'Times New Roman',serif;
  --script:'Parisienne','Snell Roundhand','Apple Chancery',cursive;
  /* Korean: soft, warm, handwriting-adjacent myeongjo first. The first three
     are not yet self-hosted — naming them here means dropping the woff2 files
     in later needs no CSS change. macOS today lands on Apple Myungjo /
     AppleMyungjo, then Apple SD Gothic Neo. Noto Serif KR is demoted to a
     late fallback: it is the stiff institutional face the couple disliked. */
  --kr:'Nanum Myeongjo','Gowun Batang','KoPub Batang','AppleMyungjo','Apple Myungjo',
       'Apple SD Gothic Neo','Malgun Gothic','Noto Serif KR',serif;

  --ease:cubic-bezier(.22,.61,.36,1);
  --reveal:.9s;
  --ui:.35s;

  --gut:6vw;
  --sec:clamp(70px,11vw,140px);
  --card-pad:clamp(28px,5vw,56px);
  --measure:64ch;

  /* Daylight shadows: cast, not emitted. Cooler and shallower than the
     night sheet's bloom-adjacent drops. */
  --shadow-card:0 10px 28px rgba(79,61,122,.10);
  --shadow-lift:0 4px 14px rgba(79,61,122,.20);
  --shadow-deep:0 20px 54px rgba(79,61,122,.20);
}

*,*::before,*::after{box-sizing:border-box}
html,body,h1,h2,h3,h4,p,ul,ol,li,figure,blockquote,fieldset,legend{margin:0;padding:0}
ul,ol{list-style:none}
html{-webkit-text-size-adjust:100%}
@media (prefers-reduced-motion:no-preference){html{scroll-behavior:smooth}}

body{
  font-family:var(--serif);
  font-size:18px;
  line-height:1.6;
  color:var(--ink);
  background:var(--cream);
  overflow-x:hidden;
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
}
body.is-loading{opacity:1}
body.is-locked{overflow:hidden}

img,svg{display:block;max-width:100%}
a{color:inherit;text-decoration:none}
button{font:inherit;color:inherit;background:none;border:none;cursor:pointer}
input,select,textarea{font:inherit;color:inherit}

/* ── Korean typography ───────────────────────────────────────────────────
   Round 4. The complaint was "딱딱한 느낌" — stiff. Four levers, no webfont:
   1. family order  — soft myeongjo first (see --kr)
   2. weight 300    — lighter stroke than the default 400 Noto Serif KR
   3. leading 1.9   — Hangul syllable blocks want far more air than Latin
   4. keep-all      — no mid-word breaks, which is what made it read as blocky
   Plus a ~4% optical reduction so Hangul does not out-size Cormorant. */
html[lang="ko"] body,
html[lang="ko"] .script,
[lang="ko"]{
  font-family:var(--kr);
  font-weight:400;
  font-size:1.02em;
  line-height:1.9;
  letter-spacing:.005em;
  word-break:keep-all;
  overflow-wrap:break-word;
  font-optical-sizing:auto;
}
html[lang="ko"] body{font-size:18.5px}
html[lang="ko"] p,
html[lang="ko"] li,
html[lang="ko"] dd{line-height:1.92;word-break:keep-all}
/* Headings keep-all too, but tighter leading so they do not fall apart. */
html[lang="ko"] h1,
html[lang="ko"] h2,
html[lang="ko"] h3,
html[lang="ko"] .section__title,
html[lang="ko"] .plate__title{
  font-weight:400;line-height:1.45;letter-spacing:0;word-break:keep-all;
}
html[lang="ko"] strong,
html[lang="ko"] b{font-weight:700}
html[lang="ko"] .no-kr{font-family:var(--serif);font-weight:400;font-size:1em;line-height:1.6}
/* The script face has no Hangul; Korean display type falls back to the
   Korean serif — lighter and looser, never tofu. */
html[lang="ko"] .script{letter-spacing:.015em;font-weight:400;line-height:1.5}

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

.skip-link{
  position:absolute;left:12px;top:-100px;z-index:200;
  background:var(--white);color:var(--ink);
  padding:.7em 1.2em;border-radius:100px;border:1.5px solid var(--sage);
  box-shadow:var(--shadow-card);transition:top var(--ui) var(--ease);
}
.skip-link:focus{top:12px}

:focus-visible{
  outline:2.5px solid var(--sage-deep);
  outline-offset:3px;
  border-radius:4px;
}
.on-dark :focus-visible,
.envelope :focus-visible,
.menu :focus-visible,
.colophon :focus-visible{outline-color:var(--sage-deep)}

.noscript{padding:14vh var(--gut);text-align:center;max-width:36em;margin:0 auto}
.noscript p{margin-bottom:1em}
.noscript form{display:grid;gap:.75rem;text-align:left;margin:1.5rem auto 0;max-width:24rem}
.noscript input{width:100%;min-height:48px;padding:.7rem .85rem;border:1px solid var(--line);border-radius:2px;background:var(--white);color:var(--ink);font:inherit;text-transform:uppercase;letter-spacing:.16em}
.noscript [role="alert"]{color:#8a3d2a;font-weight:600}

/* Shown when the content payload fails to load. Same shape as .noscript:
   this is the other way a guest can end up with nothing to read. */
.loaderr{padding:14vh var(--gut);text-align:center;max-width:36em;margin:0 auto}
.loaderr__title{font-size:clamp(1.5rem,4vw,2rem);font-weight:400;line-height:1.3;color:var(--ink)}
.loaderr__body{margin:1em 0 1.8em;color:var(--ink-soft);line-height:1.75}

/* =========================================================================
   Chunk 2/6 — buttons, rules, reveal, envelope intro
   ========================================================================= */

.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:.5em;
  font-family:inherit;font-size:1rem;letter-spacing:.06em;
  padding:.85em 1.8em;border-radius:100px;white-space:normal;text-align:center;
  min-height:48px;cursor:pointer;
  transition:background var(--ui) var(--ease),color var(--ui) var(--ease),
             transform var(--ui) var(--ease),box-shadow var(--ui) var(--ease);
}
.btn--solid{background:var(--sage-deep);color:var(--on-sage);box-shadow:var(--shadow-lift)}
.btn--solid:hover{background:#3f2f63;transform:translateY(-2px);box-shadow:0 8px 20px rgba(79,61,122,.26)}
.btn--outline{border:1.5px solid var(--ink);color:var(--ink)}
.btn--outline:hover{background:var(--ink);color:var(--cream)}
.btn--soft{background:var(--cream-2);color:var(--ink);border:1px solid var(--line)}
.btn--soft:hover{background:var(--sage-deep);color:var(--on-sage);border-color:var(--sage-deep)}
.btn--ghost{color:var(--ink-soft);text-decoration:underline;text-underline-offset:.3em;padding:.6em 1em}
.btn--ghost:hover{color:var(--ink)}
.btn[disabled]{opacity:.55;cursor:not-allowed;transform:none;box-shadow:none}
.btn--wide{width:100%}

.eyebrow{
  font-size:.8rem;letter-spacing:.28em;text-transform:uppercase;
  color:var(--sage-deep);font-family:var(--serif);
}
html[lang="ko"] .eyebrow{letter-spacing:.18em;font-size:.78rem}

.rule{height:1px;background:var(--line);border:0}
.rule--short{width:64px;margin:0 auto}

/* Reveal — genuinely off under reduced motion (see chunk 6). */
[data-reveal]{opacity:0;transform:translateY(28px);
  transition:opacity var(--reveal) var(--ease),transform var(--reveal) var(--ease)}
[data-reveal].in{opacity:1;transform:none}

/* ── Envelope intro ─────────────────────────────────────────────────────
   old3 opened with a modal gate. Kept as an opening *moment*, but it is a
   real dialog: focus-trapped, Escape-closable, dismissed state remembered,
   and the page beneath is inert only while it is open.                    */
.envelope{position:fixed;inset:0;z-index:150;display:grid;place-items:center;padding:24px}
.envelope[hidden]{display:none}
.envelope__scrim{position:absolute;inset:0;background:rgba(79,61,122,.28);backdrop-filter:blur(6px)}
.envelope__card{
  position:relative;z-index:1;
  width:min(440px,100%);max-height:calc(100dvh - 48px);overflow:auto;
  background:var(--white);border-radius:20px;
  padding:clamp(32px,6vw,48px) clamp(24px,5vw,40px);
  text-align:center;box-shadow:var(--shadow-deep);
  animation:env-in .7s var(--ease) both;
}
@keyframes env-in{from{opacity:0;transform:scale(.94) translateY(18px)}to{opacity:1;transform:none}}
.envelope__rule{height:1px;background:var(--line);margin:0 auto;width:56px}
.envelope .eyebrow{margin:1.4em 0 .8em}
.envelope__recipient.is-personalized{
  max-width:100%;overflow-wrap:anywhere;text-wrap:balance;
  text-transform:none;letter-spacing:.12em;
}
.envelope__monogram{
  margin:0 auto 1.1em;color:var(--sage-deep);
}
.mono{display:block;line-height:0}
.mono__image{display:block;width:100%;height:100%;object-fit:contain}
.envelope__monogram .mono__image{width:76px;height:76px;margin:0 auto}
.envelope__title{font-family:var(--script);font-size:clamp(1.5rem,6.6vw,2.9rem);
  font-weight:400;line-height:1.3;margin-bottom:.25em;
  white-space:nowrap;font-synthesis:none;font-kerning:normal;
  -webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;
  padding-bottom:.1em}
html[lang="ko"] .envelope__title{white-space:nowrap;line-height:1.4;
  -webkit-font-smoothing:auto;-moz-osx-font-smoothing:auto}
.envelope__date{font-size:.85rem;letter-spacing:.24em;text-transform:uppercase;
  color:var(--ink-soft);margin-bottom:1.2em}
html[lang="ko"] .envelope__date{letter-spacing:.1em;text-transform:none}
.envelope__body{color:var(--ink-soft);margin-bottom:1.5em;line-height:1.75}
/* Language is chosen here, before the invitation opens: the guest picks a
   language rather than discovering a switch later. Same control, same
   storage key as the header switch. */
.envelope__langlabel{font-size:.72rem;letter-spacing:.2em;text-transform:uppercase;
  color:var(--ink-soft);margin-bottom:.7em}
html[lang="ko"] .envelope__langlabel{letter-spacing:.08em;text-transform:none;font-size:.85rem}
.langswitch--env{display:inline-flex;margin-bottom:1.6em}
.langswitch--env button{padding:.6em 1.25em;font-size:.85rem;min-height:44px}
.envelope__enter{width:100%;margin-bottom:1.6em}

/* =========================================================================
   Chunk 3/6 — chrome, menu, hero, section frame
   ========================================================================= */

.chrome{position:fixed;top:0;left:0;right:0;z-index:60;transition:background var(--ui),box-shadow var(--ui)}
.chrome.is-scrolled{background:rgba(246,243,236,.94);backdrop-filter:blur(10px);
  box-shadow:0 1px 0 var(--line)}
.chrome__bar{display:flex;align-items:center;justify-content:space-between;
  gap:12px;padding:14px var(--gut);max-width:1440px;margin:0 auto}
.chrome__mark{display:inline-flex;align-items:center;gap:.7em;min-height:44px;padding:.2em 0}
.chrome__mark-glyph{display:grid;place-items:center;width:44px;height:44px;padding:3px;
  border-radius:50%;background:rgba(255,253,249,.92);box-shadow:0 1px 8px rgba(48,37,70,.12)}
.chrome__mark-glyph .mono__image{width:38px;height:38px}
.chrome__mark-text{font-size:.72rem;letter-spacing:.22em;text-transform:uppercase;color:var(--ink-soft)}
html[lang="ko"] .chrome__mark-text{letter-spacing:.08em;text-transform:none}
.chrome__tools{display:flex;align-items:center;gap:10px}

.langswitch{display:inline-flex;border:1px solid var(--line);border-radius:100px;
  background:var(--white);overflow:hidden}
.langswitch button{padding:.5em .95em;font-size:.78rem;letter-spacing:.1em;
  color:var(--ink-soft);min-height:40px;transition:background var(--ui),color var(--ui)}
.langswitch button[aria-pressed="true"]{background:var(--sage-deep);color:var(--on-sage)}
.langswitch button:not([aria-pressed="true"]):hover{background:var(--cream-2);color:var(--ink)}

.chrome__menu{display:inline-flex;align-items:center;gap:.6em;
  border:1px solid var(--line);background:var(--white);border-radius:100px;
  padding:.5em 1.05em;min-height:40px;font-size:.78rem;letter-spacing:.18em;text-transform:uppercase}
html[lang="ko"] .chrome__menu{letter-spacing:.06em;text-transform:none}
.chrome__menu-bars{display:inline-flex;flex-direction:column;gap:4px;width:16px}
.chrome__menu-bars i{display:block;height:1.5px;background:var(--ink);
  transition:transform var(--ui) var(--ease),opacity var(--ui) var(--ease)}
.chrome__menu[aria-expanded="true"] .chrome__menu-bars i:first-child{transform:translateY(2.75px) rotate(45deg)}
.chrome__menu[aria-expanded="true"] .chrome__menu-bars i:last-child{transform:translateY(-2.75px) rotate(-45deg)}

/* Full-bleed menu, old3's script-set link stack — but as a real nav list. */
.menu{position:fixed;inset:0;z-index:70;background:var(--cream);
  display:grid;place-items:safe center;padding:80px 6vw 40px;overflow:auto;
  /* `place-items:center` alone is the bug: when the link stack is taller than
     the viewport, a centred grid item overflows in BOTH directions and the
     overflow above the container is unreachable — the scroll range starts at
     the container's top edge, so the first menu links are simply cut off.
     `safe` degrades to start-alignment exactly in that case, which is the
     whole fix. `-webkit-overflow-scrolling` keeps the scroll usable on iOS.
     `100dvh` rather than relying on `inset:0` alone: on mobile the collapsing
     URL bar changes the visual viewport mid-scroll, which is why this showed
     up only when the page was already scrolled. */
  height:100dvh;max-height:100dvh;-webkit-overflow-scrolling:touch}
.menu[hidden]{display:none}
.menu__inner{text-align:center;max-width:520px;width:100%}
.menu__flourish{color:var(--sage);margin:0 auto .8em;width:64px}
.menu__list{display:flex;flex-direction:column;gap:.35em;margin-bottom:2.2em}
.menu__list a{display:inline-block;font-family:var(--script);
  font-size:clamp(1.9rem,7vw,2.6rem);line-height:1.35;padding:.1em .4em;
  transition:color var(--ui) var(--ease)}
.menu__list a:hover{color:var(--sage-deep)}
html[lang="ko"] .menu__list a{font-size:clamp(1.5rem,5.5vw,1.9rem)}
.menu__foot{font-style:italic;font-size:.9rem;letter-spacing:.14em;color:var(--ink-soft)}
html[lang="ko"] .menu__foot{letter-spacing:.04em;font-style:normal}

/* ── Hero ─────────────────────────────────────────────────────────────── */
.hero{position:relative;min-height:100svh;display:flex;flex-direction:column;
  align-items:center;justify-content:center;text-align:center;
  padding:130px var(--gut) 96px;overflow:hidden;color:var(--ink)}
.hero__art{position:absolute;inset:0;z-index:0}
.hero__art svg{width:100%;height:100%;object-fit:cover}
/* A photograph in the hero bleed. The rule above sizes an <svg> child only,
   so a <picture> arrived with no dimensions and the hero rendered empty. */
.hero__art--photo picture{display:block;width:100%;height:100%}
.hero__art--photo img{width:100%;height:100%;object-fit:cover;display:block}
.hero__veil{position:absolute;inset:0;z-index:1;
  background:linear-gradient(180deg,rgba(255,253,249,.62),rgba(255,253,249,.80))}
/* ── Hero with a photograph: stacked, not overlaid ────────────────────
   The overlaid layout needs a white veil to keep the copy legible, and the
   veil is what was bleaching the picture — lighten it and the words go, darken
   it and the photograph goes. There is no setting that satisfies both, so the
   two stop competing for the same pixels: the photograph gets the top of the
   screen at full strength, the words sit on cream underneath it.

   The bleed layout is kept for the drawing (no photo, nothing to bleach). */
.hero:has(.hero__art--photo){
  display:block;
  min-height:0;
  padding:0 0 clamp(56px,7vw,88px);
  background:var(--cream)}
/* Height is capped in vh as well as by ratio so the copy is never pushed off
   a short laptop screen. 4:5 source, so the frame stays portrait on phones
   and lets the crop breathe on desktop. */
.hero:has(.hero__art--photo) .hero__art{
  position:relative;
  inset:auto;
  width:100%;
  aspect-ratio:4/5;
  max-height:68svh;
  overflow:hidden}
@media (min-width:900px){
  /* 76svh put the names below the fold on a 900px-tall laptop: the frame ate
     684px and the title started at 860. Capped so monogram + names + date all
     land above it, measured rather than guessed. */
  .hero:has(.hero__art--photo) .hero__art{aspect-ratio:16/10;max-height:52svh}
}
/* Approved focal points remain explicit even though both responsive files are
   pre-cropped to their actual frame ratios. */
.hero:has(.hero__art--photo) .hero__art--photo img{object-position:50% 55%}
@media (min-width:900px){
  .hero:has(.hero__art--photo) .hero__art--photo img{object-position:50% 54%}
}
/* No veil over a photograph that nothing is written on. */
.hero:has(.hero__art--photo) .hero__veil{display:none}
/* The chrome is transparent until scroll, which was fine over a pale drawing
   and is not over a photograph: the wordmark and language links sat in ink
   purple on dark eaves. A soft top scrim, only while a photo is behind it. */
.hero:has(.hero__art--photo) ~ .chrome:not(.is-scrolled),
body:has(.hero__art--photo) .chrome:not(.is-scrolled){
  background:linear-gradient(180deg,rgba(255,253,249,.92),rgba(255,253,249,.55) 70%,rgba(255,253,249,0));
  backdrop-filter:blur(3px)}
.hero:has(.hero__art--photo) .hero__center{
  padding:clamp(30px,5vw,48px) var(--gut) 0;
  margin-inline:auto}
/* The monogram was a lockup against the photograph; stacked, it reads as a
   seam between picture and words. */
.hero:has(.hero__art--photo) .hero__monogram{
  margin-top:-.4em;
  background:var(--cream);
  box-shadow:none}
.hero__center{position:relative;z-index:2;display:flex;flex-direction:column;
  align-items:center;max-width:780px;width:100%}
.hero__monogram{width:82px;height:82px;border:1.5px solid var(--sage-line);
  border-radius:50%;display:grid;place-items:center;margin-bottom:1.3em;
  color:var(--sage-deep);padding:15px;
  box-shadow:var(--shadow-lift);background:rgba(255,253,249,.55)}
.hero__monogram .mono__image{width:100%;height:100%}
.hero__eyebrow{font-size:.82rem;letter-spacing:.34em;text-transform:uppercase;
  color:var(--sage-deep);opacity:1;margin-bottom:.7em}
html[lang="ko"] .hero__eyebrow{letter-spacing:.16em;text-transform:none}
.hero__title{font-family:var(--script);font-weight:400;line-height:1.18;
  font-size:clamp(1.6rem,7.4vw,7.5rem);text-shadow:none;
  white-space:nowrap;overflow-wrap:normal;text-wrap:nowrap;
  /* Parisienne is a thin connected script: synthesised bold/italic and
     subpixel hinting are what make it look broken at large sizes. */
  font-synthesis:none;font-kerning:normal;
  text-rendering:optimizeLegibility;
  -webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;
  padding-bottom:.12em}
.hero__title .amp{font-size:.62em;opacity:.9;font-family:var(--serif);font-style:italic}
html[lang="ko"] .hero__title{font-size:clamp(1.5rem,6.2vw,5rem);line-height:1.34;white-space:nowrap;-webkit-font-smoothing:auto;-moz-osx-font-smoothing:auto}
.hero__date{margin-top:.7em;font-size:.92rem;letter-spacing:.26em;text-transform:uppercase;opacity:1;color:var(--ink-soft)}
html[lang="ko"] .hero__date{letter-spacing:.1em;text-transform:none;font-size:1.05rem}
.hero__tag{margin-top:1.1em;max-width:34ch;font-size:1.12rem;line-height:1.65;opacity:1;color:var(--ink-soft)}
.hero__cta{display:flex;flex-wrap:wrap;gap:.8em;justify-content:center;margin-top:1.9em}
.hero__cta .btn--outline{border-color:var(--ink);color:var(--ink);background:rgba(255,253,249,.55)}
.hero__cta .btn--outline:hover{background:var(--ink);color:var(--cream)}
.hero__scroll{margin-top:2.4em;font-size:.8rem;letter-spacing:.2em;text-transform:uppercase;
  opacity:1;color:var(--ink-soft);display:inline-flex;flex-direction:column;align-items:center;gap:.35em}
html[lang="ko"] .hero__scroll{letter-spacing:.06em;text-transform:none}
.hero__scroll i{font-style:normal;font-size:1.2rem;animation:bob 1.8s var(--ease) infinite}
@keyframes bob{0%,100%{transform:translateY(0)}50%{transform:translateY(6px)}}

/* ── The arrival plate (FACT-06). Restricted invitation class only. ─────
   Not a schedule row or footnote: an accented card for urgent arrival copy. */
.plate{
  position:relative;z-index:2;width:min(560px,100%);margin:2.4em auto 0;
  background:var(--white);color:var(--ink);text-align:left;
  border-radius:16px;padding:clamp(20px,4vw,28px) clamp(20px,4vw,30px);
  border:1px solid var(--line);border-left:4px solid var(--accent);
  box-shadow:var(--shadow-card);
}
.plate__label{font-size:.72rem;letter-spacing:.24em;text-transform:uppercase;
  color:var(--accent);margin-bottom:.7em;display:flex;align-items:center;gap:.6em}
html[lang="ko"] .plate__label{letter-spacing:.08em;text-transform:none}
.plate__label::before{content:"";width:22px;height:1px;background:var(--accent);flex:none}
.plate__title{font-size:clamp(1.25rem,3.6vw,1.55rem);line-height:1.35;margin-bottom:.45em;font-weight:500}
.plate__body{color:var(--ink-soft);font-size:1rem;line-height:1.7}
.plate--inline{margin:1.6em 0 0}
.plate--quiet{border-left-color:var(--sage);background:var(--cream-2);box-shadow:none}
.plate--quiet .plate__label{color:var(--sage-deep)}
.plate--quiet .plate__label::before{background:var(--sage-deep)}

/* ── Section frame ─────────────────────────────────────────────────────── */
.section{padding:var(--sec) var(--gut);position:relative;
  /* The chrome is position:fixed, so an anchored jump lands with the first
     rows of the section underneath it — which was cropping heads off the
     first gallery photograph. */
  scroll-margin-top:76px}
.section--alt{background:var(--cream-2)}
.section--sage{background:var(--sage-soft);color:var(--ink)}
.section--sage .eyebrow{color:var(--sage-deep)}
.section__head{max-width:720px;margin:0 auto clamp(40px,6vw,72px);text-align:center}
.section__head .eyebrow{display:block;margin-bottom:.9em}
.section__title{font-weight:400;font-size:clamp(2rem,4vw,2.9rem);line-height:1.25;
  overflow-wrap:break-word}
.section__lead{margin-top:1em;color:var(--ink-soft);font-size:1.06rem;line-height:1.75;
  max-width:52ch;margin-left:auto;margin-right:auto}
.section--sage .section__lead{color:var(--ink-soft);opacity:1}
.section__mark{display:block;width:1px;height:52px;background:var(--line);margin:0 auto 2.2em}
.section--sage .section__mark{background:var(--sage-line)}
.wrap{max-width:1040px;margin:0 auto}
.wrap--narrow{max-width:760px;margin:0 auto}

/* =========================================================================
   Chunk 4/6 — countdown, schedule, venues, travel, FAQ, plates, footer
   ========================================================================= */

/* ── Countdown ─── Round 4 DAY: the open-sky band. ────────────────
   Cream paper still owns the page; this and the colophon are the two
   wide-sky moments, which is where the Corona-by-day image lives. */
.countdown{text-align:center;position:relative;overflow:hidden;
  background:radial-gradient(120% 90% at 50% 108%,#fdfaf2 0%,var(--dusk-2) 42%,var(--dusk) 100%);
  color:var(--on-deep)}
.countdown__sky{position:absolute;inset:0;z-index:0;pointer-events:none}
.countdown__sky svg{width:100%;height:100%}
.countdown > *:not(.countdown__sky){position:relative;z-index:1}
.countdown .eyebrow{color:var(--lantern)}
.countdown .section__title{color:var(--on-deep)}
.countdown__grid{display:flex;flex-wrap:wrap;justify-content:center;
  gap:clamp(14px,4vw,44px);margin-top:.4em}
.cd{min-width:72px;display:flex;flex-direction:column;align-items:center;gap:.5em}
.cd__num{font-size:clamp(2.4rem,7vw,3.4rem);line-height:1;font-weight:500;
  font-variant-numeric:tabular-nums;font-family:var(--serif);color:var(--lantern);
  text-shadow:none}
.cd__lab{font-size:.7rem;letter-spacing:.2em;text-transform:uppercase;color:var(--ink-soft)}
html[lang="ko"] .cd__lab{letter-spacing:.06em;text-transform:none;font-size:.8rem}
.countdown__note{margin-top:2.2em;font-style:italic;color:var(--ink-soft);font-size:.98rem}
html[lang="ko"] .countdown__note{font-style:normal}
.countdown__done{margin-top:1.6em;font-size:1.15rem;color:var(--lantern)}

/* ── Schedule — old3's two-column event blocks, alternating side ───────── */
.sched__intro{max-width:60ch;margin:0 auto clamp(32px,5vw,56px)}
.event{display:grid;grid-template-columns:1.05fr .95fr;gap:clamp(28px,5vw,64px);
  align-items:center;padding:clamp(36px,6vw,64px) 0}
.event + .event{border-top:1px solid var(--line)}
.event--rev .event__info{order:2}
.event__index{font-size:.72rem;letter-spacing:.26em;text-transform:uppercase;
  color:var(--sage-deep);margin-bottom:.9em;display:flex;align-items:center;gap:.7em}
html[lang="ko"] .event__index{letter-spacing:.08em;text-transform:none}
.event__index::after{content:"";height:1px;flex:1;background:var(--line)}
.event__title{font-size:clamp(1.7rem,4vw,2.3rem);font-weight:400;margin-bottom:.5em;line-height:1.25}
.event__time{font-size:1.18rem;line-height:1.6;margin-bottom:.6em;color:var(--ink)}
.event__venue{color:var(--ink-soft);font-size:1.02rem;margin-bottom:.7em;line-height:1.6}
.event__desc{color:var(--ink-soft);line-height:1.75;max-width:46ch}
.event__actions{display:flex;flex-wrap:wrap;gap:.7em;margin-top:1.4em}
.event__actions .btn{font-size:.88rem;padding:.7em 1.3em}

/* Framed art plate — the printed-invitation crop old3 gave its maps. */
.frame{position:relative;border-radius:16px;overflow:hidden;background:var(--cream-2);
  box-shadow:var(--shadow-card);border:1px solid var(--line)}
.frame svg{width:100%;height:auto;display:block}
/* A real photograph in a slot. The aspect box above already reserves the
   space, so the image only has to fill it: no layout shift when it decodes,
   and no change to any surrounding rule. object-position is set per slot
   inline so a crop can be nudged without touching this file. */
.frame--photo picture,.frame--photo img{display:block;width:100%;height:100%}
.frame--photo img{object-fit:cover}
.frame--16x9{aspect-ratio:16/9}
.frame--4x5{aspect-ratio:4/5}
.frame--1x1{aspect-ratio:1/1}
.frame--4x3{aspect-ratio:4/3}
.frame--3x4{aspect-ratio:3/4}
.frame > svg{position:absolute;inset:0;width:100%;height:100%}
/* The scrim starts at .55 rather than at 0.
   A fully transparent top stop meant the upper half of every glyph sat on the
   photograph undimmed, and the photograph is not a colour the stylesheet
   controls. Measured over the real pixels behind the text, every caption came
   in between 2.00:1 and 4.05:1 against a 4.5:1 requirement, in both languages
   at every viewport — see docs/TEST-FINDINGS.md F-001 P-2. Korean is the
   binding case: 13px, thin strokes, no letter-spacing to open it up. */
.frame__cap{position:absolute;left:0;right:0;bottom:0;padding:14px 16px;
  font-size:.74rem;letter-spacing:.16em;text-transform:uppercase;
  color:var(--ink);background:linear-gradient(180deg,rgba(255,253,249,.55),rgba(255,253,249,.88))}
html[lang="ko"] .frame__cap{letter-spacing:.04em;text-transform:none;font-size:.8rem}

/* ── Venues ────────────────────────────────────────────────────────────── */
.venues{display:grid;gap:clamp(28px,5vw,44px);grid-template-columns:1fr}
.venue{scroll-margin-top:76px;background:var(--white);border:1px solid var(--line);border-radius:20px;
  overflow:hidden;box-shadow:var(--shadow-card);display:grid;
  grid-template-columns:minmax(0,1fr) minmax(0,1.1fr)}
/* Two columns above 900px, and the photograph fills its own column rather
   than deriving a width from its height.

   `min-height:100%` gives this box a definite height (the grid row, ~720px).
   With `aspect-ratio` still applied, `height:100%` on the frame below made the
   browser compute the WIDTH backwards — 720 x 16/9 = 1280px inside a 494px
   column. The frame escaped the column, and because it is `position:relative`
   it painted above the static venue name, room, address and map link, which
   vanished entirely at every width over 900px. See docs/TEST-FINDINGS.md
   F-002; the `@media (max-width:900px)` block below restores 16:9 for the
   single-column layout, where width drives height and nothing can overflow.

   `overflow:hidden` is the second line of defence rather than the fix: no
   child of this column should ever be able to paint over the text beside it,
   whatever a future rule does to its size. */
.venue__map:focus-within,.venue__map.is-focused{outline:3px solid var(--sage-deep);outline-offset:-3px}
.venue__map{display:block;width:100%;height:100%;min-height:300px;border:0}
.venue__media{position:relative;min-height:100%;overflow:hidden}
.venue__media .frame{border:0;border-radius:0;box-shadow:none;height:100%;aspect-ratio:auto}
.venue__body{padding:var(--card-pad)}
.venue__name{font-size:clamp(1.45rem,3.4vw,1.9rem);font-weight:400;line-height:1.3;margin-bottom:.2em}
.venue__room{color:var(--accent);font-style:italic;margin-bottom:.5em}
html[lang="ko"] .venue__room{font-style:normal}
.venue__addr{color:var(--ink-soft);font-size:.98rem;margin-bottom:1.3em;line-height:1.6}
.venue__facts{display:flex;flex-direction:column;gap:1em;margin-bottom:1.4em}
.venue__facts li{position:relative;padding-left:1.4em;color:var(--ink-soft);line-height:1.7;font-size:1rem}
.venue__facts li::before{content:"";position:absolute;left:0;top:.72em;
  width:7px;height:7px;border:1px solid var(--sage);border-radius:50%}

/* ── Travel ────────────────────────────────────────────────────────────── */
.tips{display:grid;gap:0;max-width:820px;margin:0 auto;border-top:1px solid var(--line)}
.tip{display:grid;grid-template-columns:52px 1fr;gap:18px;align-items:start;
  padding:26px 4px;border-bottom:1px solid var(--line)}
.tip__icon{width:44px;height:44px;border:1px solid var(--sage-line);border-radius:50%;
  display:grid;place-items:center;color:var(--sage-deep)}
.tip__icon svg{width:20px;height:20px}
.tip p{line-height:1.75;color:var(--ink-soft)}

/* ── FAQ ───────────────────────────────────────────────────────────────── */
.faq{max-width:820px;margin:0 auto;border-top:1px solid var(--line)}
.faq__item{border-bottom:1px solid var(--line)}
.faq__q{width:100%;display:flex;align-items:flex-start;justify-content:space-between;
  gap:20px;text-align:left;padding:24px 4px;font-size:1.12rem;line-height:1.5;min-height:56px}
.faq__q:hover{color:var(--sage-deep)}
.faq__sign{flex:none;width:22px;height:22px;position:relative;margin-top:.3em}
.faq__sign::before,.faq__sign::after{content:"";position:absolute;background:var(--sage-deep);
  transition:transform var(--ui) var(--ease),opacity var(--ui) var(--ease)}
.faq__sign::before{left:0;right:0;top:10px;height:1.5px}
.faq__sign::after{top:0;bottom:0;left:10px;width:1.5px}
.faq__q[aria-expanded="true"] .faq__sign::after{transform:scaleY(0)}
.faq__a{padding:0 4px 26px;color:var(--ink-soft);line-height:1.8;max-width:60ch}
.faq__a[hidden]{display:none}

/* ── Colophon ──────────────────────────────────────────────────────────── */
.colophon{background:radial-gradient(120% 130% at 50% -20%,#fdfaf2 0%,var(--dusk-2) 45%,var(--dusk) 100%);
  color:var(--on-deep);text-align:center;
  padding:clamp(56px,9vw,86px) var(--gut)}
.colophon__mono{width:66px;height:66px;border:1px solid var(--sage-line);border-radius:50%;
  display:grid;place-items:center;padding:13px;color:var(--sage-deep);
  box-shadow:var(--shadow-lift)}
.colophon__mono{margin:0 auto 1.4em}
.colophon__mono .mono__image{width:100%;height:100%}
.colophon__names{font-family:var(--script);font-size:clamp(2.1rem,7vw,2.8rem);line-height:1.2;margin-bottom:.25em}
.colophon__date{letter-spacing:.3em;font-size:.82rem;text-transform:uppercase;opacity:1;color:var(--ink-soft);margin-bottom:1.4em}
html[lang="ko"] .colophon__date{letter-spacing:.08em;text-transform:none;font-size:.95rem}
.colophon__contact{font-size:.95rem;opacity:1;color:var(--ink-soft);line-height:1.8;overflow-wrap:anywhere}
/* WCAG 2.2 AA (2.5.8) wants a 24x24 hit area; this link measured 121x18.
   Vertical padding on an INLINE element grows the border box — which is what
   is hit, and what getBoundingClientRect reports — without growing the line
   box, so nothing moves on screen. The 1.8 line-height above already leaves
   more room than the padding takes, so consecutive lines do not overlap. */
.colophon__contact a{text-decoration:underline;text-underline-offset:.3em;
  padding-block:.25em}
.colophon__note{margin-top:1.6em;font-size:.78rem;opacity:1;color:var(--ink-soft);line-height:1.7;max-width:44ch;margin-inline:auto}
/* Handing the device to the next household. Set below the colophon note and
   separated by a rule: findable by someone who is looking for it, quiet for
   someone who is not. Sized as a normal control, not a tiny legal link — the
   guest most likely to need it is the one least able to hit a 20px target. */
.colophon__switch{margin-top:2.2em;padding-top:1.6em;border-top:1px solid var(--sage-line)}
.colophon__switch-intro{font-size:.82rem;color:var(--ink-soft);line-height:1.7;
  max-width:34ch;margin:0 auto .7em}
.colophon__switch-btn{font-size:.9rem;min-height:44px}

/* =========================================================================
   Chunk 5/6 — RSVP card, fields, steppers, review, confirmation
   ========================================================================= */

.rsvp__card{max-width:660px;margin:0 auto;background:var(--white);
  border:1px solid var(--line);border-radius:24px;padding:var(--card-pad);
  box-shadow:0 16px 40px rgba(79,61,122,.10)}
.rsvp__steps{display:flex;align-items:center;justify-content:center;gap:8px;margin-bottom:1.8em}
.rsvp__steps li{width:26px;height:3px;border-radius:2px;background:var(--line)}
.rsvp__steps li[aria-current="step"]{background:var(--sage-deep);width:38px}
.rsvp__steps li.is-done{background:var(--sage-line)}
.rsvp__stephead{text-align:center;margin-bottom:1.6em}
.rsvp__stephead h3{font-size:clamp(1.5rem,4vw,2rem);font-weight:400;line-height:1.3}
.rsvp__stephead p{margin-top:.7em;color:var(--ink-soft);line-height:1.75}
.rsvp__form{display:flex;flex-direction:column;gap:1.4em}
.rsvp__nav{display:flex;flex-wrap:wrap;gap:.7em;justify-content:space-between;margin-top:.6em}
.rsvp__nav .btn{flex:1 1 auto;min-width:44%}

.field{display:flex;flex-direction:column;gap:.5em}
.field__label{font-size:.92rem;letter-spacing:.04em;color:var(--ink)}
.field__help{font-size:.86rem;color:var(--ink-soft);line-height:1.6}
.field input,.field textarea,.field select{
  font-family:inherit;font-size:1.05rem;padding:.8em .95em;min-height:48px;
  border:1.5px solid var(--line);border-radius:10px;background:var(--cream);
  color:var(--ink);width:100%;
  transition:border-color var(--ui),box-shadow var(--ui)}
.field textarea{min-height:110px;resize:vertical;line-height:1.6}
.field input:focus,.field textarea:focus,.field select:focus{
  outline:none;border-color:var(--sage-deep);box-shadow:0 0 0 3px rgba(79,61,122,.20)}
.field input[aria-invalid="true"],.field textarea[aria-invalid="true"]{border-color:#96442f}
/* A single generous touch target; native caret/selection and no fake boxes. */
.field--code input{width:100%;min-width:0;min-height:52px;font-size:1.25rem;
  letter-spacing:.12em;text-align:left;padding:.7rem .9rem}
.err{color:#8a3d2a;font-size:.9rem;line-height:1.6}
.err[hidden]{display:none}

.choices{display:flex;flex-direction:column;gap:.8em}
.choice{display:flex;align-items:flex-start;gap:.8em;padding:1em 1.1em;
  border:1.5px solid var(--line);border-radius:14px;background:var(--cream);
  cursor:pointer;line-height:1.6;transition:border-color var(--ui),background var(--ui)}
.choice:hover{border-color:var(--sage-line)}
.choice input{margin-top:.28em;width:20px;height:20px;flex:none;accent-color:var(--sage-deep)}
.choice:has(input:checked){border-color:var(--sage-deep);background:var(--white)}
.choice__t{display:block}
.choice__s{display:block;font-size:.88rem;color:var(--ink-soft);margin-top:.2em}

.steppers{display:flex;flex-direction:column;gap:.9em}
.stepper{display:flex;align-items:center;justify-content:space-between;gap:14px;
  padding:.9em 1em;border:1px solid var(--line);border-radius:14px;background:var(--cream)}
.stepper__text{min-width:0}
.stepper__name{font-size:1.05rem}
.stepper__hint{display:block;font-size:.84rem;color:var(--ink-soft);line-height:1.55;margin-top:.15em}
.stepper__ctrl{display:flex;align-items:center;gap:6px;flex:none}
.stepper__btn{width:44px;height:44px;border-radius:50%;border:1.5px solid var(--sage-deep);
  color:var(--sage-deep);display:grid;place-items:center;font-size:1.3rem;line-height:1;
  transition:background var(--ui),color var(--ui)}
.stepper__btn:hover:not([disabled]){background:var(--sage-deep);color:var(--on-sage)}
.stepper__btn[disabled]{opacity:.35;cursor:not-allowed}
.stepper__val{min-width:2.2ch;text-align:center;font-size:1.25rem;font-variant-numeric:tabular-nums}

.review{display:flex;flex-direction:column;gap:0;border-top:1px solid var(--line);margin-bottom:1.6em}
.review__row{display:grid;grid-template-columns:minmax(90px,.5fr) 1fr auto;gap:12px;
  align-items:start;padding:16px 2px;border-bottom:1px solid var(--line)}
.review__k{font-size:.78rem;letter-spacing:.16em;text-transform:uppercase;color:var(--ink-soft);padding-top:.2em}
html[lang="ko"] .review__k{letter-spacing:.04em;text-transform:none;font-size:.88rem}
.review__v{line-height:1.7;overflow-wrap:anywhere}
.review__v ul li + li{margin-top:.25em}
/* Shown wherever a reply that has already been sent could be sent again. */
.rsvp__already{margin-bottom:1.2em;padding:.9em 1.1em;border-radius:10px;
  background:var(--cream-2);color:var(--ink);line-height:1.7;font-size:.94rem}

.done{text-align:center}
.done__seal{width:78px;height:78px;margin:0 auto 1.3em}
.done h3{font-size:clamp(1.6rem,4.4vw,2.1rem);font-weight:400;margin-bottom:.5em;line-height:1.3}
.done p{color:var(--ink-soft);line-height:1.8}
.done__downloads{margin-top:1.8em;padding-top:1.6em;border-top:1px solid var(--line)}
.done__downloads h4{font-size:1.05rem;font-weight:500;margin-bottom:.9em}
.done__downloads .btn{margin:.25em}

/* =========================================================================
   Chunk 6/6 — gallery/portrait, responsive, reduced motion, print
   ========================================================================= */

.portrait{display:grid;grid-template-columns:minmax(0,.85fr) minmax(0,1.15fr);
  gap:clamp(28px,6vw,72px);align-items:center;max-width:960px;margin:0 auto}
.portrait__words p{margin-bottom:1em;line-height:1.85;color:var(--ink-soft);font-size:1.08rem}
.portrait__words p:last-child{margin-bottom:0}
.portrait__quote{margin-top:1.6em;padding-left:1.5em;border-left:2px solid var(--sage)}
.portrait__quote p{font-family:var(--script);font-size:1.85rem;line-height:1.35;
  color:var(--sage-deep);margin-bottom:.3em}
html[lang="ko"] .portrait__quote p{font-size:1.3rem;line-height:1.6}
.portrait__quote span{font-size:.92rem;letter-spacing:.1em;color:var(--ink-soft)}

.gallery{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;max-width:1040px;margin:0 auto}
/* Single column stacks the tiles under the fixed chrome, which was landing
   across the faces in the first photograph. */
@media (max-width:640px){ .gallery{padding-top:104px} }
.gallery .frame{border-color:var(--sage-line);background:var(--white)}
.gallery__actions{display:flex;justify-content:center;margin-top:clamp(28px,4vw,44px)}
.gallery__more{appearance:none;border:1px solid var(--ink);border-radius:999px;background:rgba(255,253,249,.72);
  color:var(--ink);font:500 .9rem/1 var(--sans);letter-spacing:.08em;padding:1em 1.45em;cursor:pointer;
  transition:background .25s var(--ease),color .25s var(--ease),transform .25s var(--ease)}
.gallery__more:hover{background:var(--ink);color:var(--cream);transform:translateY(-2px)}
.gallery__more:focus-visible{outline:3px solid var(--sage-deep);outline-offset:4px}
body.gallery-open{overflow:hidden}
.gallery-modal{position:fixed;inset:0;z-index:1000;display:grid;place-items:center;padding:clamp(10px,2.5vw,28px);
  background:rgba(20,23,19,.92);color:var(--cream)}
.gallery-modal__panel{display:grid;grid-template-rows:auto minmax(0,1fr) auto auto;width:min(1180px,100%);
  height:min(94dvh,900px);background:#20251f;border:1px solid rgba(255,253,249,.22);border-radius:18px;
  box-shadow:0 24px 80px rgba(0,0,0,.48);overflow:hidden}
.gallery-modal__header{display:flex;align-items:center;justify-content:space-between;gap:20px;padding:14px 18px;
  border-bottom:1px solid rgba(255,253,249,.14)}
.gallery-modal__title{font:400 clamp(1.15rem,2vw,1.5rem)/1.2 var(--serif);letter-spacing:.04em}
.gallery-modal__close,.gallery-modal__nav{appearance:none;border:1px solid rgba(255,253,249,.38);background:rgba(255,255,255,.08);
  color:var(--cream);cursor:pointer;display:grid;place-items:center}
.gallery-modal__close{width:44px;height:44px;border-radius:50%;font:300 2rem/1 var(--sans)}
.gallery-modal__stage{min-height:0;display:grid;grid-template-columns:56px minmax(0,1fr) 56px;align-items:center;
  gap:12px;padding:14px 18px 8px;touch-action:pan-y}
.gallery-modal__nav{width:48px;height:48px;border-radius:50%;font:300 2.4rem/1 var(--serif)}
.gallery-modal__nav--previous{justify-self:end}.gallery-modal__nav--next{justify-self:start}
.gallery-modal__close:hover,.gallery-modal__nav:hover{background:rgba(255,255,255,.18)}
.gallery-modal__close:focus-visible,.gallery-modal__nav:focus-visible,.gallery-modal__thumb:focus-visible{
  outline:3px solid var(--accent-glow);outline-offset:3px}
.gallery-modal__image{min-width:0;height:100%;display:grid;place-items:center;margin:0;overflow:hidden}
.gallery-modal__image picture{display:flex;align-items:center;justify-content:center;width:100%;height:100%;min-width:0;min-height:0}
/* The stage is a bounded desktop grid row. Percentage max-height on an
   intrinsic image can resolve after width sizing and leave the portrait or
   landscape taller than that row, where the figure's overflow clips it.
   Give the image the stage's explicit box instead; contain then guarantees
   every photograph remains wholly visible at every desktop aspect ratio. */
.gallery-modal__image img{display:block;width:100%;height:100%;min-width:0;min-height:0;object-fit:contain}
.gallery-modal__status{text-align:center;margin:0;padding:5px 18px 8px;color:rgba(255,253,249,.8);font-size:.86rem;letter-spacing:.04em}
.gallery-modal__thumbs{display:grid;grid-auto-flow:column;grid-auto-columns:88px;gap:9px;overflow-x:auto;overscroll-behavior-x:contain;
  padding:10px 18px 16px;scrollbar-color:rgba(255,253,249,.35) transparent}
.gallery-modal__thumb{appearance:none;width:88px;height:66px;padding:0;border:2px solid transparent;border-radius:7px;
  overflow:hidden;background:#111;cursor:pointer;opacity:.64;transition:opacity .2s var(--ease),border-color .2s var(--ease)}
.gallery-modal__thumb[aria-current="true"]{opacity:1;border-color:var(--accent-glow)}
.gallery-modal__thumb picture,.gallery-modal__thumb img{display:block;width:100%;height:100%}
.gallery-modal__thumb img{object-fit:cover}
@media(max-width:640px){
  .gallery-modal{padding:0}
  .gallery-modal__panel{height:100dvh;border:0;border-radius:0}
  .gallery-modal__stage{position:relative;display:block;padding:8px}
  .gallery-modal__image{height:100%}
  .gallery-modal__nav{position:absolute;z-index:1;top:50%;transform:translateY(-50%);background:rgba(20,23,19,.72)}
  .gallery-modal__nav--previous{left:12px}.gallery-modal__nav--next{right:12px}
  .gallery-modal__thumbs{grid-auto-columns:72px;padding-inline:10px}
  .gallery-modal__thumb{width:72px;height:56px}
}

/* ── Responsive ────────────────────────────────────────────────────────── */
@media (max-width:900px){
  .event,.venue,.portrait{grid-template-columns:1fr}
  .event--rev .event__info{order:0}
  .venue__media{min-height:0}
  .venue__media .frame{aspect-ratio:16/9}
  .portrait__quote{margin-top:1.4em}
  .gallery{grid-template-columns:repeat(2,1fr)}
}
@media (max-width:560px){
  :root{--gut:7vw}
  .chrome__mark-text{display:none}
  .hero{padding-top:120px}
  .cd{min-width:60px}
  .countdown__grid{gap:16px}
  .rsvp__nav .btn{min-width:100%}
  .review__row{grid-template-columns:1fr;gap:4px}
  .gallery{grid-template-columns:1fr}
  .menu__list a{font-size:clamp(1.7rem,8vw,2.2rem)}
}
@media (max-width:360px){
  body{font-size:17px}
  .cd__num{font-size:2rem}
  .cd{min-width:52px}
  .langswitch button{padding:.5em .7em}
}
@media (min-width:1200px){
  .section{padding-inline:max(var(--gut),calc((100vw - 1240px)/2))}
}

/* ── Reduced motion: genuinely off, not merely faster ──────────────────── */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.001ms !important;
    animation-iteration-count:1 !important;
    transition-duration:.001ms !important;
    scroll-behavior:auto !important;
  }
  [data-reveal]{opacity:1 !important;transform:none !important;transition:none !important}
  .envelope__card{animation:none !important}
  .hero__scroll i{animation:none !important}
  .btn:hover{transform:none !important}
}

/* ── Print: the invitation, on paper ───────────────────────────────────── */
@media print{
  .chrome,.menu,.envelope,.hero__scroll,.rsvp__card,.skip-link{display:none !important}
  body{background:#fff;color:#000;font-size:12pt}
  .section{padding:18pt 0;break-inside:avoid}
  .hero{min-height:auto;color:#000;padding:0 0 18pt}
  .hero__art,.hero__veil{display:none}
  .colophon{background:none;color:#000}
}

/* hero slot fill (SPEC-13 hero-primary, 4:5 source, bleed crop) */
.hero__art > svg{width:100%;height:100%}
.done__seal svg{border-radius:50%}
.gallery .frame__cap{color:var(--ink)}

/* Chrome sits over the sunlit hero until the page scrolls: ink either way,
   no light-on-dark swap needed. Checked both ways for AA. */
.chrome:not(.is-scrolled) .chrome__mark-glyph,
.chrome:not(.is-scrolled) .chrome__mark-text{color:var(--ink-soft);text-shadow:none}
.chrome:not(.is-scrolled) .langswitch,
.chrome:not(.is-scrolled) .chrome__menu{background:rgba(255,253,249,.94);border-color:rgba(255,253,249,.5)}
