/* ==========================================================================
   Design tokens
   ========================================================================== */
:root {
  color-scheme: light;

  /* Palette */
  --color-sky: #DCEEF8;
  --color-white: #FFFFFF;
  --color-panel: #F8FCFF;
  --color-text: #1F3A42;
  --color-text-muted: #4A6670;
  --color-script: #0F2D55;
  --color-accent: #1B4A85;
  --color-accent-strong: #2A62A5;
  --color-primary: #2D6CB5;
  --color-primary-hover: #245B9C;
  --color-on-primary: #FFFFFF;
  --color-info: #228AD3;
  --color-info-text: #1A6FA8;
  --color-border: #D5E6F0;
  --color-note-bg: #F1F5F8;
  --color-error: #B3261E;
  --color-on-dark: #FFFFFF;
  --color-on-dark-muted: rgba(255, 255, 255, 0.86);
  --color-error-on-dark: #FFD3D8;

  /* Section backgrounds */
  --gradient-down: linear-gradient(180deg, #DCEEF8 0%, #FFFFFF 100%);
  --gradient-up: linear-gradient(180deg, #FFFFFF 0%, #DCEEF8 100%);

  /* Overlays (raise opacity when real photos are used) */
  /* White veil over the hero video: softens the deep blue sky behind the names, keeps the flowers vivid. */
  --hero-overlay: linear-gradient(180deg, rgba(255, 255, 255, 0.66) 0%, rgba(255, 255, 255, 0.52) 48%, rgba(255, 255, 255, 0.14) 82%, rgba(255, 255, 255, 0) 100%);
  --rsvp-overlay: rgba(10, 12, 30, 0.3);

  /* Typography */
  --font-script: 'Great Vibes', 'Snell Roundhand', cursive;
  --font-quote: 'Courgette', Georgia, serif;
  --font-serif: 'Cormorant Garamond', Georgia, 'Times New Roman', serif;
  --font-sans: 'Josefin Sans', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --text-base: 1.125rem;
  --text-small: 1rem;
  --text-label: 0.8125rem;
  --tracking-label: 0.18em;

  /* Spacing */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;
  --space-8: 64px;
  --space-9: 96px;
  --gutter: 16px;
  --content-width: 560px;
  --content-width-wide: 1040px;

  /* Shape */
  --radius-sm: 12px;
  --radius-md: 16px;
  --radius-lg: 24px;
  --radius-card: 22px;
  --radius-pill: 999px;
  --shadow-soft: 0 12px 32px rgba(31, 58, 66, 0.08), 0 2px 6px rgba(31, 58, 66, 0.04);
  --shadow-button: 0 6px 16px rgba(45, 108, 181, 0.28);

  /* Interaction */
  --tap-size: 44px;
  --control-height: 48px;
  --focus-color: var(--color-primary);
  --duration-fast: 160ms;
  --duration-reveal: 350ms;
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
}

/* ==========================================================================
   Base
   ========================================================================== */
*,
*::before,
*::after {
  box-sizing: border-box;
}

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

@media (prefers-reduced-motion: no-preference) {
  html {
    scroll-behavior: smooth;
  }
}

body {
  margin: 0;
  min-height: 100vh;
  background: var(--color-white);
  color: var(--color-text);
  font-family: var(--font-serif);
  font-size: var(--text-base);
  font-weight: 500;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-wrap: break-word;
}

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

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

address {
  font-style: normal;
}

a {
  color: var(--color-info-text);
}

button,
input,
select,
textarea {
  font: inherit;
  color: inherit;
}

:focus-visible {
  outline: 3px solid var(--focus-color);
  outline-offset: 3px;
}

[hidden] {
  display: none !important;
}

.sprite {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}

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

.icon {
  width: 20px;
  height: 20px;
  flex: none;
}

/* ==========================================================================
   Shared components
   ========================================================================== */
.eyebrow {
  font-family: var(--font-sans);
  font-size: var(--text-label);
  font-weight: 600;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-accent);
}

.script-title {
  font-family: var(--font-script);
  font-weight: 400;
  font-size: clamp(2.75rem, 11vw, 3.5rem);
  line-height: 1.15;
  color: var(--color-accent);
}

.script-title--light {
  color: var(--color-on-dark);
  text-shadow: 0 2px 12px rgba(0, 0, 0, 0.25);
}

.flourish {
  width: 168px;
  height: 20px;
  margin: 0 auto var(--space-4);
  color: var(--color-accent);
  opacity: 0.55;
}

/* Sized by height so the tall bouquet never fills a short (laptop or phone) viewport. */
.bouquet {
  display: block;
  width: auto;
  height: min(240px, 30vh);
  height: min(240px, 30svh);
  margin: 0 auto var(--space-4);
}

@media (min-width: 1024px) {
  .bouquet {
    height: min(280px, 32vh);
  }
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: var(--control-height);
  padding: 0 var(--space-5);
  border: 1px solid transparent;
  border-radius: var(--radius-pill);
  font-family: var(--font-sans);
  font-size: 0.9375rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  line-height: 1.2;
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--duration-fast) ease-out, transform var(--duration-fast) ease-out, box-shadow var(--duration-fast) ease-out;
  -webkit-tap-highlight-color: transparent;
}

.btn--primary {
  background: var(--color-primary);
  color: var(--color-on-primary);
  box-shadow: var(--shadow-button);
}

.btn--primary:hover {
  background: var(--color-primary-hover);
}

.btn--primary:active {
  transform: translateY(1px);
}

.btn--primary:disabled {
  cursor: progress;
  opacity: 0.75;
  transform: none;
}

.btn--block {
  width: 100%;
}

/* Secondary action next to a primary one on light backgrounds. */
.btn--outline {
  background: var(--color-white);
  border: 1.5px solid var(--color-primary);
  color: var(--color-primary);
}

.btn--outline:hover {
  background: var(--color-panel);
  border-color: var(--color-primary-hover);
  color: var(--color-primary-hover);
}

.card {
  background: var(--color-white);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-soft);
  padding: var(--space-6) var(--space-5);
}

.pill {
  display: inline-block;
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-pill);
  background: var(--color-panel);
  border: 1px solid var(--color-border);
  font-family: var(--font-sans);
  font-size: 0.875rem;
  letter-spacing: 0.02em;
  color: var(--color-text);
}

/* ==========================================================================
   Layout
   ========================================================================== */
.section {
  padding: var(--space-8) var(--gutter);
  text-align: center;
}

.section--down {
  background: var(--gradient-down);
}

.section--up {
  background: var(--gradient-up);
}

.section--panel {
  background: var(--color-panel);
}

.section__inner {
  width: 100%;
  max-width: var(--content-width);
  margin: 0 auto;
}

.section__subtitle {
  margin-top: var(--space-2);
  font-size: 1.25rem;
  font-weight: 500;
  color: var(--color-text);
}

@media (min-width: 768px) {
  .section {
    padding-block: var(--space-9);
  }

  .card {
    padding: var(--space-7) var(--space-6);
  }
}

/* ==========================================================================
   Hero
   ========================================================================== */
.hero {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  min-height: 100svh;
  padding: var(--space-8) var(--gutter) calc(var(--space-9) + var(--space-4));
  text-align: center;
  overflow: hidden;
  isolation: isolate;
  background: var(--color-sky);
}

.hero__bg {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  max-width: none;
  object-fit: cover;
  object-position: center bottom;
}

/* The video is portrait; on landscape screens frame the poppies instead of only the bottom daisies. */
@media (orientation: landscape) {
  .hero__bg {
    object-position: center 58%;
  }
}

.hero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--hero-overlay);
}

.hero__content {
  position: relative;
  isolation: isolate;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  max-width: var(--content-width);
}

/* Soft pearl halo behind the text block so the date and families stay readable over the meadow. */
.hero__content::before {
  content: "";
  position: absolute;
  inset: -18% -12%;
  z-index: -1;
  background: radial-gradient(closest-side, rgba(255, 255, 255, 0.82), rgba(255, 255, 255, 0.55) 60%, rgba(255, 255, 255, 0));
  pointer-events: none;
}

.hero__names {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin: var(--space-2) 0;
  font-family: var(--font-script);
  font-weight: 400;
  font-size: clamp(3.5rem, 16vw, 6rem);
  line-height: 1.05;
  color: var(--color-script);
}

/* Focus target after the intro opens; it is not interactive, so no ring. */
.hero__names:focus {
  outline: none;
}

.hero__amp {
  font-size: 0.6em;
  line-height: 1.2;
  color: var(--color-accent-strong);
}

.hero__date {
  font-family: var(--font-sans);
  font-size: 1.125rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  color: var(--color-text);
}

.hero__families {
  font-size: 1.1875rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  color: var(--color-text);
}

.hero__scroll {
  position: absolute;
  bottom: var(--space-5);
  left: 50%;
  transform: translateX(-50%);
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-1);
  min-height: var(--tap-size);
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-md);
  font-family: var(--font-sans);
  font-size: var(--text-label);
  font-weight: 600;
  letter-spacing: 0.12em;
  text-decoration: none;
  color: var(--color-text);
  /* Frosted chip: the hint sits over the busiest part of the video. */
  background: rgba(255, 255, 255, 0.72);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  box-shadow: 0 4px 16px rgba(31, 58, 66, 0.12);
}

.hero__scroll .icon {
  width: 24px;
  height: 24px;
  order: 2;
}

@media (prefers-reduced-motion: no-preference) {
  .hero__scroll .icon {
    animation: hint-bob 2.4s ease-in-out infinite;
  }
}

@keyframes hint-bob {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(4px); }
}

/* Calendar popover ---------------------------------------------------- */
.calendar-menu {
  position: relative;
  margin-top: var(--space-4);
}

.calendar-menu__list {
  position: absolute;
  top: calc(100% + var(--space-2));
  left: 50%;
  z-index: 20;
  width: max-content;
  min-width: 248px;
  max-width: calc(100vw - 2 * var(--gutter));
  margin: 0;
  padding: var(--space-2);
  list-style: none;
  transform: translateX(-50%);
  background: var(--color-white);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-soft);
  text-align: left;
}

.calendar-menu__item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: var(--control-height);
  padding: 0 var(--space-4);
  border-radius: var(--radius-sm);
  font-size: 1.0625rem;
  font-weight: 600;
  text-decoration: none;
  color: var(--color-text);
}

.calendar-menu__item .icon {
  color: var(--color-info);
}

.calendar-menu__item:hover,
.calendar-menu__item:focus-visible {
  background: var(--color-panel);
}

.calendar-menu__item:focus-visible {
  outline-offset: -3px;
}

/* ==========================================================================
   Countdown
   ========================================================================== */
.countdown {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  margin: var(--space-6) auto 0;
  max-width: 440px;
}

.countdown__unit {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-2) var(--space-1);
}

.countdown__unit + .countdown__unit {
  border-left: 1px solid rgba(15, 45, 85, 0.16);
}

.countdown__value {
  font-family: var(--font-sans);
  font-size: clamp(2rem, 9vw, 2.75rem);
  font-weight: 600;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  color: var(--color-script);
}

.countdown__label {
  font-family: var(--font-sans);
  font-size: var(--text-label);
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}

.quote {
  margin: var(--space-7) auto 0;
  max-width: 460px;
  font-family: var(--font-quote);
  font-size: 1.25rem;
  line-height: 1.7;
  color: var(--color-accent);
}

/* ==========================================================================
   Location
   ========================================================================== */
.location {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
  margin-top: var(--space-5);
}

.location__date {
  font-size: 1.1875rem;
}

.location__venue {
  margin-top: var(--space-2);
  font-size: 1.375rem;
  font-weight: 600;
  color: var(--color-script);
}

.location__address {
  max-width: 360px;
  color: var(--color-text-muted);
}

.location__map {
  width: 100%;
  margin: var(--space-3) 0 var(--space-2);
  aspect-ratio: 4 / 3;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--color-panel);
  border: 1px solid var(--color-border);
}

.location__map iframe {
  width: 100%;
  height: 100%;
  border: 0;
}

/* ==========================================================================
   Weather
   ========================================================================== */
.weather {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
}

.weather__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 64px;
  height: 64px;
  margin-bottom: var(--space-2);
  border-radius: 50%;
  background: var(--color-sky);
  color: var(--color-info);
}

.weather__icon .icon {
  width: 30px;
  height: 30px;
}

.weather__date {
  font-size: 1.1875rem;
}

.weather__venue {
  font-weight: 600;
  color: var(--color-script);
}

.weather__body {
  width: 100%;
  margin-top: var(--space-4);
  padding-top: var(--space-5);
  border-top: 1px solid var(--color-border);
}

.weather__message {
  color: var(--color-text-muted);
}

.weather__result {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
}

.weather__temp {
  font-family: var(--font-sans);
  font-size: 3.5rem;
  font-weight: 600;
  line-height: 1;
  color: var(--color-info-text);
}

.weather__condition {
  font-size: 1.25rem;
  font-weight: 600;
}

.weather__note {
  font-size: var(--text-small);
  color: var(--color-text-muted);
}

/* ==========================================================================
   RSVP
   ========================================================================== */
.rsvp {
  position: relative;
  padding: var(--space-8) var(--gutter);
  text-align: center;
  color: var(--color-on-dark);
  overflow: hidden;
  isolation: isolate;
  background: #2A3358;
}

.rsvp__bg {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  max-width: none;
  object-fit: cover;
}

.rsvp::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--rsvp-overlay);
}

.rsvp :focus-visible {
  outline-color: var(--color-on-dark);
}

.rsvp__card {
  margin-top: var(--space-5);
  padding: var(--space-5) var(--space-4);
  border: 1px solid rgba(255, 255, 255, 0.22);
  border-radius: var(--radius-card);
  background: rgba(14, 18, 44, 0.32);
  text-align: left;
}

@supports ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
  .rsvp__card {
    -webkit-backdrop-filter: blur(6px);
    backdrop-filter: blur(6px);
  }
}

@media (min-width: 768px) {
  .rsvp {
    padding-block: var(--space-9);
  }

  .rsvp__card {
    padding: var(--space-6);
  }
}

.rsvp-form {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}

.field {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
}

.field__label {
  padding: 0;
  font-size: 1.1875rem;
  font-weight: 600;
  color: var(--color-on-dark);
}

.field__optional {
  font-weight: 500;
  color: var(--color-on-dark-muted);
}

.field__control {
  width: 100%;
  min-height: var(--control-height);
  padding: var(--space-3) var(--space-4);
  border: 1.5px solid transparent;
  border-radius: var(--radius-sm);
  background: var(--color-white);
  color: var(--color-text);
  font-size: var(--text-base);
  line-height: 1.4;
}

.field__control:focus-visible {
  outline: 3px solid var(--color-on-dark);
  outline-offset: 2px;
}

.field__control[aria-invalid="true"] {
  border-color: var(--color-error);
  box-shadow: 0 0 0 2px var(--color-error-on-dark);
}

textarea.field__control {
  min-height: 120px;
  resize: vertical;
}

.select-wrap {
  position: relative;
}

.select-wrap select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: var(--space-7);
  cursor: pointer;
}

.select-wrap__icon {
  position: absolute;
  top: 50%;
  right: var(--space-4);
  transform: translateY(-50%);
  color: var(--color-primary);
  pointer-events: none;
}

.choices {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: var(--space-3);
}

.choice {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: var(--control-height);
  padding: var(--space-2) var(--space-4);
  border: 1.5px solid rgba(255, 255, 255, 0.55);
  border-radius: var(--radius-sm);
  font-size: var(--text-base);
  font-weight: 600;
  cursor: pointer;
  transition: background-color var(--duration-fast) ease-out, color var(--duration-fast) ease-out;
}

.choice input {
  width: 20px;
  height: 20px;
  margin: 0;
  flex: none;
  accent-color: var(--color-primary);
  cursor: pointer;
}

.choice:has(input:checked) {
  background: var(--color-white);
  border-color: var(--color-white);
  color: var(--color-script);
}

.choice:has(input[aria-invalid="true"]) {
  border-color: var(--color-error-on-dark);
}

.field__meta {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: var(--space-3);
}

.field__counter {
  margin-left: auto;
  font-family: var(--font-sans);
  font-size: 0.875rem;
  white-space: nowrap;
  color: var(--color-on-dark-muted);
}

.field__error {
  font-size: var(--text-small);
  font-weight: 600;
  color: var(--color-error-on-dark);
}

/* Honeypot: off-screen for humans, still in the DOM for bots. */
.hp {
  position: absolute;
  left: -10000px;
  top: auto;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.rsvp__status:empty {
  display: none;
}

.rsvp__status {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  margin-top: var(--space-4);
  font-size: var(--text-base);
  font-weight: 600;
}

.rsvp__status:focus {
  outline: none;
}

.rsvp__status:focus-visible {
  outline: 3px solid var(--color-on-dark);
  outline-offset: 4px;
  border-radius: var(--radius-sm);
}

.rsvp__status .icon {
  width: 24px;
  height: 24px;
  margin-top: 2px;
}

.rsvp__status[data-state="error"] {
  color: var(--color-error-on-dark);
}

.rsvp__status[data-state="success"] {
  flex-direction: column;
  align-items: center;
  margin-top: 0;
  padding: var(--space-4) 0;
  text-align: center;
  font-size: 1.375rem;
}

.rsvp__status[data-state="success"] .icon {
  width: 40px;
  height: 40px;
}

.rsvp__status-detail {
  display: block;
  margin-top: var(--space-2);
  font-size: var(--text-base);
  font-weight: 500;
  color: var(--color-on-dark-muted);
}

/* ==========================================================================
   Photo upload (light section: the shared form fields are restyled for dark text)
   ========================================================================== */
.photo-upload__intro {
  max-width: 460px;
  margin-inline: auto;
  font-size: var(--text-base);
}

.photo-upload {
  margin-top: var(--space-5);
  text-align: left;
}

.photo-form {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}

.photo-form .field__label {
  color: var(--color-text);
}

.photo-form .field__optional {
  color: var(--color-text-muted);
}

.photo-form .field__control {
  border-color: var(--color-border);
}

.photo-form .field__control:focus-visible {
  outline-color: var(--focus-color);
}

.photo-form__picker {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

/* The file input is visually hidden; mirror its keyboard focus and disabled state on the label button. */
.photo-form__input:focus-visible + .photo-form__pick {
  outline: 3px solid var(--focus-color);
  outline-offset: 3px;
}

.photo-form__input:disabled + .photo-form__pick {
  cursor: default;
  opacity: 0.75;
}

.photo-form__hint {
  font-size: var(--text-small);
  color: var(--color-text-muted);
  text-align: center;
}

.photo-list {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-3);
  margin: 0;
  padding: 0;
  list-style: none;
}

.photo-item {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-width: 0;
}

.photo-item__frame {
  position: relative;
  aspect-ratio: 1;
  border-radius: var(--radius-sm);
  overflow: hidden;
  background: var(--color-note-bg);
  border: 1px solid var(--color-border);
}

.photo-item__thumb {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.photo-item[data-state="uploading"] .photo-item__thumb {
  opacity: 0.55;
}

.photo-item[data-state="error"] .photo-item__frame {
  border: 2px solid var(--color-error);
}

/* Full 44px hit area in the corner; the visible chip inside is smaller. */
.photo-item__remove {
  position: absolute;
  top: 0;
  right: 0;
  display: flex;
  align-items: flex-start;
  justify-content: flex-end;
  width: var(--tap-size);
  height: var(--tap-size);
  padding: var(--space-1);
  border: 0;
  background: transparent;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.photo-item__remove:disabled {
  cursor: default;
  opacity: 0.55;
}

.photo-item__remove:focus-visible {
  outline-offset: -3px;
}

.photo-item__remove-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--color-white);
  color: var(--color-text);
  box-shadow: var(--shadow-soft);
}

.photo-item__remove-chip .icon {
  width: 16px;
  height: 16px;
}

.photo-item__note {
  font-family: var(--font-sans);
  font-size: var(--text-label);
  font-weight: 600;
  line-height: 1.3;
  color: var(--color-text-muted);
}

.photo-item[data-state="error"] .photo-item__note {
  color: var(--color-error);
}

.photo-upload__status:empty {
  display: none;
}

.photo-upload__status {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  margin-top: var(--space-4);
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--color-text);
}

.photo-upload__status:focus {
  outline: none;
}

.photo-upload__status:focus-visible {
  outline: 3px solid var(--focus-color);
  outline-offset: 4px;
  border-radius: var(--radius-sm);
}

.photo-upload__status .icon {
  width: 24px;
  height: 24px;
  margin-top: 2px;
}

.photo-upload__status[data-state="error"] {
  color: var(--color-error);
}

.photo-upload__status[data-state="success"] {
  color: var(--color-script);
}

.photo-upload__status-detail {
  display: block;
  margin-top: var(--space-1);
  font-size: var(--text-small);
  font-weight: 500;
  color: var(--color-text);
}

/* ==========================================================================
   Guestbook
   ========================================================================== */
.guestbook__status {
  margin-top: var(--space-4);
  color: var(--color-text-muted);
}

.guestbook__list {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  margin: var(--space-5) 0 0;
  padding: 0;
  list-style: none;
  text-align: left;
}

.note-card {
  padding: var(--space-4) var(--space-4) var(--space-4);
  background: var(--color-white);
  border-radius: 20px;
  box-shadow: var(--shadow-soft);
}

.note-card__head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-3);
  margin-bottom: var(--space-3);
}

.note-card__name {
  min-width: 0;
  font-size: 1.1875rem;
  font-weight: 600;
  color: var(--color-script);
}

.note-card__time {
  flex: none;
  font-family: var(--font-sans);
  font-size: 0.875rem;
  color: var(--color-text-muted);
}

.note-card__body {
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-sm);
  background: var(--color-note-bg);
  white-space: pre-line;
  overflow-wrap: anywhere;
}

/* ==========================================================================
   Wide screens: spread the cards out instead of a phone-width column
   ========================================================================== */
@media (min-width: 1024px) {
  .section__inner--wide {
    max-width: var(--content-width-wide);
  }

  .countdown {
    max-width: 560px;
  }

  .countdown__value {
    font-size: 3.5rem;
  }

  /* Location: details on the left, map on the right, details centred vertically. */
  .location {
    display: grid;
    grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
    grid-template-rows: 1fr repeat(5, auto) 1fr;
    column-gap: var(--space-7);
    row-gap: var(--space-3);
    justify-items: center;
  }

  .location > * {
    grid-column: 1;
  }

  .location .eyebrow {
    grid-row: 2;
  }

  .location__date {
    grid-row: 3;
  }

  .location__venue {
    grid-row: 4;
  }

  .location__address {
    grid-row: 5;
  }

  .location .btn {
    grid-row: 6;
    margin-top: var(--space-3);
  }

  .location__map {
    grid-column: 2;
    grid-row: 1 / -1;
    margin: 0;
  }

  /* Weather: title block on the left, forecast on the right. */
  .weather {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-template-rows: 1fr repeat(4, auto) 1fr;
    column-gap: var(--space-7);
    row-gap: var(--space-2);
    justify-items: center;
    max-width: 880px;
    margin-inline: auto;
  }

  .weather > * {
    grid-column: 1;
  }

  .weather__icon {
    grid-row: 2;
  }

  .weather .script-title {
    grid-row: 3;
  }

  .weather__date {
    grid-row: 4;
  }

  .weather__venue {
    grid-row: 5;
  }

  .weather__body {
    grid-column: 2;
    grid-row: 1 / -1;
    align-self: stretch;
    display: flex;
    flex-direction: column;
    justify-content: center;
    margin-top: 0;
    padding: 0 0 0 var(--space-7);
    border-top: 0;
    border-left: 1px solid var(--color-border);
  }

  .guestbook__list {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    align-items: start;
  }
}

/* ==========================================================================
   Footer
   ========================================================================== */
.footer {
  padding: var(--space-7) var(--gutter) var(--space-8);
  text-align: center;
  background: var(--gradient-down);
}

.footer__names {
  font-family: var(--font-script);
  font-size: 2.5rem;
  line-height: 1.2;
  color: var(--color-script);
}

/* Great Vibes draws its capital "A" like a lowercase "a", so "Aybike" reads as lowercase next to
   "Halil". The initial uses Alex Brush, whose "A" is a true capital with a matching entry swash;
   inline-block lets ::first-letter apply. */
[data-bind="coupleFirst"] {
  display: inline-block;
}

[data-bind="coupleFirst"]::first-letter {
  font-family: 'Alex Brush', var(--font-script);
  font-size: 1.15em;
  line-height: 0.8;
}

.footer__date {
  margin-top: var(--space-2);
  font-family: var(--font-sans);
  font-size: var(--text-label);
  font-weight: 600;
  letter-spacing: var(--tracking-label);
  color: var(--color-text-muted);
}

/* ==========================================================================
   Floating music button
   ========================================================================== */
.music-toggle {
  position: fixed;
  top: var(--space-4);
  left: var(--space-4);
  z-index: 50;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  padding: 0;
  border: 2px solid rgba(255, 255, 255, 0.85);
  border-radius: 50%;
  background: var(--color-primary);
  color: var(--color-on-primary);
  box-shadow: var(--shadow-button);
  cursor: pointer;
}

.music-toggle:hover {
  background: var(--color-primary-hover);
}

.music-toggle__icon--pause,
.music-toggle.is-playing .music-toggle__icon--play {
  display: none;
}

.music-toggle.is-playing .music-toggle__icon--pause {
  display: block;
}

@media (prefers-reduced-motion: no-preference) {
  .music-toggle.is-playing {
    animation: music-pulse 2s ease-out infinite;
  }
}

@keyframes music-pulse {
  0% { box-shadow: 0 0 0 0 rgba(45, 108, 181, 0.45), var(--shadow-button); }
  70% { box-shadow: 0 0 0 14px rgba(45, 108, 181, 0), var(--shadow-button); }
  100% { box-shadow: 0 0 0 0 rgba(45, 108, 181, 0), var(--shadow-button); }
}

/* ==========================================================================
   Intro cover (rings on a satin band)
   .js and .intro-active are set by the inline script at the top of <body>;
   main.js removes .intro-active (and the cover itself) once it has opened.
   ========================================================================== */
.intro-active,
.intro-active body {
  overflow: hidden;
}

.intro-active .music-toggle {
  visibility: hidden;
}

.intro {
  /* Watercolor card (assets/intro/): two paper doors, a satin band and two linked gold rings threaded on it. */
  --intro-paper: #F7F3EC;
  --intro-h: 100vh;
  --intro-band-h: 64px;
  --intro-band-shadow: 0 1px 3px rgba(30, 70, 130, 0.16), 0 6px 12px -6px rgba(30, 70, 130, 0.26);
  --intro-ring-d: 120px;
  /* ring.webp is 560x554 and the ring fills it, so the box's center is the ring's center. */
  --intro-ring-h: calc(var(--intro-ring-d) * 554 / 560);
  /* The rings overlap by 33% of their diameter: centers sit 0.335 diameters either side of the middle. */
  --intro-ring-offset: calc(var(--intro-ring-d) * 0.335);
  --intro-ring-shadow: drop-shadow(0 4px 5px rgba(30, 70, 130, 0.24));
  /* Vertical center of the band and the rings. */
  --intro-band-y: calc(var(--intro-h) * 0.42);
  /* Slow start, then the door keeps swinging until it leaves the view right as the transition ends. */
  --intro-ease-door: cubic-bezier(0.5, 0, 0.75, 0.9);
  --intro-ease-band: cubic-bezier(0.61, 1, 0.88, 1);

  display: none;
  position: fixed;
  top: 0;
  left: 0;
  z-index: 100;
  width: 100%;
  height: var(--intro-h);
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--color-text);
  text-align: center;
  overflow: hidden;
  perspective: 1600px;
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  -webkit-user-select: none;
  user-select: none;
}

@supports (height: 100dvh) {
  .intro {
    --intro-h: 100dvh;
  }
}

.js .intro {
  display: block;
}

.intro.is-opening {
  cursor: default;
}

/* The whole screen is the control; show the ring around the text block instead of the viewport edge. */
.intro:focus-visible {
  outline: none;
}

.intro:focus-visible .intro__label {
  outline: 3px solid var(--focus-color);
  outline-offset: 4px;
}

/* Paper doors ----------------------------------------------------------- */
.intro__door {
  position: absolute;
  top: 0;
  bottom: 0;
  overflow: hidden;
  /* Shown until paper.webp has loaded, so the cover never flashes transparent. */
  background-color: var(--intro-paper);
}

.intro__door--left {
  left: 0;
  right: 50%;
  transform-origin: 0% 50%;
}

.intro__door--right {
  left: 50%;
  right: 0;
  transform-origin: 100% 50%;
}

/* Portrait: the two doors are halves of one sheet (the sheet is twice a door's width). */
.intro__door::before {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  width: 200%;
  background: url('../assets/intro/paper.webp') center / cover no-repeat;
}

.intro__door--left::before {
  left: 0;
}

.intro__door--right::before {
  right: 0;
}

/* Shading on the free edge, faded in while the door swings open. */
.intro__door::after {
  content: '';
  position: absolute;
  inset: 0;
  opacity: 0;
}

.intro__door--left::after {
  background: linear-gradient(90deg, rgba(31, 58, 66, 0) 25%, rgba(31, 58, 66, 0.4) 100%);
}

.intro__door--right::after {
  background: linear-gradient(270deg, rgba(31, 58, 66, 0) 25%, rgba(31, 58, 66, 0.4) 100%);
}

/* Wide screens: a gatefold card, each door shows the whole sheet so all four flower corners stay visible. */
@media (min-aspect-ratio: 1/1) {
  .intro__door::before {
    inset: 0;
    width: auto;
  }
}

/* Satin band, split in the middle so each half can slide away ------------- */
/* ribbon.webp is not tileable: one copy is stretched across the band and each half shows its part. */
.intro__band {
  position: absolute;
  top: calc(var(--intro-band-y) - var(--intro-band-h) / 2);
  z-index: 2;
  height: var(--intro-band-h);
  background: url('../assets/intro/ribbon.webp') no-repeat;
  background-size: 200% 100%;
  box-shadow: var(--intro-band-shadow);
  /* The satin image is lavender; rotate its hue to the site's blue. */
  filter: hue-rotate(-55deg) saturate(1.1);
}

/* Each half keeps its shadow off the middle, so the two halves meet without a seam. */
.intro__band--left {
  left: 0;
  right: 50%;
  background-position: 0 0;
  clip-path: inset(-24px 0 -24px -24px);
}

.intro__band--right {
  left: 50%;
  right: 0;
  background-position: 100% 0;
  clip-path: inset(-24px -24px -24px 0);
}

/* Rings -----------------------------------------------------------------
   Each ring is cut into clipped pieces of the same box that never overlap, so
   they can fade out together without double-exposed seams:
   - --base, behind the band: everything except the pieces below;
   - --front, above the band: the outer side where it crosses the band (the band
     runs behind the outer sides and in front of the inner ones);
   - --link, above the right ring: the left ring's upper-right arc, so the left
     ring lies on top at the upper crossing (the right one stays on top at the lower).
   All pieces share position and transitions. Boxes only ever move sideways, so the
   cuts stay on the band's rows; float and turn are applied to the image inside. */
.intro__ring {
  /* Cut lines in the box (box center = band center): the band's edges plus the reach of its
     shadow, so the front pieces are never shaded by the band they lie on. */
  --intro-cut-top: calc(50% - var(--intro-band-h) / 2 - 4px);
  --intro-cut-bottom: calc(50% + var(--intro-band-h) / 2 + 12px);
  /* The link piece stops above the band's shadow, right of 60% of the box. */
  --intro-cut-link-y: var(--intro-cut-top);
  --intro-cut-link-x: 60%;
  --intro-cut-out: 16px;

  position: absolute;
  top: calc(var(--intro-band-y) - var(--intro-ring-h) / 2);
  z-index: 1;
  width: var(--intro-ring-d);
  height: var(--intro-ring-h);
}

/* The image lives on a pseudo-element so it can be turned and floated without moving the cuts. */
.intro__ring::before {
  content: '';
  position: absolute;
  inset: 0;
  background: url('../assets/intro/ring.webp') center / 100% 100% no-repeat;
  filter: var(--intro-ring-shadow);
}

.intro__ring--left {
  left: calc(50% - var(--intro-ring-offset) - var(--intro-ring-d) / 2);
}

.intro__ring--right {
  left: calc(50% + var(--intro-ring-offset) - var(--intro-ring-d) / 2);
}

/* Same image, mirrored and slightly turned, so the two rings do not look identical. */
.intro__ring--right::before {
  transform: scaleX(-1) rotate(8deg);
}

/* Outer edges reach --intro-cut-out past the box, so the shadow and the float are never cut off. */
.intro__ring--left.intro__ring--base {
  clip-path: polygon(
    calc(-1 * var(--intro-cut-out)) calc(-1 * var(--intro-cut-out)),
    var(--intro-cut-link-x) calc(-1 * var(--intro-cut-out)),
    var(--intro-cut-link-x) var(--intro-cut-link-y),
    calc(100% + var(--intro-cut-out)) var(--intro-cut-link-y),
    calc(100% + var(--intro-cut-out)) calc(100% + var(--intro-cut-out)),
    calc(-1 * var(--intro-cut-out)) calc(100% + var(--intro-cut-out)),
    calc(-1 * var(--intro-cut-out)) var(--intro-cut-bottom),
    50% var(--intro-cut-bottom),
    50% var(--intro-cut-top),
    calc(-1 * var(--intro-cut-out)) var(--intro-cut-top)
  );
}

.intro__ring--right.intro__ring--base {
  clip-path: polygon(
    calc(-1 * var(--intro-cut-out)) calc(-1 * var(--intro-cut-out)),
    calc(100% + var(--intro-cut-out)) calc(-1 * var(--intro-cut-out)),
    calc(100% + var(--intro-cut-out)) var(--intro-cut-top),
    50% var(--intro-cut-top),
    50% var(--intro-cut-bottom),
    calc(100% + var(--intro-cut-out)) var(--intro-cut-bottom),
    calc(100% + var(--intro-cut-out)) calc(100% + var(--intro-cut-out)),
    calc(-1 * var(--intro-cut-out)) calc(100% + var(--intro-cut-out))
  );
}

.intro__ring--front {
  z-index: 3;
}

.intro__ring--left.intro__ring--front {
  clip-path: polygon(
    calc(-1 * var(--intro-cut-out)) var(--intro-cut-top),
    50% var(--intro-cut-top),
    50% var(--intro-cut-bottom),
    calc(-1 * var(--intro-cut-out)) var(--intro-cut-bottom)
  );
}

.intro__ring--right.intro__ring--front {
  clip-path: polygon(
    50% var(--intro-cut-top),
    calc(100% + var(--intro-cut-out)) var(--intro-cut-top),
    calc(100% + var(--intro-cut-out)) var(--intro-cut-bottom),
    50% var(--intro-cut-bottom)
  );
}

.intro__ring--link {
  clip-path: polygon(
    var(--intro-cut-link-x) calc(-1 * var(--intro-cut-out)),
    calc(100% + var(--intro-cut-out)) calc(-1 * var(--intro-cut-out)),
    calc(100% + var(--intro-cut-out)) var(--intro-cut-link-y),
    var(--intro-cut-link-x) var(--intro-cut-link-y)
  );
}

/* Names on the band, either side of the rings ----------------------------- */
.intro__name {
  position: absolute;
  top: calc(var(--intro-band-y) - var(--intro-band-h) / 2);
  /* On the band but under the rings' front pieces, which slide over the names as they unlink. */
  z-index: 2;
  display: flex;
  align-items: center;
  height: var(--intro-band-h);
  font-family: var(--font-script);
  font-size: clamp(1.375rem, 6vw, 2.5rem);
  line-height: 1;
  color: var(--color-script);
  word-spacing: 0.1em;
  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.55);
  text-wrap: balance;
}

/* Each name box ends a small gap before the outer edge of its ring. */
.intro__name--first {
  left: var(--space-2);
  right: calc(50% + var(--intro-ring-offset) + var(--intro-ring-d) / 2 + var(--space-2));
  justify-content: flex-end;
  text-align: right;
}

.intro__name--second {
  left: calc(50% + var(--intro-ring-offset) + var(--intro-ring-d) / 2 + var(--space-2));
  right: var(--space-2);
  justify-content: flex-start;
  text-align: left;
}

/* Date and hint below the rings, printed on the paper --------------------- */
.intro__label {
  position: absolute;
  top: calc(var(--intro-band-y) + var(--intro-ring-h) / 2 + var(--space-4));
  left: 0;
  right: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  width: min(440px, calc(100% - 2 * var(--gutter) - env(safe-area-inset-left, 0px) - env(safe-area-inset-right, 0px)));
  margin: 0 auto;
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-card);
}

.intro__date {
  font-family: var(--font-sans);
  font-size: var(--text-label);
  font-weight: 600;
  letter-spacing: var(--tracking-label);
  color: var(--color-text-muted);
}

.intro__flourish {
  width: 120px;
  height: 16px;
  margin: 0 auto;
}

.intro__hint {
  font-family: var(--font-sans);
  font-size: var(--text-label);
  font-weight: 600;
  letter-spacing: 0.08em;
  color: var(--color-primary);
}

@media (min-width: 768px) {
  .intro {
    --intro-band-h: 84px;
    --intro-ring-d: 160px;
  }
}

/* Short landscape screens: smaller rings and tighter text so everything fits. */
@media (max-height: 560px) {
  .intro {
    --intro-band-h: 52px;
    --intro-ring-d: 96px;
    --intro-band-y: calc(var(--intro-h) * 0.36);
  }

  .intro__name {
    font-size: 1.75rem;
  }

  .intro__label {
    gap: var(--space-1);
    padding: var(--space-2) var(--space-4);
  }

  .intro__flourish {
    display: none;
  }
}

/* Open sequence (~1.9s): rings unlink (0-800ms) -> band halves pull free (300-1000ms)
   -> doors swing open (700-1900ms). Timings must match INTRO_OPEN_MS in js/main.js
   (the right door's transform ends last). */
@media (prefers-reduced-motion: no-preference) {
  .intro__ring {
    transition: transform 700ms var(--ease-out), opacity 300ms ease-in 500ms;
  }

  .intro__ring::before {
    animation: intro-ring-float 5s ease-in-out infinite;
    transition: rotate 700ms var(--ease-out);
  }

  .intro__hint {
    animation: intro-hint-pulse 2.4s ease-in-out infinite;
  }

  .intro__name,
  .intro__label {
    transition: opacity 500ms ease-out;
  }

  .intro__band {
    transition: transform 700ms var(--intro-ease-band) 300ms, opacity 250ms ease-in 750ms;
  }

  .intro__door {
    transition: transform 1200ms var(--intro-ease-door) 700ms, opacity 350ms ease-in 1550ms;
  }

  .intro__door::after {
    transition: opacity 900ms ease-out 700ms;
  }

  /* Hero content waits behind the cover, then fades up once it has opened. */
  .intro-active .hero__content > * {
    opacity: 0;
  }

  .hero--enter .hero__content > * {
    animation: hero-enter 650ms var(--ease-out) both;
  }

  .hero--enter .hero__content > :nth-child(2) { animation-delay: 80ms; }
  .hero--enter .hero__content > :nth-child(3) { animation-delay: 160ms; }
  .hero--enter .hero__content > :nth-child(4) { animation-delay: 240ms; }
  .hero--enter .hero__content > :nth-child(5) { animation-delay: 320ms; }
}

.intro.is-opening .intro__ring {
  opacity: 0;
}

.intro.is-opening .intro__ring--left {
  transform: translateX(calc(-0.8 * var(--intro-ring-d)));
}

.intro.is-opening .intro__ring--right {
  transform: translateX(calc(0.8 * var(--intro-ring-d)));
}

.intro.is-opening .intro__ring--left::before {
  rotate: -25deg;
}

.intro.is-opening .intro__ring--right::before {
  rotate: 25deg;
}

.intro.is-opening .intro__name,
.intro.is-opening .intro__label {
  opacity: 0;
}

/* The extra 32px also carries the band's drop shadow out of view. */
.intro.is-opening .intro__band--left {
  transform: translateX(calc(-100% - 32px));
  opacity: 0;
}

.intro.is-opening .intro__band--right {
  transform: translateX(calc(100% + 32px));
  opacity: 0;
}

/* Each door swings towards the viewer around its outer edge. */
.intro.is-opening .intro__door--left {
  transform: rotateY(-105deg);
  opacity: 0;
}

.intro.is-opening .intro__door--right {
  transform: rotateY(105deg);
  opacity: 0;
}

.intro.is-opening .intro__door::after {
  opacity: 1;
}

/* Reduced motion: a plain 200ms fade. The !important intentionally beats the global
   reduced-motion reset below (higher specificity wins between two !important rules). */
.intro.is-fading {
  opacity: 0;
  transition: opacity 200ms ease-out !important;
}

/* `translate`, so the right ring's mirroring `transform` is kept while it floats. */
@keyframes intro-ring-float {
  0%, 100% { translate: 0 2px; }
  50% { translate: 0 -2px; }
}

@keyframes intro-hint-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.55; }
}

@keyframes hero-enter {
  from {
    opacity: 0;
    transform: translateY(16px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* ==========================================================================
   Scroll reveal (only active once JS has initialised it, and never under reduced motion)
   ========================================================================== */
@media (prefers-reduced-motion: no-preference) {
  .reveal-ready .reveal {
    transition: opacity var(--duration-reveal) ease-out, transform var(--duration-reveal) ease-out;
  }

  .reveal-ready .reveal:not(.is-visible) {
    opacity: 0;
    transform: translateY(16px);
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation: none !important;
    transition: none !important;
  }
}
