/* ============================================================
   MOTYW: white-linen  (Biały Len)
   6 ekranów — koperta z pieczęcią, koronkowe serce, anioł
   Paleta pobrana pipetą z plansz, wpisana też w THEMES w js/app.js —
   te dwa miejsca muszą się zgadzać.
   ============================================================ */

body[data-theme="white-linen"] {
  /* --- Paleta --- */
  --rg-ink:      #3B3B3E;      /* nagłówki, imiona */
  --rg-body:     #2A2A2C;      /* tekst opisowy */
  --rg-accent:   #687684;      /* przyciski */
  --rg-line:     #EFEFF1;      /* linie, ramki */
  --rg-pale:     #F5F4F2;
  --rg-cream:    #FAF9F7;      /* papier */
  --rg-card:     #FFFFFF;
  --rg-muted:    #8A8A8F;

  /* --- 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="white-linen"] #rgScreens { background: var(--rg-cream); }

/* Plansze są pionowe 3:5 i mają wypełnić kadr bez zniekształceń. */
body[data-theme="white-linen"] .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 white-linen-oddech {
  0%, 100% { scale: 1; }
  50%      { scale: 1.018; }
}
body[data-theme="white-linen"] .rg-screen .rg-bg {
  animation: white-linen-oddech 34s ease-in-out infinite;
}

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

/* Kwiaty i anioł unoszą się jak na wietrze — motyw jest lekki, więc ruch też.
   Wybieramy po nazwie pliku, bo warstwy są wstawiane dynamicznie
   i nie mają własnych klas — atrybut src jest jedynym pewnym uchwytem. */
@keyframes wl-unos {
  0%,100% { translate: 0 0; rotate: -1.1deg; }
  50%      { translate: 0 -1.6%; rotate: 1.1deg; }
}
body[data-theme="white-linen"] .rg-bg img[src$="kwiatek.webp"],
body[data-theme="white-linen"] .rg-bg img[src$="kwiatek_1.webp"],
body[data-theme="white-linen"] .rg-bg img[src$="kwiatek_2.webp"],
body[data-theme="white-linen"] .rg-bg img[src$="aniol.webp"] {
  animation: wl-unos 13s ease-in-out infinite;
  transform-origin: 50% 12%;
}
/* Rozsuwamy fazy, żeby elementy nie ruszały się zgodnym marszem. */
body[data-theme="white-linen"] .rg-bg img[src$="kwiatek.webp"]:nth-of-type(2n) { animation-delay: -4.3s; }

@media (prefers-reduced-motion: reduce) {
body[data-theme="white-linen"] .rg-bg img[src$="kwiatek.webp"],
body[data-theme="white-linen"] .rg-bg img[src$="kwiatek_1.webp"],
body[data-theme="white-linen"] .rg-bg img[src$="kwiatek_2.webp"],
body[data-theme="white-linen"] .rg-bg img[src$="aniol.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="white-linen"] .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.2400);
}
body[data-theme="white-linen"] .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.1804);
}
body[data-theme="white-linen"] .rg-outro .rg-inner {
  width: min(56vw, calc(var(--rg-w, 760px) * 0.56));
  margin: 0 auto;
  text-align: center;
}
body[data-theme="white-linen"] .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.3600);
}
body[data-theme="white-linen"] .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.1317);
}
body[data-theme="white-linen"] .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.6400);
}

/* 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="white-linen"] .rg-names {
  font-size: clamp(34px, 9.4vw, 88px);
  line-height: 1.06;
  overflow-wrap: anywhere;
}
body[data-theme="white-linen"] .rg-sub {
  margin-top: clamp(14px, 3.2vw, 26px);
  line-height: 1.9;
}
body[data-theme="white-linen"] .rg-h {
  font-size: clamp(24px, 5.6vw, 52px);
}

/* ══════════════════════════════════════════════════════════════
   UKŁAD WG PLIKU ŹRÓDŁOWEGO (2026-08-26)
   „z tekstem full zaproszenie białe minimalistyczne .svg",
   płótno 900 × 1497,45 (sześć ekranów w jednym pliku 900 × 8984,7).

   Poprzedni układ stawiał w każdej sekcji jedną wyśrodkowaną kolumnę
   i dobierał tylko odstęp od góry. Grafiki są jednak KOLAŻEM: imiona
   należą do karteczki po prawej, „Save the date" do koronkowego serca
   po lewej, licznik do ozdobnej etykiety na dole, a harmonogram to
   dwie kolumny (godzina | opis) na zawieszce. Jedna kolumna nie ma
   jak w to trafić — stąd teksty w złych miejscach.

   Teraz każda sekcja ma wysokość PŁÓTNA, a `.rg-inner` jest ramką
   płótna (900 × 1500), więc bloki tekstu można ustawić dokładnie tam,
   gdzie stoją w projekcie. Wszystkie liczby poniżej to procenty
   z pliku źródłowego: pozycje z prostokątów tekstowych, stopnie pisma
   przeliczone jako px/900 szerokości płótna.
   ══════════════════════════════════════════════════════════════ */

/* --- Kolory z pliku: to jest motyw GRANATOWY na bieli, nie szary --- */
body[data-theme="white-linen"] {
  --rg-ink:       #002570;   /* nagłówki „The Seasons" */
  --rg-body:      #002570;   /* teksty „Now Light" */
  --rg-names:     #002266;   /* imiona pary */
  --rg-count:     #001468;   /* licznik */
  --rg-rsvp:      #001866;   /* formularz RSVP */
  --rg-outro-ink: #00215B;   /* zakończenie */
  --rg-graphite:  #2D2D2D;   /* „Lokalizacja", data */
  --rg-graphite2: #353535;   /* „Dresscode" */
  --rg-accent:    #003FA3;   /* przycisk RSVP z planszy */
  --rg-taupe:     #A99E90;   /* przycisk „Dojazd" z planszy */
  /* The Seasons → Bodoni Moda (ten sam zamiennik co w motywie 4);
     Cormorant był o klasę za lekki i za wąski. */
  --rg-display:   'Bodoni Moda', serif;
  --rg-serif:     'Bodoni Moda', serif;
}

/* --- Ramka płótna: sekcja = 900 × 1500, `.rg-inner` = to samo pole --- */
body[data-theme="white-linen"] .rg-screen {
  position: relative;
  padding-top: 0;
  padding-bottom: 0;
  min-height: calc(var(--rg-w, 760px) * 5 / 3);
}
body[data-theme="white-linen"] .rg-screen > .rg-bg {
  height: calc(var(--rg-w, 760px) * 5 / 3);
}
body[data-theme="white-linen"] .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;
}
/* Wspólny skrót: blok tekstu ustawiony w procentach płótna. */
body[data-theme="white-linen"] .rg-screen > .rg-inner > * {
  position: absolute;
  margin: 0;
}

/* ── EKRAN 2 — IMIONA, DATA, LICZNIK ─────────────────────────
   Karteczka z koronkowym brzegiem zajmuje prawą górną część planszy
   (x 41–86 %): tam idą imiona i zaproszenie. Koronkowe serce po
   lewej (x 6,6–53,6 %) nosi „Save the date" i datę, a ozdobna
   etykieta na dole po prawej (x 55–92 %) — licznik. */
body[data-theme="white-linen"] .rg-date .rg-names {
  left: 41%;
  width: 45%;
  top: 24.4%;
  font-size: clamp(30px, calc(var(--rg-w, 760px) * 0.093), 71px);
  line-height: 1.12;
  color: var(--rg-names);
}
body[data-theme="white-linen"] .rg-date .rg-names .amp {
  font-size: .45em;
}
body[data-theme="white-linen"] .rg-date .rg-sub {
  left: 41%;
  width: 45%;
  top: 38.9%;
  font-size: clamp(10px, calc(var(--rg-w, 760px) * 0.0167), 13px);
  line-height: 1.75;
  letter-spacing: .02em;
  color: var(--rg-names);
  text-transform: none;
}
/* Data na koronkowym sercu, z odręcznym „Save the date" nad nią —
   tak jak na planszy (napis jest częścią projektu, nie treści pary,
   więc stoi w CSS, a nie w treści zaproszenia). */
body[data-theme="white-linen"] .rg-date .rg-dateline {
  left: 6.6%;
  width: 47%;
  top: 52.3%;
  font-family: var(--rg-display);
  font-size: clamp(12px, calc(var(--rg-w, 760px) * 0.0286), 22px);
  line-height: 1.5;
  color: var(--rg-graphite);
}
body[data-theme="white-linen"] .rg-date .rg-dateline::before {
  content: "Save the date";
  display: block;
  font-family: var(--rg-script);
  font-size: clamp(20px, calc(var(--rg-w, 760px) * 0.0403), 31px);
  line-height: 1.1;
  margin-bottom: .18em;
  color: var(--rg-graphite);
}
/* Licznik na etykiecie: trzy kolumny rozstawione jak w projekcie
   (55,2 / 67,0 / 78,1 % płótna), z dwukropkami między nimi. */
body[data-theme="white-linen"] .rg-date .rg-count {
  left: 55.2%;
  width: 36.8%;
  top: 64.5%;
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 0;
  color: var(--rg-count);
}
body[data-theme="white-linen"] .rg-date .rg-count > div {
  position: relative;
  flex: 1 1 0;
  text-align: center;
}
body[data-theme="white-linen"] .rg-date .rg-count > div + div::before {
  content: ":";
  position: absolute;
  left: -.18em;
  top: -.12em;
  font-family: var(--rg-display);
  font-size: clamp(18px, calc(var(--rg-w, 760px) * 0.0578), 44px);
  line-height: 1;
  color: var(--rg-count);
}
body[data-theme="white-linen"] .rg-date .rg-count .num {
  font-family: var(--rg-display);
  font-size: clamp(15px, calc(var(--rg-w, 760px) * 0.026), 20px);
  line-height: 1.2;
  color: var(--rg-count);
}
body[data-theme="white-linen"] .rg-date .rg-count .lbl {
  font-family: var(--rg-display);
  font-size: clamp(9px, calc(var(--rg-w, 760px) * 0.0167), 13px);
  letter-spacing: .04em;
  text-transform: none;
  color: var(--rg-count);
}

/* ── EKRAN 3 — HARMONOGRAM ───────────────────────────────────
   Zawieszka z kokardką ma narysowane LINIE — godzina i opis stoją
   na nich w dwóch kolumnach (x 15,7 % i 37,6 %), a nie jedna pod
   drugą. Ikonek ten motyw nie ma w dostawie (04 pliki 404 w konsoli),
   w projekcie ich zresztą nie ma. */
body[data-theme="white-linen"] .rg-schedule .rg-h {
  left: 8%;
  width: 84%;
  top: 12.6%;
  font-size: clamp(30px, calc(var(--rg-w, 760px) * 0.1111), 84px);
  line-height: 1.05;
  color: var(--rg-ink);
}
body[data-theme="white-linen"] .rg-schedule .rg-timeline {
  left: 15.74%;
  width: 64.21%;
  top: 30.2%;
  display: flex;
  flex-direction: column;
  gap: calc(var(--rg-w, 760px) * 5 / 3 * 0.076);
  text-align: left;
}
body[data-theme="white-linen"] .rg-schedule .rg-item {
  display: block;
  margin: 0;
  padding: 0;
}
body[data-theme="white-linen"] .rg-schedule .rg-item .ico,
body[data-theme="white-linen"] .rg-schedule .rg-item .pearl {
  display: none;
}
body[data-theme="white-linen"] .rg-schedule .rg-item .txt {
  display: grid;
  grid-template-columns: 34% 66%;
  align-items: baseline;
  column-gap: 0;
}
body[data-theme="white-linen"] .rg-schedule .rg-item .time,
body[data-theme="white-linen"] .rg-schedule .rg-item .desc {
  font-family: var(--rg-text);
  font-size: clamp(11px, calc(var(--rg-w, 760px) * 0.03), 23px);
  line-height: 1.25;
  letter-spacing: 0;
  text-transform: none;
  color: var(--rg-body);
  margin: 0;
}

/* ── EKRAN 4 — HISTORIA PARY ─────────────────────────────────
   Medalion ze zdjęciami, wstążka i pognieciony papier są warstwami
   planszy. Tekst to DWIE kolumny na papierze (x 20,8 % i 55,1 %,
   y ok. 65 %); serce ze zdjęciem z innych motywów tu nie występuje. */
body[data-theme="white-linen"] .rg-story .rg-h {
  left: 8%;
  width: 84%;
  top: 10%;
  font-size: clamp(30px, calc(var(--rg-w, 760px) * 0.1111), 84px);
  line-height: 1.05;
  color: var(--rg-ink);
}
body[data-theme="white-linen"] .rg-story .rg-heart,
body[data-theme="white-linen"] .rg-story .rg-collage,
body[data-theme="white-linen"] .rg-story .rg-postcard {
  display: none;
}
body[data-theme="white-linen"] .rg-story .rg-cols {
  left: 20.76%;
  width: 61.25%;
  top: 65.3%;
  display: grid;
  grid-template-columns: 47.8% 43.9%;
  column-gap: 8.3%;
  text-align: left;
}
body[data-theme="white-linen"] .rg-story .rg-cols .rg-p {
  font-size: clamp(10px, calc(var(--rg-w, 760px) * 0.0222), 17px);
  line-height: 1.6;
  color: var(--rg-body);
  margin: 0;
}

/* ── EKRAN 5 — LOKALIZACJA I DRESS CODE ──────────────────────
   Jedna plansza mieści oba bloki: list z sercami-zdjęciami i kopertą
   u góry (adres na liście, przycisk „Dojazd" na 50,7 %), a pod kopertą
   dress code (nagłówek 78,5 %, próbki 86,7 %, opis 93 %).
   Mapy Google w projekcie nie ma — miejsce zajmują zdjęcia w sercach.
   Zostaje jednak jako element użytkowy: schodzi na lico koperty,
   czyli w jedyne wolne pole planszy. */
body[data-theme="white-linen"] .rg-location > .rg-inner > .rg-card {
  position: absolute;
  inset: 0;
  background: none;
  border: none;
  box-shadow: none;
  padding: 0;
  margin: 0;
}
body[data-theme="white-linen"] .rg-location .rg-card > * {
  position: absolute;
  margin: 0;
}
body[data-theme="white-linen"] .rg-location .rg-h {
  left: 8%;
  width: 84%;
  top: 6.4%;
  font-size: clamp(26px, calc(var(--rg-w, 760px) * 0.0944), 71px);
  line-height: 1.05;
  color: var(--rg-graphite);
}
body[data-theme="white-linen"] .rg-location .rg-addr {
  left: 32.22%;
  width: 35.56%;
  top: 43.5%;
  font-size: clamp(10px, calc(var(--rg-w, 760px) * 0.0156), 12px);
  line-height: 1.7;
  color: var(--rg-body);
}
body[data-theme="white-linen"] .rg-location .rg-btn {
  left: 39.94%;
  width: 20.33%;
  top: 50.69%;
  height: calc(var(--rg-w, 760px) * 5 / 3 * 0.0351);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border-radius: 0;
  background: var(--rg-taupe);
  color: #FFFFFF;
  font-family: var(--rg-text);
  font-size: clamp(10px, calc(var(--rg-w, 760px) * 0.0225), 17px);
  letter-spacing: .08em;
  text-transform: uppercase;
}
body[data-theme="white-linen"] .rg-location .rg-btn:hover { background: #8F8578; }
body[data-theme="white-linen"] .rg-location .rg-map {
  left: 21%;
  width: 58%;
  top: 59.5%;
  height: calc(var(--rg-w, 760px) * 5 / 3 * 0.175);
  border: none;
  border-radius: 2px;
  opacity: .95;
}
body[data-theme="white-linen"] .rg-location .rg-loc-cards { display: none; }

/* Dress code — druga połowa tej samej planszy */
body[data-theme="white-linen"] .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;
}
body[data-theme="white-linen"] .rg-dress .rg-inner {
  position: absolute;
  inset: 0;
  width: 100%;
  max-width: none;
  margin: 0;
  padding: 0;
  text-align: center;
}
body[data-theme="white-linen"] .rg-dress .rg-inner > * {
  position: absolute;
  margin: 0;
}
body[data-theme="white-linen"] .rg-dress .rg-h {
  left: 8%;
  width: 84%;
  top: 77.9%;
  font-size: clamp(26px, calc(var(--rg-w, 760px) * 0.0944), 71px);
  line-height: 1.05;
  color: var(--rg-graphite2);
}
/* Cztery prostokątne próbki dokładnie w rozstawie z planszy
   (x 21,19 / 37,13 / 52,40 / 68,17 %, każda 11,02 × 3,47 %). */
body[data-theme="white-linen"] .rg-dress-grid {
  left: 21.19%;
  width: 58%;
  top: 86.67%;
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 0;
  max-width: none;
}
body[data-theme="white-linen"] .rg-swatches { display: contents; }
body[data-theme="white-linen"] .rg-dress-fig { display: none; }
body[data-theme="white-linen"] .rg-sw {
  width: calc(var(--rg-w, 760px) * 0.1102);
  height: calc(var(--rg-w, 760px) * 5 / 3 * 0.0347);
  border-radius: 0;
  border: none;
  box-shadow: none;
}
body[data-theme="white-linen"] .rg-dress .rg-p {
  left: 28.88%;
  width: 42.24%;
  top: 93%;
  margin: 0 !important;
  font-size: clamp(10px, calc(var(--rg-w, 760px) * 0.0167), 13px);
  line-height: 1.65;
  color: var(--rg-body);
}

/* ── EKRAN 6 — RSVP I ZAKOŃCZENIE ────────────────────────────
   Formularz siedzi w owalnej ramce z planszy (x 13–83 %, y 11–65 %),
   a pod nią zakończenie: nagłówek 70,9 %, imiona kaligrafią 76,8 %,
   zdanie 82,7 %, łabędzie 85–97 %. Wszystkie pozycje i rozmiary pól
   (pole wiadomości, przycisk) to prostokąty z pliku źródłowego. */
body[data-theme="white-linen"] .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="white-linen"] .rg-rsvp .rg-card > * {
  position: absolute;
  margin: 0;
}
body[data-theme="white-linen"] .rg-rsvp .rg-h {
  left: 16.41%;
  width: 67.5%;
  top: 17.4%;
  font-size: clamp(22px, calc(var(--rg-w, 760px) * 0.0656), 50px);
  line-height: 1.05;
  color: var(--rg-rsvp);
}
body[data-theme="white-linen"] .rg-rsvp .rg-q {
  left: 16.41%;
  width: 67.5%;
  top: 24.6%;
  font-family: var(--rg-text);
  font-size: clamp(11px, calc(var(--rg-w, 760px) * 0.0256), 19px);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--rg-rsvp);
}
body[data-theme="white-linen"] .rg-rsvp .rg-radios {
  left: 16.41%;
  width: 67.5%;
  top: 29.4%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: calc(var(--rg-w, 760px) * 5 / 3 * 0.012);
}
body[data-theme="white-linen"] .rg-rsvp .rg-radio {
  font-family: var(--rg-text);
  font-size: clamp(10px, calc(var(--rg-w, 760px) * 0.0229), 17px);
  color: var(--rg-rsvp);
}
body[data-theme="white-linen"] .rg-rsvp .rg-radio .dot { border-color: var(--rg-rsvp); }
body[data-theme="white-linen"] .rg-rsvp .rg-sep { display: none; }
body[data-theme="white-linen"] .rg-rsvp .rg-msg-label {
  left: 16.41%;
  width: 67.5%;
  top: 41.3%;
  font-family: var(--rg-text);
  font-size: clamp(11px, calc(var(--rg-w, 760px) * 0.0256), 19px);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--rg-rsvp);
}
body[data-theme="white-linen"] .rg-rsvp .rg-textarea {
  left: 33.41%;
  width: 33.51%;
  top: 43.88%;
  height: calc(var(--rg-w, 760px) * 5 / 3 * 0.0531);
  min-height: 0;
  background: #FFFEF8;
  border: 1px solid rgba(0, 24, 102, .22);
  border-radius: 0;
  color: var(--rg-rsvp);
  font-family: var(--rg-text);
  font-size: clamp(10px, calc(var(--rg-w, 760px) * 0.0167), 13px);
}
body[data-theme="white-linen"] .rg-rsvp .rg-btn {
  left: 38.58%;
  width: 23.16%;
  top: 52.07%;
  height: calc(var(--rg-w, 760px) * 5 / 3 * 0.0399);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border-radius: 0;
  background: var(--rg-accent);
  color: #FFFFFF;
  font-family: var(--rg-text);
  font-size: clamp(10px, calc(var(--rg-w, 760px) * 0.0256), 20px);
  letter-spacing: .08em;
  text-transform: uppercase;
}
body[data-theme="white-linen"] .rg-rsvp .rg-btn:hover { background: #0B4FBC; }
body[data-theme="white-linen"] .rg-rsvp .rg-note {
  left: 20%;
  width: 60%;
  top: 57.6%;
  font-size: clamp(8px, calc(var(--rg-w, 760px) * 0.0139), 11px);
  line-height: 1.5;
  color: var(--rg-muted);
}

/* Zakończenie na tej samej planszy, pod owalem */
body[data-theme="white-linen"] .rg-rsvp .rg-outro-inline,
body[data-theme="white-linen"] .rg-outro-inline {
  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;
}
body[data-theme="white-linen"] .rg-outro-inline .rg-inner {
  position: absolute;
  inset: 0;
  width: 100%;
  max-width: none;
  margin: 0;
  padding: 0;
  text-align: center;
}
body[data-theme="white-linen"] .rg-outro-inline .rg-inner > * {
  position: absolute;
  margin: 0;
}
body[data-theme="white-linen"] .rg-outro-inline .rg-h {
  left: 16.24%;
  width: 67.5%;
  top: 70.9%;
  font-size: clamp(22px, calc(var(--rg-w, 760px) * 0.0656), 50px);
  line-height: 1.05;
  color: var(--rg-outro-ink);
}
body[data-theme="white-linen"] .rg-outro-inline .rg-monogram {
  left: 16.24%;
  width: 67.5%;
  top: 76.3%;
  font-family: var(--rg-script);
  font-size: clamp(22px, calc(var(--rg-w, 760px) * 0.0611), 47px);
  line-height: 1.15;
  color: var(--rg-outro-ink);
}
body[data-theme="white-linen"] .rg-outro-inline .rg-cols {
  left: 16.24%;
  width: 67.5%;
  top: 82.4%;
  display: block;
  text-align: center;
}
body[data-theme="white-linen"] .rg-outro-inline .rg-cols .rg-p {
  display: inline;
  font-size: clamp(9px, calc(var(--rg-w, 760px) * 0.0185), 14px);
  line-height: 1.6;
  color: var(--rg-outro-ink);
  margin: 0;
}
body[data-theme="white-linen"] .rg-outro-inline .rg-cols .rg-p:first-child::after {
  content: " ";
}

/* ── POPRAWKI PO PIERWSZYM POMIARZE ──────────────────────────
   1. Bazowe `.rg-h` jest kursywą, bold i wersalikami (tak wygląda
      w motywie 1). W tym projekcie nagłówki są zwykłym krojem
      „The Seasons" z wielkiej litery: „Hormonogram", „Lokalizacja",
      „Dresscode", „Kilka słów".
   2. Bloki treści muszą leżeć NAD warstwami planszy.
   3. `.rg-dress` i zakończenie dostają `inset: 0` po regule ramki
      płótna, ale zostawało po niej `translate: -50% 0` — cały blok
      odjeżdżał o pół szerokości w lewo (nagłówek „Kilka słów od
      pary" wychodził poza kadr). */
body[data-theme="white-linen"] .rg-h {
  font-style: normal;
  font-weight: 400;
  text-transform: none;
  letter-spacing: .01em;
}
body[data-theme="white-linen"] .rg-screen > .rg-inner,
body[data-theme="white-linen"] .rg-dress,
body[data-theme="white-linen"] .rg-outro-inline {
  z-index: 3;
}
body[data-theme="white-linen"] .rg-dress .rg-inner,
body[data-theme="white-linen"] .rg-outro-inline .rg-inner {
  translate: none;
}
/* Nagłówek harmonogramu ma zostać w jednej linii — w projekcie zajmuje
   78 % szerokości płótna, polskie „Harmonogram" jest odrobinę dłuższe
   od „Hormonogram" z pliku, więc stopień pisma jest nieco niższy. */
body[data-theme="white-linen"] .rg-schedule .rg-h {
  font-size: clamp(26px, calc(var(--rg-w, 760px) * 0.098), 74px);
  white-space: nowrap;
}
/* Kolumna z godziną mieści u nas GODZINĘ I NAZWĘ punktu („15:30 ·
   Przyjazd gości"), a nie samą godzinę jak w pliku — stąd szersza
   niż 34 % i mniejszy stopień pisma, żeby wiersze nie łamały się
   na trzy linie i rozstaw wierszy został z projektu (10,5 % płótna). */
body[data-theme="white-linen"] .rg-schedule .rg-item .txt {
  grid-template-columns: 40% 60%;
}
body[data-theme="white-linen"] .rg-schedule .rg-item .time,
body[data-theme="white-linen"] .rg-schedule .rg-item .desc {
  font-size: clamp(10px, calc(var(--rg-w, 760px) * 0.0245), 19px);
}
body[data-theme="white-linen"] .rg-schedule .rg-timeline {
  gap: calc(var(--rg-w, 760px) * 5 / 3 * 0.083);
}

/* ── DOSTROJENIE PO PORÓWNANIU Z PLANSZAMI ───────────────────
   1. Zaproszenie pod imionami: bazowy `.rg-sub` jest kursywą
      wersalikami; w projekcie to zwykły Now Light, a linia zaczyna
      się dopiero pod „Patrycją" (40,3 % zamiast 38,9 %).
   2. Wiersze harmonogramu mają w projekcie STAŁY rozstaw 10,87 %
      płótna. Przy `gap` liczył się od wysokości wiersza, a ta rośnie,
      gdy nazwa punktu łamie się na dwie linie — przez to wiersze
      rozjeżdżały się względem linii narysowanych na zawieszce.
   3. Mapa (u nas dodatkowa wobec projektu) schodzi niżej na lico
      koperty, żeby zostawić widoczną pieczęć. */
body[data-theme="white-linen"] .rg-date .rg-sub {
  font-style: normal;
  top: 40.3%;
}
body[data-theme="white-linen"] .rg-schedule .rg-timeline {
  top: 30.9%;
  gap: 0;
}
body[data-theme="white-linen"] .rg-schedule .rg-item {
  height: calc(var(--rg-w, 760px) * 5 / 3 * 0.1087);
}
body[data-theme="white-linen"] .rg-schedule .rg-item .txt {
  grid-template-columns: 44% 56%;
}
body[data-theme="white-linen"] .rg-schedule .rg-item .time,
body[data-theme="white-linen"] .rg-schedule .rg-item .desc {
  font-size: clamp(10px, calc(var(--rg-w, 760px) * 0.023), 18px);
}
body[data-theme="white-linen"] .rg-location .rg-map {
  left: 23%;
  width: 54%;
  top: 61.5%;
  height: calc(var(--rg-w, 760px) * 5 / 3 * 0.155);
}

/* ── EKRAN 1 — ODSŁONA (KOPERTA) ─────────────────────────────
   Plansza startowa ma dwa napisy: pisane „You received a message"
   nad kopertą (17,5 % wysokości płótna) i „Dotknij aby otworzyć"
   krojem The Seasons pod nią (61,9 %). U nas był tylko ten drugi —
   drobnymi wersalikami przyklejony do dołu okna, czyli zupełnie
   inaczej niż w projekcie. Oba napisy są elementem GRAFIKI (tak jak
   „Save the date" na ekranie 2), dlatego stoją w CSS, a nie w treści
   zaproszenia. Pozycje liczone od planszy `.plate-stage` (3:5),
   nie od okna — inaczej rozjeżdżałyby się z kopertą. */
body[data-theme="white-linen"] .plate-canvas::before {
  content: "You received a message";
  position: absolute;
  left: 50%;
  translate: -50% 0;
  top: 17.5%;
  width: 92%;
  text-align: center;
  font-family: var(--rg-script);
  font-size: clamp(20px, calc(var(--pl-h, 100svh) * 3 / 5 * 0.0693), 52px);
  line-height: 1.15;
  color: var(--rg-graphite);
  pointer-events: none;
  /* Warstwy planszy wstawia JS DO `.plate-canvas`, więc bez z-index
     napis malowałby się pod papierem tła. */
  z-index: 5;
}
body[data-theme="white-linen"] .plate-cta {
  --pl-h: min(100svh, calc(100vw * 5 / 3));
  bottom: auto;
  top: calc(50% - var(--pl-h) / 2 + var(--pl-h) * 0.619);
  font: 400 clamp(18px, calc(var(--pl-h) * 3 / 5 * 0.0722), 54px) / 1.15 var(--rg-display);
  letter-spacing: .015em;
  text-transform: none;
  color: #262626;
  opacity: .88;
}
@keyframes wl-cta-tetno { 0%, 100% { opacity: .88; } 50% { opacity: .5; } }
body[data-theme="white-linen"] .plate-cta {
  animation: wl-cta-tetno 3.4s ease-in-out infinite;
}

/* ── ODSŁONA: KOPERTA WIĘKSZA ────────────────────────────────
   Plansza odsłony (`.plate-stage`) jest skalowana WYSOKOŚCIĄ okna
   (3:5, `--pl-h: min(100svh, 100vw*5/3)`), więc na typowym, szerokim
   ekranie laptopa ma ok. 630 px przy oknie 1740 px — koperta zajmuje
   w projekcie 59 % planszy, czyli ledwie 21 % szerokości okna i czyta
   się jako mała. Powiększamy samą kopertę (warstwa kluczowa) o 40 %
   względem jej środka; papier tła zostaje bez zmian, bo i tak jest
   pełnoekranowy. Napisy nad i pod kopertą (17,5 % i 61,9 % planszy)
   mieszczą się dalej: po skalowaniu koperta zajmuje 26–58,4 %. */
body[data-theme="white-linen"] .plate-key {
  /* Na telefonie plansza ma szerokość całego ekranu, więc koperta jest
     duża już w proporcji z projektu — tam wystarcza delikatne
     powiększenie. Skala 1,4 dotyczy okien, w których plansza jest
     wyraźnie węższa od okna. */
  scale: 1.12;
}
@media (min-width: 720px) {
  body[data-theme="white-linen"] .plate-key { scale: 1.4; }
}
/* ── ROZKŁADANIE KOPERTY NA CZTERY KLAPY ─────────────────────
   Koperta na planszy zajmuje x 20,667–80,089 %, y 30,505–53,845 %
   (środek 50,378 % / 42,175 %). Linie złożenia zmierzone z grafiki
   (713 × 466 px) i przeliczone na procenty płótna:
     • klapa GÓRNA  — trójkąt sięgający grotu na 50,34 % / 51,24 %;
       obrys biegnie POD koronką (offset +62 px w pliku), żeby cały
       koronkowy brzeg i pieczęć jechały razem z klapą,
     • klapy BOCZNE — groty na 35,50 % i 65,26 % (43,15 %), tam gdzie
       szew od dolnego narożnika spotyka brzeg klapy górnej,
     • klapa DOLNA  — reszta, z wycięciem na grot klapy górnej.

   Powiększenie koperty (`--wl-skala`) nie może iść osobno na obrazek,
   bo przycięcie jest w procentach RAMKI — skalujemy więc całą ramkę
   względem środka koperty, a oś zawiasu przesuwamy parą translate().
   Dzięki temu przycięcie i grafika skalują się razem, a obrót i tak
   dzieje się wokół właściwej krawędzi. */
body[data-theme="white-linen"] .plate-skrz {
  --wl-skala: 1.12;
  --wl-kat: 0deg;
  z-index: 4;
  transform-origin: 50.378% 42.175%;
  transition: transform 1s cubic-bezier(.36, .02, .26, 1),
              opacity .3s linear;
}
@media (min-width: 720px) {
  body[data-theme="white-linen"] .plate-skrz { --wl-skala: 1.4; }
}
/* Klony w ramkach nie mogą dostać powiększenia drugi raz. */
body[data-theme="white-linen"] .plate-skrz .plate-key {
  scale: none;
  transform: none;
  opacity: 1;
}
/* Nakładka gaśnie dopiero, gdy ostatnia klapa jest już rozłożona —
   inaczej koperta znikała w połowie ruchu. */
body[data-theme="white-linen"] .plate-reveal.opening {
  transition: opacity 1s cubic-bezier(.4, 0, .2, 1) 1.15s;
}

body[data-theme="white-linen"] .sk-gora {
  z-index: 7;
  clip-path: polygon(-3.27% 22%, 104.64% 22%, 50.34% 51.24%);
  transform: scale(var(--wl-skala))
             translateY(-11.67%) rotateX(var(--wl-kat)) translateY(11.67%);
}
body[data-theme="white-linen"] .sk-lewo {
  z-index: 6;
  clip-path: polygon(-6% 20.51%, 35.5% 43.15%, -6% 69.69%);
  transform: scale(var(--wl-skala))
             translateX(-29.711%) rotateY(var(--wl-kat)) translateX(29.711%);
}
body[data-theme="white-linen"] .sk-prawo {
  z-index: 6;
  clip-path: polygon(106.76% 20.51%, 65.26% 43.15%, 106.76% 69.69%);
  transform: scale(var(--wl-skala))
             translateX(29.711%) rotateY(var(--wl-kat)) translateX(-29.711%);
}
body[data-theme="white-linen"] .sk-dol {
  z-index: 5;
  clip-path: polygon(35.5% 43.15%, 50.34% 51.24%, 65.26% 43.15%,
                     106.76% 69.69%, 106.76% 86%, -6% 86%, -6% 69.69%);
  transform: scale(var(--wl-skala))
             translateY(11.67%) rotateX(var(--wl-kat)) translateY(-11.67%);
}
/* Kolejność jak przy otwieraniu prawdziwej koperty: najpierw zaklejona
   klapa górna z pieczęcią, potem boki, na końcu spód. */
body[data-theme="white-linen"] .plate-reveal.opening .sk-gora {
  --wl-kat: 152deg;
  opacity: 0;
  transition-delay: 0s, .75s;
}
body[data-theme="white-linen"] .plate-reveal.opening .sk-lewo,
body[data-theme="white-linen"] .plate-reveal.opening .sk-prawo {
  --wl-kat: 152deg;
  opacity: 0;
  transition-delay: .3s, 1.05s;
}
body[data-theme="white-linen"] .plate-reveal.opening .sk-dol {
  --wl-kat: 152deg;
  opacity: 0;
  transition-delay: .46s, 1.21s;
}
/* Napis nad kopertą i wezwanie pod nią schodzą razem z pierwszą klapą. */
body[data-theme="white-linen"] .plate-reveal.opening .plate-canvas::before {
  opacity: 0;
  transition: opacity .5s linear;
}
@media (prefers-reduced-motion: reduce) {
  body[data-theme="white-linen"] .plate-skrz,
  body[data-theme="white-linen"] .plate-reveal.opening .plate-skrz {
    transition: opacity .3s linear;
    transform: scale(var(--wl-skala));
  }
}

/* ── EKRAN 2: TEKST TYLKO W TRZECH JASNYCH POLACH ────────────
   Plansza wyznacza trzy pola do pisania i nic poza nimi nie powinno
   nieść tekstu:
     1) karteczka z koronkowym brzegiem   x 30–88 %, y 20–54 %
     2) koronkowe serce (doily)           x 10–53 %, y 43–66 %
     3) ozdobna etykieta                  x 51–91 %, y 59–79 %
   Data z miejscem jest u nas dłuższa niż „13.09.2005" z projektu,
   więc blok zwęża się do 37 % szerokości płótna i łamie na dwie
   linie — dzięki temu zostaje nad sercem zamiast wychodzić na goły
   papier po prawej. Licznik dostaje szerokość samej etykiety. */
body[data-theme="white-linen"] .rg-date .rg-dateline {
  left: 10%;
  width: 37%;
  top: 51.5%;
}
body[data-theme="white-linen"] .rg-date .rg-count {
  left: 53%;
  width: 37%;
  top: 63.5%;
}

/* Parallaks warstw a pola tekstowe — wykluczają się.
   `.rg-bg img` dostaje z bazy `translate3d(0, --rg-par * --rg-depth)`,
   czyli przy przewijaniu każda warstwa jedzie o własną odległość
   (do 42 px). Tekst stoi nieruchomo w procentach płótna, więc karta,
   serce i etykieta wysuwały się spod niego — na telefonie nawet o 6 %
   wysokości płótna. W motywie, w którym tekst MUSI leżeć w polach
   z grafiki, plansza nie może pływać względem tekstu. Zostaje
   „oddech" (skala) — wspólny dla całej planszy, więc pola i tekst
   zmieniają się razem, i tylko delikatny, żeby ich nie rozsuwał. */
body[data-theme="white-linen"] .rg-bg img {
  transform: none;
}
@keyframes white-linen-oddech {
  0%, 100% { scale: 1; }
  50%      { scale: 1.008; }
}

/* Środek karteczki to 68 % płótna, nie 63,5 %.
   Zmierzone na pliku 02-date/koperta.webp: płaskie, białe pole karty
   (bez koronkowego brzegu) to x 45,4–90,7 %, y 21,1–53,6 % płótna.
   Blok z imionami stał symetrycznie względem PŁÓTNA, a nie względem
   karty, więc długie imię („Aleksandra") dochodziło do koronki po
   lewej, a po prawej zostawał szeroki margines. Teraz oba bloki mają
   oś karty; zdanie zapraszające trzyma się węższej kolumny z projektu
   (x 54,5–81,7 %, oś 68,1 %). */
body[data-theme="white-linen"] .rg-date .rg-names {
  left: 45.4%;
  width: 45.3%;
}
body[data-theme="white-linen"] .rg-date .rg-sub {
  left: 51%;
  width: 34%;
}

/* ── EKRAN 2: DATA W DWÓCH POLACH, LICZNIK NA ŚRODKU ETYKIETY ──
   Na koronkowym sercu (lewa strona) ma stać wyłącznie „Save the date"
   i data — bez nazwy miejsca, bo długa nazwa wychodziła poza koronkę.
   Nazwa miejsca razem z datą trafia na karteczkę, pod zdanie
   zapraszające — tam, gdzie w pliku źródłowym stoi osobna linia
   krojem The Seasons (y 46,4 %).
   `.rg-dateline` nie rysuje już własnego pola: `display: contents`
   oddaje oba kawałki bezpośrednio ramce płótna, więc każdy można
   ustawić w swoim polu. */
body[data-theme="white-linen"] .rg-date .rg-dateline {
  display: contents;
}
body[data-theme="white-linen"] .rg-date .dl-data {
  position: absolute;
  left: 10%;
  width: 37%;
  top: 51.5%;
  margin: 0;
  text-align: center;
  font-family: var(--rg-display);
  font-size: clamp(12px, calc(var(--rg-w, 760px) * 0.0286), 22px);
  line-height: 1.5;
  color: var(--rg-graphite);
}
body[data-theme="white-linen"] .rg-date .dl-data::before {
  content: "Save the date";
  display: block;
  font-family: var(--rg-script);
  font-size: clamp(20px, calc(var(--rg-w, 760px) * 0.0403), 31px);
  line-height: 1.1;
  margin-bottom: .18em;
  color: var(--rg-graphite);
}
body[data-theme="white-linen"] .rg-date .dl-miejsce {
  position: absolute;
  left: 55.5%;
  width: 34.06%;
  top: 70.9%;
  margin: 0;
  text-align: center;
  font-family: var(--rg-display);
  font-size: clamp(11px, calc(var(--rg-w, 760px) * 0.022), 17px);
  line-height: 1.35;
  color: var(--rg-count);
}
/* Poprzednia reguła pozycjonowała cały `.rg-dateline`; teraz pole
   wyznaczają dwa kawałki, więc trzeba ją wyzerować. */
body[data-theme="white-linen"] .rg-date .rg-dateline::before {
  content: none;
}
/* Licznik na ŚRODKU etykiety. Zmierzone pole ozdobnej etykiety
   (02-date/papier.webp, nieprzezroczysta część): x 55,5–89,6 %,
   y 61,9–77,4 % płótna, środek (72,5 %, 69,6 %). Licznik stał
   przy jej górnej krawędzi i pół centymetra w lewo. */
body[data-theme="white-linen"] .rg-date .rg-count {
  left: 55.5%;
  width: 34.06%;
  top: 61.86%;
  height: calc(var(--rg-w, 760px) * 5 / 3 * 0.1549);
  align-items: center;
}
/* Na wąskim ekranie zdanie zapraszające łamie się na trzy linie
   (na komputerze na dwie) i sięgało pod linię z datą. Data schodzi
   wtedy niżej — karta ma na to miejsce do 53,6 % płótna. */
@media (max-width: 560px) {
  body[data-theme="white-linen"] .rg-date .rg-sub { line-height: 1.55; }
}

/* Nagłówek harmonogramu niżej: przy 12,6 % siedział tuż pod górnym
   łukiem zawieszki i optycznie się z nim zlewał. Na 15,6 % ma nad sobą
   spokojny pas papieru, a do pierwszej narysowanej linii (26,7 %)
   zostaje prawie 5 punktów procentowych światła. */
body[data-theme="white-linen"] .rg-schedule .rg-h {
  top: 15.6%;
}

/* Łabędzie niżej — na środek pasa pod tekstem zakończenia.
   Warstwa z rejestru stoi na 87,9–94,2 % płótna, a tekst kończy się
   na 84,4 %: nad łabędziami zostawały 3,5 punktu procentowego, pod
   nimi 5,8 — czytało się to jak zsunięcie do góry. Środek tego pasa
   wypada na 89,5 %. Geometrię warstw wpisuje inline renderer,
   więc jedyną drogą jest `!important`; rejestr zostaje 1:1
   z projektem. */
body[data-theme="white-linen"] #rgRsvp .rg-bg img[src$="06-rsvp/illustracja.webp"] {
  top: 89.5% !important;
}

/* ── EKRAN 4 KRÓTSZY, EKRAN 5 DŁUŻSZY ────────────────────────
   Historia pary kończy się na 85 % płótna (dolna krawędź pogniecionego
   papieru), a sekcja miała pełne 100 % — 15 % wysokości to była pusta
   kartka, przez którą trzeba było przewijać. Skracamy ją do 87 %
   i wygaszamy dolną krawędź planszy, żeby cięcie nie było twarde.
   Odzyskane 13 % płótna (165 px przy oknie 1050) idzie do lokalizacji:
   tam sekcja musi pomieścić list ze zdjęciami, adres, przycisk, mapę
   i cały dress code, i było za ciasno. */
body[data-theme="white-linen"] .rg-story {
  min-height: calc(var(--rg-w, 760px) * 5 / 3 * 0.87);
  overflow: hidden;
}
body[data-theme="white-linen"] .rg-story .rg-bg {
  -webkit-mask-image: linear-gradient(180deg, #000 78%, transparent 87%);
          mask-image: linear-gradient(180deg, #000 78%, transparent 87%);
}
body[data-theme="white-linen"] .rg-location {
  min-height: calc(var(--rg-w, 760px) * 5 / 3 * 1.13);
}
/* Papier planszy kończy się na wysokości płótna, a sekcja jest teraz
   wyższa — ten pas przedłuża go do dołu tym samym plikiem, z miękkim
   przejściem na styku, żeby nie było widać szwu. */
body[data-theme="white-linen"] .rg-location::after {
  content: "";
  position: absolute;
  left: 50%;
  translate: -50% 0;
  top: calc(var(--rg-w, 760px) * 5 / 3 * 0.86);
  bottom: 0;
  width: var(--rg-w, 760px);
  max-width: 100vw;
  background: url("../assets/themes/white-linen/05-location/tlo.webp") center bottom / 100% auto no-repeat;
  -webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 14%);
          mask-image: linear-gradient(180deg, transparent 0%, #000 14%);
  z-index: 0;
  pointer-events: none;
}
/* Dress code schodzi w odzyskane miejsce — w projekcie leży na gołym
   papierze pod kopertą, więc niżej wygląda tak samo, a przestaje się
   tłoczyć z mapą. */
body[data-theme="white-linen"] .rg-dress .rg-h { top: 84.5%; }
body[data-theme="white-linen"] .rg-dress-grid  { top: 94%; }
body[data-theme="white-linen"] .rg-dress .rg-p { top: 100.6%; }

/* Dress code jeszcze niżej — po podniesieniu sekcji zostawał pod nim
   pas pustego papieru i przerwa do RSVP czytała się jak dziura.
   Opis kończy się teraz na ~111 % płótna, a sekcja ma 113 %, więc do
   następnej planszy zostaje tylko styk (sekcje i tak zachodzą na
   siebie o 7vw). */
body[data-theme="white-linen"] .rg-dress .rg-h { top: 91.5%; }
body[data-theme="white-linen"] .rg-dress-grid  { top: 101%; }
body[data-theme="white-linen"] .rg-dress .rg-p { top: 107.6%; }

/* ── HISTORIA PARY WYŻEJ ─────────────────────────────────────
   Nad nagłówkiem zostawał pusty pas papieru: nagłówek startował na
   10 % płótna, a medalion dopiero na 19 %. Cały kolaż (medalion,
   wstążka, pognieciony papier) jedzie w górę o 6 punktów
   procentowych — razem, jednym przesunięciem w jednostkach płótna,
   więc wzajemnie się nie rozjeżdżają. Papier tła zostaje na miejscu,
   bo wypełnia całą sekcję. Sekcja skraca się o tyle samo, żeby dołem
   nie urosła pustka. */
/* UWAGA: nie przez `translate` — bazowe warstwy `.rg-bg img` mają
   animację dryfu (`rg-drift-a/b/c`), która animuje właśnie `translate`,
   więc statyczne przesunięcie było przez nią nadpisywane (z 6 punktów
   procentowych zostawało 1,2). Pozycję zmieniamy więc na `top`
   warstwy — to jest ta sama wielkość, którą wpisuje inline renderer,
   stąd `!important`. */
/* Podpórki `top: … !important` dla warstw historii usunięte — warstwy
   mają teraz właściwe pozycje wprost z rejestru (patrz koniec pliku). */
body[data-theme="white-linen"] .rg-story .rg-h { top: 4.5%; }
body[data-theme="white-linen"] .rg-story .rg-cols { top: 53.4%; }
body[data-theme="white-linen"] .rg-story {
  /* Treść kończy się teraz na 76 % płótna (dolna krawędź papieru),
     więc sekcja ma 78 % — nad nagłówkiem 4,5 %, pod papierem 2 %. */
  min-height: calc(var(--rg-w, 760px) * 5 / 3 * 0.78);
}
body[data-theme="white-linen"] .rg-story .rg-bg {
  -webkit-mask-image: linear-gradient(180deg, #000 69%, transparent 78%);
          mask-image: linear-gradient(180deg, #000 69%, transparent 78%);
}

/* Dryf warstw wyłączony w całym motywie — z tego samego powodu, dla
   którego zniknął parallaks: tekst stoi w polach wyznaczonych przez
   grafikę (karta, serce, etykieta, papier historii), a każda warstwa
   dryfowała osobno o 1–2 punkty procentowe, więc pola uciekały spod
   liter. Ruch zostaje tam, gdzie nie niesie tekstu: kwiaty i anioł
   dalej się unoszą, a cała plansza „oddycha". */
body[data-theme="white-linen"] .rg-bg img[data-drift] {
  animation: none;
}
body[data-theme="white-linen"] .rg-bg img[src$="kwiatek.webp"],
body[data-theme="white-linen"] .rg-bg img[src$="kwiatek_1.webp"],
body[data-theme="white-linen"] .rg-bg img[src$="kwiatek_2.webp"],
body[data-theme="white-linen"] .rg-bg img[src$="aniol.webp"] {
  animation: wl-unos 13s ease-in-out infinite;
}
body[data-theme="white-linen"] .rg-bg img[src$="kwiatek.webp"]:nth-of-type(2n) {
  animation-delay: -4.3s;
}
@media (prefers-reduced-motion: reduce) {
  body[data-theme="white-linen"] .rg-bg img { animation: none !important; }
}

/* Mapa („pływająca karta") schodzi pod kopertę — między nią a słowem
   „Dress code" wisiał pusty pas 14,5 punktu procentowego. Teraz karta
   wysuwa się z koperty w dół i kończy 2 punkty nad nagłówkiem dress
   code'u (74–89,5 % płótna). */
body[data-theme="white-linen"] .rg-location .rg-map {
  top: 74%;
}

/* Tekst historii pionowo na ŚRODKU pogniecionego papieru.
   Blok stał na sztywnej pozycji tuż pod górną krawędzią kartki
   (53,4 % przy papierze 51,5–76 %), więc pod spodem zostawało dwa razy
   więcej miejsca niż nad. Teraz zajmuje całą wysokość kartki
   i wyśrodkowuje się w niej — działa też, gdy tekst pary jest dłuższy
   albo krótszy niż przykładowy. */
body[data-theme="white-linen"] .rg-story .rg-cols {
  top: 51.5%;
  height: calc(var(--rg-w, 760px) * 5 / 3 * 0.245);
  align-content: center;
}

/* ── EKRAN 2: KARTA BEZ DATY, MIEJSCE POD LICZNIKIEM ─────────
   Na karteczce zostają tylko imiona i zdanie zapraszające — data
   i nazwa miejsca z niej znikają. Data jest już na koronkowym sercu,
   a nazwa miejsca schodzi na ozdobną etykietę, pod licznik. Licznik
   przesuwa się przez to w górę pola etykiety (61,9–77,4 %), żeby oba
   napisy stały razem, wyśrodkowane w niej jako jedna grupa. */
body[data-theme="white-linen"] .rg-date .rg-count {
  top: 64.2%;
  height: auto;
  align-items: flex-start;
}

/* ── RSVP: wszystko WEWNĄTRZ owalu ───────────────────────────
   Owal z planszy to elipsa (x 15,8–86 %, y 8,9–66 % płótna), więc im
   niżej, tym węższe pole: na wysokości zdania pod przyciskiem ma już
   tylko ~50 % szerokości płótna, a zdanie szło przez 60 % — wychodziło
   poza kreskę. Cały blok pod pytaniem podjeżdża więc wyżej, a zdanie
   dostaje szerokość policzoną z równania elipsy dla swojej wysokości
   (na 57,4 % pole ma x 25,8–76 %). */
body[data-theme="white-linen"] .rg-rsvp .rg-msg-label { top: 39.8%; }
body[data-theme="white-linen"] .rg-rsvp .rg-textarea  { top: 42.3%; }
body[data-theme="white-linen"] .rg-rsvp .rg-btn       { top: 49.8%; }
body[data-theme="white-linen"] .rg-rsvp .rg-note {
  left: 27%;
  width: 46%;
  top: 55.8%;
  font-size: clamp(8px, calc(var(--rg-w, 760px) * 0.0132), 10.5px);
  line-height: 1.45;
}

/* ══════════════════════════════════════════════════════════════════
   WYRÓWNANIE DO PLANSZ — jedno miejsce, na końcu pliku
   ══════════════════════════════════════════════════════════════════
   Warstwy graficzne dostały w js/app.js współrzędne liczone 1:1
   z plansz „svg osobne plansze z tekstem" (każda 900×1500). Poprzednie
   były przesunięte o 0,6–1,7 punktu procentowego — różnie na każdym
   ekranie — a teksty były do nich dostrojone na oko. Po poprawieniu
   warstw trzeba było więc przestawić i teksty, tym razem na POLA
   TEKSTOWE z plików (prostokąty, które projektant zostawił pod napisy).

   Reguły stoją na końcu, bo wyżej w tym pliku ta sama własność bywa
   ustawiana po dwa–trzy razy (historia dostrajania) i przy równej
   specyficzności decyduje kolejność. */

/* ── EKRAN 3 — HARMONOGRAM ─────────────────────────────────────
   Nagłówek: pole 6,84–90,78 %, y 14,39 %.

   LINIE NA PAPIERZE. Poprzednie wartości (32,68 / 43,53 / 53,30 /
   64,02 %, odstęp 10,447) zakładały CZTERY linie. Pomiar pikseli pliku
   03-schedule/papier_z_kokardka.webp (768×1350) pokazuje PIĘĆ kreskowanych
   linii, w osiach y = 368,5 / 514 / 661 / 807 / 953,5 px, czyli
   27,30 / 38,07 / 48,96 / 59,78 / 70,63 % wysokości papieru.

   Papier leży na kadrze od 4,41 % i ma 90,93 % jego wysokości, więc
   w układzie kadru linie wypadają na:

       29,23 / 39,02 / 48,93 / 58,77 / 68,63 %      (krok ≈ 9,85)

   Dlatego tekst nigdy nie siadał na kreskach: zły był i punkt startu,
   i odstęp, i liczba linii.

   Wiersz ma KOŃCZYĆ się na swojej linii — tak się pisze na linii.
   Pierwszy wiersz zaczyna się więc o jeden krok nad pierwszą kreską:
   29,23 − 9,85 = 19,38 %. Przy równym kroku 9,85 % wszystkie pięć
   trafia z błędem najwyżej 0,06 pkt proc., czyli pół piksela. */
body[data-theme="white-linen"] .rg-schedule .rg-h { top: 14.39%; }
body[data-theme="white-linen"] .rg-schedule .rg-timeline {
  top: 19.38%;
  gap: 0;
  /* Kreski biegną od 16,77 % do 80,68 % szerokości kadru — tekst
     zaczyna się dokładnie tam, gdzie zaczyna się linia. */
  left: 16.77%;
  width: 63.91%;
}
body[data-theme="white-linen"] .rg-schedule .rg-item {
  height: calc(var(--rg-w, 760px) * 5 / 3 * 0.0985);
  /* Tekst dosunięty do dołu wiersza, czyli tuż nad kreskę. Odstęp
     1,15 % kadru to prześwit, dzięki któremu ogonki liter (g, j, y)
     nie siadają na linii. */
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  /* align-items: stretch jest tu konieczne. Wyżej w pliku wiersz dostaje
     align-items: center — przy display:block nie znaczyło to nic, ale
     w kolumnie flex ścisnęło tekst do jego własnej szerokości i ustawiło
     na środku. Efekt: kolumna godziny zwężała się do ~30 px i „15:00"
     łamało się na dwie linie. */
  align-items: stretch;
  padding-bottom: calc(var(--rg-w, 760px) * 5 / 3 * 0.0115);
  box-sizing: border-box;
}
/* Godzina nigdy się nie łamie — to jedna liczba, nie zdanie. */
body[data-theme="white-linen"] .rg-schedule .rg-item .godz { white-space: nowrap; }

/* ── EKRAN 4 — HISTORIA PARY ───────────────────────────────────
   Warstwy wracają na pozycje z planszy, więc znikają podpórki
   `top: … !important`, którymi podciągano je wcześniej w górę.
   Nagłówek: pole y 11,25 %. Tekst: dwie kolumny w polu 65,35–75,75 %,
   czyli pionowo na środku pogniecionego papieru (58,46–82,74 %). */
body[data-theme="white-linen"] .rg-story .rg-h { top: 11.25%; }
body[data-theme="white-linen"] .rg-story .rg-cols {
  top: 58.464%;
  height: calc(var(--rg-w, 760px) * 5 / 3 * 0.24279);
  align-content: center;
}
/* Papier kończy się na 82,74 % — sekcja ma 86 %, reszta planszy to
   pusta kartka, przez którą trzeba by przewijać. */
body[data-theme="white-linen"] .rg-story {
  min-height: calc(var(--rg-w, 760px) * 5 / 3 * 0.86);
}
body[data-theme="white-linen"] .rg-story .rg-bg {
  -webkit-mask-image: linear-gradient(180deg, #000 78%, transparent 86%);
          mask-image: linear-gradient(180deg, #000 78%, transparent 86%);
}

/* ── EKRAN 5 — LOKALIZACJA I DRESS CODE ────────────────────────
   Pola z planszy: nagłówek 5,34 %, adres 32,48–68,04 % / 41,73 %,
   przycisk 40,20–60,53 % / 48,94 %, „Dresscode" 76,67 %,
   cztery próbki 84,86 % (11,02 × 3,46 %, x 21,46 / 37,39 / 52,66 /
   68,43 %), opis 91,21 %. */
body[data-theme="white-linen"] .rg-location { min-height: calc(var(--rg-w, 760px) * 5 / 3); }
body[data-theme="white-linen"] .rg-location::after { content: none; }
body[data-theme="white-linen"] .rg-location .rg-h { top: 5.34%; }
body[data-theme="white-linen"] .rg-location .rg-addr { left: 32.48%; width: 35.56%; top: 41.73%; }
body[data-theme="white-linen"] .rg-location .rg-btn { left: 40.2%; width: 20.33%; top: 48.94%; }
body[data-theme="white-linen"] .rg-dress .rg-h { top: 76.67%; }
body[data-theme="white-linen"] .rg-dress-grid  { top: 84.86%; }
body[data-theme="white-linen"] .rg-dress .rg-p { top: 91.21%; }
/* MAPA. W plikach tego motywu jej nie ma (folder „5 ekran lokalizacja
   i dresscode" to koperta, dwa serduszka, dwie koronki i kwiatek), a na
   planszy nie ma dla niej wolnego pola: karta z adresem kończy się na
   56 %, koperta na 74,6 %, a „Dresscode" zaczyna na 76,67 %. Kładziemy
   ją więc NA LICU KOPERTY — czyta się jak karta wsunięta do środka.
   Zasłania lakową pieczęć (57,4–65,4 % planszy); jeśli pieczęć ma
   zostać widoczna, mapa musi zejść pod opis dress code'u. */
body[data-theme="white-linen"] .rg-location .rg-map {
  left: 19%;
  width: 60%;
  top: 56.5%;
  height: auto;
  aspect-ratio: 1.95;                /* 60 % szerokości płótna × 18,5 % jego wysokości */
  margin: 0;
}

/* ── EKRAN 6 — RSVP I ZAKOŃCZENIE ──────────────────────────────
   Pola z planszy: RSVP 17,68 %, pytanie 24,52 %, „Wiadomość dla pary"
   41,31 %, okno wiadomości 43,43 %, przycisk 51,60 %,
   „Kilka słów" 70,39 %, opis 76,32 %. */
body[data-theme="white-linen"] .rg-rsvp > .rg-inner .rg-h { top: 17.68%; }
body[data-theme="white-linen"] .rg-rsvp .rg-q { top: 24.52%; }
body[data-theme="white-linen"] .rg-rsvp .rg-msg-label { top: 41.31%; }
body[data-theme="white-linen"] .rg-rsvp .rg-textarea  { top: 43.43%; }
body[data-theme="white-linen"] .rg-rsvp .rg-btn       { top: 51.6%; }
body[data-theme="white-linen"] .rg-rsvp .rg-note      { top: 56.3%; }
/* Zakończenie („Kilka słów od pary") leży na tej samej planszy —
   własne pola: nagłówek 70,39 %, opis 76,32 %. */
body[data-theme="white-linen"] .rg-outro-inline .rg-h { top: 70.39%; }
body[data-theme="white-linen"] .rg-outro-inline .rg-cols { top: 76.32%; }

/* ── EKRAN 2 — DATA I OSOBY ────────────────────────────────────
   Pola z planszy: napis „Save the date" na koronkowym sercu 52,85 %,
   data pod nim 56,60 %, licznik na etykiecie 65,09 %. */
body[data-theme="white-linen"] .rg-date .dl-data { top: 52.85%; }
body[data-theme="white-linen"] .rg-date .rg-count { top: 65.09%; }

/* ── EKRAN 3: WIERSZ PROGRAMU JAK NA PLANSZY ────────────
   Na planszy wiersz ma DWIE kolumny: w lewej sama godzina („13:00 p.m.",
   x 17,56–30 % kadru), w prawej opis (x 40,11–71,89 %). U nas w lewej
   kolumnie lądowała godzina RAZEM z nazwą punktu — czyli dwa i pół raza
   więcej tekstu na tej samej szerokości — więc nazwa łamała się na dwa,
   trzy wiersze i schodziła na kreski sąsiednich punktów.

   Renderer rozdziela je teraz na `span.godz` i `span.nazwa` (kropka
   rozdzielająca wraca z CSS, więc pozostałe motywy wyglądają jak
   przedtem). Tutaj `display: contents` wpuszcza oba do siatki: godzina
   w lewej kolumnie, nazwa i opis jeden pod drugim w prawej. */
body[data-theme="white-linen"] .rg-schedule .rg-item .txt {
  display: grid;
  grid-template-columns: 26% 74%;
  align-items: baseline;
  column-gap: 0;
  row-gap: 0.18em;
}
body[data-theme="white-linen"] .rg-schedule .rg-item .time { display: contents; }
body[data-theme="white-linen"] .rg-schedule .rg-item .godz  { grid-column: 1; }
body[data-theme="white-linen"] .rg-schedule .rg-item .nazwa { grid-column: 2; }
body[data-theme="white-linen"] .rg-schedule .rg-item .desc  { grid-column: 2; }
/* Kolumny same rozdzielają godzinę od nazwy — kropka jest tu zbędna. */
body[data-theme="white-linen"] .rg-schedule .rg-item .nazwa::before { content: none; }
/* Stopień pisma z planszy: tusz wiersza ma tam 26 px na kadrze 900 px,
   czyli 2,9 % jego szerokości. Opis — nasz dodatek, na planszy go nie
   ma — schodzi o stopień niżej i jest stłumiony kolorem. */
body[data-theme="white-linen"] .rg-schedule .rg-item .godz,
body[data-theme="white-linen"] .rg-schedule .rg-item .nazwa {
  font-size: clamp(11px, calc(var(--rg-w, 760px) * 0.029), 22px);
  line-height: 1.2;
}
body[data-theme="white-linen"] .rg-schedule .rg-item .desc {
  font-size: clamp(9px, calc(var(--rg-w, 760px) * 0.0235), 18px);
  line-height: 1.3;
  color: color-mix(in srgb, var(--rg-body) 74%, transparent);
}
body[data-theme="white-linen"] .rg-schedule .rg-item .nazwa,
body[data-theme="white-linen"] .rg-schedule .rg-item .desc { text-wrap: pretty; }

/* ŚCIEŚNIANIE WIERSZY USUNIĘTE.
   Stały tu dwie reguły, które przy pięciu i sześciu punktach zmniejszały
   wysokość wiersza (0,09 i 0,075 zamiast rozstawu z planszy). Leczyły
   objaw: przy błędnym rozstawie 10,447 % piąty punkt rzeczywiście
   lądował na kokardce. Ale ceną było to, że przy pięciu punktach —
   czyli dokładnie tylu, ile jest linii — ŻADEN wiersz nie trafiał na
   swoją kreskę.

   Przy poprawnym rozstawie 9,85 % pięć punktów siada na pięciu liniach
   i nic nie wchodzi na wstążkę: ostatni wiersz kończy się na 68,63 %,
   a papier jest pełnej szerokości do 79,15 % kadru (dalej zaczyna się
   kokardka).

   SZEŚĆ PUNKTÓW: na planszy były cztery linie opisane w CSS i pięć
   narysowanych, a kreator pozwala dodać sześć punktów. Do grafiki
   doszła więc SZÓSTA kreska, w osi y = 1100 px pliku (81,52 % papieru,
   78,54 % kadru) — ten sam krok 146,25 px co pozostałe. Tusz jest
   przeniesiony z piątej kreski piksel w piksel: ten sam wzór 12/2,
   ten sam kolor, ta sama grubość. Pod kokardką kreska się urywa,
   bo wstążka leży NA papierze — maska wycięta z samej grafiki
   (satyna odróżniona od papieru po lokalnym odchyleniu jasności).
   Oryginał z pięcioma liniami leży w _to_delete/grafika-oryginaly/. */

/* ── 12.10 — EKRAN 5: drugi kwiatek z planszy ──────────────────
   Mały kwiatek to teraz osobny plik (kwiatek_maly.webp, wycięty z planszy
   i odbity jak na niej). Unosi się tak jak duży, z przesuniętą fazą,
   żeby oba nie szły równym krokiem. */
body[data-theme="white-linen"] .rg-bg img[src$="kwiatek_maly.webp"] {
  animation: wl-unos 13s ease-in-out infinite;
  animation-delay: -4.3s;
}
@media (prefers-reduced-motion: reduce) {
  body[data-theme="white-linen"] .rg-bg img[src$="kwiatek_maly.webp"] { animation: none !important; }
}

/* ── 12.10 — EKRAN 5: KARTA Z MAPĄ NA LIŚCIE, MIĘDZY SERCAMI A ADRESEM ──
   Na planszy mapy nie ma. Najpierw leżała na licu koperty (zasłaniała
   pieczęć), potem pod kopertą (odklejona od reszty). Teraz jest częścią
   listu: serca → karta z mapą → adres → „Dojazd" → koperta.

   Żeby się zmieściła, list jest dłuższy o 15 % płótna (kopert_dlugi.webp,
   patrz app.js) — koperta, kwiatki i wszystko pod nimi zjeżdżają o tyle
   samo, a serca zostają jak na planszy. Mapa, adres i przycisk stoją
   w jednej kolumnie (flex) wyśrodkowanej między czubkiem lewego serca
   (36,51 %, policzone z macierzy planszy) a brzegiem koperty. Adres w dwóch
   wierszach (telefon) czy w jednym (komputer) — odstępy zostają te same.

   Pod kopertą sekcja rośnie o te 15 % (--wl-rozsuw): .rg-bg ma stałą
   wysokość płótna (inaczej warstwy w % rozciągnęłyby się z sekcją),
   dress code schodzi o rozsuw, a od dolnej krawędzi koperty w dół leży
   kopia tła przesunięta o rozsuw (::after, ten sam plik). */
body[data-theme="white-linen"] .rg-location {
  --wl-1p: calc(var(--rg-w, 760px) * 5 / 3 / 100);
  --wl-rozsuw: calc(var(--wl-1p) * 14.991);
  min-height: calc(var(--wl-1p) * 100 + var(--wl-rozsuw));
}
body[data-theme="white-linen"] .rg-location > .rg-bg {
  height: calc(var(--wl-1p) * 100);
}
body[data-theme="white-linen"] .rg-location::after {
  content: "";
  position: absolute;
  left: 50%;
  translate: -50% 0;
  width: var(--rg-w, 760px);
  max-width: 100vw;
  /* od dolnej krawędzi koperty: 13,107 + 76,580 = 89,69 % */
  top: calc(var(--wl-1p) * 89.69);
  height: calc(var(--wl-1p) * 10.31 + var(--wl-rozsuw));
  background: url("../assets/themes/white-linen/05-location/tlo.webp") center bottom / 100% auto no-repeat;
  -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 calc(var(--rg-w, 760px) * 0.03));
          mask-image: linear-gradient(180deg, transparent 0, #000 calc(var(--rg-w, 760px) * 0.03));
  z-index: 0;
  pointer-events: none;
}
body[data-theme="white-linen"] .rg-dress {
  top: var(--wl-rozsuw);
}
/* Kolumna wyśrodkowana w pionie w pasie listu od czubka lewego serca
   (36,51 %) do górnej krawędzi koperty (66,83 % — wiersz 860 wydłużonego
   pliku). Na komputerze adres ma jeden wiersz, na telefonie dwa — luz
   rozkłada się wtedy po równo nad mapą i pod przyciskiem, zamiast
   zbierać się w jednym miejscu. */
body[data-theme="white-linen"] .rg-location > .rg-inner > .rg-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding-top: calc(var(--wl-1p) * 36.51);
  padding-bottom: calc(var(--wl-1p) * (100 - 66.83));
}
/* Kolejność w HTML to mapa, adres, przycisk — tu akurat ta sama, ale
   ustawiona jawnie, bo zależy od niej cały rytm listu. */
body[data-theme="white-linen"] .rg-location .rg-card > .rg-map {
  order: 1;
  position: relative;
  display: block;
  left: auto; top: auto;
  /* x 29–71 % kadru: w obrębie listu, z daleka od kwiatków po prawej */
  width: calc(var(--rg-w, 760px) * 0.42);
  height: calc(var(--rg-w, 760px) * 0.42 * 9 / 16);
  aspect-ratio: auto;
  flex: none;
  margin: 0;
  border: clamp(4px, calc(var(--rg-w, 760px) * 0.009), 7px) solid #FFFFFF;
  border-radius: 2px;
  box-shadow: 0 8px 22px rgba(60, 60, 70, .13);
  background: #F3F2EE;
  opacity: 1;
}
body[data-theme="white-linen"] .rg-location .rg-card > .rg-addr {
  order: 2;
  position: relative;
  left: auto; top: auto;
  /* Szerzej niż kolumna z planszy (35,6 %) — list ma 63 %, a w węższej
     kolumnie adres łamał się na telefonie na trzy wiersze. */
  width: 50%;
  flex: none;
  margin: calc(var(--wl-1p) * 1.8) 0 0;
}
body[data-theme="white-linen"] .rg-location .rg-card > .rg-btn {
  order: 3;
  position: relative;
  left: auto; top: auto;
  flex: none;
  margin: calc(var(--wl-1p) * 1.2) 0 0;
}

/* ── 12.10 — EKRAN 5: opis dress code'u na telefonie ───────────
   Wąska kolumna z planszy (42 % kadru) przy minimalnym rozmiarze pisma
   łamała opis na 4–5 wierszy i ostatnie wychodziły poza planszę, pod
   następną sekcję (przy 390 px dół opisu 657 px na 650 px planszy,
   przy 320 px 567 na 533). Na telefonie kolumna jest szersza — pod
   próbkami nie ma nic, co by jej przeszkadzało — i opis mieści się
   w 2–3 wierszach nad dolną krawędzią planszy. */
@media (max-width: 560px) {
  body[data-theme="white-linen"] .rg-dress .rg-p {
    left: 10%;
    width: 80%;
    line-height: 1.5;
  }
}

/* 13.10 — EKRAN 6: ZDANIE POD „WYŚLIJ RSVP" W DWÓCH LINIJKACH
   Na szerokim ekranie zdanie mieściło się w 46 % szerokości płótna
   w jednej linijce (28,6–71,5 %) i oba końce dotykały kreski owalu,
   który na tej wysokości zwęża się już do ~26–76 %. Pole jest teraz
   węższe od całego zdania, więc zawsze łamie się na dwie linijki,
   a text-wrap: balance wyrównuje je do podobnej długości. Szerokość
   ma podłogę 18,5em — przy minimalnej czcionce 8 px na telefonie zdanie
   nadal dzieli się na dwie, a nie na trzy linijki. To samo pole dostają
   komunikaty po wysłaniu formularza (komunikat() w zaproszenie.html). */
body[data-theme="white-linen"] .rg-rsvp .rg-note {
  --wl-notka: max(calc(var(--rg-w, 760px) * 0.34), 18.5em);
  left: calc(50% - var(--wl-notka) / 2);
  width: var(--wl-notka);
  white-space: normal;
  text-wrap: balance;
}
/* Poniżej 360 px nawet przy 8 px pierwsza linijka (28,3–71,8 %) szła
   o włos od kreski owalu (na tej wysokości ~27,3–72,9 %). Pół piksela
   mniej daje ~2,5 punktu zapasu z każdej strony, nadal dwie linijki. */
@media (max-width: 359px) {
  body[data-theme="white-linen"] .rg-rsvp .rg-note { font-size: 7.5px; }
}
/* Telefon i wąski tablet: czcionka ma podłogę 8 px, więc względem
   płótna zdanie jest tu prawie dwa razy szersze niż na komputerze,
   a owal pod przyciskiem zwęża się szybko (56 %: 28–72 %, 58 %: 31–69 %,
   60 %: 34–66 %). Cały dolny blok — „Wiadomość dla pary", okno,
   przycisk i zdanie — podjeżdża o ~1,8 punktu (miejsce jest pod „Niestety,
   nie"), dzięki czemu obie linijki zdania stoją tam, gdzie owal jest
   jeszcze szeroki. Komputer zostaje dokładnie na polach z planszy. */
@media (max-width: 759px) {
  body[data-theme="white-linen"] .rg-rsvp .rg-msg-label { top: 38.9%; }
  /* Napis ma na telefonie stałe ~18 px wysokości, a 2 % płótna przy
     320 px to tylko 11 px — okno wchodziło na „Wiadomość dla pary".
     Okno stoi więc co najmniej 21 px pod górą napisu. */
  body[data-theme="white-linen"] .rg-rsvp .rg-textarea  { top: max(41.4%, calc(38.9% + 21px)); }
  body[data-theme="white-linen"] .rg-rsvp .rg-btn       { top: 49.7%; }
  body[data-theme="white-linen"] .rg-rsvp .rg-note      { top: 54.1%; line-height: 1.4; }
}

/* 13.10 — ZAKOŃCZENIE: IMIONA PARY NACHODZIŁY NA OPIS
   Blok „wyrównania do plansz" postawił opis na 76,32 %, ale na tej
   samej wysokości stoi monogram z imionami (76,3 %), więc „Robert &
   Patrycja" leżało na tekście — na każdej szerokości. Na planszy
   „6 ekran.svg" kolejność jest: „Kilka słów" (linia bazowa 73,6 %),
   linijka pisana (79,8 %), opis (83,6 %). Opis wraca więc pod imiona,
   a odstęp między linijkami liczy się z czcionki opisu, nie z 16 px
   kontenera (stąd brały się na telefonie ~25 px przerwy). */
body[data-theme="white-linen"] .rg-outro-inline .rg-cols {
  top: 81.2%;
  font-size: clamp(9px, calc(var(--rg-w, 760px) * 0.0185), 14px);
  line-height: 1.6;
}
/* Poniżej 360 px opis łamał się na cztery linijki i schodził na łabędzie
   (89,5 %) — tu, poza owalem, może być szerszy, wtedy mieści się w trzech. */
@media (max-width: 359px) {
  body[data-theme="white-linen"] .rg-outro-inline .rg-cols { left: 10%; width: 80%; top: 81.6%; }
}

/* 13.10 — ZAKOŃCZENIE: OPIS ZAWSZE NA ŚRODKU SWOJEGO MIEJSCA
   Opis był przypięty górą (81,2 %), więc krótki tekst wisiał tuż pod
   imionami z pustką nad łabędziami, a długi schodził na łabędzie.
   Miejsce na opis to pas między dołem imion (~80,8 %) a górą łabędzi
   (89,5 %) — środek pasa to ~85,1 %. Blok stoi teraz środkiem na tej
   linii (translate -50 % liczy się z jego własnej wysokości), więc
   jedna linijka, trzy czy pięć — zawsze jest pośrodku. `translate`
   to osobna właściwość, nie gryzie się z animacją wejścia (transform). */
body[data-theme="white-linen"] .rg-outro-inline .rg-cols {
  top: 85.1%;
  translate: 0 -50%;
}
@media (max-width: 359px) {
  body[data-theme="white-linen"] .rg-outro-inline .rg-cols { top: 85.1%; }
}
/* Telefon: opis ma podłogę 9 px, więc względem płótna jest dużo większy
   niż na komputerze, a pas między imionami a łabędziami (8,7 % płótna)
   to przy 320 px tylko 46 px — domyślny tekst ledwo się mieścił,
   dłuższy wchodził na imiona i łabędzie. Pas jest tu więc większy:
   nagłówek i imiona podjeżdżają o ~1,8 pkt (pod owalem jest zapas),
   łabędzie zjeżdżają o 2,1 pkt (do 97,7 % — nadal w sekcji), a opis
   jest szerszy (poza owalem nic go nie ogranicza). Pas: ~79,2–91,6 %,
   środek 85,4 %. */
@media (max-width: 759px) {
  body[data-theme="white-linen"] .rg-outro-inline .rg-h        { top: 68.6%; }
  body[data-theme="white-linen"] .rg-outro-inline .rg-monogram { top: 74.4%; }
  body[data-theme="white-linen"] .rg-outro-inline .rg-cols     { left: 8%; width: 84%; top: 85.4%; }
  body[data-theme="white-linen"] #rgRsvp .rg-bg img[src$="06-rsvp/illustracja.webp"] { top: 91.6% !important; }
}
