:root { color-scheme: dark; }
/* Full-width scrolling invitation page (theme.layout = "scroll").
   Used by the adult / formal themes; the tile layout is untouched. */

.stage-scroll {
  display: block;
  position: static;
  height: auto;
  min-height: 100vh;
  overflow: visible;
  padding: 0;
  background: var(--brand-navy-dark);
}
.stage-scroll:not(.active) { display: none; }
/* Edge to edge. style.css gives #card-stage 16px of padding and .app-container a lighter card colour
   (both from the old tile layout); an ID beats this file's classes, so the invitation sat inside a
   frame of that colour — green on the beer theme, grey on Callum's (Gary 21/9). */
#card-stage.stage-scroll { padding: 0; background: var(--brand-navy-dark); }
.app-container.app-scroll { max-width: none; background: var(--brand-navy-dark); box-shadow: none; }

/* ---- hero: the glass sits in a band at the top, the words underneath ---- */
.sc-hero {
  position: relative;
  min-height: 100svh;
  display: flex; flex-direction: column;
  align-items: center; justify-content: flex-start;
  overflow: hidden; text-align: center;
  padding: 0 22px 90px;
}
.sc-hero-texture {
  position: absolute; inset: 0;
  background-size: cover; background-position: center;
  filter: brightness(0.5) contrast(1.1);
  opacity: 0.9;
}
.sc-hero::after {
  content: ""; position: absolute; inset: 0;
  background: radial-gradient(ellipse 80% 60% at 50% 40%, rgba(0,0,0,0.25), rgba(0,0,0,0.75) 75%, var(--brand-navy-dark) 100%);
}
.sc-hero-media {
  position: relative; z-index: 1;
  width: 100%; margin-bottom: 10px;
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 86%, transparent 100%);
  mask-image: linear-gradient(to bottom, #000 0%, #000 86%, transparent 100%);
}

.sc-hero-inner { position: relative; z-index: 2; max-width: 620px; }
.sc-eyebrow {
  font-family: var(--font-ui);
  font-size: 11px; letter-spacing: 5px; text-transform: uppercase;
  color: var(--brand-yellow); margin-bottom: 10px;
}
.sc-hero-title {
  font-family: var(--font-display);
  font-size: clamp(50px, 15vw, 92px); line-height: 0.95; font-weight: 600;
  color: var(--brand-white); margin: 0;
}
.sc-hero-sub {
  font-family: var(--font-ui);
  font-size: 17px; letter-spacing: 7px; text-transform: uppercase; font-weight: 500;
  color: var(--brand-white); opacity: .92; margin-top: 14px;
}
.sc-hero-date { font-family: var(--font-display); font-size: 23px; color: var(--brand-white); margin-top: 4px; }
.sc-hero-time { font-family: var(--font-ui); font-size: 12px; letter-spacing: 2px; color: var(--theme-text-muted); margin-top: 6px; }
.sc-hero-actions { display: flex; gap: 18px; justify-content: center; flex-wrap: wrap; margin-top: 30px; }

.sc-scroll-hint {
  position: absolute; bottom: 26px; left: 50%; transform: translateX(-50%);
  width: 1px; height: 42px; background: linear-gradient(to bottom, transparent, var(--brand-yellow));
  opacity: 0.7; z-index: 2;
}

/* ---- rules and sections ---- */
.sc-rule {
  width: 92px; height: 1px; margin: 22px auto;
  background: linear-gradient(90deg, transparent, var(--brand-yellow), transparent);
}
.sc-rule-sm { width: 58px; margin: 14px 0 26px; }
.sc-centered .sc-rule-sm { margin-left: auto; margin-right: auto; }

.sc-section {
  max-width: 620px;
  margin: 0 auto;
  padding: 58px 22px;
  border-bottom: 1px solid var(--theme-card-border);
}
.sc-section:last-of-type { border-bottom: 0; }
.sc-centered { text-align: center; }
.sc-countdown-wrap { padding-top: 36px; padding-bottom: 36px; }

.sc-h2 {
  font-family: var(--font-display);
  font-size: 34px; font-weight: 600; color: var(--brand-white); margin: 0;
}
.sc-script {
  font-family: var(--font-script, 'Great Vibes', cursive);
  font-size: 46px; line-height: 1.1; color: var(--brand-yellow); margin: 0 0 10px;
}
.sc-lead { font-size: 17px; line-height: 1.7; color: var(--theme-text-primary); }
.sc-signature { font-family: var(--font-script, 'Great Vibes', cursive); font-size: 30px; color: var(--brand-yellow); margin-top: 18px; }

/* ---- detail rows ---- */
.sc-detail { display: flex; gap: 18px; padding: 15px 0; border-bottom: 1px solid var(--theme-card-border); }
.sc-detail:last-child { border-bottom: 0; }
.sc-label {
  flex: 0 0 96px;
  font-family: var(--font-ui); font-size: 11px; letter-spacing: 3px;
  text-transform: uppercase; color: var(--brand-yellow); padding-top: 5px;
}
.sc-value { font-family: var(--font-display); font-size: 21px; line-height: 1.45; color: var(--theme-text-primary); }

/* ---- programme ---- */
.sc-timeline { list-style: none; margin: 0; padding: 0; }
.sc-timeline li {
  display: grid; grid-template-columns: 72px 16px 1fr; align-items: center;
  gap: 14px; padding: 14px 0; border-bottom: 1px solid var(--theme-card-border);
}
.sc-timeline li:last-child { border-bottom: 0; }
.sc-time { font-family: var(--font-ui); font-weight: 600; letter-spacing: 1px; color: var(--brand-yellow); }
.sc-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--brand-yellow); opacity: 0.6; }
.sc-what { font-family: var(--font-display); font-size: 20px; color: var(--theme-text-primary); }

/* ---- dress code ---- */
.sc-swatches { display: flex; gap: 12px; justify-content: center; margin-top: 22px; }
.sc-swatches span {
  width: 40px; height: 40px; border-radius: 50%;
  border: 1px solid rgba(255,255,255,0.2); box-shadow: 0 6px 14px rgba(0,0,0,0.5);
}

/* ---- map ---- */
.sc-map {
  border-radius: 14px; overflow: hidden; border: 1px solid var(--theme-card-border);
  box-shadow: 0 16px 40px rgba(0,0,0,0.5);
}
.sc-map iframe { width: 100%; height: 260px; border: 0; display: block; filter: grayscale(1) invert(0.9) contrast(0.85); }
.sc-btn-row { display: flex; gap: 14px; margin-top: 20px; flex-wrap: wrap; justify-content: center; }
.sc-btn-row .sc-btn { flex: 0 0 auto; }
/* the other Maps / calendar app, small, under the buttons */
.sc-alt-links { margin: 12px 0 0; text-align: center; font-size: 12px; letter-spacing: 0.5px; color: var(--brand-gray-muted); }
.sc-alt-links a { color: var(--brand-gray-muted); text-decoration: underline; text-underline-offset: 3px; }
.sc-alt-links [hidden] { display: none; }

/* ---- gallery ---- */
.sc-gallery { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; }
.sc-gallery figure { margin: 0; border-radius: 12px; overflow: hidden; aspect-ratio: 3 / 4; }
.sc-gallery figure:first-child { grid-column: 1 / -1; aspect-ratio: 16 / 10; }
.sc-gallery img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* ---- buttons ---- */
.sc-btn {
  display: inline-block; padding: 15px 30px; border-radius: 999px;
  font-family: var(--font-ui); font-size: 13px; letter-spacing: 3px;
  text-transform: uppercase; text-decoration: none; cursor: pointer;
  transition: transform .15s ease, box-shadow .15s ease;
}
.sc-btn:active { transform: translateY(1px); }
.sc-btn-ghost { background: rgba(255,255,255,0.03); border: 1px solid var(--brand-yellow); color: var(--brand-yellow); }
.sc-btn-solid {
  background: #d8b45e;
  background-image: linear-gradient(135deg, #f3e2a8 0%, #d8b45e 45%, #c9a24d 100%);
  background-color: #d8b45e;   /* stays gold even if a browser drops the gradient */
  border: 1px solid rgba(255,255,255,0.35); color: #1a1408; font-weight: 600;
  box-shadow: 0 12px 30px rgba(0,0,0,0.45);
}
.sc-btn-block { display: block; width: 100%; margin-top: 22px; }

/* ---- form ---- */
.sc-form label, .sc-legend {
  display: block; margin: 20px 0 8px;
  font-family: var(--font-ui); font-size: 11px; letter-spacing: 3px;
  text-transform: uppercase; color: var(--brand-yellow);
}
.sc-form input[type="text"], .sc-form select, .sc-form textarea {
  width: 100%; padding: 15px 16px; border-radius: 10px;
  background: rgba(255,255,255,0.03); border: 1px solid var(--theme-card-border);
  color: var(--theme-text-primary); font-family: var(--font-ui); font-size: 16px;
}
.sc-form input:focus, .sc-form select:focus, .sc-form textarea:focus {
  outline: none; border-color: var(--brand-yellow);
}
.sc-choice { display: flex; gap: 12px; }
.sc-choice label { flex: 1; margin: 0; }
/* the host's own pick-one questions can have several options, so they wrap two to a row */
.sc-choice-wrap { flex-wrap: wrap; gap: 10px; }
.sc-choice-wrap label { flex: 1 1 calc(50% - 5px); min-width: 0; }
.sc-choice input { position: absolute; opacity: 0; pointer-events: none; }
.sc-choice span {
  display: block; text-align: center; padding: 15px 10px; border-radius: 10px;
  border: 1px solid var(--theme-card-border); color: var(--theme-text-primary);
  font-family: var(--font-ui); font-size: 13px; letter-spacing: 2px; text-transform: uppercase;
}
.sc-choice input:checked + span {
  background: #d8b45e; border-color: #d8b45e; color: #1a1408; font-weight: 600;
}
.sc-thanks { margin-top: 22px; text-align: center; font-size: 17px; color: var(--theme-text-primary); }

/* ---- footer ---- */
.sc-footer { text-align: center; padding: 64px 22px 80px; }
.sc-footer .sc-script { font-size: 54px; }
.sc-footer-sub {
  font-family: var(--font-ui); font-size: 11px; letter-spacing: 5px;
  text-transform: uppercase; color: var(--theme-text-muted); margin-top: 10px;
}

@media (min-width: 720px) {
  .sc-section { padding: 74px 22px; }
  .sc-map iframe { height: 340px; }
}

/* ---- gatefold envelope, the interactive entry for scroll themes ---- */
.gf-scene { position: absolute; inset: 0; width: 100%; height: 100%; overflow: hidden; }
.gf-envelope {
  position: absolute; inset: 0;   /* full bleed, exactly like the video */
  width: 100%; height: 100%;
}
.gf-panel {
  position: absolute; top: 0; bottom: 0; width: 50%; overflow: hidden;
  transition: transform 1s cubic-bezier(.4,0,.2,1), opacity .45s ease .7s;
}
.gf-left  { left: 0; }
.gf-right { right: 0; }
/* one full envelope face per panel, offset so each shows its own half */
.gf-face { position: absolute; top: 0; bottom: 0; width: 200%; }
.gf-left  .gf-face { left: 0; }
.gf-right .gf-face { right: 0; }
.gf-paper { position: absolute; inset: 0; background-size: cover; background-position: center; }
.gf-folds { position: absolute; inset: 0; width: 100%; height: 100%; }
.gf-flap { position: absolute; inset: 0; pointer-events: none; }
.gf-flap-side-l { clip-path: polygon(0 0, 50% 50%, 0 100%); background: linear-gradient(90deg, rgba(255,255,255,0.035), rgba(0,0,0,0.16)); }
.gf-flap-side-r { clip-path: polygon(100% 0, 50% 50%, 100% 100%); background: linear-gradient(270deg, rgba(255,255,255,0.035), rgba(0,0,0,0.16)); }
.gf-flap-bottom { clip-path: polygon(0 100%, 50% 50%, 100% 100%); background: linear-gradient(0deg, rgba(255,255,255,0.02), rgba(0,0,0,0.26)); }
.gf-flap-top    { clip-path: polygon(0 0, 100% 0, 50% 50%); background: linear-gradient(180deg, rgba(255,255,255,0.07), rgba(255,255,255,0.015) 60%, rgba(0,0,0,0.1)); }
/* half of the wax seal, stuck to its own panel */
.gf-seal-half { position: absolute; top: 50%; width: 44%; aspect-ratio: 1; }
.gf-left  .gf-seal-half { right: 0; transform: translate(50%, -50%); clip-path: inset(0 50% 0 0); }
.gf-right .gf-seal-half { left: 0;  transform: translate(-50%, -50%); clip-path: inset(0 0 0 50%); }
.gf-seal-half img { width: 100%; height: 100%; display: block; filter: drop-shadow(0 10px 14px rgba(0,0,0,0.6)); }
.gf-seal-half span {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  font-family: var(--font-script, 'Great Vibes', cursive); font-size: clamp(34px, 10vw, 54px);
  color: #6b4d17; text-shadow: 0 1px 0 rgba(255,240,200,.5), 0 -1px 1px rgba(60,40,10,.7);
}
.gf-seal-hit {
  position: absolute; top: 50%; left: 50%;
  width: 190px; height: 190px; margin: -95px 0 0 -95px;
  background: none; border: 0; padding: 0; cursor: pointer;
  -webkit-tap-highlight-color: transparent; touch-action: none; z-index: 5;
}
.gf-ring { position: absolute; inset: 0; width: 100%; height: 100%; transform: rotate(-90deg); pointer-events: none; }
.gf-ring { display: none; }   /* a tap opens it, so no hold-progress ring */
/* 15% up, not tucked against the bottom edge (Gary 21/9: "it's right at the very bottom") */
.gf-hint {
  position: absolute; bottom: calc(15% + env(safe-area-inset-bottom, 0px)); z-index: 6; left: 0; right: 0; text-align: center;
  font-family: var(--font-ui); font-size: 11px; letter-spacing: 4px;
  text-transform: uppercase; color: var(--theme-text-muted);
  animation: gf-pulse 2.6s ease-in-out infinite;
}
@keyframes gf-pulse { 0%,100% { opacity: .45 } 50% { opacity: 1 } }
.gf-envelope.gf-open .gf-left  { transform: translateX(-108%); opacity: 0; }
.gf-envelope.gf-open .gf-right { transform: translateX(108%); opacity: 0; }

#film-stage:not(.active) { display: none !important; }
#envelope-stage { display: none; }
/* The envelope has no backdrop of its own on scroll themes: style.css gives #envelope-stage a
   purple radial gradient (the Halloween theme's), and that is what the halves used to part onto.
   With it transparent, and the invitation already rendered underneath, they part onto the drink. */
#envelope-stage.active {
  display: block; position: fixed; top: 0; left: 0; right: 0; height: 100vh; height: 100svh;
  overflow: hidden; z-index: 30; background: transparent; padding: 0;
}
/* the invitation is real content under the envelope now, so the lock is the strict kind or a
   phone will still drag the page about behind the seal */
body.gf-locked { overflow: hidden; height: 100svh; overscroll-behavior: none; position: fixed; top: 0; left: 0; right: 0; width: 100%; }
body.gf-locked .stage-scroll { pointer-events: none; }
/* The music pill belongs to the invitation, so it stays away until the envelope has gone —
   keyed off the envelope rather than the lock, which is released the moment the seal is tapped */
#envelope-stage.active ~ #card-stage .sc-music { display: none; }

.sc-form .hidden { display: none; }
.sc-thanks[hidden] { display: none; }

/* ---- music: starts on the tap that opens the envelope, and can be turned off ---- */
.sc-music {
  position: fixed; top: 14px; right: 14px; z-index: 40;
  display: flex; align-items: center; gap: 9px;
  padding: 9px 15px 9px 12px; border-radius: 999px;
  background: rgba(10,10,12,0.72); border: 1px solid var(--brand-yellow);
  color: var(--brand-yellow); cursor: pointer;
  font-family: var(--font-ui); font-size: 10px; letter-spacing: 2.5px; text-transform: uppercase;
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
}
.sc-music-bars { display: flex; align-items: flex-end; gap: 2px; height: 12px; }
.sc-music-bars i { width: 2px; height: 4px; background: currentColor; border-radius: 1px; }
.sc-music[data-playing="1"] .sc-music-bars i { animation: sc-eq .9s ease-in-out infinite; }
.sc-music[data-playing="1"] .sc-music-bars i:nth-child(2) { animation-delay: .15s; }
.sc-music[data-playing="1"] .sc-music-bars i:nth-child(3) { animation-delay: .3s; }
@keyframes sc-eq { 0%,100% { height: 4px } 50% { height: 12px } }
body.gf-locked .sc-music { display: none; }

/* ---- the front page animates itself in when the envelope opens (the glass stays still) ---- */
.sc-hero-media img { transform: scale(1.02); }
/* no entrance of its own for the glass: the envelope parting IS its entrance now, and a fade here
   made it vanish and come back just as the halves cleared */
.sc-hero.armed .sc-eyebrow,
.sc-hero.armed .sc-hero-title,
.sc-hero.armed .sc-hero-sub,
.sc-hero.armed .sc-rule,
.sc-hero.armed .sc-hero-date,
.sc-hero.armed .sc-hero-time,
.sc-hero.armed .sc-hero-actions { opacity: 0; }
.sc-hero.is-in .sc-eyebrow     { animation: sc-fade-up .7s ease-out .25s both; }
.sc-hero.is-in .sc-hero-title  { animation: sc-drop-in .85s cubic-bezier(.2,.9,.3,1) .4s both; }
.sc-hero.is-in .sc-hero-sub    { animation: sc-fade-up .7s ease-out .68s both; }
.sc-hero.is-in .sc-rule        { animation: sc-widen .6s ease-out .82s both; }
.sc-hero.is-in .sc-hero-date   { animation: sc-fade-up .7s ease-out .92s both; }
.sc-hero.is-in .sc-hero-time   { animation: sc-fade-up .7s ease-out 1.02s both; }
.sc-hero.is-in .sc-hero-actions{ animation: sc-fade-up .7s ease-out 1.18s both; }
@keyframes sc-fade-up { from { opacity: 0; transform: translateY(18px) } to { opacity: 1; transform: none } }
@keyframes sc-drop-in { 0% { opacity: 0; transform: translateY(-46px) scale(1.18) } 100% { opacity: 1; transform: none } }
@keyframes sc-widen  { from { opacity: 0; transform: scaleX(.2) } to { opacity: 1; transform: none } }
@media (prefers-reduced-motion: reduce) {
  .sc-hero .sc-eyebrow, .sc-hero .sc-hero-title, .sc-hero .sc-hero-sub,
  .sc-hero .sc-rule, .sc-hero .sc-hero-date, .sc-hero .sc-hero-time,
  .sc-hero .sc-hero-actions { opacity: 1; animation: none !important; }
}

/* ---- browser fallbacks: svh and CSS-var gradients are not everywhere ---- */
.sc-hero { min-height: 100vh; min-height: 100svh; padding-top: 0; justify-content: flex-start; }
.sc-hero-media { height: 42vh; height: 42svh; max-height: 380px; margin-top: 8px; }
.sc-hero-media img, .sc-hero-media video {
  width: 100%; height: 100%; object-fit: contain; object-position: center center; display: block;
}
#envelope-stage.active { height: 100vh; height: 100svh; }
body.gf-locked { height: 100vh; height: 100svh; }
.gf-envelope { min-height: 100vh; min-height: 100svh; }
/* solid colours first, so a browser that ignores the gradient still gets gold, not brown */
.sc-btn-solid { color: #1a1408; }   /* the gradient above already carries a solid fallback */
.sc-btn-ghost { background-color: rgba(255,255,255,0.03); }
.sc-music { background-color: rgba(10,10,12,0.85); }

#gifts .sc-btn { margin-top: 26px; }
#gifts .gifts-secret { margin-top: 18px; }
#gifts .sc-gift-link { margin-top: 22px; }

/* save-the-date: the one line under the date */
.sc-std { padding-top: 34px; padding-bottom: 80px; border-bottom: 0; }
.sc-std-follow {
  font-family: var(--font-ui); font-size: 13px; letter-spacing: 6px; text-transform: uppercase;
  color: var(--brand-yellow); margin: 0;
}

/* ---- the host's YouTube song: tap to play ---- */
.sc-yt {
  position: relative; aspect-ratio: 16 / 9; border-radius: 14px; overflow: hidden;
  border: 1px solid var(--theme-card-border); box-shadow: 0 16px 40px rgba(0,0,0,0.5); background: #000;
}
.sc-yt-play { position: absolute; inset: 0; width: 100%; height: 100%; padding: 0; border: 0; background: none; cursor: pointer; }
.sc-yt-play img { width: 100%; height: 100%; object-fit: cover; display: block; filter: brightness(0.62); }
.sc-yt-btn {
  position: absolute; left: 50%; top: 50%; width: 74px; height: 74px; margin: -37px 0 0 -37px;
  border-radius: 50%; background: var(--brand-yellow); box-shadow: 0 10px 30px rgba(0,0,0,0.55);
}
.sc-yt-btn::after {
  content: ""; position: absolute; left: 30px; top: 23px;
  border-left: 22px solid #140f08; border-top: 14px solid transparent; border-bottom: 14px solid transparent;
}
.sc-yt iframe { width: 100%; height: 100%; border: 0; display: block; }
.sc-yt-hint {
  font-family: var(--font-ui); font-size: 11px; letter-spacing: 3px; text-transform: uppercase;
  color: var(--theme-text-muted); margin-top: 14px;
}

/* ---- sections fly in from the sides as you scroll ----
   Gary 21/9: "more interactive and flying in from the sides". Each line of a section comes in from
   alternate sides, one after another, with a touch of overshoot so it lands rather than stops. The
   rows inside (running order, countdown boxes, photos) take their own turns instead of moving as a
   block, and the colour swatches pop in one by one. It plays again every time a section comes back
   into view (guest.js drops .seen when it leaves). */
.sc-section.reveal > *, .sc-footer.reveal > * { opacity: 0; transform: translateX(-84px); }
.sc-section.reveal > *:nth-child(even), .sc-footer.reveal > *:nth-child(even) { transform: translateX(84px); }
.sc-section.reveal.seen > *, .sc-footer.reveal.seen > * {
  opacity: 1; transform: none;
  transition: opacity .7s ease-out, transform .8s cubic-bezier(.2,.9,.3,1.08);
}
.sc-section.reveal.seen > *:nth-child(2) { transition-delay: .09s; }
.sc-section.reveal.seen > *:nth-child(3) { transition-delay: .18s; }
.sc-section.reveal.seen > *:nth-child(4) { transition-delay: .27s; }
.sc-section.reveal.seen > *:nth-child(5) { transition-delay: .36s; }
.sc-section.reveal.seen > *:nth-child(6) { transition-delay: .45s; }
.sc-section.reveal.seen > *:nth-child(n+7) { transition-delay: .52s; }

/* containers of rows stay put; their rows fly in */
.sc-section.reveal > .sc-timeline, .sc-section.reveal > .countdown-bar,
.sc-section.reveal > .sc-swatches, .sc-section.reveal > .sc-gallery { opacity: 1; transform: none; transition: none; }

.sc-section.reveal .sc-timeline li,
.sc-section.reveal .countdown-item,
.sc-section.reveal .sc-gallery figure { opacity: 0; transform: translateX(-70px); }
.sc-section.reveal .sc-timeline li:nth-child(even),
.sc-section.reveal .countdown-item:nth-child(even),
.sc-section.reveal .sc-gallery figure:nth-child(even) { transform: translateX(70px); }
.sc-section.reveal.seen .sc-timeline li,
.sc-section.reveal.seen .countdown-item,
.sc-section.reveal.seen .sc-gallery figure {
  opacity: 1; transform: none;
  transition: opacity .6s ease-out, transform .75s cubic-bezier(.2,.9,.3,1.08);
}
.sc-section.reveal.seen .sc-timeline li:nth-child(1), .sc-section.reveal.seen .countdown-item:nth-child(1), .sc-section.reveal.seen .sc-gallery figure:nth-child(1) { transition-delay: .18s; }
.sc-section.reveal.seen .sc-timeline li:nth-child(2), .sc-section.reveal.seen .countdown-item:nth-child(2), .sc-section.reveal.seen .sc-gallery figure:nth-child(2) { transition-delay: .28s; }
.sc-section.reveal.seen .sc-timeline li:nth-child(3), .sc-section.reveal.seen .countdown-item:nth-child(3), .sc-section.reveal.seen .sc-gallery figure:nth-child(3) { transition-delay: .38s; }
.sc-section.reveal.seen .sc-timeline li:nth-child(4), .sc-section.reveal.seen .countdown-item:nth-child(4), .sc-section.reveal.seen .sc-gallery figure:nth-child(4) { transition-delay: .48s; }
.sc-section.reveal.seen .sc-timeline li:nth-child(5), .sc-section.reveal.seen .sc-gallery figure:nth-child(5) { transition-delay: .58s; }
.sc-section.reveal.seen .sc-timeline li:nth-child(n+6), .sc-section.reveal.seen .sc-gallery figure:nth-child(n+6) { transition-delay: .66s; }

.sc-section.reveal .sc-swatches span { opacity: 0; transform: scale(0.3); }
.sc-section.reveal.seen .sc-swatches span {
  opacity: 1; transform: none;
  transition: opacity .45s ease-out, transform .55s cubic-bezier(.3,1.6,.5,1);
}
.sc-section.reveal.seen .sc-swatches span:nth-child(2) { transition-delay: .08s; }
.sc-section.reveal.seen .sc-swatches span:nth-child(3) { transition-delay: .16s; }
.sc-section.reveal.seen .sc-swatches span:nth-child(4) { transition-delay: .24s; }
.sc-section.reveal.seen .sc-swatches span:nth-child(n+5) { transition-delay: .32s; }

/* things flying in from off the side must never make the page scroll sideways */
.stage-scroll { overflow-x: hidden; overflow-x: clip; }

@media (prefers-reduced-motion: reduce) {
  .sc-section.reveal > *, .sc-footer.reveal > *,
  .sc-section.reveal .sc-timeline li, .sc-section.reveal .countdown-item,
  .sc-section.reveal .sc-gallery figure, .sc-section.reveal .sc-swatches span { opacity: 1; transform: none; }
}

/* ---- the four-flap envelope (envelope style "flaps", after Gary's second reference video) ----
   Four paper triangles meeting just above the middle of the screen, where the seal sits. On the tap
   each lifts towards you about its own edge and folds away out of sight, top first with the seal on
   it, then the sides, then the bottom, straight onto the invitation underneath. Each flap carries its
   own perspective() so the stacking order is plain DOM order on every browser.
   Gary 21/9 on his phone: seal and meeting point moved up to 47% (they were at 56%, visibly low);
   top and bottom shaded the same (the bottom was darker and read as a shadow); and no lined rim
   on opening — it goes straight into the invitation. */
.fl-scene { position: absolute; inset: 0; overflow: hidden; }
/* Laptop and desktop screens, and phones turned sideways (Gary 22/9: on a laptop the envelope filled the width
   and the seal came out ~500px across): the envelope is a phone-shaped card in the middle, 9:16 of the screen's
   height, for both envelope styles (sizes inside are % / container units, so they follow). A 100vmax spread
   shadow covers the rest of the screen in the page's colour, so the invitation underneath isn't seen round it;
   it fades while the last flaps open (browsers without :has keep it until the page takes over). Portrait
   tablets (3:4) keep the full-width envelope. */
@media (min-aspect-ratio: 4/5) {
  .fl-scene {
    left: 50%; right: auto; width: min(100%, calc(100vh * 9 / 16)); width: min(100%, calc(100svh * 9 / 16)); translate: -50% 0;
    box-shadow: 0 0 0 100vmax var(--brand-navy-dark);
    transition: box-shadow .9s ease 1.2s;
  }
  .fl-scene:has(.gf-open) { box-shadow: 0 0 0 100vmax transparent; }
}
.fl-envelope { position: absolute; inset: 0; }
.fl-flap {
  position: absolute; inset: 0;
  filter: drop-shadow(0 2px 7px rgba(0,0,0,0.42));
  backface-visibility: hidden; -webkit-backface-visibility: hidden;
  will-change: transform, opacity;
}
.fl-face { position: absolute; inset: 0; background-size: cover; background-position: center; }
.fl-face::after { content: ""; position: absolute; inset: 0; }
/* the fine accent lines along the flap edges, when a theme asks for them (theme.envelope_finish) */
.fl-edge { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
/* the triangles; the top one is last in the markup so it lies over the others, as a sealed flap does */
.fl-left  .fl-face { clip-path: polygon(0 0, 52% 47%, 0 100%); }
.fl-right .fl-face { clip-path: polygon(100% 0, 48% 47%, 100% 100%); }
.fl-bottom .fl-face { clip-path: polygon(0 100%, 50% 40%, 100% 100%); }
.fl-top   .fl-face { clip-path: polygon(0 0, 100% 0, 50% 47%); }
/* even light: the top and bottom flaps are shaded as mirror images, the sides just a touch */
.fl-top .fl-face::after    { background: linear-gradient(180deg, rgba(255,255,255,0.04), rgba(0,0,0,0.05)); }
.fl-bottom .fl-face::after { background: linear-gradient(0deg,   rgba(255,255,255,0.04), rgba(0,0,0,0.05)); }
.fl-left .fl-face::after   { background: linear-gradient(90deg,  rgba(255,255,255,0.02), rgba(0,0,0,0.07)); }
.fl-right .fl-face::after  { background: linear-gradient(270deg, rgba(255,255,255,0.02), rgba(0,0,0,0.07)); }

.fl-top    { transform-origin: 50% 0;    transform: perspective(1900px) rotateX(0deg); }
.fl-bottom { transform-origin: 50% 100%; transform: perspective(1900px) rotateX(0deg); }
.fl-left   { transform-origin: 0 50%;    transform: perspective(1900px) rotateY(0deg); }
.fl-right  { transform-origin: 100% 50%; transform: perspective(1900px) rotateY(0deg); }

/* the seal sits whole on the tip of the top flap and lifts away with it */
.fl-seal {
  position: absolute; left: 50%; top: 47%; width: 40%; aspect-ratio: 1;
  transform: translate(-50%, -50%);
}
.fl-seal img { width: 100%; height: 100%; display: block; filter: drop-shadow(0 10px 14px rgba(0,0,0,0.6)); }
.fl-seal span {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  font-family: var(--font-script, 'Great Vibes', cursive); font-size: clamp(34px, 10vw, 54px);
  color: rgba(40, 26, 8, 0.78); text-shadow: 0 1px 0 rgba(255,240,200,.5), 0 -1px 1px rgba(60,40,10,.7);
}
.fl-seal-hit {
  position: absolute; left: 50%; top: 47%; width: 190px; height: 190px; margin: -95px 0 0 -95px;
  background: none; border: 0; padding: 0; cursor: pointer; z-index: 6;
  -webkit-tap-highlight-color: transparent; touch-action: manipulation;
}

/* opening: flaps lift towards you and fold away about their edges, one after another */
/* The flaps fade as they turn, gone by 85%. Holding them solid to the end left each flap's outer edge
   standing as a sliver while it folded: invisible on black paper, a green frame round the pint on the
   beer theme (Gary 21/9). */
/* the top flap carries the seal: a slow tug first (pulled up and towards you) while the seal holds on to the
   flaps under it, then it comes away and the flap lifts with the wax on it, solid until it is nearly edge-on
   (Gary 22/9: "showing the wax attached to it"; and not a jump: "it's got to look like it's stuck ... and then
   that just gets pulled off") */
@keyframes fl-lift-top {
  0%   { transform: perspective(1900px) translateY(0) rotateX(0deg); opacity: 1; animation-timing-function: cubic-bezier(.35, 0, .65, 1); }
  30%  { transform: perspective(1900px) translateY(-1.2%) rotateX(12deg); opacity: 1; animation-timing-function: cubic-bezier(.45, 0, .3, 1); }
  75%  { opacity: 1; }
  92%  { opacity: 0; }
  100% { transform: perspective(1900px) translateY(-1.2%) rotateX(88deg); opacity: 0; }
}
@keyframes fl-lift-bottom { 0% { transform: perspective(1900px) rotateX(0deg); opacity: 1; } 30% { opacity: 1; } 85% { opacity: 0; } 100% { transform: perspective(1900px) rotateX(-88deg); opacity: 0; } }
@keyframes fl-lift-left   { 0% { transform: perspective(1900px) rotateY(0deg); opacity: 1; } 30% { opacity: 1; } 85% { opacity: 0; } 100% { transform: perspective(1900px) rotateY(-88deg); opacity: 0; } }
@keyframes fl-lift-right  { 0% { transform: perspective(1900px) rotateY(0deg); opacity: 1; } 30% { opacity: 1; } 85% { opacity: 0; } 100% { transform: perspective(1900px) rotateY(88deg);  opacity: 0; } }

/* slowed down (Gary 22/9: "slow all the envelope openings down"): the top flap is tugged, lets go of the seal
   and lifts (0-1.5s); then the sides and the bottom all open together (Gary 22/9: "have them all kind of open at
   the same time"), done by 2.2s */
.fl-envelope.gf-open .fl-top    { animation: fl-lift-top    1.5s linear forwards; }
.fl-envelope.gf-open .fl-seal   { animation: fl-seal-peel   1.5s linear forwards; }
.fl-envelope.gf-open .fl-left   { animation: fl-lift-left   1.1s cubic-bezier(.45,0,.3,1) 1.1s forwards; }
.fl-envelope.gf-open .fl-right  { animation: fl-lift-right  1.1s cubic-bezier(.45,0,.3,1) 1.1s forwards; }
.fl-envelope.gf-open .fl-bottom { animation: fl-lift-bottom 1.1s cubic-bezier(.45,0,.3,1) 1.1s forwards; }
/* the seal while the top flap is tugged: held by its lower edge on the flaps underneath, stretched a little and
   kept flat (the flap's rise and turn undone), then it lets go with a small snap and rides up on the flap */
.fl-seal { transform-origin: 50% 100%; }
@keyframes fl-seal-peel {
  0%   { transform: translate(-50%, -50%) translateY(0) scaleY(1) perspective(800px) rotateX(0deg); animation-timing-function: cubic-bezier(.35, 0, .65, 1); }
  30%  { transform: translate(-50%, -50%) translateY(6%) scaleY(1.05) perspective(800px) rotateX(-12deg); animation-timing-function: cubic-bezier(.3, 0, .4, 1.5); }
  38%  { transform: translate(-50%, -50%) translateY(0) scaleY(1) perspective(800px) rotateX(0deg); }
  100% { transform: translate(-50%, -50%) translateY(0) scaleY(1) perspective(800px) rotateX(0deg); }
}
/* its shadow grows as it comes away from the paper (the dark designs' shadow; no light design uses these flaps) */
html:not([data-tone="light"]) .fl-envelope.gf-open .fl-seal :is(img, canvas) { animation: fl-seal-lift 1.5s linear forwards; }
@keyframes fl-seal-lift {
  0%, 30% { filter: drop-shadow(0 10px 14px rgba(0,0,0,0.6)); }
  38%  { filter: drop-shadow(0 20px 22px rgba(0,0,0,0.55)); }
  100% { filter: drop-shadow(0 16px 18px rgba(0,0,0,0.58)); }
}
@media (prefers-reduced-motion: reduce) {
  .fl-envelope.gf-open :is(.fl-flap, .fl-seal, .fl-seal img, .fl-seal canvas) { animation-duration: .01s; animation-delay: 0s; }
}

/* the seam is drawn inside the face so the wax seal sits on top of it, never crossed by it */
.gf-seam {
  position: absolute; top: 0; bottom: 0; left: 50%; width: 1px;
  background: rgba(201,162,77,0.9); transform: translateX(-0.5px);
}

/* keep the gold gold even under a browser's own dark or high-contrast mode */
.sc-btn-solid, .sc-choice input:checked + span, .sc-music {
  forced-color-adjust: none;
  -webkit-print-color-adjust: exact;
  print-color-adjust: exact;
}

/* =====================================================================================
   THE NEW LOOK (?look=new) — ideas from Gary's reference listings, 21 Sep 2026.
   Everything here is scoped to body.look-new, so the invitation as it stands is untouched
   until a theme chooses "look": "new".
   ===================================================================================== */

.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.look-new .wd { display: inline-block; white-space: nowrap; }
.look-new .l, .look-new .w { display: inline-block; }

/* ---- the hero writes itself in: eyebrow word by word, the name in script like handwriting,
        the occasion letter by letter (Olivia's ribbon envelope, the cauldron's BREWING) ---- */
.look-new .sc-hero.is-in .sc-eyebrow,
.look-new .sc-hero.is-in .sc-hero-title,
.look-new .sc-hero.is-in .sc-hero-sub { animation: none; opacity: 1; }

.look-new .sc-eyebrow .w { opacity: 0; transform: translateY(10px); }
.look-new .sc-hero.is-in .sc-eyebrow .w { animation: nl-in .55s ease-out forwards; animation-delay: calc(.15s + var(--i) * .13s); }

.look-new .sc-hero-title {
  font-family: var(--font-script, 'Great Vibes', cursive); font-weight: 400;
  font-size: clamp(66px, 20vw, 122px); line-height: 1.06; margin: 2px 0 0;
}
/* a soft-edged wipe runs left to right across the name, like a pen writing it */
.look-new .hw {
  display: inline-block; padding: .08em .24em .16em; margin: 0 -.24em;
  -webkit-mask-image: linear-gradient(90deg, #000 0 42%, transparent 58% 100%);
          mask-image: linear-gradient(90deg, #000 0 42%, transparent 58% 100%);
  -webkit-mask-size: 250% 100%; mask-size: 250% 100%;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: 100% 0; mask-position: 100% 0;
}
.look-new .sc-hero.is-in .hw { animation: nl-write 1.7s cubic-bezier(.5,.1,.3,1) .55s forwards; }
@keyframes nl-write { to { -webkit-mask-position: 0 0; mask-position: 0 0; } }

.look-new .sc-hero-sub .l { opacity: 0; transform: translateY(9px) scale(.55); }
.look-new .sc-hero.is-in .sc-hero-sub .l { animation: nl-pop .5s cubic-bezier(.3,1.6,.5,1) forwards; animation-delay: calc(1.55s + var(--i) * .055s); }

/* the rest follows once the name has been written */
.look-new .sc-hero.is-in .sc-rule         { animation-delay: 2.15s; }
.look-new .sc-hero.is-in .sc-hero-date    { animation-delay: 2.3s; }
.look-new .sc-hero.is-in .sc-hero-time    { animation-delay: 2.42s; }
.look-new .sc-hero.is-in .sc-hero-actions { animation-delay: 2.6s; }

@keyframes nl-in  { to { opacity: 1; transform: none; } }
@keyframes nl-pop { to { opacity: 1; transform: none; } }

/* ---- section headings: the letters drop in one after another as the section arrives ---- */
.look-new .sc-section.reveal > .sc-h2 { opacity: 1; transform: none; transition: none; }
.look-new .sc-h2 .l { opacity: 0; transform: translateY(-18px) rotate(-7deg); }
.look-new .sc-section.reveal.seen .sc-h2 .l {
  opacity: 1; transform: none;
  transition: opacity .35s ease-out, transform .55s cubic-bezier(.3,1.5,.5,1);
  transition-delay: calc(var(--i) * .035s);
}

/* ---- the record player (retirement + quinceañera listings) ---- */
.sc-nowplaying { max-width: 620px; margin: 0 auto; padding: 6px 22px 4px; }
.np {
  width: 100%; display: flex; align-items: center; gap: 14px; padding: 11px 18px 11px 11px;
  border-radius: 999px; border: 1px solid var(--theme-card-border); background: rgba(255,255,255,0.04);
  color: var(--theme-text-primary); font-family: var(--font-ui); text-align: left; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.np-disc {
  position: relative; flex: 0 0 50px; height: 50px; border-radius: 50%;
  background: repeating-radial-gradient(circle at 50% 50%, #0d0d0d 0 1.6px, #1f1f1f 1.6px 2.6px);
  box-shadow: 0 6px 14px rgba(0,0,0,0.55), inset 0 0 0 1px rgba(255,255,255,0.06);
}
.np-disc::before {  /* the shine across the grooves */
  content: ""; position: absolute; inset: 0; border-radius: 50%;
  background: conic-gradient(from 40deg, transparent 0 20%, rgba(255,255,255,0.13) 25%, transparent 32% 70%, rgba(255,255,255,0.08) 75%, transparent 82%);
}
.np-disc i { position: absolute; inset: 16px; border-radius: 50%; background: var(--brand-yellow); }
.np-disc i::after { content: ""; position: absolute; inset: 7px; border-radius: 50%; background: #0d0d0d; }
.np[data-playing="1"] .np-disc { animation: nl-spin 3.2s linear infinite; }
@keyframes nl-spin { to { transform: rotate(360deg); } }
.np-text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.np-label { font-size: 10px; letter-spacing: 3px; text-transform: uppercase; color: var(--brand-yellow); }
.np-title { font-family: var(--font-display); font-size: 19px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.np-wave { display: flex; align-items: center; gap: 3px; height: 30px; }
.np-wave i { width: 3px; height: 26%; border-radius: 2px; background: var(--brand-yellow); opacity: .75; }
.np[data-playing="1"] .np-wave i { animation: nl-bar .9s ease-in-out infinite alternate; }
.np-wave i:nth-child(2)  { animation-delay: -.2s; } .np-wave i:nth-child(3)  { animation-delay: -.5s; }
.np-wave i:nth-child(4)  { animation-delay: -.1s; } .np-wave i:nth-child(5)  { animation-delay: -.7s; }
.np-wave i:nth-child(6)  { animation-delay: -.35s; } .np-wave i:nth-child(7) { animation-delay: -.6s; }
.np-wave i:nth-child(8)  { animation-delay: -.15s; } .np-wave i:nth-child(9) { animation-delay: -.45s; }
.np-wave i:nth-child(10) { animation-delay: -.8s; }
@keyframes nl-bar { from { height: 18%; } to { height: 100%; } }

/* ---- icons down the running order (the bestseller's timeline) ---- */
.look-new .sc-timeline li { grid-template-columns: 64px 30px 1fr; }
.sc-ico { width: 26px; height: 26px; color: var(--brand-yellow); display: flex; align-items: center; justify-content: center; }
.sc-ico svg { width: 26px; height: 26px; }

/* ---- photos as polaroids (quinceañera listing): white border, a little tilt each ---- */
.look-new .sc-gallery { gap: 20px 16px; padding: 6px 6px 10px; }
.look-new .sc-gallery figure {
  --r: -2deg; aspect-ratio: auto; overflow: visible; border-radius: 3px;
  background: #f5f1e8; padding: 8px 8px 30px; box-shadow: 0 16px 30px rgba(0,0,0,0.55);
}
.look-new .sc-gallery figure:first-child { aspect-ratio: auto; }
.look-new .sc-gallery figure:nth-child(2) { --r: 3deg; }
.look-new .sc-gallery figure:nth-child(3) { --r: -3.5deg; }
.look-new .sc-gallery figure:nth-child(4) { --r: 2deg; }
.look-new .sc-gallery figure:nth-child(5) { --r: -1.5deg; }
.look-new .sc-gallery img { aspect-ratio: 1; height: auto; border-radius: 1px; }
.look-new .sc-gallery figure:first-child img { aspect-ratio: 4 / 3; }
.look-new .sc-section.reveal .sc-gallery figure { transform: translateX(-70px) rotate(var(--r)); }
.look-new .sc-section.reveal .sc-gallery figure:nth-child(even) { transform: translateX(70px) rotate(var(--r)); }
.look-new .sc-section.reveal.seen .sc-gallery figure,
.look-new .sc-section.reveal.seen .sc-gallery figure:nth-child(even) { transform: rotate(var(--r)); }

/* ---- the closing card: the date big over a faded still of the drink (retirement listing) ---- */
.look-new .sc-finale { position: relative; overflow: hidden; text-align: center; padding: 96px 22px 118px; }
.look-new .sc-footer.sc-finale.reveal > .sc-finale-bg,
.look-new .sc-footer.sc-finale.reveal.seen > .sc-finale-bg { opacity: .26; transform: none; transition: none; }
.sc-finale-bg { position: absolute; inset: 0; background-size: cover; background-position: center 30%; filter: saturate(.85); }
.sc-finale-bg::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(180deg, var(--brand-navy-dark) 0%, transparent 32%, transparent 62%, var(--brand-navy-dark) 100%);
}
.look-new .sc-finale > *:not(.sc-finale-bg) { position: relative; }
.sc-finale-day { font-family: var(--font-display); font-size: 132px; line-height: .9; font-weight: 600; color: var(--brand-white); margin: 0; }
/* 15/10 (Gary, christening): a script numeral's descender (the 9) dropped into the month line below */
.sc-finale-day { line-height: 1; padding-bottom: .14em; }
.sc-finale-month { font-family: var(--font-ui); font-size: 14px; letter-spacing: 8px; text-transform: uppercase; color: var(--brand-yellow); margin: 12px 0 28px; }
.look-new .sc-footer.reveal > .sc-finale-day { transform: scale(.55); }
.look-new .sc-footer.reveal.seen > .sc-finale-day { transform: none; }

@media (prefers-reduced-motion: reduce) {
  .look-new .l, .look-new .w, .look-new .hw, .look-new .sc-h2 .l { opacity: 1 !important; transform: none !important; animation: none !important; -webkit-mask-image: none; mask-image: none; }
  .np-disc, .np-wave i { animation: none !important; }
}

/* =====================================================================================
   THE PHOTO ENVELOPE (theme envelope_style "photo", views/guest.ejs; Gary 22/9 after a bestseller)
   A photographed embossed envelope with four flaps, the right-hand one on top with a real wax seal on its tip.
   The sheet keeps the photo's own proportions and covers the screen (like cover), placed so the flap's tip
   sits 17% in from the left; everything inside it is in % of the photo, so each flap's outline (theme
   envelope_photo.flap / .pieces) lines up with the picture exactly.
   ===================================================================================== */
.ph-envelope {
  container-type: size;
  --ph-h: max(100cqh, calc(100cqw / var(--ph-aspect)));
  --ph-w: calc(var(--ph-h) * var(--ph-aspect));
  --ph-left: clamp(calc(100cqw - var(--ph-w)), calc(17cqw - var(--ph-tipx) * var(--ph-w) / 100), 0px);
}
.ph-sheet { position: absolute; top: 50%; left: var(--ph-left); width: var(--ph-w); height: var(--ph-h); translate: 0 -50%; }
.ph-photo { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
/* each of the other flaps is just the part of the photo it shows, so once the right flap has gone the gap it
   covered is open onto the invitation; a soft shadow round each (on the parent, so the outline cut doesn't clip
   it) falls on the invitation along the gap's edges */
.ph-piece, .ph-flap { position: absolute; inset: 0; backface-visibility: hidden; -webkit-backface-visibility: hidden; will-change: transform, opacity; }
.ph-piece { filter: drop-shadow(0 1px 3px rgba(40,30,20,.22)); }
.ph-piece-face, .ph-flap-front { position: absolute; inset: 0; }
.ph-top    { transform-origin: 50% 0; }
.ph-bottom { transform-origin: 50% 100%; }
.ph-left   { transform-origin: 0 50%; }
.ph-flap   { transform-origin: 100% 50%; filter: drop-shadow(-2px 3px 6px rgba(40,30,20,.25)); }
/* the seal: its left edge 8% in from the screen's edge, 44% of the screen wide (Gary 22/9), on the flap's tip */
.ph-seal {
  position: absolute; left: calc(8cqw - var(--ph-left)); top: calc(var(--ph-tipy) * 1%);
  width: 44cqw; aspect-ratio: 1; translate: 0 -50%;
}
.ph-seal :is(img, canvas) { width: 100%; height: 100%; display: block; filter: drop-shadow(0 7px 10px rgba(40,30,20,.32)); }
/* tap anywhere on the envelope */
.fl-seal-hit.ph-hit { left: 0; top: 0; width: 100%; height: 100%; margin: 0; }
/* "Tap the seal to open" on embossed paper (Gary 22/9: you can't really see it; gold, to match the wax): a soft
   paper pill behind it, the words filled with the design's own metal */
.ph-scene .gf-hint {
  left: 50%; right: auto; width: max-content; max-width: 92%; transform: translateX(-50%);
  padding: 8px 18px; border-radius: 999px; font-size: 13px; font-weight: 600; letter-spacing: 4px;
  background: rgba(255,252,247,.74); box-shadow: 0 2px 10px rgba(60,45,30,.12), inset 0 0 0 1px rgba(170,130,70,.3);
  animation-name: ph-pulse;   /* the usual pulse dipped to 45%, which vanished on the roses */
}
.ph-scene .gf-hint span {
  background: linear-gradient(100deg, var(--ph-metal-deep, #5e4418) 0%, var(--ph-metal, #8a6a2e) 50%, var(--ph-metal-deep, #5e4418) 100%);
  -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; color: var(--ph-metal-deep, #5e4418);
}
@keyframes ph-pulse { 0%,100% { opacity: .85 } 50% { opacity: 1 } }
/* on Android the pill is the white picture (an <img> that ss-canvas.js redraws as a canvas, like the music
   button's) and the words the accent ink picture: Samsung's dark mode would repaint drawn colours. The extra
   .fl-scene outranks the light-design rule further down that fills .gf-hint with the muted ink. */
[data-ss] .fl-scene.ph-scene p.gf-hint { background: none; box-shadow: none; isolation: isolate; -webkit-text-fill-color: initial; }
[data-ss] .ph-scene .gf-hint > .ss-fill { position: absolute; inset: 0; width: 100%; height: 100%; border-radius: inherit; object-fit: cover; z-index: -1; opacity: .74; pointer-events: none; }
/* --ss-ink-accent only exists for light themes (views/guest.ejs); a dark theme's photo envelope (24/9, the
   Christmas party, the first one) falls back to --ss-ink-button instead of straight to --ss-button — dark ink
   for a light/gold surface is what a pale hint pill needs, on any tone, and every theme already has that file
   (scripts/make-samsung-safe.js makes it unconditionally). Without this a dark theme showed the gold BUTTON
   metal as the hint's "ink", unreadable on the pale pill (Gary 24/9, checked on Samsung ?ss=1 --dark). */
[data-ss] .ph-scene .gf-hint span { background: var(--ss-ink-accent, var(--ss-ink-button, var(--ss-button))) center / cover; -webkit-background-clip: text; background-clip: text; }
/* opening (Gary 22/9): the right flap folds OUT towards you on its fold at the right-hand edge (a plus rotateY
   brings the tip towards the viewer) and is off the side by about 1.2s (past 90deg its back faces you and is
   hidden). The seal is stuck to the left flap under it, so the flap is tugged first, to the right and towards
   you, while the seal holds on by its left side; then it comes away and goes with the flap ("it's got to look
   like it's stuck to the left-hand side, and then that just gets pulled off and opens"; not a jump). The left
   flap's photo face (with the V the right flap cut, and its shadow) fades as the flap lifts, leaving the whole
   left flap (theme open_left: "a nice straight triangle flap underneath"). Then the top, bottom and left flaps
   all open together ("have them all kind of open at the same time"). Slow (Gary 22/9): done by 2.3s. */
.ph-seal { transform-origin: 0 50%; }
.ph-envelope.gf-open .ph-flap     { animation: ph-open-flap 1.5s linear forwards; }
.ph-envelope.gf-open .ph-seal     { animation: ph-seal-peel 1.5s linear forwards; }
.ph-envelope.gf-open .ph-seal > * { animation: ph-seal-lift 1.5s linear forwards; }
.ph-envelope.gf-open .ph-sealed-face { animation: ph-fade-out .6s ease .5s forwards; }
.ph-envelope.gf-open .ph-top    { animation: ph-lift-top    1s cubic-bezier(.45, 0, .3, 1) 1.3s forwards; }
.ph-envelope.gf-open .ph-bottom { animation: ph-lift-bottom 1s cubic-bezier(.45, 0, .3, 1) 1.3s forwards; }
.ph-envelope.gf-open .ph-left   { animation: ph-lift-left   1s cubic-bezier(.45, 0, .3, 1) 1.3s forwards; }
@keyframes ph-fade-out { to { opacity: 0; } }
@keyframes ph-open-flap {
  0%   { transform: perspective(1500px) translateX(0) rotateY(0deg); animation-timing-function: cubic-bezier(.35, 0, .65, 1); }
  30%  { transform: perspective(1500px) translateX(2.5%) rotateY(12deg); animation-timing-function: cubic-bezier(.45, 0, .55, 1); }
  100% { transform: perspective(1500px) translateX(2.5%) rotateY(100deg); }
}
/* the seal while the flap is tugged: held by its left side on the left flap, stretched a little and kept flat
   (the flap's slide and turn undone), then it lets go with a small snap and rides on the flap */
@keyframes ph-seal-peel {
  0%   { transform: translateX(0) scaleX(1) perspective(800px) rotateY(0deg); animation-timing-function: cubic-bezier(.35, 0, .65, 1); }
  30%  { transform: translateX(-7%) scaleX(1.05) perspective(800px) rotateY(-12deg); animation-timing-function: cubic-bezier(.3, 0, .4, 1.5); }
  38%  { transform: translateX(0) scaleX(1) perspective(800px) rotateY(0deg); }
  100% { transform: translateX(0) scaleX(1) perspective(800px) rotateY(0deg); }
}
/* its shadow grows as it comes away from the paper */
@keyframes ph-seal-lift {
  0%, 30% { filter: drop-shadow(0 7px 10px rgba(40,30,20,.32)); }
  38%  { filter: drop-shadow(0 18px 20px rgba(40,30,20,.34)); }
  100% { filter: drop-shadow(0 14px 16px rgba(40,30,20,.3)); }
}
@keyframes ph-lift-top    { 0% { transform: perspective(1900px) rotateX(0deg); opacity: 1; } 30% { opacity: 1; } 85% { opacity: 0; } 100% { transform: perspective(1900px) rotateX(88deg);  opacity: 0; } }
@keyframes ph-lift-bottom { 0% { transform: perspective(1900px) rotateX(0deg); opacity: 1; } 30% { opacity: 1; } 85% { opacity: 0; } 100% { transform: perspective(1900px) rotateX(-88deg); opacity: 0; } }
@keyframes ph-lift-left   { 0% { transform: perspective(1900px) rotateY(0deg); opacity: 1; } 30% { opacity: 1; } 85% { opacity: 0; } 100% { transform: perspective(1900px) rotateY(-88deg); opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
  .ph-envelope.gf-open :is(.ph-flap, .ph-top, .ph-bottom, .ph-left, .ph-seal, .ph-seal > *, .ph-sealed-face) { animation-duration: .01s; animation-delay: 0s; }
}

/* =====================================================================================
   LIGHT THEMES (theme.tone "light" — blush-21st first, 21 Sep 2026)
   The page was built dark. These undo its dark-only touches: the darkened hero texture and the
   black vignette, see-through white fills that vanish on a light page, black shadows that look
   dirty on pink, a black record, and the seal lettering made for gold wax.
   ===================================================================================== */
html[data-tone="light"] { color-scheme: light; }
[data-tone="light"] .sc-hero-texture { filter: none; opacity: 1; }
[data-tone="light"] .sc-hero::after {
  background: radial-gradient(ellipse 90% 70% at 50% 36%, rgba(255,255,255,0.32), rgba(255,255,255,0) 58%, var(--brand-navy-dark) 100%);
}
/* the pour was filmed on a slightly deeper pink than the page, so the video itself is faded out
   all round (sized to its own picture, so the fade sits on its edges) and melts into the page */
[data-tone="light"] .sc-hero-media { height: 46vh; height: 46svh; max-height: 430px; -webkit-mask-image: none; mask-image: none; }
[data-tone="light"] .sc-hero-media video,
[data-tone="light"] .sc-hero-media img {
  width: auto; max-width: 100%; margin: 0 auto; object-fit: cover;
  -webkit-mask-image: radial-gradient(ellipse 50% 50% at 50% 50%, #000 60%, transparent 100%);
          mask-image: radial-gradient(ellipse 50% 50% at 50% 50%, #000 60%, transparent 100%);
}
[data-tone="light"] .sc-btn-ghost { background-color: rgba(255,255,255,0.5); }
[data-tone="light"] .sc-btn-solid { border-color: rgba(255,255,255,0.75); box-shadow: 0 10px 24px rgba(158,90,102,0.22); }
[data-tone="light"] .sc-swatches span { border-color: rgba(74,44,51,0.14); box-shadow: 0 6px 14px rgba(74,44,51,0.16); }
[data-tone="light"] .sc-map { box-shadow: 0 14px 32px rgba(74,44,51,0.16); }
[data-tone="light"] .sc-map iframe { filter: grayscale(0.3) sepia(0.12); }
[data-tone="light"] .sc-form input[type="text"],
[data-tone="light"] .sc-form select,
[data-tone="light"] .sc-form textarea { background: rgba(255,255,255,0.62); }
[data-tone="light"] .sc-music { background: rgba(255,255,255,0.82); background-color: rgba(255,255,255,0.86); }
[data-tone="light"] .countdown-bar { background: rgba(255,255,255,0.5); border-color: var(--theme-card-border); }
[data-tone="light"] .np { background: rgba(255,255,255,0.55); }
/* a rose-gold record, not a black one (the quinceañera listing's is rose gold too) */
[data-tone="light"] .np-disc {
  background: repeating-radial-gradient(circle at 50% 50%, #b98078 0 1.6px, #d4a39a 1.6px 2.6px);
  box-shadow: 0 6px 14px rgba(120,60,60,0.25), inset 0 0 0 1px rgba(255,255,255,0.3);
}
[data-tone="light"] .np-disc i::after { background: var(--brand-navy-dark); }
[data-tone="light"] .sc-yt { box-shadow: 0 14px 32px rgba(74,44,51,0.18); }
[data-tone="light"] .look-new .sc-gallery figure { background: #fffaf8; box-shadow: 0 14px 26px rgba(74,44,51,0.16); }
/* the envelope: a soft rosy shadow under pink paper, and a rose-brown letter pressed in the wax */
[data-tone="light"] .fl-flap { filter: drop-shadow(0 2px 7px rgba(120,64,64,0.22)); }
[data-tone="light"] .fl-seal img, [data-tone="light"] .gf-seal-half img { filter: drop-shadow(0 8px 12px rgba(110,50,50,0.32)); }
[data-tone="light"] .fl-seal span, [data-tone="light"] .gf-seal-half span {
  color: rgba(84,34,40,0.72); text-shadow: 0 1px 0 rgba(255,236,228,.55), 0 -1px 1px rgba(70,24,30,.55);
}

/* a LIGHT design in GOLD (theme palette.metal "gold", html[data-metal]: the white espresso design, 21/9).
   The light rules above were made for rose gold (blush-21st); these swap their rosy shadows, the rose-gold
   record and the seal's rose-brown letter for warm browns and gold. */
[data-tone="light"][data-metal="gold"] .sc-btn-solid { box-shadow: 0 10px 24px rgba(150,115,50,0.22); }
[data-tone="light"][data-metal="gold"] .sc-swatches span { border-color: rgba(60,45,30,0.14); box-shadow: 0 6px 14px rgba(60,45,30,0.16); }
[data-tone="light"][data-metal="gold"] :is(.sc-map, .sc-yt) { box-shadow: 0 14px 32px rgba(60,45,30,0.16); }
[data-tone="light"][data-metal="gold"] .look-new .sc-gallery figure { box-shadow: 0 14px 26px rgba(60,45,30,0.16); }
[data-tone="light"][data-metal="gold"] .np-disc {
  background: repeating-radial-gradient(circle at 50% 50%, #b89154 0 1.6px, #d9b878 1.6px 2.6px);
  box-shadow: 0 6px 14px rgba(90,66,30,0.25), inset 0 0 0 1px rgba(255,255,255,0.3);
}
[data-tone="light"][data-metal="gold"] .fl-flap { filter: drop-shadow(0 2px 7px rgba(90,70,40,0.2)); }
[data-tone="light"][data-metal="gold"] :is(.fl-seal, .gf-seal-half) :is(img, canvas) { filter: drop-shadow(0 8px 12px rgba(90,66,30,0.32)); }
[data-tone="light"][data-metal="gold"] :is(.fl-seal, .gf-seal-half) span {
  color: rgba(70,48,20,0.74); text-shadow: 0 1px 0 rgba(255,244,214,.55), 0 -1px 1px rgba(60,40,10,.55);
}

/* =====================================================================================
   DECORATIONS (theme.decor), placed by views/partials/scroll-sections.ejs
   Nothing here is static (rule 7): the roses sway, bubbles rise, butterflies fly in and hover,
   petals drift, the bow sways. Movement that sits on top of a reveal uses the separate
   translate / rotate properties, so it never fights the reveal's transform.
   ===================================================================================== */
.has-decor .sc-section { position: relative; border-bottom: 0; }
.has-decor .sc-countdown-wrap { padding-bottom: 14px; }

/* roses framing the glass at the top */
.dc-corner { position: absolute; top: -8px; width: min(42vw, 250px); height: auto; z-index: 2; pointer-events: none; }
.dc-corner-l { left: -12px; transform-origin: 0 0; animation: dc-sway 9s ease-in-out infinite alternate; }
/* flipped about its own middle (flipping about the right edge threw it off the screen) */
.dc-corner-r { right: -12px; transform: scaleX(-1); transform-origin: 50% 0; animation: dc-sway-r 10s ease-in-out infinite alternate; }
@keyframes dc-sway   { from { rotate: -1.2deg; } to { rotate: 1.5deg; } }
@keyframes dc-sway-r { from { rotate: 1.2deg; } to { rotate: -1.5deg; } }

/* champagne bubbles rising through the top of the page */
.dc-bubbles { position: absolute; inset: 0; z-index: 1; pointer-events: none; overflow: hidden; }
.dc-bubbles i {
  position: absolute; bottom: -14px; left: var(--x); width: var(--s); height: var(--s); border-radius: 50%;
  background: radial-gradient(circle at 32% 30%, rgba(255,255,255,0.95), rgba(255,247,235,0.35) 45%, rgba(255,255,255,0.06) 72%);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,0.75), 0 0 5px rgba(255,236,210,0.45);
  opacity: 0; animation: dc-rise var(--d) linear var(--w) infinite;
}
@keyframes dc-rise {
  0%   { transform: translate(0, 0); opacity: 0; }
  10%  { opacity: .9; }
  50%  { transform: translate(9px, -55vh); }
  88%  { opacity: .7; }
  100% { transform: translate(-7px, -110vh); opacity: 0; }
}

/* a garland over each section: it opens out from the middle as the section arrives */
.dc-divider { display: block; width: min(80%, 420px); height: auto; margin: -22px auto 26px; pointer-events: none; }
.sc-section.reveal > .dc-divider,
.sc-section.reveal > .dc-divider:nth-child(even) { opacity: 0; transform: scale(.7); transition: none; }
.sc-section.reveal.seen > .dc-divider,
.sc-section.reveal.seen > .dc-divider:nth-child(even) {
  opacity: 1; transform: none;
  transition: opacity .8s ease-out, transform 1.1s cubic-bezier(.2,.9,.3,1.05);
}

/* butterflies: fly in from their side as the section arrives, land by the garland, then hover */
.dc-fly { position: absolute; top: -10px; width: 62px; z-index: 3; pointer-events: none; }
.dc-fly-r { right: 7%; }
.dc-fly-l { left: 7%; }
.dc-fly img { display: block; width: 100%; height: auto; animation: dc-flap 1.3s ease-in-out infinite; animation-delay: calc(var(--n) * -.41s); }
@keyframes dc-flap { 0%, 100% { transform: scaleX(1); } 50% { transform: scaleX(.6); } }
.sc-section.reveal > .dc-fly-r,
.sc-section.reveal > .dc-fly-r:nth-child(even) { opacity: 0; transform: translate(62vw, -60px) rotate(22deg); transition: none; }
.sc-section.reveal > .dc-fly-l,
.sc-section.reveal > .dc-fly-l:nth-child(even) { opacity: 0; transform: translate(-62vw, -60px) rotate(-22deg); transition: none; }
.sc-section.reveal.seen > .dc-fly,
.sc-section.reveal.seen > .dc-fly:nth-child(even) {
  opacity: 1; transform: none;
  transition: opacity .5s ease-out .1s, transform 2.3s cubic-bezier(.22,.8,.3,1) .1s;
  animation: dc-hover 5.5s ease-in-out 2.4s infinite alternate;
}
@keyframes dc-hover { from { translate: 0 0; rotate: 0deg; } to { translate: -12px -16px; rotate: 6deg; } }

/* the bow on the closing card */
.dc-bow { display: block; width: 128px; height: auto; margin: 0 auto 4px; transform-origin: 50% 25%; animation: dc-bow 5s ease-in-out infinite alternate; }
@keyframes dc-bow { from { rotate: -2.5deg; } to { rotate: 2.5deg; } }
.sc-footer.reveal > .dc-bow,
.sc-footer.reveal > .dc-bow:nth-child(even) { opacity: 0; transform: translateY(-34px) scale(.8); transition: none; }
.sc-footer.reveal.seen > .dc-bow,
.sc-footer.reveal.seen > .dc-bow:nth-child(even) { opacity: 1; transform: none; transition: opacity .7s ease-out, transform 1s cubic-bezier(.2,.9,.3,1.1); }

/* a few petals drifting down over the page once it is open */
.dc-petals { position: fixed; inset: 0; z-index: 25; pointer-events: none; overflow: hidden; }
body.gf-locked .dc-petals { display: none; }
.dc-petals i {
  position: absolute; top: -40px; left: var(--x); width: 13px; height: 17px;
  border-radius: 150% 0 150% 0;
  background: #f0bdb3; background-image: linear-gradient(135deg, #fbe3de 0%, #f0bdb3 60%, #e3a59b 100%);
  box-shadow: 0 2px 4px rgba(120,60,60,0.12);
  opacity: 0; animation: dc-fall var(--d) linear var(--w) infinite;
}
@keyframes dc-fall {
  0%   { transform: translate(0, 0) rotate(var(--r)); opacity: 0; }
  8%   { opacity: .85; }
  50%  { transform: translate(var(--sw), 55vh) rotate(calc(var(--r) + 160deg)); }
  90%  { opacity: .7; }
  100% { transform: translate(calc(var(--sw) * -0.6), 112vh) rotate(calc(var(--r) + 320deg)); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .dc-petals, .dc-bubbles { display: none; }
  .dc-corner, .dc-fly img, .dc-bow { animation: none !important; }
  .sc-section.reveal.seen > .dc-fly { animation: none; }
}

/* gold glints twinkling in the hero and on the closing card (decor.glints, the dark themes' bubbles) */
.dc-glints { position: absolute; inset: 0; z-index: 1; pointer-events: none; overflow: hidden; }
.dc-glints i {
  position: absolute; left: var(--x); top: var(--y); width: var(--s); height: var(--s);
  background: radial-gradient(circle, #fff6dc 0 16%, rgba(241,220,174,.9) 30%, rgba(241,220,174,0) 64%);
  clip-path: polygon(50% 0, 58% 42%, 100% 50%, 58% 58%, 50% 100%, 42% 58%, 0 50%, 42% 42%);
  opacity: 0; animation: dc-twinkle var(--d) ease-in-out var(--w) infinite;
}
@keyframes dc-twinkle {
  0%, 100% { opacity: 0; transform: scale(.3) rotate(0deg); }
  50%      { opacity: .95; transform: scale(1) rotate(45deg); }
}
.sc-footer.reveal > .dc-glints, .sc-footer.reveal > .dc-glints:nth-child(even) { opacity: 1; transform: none; transition: none; }
@media (prefers-reduced-motion: reduce) { .dc-glints { display: none; } }

/* =====================================================================================
   SAMSUNG INTERNET'S DARK MODE (tested on Gary's phone: v30 / Chromium 143, 21 Sep 2026)
   It ignores color-scheme and prefers-color-scheme and repaints the page itself: colours the page
   draws are FLIPPED (light backgrounds go dark, dark writing goes light, a gold button went dark
   brown), while pictures keep their colours, only dimmed (a real <img> to about 70%, a CSS background
   picture to about 50%). So on Android (html[data-ss], set by routes/guest.js) anything whose colour
   matters is a picture (scripts/make-samsung-safe.js, the variables come from views/guest.ejs), shaped
   with masks, which are never recoloured. They draw the same thing as before in a normal browser;
   iPhones and computers never get them and keep the plain version.
   ===================================================================================== */
/* the envelope paper, the top picture and the dress-code colours are real pictures on Android */
[data-ss] .fl-face .fl-paper { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
[data-ss] .sc-hero-texture img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* (each colour picture is drawn wider than its circle and clipped to it: Chrome treats a picture drawn in a small
   box as an icon and may invert a pale one; in a wide box it is left alone) */
[data-ss] .sc-swatches span { position: relative; overflow: hidden; }
[data-ss][data-tone="light"] .sc-swatches span { border-color: transparent; }   /* its faint dark rim turns dark in dark mode */
[data-ss] .sc-swatches span img { position: absolute; top: 0; left: 50%; width: 130px; height: 100%; margin-left: -65px; object-fit: cover; display: block; }
/* the photo frames of the new look: a real picture behind each photo, not a drawn cream */
[data-ss] .look-new .sc-gallery figure { position: relative; isolation: isolate; }
[data-ss] .look-new .sc-gallery figure > img.ss-fill {
  position: absolute; left: 0; top: 0; width: 100%; height: 100%; aspect-ratio: auto;
  border-radius: inherit; object-fit: cover; z-index: -1; pointer-events: none;
}

/* the small gold touches, as the button's own metal */
[data-ss] .sc-dot, [data-ss] .np-disc i { background: var(--ss-button) center / cover; }
[data-ss] .sc-rule {
  background: var(--ss-button) center / cover;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 30%, #000 70%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 30%, #000 70%, transparent);
}
/* bubbles, glints and petals: a picture shaped by a mask, instead of drawn gradients */
[data-ss] .dc-bubbles i {
  background: var(--ss-white) center / cover; box-shadow: none;
  -webkit-mask-image: radial-gradient(circle at 32% 30%, #000 0 14%, transparent 26%), radial-gradient(circle, rgba(0,0,0,.2) 0 56%, rgba(0,0,0,.85) 66%, transparent 71%);
          mask-image: radial-gradient(circle at 32% 30%, #000 0 14%, transparent 26%), radial-gradient(circle, rgba(0,0,0,.2) 0 56%, rgba(0,0,0,.85) 66%, transparent 71%);
}
[data-ss] .dc-glints i {
  background: var(--ss-button) center / cover;
  -webkit-mask-image: radial-gradient(circle, #000 0 26%, rgba(0,0,0,.65) 40%, transparent 64%);
          mask-image: radial-gradient(circle, #000 0 26%, rgba(0,0,0,.65) 40%, transparent 64%);
}
[data-ss] .dc-petals i { background: var(--ss-button) center / cover; box-shadow: none; }
/* the music bars (corner pill and record player) are drawn shapes too */
[data-ss] .sc-music-bars i, [data-ss] .np-wave i { background: var(--ss-button) center / cover; }
/* the music pill on a light page: a real white picture inside it (partials/scroll-sections.ejs), not a drawn white */
[data-ss][data-tone="light"] .sc-music { background: transparent; isolation: isolate; }
[data-ss] .sc-music > .ss-fill {
  position: absolute; left: -1px; top: -1px; width: calc(100% + 2px); height: calc(100% + 2px);
  border-radius: inherit; object-fit: cover; z-index: -1; pointer-events: none;
}
[data-ss][data-tone="light"] .sc-music-label {
  background: var(--ss-ink-accent) center / cover;
  -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent;
}

/* a LIGHT design (blush-21st): the page is a picture behind everything (views/guest.ejs), the drawn
   washes over it are dropped (they would turn dark), and the writing is filled with ink pictures so it
   stays dark instead of being flipped light */
.sc-page-bg { position: fixed; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: 0; pointer-events: none; }
[data-ss][data-tone="light"] .app-container.app-scroll { position: relative; z-index: 1; background: transparent; }
[data-ss][data-tone="light"] #card-stage.stage-scroll, [data-ss][data-tone="light"] .stage-scroll { background: transparent; }
[data-ss][data-tone="light"] .sc-hero::after { display: none; }
/* ...so the top picture fades into the page with a mask instead, the same shape as the wash it replaces */
[data-ss][data-tone="light"] .sc-hero-texture {
  -webkit-mask-image: radial-gradient(ellipse 90% 70% at 50% 36%, #000 58%, transparent 100%);
          mask-image: radial-gradient(ellipse 90% 70% at 50% 36%, #000 58%, transparent 100%);
}
/* outlines of boxes, pills and buttons, and the rules between rows, are pictures too: a line drawn in a
   colour turns dark. Each outline is a picture shaped into a 1px ring by a mask. */
[data-ss][data-tone="light"] :is(.sc-btn-ghost, .countdown-bar, .np, .sc-map, .sc-choice span) { position: relative; }
[data-ss][data-tone="light"] :is(.sc-btn-ghost, .countdown-bar, .np, .sc-music, .sc-map, .sc-choice span) { border-color: transparent; }
[data-ss][data-tone="light"] :where(.sc-btn-ghost, .countdown-bar, .np, .sc-music, .sc-map, .sc-choice span)::before {
  content: ""; position: absolute; inset: -1px; border-radius: inherit; padding: 1px; pointer-events: none;
  background: var(--ss-line) center / cover;
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor; mask-composite: exclude;
}
[data-ss][data-tone="light"] :is(.sc-btn-ghost, .sc-music)::before { background-image: var(--ss-ink-accent); }
[data-ss][data-tone="light"] .sc-btn-ghost { background: transparent; }
[data-ss][data-tone="light"] :is(.sc-detail, .sc-timeline li):not(:last-child) {
  border-bottom-color: transparent;
  background: var(--ss-line) left bottom / 100% 1px no-repeat border-box;
}
[data-ss][data-tone="light"] .countdown-bar, [data-ss][data-tone="light"] .np { background: transparent; }
[data-ss][data-tone="light"] .sc-finale-bg::after { display: none; }
[data-ss][data-tone="light"] .sc-finale-bg {
  -webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 32%, #000 62%, transparent 100%);
          mask-image: linear-gradient(180deg, transparent 0%, #000 32%, #000 62%, transparent 100%);
}
/* (a text fill also paints the element's children, so on the new look, where letters drop in and the
   name writes itself in, only the letters themselves are filled, or the word would show before it lands) */
[data-ss][data-tone="light"] :is(.sc-hero-date, .sc-lead, .sc-value, .sc-what, .sc-finale-day, .np-title, .sc-choice input:not(:checked) + span, .sc-thanks),
[data-ss][data-tone="light"] body:not(.look-new) :is(.sc-hero-title, .sc-hero-sub, .sc-h2),
[data-ss][data-tone="light"] .look-new :is(.sc-hero-title .hw, .sc-hero-sub .l, .sc-h2 .l),
[data-ss][data-tone="light"] :is(.sc-script, .sc-signature, .sc-label, .sc-time, .sc-legend, .sc-form label, .countdown-val, .np-label, .sc-finale-month, .sc-btn-ghost),
[data-ss][data-tone="light"] body:not(.look-new) .sc-eyebrow,
[data-ss][data-tone="light"] .look-new .sc-eyebrow .w,
[data-ss][data-tone="light"] :is(.sc-hero-time, .countdown-lbl, .sc-footer-sub, .sc-alt-links a, .gf-hint) {
  background-size: cover; background-position: center;
  -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent;
}
[data-ss][data-tone="light"] :is(.sc-hero-date, .sc-lead, .sc-value, .sc-what, .sc-finale-day, .np-title, .sc-choice input:not(:checked) + span, .sc-thanks),
[data-ss][data-tone="light"] body:not(.look-new) :is(.sc-hero-title, .sc-hero-sub, .sc-h2),
[data-ss][data-tone="light"] .look-new :is(.sc-hero-title .hw, .sc-hero-sub .l, .sc-h2 .l) { background-image: var(--ss-ink-text); }
[data-ss][data-tone="light"] :is(.sc-script, .sc-signature, .sc-label, .sc-time, .sc-legend, .sc-form label, .countdown-val, .np-label, .sc-finale-month, .sc-btn-ghost),
[data-ss][data-tone="light"] body:not(.look-new) .sc-eyebrow,
[data-ss][data-tone="light"] .look-new .sc-eyebrow .w { background-image: var(--ss-ink-accent); }
[data-ss][data-tone="light"] :is(.sc-hero-time, .countdown-lbl, .sc-footer-sub, .sc-alt-links a, .gf-hint) { background-image: var(--ss-ink-muted); }
/* script lettering reaches outside its box, and a text-filled picture only covers the box: room round it */
[data-ss][data-tone="light"] .sc-script { padding: .2em .4em; margin: -.2em -.4em calc(10px - .2em); }
[data-ss][data-tone="light"] .sc-signature { padding: .2em .4em; margin: calc(18px - .2em) -.4em -.2em; display: inline-block; }

/* ---- PICTURES AS CANVAS (Android): public/js/ss-canvas.js redraws each picture as a <canvas>, which
        Samsung's dark mode leaves at full brightness (a picture drops to 70%, measured 21/9). A canvas
        takes the img's classes and style, so class rules carry over; these are the rules written for
        "img", repeated for "canvas". ---- */
[data-ss] .sc-gallery canvas { width: 100%; height: 100%; object-fit: cover; display: block; }
[data-ss] .look-new .sc-gallery canvas { aspect-ratio: 1; height: auto; border-radius: 1px; }
[data-ss] .look-new .sc-gallery figure:first-child canvas { aspect-ratio: 4 / 3; }
[data-ss] .look-new .sc-gallery figure > canvas.ss-fill {
  position: absolute; left: 0; top: 0; width: 100%; height: 100%; aspect-ratio: auto;
  border-radius: inherit; object-fit: cover; z-index: -1; pointer-events: none;
}
[data-ss] .fl-seal canvas, [data-ss] .gf-seal-half canvas { width: 100%; height: 100%; display: block; filter: drop-shadow(0 10px 14px rgba(0,0,0,0.6)); }
[data-ss][data-tone="light"] .fl-seal canvas, [data-ss][data-tone="light"] .gf-seal-half canvas { filter: drop-shadow(0 8px 12px rgba(110,50,50,0.32)); }
[data-ss] .sc-hero-media canvas { width: 100%; height: 100%; object-fit: contain; object-position: center center; display: block; transform: scale(1.02); }
[data-ss][data-tone="light"] .sc-hero-media canvas {
  width: auto; max-width: 100%; margin: 0 auto; object-fit: cover;
  -webkit-mask-image: radial-gradient(ellipse 50% 50% at 50% 50%, #000 60%, transparent 100%);
          mask-image: radial-gradient(ellipse 50% 50% at 50% 50%, #000 60%, transparent 100%);
}
[data-ss] .sc-hero-texture canvas { width: 100%; height: 100%; object-fit: cover; display: block; }
[data-ss] .sc-swatches span canvas { position: absolute; top: 0; left: 50%; width: 130px; height: 100%; margin-left: -65px; object-fit: cover; display: block; }
[data-ss] .dc-fly canvas { display: block; width: 100%; height: auto; animation: dc-flap 1.3s ease-in-out infinite; animation-delay: calc(var(--n) * -.41s); }
@media (prefers-reduced-motion: reduce) { [data-ss] .dc-fly canvas { animation: none !important; } }

/* ---- the host's own section order (settings.section_order): each section carries its place as a
        CSS order inside this column, so the markup stays in one sequence ---- */
.sc-flow { display: flex; flex-direction: column; }
/* full width, then capped and centred as before (in a flex column, auto margins alone would shrink
   a section to fit its words) */
.sc-flow > * { box-sizing: border-box; width: 100%; }

/* ---- edit mode (?edit=1, inside the editor): an Edit tab on every section, tap to open it ---- */
.edit-mode [data-edit] { position: relative; cursor: pointer; }
.edit-mode [data-edit]:active { outline: 2px solid #2563eb; outline-offset: -2px; }
.edit-chip {
  position: absolute; top: 12px; left: 12px; z-index: 30; pointer-events: none;
  padding: 6px 12px; border-radius: 999px;
  font: 600 12px/1 system-ui, -apple-system, sans-serif; letter-spacing: .3px; text-transform: none;
  background: #2563eb; color: #fff; box-shadow: 0 4px 12px rgba(0,0,0,.25);
}
.edit-mode .sc-scroll-hint { display: none; }

/* Adult invitation first screen: distribute spare height above the buttons,
   rather than leaving an empty band below them. Natural overflow still scrolls. */
@media (max-width: 719px) {
  .sc-hero:has(source:is([src^="/themes/blush-21st/"], [src^="/themes/espresso-martini-white/"], [src^="/themes/black-gold-50th/"], [src^="/themes/beer-30th/"])) {
    padding-bottom: 56px;
  }
  .sc-hero:has(source:is([src^="/themes/blush-21st/"], [src^="/themes/espresso-martini-white/"], [src^="/themes/black-gold-50th/"], [src^="/themes/beer-30th/"])) .sc-hero-inner {
    flex: 1 0 auto;
    width: 100%;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
  }
  .sc-hero:has(source:is([src^="/themes/blush-21st/"], [src^="/themes/espresso-martini-white/"], [src^="/themes/black-gold-50th/"], [src^="/themes/beer-30th/"])) .sc-hero-media { flex-shrink: 0; }
  .sc-hero:has(source:is([src^="/themes/blush-21st/"], [src^="/themes/espresso-martini-white/"], [src^="/themes/black-gold-50th/"], [src^="/themes/beer-30th/"])) .sc-scroll-hint { height: 24px; bottom: 14px; }
}
@media (max-width: 719px) {
  [data-tone="light"] .sc-hero:has(source:is([src^="/themes/blush-21st/"], [src^="/themes/espresso-martini-white/"])) .sc-hero-media {
    height: min(46svh, max(120px, calc(100svh - 450px)));
  }
}

/* Christmas mobile spacing, reviewed 25Sep */

@media (max-width: 719px) {
  .sc-hero:has(source[src^="/themes/christmas-green-gold/"], img[src^="/themes/christmas-green-gold/"], video[src^="/themes/christmas-green-gold/"]) { padding-bottom: 56px; }
  .sc-hero:has(source[src^="/themes/christmas-green-gold/"], img[src^="/themes/christmas-green-gold/"], video[src^="/themes/christmas-green-gold/"]) .sc-hero-inner {
    flex: 1 0 auto;
    width: 100%;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
  }
  .sc-hero:has(source[src^="/themes/christmas-green-gold/"], img[src^="/themes/christmas-green-gold/"], video[src^="/themes/christmas-green-gold/"]) .sc-hero-media { flex-shrink: 0; }
  .sc-hero:has(source[src^="/themes/christmas-green-gold/"], img[src^="/themes/christmas-green-gold/"], video[src^="/themes/christmas-green-gold/"]) .sc-scroll-hint { height: 24px; bottom: 14px; }
  .sc-hero:has(source[src^="/themes/christmas-green-gold/"], img[src^="/themes/christmas-green-gold/"], video[src^="/themes/christmas-green-gold/"]) .dc-glints i {
    opacity: .42 !important;
    filter: blur(.15px) !important;
  }
}
@media (max-width: 719px) and (max-height: 720px) {
  .sc-hero:has(source[src^="/themes/christmas-green-gold/"], img[src^="/themes/christmas-green-gold/"], video[src^="/themes/christmas-green-gold/"]) .sc-hero-media {
    height: min(42svh, max(120px, calc(100svh - 450px)));
  }
}
