/* The product film on the home page, after docs/redesign/prototype/Film.dc.html.
 *
 * The host's screen, the guest's phone and the tags are drawn at the
 * prototype's own pixel sizes on a 956 by 790 stage and scaled as one picture
 * from --film-w, the stage's width, which film.js measures. That keeps every
 * seat, ring and flight path exactly where the prototype puts it at any width.
 *
 * Only transform, opacity and clip-path animate. Under reduced motion every
 * animation is collapsed to its last frame rather than switched off, so each
 * screen shows its finished state: chips seated, counts final, photos in the
 * album.
 */

.film {
  --film-w: 956;
  /* The shadow under a printed card and the hint pill on the kids world are
     the same in both themes, because they sit on artwork, not on the page. */
  --film-card-shadow: 0 30px 60px -30px rgb(0 0 0 / 0.5);
  --film-hint: rgb(255 255 255 / 0.9);
  /* The ink the kids and baptism artwork is lettered in, part of the drawing. */
  --film-kids-ink: #1E3A4A;
  --film-baptism-ink: #4A3A3A;

  padding: 56px 0 72px;
  background: var(--bg);
  color: var(--ink);
  border-block: 1px solid var(--line);
  overflow-x: clip;
}

.film-wrap {
  max-width: var(--max);
  margin: 0 auto;
  padding: 0 var(--gutter);
}

.film-head { margin-bottom: 36px; }

.film-families { margin: -12px 0 40px; }

.film-title {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(34px, 4.2vw, 60px);
  line-height: 1;
  letter-spacing: -0.02em;
  text-wrap: balance;
}

.film-step:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

/* ── The track and its pinned frame ───────────────────────────────────── */
/* The track is one frame tall plus a span of scroll for every step, and the
   frame stays pinned under the header while the track passes, so a visitor
   who only scrolls sees every step, sped up. film-story.js reads how far the
   track has travelled and film.js sets --steps for the family shown. */
.film {
  --frame-h: calc(100svh - var(--header-h));
  --step-span: 30svh;
}
/* The track is exactly as tall as its steps, so the last bar is full as the
   page lets go of the frame and one gesture leaves the film. The film plays
   by itself and film-story.js moves the scroll along with it (Stefan, 25
   October 2026). A step's span is short because the film plays itself and the
   span only sets how far a reader scrolls to pass it, up as well as down, so
   the film is not a stop on the way back up the page ("so it doesn become a
   headstop for the website when u scroll up"). */
.film-track {
  --steps: 8;
  height: calc(var(--frame-h) + var(--steps) * var(--step-span));
  /* film-story.js moves the scroll itself as the film plays, so the browser
     must not correct it a second time from inside the film. */
  overflow-anchor: none;
}
.film-frame {
  position: sticky;
  top: var(--header-h);
  height: var(--frame-h);
  display: grid;
  grid-template-columns: 300px minmax(0, 1fr);
  gap: 56px;
  align-items: center;
}
.film-where, .film-progress { display: none; }

/* ── The step rail ────────────────────────────────────────────────────── */

.film-rail {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.film-phase {
  padding: 14px 0 0 38px;
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}
.film-phase.is-first { padding-top: 0; }

.film-step {
  display: flex;
  flex-direction: column;
  gap: 7px;
  padding: 9px 0;
  border: 0;
  border-bottom: 1px solid var(--line);
  background: transparent;
  color: var(--ink);
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  transition: color var(--dur-ui) ease;
}
/* Every step reads at full strength, because Stefan could not read the
   faded ones; the step being shown is told apart by its darker ink alone. */
.film-step:not(.is-current) { color: var(--ink2); }
@media (hover: hover) and (pointer: fine) {
  .film-step:not(.is-current):hover { color: var(--ink); }
}

.film-step-label { display: flex; gap: 16px; align-items: baseline; line-height: 1.25; }
.film-step-num { width: 22px; flex-shrink: 0; font-size: 19px; font-style: italic; color: var(--accent); }
.film-step-title { font-size: 16px; font-weight: 600; }

/* The whole rail has to stand inside the pinned frame, so on a short
   screen its steps close up rather than the last one falling off. */
@media (min-width: 900px) and (max-height: 760px) {
  .film-step { padding: 6px 0; gap: 5px; }
  .film-phase { padding-top: 10px; }
}

/* Used below for the one step shown on a phone coming into place; see the
   "Below 900 pixels" section. */
@keyframes film-point-in { from { opacity: 0; transform: translateY(6px); } }

.film-step-track {
  display: block;
  height: 2px;
  margin-left: 38px;
  border-radius: 1px;
  background: var(--line);
  overflow: hidden;
}
/* Filled frame by frame by film.js as the step plays, with no easing of its own. */
.film-step-fill {
  display: block;
  height: 100%;
  background: var(--ink);
  transform: scaleX(0);
  transform-origin: left center;
}

/* A film nobody is watching holds still, and carries on from the same frame
   when it is back in view. */
.film[data-running="false"] .film-stage *,
.film[data-running="false"] .film-stage *::before,
.film[data-running="false"] .film-stage *::after {
  animation-play-state: paused !important;
}

/* ── The stage ────────────────────────────────────────────────────────── */

.film-stage {
  --s: min(1, var(--film-w) / 956);
  position: relative;
  /* Every child is placed absolutely, so the stage takes its width from the
     layout and never from its content, which would be none. It is no wider
     than lets its 790 by 956 picture fit the pinned frame's height. */
  width: min(100%, calc((var(--frame-h) - 48px) * 1.21));
  justify-self: center;
  height: calc(790px * var(--s));
}

.film-host {
  position: absolute;
  left: 0;
  top: 0;
  width: 806px;
  height: 700px;
  display: flex;
  flex-direction: column;
  border-radius: 22px;
  background: var(--surface);
  box-shadow: var(--shadow-lift);
  overflow: hidden;
  transform: scale(var(--s));
  transform-origin: 0 0;
}

.film-host-bar {
  flex-shrink: 0;
  height: 46px;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0 18px;
  border-bottom: 1px solid var(--line);
  font-size: 12px;
}
.film-host-bar > i { width: 10px; height: 10px; border-radius: 50%; background: var(--line); }
.film-host-meta { margin-left: 14px; color: var(--muted); }
.film-host-title { margin-left: auto; font-weight: 600; }

.film-host-screen { position: relative; flex-grow: 1; min-height: 0; }

.film-phone {
  position: absolute;
  left: 0;
  top: 0;
  width: 250px;
  height: 500px;
  padding: 10px;
  border-radius: 42px;
  background: var(--phone);
  box-shadow: var(--shadow-lift);
  transform: translate(calc(706px * var(--s)), calc(290px * var(--s))) scale(var(--s));
  transform-origin: 0 0;
}
.film-phone-screen {
  position: relative;
  height: 100%;
  border-radius: 33px;
  background: var(--surface);
  overflow: hidden;
  isolation: isolate;
}
/* The phone's camera cut out, drawn over whatever the screen shows. */
.film-phone-screen::after {
  content: "";
  position: absolute;
  z-index: 3;
  top: 10px;
  left: 50%;
  width: 72px;
  height: 22px;
  margin-left: -36px;
  border-radius: 11px;
  background: var(--phone);
}

/* A step leaving fades out under the one arriving. */
.film-scene {
  position: absolute;
  inset: 0;
  transition: opacity var(--dur-ui) var(--ease-out);
}
.film-scene.is-leaving { opacity: 0; pointer-events: none; }

/* ── Shared pieces ────────────────────────────────────────────────────── */

.film-display { font-family: var(--font-display); font-weight: 400; }
.film-muted { color: var(--muted); }
.film-note { font-size: 12px; color: var(--muted); line-height: 1.5; }
.film-cover { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.film-dot { flex-shrink: 0; width: 10px; height: 10px; border-radius: 50%; background: var(--accent); }

.film-pill {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 28px;
  padding: 0 12px;
  border-radius: 999px;
  background: var(--bg2);
  color: var(--ink);
  font-size: 11px;
  font-weight: 500;
}
.film-pill.is-on { background: var(--ink); color: var(--bg); }

.film-rise { animation: film-rise var(--dur-reveal) var(--ease-out) var(--at, 0s) both; }
@keyframes film-rise { from { opacity: 0; transform: translateY(18px); } }

.film-tick { animation: film-tick calc(var(--dur-reveal) * 0.55) var(--ease-out) var(--at, 0s) both; }
@keyframes film-tick { from { opacity: 0; transform: scale(0.92); } }

.film-zoom { animation: film-zoom calc(var(--dur-reveal) * 1.55) var(--ease-out) both; }
@keyframes film-zoom { from { opacity: 0; transform: scale(0.92) translateY(10px); } }

/* The artwork breathes three times and then rests. */
.film-float { animation: film-float 5s var(--ease-in-out) 3; }
.film-float-slow { animation: film-float 6s var(--ease-in-out) 0.8s 3; }
@keyframes film-float { 50% { transform: translateY(-8px); } }

@keyframes film-settle { from { opacity: 0; transform: scale(0.96); } to { opacity: 1; transform: none; } }
@keyframes film-press { 40% { transform: scale(0.96); } }
@keyframes film-show { from { opacity: 0; } to { opacity: 1; } }
@keyframes film-hide { from { opacity: 1; } to { opacity: 0; } }

/* A count reads straight from the seating step's own scroll position
   (film.js's countBadge), so it only needs to sit inline where it is put. */
.film-count { display: inline-block; }

/* ── Create ───────────────────────────────────────────────────────────── */

.film-create { position: absolute; inset: 0; display: grid; grid-template-columns: 170px minmax(0, 1fr) 220px; }
.film-create-tabs { display: flex; flex-direction: column; gap: 6px; padding: 20px 14px; border-right: 1px solid var(--line); font-size: 13px; }
.film-create-tab { padding: 10px 12px; border-radius: 10px; }
.film-create-tab.is-on { background: var(--ink); color: var(--bg); }
.film-create-preview { position: relative; display: flex; align-items: center; justify-content: center; overflow: hidden; background: var(--bg2); }
.film-create-side { display: flex; flex-direction: column; gap: 12px; padding: 20px 16px; border-left: 1px solid var(--line); font-size: 12px; }
.film-create-hint { font-weight: 600; }
.film-swatches { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; }
.film-swatch { aspect-ratio: 1; border-radius: 8px; background: var(--swatch); }
.film-create-note { color: var(--muted); line-height: 1.55; }
.film-create-saved { align-self: flex-start; }
.film-create-card { height: 420px; border-radius: 4px; box-shadow: var(--film-card-shadow); }
/* A plain <img> here sizes its width from its own intrinsic 640 by 900
   picture and this height; a composed card (site.css) is not a replaced
   element and needs that same width: auto told explicitly, or its base
   rule's width: 100% would stretch it to the preview panel instead. */
.film-create-card.card-composed { width: auto; }

.film-browse { position: relative; width: 300px; height: 426px; }
.film-browse-card {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top;
  border-radius: 4px;
  box-shadow: var(--film-card-shadow);
  animation: film-cycle 1.2s var(--ease-out) var(--at) both;
}
.film-browse-card.is-last { animation: film-settle 1.4s var(--ease-out) var(--at) both; }
@keyframes film-cycle {
  0% { opacity: 0; transform: scale(0.96); }
  18% { opacity: 1; transform: none; }
  82% { opacity: 1; }
  100% { opacity: 0; }
}
.film-browse-strip { position: absolute; left: 0; right: 0; bottom: 14px; display: flex; justify-content: center; gap: 10px; }
.film-browse-thumb { position: relative; width: 38px; height: 54px; border-radius: 3px; overflow: hidden; box-shadow: 0 0 0 1px var(--line); }
.film-browse-thumb img { width: 100%; height: 100%; object-fit: cover; object-position: top; }
.film-browse-ring {
  position: absolute;
  inset: 0;
  border-radius: 3px;
  box-shadow: inset 0 0 0 2px var(--ink);
  animation: film-ring 1.2s var(--ease-out) var(--at) both;
}
.film-browse-ring.is-last { animation: film-settle 0.5s var(--ease-out) var(--at) both; }
@keyframes film-ring { 0% { opacity: 0; } 15% { opacity: 1; } 85% { opacity: 1; } 100% { opacity: 0; } }

.film-kids-card, .film-baptism-card {
  position: relative;
  width: 300px;
  height: 420px;
  border-radius: 10px;
  overflow: hidden;
  box-shadow: var(--film-card-shadow);
}
.film-kids-lights { position: absolute; left: 0; top: 18px; width: 100%; }
.film-kids-title, .film-kids-time, .film-baptism-title, .film-baptism-time { position: absolute; left: 0; right: 0; text-align: center; }
.film-kids-title { top: 86px; font-size: 34px; line-height: 1.05; color: var(--film-kids-ink); }
.film-kids-time { top: 168px; font-size: 12px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--film-kids-ink); }
.film-kids-palm { position: absolute; right: -30px; bottom: 30px; width: 150px; }
.film-kids-trex { position: absolute; left: 10px; bottom: 14px; width: 150px; }
.film-kids-cake { position: absolute; right: 70px; bottom: 10px; width: 78px; }
.film-baptism-arch { position: absolute; left: 10px; top: 40px; width: 280px; }
.film-baptism-title { top: 272px; font-size: 30px; line-height: 1.05; color: var(--film-baptism-ink); }
.film-baptism-time { top: 314px; font-size: 11px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--film-baptism-ink); }
.film-baptism-lamb { position: absolute; left: 14px; bottom: 6px; width: 90px; }
.film-baptism-candle { position: absolute; right: 26px; bottom: 10px; width: 34px; }

/* ── Questions ────────────────────────────────────────────────────────── */

.film-rsvp { position: absolute; inset: 0; display: flex; flex-direction: column; gap: 14px; padding: 30px 36px; }
.film-rsvp-title { font-size: 30px; }
.film-rsvp-row { display: flex; justify-content: space-between; align-items: center; padding: 16px 18px; border-radius: 14px; background: var(--bg2); font-size: 14px; }

/* A switch turns on the way a switch does: the knob slides and the track fills. */
.film-switch { position: relative; width: 46px; height: 26px; border-radius: 13px; background: var(--line); }
.film-switch::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: var(--ink);
  animation: film-show calc(var(--dur-ui) * 1.5) var(--ease-out) var(--at) both;
}
.film-switch::after {
  content: "";
  position: absolute;
  left: 3px;
  top: 3px;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--bg);
  transform: translateX(20px);
  animation: film-knob calc(var(--dur-ui) * 1.5) var(--ease-out) var(--at) both;
}
@keyframes film-knob { from { transform: none; } to { transform: translateX(20px); } }

/* ── Sending ──────────────────────────────────────────────────────────── */

.film-send { position: absolute; inset: 0; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 30px; padding: 34px 36px; }
.film-send-main { display: flex; flex-direction: column; gap: 18px; }
.film-send-title { font-size: 30px; }
.film-send-link { padding: 18px; border-radius: 14px; background: var(--bg2); font-size: 15px; font-weight: 600; }
.film-send-buttons { display: flex; gap: 8px; }
.film-send-buttons .film-pill { min-height: 40px; padding: 0 18px; font-size: 13px; }
.film-send-viber { animation: film-press 0.32s var(--ease-out) var(--at) both; }
.film-send-status { display: flex; align-items: center; gap: 10px; font-size: 13px; color: var(--ink2); }
.film-send-qr { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px; border-radius: 16px; background: var(--bg2); }
.film-qr { width: 150px; height: 150px; }
.film-qr-paper { fill: var(--surface); }
.film-qr-ink { fill: var(--ink); }

/* ── Replies ──────────────────────────────────────────────────────────── */

.film-replies { position: absolute; inset: 0; display: flex; flex-direction: column; gap: 18px; padding: 30px 36px; }
.film-stats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; }
.film-stat { display: flex; flex-direction: column; gap: 6px; padding: 18px; border-radius: 16px; background: var(--bg2); }
.film-stat-n { position: relative; display: block; height: 1em; font-size: 42px; line-height: 1; }
/* The reply table's own new row lands mid step, so its two headline numbers
   cross fade from what was true before it to what is true once it has
   arrived, reusing the fade the send screen's status line already plays
   with rather than a new pair of keyframes for the same opacity swap. */
.film-stat-n-before, .film-stat-n-after { position: absolute; inset: 0; }
.film-stat-n-before { animation: film-hide var(--dur-reveal) var(--ease-out) var(--at, 0s) both; }
.film-stat-n-after { animation: film-show var(--dur-reveal) var(--ease-out) var(--at, 0s) both; }
.film-stat-label { font-size: 12px; color: var(--muted); }
.film-table { display: flex; flex-direction: column; font-size: 13px; }
.film-table-row { display: grid; grid-template-columns: 2fr 1fr 1.4fr; padding: 13px 6px; border-bottom: 1px solid var(--line); border-radius: 8px; }
.film-table-row.is-head { padding: 10px 6px; border-radius: 0; color: var(--muted); }
.film-table-row.is-new { background: var(--accent-soft); font-weight: 600; }

/* ── Seating ──────────────────────────────────────────────────────────── */

.film-canvas-wrap { position: absolute; inset: 0; }
.film-canvas { position: absolute; left: 50%; top: 50%; width: 760px; height: 460px; margin: -230px 0 0 -380px; }
.film-canvas.film-after { height: 440px; margin-top: -220px; }
.film-canvas-note { position: absolute; left: 36px; right: 36px; bottom: 18px; }

.film-seat-bar { position: absolute; left: 0; top: 0; right: 0; display: flex; justify-content: space-between; font-size: 13px; }
.film-seat-list { position: absolute; left: 0; top: 44px; width: 210px; height: 416px; border-radius: 16px; background: var(--bg2); }
.film-seat-unseated {
  position: absolute;
  left: 14px;
  top: 56px;
  width: 182px;
  display: flex;
  justify-content: space-between;
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
}
.film-seat-left { width: 3ch; text-align: right; letter-spacing: 0; font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }
.film-seat-room { position: absolute; left: 240px; top: 44px; width: 520px; height: 416px; border-radius: 16px; background: var(--bg2); }
.film-seat-head {
  position: absolute;
  left: 420px;
  top: 60px;
  width: 160px;
  height: 26px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 6px;
  background: var(--line);
  color: var(--ink2);
  font-size: 11px;
}
.film-table-round {
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: 96px;
  height: 96px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  border-radius: 50%;
  background: var(--surface);
  box-shadow: 0 0 0 1px var(--line);
}
.film-table-round.is-star { box-shadow: 0 0 0 3px var(--accent); }
/* A table gives a little the moment a party lands, triggered by film.js
   adding this class at the moment of the step seatingPlan gives it, not by a
   delay, so a fast forward never leaves it waiting to play. */
.film-table-round.lands { animation: film-land 0.5s var(--ease-out) both; }
@keyframes film-land { 40% { transform: scale(1.06); } }
.film-table-label { font-size: 17px; font-weight: 700; line-height: 1; }
.film-table-count { width: 4ch; font-size: 11px; color: var(--muted); text-align: center; font-variant-numeric: tabular-nums; }

.film-seat-dot { position: absolute; left: var(--x); top: var(--y); width: 14px; height: 14px; border-radius: 50%; background: var(--line); }
.film-seat-dot.is-seated { background: var(--ink2); }
.film-seat-dot.is-fills::after { content: ""; position: absolute; inset: 0; border-radius: 50%; background: var(--accent); opacity: 0; }
/* film.js adds is-filled at the moment the seat's own `at` gives it. */
.film-seat-dot.is-fills.is-filled::after { animation: film-seat-fill 0.35s var(--ease-out) both; }
@keyframes film-seat-fill {
  0% { opacity: 0; transform: scale(0.5); }
  70% { opacity: 1; transform: scale(1.15); }
  100% { opacity: 1; transform: none; }
}

/* A chip's flight is set directly from how far through the step the film has
   played (film.js's filmScrub), never by a CSS timer, so a fast forward
   carries it straight to the table it implies instead of cutting it off mid air. */
.film-chip {
  position: absolute;
  left: 10px;
  top: var(--top);
  width: 190px;
  height: 38px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 19px;
  background: var(--ink);
  color: var(--bg);
  font-size: 12px;
  font-weight: 600;
}

/* ── Finding a seat ───────────────────────────────────────────────────── */

.film-findseat { position: absolute; inset: 0; display: flex; flex-direction: column; gap: 14px; padding: 28px 34px; }
.film-findseat-title { font-size: 28px; }
.film-findseat-recent { margin-top: 6px; font-size: 13px; font-weight: 600; }
/* The newest arrival takes the top row and the earlier ones make room for it. */
.film-arrivals { position: relative; padding-top: 58px; }
.film-arrivals-earlier {
  display: flex;
  flex-direction: column;
  gap: 14px;
  animation: film-make-room 0.6s var(--ease-out) var(--at) both;
}
@keyframes film-make-room { from { transform: translateY(-58px); } }
.film-arrival {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr;
  align-items: center;
  height: 44px;
  padding: 0 14px;
  border-radius: 10px;
  background: var(--bg2);
  font-size: 13px;
}
.film-arrival.is-new {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  background: var(--accent-soft);
  font-weight: 600;
  animation: film-arrive 0.6s var(--ease-out) var(--at) both;
}
@keyframes film-arrive { from { opacity: 0; transform: translateY(-8px) scale(0.97); } }

/* ── Photos arriving ──────────────────────────────────────────────────── */

.film-upload { position: absolute; inset: 0; display: flex; flex-direction: column; gap: 16px; padding: 28px 34px; }
.film-upload-title { font-size: 28px; }
.film-upload-grid { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 10px; }
.film-upload-tile { aspect-ratio: 3 / 4; border-radius: 10px; overflow: hidden; }
.film-upload-tile img, .film-after-tile img, .film-flyer img, .film-phone-tile img, .film-phone-photo img { display: block; width: 100%; height: 100%; object-fit: cover; }
.film-upload-note { max-width: 620px; font-size: 14px; line-height: 1.65; color: var(--ink2); }

/* ── Everyone's own photos ────────────────────────────────────────────── */

.film-after-heading { position: absolute; left: 0; top: 0; width: 500px; font-size: 13px; font-weight: 600; }
.film-after-tile { position: absolute; left: var(--x); top: var(--y); width: 118px; height: 118px; border-radius: 6px; overflow: hidden; }
.film-scan {
  position: absolute;
  left: -6px;
  top: 40px;
  width: 508px;
  height: 3px;
  background: var(--accent);
  box-shadow: 0 0 18px 4px var(--accent);
  animation: film-scan 1.7s var(--ease-in-out) 0.4s both;
}
@keyframes film-scan {
  0% { opacity: 0; transform: none; }
  8% { opacity: 1; }
  92% { opacity: 1; }
  100% { opacity: 0; transform: translateY(370px); }
}
.film-face-ring {
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: 40px;
  height: 40px;
  border-radius: 50%;
  box-shadow: 0 0 0 2px var(--on-photo), 0 0 0 4px var(--accent);
  animation: film-ring-pop 0.5s var(--ease-out) var(--at) both;
}
@keyframes film-ring-pop {
  0% { opacity: 0; transform: scale(1.6); }
  70% { opacity: 1; transform: scale(0.94); }
  100% { opacity: 1; transform: none; }
}
.film-face-tag {
  position: absolute;
  left: 50%;
  top: 46px;
  padding: 2px 7px;
  border-radius: 999px;
  background: var(--accent);
  color: var(--on-photo);
  font-size: 9px;
  font-weight: 600;
  white-space: nowrap;
  transform: translateX(-50%);
}
.film-album { position: absolute; left: 560px; top: 40px; width: 200px; height: 372px; border-radius: 16px; background: var(--bg2); }
.film-album-label { position: absolute; left: 578px; top: 56px; font-size: 11px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted); }
.film-flyer {
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: 118px;
  height: 118px;
  border-radius: 6px;
  overflow: hidden;
  box-shadow: 0 14px 28px -12px rgb(0 0 0 / 0.45);
  animation: film-fly 1s var(--ease-in-out) var(--at) both;
}
@keyframes film-fly {
  from { transform: none; }
  to { transform: translate(var(--dx), var(--dy)) rotate(var(--turn)) scale(1.18); }
}
.film-sent {
  position: absolute;
  left: 578px;
  top: 360px;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  border-radius: 999px;
  background: var(--ink);
  color: var(--bg);
  font-size: 11px;
  font-weight: 600;
  animation: film-settle 0.6s var(--ease-out) var(--at) both;
}
.film-sent .film-dot { width: 7px; height: 7px; }

/* ── The guest's phone ────────────────────────────────────────────────── */

.film-phone-create { position: absolute; inset: 0; overflow: hidden; background: var(--bg2); }
.film-phone-envelope { position: absolute; left: 50%; top: 50%; width: 520px; height: 560px; margin: -280px 0 0 -260px; transform: scale(0.44); }
.film-phone-balloons { position: absolute; left: 40px; top: 60px; width: 150px; }
.film-phone-trice { position: absolute; left: 30px; bottom: 30px; width: 170px; }
.film-phone-olive { position: absolute; left: -20px; top: 80px; width: 210px; }
.film-phone-owl { position: absolute; right: 16px; bottom: 60px; width: 90px; }
.film-phone-hint {
  position: absolute;
  left: 16px;
  right: 16px;
  bottom: 16px;
  padding: 10px;
  border-radius: 12px;
  background: var(--film-hint);
  color: var(--film-kids-ink);
  font-size: 11px;
  text-align: center;
}

.film-phone-form { position: absolute; inset: 0; display: flex; flex-direction: column; gap: 10px; padding: 44px 16px 16px; }
.film-phone-title { font-size: 24px; }
.film-phone-choice { display: flex; gap: 6px; }
.film-phone-choice .film-pill { flex-grow: 1; min-height: 36px; }
.film-phone-yes { background: var(--ink); color: var(--bg); animation: film-press 0.32s var(--ease-out) var(--at) both; }
.film-phone-answer { display: flex; justify-content: space-between; padding: 11px; border-radius: 10px; background: var(--bg2); font-size: 12px; }
.film-phone-cta { min-height: 40px; font-size: 12px; }
.film-phone-label { font-size: 12px; font-weight: 600; }
.film-phone-small { font-size: 10px; color: var(--muted); }

.film-phone-chat { position: absolute; inset: 0; display: flex; flex-direction: column; gap: 10px; padding: 44px 14px 14px; background: var(--bg2); }
.film-phone-app { font-size: 11px; color: var(--muted); text-align: center; }
.film-bubble { animation: film-message 0.5s var(--ease-out) var(--at) both; }
.film-bubble.is-in {
  align-self: flex-start;
  width: 190px;
  border-radius: 16px 16px 16px 4px;
  background: var(--surface);
  overflow: hidden;
  transform-origin: 0 100%;
}
.film-bubble.is-out {
  align-self: flex-end;
  padding: 9px 12px;
  border-radius: 16px 16px 4px 16px;
  background: var(--ink);
  color: var(--bg);
  font-size: 12px;
  transform-origin: 100% 100%;
  --from-x: 12px;
}
@keyframes film-message { from { opacity: 0; transform: translate(var(--from-x, -12px), 8px) scale(0.96); } }
.film-bubble-envelope { position: relative; height: 96px; background: var(--paper); }
.film-bubble-envelope::before, .film-bubble-flap {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 120px;
  height: 76px;
  margin: -38px 0 0 -60px;
  border-radius: 5px;
  background: var(--paper-deep);
}
.film-bubble-flap { clip-path: polygon(0 0, 50% 58%, 100% 0); background: var(--paper-flap); }
.film-bubble-seal { position: absolute; left: 50%; top: 50%; width: 20px; height: 20px; margin: -10px; border-radius: 50%; background: var(--accent); }
.film-bubble-caption { display: flex; flex-direction: column; padding: 9px 11px; font-size: 11px; line-height: 1.4; }

.film-phone-done { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; gap: 14px; padding: 60px 18px; text-align: center; }
.film-phone-check { width: 60px; height: 60px; display: flex; align-items: center; justify-content: center; border-radius: 50%; background: var(--accent-soft); }
.film-phone-check svg { width: 26px; height: 26px; fill: none; stroke: var(--accent); stroke-width: 2; stroke-linecap: round; }
.film-phone-thanks { font-size: 24px; line-height: 1.1; }
.film-phone-note { font-size: 12px; line-height: 1.5; color: var(--ink2); }
.film-phone-seat-title { font-size: 22px; line-height: 1.15; }
.film-phone-done .film-muted { font-size: 12px; }

.film-phone-field { padding: 10px 12px; border-radius: 10px; box-shadow: inset 0 0 0 1.5px var(--ink); font-size: 14px; }
/* The name is typed a letter at a time, and the caret sits after the last
   letter typed. Only opacity moves, so each letter and its caret are shown
   and hidden in turn rather than a box being widened. */
.film-typed { --type-start: 0.5s; --type-step: 0.157s; position: relative; display: inline-flex; min-height: 1.2em; }
.film-typed::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.15em;
  bottom: 0.1em;
  width: 2px;
  background: var(--ink);
  animation: film-hide 0.01s linear var(--type-start) both;
}
.film-key { position: relative; animation: film-show 0.01s linear calc(var(--type-start) + var(--k) * var(--type-step)) both; }
.film-key::after {
  content: "";
  position: absolute;
  right: -2px;
  top: 0.15em;
  bottom: 0.1em;
  width: 2px;
  background: var(--ink);
  opacity: 0;
  animation: film-hide 0.01s linear calc(var(--type-start) + (var(--k) + 1) * var(--type-step)) both;
}
.film-key.is-last::after { animation: film-blink 1s linear calc(var(--type-start) + var(--k) * var(--type-step)) 4 both; }
@keyframes film-blink { 0%, 50% { opacity: 1; } 50.1%, 100% { opacity: 0; } }
.film-phone-result { font-size: 11px; }
.film-phone-map { width: 100%; }
.film-map-table { fill: var(--surface); stroke: var(--muted); stroke-width: 1.2; }
.film-map-found {
  fill: var(--accent-soft);
  stroke: var(--accent);
  stroke-width: 2;
  transform-box: fill-box;
  transform-origin: center;
  animation: film-found 0.6s var(--ease-out) var(--at) both;
}
@keyframes film-found { 0% { opacity: 0; transform: scale(1.5); } 100% { opacity: 1; transform: none; } }
.film-map-label { font-size: 12px; font-weight: 700; fill: var(--ink); }

.film-phone-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 5px; }
/* The guest's own picks, on the phone from the first frame, each veiled with
   a turning ring until it is sent and then checked (film-upload.js). */
.film-phone-tile { position: relative; aspect-ratio: 1; border-radius: 7px; overflow: hidden; background: var(--bg2); }
.film-phone-veil {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  background: rgb(255 255 255 / 0.55);
  animation: film-veil-lift 0.25s var(--ease-out) var(--at) both;
}
.film-phone-veil::after {
  content: "";
  width: 30%;
  aspect-ratio: 1;
  border-radius: 50%;
  border: 2px solid rgb(255 255 255 / 0.9);
  border-top-color: var(--accent);
  animation: film-turn 0.8s linear infinite;
}
@keyframes film-veil-lift { to { opacity: 0; } }
@keyframes film-turn { to { transform: rotate(1turn); } }
.film-phone-sent {
  position: absolute;
  right: 4px;
  bottom: 4px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 1.5px #fff;
  animation: film-tick calc(var(--dur-reveal) * 0.55) var(--ease-out) var(--at) both;
}
.film-phone-sent::after {
  content: "";
  position: absolute;
  left: 5.5px;
  top: 3px;
  width: 4px;
  height: 7px;
  border: solid #fff;
  border-width: 0 1.5px 1.5px 0;
  transform: rotate(45deg);
}
.film-phone-progress { height: 6px; border-radius: 3px; background: var(--line); overflow: hidden; }
.film-phone-progress span {
  display: block;
  height: 100%;
  background: var(--accent);
  transform-origin: left center;
  animation: film-progress var(--for) steps(var(--photos), end) var(--at) both;
}
@keyframes film-progress { from { transform: scaleX(0); } }

.film-phone-mail { font-size: 20px; line-height: 1.15; }
.film-phone-photo { aspect-ratio: 1; border-radius: 10px; overflow: hidden; }

/* ── Below 900 pixels ─────────────────────────────────────────────────── */
/* On a phone the pinned frame holds the stage and, under it, the one step
   being shown: its phase and position, its number and title and a row of
   segments that fill as the track is scrolled. The text changes in
   place with the picture instead of scrolling away beneath it, which Stefan
   judged to be merely scrollable text. */
@media (max-width: 899px) {
  .film { padding: 48px 0 56px; --step-span: 28svh; }
  .film-head { margin-bottom: 20px; }
  .film-families { margin: 0 0 24px; }

  .film-frame {
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
    gap: 16px;
    padding-top: 10px;
  }

  /* Both screens, as on a computer, because what the host does (the tables
     dragged into the room, the replies counting up) is what sells, and Stefan
     judged a phone showing only the guest's side to be missing it. The host's
     screen fills the stage's width, and the guest's phone stands over its
     lower right corner, so the two read as one scene. The stage leaves about
     200 pixels above the action bar for the step's text, which on a short
     phone makes it narrower than the column. */
  .film-stage {
    --hs: calc(var(--film-w) / 806);
    --ps: calc(var(--film-w) * 0.34 / 250);
    order: -1;
    flex-shrink: 0;
    width: clamp(220px, calc((var(--frame-h) - 306px) * 0.78), 100%);
    height: calc(700px * var(--hs) + 500px * var(--ps) * 0.6);
    margin-inline: auto;
  }
  .film-host { transform: scale(var(--hs)); border-radius: 14px; }
  .film-phone {
    transform: translate(
      calc(var(--film-w) * 1px - 250px * var(--ps) - 6px),
      calc(700px * var(--hs) - 500px * var(--ps) * 0.4)
    ) scale(var(--ps));
  }

  .film-text { display: flex; flex-direction: column; gap: 10px; }
  .film-where {
    display: block;
    margin: 0;
    font-size: 12px;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--muted);
    font-variant-numeric: tabular-nums;
  }
  .film-phase, .film-step:not(.is-current) { display: none; }
  .film-step { gap: 8px; padding: 0; border-bottom: 0; animation: film-point-in 260ms var(--ease-out) both; }
  .film-step-label { gap: 12px; }
  .film-step-num { width: auto; font-size: 26px; }
  .film-step-title { font-family: var(--font-display); font-size: 26px; font-weight: 400; line-height: 1.12; }
  .film-step-track { display: none; }

  .film-progress { display: flex; gap: 4px; margin-top: 4px; }
  .film-segment { flex: 1 1 0; height: 3px; border-radius: 2px; background: var(--line); overflow: hidden; }
}

@media (prefers-reduced-motion: reduce) {
  .film-stage *, .film-stage *::before, .film-stage *::after {
    animation-duration: 1ms !important;
    animation-delay: 0s !important;
    animation-iteration-count: 1 !important;
  }
  .film-scene, .film-host, .film-phone, .film-step { transition: none; }
  .film-step { animation: none; }
}
