/* ============================================================
   Khmer wedding invitation — ported from the Claude Design source
   "Wedding Invitation.dc.html". Colour, type and motion values
   are carried over verbatim; layout is expressed in classes.
   ============================================================ */

:root {
  --bg:        #E4E0CB;
  --bg-top:    #F5EEE6;
  --card:      #FBF7EE;
  --cream-1:   #F8F0E6;
  --cream-2:   #F4EFE2;
  --cream-3:   #EDE9D2;
  --cream-4:   #EFEADC;
  --sand:      #E9E6D2;

  --ink:       #24261A;
  --muted:     #6A6752;
  --muted-2:   #87866B;

  --olive-deep:#5F621C;
  --olive:     #818427;
  --olive-lt:  #9C9E70;

  --rose:      #CC9187;
  --rose-lt:   #EFD2CB;
  --rose-dk:   #B4685C;

  --line:      #E9E6D2;
  --border:    #DFDCC0;

  --shadow-sm: 0 1px 2px rgba(10,58,69,.04), 0 1px 3px rgba(10,58,69,.04);
  --shadow-md: 0 2px 6px rgba(10,58,69,.05), 0 4px 12px rgba(10,58,69,.05);
  --shadow-lg: 0 4px 12px rgba(10,58,69,.06), 0 8px 24px rgba(10,58,69,.06);

  --ease:      cubic-bezier(.16,1,.3,1);
  --ease-tap:  cubic-bezier(.2,.8,.2,1);

  --sans:      'Inter', system-ui, -apple-system, sans-serif;
  --khmer:     'Kantumruy Pro', 'Khmer OS', sans-serif;
  --display:   'Moul', 'Kantumruy Pro', serif;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}

body {
  font-family: var(--sans);
  color: var(--ink);
}

h1, h2, p, figure { margin: 0; }

img { display: block; max-width: 100%; }

a { color: var(--olive-deep); text-decoration: none; }
a:hover { color: var(--olive); }

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

/* ---------- keyframes ---------- */
@keyframes wSpin   { to { transform: rotate(360deg); } }
@keyframes wSpinR  { to { transform: rotate(-360deg); } }
@keyframes wFloat  {
  0%   { transform: translate3d(0,-8vh,0) rotate(0deg); opacity: 0; }
  10%  { opacity: .75; }
  90%  { opacity: .55; }
  100% { transform: translate3d(24px,105vh,0) rotate(320deg); opacity: 0; }
}
@keyframes wPulse   { 0%,100% { transform: scale(1); opacity: .55; } 50% { transform: scale(1.06); opacity: .9; } }
@keyframes wShimmer { 0% { background-position: 0% 50%; } 100% { background-position: 200% 50%; } }
@keyframes wRise    { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }

/* ---------- shell ---------- */
.stage {
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  justify-content: center;
  background: radial-gradient(120% 60% at 50% 0%, var(--bg-top) 0%, var(--bg) 100%);
}

.card {
  width: 100%;
  max-width: 430px;
  background: var(--card);
  position: relative;
  overflow: hidden;
  box-shadow: 0 4px 40px rgba(10,58,69,.10);
}

/* ---------- petals ---------- */
.petals {
  position: absolute;
  inset: 0;
  pointer-events: none;
  overflow: hidden;
  z-index: 3;
}
.petals span {
  position: absolute;
  top: 0;
  width: 11px;
  height: 11px;
  border-radius: 60% 0 60% 0;
  background: linear-gradient(140deg, var(--rose-lt), var(--rose));
  opacity: 0;
  animation-name: wFloat;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
}

/* ---------- hero ---------- */
.hero {
  position: relative;
  padding: 0 0 44px;
  background: linear-gradient(180deg, var(--cream-1) 0%, var(--card) 88%);
  overflow: hidden;
}

.mandala {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  pointer-events: none;
}
.mandala svg { animation: wSpin 90s linear infinite; }
.mandala--lg { top: -90px; width: 420px; height: 420px; opacity: .5; }
.mandala--sm { top: -40px; width: 300px; height: 300px; opacity: .35; }
.mandala--sm svg { animation: wSpinR 130s linear infinite; }

.hero__inner {
  position: relative;
  z-index: 2;
  padding: 64px 24px 0;
  text-align: center;
}

.eyebrow-km {
  font-family: var(--khmer);
  font-weight: 400;
  font-size: 12px;
  letter-spacing: .22em;
  color: var(--olive-deep);
  line-height: 1.5;
}
.eyebrow-en {
  font-size: 11px;
  letter-spacing: .3em;
  color: var(--olive-lt);
  margin-top: 6px;
}

.portrait {
  margin: 26px auto 0;
  width: 124px;
  height: 124px;
  border-radius: 50%;
  overflow: hidden;
  border: 2px solid var(--border);
  box-shadow: 0 6px 18px rgba(10,58,69,.10);
  background: var(--sand);
}
.portrait img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* framed on the couple's faces rather than the centre of the photo */
  object-position: 50% 6%;
}

.names {
  margin: 22px 0 0;
  font-family: var(--display);
  font-size: 25px;
  line-height: 1.5;
  font-weight: 400;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
}
.names__km {
  background: linear-gradient(100deg, var(--olive) 0%, #E7CD8E 32%, #9A7629 62%, #DFC384 100%);
  background-size: 200% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  animation: wShimmer 9s linear infinite;
  /* Moul has no descender room to spare — give the glyphs a little air */
  padding: 0 2px 2px;
}
.names__amp {
  font-family: var(--sans);
  font-size: 15px;
  font-weight: 400;
  color: var(--rose);
  line-height: 1;
  margin: 2px 0;
}
.names-en {
  margin-top: 10px;
  font-size: 12px;
  letter-spacing: .14em;
  color: var(--muted);
  text-wrap: balance;
}

.rule {
  margin: 22px auto 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  max-width: 280px;
}
.rule__line { flex: 1; height: 1px; }
.rule__line--l { background: linear-gradient(90deg, transparent, #E3C4BC); }
.rule__line--r { background: linear-gradient(270deg, transparent, #E3C4BC); }

.date-km {
  margin-top: 18px;
  font-family: var(--khmer);
  font-size: 17px;
  font-weight: 500;
  line-height: 1.5;
  color: var(--ink);
}
.date-en {
  margin-top: 4px;
  font-size: 13px;
  letter-spacing: .06em;
  color: var(--muted-2);
}

/* ---------- countdown ---------- */
.countdown {
  position: relative;
  z-index: 2;
  margin: 30px 20px 0;
  padding: 18px 12px;
  background: #FFFFFF;
  border-radius: 22px;
  box-shadow: var(--shadow-md);
}
.countdown__label {
  text-align: center;
  font-family: var(--khmer);
  font-size: 12px;
  color: var(--muted-2);
  line-height: 1.5;
}
.countdown__grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 6px;
  margin-top: 12px;
}
.cd { text-align: center; }
.cd__v {
  font-size: 24px;
  font-weight: 500;
  color: var(--olive);
  font-variant-numeric: tabular-nums;
}
.cd__km {
  font-family: var(--khmer);
  font-size: 11px;
  color: var(--ink);
  margin-top: 2px;
  line-height: 1.5;
}
.cd__en {
  font-size: 9px;
  letter-spacing: .12em;
  color: var(--olive-lt);
  text-transform: uppercase;
}

/* ---------- photoshoot ---------- */
.shoot { padding: 0 0 34px; background: var(--card); }

.shoot__hero {
  position: relative;
  height: 460px;
  overflow: hidden;
  background: var(--sand);
}
.shoot__hero .par {
  position: absolute;
  left: 0; right: 0;
  top: -14%;
  height: 128%;
  will-change: transform;
}
.shoot__hero .par img { width: 100%; height: 100%; object-fit: cover; }

.shoot__scrim {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(180deg,
    rgba(42,35,24,.30) 0%,
    rgba(42,35,24,0)  34%,
    rgba(42,35,24,0)  46%,
    rgba(42,35,24,.62) 100%);
}
.shoot__caption {
  position: absolute;
  left: 20px; right: 20px;
  bottom: 26px;
  pointer-events: none;
  will-change: transform;
}
.shoot__title {
  font-family: var(--khmer);
  font-size: 24px;
  font-weight: 500;
  line-height: 1.5;
  color: #FFFFFF;
  text-shadow: 0 2px 14px rgba(0,0,0,.35);
}
.shoot__sub {
  font-size: 12px;
  letter-spacing: .22em;
  color: rgba(255,255,255,.85);
  margin-top: 4px;
}
.shoot__mandala {
  position: absolute;
  top: 22px; right: 18px;
  width: 120px; height: 120px;
  opacity: .5;
  will-change: transform;
}
.shoot__mandala svg { animation: wSpin 70s linear infinite; }

/* ---------- photo showcase ----------
   A lead-weighted rail. `--t` is written per frame by app.js: 0 when a photo
   sits at the leading edge of the rail, 1 once it is a full frame away.
   Everything here reads from that one number, so the whole effect is
   transform + opacity and never touches layout. */
.showcase { margin-top: 26px; }

.showcase__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding: 0 20px;
}
.showcase__label {
  font-family: var(--khmer);
  font-size: 13px;
  font-weight: 500;
  line-height: 1.5;
  color: var(--muted);
}
.showcase__count {
  font-family: var(--khmer);
  font-size: 12px;
  color: var(--olive);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.showcase__track {
  height: 1px;
  margin: 9px 20px 0;
  background: var(--line);
  overflow: hidden;
}
.showcase__fill {
  display: block;
  height: 100%;
  background: linear-gradient(90deg, var(--rose), var(--olive));
  transform: scaleX(.04);
  transform-origin: left center;
}

.gallery {
  margin-top: 16px;
  display: flex;
  gap: 14px;
  /* A left-aligned rail. The first photo starts on the same 20px gutter as the
     label and progress track above it, so nothing sits in dead space before
     the rail begins. The trailing padding is what the leading gutter used to
     be: it keeps the invariant that EVERY photo can reach the focus position,
     including the last one — otherwise the counter could never read 27 / 27
     while the progress bar showed 100%. */
  padding: 12px calc(100% - 272px) 24px 20px;
  /* Snapping aligns to the snapport, which is the scrollport inset by
     scroll-padding. Without this the snap would yank the leading photo flush
     against the edge and fight the 20px padding on every settle. */
  scroll-padding-left: 20px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  overscroll-behavior-x: contain;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.gallery::-webkit-scrollbar { display: none; }

.shot {
  flex: none;
  width: 252px;
  scroll-snap-align: start;
  /* button reset */
  font: inherit;
  color: inherit;
  border: 0;
  padding: 0;
  background: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  --t: 1;
  transform: scale(calc(1 - .12 * var(--t)));
  opacity: calc(1 - .42 * var(--t));
  will-change: transform;
}
.shot:active { transform: scale(calc(.97 - .12 * var(--t))); }

.shot__frame {
  position: relative;
  display: block;
  height: 336px;
  border-radius: 20px;
  overflow: hidden;
  background: var(--sand);
  box-shadow: var(--shadow-lg);
  transition: box-shadow 380ms var(--ease);
}
/* a hairline inside the frame, like the edge of a mounted print */
.shot__frame::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow: inset 0 0 0 1px rgba(204,145,135,.28);
  pointer-events: none;
}
.shot__frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* the slight overscale gives the drift room to move without baring an edge */
  transform: scale(1.06);
}

.shot.is-active .shot__frame {
  box-shadow: 0 14px 34px rgba(10,58,69,.16), 0 3px 10px rgba(10,58,69,.08);
}
/* only the photo at the centre drifts — one animation on screen, not 25 */
.shot.is-active .shot__frame img {
  animation: wDrift 15s ease-in-out infinite alternate;
}
@keyframes wDrift {
  from { transform: scale(1.06) translate3d(0, 0, 0); }
  to   { transform: scale(1.15) translate3d(-1.5%, -2%, 0); }
}

/* ---------- photo grid ---------- */
.grid {
  padding: 0 20px;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}
.grid__cell {
  position: relative;
  height: 210px;
  border-radius: 14px;
  overflow: hidden;
  background: var(--sand);
}
.grid__cell--drop { margin-top: 26px; }
.grid__cell--wide { grid-column: 1 / -1; height: 200px; margin-top: 6px; }
.grid__cell .par {
  position: absolute;
  left: 0; right: 0;
  top: -12%;
  height: 124%;
  will-change: transform;
}
.grid__cell--wide .par { top: -14%; height: 128%; }
.grid__cell .par img { width: 100%; height: 100%; object-fit: cover; }

/* ---------- generic section ---------- */
.section { padding: 36px 20px 34px; background: var(--card); }
.section--venue { background: linear-gradient(180deg, var(--cream-2), var(--cream-1)); }
.section--gift  { background: linear-gradient(180deg, var(--cream-1), var(--cream-3)); padding-bottom: 46px; }
.center { text-align: center; }

.h-km {
  font-family: var(--khmer);
  font-size: 20px;
  font-weight: 500;
  line-height: 1.5;
  color: var(--ink);
}
.h-en {
  font-size: 12px;
  letter-spacing: .18em;
  color: var(--olive-lt);
  margin-top: 2px;
}

/* ---------- agenda ---------- */

.agenda {
  margin-top: 16px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.item {
  display: flex;
  gap: 14px;
  align-items: flex-start;
  background: #FFFFFF;
  border-radius: 18px;
  padding: 16px;
  box-shadow: var(--shadow-sm);
}
.item__when { flex: none; width: 58px; text-align: center; }
.item__time {
  font-size: 16px;
  font-weight: 500;
  color: var(--olive);
  font-variant-numeric: tabular-nums;
}
.item__ampm { font-size: 10px; color: var(--olive-lt); letter-spacing: .1em; }
.item__sep { flex: none; width: 1px; align-self: stretch; background: var(--line); }
.item__body { flex: 1; min-width: 0; }
.item__km {
  font-family: var(--khmer);
  font-size: 15px;
  font-weight: 500;
  line-height: 1.5;
  color: var(--ink);
}
.item__en { font-size: 13px; line-height: 1.4; color: var(--muted); margin-top: 1px; }
.item__note { font-size: 12px; line-height: 1.4; color: var(--olive-lt); margin-top: 6px; }

/* ---------- venue ---------- */
.venue {
  margin-top: 16px;
  background: #FFFFFF;
  border-radius: 22px;
  overflow: hidden;
  box-shadow: var(--shadow-md);
}
.venue__map {
  position: relative;
  height: 168px;
  background: var(--cream-4);
}
.venue__map img,
.venue__mapfallback {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* a real map screenshot (set venue.mapImage in config.js) replaces the
   stylised fallback drawing */
.venue__map[data-has-map="1"] .venue__mapfallback { display: none; }

.venue__map img { z-index: 1; }
.pin {
  position: absolute;
  left: 50%; top: 50%;
  transform: translate(-50%,-50%);
  pointer-events: none;
  z-index: 2;
}
.pin span {
  width: 34px; height: 34px;
  border-radius: 50%;
  background: rgba(204,145,135,.35);
  animation: wPulse 2.6s ease-in-out infinite;
  display: flex;
  align-items: center;
  justify-content: center;
}
.pin span::after {
  content: "";
  width: 12px; height: 12px;
  border-radius: 50%;
  background: var(--olive-deep);
  box-shadow: 0 0 0 3px #fff;
}

.venue__body { padding: 16px; }
.venue__name {
  font-family: var(--khmer);
  font-size: 17px;
  font-weight: 500;
  line-height: 1.5;
  color: var(--ink);
}
.venue__addr { font-size: 13px; line-height: 1.5; color: var(--muted); margin-top: 2px; }
.venue__actions { display: flex; gap: 8px; margin-top: 14px; }

/* ---------- buttons ---------- */
.btn {
  font: inherit;
  font-size: 14px;
  font-weight: 500;
  border-radius: 999px;
  cursor: pointer;
  text-align: center;
  transition: transform 120ms var(--ease-tap), background-color 160ms var(--ease-tap);
}
.btn:active { transform: scale(.97); }

.btn--primary {
  flex: 1;
  padding: 12px 16px;
  background: var(--olive-deep);
  color: #fff;
  border: 0;
}
.btn--primary:hover { background: var(--olive); color: #fff; }

.btn--ghost {
  flex: none;
  padding: 12px 18px;
  border: 1.5px solid var(--rose);
  background: transparent;
  color: var(--olive-deep);
}
.btn--ghost:hover { background: rgba(204,145,135,.10); }

.btn--soft {
  margin-top: 14px;
  padding: 10px 18px;
  background: var(--cream-2);
  color: var(--olive-deep);
  border: 0;
  font-size: 13px;
}
.btn--soft:hover { background: #EDE7D6; }

/* ---------- gift / KHQR ---------- */
.gift__note-en {
  font-size: 13px;
  line-height: 1.5;
  color: var(--muted);
  margin: 10px auto 0;
  max-width: 300px;
  text-wrap: pretty;
}
.gift__note-km {
  font-family: var(--khmer);
  font-size: 13px;
  line-height: 1.7;
  color: var(--muted-2);
  margin: 6px auto 0;
  max-width: 300px;
}

.khqr {
  margin: 18px auto 0;
  max-width: 300px;
  background: #fff;
  border-radius: 22px;
  padding: 6px;
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}
.khqr__head {
  background: var(--rose-dk);
  border-radius: 18px 18px 0 0;
  padding: 12px 16px;
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.khqr__brand { color: #fff; font-size: 15px; font-weight: 500; letter-spacing: .08em; }
.khqr__scan  { color: rgba(255,255,255,.8); font-size: 10px; letter-spacing: .12em; }

.khqr__body { padding: 18px 18px 20px; text-align: center; }
.khqr__name {
  font-family: var(--khmer);
  font-size: 15px;
  font-weight: 500;
  line-height: 1.5;
  color: var(--ink);
}
.khqr__acc {
  font-size: 12px;
  color: var(--olive-lt);
  margin-top: 2px;
  font-variant-numeric: tabular-nums;
}
.khqr__code {
  position: relative;
  margin: 14px auto 0;
  width: 186px;
  height: 186px;
  padding: 10px;
  border-radius: 14px;
  border: 1px solid var(--line);
  background: #fff;
}
.khqr__code img { width: 100%; height: 100%; object-fit: contain; }

.khqr__empty {
  display: flex;
  position: absolute;
  inset: 10px;
  border: 1.5px dashed var(--border);
  border-radius: 8px;
  background: #FCFAF3;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 10px;
}
.khqr__code[data-has-qr="1"] .khqr__empty { display: none; }
.khqr__empty p { font-size: 12px; color: var(--muted-2); line-height: 1.4; }
.khqr__empty-hint { font-size: 10px; color: var(--olive-lt); word-break: break-all; }

/* ---------- signoff ---------- */
.signoff { text-align: center; margin-top: 28px; }
.signoff svg { display: inline-block; opacity: .8; }
.signoff__km {
  font-family: var(--khmer);
  font-size: 13px;
  line-height: 1.6;
  color: var(--muted-2);
  margin-top: 10px;
}
.signoff__en {
  font-size: 11px;
  letter-spacing: .16em;
  color: var(--olive-lt);
  margin-top: 4px;
}

/* ---------- toast ---------- */
.toast {
  position: fixed;
  left: 50%;
  bottom: 28px;
  transform: translate(-50%, 12px);
  background: rgba(36,38,26,.94);
  color: #FBF7EE;
  font-size: 13px;
  padding: 10px 18px;
  border-radius: 999px;
  box-shadow: 0 8px 24px rgba(10,58,69,.20);
  opacity: 0;
  pointer-events: none;
  transition: opacity 200ms var(--ease), transform 200ms var(--ease);
  z-index: 20;
}
.toast[data-show="1"] { opacity: 1; transform: translate(-50%, 0); }

/* ---------- theme-song button ----------
   Sits under the toast in the stacking order so a "Copied" confirmation
   is never hidden behind it, and clears the iOS home indicator via the
   safe-area inset the viewport-fit=cover meta opts us into. */
.music {
  position: fixed;
  right: 16px;
  bottom: calc(18px + env(safe-area-inset-bottom, 0px));
  width: 46px;
  height: 46px;
  display: grid;
  place-items: center;
  border-radius: 999px;
  border: 1.5px solid var(--rose);
  background: var(--card);
  color: var(--olive-deep);
  box-shadow: var(--shadow-md);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform 120ms var(--ease-tap), background-color 160ms var(--ease-tap);
  z-index: 18;
}
.music:hover  { background: var(--cream-1); }
.music:active { transform: scale(.94); }
.music:focus-visible { outline: 2px solid var(--olive); outline-offset: 3px; }

/* equaliser bars (audible) and the muted speaker (silent) swap places */
.music__bars { display: none; gap: 3px; align-items: flex-end; height: 16px; }
.music__off  { width: 20px; height: 20px; }
.music[data-on="1"] .music__bars { display: flex; }
.music[data-on="1"] .music__off  { display: none; }

.music__bars i {
  display: block;
  width: 3px;
  border-radius: 2px;
  background: var(--olive);
  animation: wEq 900ms var(--ease) infinite alternate;
}
.music__bars i:nth-child(1) { height: 7px;  animation-delay: 0ms; }
.music__bars i:nth-child(2) { height: 15px; animation-delay: 180ms; }
.music__bars i:nth-child(3) { height: 10px; animation-delay: 360ms; }

@keyframes wEq { from { transform: scaleY(.35); } to { transform: scaleY(1); } }

/* buffered and waiting for the first tap — a soft ring, no motion sickness */
.music[data-pending="1"]::after {
  content: "";
  position: absolute;
  inset: -5px;
  border-radius: 999px;
  border: 1.5px solid var(--rose-lt);
  animation: wRing 2.4s var(--ease) infinite;
}
/* Named wRing, not wPulse — the map pin already owns that name and a
   second @keyframes block with the same name silently replaces it. */
@keyframes wRing {
  0%   { opacity: .9; transform: scale(.92); }
  70%  { opacity: 0;  transform: scale(1.18); }
  100% { opacity: 0;  transform: scale(1.18); }
}

@media print { .music { display: none; } }

/* ---------- reveal-on-scroll ---------- */
.reveal[data-armed="1"] { opacity: 0; }
.reveal[data-shown="1"] { animation: wRise 620ms var(--ease) both; }

/* ---------- motion & contrast preferences ---------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  .petals { display: none; }
  .par { transform: none !important; }
}


/* ---------- account rows ---------- */
.accounts {
  margin-top: 16px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.acct {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 10px 9px 12px;
  background: var(--cream-2);
  border-radius: 12px;
}
.acct__cur {
  flex: none;
  font-size: 10px;
  font-weight: 500;
  letter-spacing: .1em;
  color: #fff;
  background: var(--olive);
  padding: 3px 7px;
  border-radius: 5px;
}
.acct__num {
  flex: 1;
  text-align: left;
  font-size: 14px;
  font-weight: 500;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  letter-spacing: .02em;
}
.acct__copy {
  font: inherit;
  flex: none;
  font-size: 12px;
  font-weight: 500;
  color: var(--olive-deep);
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 6px 12px;
  cursor: pointer;
  white-space: nowrap;
  transition: transform 120ms var(--ease-tap), background-color 160ms var(--ease-tap);
}
.acct__copy:hover { background: var(--cream-1); }
.acct__copy:active { transform: scale(.96); }

/* ---------- ABA click-to-pay ---------- */
.aba {
  margin: 14px auto 0;
  max-width: 300px;
  padding: 16px 18px 18px;
  background: #FFFFFF;
  border-radius: 20px;
  box-shadow: var(--shadow-md);
  text-align: center;
}
.aba__km {
  font-family: var(--khmer);
  font-size: 14px;
  font-weight: 500;
  line-height: 1.5;
  color: var(--ink);
}
.aba__en { font-size: 11px; color: var(--muted-2); margin-top: 2px; }

.aba__links {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  margin-top: 14px;
}

.btn--aba {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 12px 10px;
  background: var(--rose-dk);
  color: #fff;
  border: 0;
  font-size: 14px;
  font-weight: 500;
  letter-spacing: .06em;
}
.btn--aba:hover { background: #A25A4F; color: #fff; }

/* ---------- venue: Khmer address line ---------- */
.venue__addr-km {
  font-family: var(--khmer);
  font-size: 13px;
  line-height: 1.6;
  color: var(--muted);
  margin-top: 4px;
}
.venue__addr { margin-top: 4px; }

/* ---------- KHQR: romanised account name ---------- */
.khqr__name-en {
  font-size: 11px;
  letter-spacing: .1em;
  color: var(--olive-lt);
  margin-top: 2px;
}

/* ---------- day picker: a carved lintel ----------
   Both days share one stone band with chamfered corners, and the selected day
   is a lit panel that slides between them — no per-tab restyling, one
   transform. The medallion holds the day's Khmer numeral inside a ring of
   eight lotus petals; selecting a day turns the ring a half-step, echoing
   បង្វិលពពិល, the popil-turning rite in the programme below. */

/* chamfered, not rounded — the corner reads as cut stone rather than a pill */
.daypick__band,
.daypick__lit {
  clip-path: polygon(
    9px 0, calc(100% - 9px) 0, 100% 9px, 100% calc(100% - 9px),
    calc(100% - 9px) 100%, 9px 100%, 0 calc(100% - 9px), 0 9px);
}

.daypick { margin-top: 16px; }

.daypick__band {
  position: relative;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  padding: 4px;
  background: var(--sand);
  /* --n days, --i selected; both written by app.js */
  --n: 2;
  --i: 0;
}

.daypick__lit {
  position: absolute;
  top: 4px;
  bottom: 4px;
  left: 4px;
  width: calc((100% - 8px) / var(--n));
  background: linear-gradient(180deg, #6E7126 0%, var(--olive-deep) 100%);
  box-shadow: inset 0 1px 0 rgba(223,195,132,.45), 0 1px 3px rgba(10,58,69,.18);
  transform: translateX(calc(var(--i) * 100%));
  transition: transform 460ms var(--ease);
  z-index: 0;
}

.dayb {
  position: relative;
  z-index: 1;
  font: inherit;
  display: flex;
  align-items: center;
  gap: 10px;
  /* medallion left, text right — the pair reads as a seal beside its title */
  justify-content: flex-start;
  padding: 9px 12px;
  border: 0;
  background: none;
  color: var(--muted);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: color 300ms var(--ease);
}
.dayb[aria-selected="true"] { color: #FBF7EE; }

.dayb__num {
  flex: none;
  width: 27px;
  height: 27px;
  display: grid;
  place-items: center;
  font-family: var(--khmer);
  font-size: 15px;
  font-weight: 600;
  line-height: 1;
  color: var(--olive-deep);
  background: rgba(95,98,28,.10);
  /* the band's chamfer again, at a quarter of the size */
  clip-path: polygon(
    5px 0, calc(100% - 5px) 0, 100% 5px, 100% calc(100% - 5px),
    calc(100% - 5px) 100%, 5px 100%, 0 calc(100% - 5px), 0 5px);
  transition: background-color 320ms var(--ease), color 320ms var(--ease);
}
.dayb[aria-selected="true"] .dayb__num {
  color: #F2E4BF;
  background: rgba(223,195,132,.20);
}

.dayb__label {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1px;
  min-width: 0;
}
.dayb__km {
  font-family: var(--khmer);
  font-size: 13px;
  font-weight: 500;
  line-height: 1.4;
  white-space: nowrap;
}
.dayb__en {
  font-size: 9px;
  letter-spacing: .16em;
  text-transform: uppercase;
  opacity: .7;
}

/* a row of lotus-petal cresting, like the cornice along a temple roof */
.daypick__cornice {
  height: 7px;
  margin-top: 5px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='11' height='7' viewBox='0 0 11 7'%3E%3Cpath d='M0 7C2.6 6.6 4.1 4.1 5.5 0 6.9 4.1 8.4 6.6 11 7Z' fill='%239C9E70'/%3E%3C/svg%3E");
  background-repeat: repeat-x;
  background-size: 11px 7px;
  opacity: .5;
}

.dayline { margin-top: 14px; }
.dayline.is-fresh { animation: wRise 460ms var(--ease) both; }
.dayline__km {
  font-family: var(--khmer);
  font-size: 13px;
  font-weight: 500;
  line-height: 1.5;
  color: var(--olive-deep);
}
.dayline__en {
  font-size: 11px;
  letter-spacing: .1em;
  color: var(--olive-lt);
  margin-top: 1px;
}

/* the programme list follows the day line, not the section header */
.dayline + .agenda { margin-top: 12px; }

/* ---------- cover letter ---------- */
.letter { margin: 30px auto 0; max-width: 330px; }

.letter__ornament {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  margin-bottom: 16px;
}
.letter__line {
  flex: 1;
  height: 1px;
  background: linear-gradient(90deg, transparent, #E3C4BC, transparent);
}

.letter__km {
  font-family: var(--khmer);
  font-size: 13px;
  font-weight: 300;
  /* Khmer stacks diacritics above and below the baseline — it needs
     noticeably more leading than Latin at the same size. */
  line-height: 2;
  color: var(--muted);
  text-indent: 1.4em;
}
.letter__km + .letter__km { margin-top: 10px; }

.letter__en {
  font-size: 11.5px;
  line-height: 1.75;
  color: var(--olive-lt);
  text-indent: 1.4em;
  text-wrap: pretty;
}
.letter__km + .letter__en { margin-top: 16px; }
.letter__en + .letter__en { margin-top: 8px; }

/* ---------- fullscreen viewer ---------- */
.viewer {
  position: fixed;
  inset: 0;
  z-index: 60;
  --drag: 0;
  display: grid;
  grid-template-rows: auto 1fr auto;
  opacity: 0;
  transition: opacity 260ms var(--ease);
}
.viewer[data-open="1"] { opacity: 1; }

/* `display: grid` above is an author rule, so it overrides the browser's
   built-in `[hidden] { display: none }` — without this the closed viewer
   stays laid out, full-screen at z-index 60, and silently eats every scroll
   and tap on the page even at opacity 0. Restate the hiding here.
   The pointer-events rule covers the 260ms close fade, when the element is
   still displayed but no longer interactive. */
.viewer[hidden] { display: none; }
.viewer:not([data-open="1"]) { pointer-events: none; }

.viewer__scrim {
  position: absolute;
  inset: 0;
  /* ink tinted toward the invitation's olive, never a flat black */
  background: #191A12;
  opacity: calc(.97 - .45 * var(--drag));
}

.viewer__bar {
  position: relative;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: calc(14px + env(safe-area-inset-top, 0px)) 16px 10px;
}
.viewer__count {
  font-family: var(--khmer);
  font-size: 13px;
  color: rgba(251,247,238,.74);
  font-variant-numeric: tabular-nums;
}
.viewer__close {
  width: 40px;
  height: 40px;
  display: grid;
  place-items: center;
  border-radius: 999px;
  border: 1px solid rgba(251,247,238,.22);
  background: rgba(251,247,238,.07);
  color: #FBF7EE;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background-color 160ms var(--ease-tap), transform 120ms var(--ease-tap);
}
.viewer__close:hover { background: rgba(251,247,238,.16); }
.viewer__close:active { transform: scale(.94); }

.viewer__track {
  position: relative;
  z-index: 1;
  display: flex;
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  overscroll-behavior: contain;
  scrollbar-width: none;
  touch-action: pan-x;
}
.viewer__track::-webkit-scrollbar { display: none; }
/* a zoomed photo owns the gesture — paging would fight the pan */
.viewer__track.is-zoomed { overflow: hidden; touch-action: none; }

.viewer__slide {
  flex: none;
  width: 100%;
  align-self: stretch;
  scroll-snap-align: center;
  display: grid;
  place-items: center;
}
.viewer__slide img {
  /* Bounded in viewport units, not percentages. A percentage max-height
     resolves against an ancestor chain that never hands down a definite
     height here, so the photo rendered at full natural size and overflowed
     the slide. dvh also tracks mobile browser chrome as it hides. */
  --chrome: calc(112px + env(safe-area-inset-top, 0px) + env(safe-area-inset-bottom, 0px));
  max-width: calc(100vw - 20px);
  max-height: calc(100dvh - var(--chrome));
  width: auto;
  height: auto;
  border-radius: 3px;
  transform-origin: center center;
  will-change: transform;
  user-select: none;
  -webkit-user-drag: none;
}

.viewer__hint {
  position: relative;
  z-index: 2;
  text-align: center;
  padding: 0 20px calc(16px + env(safe-area-inset-bottom, 0px));
  font-size: 11px;
  letter-spacing: .1em;
  color: rgba(251,247,238,.48);
  opacity: 0;
  transition: opacity 500ms var(--ease);
}
.viewer__hint[data-show="1"] { opacity: 1; }

/* the page must not scroll behind the viewer, and the music button must
   not float over a full-screen photo */
body[data-viewer-open] { overflow: hidden; }
body[data-viewer-open] .music { opacity: 0; pointer-events: none; }

@media (prefers-reduced-motion: reduce) {
  .shot.is-active .shot__frame img { animation: none; }
}
