/* ============================================================
   MOTYW: violet-dusk  (Fioletowa Wisteria)
   7 ekranów — wisteria, żyrandol, pałac nad wodą
   Paleta pobrana pipetą z plansz, wpisana też w THEMES w js/app.js —
   te dwa miejsca muszą się zgadzać.
   ============================================================ */

body[data-theme="violet-dusk"] {
  /* --- Paleta --- */
  --rg-ink:      #1F2A6B;      /* nagłówki, imiona */
  --rg-body:     #141B4A;      /* tekst opisowy */
  --rg-accent:   #6570C1;      /* przyciski */
  --rg-line:     #D8DCF2;      /* linie, ramki */
  --rg-pale:     #EFF1FB;
  --rg-cream:    #F7F8FE;      /* papier */
  --rg-card:     #FFFFFF;
  --rg-muted:    #7B83AE;

  /* --- Fonty (darmowe, z pełnym zestawem polskich znaków) --- */
  --rg-script:   'Pinyon Script', cursive;
  --rg-display:  'Cormorant Garamond', serif;
  --rg-ui:       'Poppins', sans-serif;
  --rg-text:     'Poppins', sans-serif;
  --rg-serif:    'Cormorant Garamond', serif;

  background: #FFFFFF;
  color: var(--rg-body);
  font-family: var(--rg-text);
}

body[data-theme="violet-dusk"] #rgScreens { background: var(--rg-cream); }

/* Plansze są pionowe 3:5 i mają wypełnić kadr bez zniekształceń. */
body[data-theme="violet-dusk"] .rg-screen .rg-bg {
  object-fit: cover;
  object-position: center;
}

/* Delikatny oddech tła — ruch jest w skali czasu kilkudziesięciu sekund,
   więc czyta się jak żywy papier, a nie jak animacja.
   Używamy WYŁĄCZNIE właściwości indywidualnych (translate/rotate/scale);
   `transform` jest zarezerwowany dla animacji odsłaniających. */
@keyframes violet-dusk-oddech {
  0%, 100% { scale: 1; }
  50%      { scale: 1.018; }
}
body[data-theme="violet-dusk"] .rg-screen .rg-bg {
  animation: violet-dusk-oddech 34s ease-in-out infinite;
}

@media (prefers-reduced-motion: reduce) {
  body[data-theme="violet-dusk"] .rg-screen .rg-bg { animation: none; }
}

/* Co się rusza i dlaczego akurat to.
   Plansza zbiorcza (`svg cała plansza/z tekstem full zaproszenie .svg`)
   wiesza na ekranie „data" trzy rzeczy pod sufitem: kaskadę wisterii
   w lewym rogu, jej lustro w prawym i żyrandol pomiędzy nimi. Do tej
   pory ruszał się wyłącznie żyrandol — wisteria po obu jego stronach
   stała jak przyklejona. Wisząca gałąź nieruchoma obok kołyszącego się
   żyrandola nie czyta się jako „spokój", tylko jako zacięta animacja.

   Wybieramy po nazwie pliku, bo warstwy są wstawiane dynamicznie
   i nie mają własnych klas — atrybut src jest jedynym pewnym uchwytem. */
@keyframes vd-dryf {
  0%,100% { translate: 0 0; rotate: 0deg; }
  33%      { translate: 0.8% -1.2%; rotate: 0.7deg; }
  66%      { translate: -0.6% -0.5%; rotate: -0.5deg; }
}

/* RZECZY WISZĄCE — kołyszą się wokół punktu zaczepienia, czyli górnej
   krawędzi. Poprzednie `transform-origin: 50% 12%` obracało kaskadę
   wokół punktu pod jej nasadą, przez co cała gałąź wędrowała w bok
   zamiast się bujać. */
body[data-theme="violet-dusk"] .rg-bg img[src$="zyrandol.webp"],
body[data-theme="violet-dusk"] .rg-bg img[src$="kwiaty_gora.webp"],
body[data-theme="violet-dusk"] .rg-bg img[src$="kwiaty_gora_p.webp"],
body[data-theme="violet-dusk"] .rg-bg img[src$="kwiaty_z_ptakami.webp"] {
  animation: vd-dryf 17s ease-in-out infinite;
  transform-origin: 50% 0%;
}

/* RZECZY LATAJĄCE — gołębie obracają się wokół własnego środka. */
body[data-theme="violet-dusk"] .rg-bg img[src$="golab.webp"],
body[data-theme="violet-dusk"] .rg-bg img[src$="illustracja_z_golebbiami.webp"] {
  animation: vd-dryf 17s ease-in-out infinite;
  transform-origin: 50% 50%;
}

/* Rozsuwamy fazy, żeby elementy nie ruszały się zgodnym marszem.
   Hak `data-drift` nadaje każdej warstwie strona zaproszenia (a/b/c wg
   kolejności w manifeście). Wcześniej stało tu `:nth-of-type(2n)`, które
   liczy WSZYSTKIE obrazki w warstwie, nie same gołębie — na ekranie
   historii pary trafiało w pierwszego gołębia i w ramkę zdjęcia, a drugi
   gołąb dostawał tę samą fazę co pierwszy tylko przez przypadek
   kolejności. `data-drift` jest niezależny od tego, ile warstw sąsiaduje. */
body[data-theme="violet-dusk"] .rg-bg img[data-drift="b"] { animation-delay: -5.7s;  }
body[data-theme="violet-dusk"] .rg-bg img[data-drift="c"] { animation-delay: -11.3s; }
/* Lustrzana kaskada po prawej nie może oddychać w tym samym rytmie co
   lewa — to ta sama grafika odbita i zgodny ruch od razu to zdradza. */
body[data-theme="violet-dusk"] .rg-bg img[src$="kwiaty_gora_p.webp"] { animation-duration: 21s; animation-delay: -8s; }

@media (prefers-reduced-motion: reduce) {
body[data-theme="violet-dusk"] .rg-bg img[src$="golab.webp"],
body[data-theme="violet-dusk"] .rg-bg img[src$="illustracja_z_golebbiami.webp"],
body[data-theme="violet-dusk"] .rg-bg img[src$="kwiaty_z_ptakami.webp"],
body[data-theme="violet-dusk"] .rg-bg img[src$="kwiaty_gora.webp"],
body[data-theme="violet-dusk"] .rg-bg img[src$="kwiaty_gora_p.webp"],
body[data-theme="violet-dusk"] .rg-bg img[src$="zyrandol.webp"] { animation: none; }
}

/* ══════════════════════════════════════════════════════════════
   UKŁAD TEKSTU — logika przeniesiona 1:1 z motywów 1–4
   ══════════════════════════════════════════════════════════════
   Poprzednia wersja pozycjonowała bloki wg pomiarów z projektu:
   `text-align: left` i `margin-left` równy lewej krawędzi napisu
   w pliku grafika. W przeglądarce imiona wychodziły poza kadr, bo
   platforma buduje sekcje jako WYŚRODKOWANĄ kolumnę, a nie jako
   swobodnie pozycjonowane pola. Dwa układy nakładały się na siebie.

   Zostaje to, co się sprawdziło w Ogrodzie Różanym i Amalfi:
     • jedna wyśrodkowana kolumna o szerokości ~60% planszy,
     • stopień pisma w clamp() — rośnie z oknem, ale ma sufit,
     • jedyna rzecz wzięta z pomiaru to ODSTĘP OD GÓRY, bo on
       decyduje, czy tekst trafi w puste pole planszy.
   ══════════════════════════════════════════════════════════════ */
body[data-theme="violet-dusk"] .rg-date .rg-inner {
  width: min(60vw, calc(var(--rg-w, 760px) * 0.60));
  margin: 0 auto;
  text-align: center;
  padding-top: calc(min(100vw, var(--rg-w, 760px)) * 5 / 3 * 0.2426);
}
body[data-theme="violet-dusk"] .rg-rsvp .rg-inner {
  width: min(52vw, calc(var(--rg-w, 760px) * 0.52));
  margin: 0 auto;
  text-align: center;
  padding-top: calc(min(100vw, var(--rg-w, 760px)) * 5 / 3 * 0.1508);
}
body[data-theme="violet-dusk"] .rg-outro .rg-inner {
  width: min(56vw, calc(var(--rg-w, 760px) * 0.56));
  margin: 0 auto;
  text-align: center;
  padding-top: calc(min(100vw, var(--rg-w, 760px)) * 5 / 3 * 0.0908);
}
body[data-theme="violet-dusk"] .rg-location .rg-inner {
  width: min(60vw, calc(var(--rg-w, 760px) * 0.60));
  margin: 0 auto;
  text-align: center;
  padding-top: calc(min(100vw, var(--rg-w, 760px)) * 5 / 3 * 0.6400);
}
body[data-theme="violet-dusk"] .rg-schedule .rg-inner {
  width: min(62vw, calc(var(--rg-w, 760px) * 0.62));
  margin: 0 auto;
  text-align: center;
  padding-top: calc(min(100vw, var(--rg-w, 760px)) * 5 / 3 * 0.0667);
}
body[data-theme="violet-dusk"] .rg-story .rg-inner {
  width: min(64vw, calc(var(--rg-w, 760px) * 0.64));
  margin: 0 auto;
  text-align: center;
  padding-top: calc(min(100vw, var(--rg-w, 760px)) * 5 / 3 * 0.0400);
}

/* Imiona: sufit dobrany tak, by najdłuższa polska para zmieściła się
   w kolumnie. Bez tego „Aleksandra & Krzysztof" wychodziło poza planszę. */
body[data-theme="violet-dusk"] .rg-names {
  font-size: clamp(34px, 9.4vw, 88px);
  line-height: 1.06;
  overflow-wrap: anywhere;
}
body[data-theme="violet-dusk"] .rg-sub {
  margin-top: clamp(14px, 3.2vw, 26px);
  line-height: 1.9;
}
body[data-theme="violet-dusk"] .rg-h {
  font-size: clamp(24px, 5.6vw, 52px);
}

/* ══════════════════════════════════════════════════════════════
   UKŁAD WG PLIKU ŹRÓDŁOWEGO (2026-08-30)
   „z tekstem full zaproszenie .svg" z folderu „fioletowe",
   płótno 900 × 1500 (osiem plansz w jednym pliku 900 × 11870,8;
   górne krawędzie na y = 0 / 1473,9 / 2961,5 / 4450 / 5931,7 /
   7420 / 8894,5 / 10389,8).

   Uwaga: w tym pliku teksty są ZAMIENIONE NA KRZYWE, więc pozycje
   poniżej to obrysy grup (zmierzone przez svgelements), a nie linie
   bazowe — dlatego są to od razu górne krawędzie bloków.

   Co pokazało porównanie z tym, co było na stronie:
     • ekran startowy miał kopertę złożoną z DWÓCH warstw (dolna część
       i górna, czyli klapa) i pieczęć — a odsłona tylko je wygaszała,
       zamiast otworzyć,
     • dress code miał w pliku CZTERY PRÓBKI KOLORÓW (#B9D2F0, #14325A,
       #BEB9F0, #37326E) — motyw nie miał `parts.dressPalette`, więc
       renderer sięgał po awaryjną różową paletę motywu 1,
     • przyciski są w pliku granatowe #282D60, nie #6570C1,
     • ekran 3 ma napis „Scratch to discover the date" (40,2 %), którego
       u nas nie było wcale,
     • wszystkie sekcje szły wyśrodkowaną kolumną, a projekt ma bloki
       w konkretnych miejscach planszy.
   ══════════════════════════════════════════════════════════════ */

body[data-theme="violet-dusk"] {
  --rg-ink:    #171C5D;   /* teksty i nagłówki z pliku */
  --rg-body:   #171C5D;
  --rg-accent: #282D60;   /* przyciski z planszy */
  --rg-pole:   #F6F2FF;   /* pole wiadomości */
}

/* ── ODSŁONA — KOPERTA, KTÓRA SIĘ ROZKŁADA ───────────────────
   Koperta jest złożona rombowo z czterech klap i tak też się
   rozkłada (obrysy i osie niżej, przy `.sk-*`). Pod nią nie ma
   żadnej wyściółki — leży tam od razu pierwsza plansza zaproszenia,
   więc kolejne klapy odsłaniają treść, a nie puste tło. */
body[data-theme="violet-dusk"] .plate-reveal {
  align-items: flex-start;
  background: var(--rg-cream, #F7F8FE);
}
/* Pod kopertą NIE ma wyściółki — pod nią leży od razu treść zaproszenia.
   Nakładka gubi więc swoje tło zaraz po kliknięciu, a klapy odchylają się
   już nad żywą pierwszą planszą: zaproszenie samo się odkrywa. */
body[data-theme="violet-dusk"] .plate-reveal.opening {
  /* podstawa wygasza CAŁĄ nakładkę; tutaj ma zostać widoczna do końca,
     bo to same klapy mają odjechać, a nie treść pod nimi przygasnąć */
  opacity: 1;
  background: transparent;
  transition: background-color .5s linear .25s;
}
body[data-theme="violet-dusk"] .plate-bleed { display: none; }
body[data-theme="violet-dusk"] .plate-stage {
  width: min(100vw, var(--rg-w, 760px));
  height: calc(min(100vw, var(--rg-w, 760px)) * 5 / 3);
}
/* Perspektywa siedzi na PŁÓTNIE, nie w każdym skrzydle osobno — dzięki
   temu wszystkie cztery klapy mają wspólny punkt zbiegu (środek grotu
   zaklejonej klapy) i rozkładają się jak jeden przedmiot. */
body[data-theme="violet-dusk"] .plate-canvas {
  perspective: 1500px;
  perspective-origin: 40% 50.6%;
}
body[data-theme="violet-dusk"] .plate-skrz {
  z-index: 2;
  transform: rotate3d(1, 0, 0, 0deg);
  transition: transform .95s cubic-bezier(.36, .02, .26, 1),
              opacity .3s linear;
}
body[data-theme="violet-dusk"] .sk-prawo {
  z-index: 4;
  transform-origin: 100% 50%;
}
body[data-theme="violet-dusk"] .sk-gora {
  z-index: 3;
  clip-path: polygon(11.9% -3%, 88.69% -3%, 54.15% 28.68%);
  transform-origin: 50% 0;
}
body[data-theme="violet-dusk"] .sk-dol {
  z-index: 3;
  clip-path: polygon(11.9% 103%, 88.69% 103%, 54.15% 72.48%);
  transform-origin: 50% 100%;
}
body[data-theme="violet-dusk"] .sk-lewo {
  z-index: 2;
  clip-path: polygon(-3% -3%, 11.9% -3%, 54.15% 28.68%, 103% 50.58%,
                     54.15% 72.48%, 11.9% 103%, -3% 103%);
  transform-origin: 0 50%;
}
body[data-theme="violet-dusk"] .plate-reveal.opening .sk-prawo {
  transform: rotateY(-155deg);
  opacity: 0;
  transition-delay: 0s, .72s;
}
body[data-theme="violet-dusk"] .plate-reveal.opening .sk-gora {
  transform: rotateX(150deg);
  opacity: 0;
  transition-delay: .34s, 1.06s;
}
body[data-theme="violet-dusk"] .plate-reveal.opening .sk-dol {
  transform: rotateX(-150deg);
  opacity: 0;
  transition-delay: .34s, 1.06s;
}
body[data-theme="violet-dusk"] .plate-reveal.opening .sk-lewo {
  transform: rotateY(150deg);
  opacity: 0;
  transition-delay: .5s, 1.22s;
}
/* Wisteria wisi NAD kopertą, nie jest jej częścią — więc nie składa
   się razem z papierem, tylko unosi się i gaśnie. */
body[data-theme="violet-dusk"] .plate-canvas .plate-layer[src$="kwiaty_z_ptakami.webp"] {
  z-index: 5;
  transition: translate 1.1s cubic-bezier(.36, .02, .26, 1), opacity .6s linear;
}
body[data-theme="violet-dusk"] .plate-reveal.opening .plate-layer[src$="kwiaty_z_ptakami.webp"] {
  translate: 0 -14%;
  opacity: 0;
  transition-delay: .1s, .5s;
}
/* Reszta warstw stoi — skala 1,08 z podstawy to był najazd, który po
   zniknięciu nakładki wyglądał jak cofnięcie. */
body[data-theme="violet-dusk"] .plate-reveal.opening .plate-layer {
  transform: none;
  opacity: 1;
}

body[data-theme="violet-dusk"] .plate-reveal.opening .plate-cta { opacity: 0; transition: opacity .3s; }
@media (prefers-reduced-motion: reduce) {
  body[data-theme="violet-dusk"] .plate-skrz,
  body[data-theme="violet-dusk"] .plate-reveal.opening .plate-skrz {
    transition: opacity .3s linear;
    transform: none;
  }
  body[data-theme="violet-dusk"] .plate-reveal.opening .plate-layer[src$="kwiaty_z_ptakami.webp"] {
    translate: none;
  }
}

/* --- Ramka płótna dla wszystkich sekcji treści --- */
body[data-theme="violet-dusk"] .rg-screen {
  position: relative;
  padding-top: 0;
  padding-bottom: 0;
  min-height: calc(var(--rg-w, 760px) * 5 / 3);
}
body[data-theme="violet-dusk"] .rg-screen > .rg-bg {
  height: calc(var(--rg-w, 760px) * 5 / 3);
}
body[data-theme="violet-dusk"] .rg-screen > .rg-inner {
  position: absolute;
  left: 50%;
  translate: -50% 0;
  top: 0;
  width: var(--rg-w, 760px);
  max-width: 100vw;
  height: calc(var(--rg-w, 760px) * 5 / 3);
  margin: 0;
  padding: 0;
  text-align: center;
  z-index: 3;
}
body[data-theme="violet-dusk"] .rg-screen > .rg-inner > * {
  position: absolute;
  margin: 0;
}
body[data-theme="violet-dusk"] .rg-h {
  font-family: var(--rg-display);
  font-style: italic;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
  line-height: 1.1;
  color: var(--rg-ink);
}

/* ── EKRAN 3 — DATA (u nas sekcja z imionami i licznikiem) ───
   Plansza niesie żyrandol (5,9–27,1 %) i trzy zdrapkowe kręgi
   (55,1–67,7 %). Napis „Scratch to discover the date" stoi w pliku
   na 40,2–49,8 % — jest częścią projektu, nie treści pary, więc
   siedzi w CSS. Licznik trafia dokładnie na kręgi, data z miejscem
   na blok tekstowy z pliku (69,9 %). Imiona idą w wolne pole między
   żyrandolem a napisem. */
body[data-theme="violet-dusk"] .rg-date .rg-names {
  left: 15%;
  width: 70%;
  top: 27.5%;
  font-family: var(--rg-script);
  font-size: clamp(28px, calc(var(--rg-w, 760px) * 0.078), 70px);
  line-height: 1.08;
  color: var(--rg-ink);
}
body[data-theme="violet-dusk"] .rg-date .rg-names .amp {
  display: inline;
  font-size: .55em;
  line-height: inherit;
  margin: 0;
}
body[data-theme="violet-dusk"] .rg-date .rg-sub {
  left: 20%;
  width: 60%;
  top: 34.5%;
  margin: 0;
  font-family: var(--rg-text);
  font-size: clamp(10px, calc(var(--rg-w, 760px) * 0.019), 17px);
  line-height: 1.6;
  letter-spacing: .01em;
  text-transform: none;
  color: var(--rg-ink);
}
body[data-theme="violet-dusk"] .rg-date > .rg-inner::before {
  content: "Scratch to discover the date";
  position: absolute;
  left: 22%;
  right: 22%;
  top: 40.2%;
  font-family: var(--rg-script);
  font-size: clamp(20px, calc(var(--rg-w, 760px) * 0.055), 50px);
  line-height: 1.15;
  color: var(--rg-ink);
  pointer-events: none;
}
/* Licznik NIE leży na zdrapkowych kręgach — w planszy zbiorczej kręgi
   są osobnym elementem (54,9–67,4 %), pod nimi idzie blok tekstowy
   (69,9 %), potem ornament (75,3 %), a licznik dopiero na 82,3–87,7 %
   (liczby 82,3 %, podpisy 85,5 %), w polu x 30,7–72,2 %. */
body[data-theme="violet-dusk"] .rg-date .rg-count {
  left: 26.5%;
  width: 47%;
  top: 81.6%;
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 0;
}
body[data-theme="violet-dusk"] .rg-date .rg-count > div {
  position: relative;
  flex: 1 1 0;
  text-align: center;
}
body[data-theme="violet-dusk"] .rg-date .rg-count .num {
  font-family: var(--rg-display);
  font-style: italic;
  font-size: clamp(20px, calc(var(--rg-w, 760px) * 0.055), 50px);
  line-height: 1.05;
  color: var(--rg-ink);
}
/* W planszy podpisy licznika są kursywą szeryfową, małymi literami —
   nie wersalikami, jak w pozostałych motywach. */
body[data-theme="violet-dusk"] .rg-date .rg-count .lbl {
  font-family: var(--rg-display);
  font-style: italic;
  font-size: clamp(11px, calc(var(--rg-w, 760px) * 0.024), 22px);
  letter-spacing: 0;
  text-transform: none;
  color: var(--rg-ink);
}
body[data-theme="violet-dusk"] .rg-date .rg-dateline {
  left: 22%;
  width: 56%;
  top: 69.9%;
  font-family: var(--rg-text);
  font-size: clamp(10px, calc(var(--rg-w, 760px) * 0.019), 17px);
  line-height: 1.6;
  color: var(--rg-ink);
}

/* ── EKRAN 5 — HARMONOGRAM ───────────────────────────────────
   Nagłówek na 9,0 %, cztery pozycje w PRAWEJ kolumnie
   (x 55,3–86,1 %), skok 13,98 % płótna; ikonki są warstwami
   planszy po lewej. */
body[data-theme="violet-dusk"] .rg-schedule .rg-h {
  left: 15%;
  width: 70%;
  top: 9%;
  font-size: clamp(22px, calc(var(--rg-w, 760px) * 0.058), 52px);
}
body[data-theme="violet-dusk"] .rg-schedule .rg-timeline {
  left: 55.3%;
  width: 32%;
  top: 23.9%;
  height: calc(var(--rg-w, 760px) * 5 / 3 * 0.559);
  display: flex;
  flex-direction: column;
  gap: 0;
  text-align: left;
}
/* Pionowa oś czasu — w planszy cienka kreska stoi na x 50,0 %
   i biegnie od 18,7 % do 73,3 % wysokości, a przy każdej pozycji
   siedzi granatowa elipsa ok. 2,6 % szerokości płótna. */
body[data-theme="violet-dusk"] .rg-schedule .rg-timeline::before {
  content: "";
  position: absolute;
  left: calc(var(--rg-w, 760px) * -0.053);
  top: calc(var(--rg-w, 760px) * 5 / 3 * -0.052);
  width: 1px;
  height: calc(var(--rg-w, 760px) * 5 / 3 * 0.5466);
  background: var(--rg-muted);
  opacity: .85;
}
body[data-theme="violet-dusk"] .rg-schedule .rg-item {
  position: relative;
  display: block;
  flex: 1 1 0;
  height: auto;
  min-height: 0;
  margin: 0;
  padding: 0;
}
body[data-theme="violet-dusk"] .rg-schedule .rg-item::before {
  content: "";
  position: absolute;
  left: calc(var(--rg-w, 760px) * -0.066);
  top: calc(var(--rg-w, 760px) * 0.012);
  width: calc(var(--rg-w, 760px) * 0.026);
  height: calc(var(--rg-w, 760px) * 0.018);
  border-radius: 50%;
  background: var(--rg-ink);
}
body[data-theme="violet-dusk"] .rg-schedule .rg-item .ico,
body[data-theme="violet-dusk"] .rg-schedule .rg-item .pearl { display: none; }
body[data-theme="violet-dusk"] .rg-schedule .rg-item .time,
body[data-theme="violet-dusk"] .rg-schedule .rg-item .desc {
  font-family: var(--rg-text);
  font-style: normal;
  font-size: clamp(10px, calc(var(--rg-w, 760px) * 0.019), 17px);
  line-height: 1.45;
  letter-spacing: 0;
  text-transform: none;
  color: var(--rg-ink);
  margin: 0;
}
body[data-theme="violet-dusk"] .rg-schedule .rg-item .desc { opacity: .8; }

/* ── EKRAN 4 — HISTORIA PARY ─────────────────────────────────
   Nagłówek 4,2 %, wstęga z bukietami 15,4–36,5 %, rama ze zdjęciem
   40,4–84,7 %, tekst pod nią na 86,9 %. Plansza nie ma tu bitmapy tła
   — jest jednolity odcień #FAF8FE. */
body[data-theme="violet-dusk"] .rg-story > .rg-bg { background: #FAF8FE; }
body[data-theme="violet-dusk"] .rg-story .rg-h {
  left: 15%;
  width: 70%;
  top: 4.2%;
  font-size: clamp(22px, calc(var(--rg-w, 760px) * 0.058), 52px);
}
body[data-theme="violet-dusk"] .rg-story .rg-heart,
body[data-theme="violet-dusk"] .rg-story .rg-collage,
body[data-theme="violet-dusk"] .rg-story .rg-postcard { display: none; }
body[data-theme="violet-dusk"] .rg-story .rg-cols {
  left: 19.9%;
  width: 60.3%;
  top: 86.9%;
  display: block;
  text-align: center;
}
body[data-theme="violet-dusk"] .rg-story .rg-cols .rg-p {
  display: inline;
  font-family: var(--rg-text);
  font-size: clamp(10px, calc(var(--rg-w, 760px) * 0.019), 17px);
  line-height: 1.5;
  color: var(--rg-ink);
  margin: 0;
}
body[data-theme="violet-dusk"] .rg-story .rg-cols .rg-p:first-child::after { content: " "; }

/* ── EKRAN 6 — LOKALIZACJA I DRESS CODE ──────────────────────
   Nagłówek 12,9 %, mapa 19,1–47,4 % (x 24,6–69,3 %), adres 53,2 %,
   przycisk 56,1–61,8 % (x 33,3–66,1 %), „Dresscode" 65,5 %,
   cztery próbki 78,5–89,2 % (x 16,8–84,5 %), opis 91,5 %. */
/* W planszy ten ekran nie ma bitmapy tła — jest czysta biel, na której
   stoi mapa, przycisk i próbki. Kolor daję sekcji, bo warstwa `tlo.webp`
   z dostawy (pałac z bramą) nie należy do tego ekranu. */
body[data-theme="violet-dusk"] .rg-location > .rg-bg { background: #FFFFFF; }

body[data-theme="violet-dusk"] .rg-location > .rg-inner > .rg-card {
  position: absolute;
  inset: 0;
  background: none;
  border: none;
  box-shadow: none;
  padding: 0;
  margin: 0;
  min-height: 0;
}
body[data-theme="violet-dusk"] .rg-location .rg-card > * {
  position: absolute;
  margin: 0;
}
body[data-theme="violet-dusk"] .rg-location .rg-h {
  left: 15%;
  width: 70%;
  top: 12.9%;
  font-size: clamp(22px, calc(var(--rg-w, 760px) * 0.058), 52px);
}
body[data-theme="violet-dusk"] .rg-location .rg-loc-cards { display: none; }
/* Mapa dokładnie z planszy: x 24,62–75,38 %, y 19,08–53,12 %. */
body[data-theme="violet-dusk"] .rg-location .rg-map {
  left: 24.62%;
  width: 50.77%;
  top: 19.08%;
  height: calc(var(--rg-w, 760px) * 5 / 3 * 0.3404);
  border: none;
  border-radius: 0;
}
body[data-theme="violet-dusk"] .rg-location .rg-addr {
  left: 20%;
  width: 60%;
  top: 53.2%;
  font-family: var(--rg-text);
  font-size: clamp(10px, calc(var(--rg-w, 760px) * 0.019), 17px);
  line-height: 1.5;
  color: var(--rg-ink);
}
body[data-theme="violet-dusk"] .rg-location .rg-btn {
  left: 33.27%;
  width: 32.8%;
  top: 56.07%;
  height: calc(var(--rg-w, 760px) * 5 / 3 * 0.0577);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border-radius: 999px;
  background: var(--rg-accent);
  color: #FFFFFF;
  font-family: var(--rg-text);
  font-size: clamp(10px, calc(var(--rg-w, 760px) * 0.0233), 21px);
  letter-spacing: .08em;
  text-transform: uppercase;
  white-space: nowrap;
}
/* Pinezka obok napisu — w planszy leży WEWNĄTRZ przycisku (x 59,6–63,4 %),
   więc nie może być warstwą tła: przycisk rysuje się nad planszą. */
body[data-theme="violet-dusk"] .rg-location .rg-btn::after {
  content: "";
  display: inline-block;
  width: calc(var(--rg-w, 760px) * 0.0387);
  height: calc(var(--rg-w, 760px) * 0.0489);
  margin-left: calc(var(--rg-w, 760px) * 0.018);
  background: currentColor;
  -webkit-mask: var(--vd-pin) center / contain no-repeat;
          mask: var(--vd-pin) center / contain no-repeat;
}
body[data-theme="violet-dusk"] {
  --vd-pin: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2C8.7 2 6 4.7 6 8c0 4.5 6 14 6 14s6-9.5 6-14c0-3.3-2.7-6-6-6zm0 8.4A2.4 2.4 0 1 1 12 5.6a2.4 2.4 0 0 1 0 4.8z'/%3E%3C/svg%3E");
}
body[data-theme="violet-dusk"] .rg-location .rg-btn:hover { background: #1E2350; }

body[data-theme="violet-dusk"] .rg-dress {
  position: absolute;
  left: 50%;
  translate: -50% 0;
  top: 0;
  width: var(--rg-w, 760px);
  max-width: 100vw;
  height: calc(var(--rg-w, 760px) * 5 / 3);
  margin: 0;
  padding: 0;
  background: none;
  pointer-events: none;
  z-index: 3;
}
body[data-theme="violet-dusk"] .rg-dress .rg-inner {
  position: absolute;
  inset: 0;
  translate: none;
  width: 100%;
  max-width: none;
  margin: 0;
  padding: 0;
  text-align: center;
}
body[data-theme="violet-dusk"] .rg-dress .rg-inner > * {
  position: absolute;
  margin: 0;
}
body[data-theme="violet-dusk"] .rg-dress .rg-h {
  left: 15%;
  width: 70%;
  top: 65.5%;
  font-size: clamp(22px, calc(var(--rg-w, 760px) * 0.058), 52px);
}
/* Cztery próbki kolorów — UKŁAD JAK W POZOSTAŁYCH MOTYWACH.

   Co tu było wcześniej i dlaczego to nie zadziałało: próbki stały
   w dwóch parach po skosie, każda przyklejona absolutnie do swojego
   rogu pola (lewa para: jedna niżej-lewo, druga wyżej-prawo; prawa
   odwrotnie), a sylwetki pary były schowane `display: none`. Odstępy
   między kółkami wychodziły z rozmiaru pola, nie ze wspólnej zmiennej,
   więc w tym jednym motywie były inne niż we wszystkich pozostałych,
   a środek rzędu — tam, gdzie wszędzie indziej stoi para — ział pustką.

   Wracamy do wzorca z `theme-rose-garden.css`: trzy kolumny
   `auto auto auto` wyśrodkowane, odstęp ze wspólnej zmiennej
   `--rg-dress-odstep`, para pośrodku. Zostaje tylko to, co jest
   naprawdę właściwością TEGO motywu: wysokość pasa z planszy
   (78,47 % płótna) i średnica kółek. */
body[data-theme="violet-dusk"] .rg-dress-grid {
  display: grid;
  grid-template-columns: auto auto auto;
  align-items: center;
  justify-content: center;
  column-gap: var(--rg-dress-odstep);
  left: 50%;
  translate: -50% 0;
  width: auto;
  top: 71.5%;
  /* WYSOKOŚĆ MUSI BYĆ PRZEWIDYWALNA, bo akapit pod spodem stoi na
     stałej pozycji w procentach płótna. Przy `height: auto` pasmo rosło
     tak, jak wysoka była grafika pary — i wchodziło na tekst. */
  height: calc(var(--rg-w, 760px) * 5 / 3 * 0.09);
  margin: 0;
}
body[data-theme="violet-dusk"] .rg-dress-grid .rg-swatches {
  position: static;
  display: flex;
  flex-direction: column;
  width: auto;
  height: auto;
  gap: var(--rg-dress-odstep);
}
/* Średnicy NIE nadpisujemy. Żaden inny motyw tego nie robi — wszystkie
   biorą wspólne `clamp(38px, 10vw, 58px)` z theme-rose-garden.css.
   Ten jeden miał 9,78 % szerokości płótna (ok. 74 px przy 760 px), czyli
   o jedną trzecią większe kółka niż wszędzie indziej. Stąd wrażenie, że
   dress code w fioletowym jest „rozjechany": inne odstępy i inny rozmiar
   w jedynym motywie, w którym ktoś je mierzył z planszy zamiast wziąć
   wspólne. Zostaje tylko zdjęcie pozycjonowania absolutnego. */
body[data-theme="violet-dusk"] .rg-dress-grid .rg-sw {
  position: static;
  box-shadow: none;
  margin: 0;
}
/* Sylwetki pary — środkowa kolumna. Szerokość z planszy; grafika ma
   własny margines, więc nie dostaje tła ani ramki. */
/* Sylwetki pary — środkowa kolumna.

   WYSOKOŚĆ PODANA WPROST, NIE W PROCENTACH — i to nie jest kosmetyka.
   Było `height: 100%`, co w Chromium rozwiązuje się względem pola
   siatki i dawało równe 114 px. W Safari element z `align-items: center`
   nie jest rozciągany, więc procent nie ma do czego się odnieść,
   przeglądarka traktuje go jak `auto` i wstawia obrazek w NATURALNEJ
   wielkości. Grafika wychodzila wtedy daleko poza pasmo i kładla sie
   na akapicie pod spodem. Ta sama liczba co wysokość pasma, podana
   w jednostkach płótna, zachowuje się tak samo w każdej przeglądarce.

   max-width pilnuje, żeby szeroka grafika nie rozepchnęła kolumn
   i nie wypchnęła próbek poza kadr. */
body[data-theme="violet-dusk"] .rg-dress-grid .rg-dress-fig {
  display: block;
  height: calc(var(--rg-w, 760px) * 5 / 3 * 0.09);
  width: auto;
  max-width: calc(var(--rg-w, 760px) * 0.34);
  object-fit: contain;
  margin: 0;
}

/* Akapit (treść dress code'u, np. „Elegancko") stał na 91,5 % płótna,
   czyli trzynaście punktów procentowych pod próbkami — przy pustym
   środku rzędu wyglądało to na odstęp, a po wstawieniu pary pasmo
   urosło i tekst znalazł się POD grafiką, częściowo na niej.
   Teraz stoi tuż pod pasmem: 71,5 % + 9 % wysokości + odstęp. */
/* 12.10 — POPRAWKA NA TELEFON. 82,5 % liczyło się od wysokości pasa
   z parą (9 % płótna), ale kolumna kółek bywa WYŻSZA od pasa: kółka
   mają wspólną średnicę clamp(38px, 10vw, 58px), a pas skaluje się
   z kadrem. Przy 390 px pas ma 58 px, kolumna kółek 90 px — dolne kółka
   wystawały pod pas i tekst na nie wchodził (−8 px). Wyższa kolumna
   nie rozkłada się przy tym równo w górę i w dół — siatka ma stałą
   wysokość, więc rząd rośnie W DÓŁ od 71,5 %. Akapit stoi więc pod
   WYŻSZYM z dwóch, liczonym od góry pasa, + odstęp 2 % szerokości
   kadru. Na telefonie tekst schodzi o ok. 26 px, na komputerze o 10. */
body[data-theme="violet-dusk"] .rg-dress .rg-p {
  left: 19.9%;
  width: 60.3%;
  top: calc(71.5%
            + max(var(--rg-w, 760px) * 5 / 3 * 0.09,
                  2 * clamp(38px, 10vw, 58px) + var(--rg-dress-odstep))
            + var(--rg-w, 760px) * 0.02);
  margin: 0 !important;
  font-family: var(--rg-text);
  font-size: clamp(10px, calc(var(--rg-w, 760px) * 0.019), 17px);
  line-height: 1.5;
  color: var(--rg-ink);
}

/* ── EKRAN 7 — RSVP ──────────────────────────────────────────
   „RSVP" 13,5 %, pytanie 22,5 %, odpowiedzi 27,8 i 30,6 %,
   „Wiadomość dla pary" 37,0 %, pole 42,7 %, przycisk 53,3–58,9 %
   (x 33,6–66,4 %), zdanie pod nim 62,6 %. */
/* Biała karta pod całym formularzem — w planszy zaczyna się na 9,8 %
   i kończy na 90,1 % wysokości, x 10,3–89,5 %, promień ok. 3,3 %
   szerokości płótna. Rysuję ją pseudoelementem TŁA, nie ramki treści:
   fontanna z gołębiem ma w projekcie wychodzić NA kartę, a warstwy
   planszy są dziećmi `.rg-bg`. Karta idzie na z-index 1 — nad akwarelowym
   tłem, a fontanna dostaje 2, więc wychodzi na kartę jak w projekcie. */
body[data-theme="violet-dusk"] .rg-rsvp > .rg-bg::after {
  content: "";
  position: absolute;
  left: 10.3%;
  width: 79.2%;
  top: 9.8%;
  height: 80.3%;
  background: #FFFFFF;
  border-radius: calc(var(--rg-w, 760px) * 0.033);
  z-index: 1;
}
body[data-theme="violet-dusk"] .rg-rsvp > .rg-bg img[src$="illustracja_z_golebbiami.webp"] {
  z-index: 2;
}

body[data-theme="violet-dusk"] .rg-rsvp > .rg-inner > .rg-card {
  position: absolute;
  inset: 0;
  background: none;
  border: none;
  box-shadow: none;
  padding: 0;
  margin: 0;
  min-height: 0;
}
body[data-theme="violet-dusk"] .rg-rsvp .rg-card > * {
  position: absolute;
  margin: 0;
}
body[data-theme="violet-dusk"] .rg-rsvp .rg-h {
  left: 20%;
  width: 60%;
  top: 13.5%;
  font-size: clamp(22px, calc(var(--rg-w, 760px) * 0.062), 56px);
}
body[data-theme="violet-dusk"] .rg-rsvp .rg-q {
  left: 20%;
  width: 60%;
  top: 22.5%;
  font-family: var(--rg-text);
  font-size: clamp(10px, calc(var(--rg-w, 760px) * 0.0211), 19px);
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--rg-ink);
}
body[data-theme="violet-dusk"] .rg-rsvp .rg-radios {
  left: 20%;
  width: 60%;
  top: 27.4%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: calc(var(--rg-w, 760px) * 5 / 3 * 0.009);
}
body[data-theme="violet-dusk"] .rg-rsvp .rg-radio {
  font-family: var(--rg-text);
  font-size: clamp(10px, calc(var(--rg-w, 760px) * 0.0189), 17px);
  color: var(--rg-ink);
}
body[data-theme="violet-dusk"] .rg-rsvp .rg-radio .dot { border-color: var(--rg-ink); }
/* Kreska między odpowiedziami a polem wiadomości — jest w planszy
   na 34,87 %, x 31,7–66,7 %. */
body[data-theme="violet-dusk"] .rg-rsvp .rg-sep {
  display: block;
  left: 31.7%;
  width: 35%;
  top: 34.87%;
  height: 1px;
  border: none;
  background: var(--rg-muted);
  opacity: .8;
}
body[data-theme="violet-dusk"] .rg-rsvp .rg-msg-label {
  left: 19.6%;
  width: 61%;
  top: 37%;
  font-family: var(--rg-text);
  font-size: clamp(10px, calc(var(--rg-w, 760px) * 0.0211), 19px);
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--rg-ink);
}
body[data-theme="violet-dusk"] .rg-rsvp .rg-textarea {
  left: 23.5%;
  width: 53%;
  top: 41.5%;
  height: calc(var(--rg-w, 760px) * 5 / 3 * 0.085);
  min-height: 0;
  background: var(--rg-pole);
  border: none;
  border-radius: 6px;
  color: var(--rg-ink);
  font-family: var(--rg-text);
  font-size: clamp(10px, calc(var(--rg-w, 760px) * 0.0167), 15px);
}
body[data-theme="violet-dusk"] .rg-rsvp .rg-btn {
  left: 33.6%;
  width: 32.8%;
  top: 53.28%;
  height: calc(var(--rg-w, 760px) * 5 / 3 * 0.0565);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border-radius: 999px;
  background: var(--rg-accent);
  color: #FFFFFF;
  font-family: var(--rg-text);
  font-size: clamp(10px, calc(var(--rg-w, 760px) * 0.0233), 21px);
  letter-spacing: .08em;
  text-transform: uppercase;
  white-space: nowrap;
}
body[data-theme="violet-dusk"] .rg-rsvp .rg-btn:hover { background: #1E2350; }
body[data-theme="violet-dusk"] .rg-rsvp .rg-note {
  left: 20%;
  width: 60%;
  top: 62.6%;
  font-family: var(--rg-text);
  font-size: clamp(9px, calc(var(--rg-w, 760px) * 0.0167), 15px);
  line-height: 1.5;
  color: var(--rg-ink);
  opacity: .75;
}

/* ── EKRAN 8 — ZAKOŃCZENIE ───────────────────────────────────
   Z pomiaru planszy wychodzilo: monogram 5,8 %, „Kilka słów" 23,1 %,
   zdanie od pary 31,5 %. Na ekranie te dwie pierwsze rzeczy stały za
   daleko od siebie — monogram przyklejony do górnej krawędzi, a nagłówek
   nisko, przez co środek planszy był pusty, a para na dole ściśnięta.

   Monogram schodzi o 3,5 pkt proc. w dół, nagłówek idzie o 3,1 w górę.
   Odstęp między nimi maleje z 17,3 do 10,7 pkt proc. Wiersz monogramu ma
   przy tym stopniu pisma 8,1 % wysokości płótna (0,135 szerokości, a ta
   jest 3/5 wysokości), więc kończy się na 17,4 % — do nagłówka zostaje
   2,6 pkt proc. zapasu i nic nie może się nałożyć. */
body[data-theme="violet-dusk"] .rg-outro .rg-monogram {
  left: 30%;
  width: 40%;
  top: 9.3%;
  font-family: var(--rg-script);
  font-size: clamp(40px, calc(var(--rg-w, 760px) * 0.135), 122px);
  line-height: 1;
  color: var(--rg-muted);
}
body[data-theme="violet-dusk"] .rg-outro .rg-h {
  left: 15%;
  width: 70%;
  top: 20.0%;
  font-size: clamp(22px, calc(var(--rg-w, 760px) * 0.058), 52px);
}
body[data-theme="violet-dusk"] .rg-outro .rg-cols {
  left: 18.3%;
  width: 63.4%;
  top: 31.5%;
  display: block;
  text-align: center;
}
body[data-theme="violet-dusk"] .rg-outro .rg-cols .rg-p {
  display: inline;
  font-family: var(--rg-text);
  font-size: clamp(10px, calc(var(--rg-w, 760px) * 0.019), 17px);
  line-height: 1.55;
  color: var(--rg-ink);
  margin: 0;
}
body[data-theme="violet-dusk"] .rg-outro .rg-cols .rg-p:first-child::after { content: " "; }

/* ══════════════════════════════════════════════════════════════
   13.10 — TEKSTY NA ŚRODKU SWOICH PÓL (pomiar planszy zbiorczej)
   Teksty w pliku są zamienione na krzywe, więc pola wziąłem z tuszu
   granatowych liter na wyrenderowanych planszach (900×1500):
     ekran 3: „Scratch…" 40,3–49,8 %, zdanie 69,9–73,5 %, ornament
              75,3–77,8 %, licznik 82,4–87,7 %; żyrandol kończy się
              na 33,65 %, kręgi 55,1–67,7 %,
     ekran 4: nagłówek 5,0–9,4 %, tekst na wstędze 19,1–26,8 %,
              rama 40,45–84,53 %, tekst pod ramą 87,1–91,7 %,
     ekran 5: nagłówek 9,5–13,9 %, punkty 26,5 / 40,8 / 54,9 / 68,5 %,
     ekran 7: „RSVP" 14,2–19,7, pytanie 22,8–26,0, odpowiedzi 27,9–32,3,
              „Wiadomość" 37,4–39,8, przycisk 53,3–58,9, fontanna od 67 %,
     ekran 8: nagłówek 21,7–28,9 %, zdanie 31,6–38,0 %.
   Każdy blok stoi teraz ŚRODKIEM na środku swojego pola
   (translate −50 % z własnej wysokości), więc krótszy czy dłuższy
   tekst zostaje na środku, a dłuższy od pola skrypt pomniejsza
   (--rg-fit). Pozycje w jednostkach płótna (--vd-1p), nie w %
   sekcji, bo sekcja bywa wyższa od płótna.
   ══════════════════════════════════════════════════════════════ */
body[data-theme="violet-dusk"] .rg-screen { --vd-1p: calc(var(--rg-w, 760px) * 5 / 3 / 100); }

/* RUCH. Paralaksa przesuwała warstwy o --rg-par × głębokość, a głębokość
   rośnie z numerem warstwy (żyrandol był 6., czyli ×3,7) — przy
   przewijaniu żyrandol zjeżdżał o ~150 px, na imiona i napis, a ornament
   na licznik. Kręgi miały do tego trzy różne dryfy i rozjeżdżały się
   w pionie. Warstwy stoją; kołyszą się nadal wisteria, żyrandol (wokół
   punktu zawieszenia) i gołębie. */
body[data-theme="violet-dusk"] .rg-bg img { transform: none !important; }
body[data-theme="violet-dusk"] .rg-bg img[src$="ornament.webp"],
body[data-theme="violet-dusk"] .rg-bg img[src$="ramka.webp"],
body[data-theme="violet-dusk"] .rg-bg img[src$="zdjecie.webp"],
body[data-theme="violet-dusk"] .rg-bg img[data-warstwa$="zdjecie.webp"],
body[data-theme="violet-dusk"] .rg-bg img[src$="papier.webp"] { animation: none; }

/* ── EKRAN 3: IMIONA, NAPIS, ZDRAPKI, ZDANIE, LICZNIK ───────── */
body[data-theme="violet-dusk"] .rg-date > .rg-inner {
  display: flex;
  flex-direction: column;
  justify-content: space-evenly;
  align-items: center;
  box-sizing: border-box;
  /* Pole między żyrandolem (33,65 %) a kręgami (55,1 %). */
  padding: calc(var(--vd-1p) * 33.9) calc(var(--rg-w, 760px) * 0.18) calc(var(--vd-1p) * 45.2);
}
body[data-theme="violet-dusk"] .rg-date .rg-names {
  position: static;
  order: 1;
  left: auto; width: auto; top: auto;
}
body[data-theme="violet-dusk"] .rg-date > .rg-inner::before {
  content: "Scratch to discover the date";
  position: static;
  order: 2;
  left: auto; right: auto; top: auto;
  width: calc(var(--rg-w, 760px) * 0.56);
  font-family: var(--rg-display);
  font-style: italic;
  font-weight: 500;
  font-size: max(20px, calc(var(--rg-w, 760px) * 0.064));
  line-height: 1.02;
  text-wrap: balance;
}
html[lang="pl"] body[data-theme="violet-dusk"] .rg-date > .rg-inner::before { content: "Zdrap, aby odkryć datę"; }
body[data-theme="violet-dusk"] .rg-date .rg-sub {
  left: 24%;
  width: 52%;
  top: calc(var(--vd-1p) * 71.7);
  translate: 0 -50%;
  line-height: 1.45;
  text-wrap: balance;
}
body[data-theme="violet-dusk"] .rg-date .rg-dateline { display: none; }
body[data-theme="violet-dusk"] .rg-date .rg-count {
  max-width: none;
  top: calc(var(--vd-1p) * 85.05);
  translate: 0 -50%;
}
/* Zdrapki */
body[data-theme="violet-dusk"] .rg-zdrapki { inset: 0; pointer-events: none; }
body[data-theme="violet-dusk"] .rg-zdrapki .zd {
  position: absolute;
  display: grid;
  place-items: center;
  pointer-events: auto;
}
body[data-theme="violet-dusk"] .rg-zdrapki .zd::before {
  content: "";
  position: absolute;
  inset: 8%;
  border-radius: 50%;
  background: radial-gradient(circle, #FFFFFF 0 55%, #E9ECFA 100%);
}
body[data-theme="violet-dusk"] .rg-zdrapki .zd-v {
  position: relative;
  font-family: var(--rg-display);
  font-style: italic;
  font-weight: 600;
  font-size: calc(var(--rg-w, 760px) * 0.05);
  line-height: 1;
  color: var(--rg-ink);
}
body[data-theme="violet-dusk"] .rg-zdrapki canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  touch-action: pan-y;   /* pionowo przewija stronę, w bok zdrapuje */
  cursor: grab;
  transition: opacity .9s ease;
}
body[data-theme="violet-dusk"] .rg-zdrapki canvas:focus-visible { outline: 2px solid var(--rg-accent); outline-offset: 4px; border-radius: 50%; }
body[data-theme="violet-dusk"] .rg-zdrapki .zd.odkryte canvas { opacity: 0; pointer-events: none; }
@keyframes vd-odkryte { 0% { scale: .85; opacity: .4; } 100% { scale: 1; opacity: 1; } }
body[data-theme="violet-dusk"] .rg-zdrapki .zd.odkryte .zd-v { animation: vd-odkryte .8s cubic-bezier(.22,1,.36,1); }

/* ── EKRAN 5: HARMONOGRAM ─────────────────────────────────────
   Oś na x 50 % od 19,5 do 73,5 %; punkty dzielą ją po równo (przy
   czterech wypadają na 26,3 / 39,8 / 53,3 / 66,8 % jak w pliku),
   każdy ma kropkę na osi, ikonkę po lewej i tekst po prawej — wszystko
   wyśrodkowane w pionie na kropce. */
body[data-theme="violet-dusk"] .rg-schedule > .rg-inner > .rg-h {
  left: 10%; width: 80%;
  top: calc(var(--vd-1p) * 11.7);
  translate: 0 -50%;
}
body[data-theme="violet-dusk"] .rg-schedule .rg-timeline {
  --vd-ico: calc(var(--vd-1p) * 10);
  left: 0;
  width: 100%;
  top: calc(var(--vd-1p) * 19.5);
  height: calc(var(--vd-1p) * 54);
  display: flex;
  flex-direction: column;
  text-align: left;
}
body[data-theme="violet-dusk"] .rg-schedule .rg-timeline:has(.rg-item:nth-child(5)) { --vd-ico: calc(var(--vd-1p) * 8.2); }
body[data-theme="violet-dusk"] .rg-schedule .rg-timeline:has(.rg-item:nth-child(6)) { --vd-ico: calc(var(--vd-1p) * 6.8); }
body[data-theme="violet-dusk"] .rg-schedule .rg-timeline::before {
  left: 50%;
  top: 0;
  height: 100%;
}
body[data-theme="violet-dusk"] .rg-schedule .rg-item {
  flex: 1 1 0;
  display: flex;
  align-items: center;
  min-height: 0;
}
body[data-theme="violet-dusk"] .rg-schedule .rg-item::before {
  left: calc(50% - var(--rg-w, 760px) * 0.013);
  top: 50%;
  margin-top: calc(var(--rg-w, 760px) * -0.009);
}
body[data-theme="violet-dusk"] .rg-schedule .rg-item .ico {
  display: block;
  position: absolute;
  left: 15%;
  width: 31%;
  top: 50%;
  height: var(--vd-ico);
  margin-top: calc(var(--vd-ico) / -2);
  object-fit: contain;
  object-position: center;
  pointer-events: none;
  animation: vd-ikona 7s ease-in-out infinite;
}
body[data-theme="violet-dusk"] .rg-schedule .rg-item:nth-child(2n) .ico { animation-delay: -2.4s; animation-duration: 8s; }
body[data-theme="violet-dusk"] .rg-schedule .rg-item:nth-child(3n) .ico { animation-delay: -4.6s; }
@keyframes vd-ikona { 0%, 100% { translate: 0 0; rotate: -1deg; } 50% { translate: 0 -4%; rotate: 1deg; } }
body[data-theme="violet-dusk"] .rg-schedule .rg-item .txt {
  position: static;
  margin-left: 55.3%;
  width: 31.5%;
  text-align: left;
}
body[data-theme="violet-dusk"] .rg-schedule .rg-item .time { font-weight: 600; }

/* ── EKRAN 4: HISTORIA — TEKST NA WSTĘDZE I POD RAMĄ ──────────
   Wstęga z planszy miała pusty środek, a cała historia szła pod ramę
   i na telefonie wychodziła poza ekran (interlinia z 16-pikselowego
   kontenera dawała ~34 px między linijkami). Pierwsza połowa idzie na
   wstęgę (jak w pliku), druga pod ramę. */
body[data-theme="violet-dusk"] .rg-story > .rg-inner > .rg-h {
  top: calc(var(--vd-1p) * 7.2);
  translate: 0 -50%;
}
body[data-theme="violet-dusk"] .rg-story .rg-cols {
  left: 0; top: 0; width: 100%; height: 100%;
  pointer-events: none;
  font-size: clamp(10px, calc(var(--rg-w, 760px) * 0.019), 17px);
  line-height: 1.45;
}
body[data-theme="violet-dusk"] .rg-story .rg-cols .rg-p {
  --rg-fit: 1;
  position: absolute;
  display: block;
  overflow: hidden;
  text-align: center;
  text-wrap: balance;
  font-size: calc(clamp(10px, calc(var(--rg-w, 760px) * 0.019), 17px) * var(--rg-k, 1));
  line-height: 1.45;
  translate: 0 -50%;
}
body[data-theme="violet-dusk"] .rg-story .rg-cols .rg-p:first-child::after { content: none; }
body[data-theme="violet-dusk"] #rgStoryA {
  left: 21%; width: 58%;
  top: calc(var(--vd-1p) * 22.95);
  max-height: calc(var(--vd-1p) * 8.8);
}
body[data-theme="violet-dusk"] #rgStoryB {
  left: 19%; width: 62%;
  top: calc(var(--vd-1p) * 90.3);
  max-height: calc(var(--vd-1p) * 9.6);
}

/* ── EKRAN 6: LOKALIZACJA I DRESS CODE ───────────────────────── */
body[data-theme="violet-dusk"] .rg-location .rg-card .rg-h {
  top: calc(var(--vd-1p) * 15.4);
  translate: 0 -50%;
}
/* Adres środkiem między mapą (do 53,12 %) a „Dojazd" (od 56,07 %). */
body[data-theme="violet-dusk"] .rg-location .rg-addr {
  left: 15%; width: 70%;
  top: calc(var(--vd-1p) * 54.6);
  translate: 0 -50%;
  line-height: 1.3;
  text-wrap: balance;
}
/* „Dress code" środkiem między przyciskiem (do 61,84 %) a próbkami
   (od 71,5 %). */
body[data-theme="violet-dusk"] .rg-dress .rg-h {
  top: calc(var(--vd-1p) * 66.67);
  translate: 0 -50%;
}

/* ── EKRAN 7: RSVP ─────────────────────────────────────────── */
body[data-theme="violet-dusk"] .rg-rsvp .rg-h        { top: calc(var(--vd-1p) * 16.95); translate: 0 -50%; }
body[data-theme="violet-dusk"] .rg-rsvp .rg-q        { top: calc(var(--vd-1p) * 24.4);  translate: 0 -50%; }
body[data-theme="violet-dusk"] .rg-rsvp .rg-radios   { top: calc(var(--vd-1p) * 30.1);  translate: 0 -50%; }
body[data-theme="violet-dusk"] .rg-rsvp .rg-msg-label{ top: calc(var(--vd-1p) * 38.6);  translate: 0 -50%; }
/* Zdanie pod przyciskiem: dwie równe linijki, środkiem między
   przyciskiem (do 58,93 %) a gołębiem na fontannie (od 67 %). */
body[data-theme="violet-dusk"] .rg-rsvp .rg-note {
  --vd-notka: max(46%, 17em);
  left: calc(50% - var(--vd-notka) / 2);
  width: var(--vd-notka);
  top: calc(var(--vd-1p) * 62.95);
  translate: 0 -50%;
  line-height: 1.35;
  text-wrap: balance;
}

/* ── EKRAN 8: ZAKOŃCZENIE ──────────────────────────────────── */
body[data-theme="violet-dusk"] .rg-outro > .rg-inner > .rg-h {
  top: calc(var(--vd-1p) * 25.3);
  translate: 0 -50%;
}
body[data-theme="violet-dusk"] .rg-outro .rg-cols {
  --rg-fit: 1;
  top: calc(var(--vd-1p) * 34.8);
  translate: 0 -50%;
  max-height: calc(var(--vd-1p) * 8.6);
  overflow: hidden;
  font-size: calc(clamp(10px, calc(var(--rg-w, 760px) * 0.019), 17px) * var(--rg-k, 1));
  line-height: 1.5;
  text-wrap: balance;
}
body[data-theme="violet-dusk"] .rg-outro .rg-cols .rg-p { font-size: inherit; line-height: inherit; }
/* Telefon: zdanie pod kręgami łamało się na trzy linijki i dotykało
   ornamentu (75,3 %) — szersze pole trzyma je w dwóch. */
@media (max-width: 480px) {
  body[data-theme="violet-dusk"] .rg-date .rg-sub { left: 15%; width: 70%; }
}
body[data-theme="violet-dusk"] .rg-location .rg-addr { line-height: 1.2; }
body[data-theme="violet-dusk"] .rg-rsvp .rg-note { --vd-notka: max(46%, 18.5em); }

/* 13.10 — DRESS CODE ŚRODKIEM W WOLNYM POLU POD „DOJAZD".
   Nagłówek, para z kółkami i opis stały pod samym przyciskiem
   (nagłówek od 64,6 %, opis kończył się ok. 87 %), a pod nimi do końca
   ekranu zostawało ~13 % płótna pustego. Teraz to jedna kolumna
   wyśrodkowana w pionie w polu od dołu przycisku (61,84 %) do końca
   płótna — przestrzeń nad nagłówkiem i pod opisem jest równa, a odstępy
   wewnątrz bloku stałe, więc dłuższy opis czy wyższe kółka na telefonie
   rozkładają się symetrycznie. */
body[data-theme="violet-dusk"] .rg-dress .rg-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  /* Dół pola: następny ekran (RSVP) zachodzi na ten o 7vw (zakładka
     sekcji) i wygasza się na 8 % swojej wysokości — dół pola to środek
     tej zakładki, nie koniec płótna, inaczej na komputerze opis lądował
     tuż przy szwie, a na telefonie pod nim zostawało za dużo miejsca. */
  padding: calc(var(--vd-1p) * 61.84) 0 max(0px, calc(7vw - var(--vd-1p) * 4));
  gap: calc(var(--vd-1p) * 2.6);
}
/* Wersja ostateczna: środek bloku = środek między dołem „Dojazd"
   a górą białej karty RSVP (ekran RSVP zaczyna się 7vw przed końcem
   tego płótna, karta 9,8 % niżej). Liczone przez górny margines:
   pole od (61,84 + 9,8) % − 7vw do końca płótna ma ten sam środek. */
body[data-theme="violet-dusk"] .rg-dress .rg-inner {
  padding: calc(var(--vd-1p) * 71.64 - 7vw) 0 0;
  gap: calc(var(--vd-1p) * 3);
}
body[data-theme="violet-dusk"] .rg-dress .rg-inner > * {
  position: static !important;
  top: auto !important;
  left: auto !important;
  translate: none !important;
}
body[data-theme="violet-dusk"] .rg-dress .rg-h { width: 70%; }
body[data-theme="violet-dusk"] .rg-dress-grid { height: auto; min-height: calc(var(--vd-1p) * 9); }
body[data-theme="violet-dusk"] .rg-dress .rg-p { width: calc(var(--rg-w, 760px) * 0.603); max-width: 90vw; }
@media (max-width: 380px) {
  /* Najwęższe telefony: kółka mają stałą podłogę 38 px, więc blok jest
     względnie wyższy — ciaśniej i szerszy opis, żeby nie wszedł na szew. */
  body[data-theme="violet-dusk"] .rg-dress .rg-inner { gap: calc(var(--vd-1p) * 1.5); }
  body[data-theme="violet-dusk"] .rg-dress .rg-p { width: 84vw; }
}

/* Opis dress code'u może sięgać w zakładkę z ekranem RSVP (jego tło jest
   tam wygaszone) — sekcja lokalizacji leży nad nią, żeby nic go nie
   przysłaniało. */
body[data-theme="violet-dusk"] #rgLocation { z-index: 3; }

/* 13.10 — HISTORIA PARY W CAŁOŚCI NA WSTĘDZE.
   Tekst nie jest już dzielony na wstęgę i pole pod ramą — cały stoi na
   wstędze nad zdjęciem. Pole: papier wstęgi ma na osi y 15,9–30,4 %,
   gołębie zachodzą na górne rogi, bukiety na dolne, więc tekst ma
   x 23–77 % i y 17,4–29,1 % (środek 23,25 %). Dłuższą historię skrypt
   pomniejsza, aż się zmieści (--rg-fit na całym bloku). */
body[data-theme="violet-dusk"] .rg-story .rg-cols {
  --rg-fit: 1;
  left: 23%;
  width: 54%;
  height: auto;
  top: calc(var(--vd-1p) * 23.25);
  translate: 0 -50%;
  max-height: calc(var(--vd-1p) * 11.7);
  overflow: hidden;
  display: block;
  text-align: center;
  text-wrap: balance;
  font-size: calc(clamp(10px, calc(var(--rg-w, 760px) * 0.019), 17px) * var(--rg-k, 1));
  line-height: 1.42;
}
body[data-theme="violet-dusk"] .rg-story .rg-cols .rg-p,
body[data-theme="violet-dusk"] #rgStoryA,
body[data-theme="violet-dusk"] #rgStoryB {
  --rg-fit: 0;
  position: static;
  display: inline;
  translate: none;
  max-height: none;
  overflow: visible;
  font-size: inherit;
  line-height: inherit;
  left: auto; top: auto; width: auto;
}
body[data-theme="violet-dusk"] .rg-story .rg-cols .rg-p:first-child::after { content: " "; }
/* Telefon: wstęga ma tu ~80 px wysokości, a podłoga stopnia 10 px —
   pole szersze (po gołębiach i bukietach jest jeszcze miejsce między
   nimi) i ciaśniejsza interlinia, żeby historia nie malała poniżej ~9 px. */
@media (max-width: 600px) {
  body[data-theme="violet-dusk"] .rg-story .rg-cols {
    left: 19%;
    width: 62%;
    max-height: calc(var(--vd-1p) * 12.6);
    line-height: 1.28;
  }
}

/* 13.10 — „LOKALIZACJA" i monogram w zakończeniu na środku swoich pól.
   Górę pola wyznacza szew z poprzednim ekranem: każdy ekran zachodzi na
   poprzedni o 7vw, więc widoczna góra płótna to 7vw, nie 0 (na komputerze
   ~8 % płótna, na telefonie ~4 %). Nagłówek lokalizacji stał na 15,4 %
   środkiem — tuż nad mapą (19,08 %), a monogram R&P wisiał wysoko nad
   „KILKA SŁÓW OD PARY". Teraz środek = środek między szwem a mapą /
   nagłówkiem (korekta o tusz liter niżej, po pomiarze). */
body[data-theme="violet-dusk"] .rg-location .rg-card .rg-h {
  top: calc((7vw + var(--vd-1p) * 19.08) / 2 + var(--vd-1p) * var(--vd-tusz-lok, 0));
  translate: 0 -50%;
}
body[data-theme="violet-dusk"] .rg-outro .rg-monogram {
  top: calc((7vw + var(--vd-1p) * 23.9) / 2 + var(--vd-1p) * var(--vd-tusz-mono, 0));
  translate: 0 -50%;
}
/* Korekta o tusz monogramu (kaligrafia ma tusz wyżej niż środek pudełka),
   zmierzona: +0,59 pkt. Poniżej 345 px nagłówek łamie się na dwie linijki
   i zaczyna wyżej, więc pole jest krótsze: −0,66 pkt. */
body[data-theme="violet-dusk"] .rg-outro { --vd-tusz-mono: 0.59; }
@media (max-width: 344px) { body[data-theme="violet-dusk"] .rg-outro { --vd-tusz-mono: -0.66; } }
/* Poprawka: górę pola nad mapą wyznacza nie szew, tylko koniec
   wygaszenia tła tego ekranu (maska .rg-bg: 0–9 % płótna) — dopiero od
   tego miejsca biel jest pełna i tam oko widzi początek „miejsca na
   napis". Pole 9–19,08 %, środek 14,04 %. */
body[data-theme="violet-dusk"] .rg-location .rg-card .rg-h {
  top: calc(var(--vd-1p) * (14.04 + var(--vd-tusz-lok, 0)));
}
/* Monogram tak samo: góra pola = koniec wygaszenia tła zakończenia
   (maska 0–8 % płótna), dół = nagłówek. Środek 15,95 %. */
body[data-theme="violet-dusk"] .rg-outro .rg-monogram {
  top: calc(var(--vd-1p) * (15.95 + var(--vd-tusz-mono, 0)));
}
body[data-theme="violet-dusk"] .rg-outro { --vd-tusz-mono: 0; }
@media (max-width: 344px) { body[data-theme="violet-dusk"] .rg-outro { --vd-tusz-mono: 0; } }
/* Korekta o tusz kaligrafii (zmierzona: +0,6 pkt; przy dwulinijkowym
   nagłówku poniżej 345 px −0,66 pkt). */
body[data-theme="violet-dusk"] .rg-outro { --vd-tusz-mono: 0.6; }
@media (max-width: 344px) { body[data-theme="violet-dusk"] .rg-outro { --vd-tusz-mono: -0.66; } }
