/* ==========================================================================
   AerialParadise — klub akrobatyki powietrznej, Wrocław
   Minimalistyczny arkusz stylów: dominuje biel, akcentem jest niebieski
   pobrany bezpośrednio z logo (#107EBF) i błękit (#B7DCF5).

   01. Tokeny            06. Nagłówek i nawigacja   11. Lokalizacje
   02. Reset i podstawy  07. Hero                   12. Opinie
   03. Układ i sekcje    08. Ramki na zdjęcia       13. Pasek kontaktowy
   04. Typografia        09. Bloki zajęć            14. Formularz
   05. Przyciski         10. Kadra                  15. Stopka
                                                    16. Znaczniki i narzędzia
                                                    17. Ruch
   ========================================================================== */

/* == 01. TOKENY ========================================================== */

:root {
  /* ---- Podróż od nieba do głębiny ------------------------------------
     Każda sekcja bierze wycinek gradientu: kolor końcowy jednej jest
     kolorem początkowym następnej, więc zejście pod wodę jest ciągłe.   */
  --niebo-1: #EAF7FE;      /* najwyżej — jasne niebo */
  --niebo-2: #CDEAFB;
  --niebo-3: #A8DCF4;      /* mgiełka nad wodą */
  --niebo-4: #93D3F0;      /* przystanek dla sekcji „Kolonie i urodziny" */
  --powierzchnia: #7FCBEC; /* laguna tuż pod taflą */
  --woda-1: #0F5D8E;       /* zanurzenie */
  --woda-2: #0B4D77;
  --woda-3: #083D5F;
  --glebia-1: #062F49;
  --glebia-2: #042236;
  --otchlan: #031829;      /* najniżej */

  /* Barwy marki — próbkowane z logo */
  --white: #FFFFFF;
  --brand: #107EBF;
  --brand-600: #0C6FA8;
  --brand-700: #0A5D90;
  --sky: #B7DCF5;
  --gwiazdka: #F2B93C;     /* ocena — jedyny ciepły akcent, echo słońca w hero */

  /* Tekst */
  --ink: #06304A;          /* nagłówki w strefie jasnej */
  --ink-2: #0F4A6B;        /* tekst pomocniczy w strefie jasnej */
  --ink-deep: #052235;     /* strefa zanurzenia — ciemniejszy, bo tło ciemnieje */
  --on-deep: #D8ECF8;      /* tekst pomocniczy pod wodą */

  --danger: #B3261E;
  --ok: #146C43;

  /* Powierzchnie — nadpisywane przez klasy stref */
  --heading: var(--ink);
  --on-surface: var(--ink);
  --muted: var(--ink-2);
  --accent: var(--brand-700);
  --rule: rgba(6, 48, 74, 0.18);
  --focus: var(--brand-700);
  --karta: rgba(255, 255, 255, 0.62);        /* szkło: karty, pola, kadry */
  --karta-obrys: rgba(255, 255, 255, 0.85);
  --karta-mocna: rgba(255, 255, 255, 0.9);

  /* Typografia */
  --font-display: "Fraunces", "Iowan Old Style", "Palatino Linotype", Georgia, serif;
  --font-body: "Figtree", system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;

  --step-0: 1rem;
  --step-1: 1.0625rem;
  --step-2: clamp(1.25rem, 0.5vw + 1.1rem, 1.375rem);
  --step-3: clamp(1.375rem, 1vw + 1.15rem, 1.75rem);
  --step-4: clamp(1.75rem, 2.8vw + 1rem, 2.75rem);
  --step-5: clamp(2.25rem, 5.4vw + 0.8rem, 4.5rem);

  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-7: 3rem;
  --space-8: 4rem;

  --container: 72rem;
  --gutter: clamp(1.25rem, 5vw, 3rem);
  --section-y: clamp(2.25rem, 5vw, 4.5rem);
  --header-h: 4.5rem;

  --r-sm: 0.5rem;
  --r-md: 0.5rem;
  --r-lg: 0.75rem;
  --r-pill: 999px;

  --ease-out: cubic-bezier(0.22, 0.68, 0.32, 1);
  --t-fast: 160ms;
  --t-base: 240ms;
  --t-slow: 380ms;

  --z-raised: 10;
  --z-panel: 90;
  --z-header: 100;
  --z-top: 1000;

  color-scheme: light;
}
/* == 02. RESET I PODSTAWY ================================================ */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + 1rem);
}

body {
  margin: 0;
  background: var(--niebo-1);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--step-0);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
body.is-locked { overflow: hidden; }

img, svg, video { display: block; max-width: 100%; }
img { height: auto; }
button { font: inherit; color: inherit; }

a { color: var(--accent); text-underline-offset: 0.2em; text-decoration-thickness: 0.08em; }

:focus-visible { outline: 3px solid var(--focus); outline-offset: 3px; border-radius: 6px; }
::selection { background: var(--sky); color: #052235; }

.skip-link {
  position: absolute;
  left: var(--space-4);
  top: var(--space-4);
  z-index: var(--z-top);
  padding: 0.75rem 1.25rem;
  background: #052235;
  color: #fff;
  border-radius: var(--r-sm);
  font-weight: 600;
  text-decoration: none;
  transform: translateY(-180%);
  transition: transform var(--t-base) var(--ease-out);
}
.skip-link:focus-visible { transform: translateY(0); }

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* == 03. UKŁAD, SEKCJE I STREFY GŁĘBOKOŚCI =============================== */

.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.container--narrow { max-width: 48rem; }

.section {
  position: relative;
  padding-block: var(--section-y);
  color: var(--on-surface);
  overflow: hidden;              /* przytrzymuje efekty: bąbelki, promienie */
}
.section--tight { padding-block: clamp(1.75rem, 4vw, 3rem); }

/* Wycinki gradientu — sąsiednie sekcje dzielą kolor styku, więc tło płynie
   bez szwu od nieba na górze do otchłani na dole.                          */
#gora        { background: linear-gradient(180deg, var(--niebo-1) 0%, var(--niebo-2) 100%); }
#o-nas       { background: linear-gradient(180deg, var(--niebo-2) 0%, var(--niebo-3) 100%); }
#zajecia     { background: linear-gradient(180deg, var(--niebo-3) 0%, var(--niebo-4) 100%); }
#oferta      { background: linear-gradient(180deg, var(--niebo-4) 0%, var(--powierzchnia) 100%); }
#galeria     { background: linear-gradient(180deg, var(--powierzchnia) 0%, var(--woda-1) 100%); }
#kadra       { background: linear-gradient(180deg, var(--woda-1) 0%, var(--woda-2) 100%); }
#lokalizacje { background: linear-gradient(180deg, var(--woda-2) 0%, var(--woda-3) 100%); }
#opinie      { background: linear-gradient(180deg, var(--woda-3) 0%, var(--glebia-1) 100%); }
#formularz   { background: linear-gradient(180deg, var(--glebia-1) 0%, var(--glebia-2) 100%); }
#kontakt     { background: linear-gradient(180deg, var(--glebia-2) 0%, var(--otchlan) 100%); }

/* Strefa jasna — niebo i tafla. Ciemny tekst na jasnym błękicie. */
.strefa--jasna {
  --heading: var(--ink);
  --on-surface: var(--ink);
  --muted: var(--ink-2);
  --accent: var(--brand-700);
  --focus: var(--brand-700);
  --rule: rgba(6, 48, 74, 0.18);
  --karta: rgba(255, 255, 255, 0.62);
  --karta-obrys: rgba(255, 255, 255, 0.85);
}

/* Strefa zanurzenia — tło ciemnieje w trakcie sekcji, więc tekst jest
   maksymalnie ciemny, a tekstu jest tu najmniej (sekcja to głównie zdjęcia). */
.strefa--zanurzenie {
  --heading: var(--ink-deep);
  --on-surface: var(--ink-deep);
  --muted: var(--ink-deep);
  --accent: var(--ink-deep);
  --focus: var(--ink-deep);
  --rule: rgba(5, 34, 53, 0.26);
  --karta: rgba(255, 255, 255, 0.55);
  --karta-obrys: rgba(255, 255, 255, 0.7);
}

/* Strefa głębi — biały tekst na granacie, karty jako matowe szkło. */
.strefa--glebia {
  --heading: #FFFFFF;
  --danger: #FFB4AE;
  --ok: #A7E8C4;
  --on-surface: #FFFFFF;
  --muted: var(--on-deep);
  --accent: #FFFFFF;
  --focus: #FFFFFF;
  --rule: rgba(255, 255, 255, 0.22);
  --karta: rgba(255, 255, 255, 0.08);
  --karta-obrys: rgba(255, 255, 255, 0.2);
}

/* == 04. TYPOGRAFIA ====================================================== */

h1, h2, h3, h4 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1.06;
  color: var(--heading);
  text-wrap: balance;
}

p { margin: 0 0 1em; text-wrap: pretty; }
p:last-child { margin-bottom: 0; }

.h1 { font-size: var(--step-5); font-weight: 700; letter-spacing: -0.028em; line-height: 1.02; }
.h2 { font-size: var(--step-4); letter-spacing: -0.022em; line-height: 1.08; }
.h3 { font-size: var(--step-3); }
.h4 { font-size: var(--step-2); }

.eyebrow {
  display: block;
  margin: 0 0 var(--space-4);
  font-family: var(--font-body);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--accent);
}

.lede {
  font-size: 1.125rem;
  line-height: 1.65;
  color: var(--muted);
  max-width: 40ch;
}

.prose { max-width: 55ch; color: var(--muted); }   /* ~70 znaków w linii */

/* Nagłówek sekcji: etykieta i tytuł po lewej, zdanie wprowadzające po prawej,
   pod włoskowatą kreską. Układ redakcyjny zamiast wyśrodkowanego stosu —
   dzięki temu każda sekcja zaczyna się jak rozdział, a nie jak slajd.        */
.section__head {
  position: relative;
  display: grid;
  row-gap: var(--space-3);
  max-width: none;
  margin-bottom: clamp(1.5rem, 4vw, 3.5rem);
  padding-top: var(--space-5);
}
/* Kreska nad nagłówkiem dorysowuje się przy wejściu sekcji.
   Bez JS jest po prostu narysowana od razu.                                */
.section__head::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 1px;
  background: var(--rule);
  transform-origin: left center;
}
.js .section__head.reveal::before { transform: scaleX(0); transition: transform 400ms var(--ease-out) 120ms; }
.js .section__head.reveal.is-in::before { transform: scaleX(1); }
.section__head .eyebrow { margin: 0; }
.section__head .lede { margin: 0; max-width: 40ch; }

@media (min-width: 62rem) {
  .section__head {
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
    column-gap: clamp(2.5rem, 6vw, 5rem);
    align-items: end;
  }
  .section__head .eyebrow { grid-column: 1; grid-row: 1; }
  .section__head .h2      { grid-column: 1; grid-row: 2; }
  .section__head .lede    { grid-column: 2; grid-row: 1 / span 2; align-self: end; }
}

/* == 05. PRZYCISKI ======================================================= */

.btn {
  --btn-bg: var(--brand-600);
  --btn-fg: #FFFFFF;
  --btn-bd: var(--brand-600);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  min-height: 3rem;
  padding: 0.75rem 1.75rem;
  border: 1.5px solid var(--btn-bd);
  border-radius: var(--r-pill);
  background: var(--btn-bg);
  color: var(--btn-fg);
  font-size: 0.9375rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: none;
  line-height: 1.2;
  text-decoration: none;
  cursor: pointer;
  touch-action: manipulation;
  transition: background-color var(--t-fast) var(--ease-out),
              border-color var(--t-fast) var(--ease-out),
              color var(--t-fast) var(--ease-out),
              transform var(--t-fast) var(--ease-out);
}
.btn--primary:hover { --btn-bg: var(--brand-700); --btn-bd: var(--brand-700); }

.btn--outline { --btn-bg: transparent; --btn-fg: var(--brand-700); --btn-bd: var(--rule); }
.btn--outline:hover { --btn-bd: var(--brand); --btn-bg: rgba(16, 126, 191, 0.07); }

.btn--light { --btn-bg: #FFFFFF; --btn-fg: var(--brand-700); --btn-bd: #FFFFFF; }
.btn--light:hover { --btn-bg: var(--sky); --btn-bd: var(--sky); }

.btn--outline-light { --btn-bg: transparent; --btn-fg: #FFFFFF; --btn-bd: rgba(255, 255, 255, 0.55); }
.btn--outline-light:hover { --btn-bg: rgba(255, 255, 255, 0.16); --btn-bd: #FFFFFF; }

.btn--sm { min-height: 2.75rem; padding: 0.5rem 1.25rem; font-size: 0.8125rem; }

.btn-row { display: flex; flex-wrap: wrap; gap: var(--space-3); margin-top: var(--space-6); }

.link-arrow {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  gap: 0.45rem;
  font-size: 0.9375rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: none;
  color: var(--accent);
  text-decoration: none;
}
.link-arrow::after {
  content: "";
  width: 1.05em; height: 1.05em;
  background: currentColor;
  transition: transform var(--t-fast) var(--ease-out);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14M13 6l6 6-6 6'/%3E%3C/svg%3E") center / contain no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14M13 6l6 6-6 6'/%3E%3C/svg%3E") center / contain no-repeat;
}
.link-arrow:hover::after { transform: translateX(4px); }

/* Reakcja na wciśnięcie — palec/mysz dostaje potwierdzenie od razu */
.btn:active { transform: scale(0.98); }
.carousel__arrow:active,
.nav-toggle:active { transform: scale(0.94); }
/* == 06. NAGŁÓWEK I NAWIGACJA ============================================ */

.site-header {
  position: sticky;
  top: 0;
  z-index: var(--z-header);
  background: rgba(234, 247, 254, 0.72);
  backdrop-filter: blur(14px) saturate(150%);
  -webkit-backdrop-filter: blur(14px) saturate(150%);
  border-bottom: 1px solid transparent;
  transition: border-color var(--t-base) var(--ease-out), background-color var(--t-base) var(--ease-out);
}
.site-header.is-stuck { background: rgba(234, 247, 254, 0.9); border-bottom-color: rgba(6, 48, 74, 0.14); }

.site-header__bar { display: flex; align-items: center; gap: var(--space-4); min-height: var(--header-h); }

.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  min-height: 2.75rem;
  min-width: 2.75rem;
  margin-right: auto;
  color: var(--heading);
  text-decoration: none;
}
.brand__mark { width: 2.4rem; height: 2.4rem; flex: none; }
.brand__name { display: flex; flex-direction: column; line-height: 1; }
.brand__name b {
  font-family: var(--font-display);
  font-size: 1.125rem;
  font-weight: 800;
  letter-spacing: 0.02em;
  text-transform: none;
}
.brand__name span {
  margin-top: 0.25em;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--brand-700);
}

.nav { display: none; }
.nav__list { display: flex; align-items: center; gap: clamp(0.75rem, 2vw, 1.75rem); margin: 0; padding: 0; list-style: none; }
.nav__link {
  position: relative;
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  padding: 0 0.15rem;
  /* Pozycje menu są elementami elastycznymi i przy ciasnym pasku kurczyły się
     poniżej własnej treści — tekst łamał się w środku, a dwie pozycje siadały
     o 2 px niżej od reszty. Zakaz łamania sprawia, że menu albo mieści się
     w całości, albo problem widać od razu, zamiast po cichu zniekształcać. */
  white-space: nowrap;
  color: var(--heading);
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  text-decoration: none;
}
.nav__link::after {
  content: "";
  position: absolute;
  left: 0.15rem; right: 0.15rem; bottom: 0.6rem;
  height: 2px;
  background: var(--brand);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--t-base) var(--ease-out);
}
.nav__link:hover::after, .nav__link[aria-current]::after { transform: scaleX(1); }
.nav__link[aria-current] { color: var(--brand-700); }

.header-cta { display: inline-flex; flex: none; }

.nav-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 3rem; height: 3rem;
  flex: none;
  padding: 0;
  border: 1px solid var(--rule);
  border-radius: var(--r-pill);
  background: var(--karta);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  color: var(--heading);
  cursor: pointer;
  touch-action: manipulation;
}
.nav-toggle__box { position: relative; width: 1.125rem; height: 0.75rem; }
.nav-toggle__box i {
  position: absolute; left: 0; right: 0;
  height: 2px; border-radius: 2px;
  background: currentColor;
  transition: transform var(--t-base) var(--ease-out), opacity var(--t-fast) linear;
}
.nav-toggle__box i:nth-child(1) { top: 0; }
.nav-toggle__box i:nth-child(2) { top: 50%; margin-top: -1px; }
.nav-toggle__box i:nth-child(3) { bottom: 0; }
.nav-toggle[aria-expanded="true"] .nav-toggle__box i:nth-child(1) { transform: translateY(5px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle__box i:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] .nav-toggle__box i:nth-child(3) { transform: translateY(-5px) rotate(-45deg); }

.mobile-nav {
  position: fixed;
  inset: 0;
  z-index: var(--z-panel);
  display: grid;
  grid-template-rows: var(--header-h) 1fr;
  background: linear-gradient(180deg, var(--niebo-1) 0%, var(--niebo-3) 100%);
  visibility: hidden;
  opacity: 0;
  transition: opacity var(--t-base) var(--ease-out), visibility 0s linear var(--t-base);
}
.mobile-nav.is-open { visibility: visible; opacity: 1; transition: opacity var(--t-base) var(--ease-out), visibility 0s; }
.mobile-nav__body {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
  padding: var(--space-4) var(--gutter) calc(var(--space-8) + env(safe-area-inset-bottom));
  overflow-y: auto;
  /* Dojechanie palcem do końca listy nie może zacząć przewijać strony
     pod spodem — na telefonie wygląda to jak zacięcie menu.             */
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}

.mobile-nav__list { margin: 0; padding: 0; list-style: none; }
.mobile-nav__list li + li { border-top: 1px solid var(--rule); }
.mobile-nav__list a {
  display: flex;
  align-items: center;
  min-height: 3.5rem;
  color: var(--heading);
  font-family: var(--font-display);
  font-size: 1.5rem;
  font-weight: 700;
  text-transform: none;
  text-decoration: none;
}
/* Telefon w poziomie: na listę zostaje ok. 300 px wysokości, a pozycje po
   3,5rem kazały przewijać całe menu, żeby dojść do zapisów na dole.
   Musi stać PO regule `.mobile-nav__list a` — ma tę samą specyficzność,
   więc decyduje kolejność w pliku.                                      */
@media (max-height: 30rem) {
  .mobile-nav__body { gap: var(--space-4); padding-top: var(--space-3); }
  .mobile-nav__list a { min-height: 2.75rem; font-size: 1.125rem; }
}

.mobile-nav__meta {
  margin-top: auto;
  padding-top: var(--space-5);
  border-top: 1px solid var(--rule);
  color: var(--ink-2);
  font-size: 0.9375rem;
}
.mobile-nav__meta a {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  color: var(--brand-700);
  font-weight: 700;
  text-decoration: none;
}

/* Menu poziome pokazujemy dopiero od 70rem (1120 px), nie od 62rem.

   Siedem pozycji z „Kolonie i urodziny" potrzebuje 740 px. Razem z logotypem
   (176 px) i przyciskiem zapisów (108 px) daje to 1056 px — przy 992 px pasek
   ma 977 px, więc brakowało 79 px. Flexbox nie zgłaszał tego jako przepełnienie:
   ściskał logotyp do 44 px, a napis „AerialParadise" wychodził poza jego
   ramkę i **wjeżdżał pod pozycję „O nas"**. Stąd wrażenie, że menu nachodzi
   na logo.

   Poniżej tej szerokości nawigację przejmuje menu pod hamburgerem — a ono
   ma bogatszą listę, z rozbiciem zajęć i obu ofert na osobne pozycje.     */
@media (min-width: 70rem) {
  .nav { display: block; }
  .nav-toggle { display: none; }
  .mobile-nav { display: none; }
}

/* Logotyp nie może być ściskany, żeby zrobić miejsce menu — jego napis i tak
   nie zawija się ani nie przycina, więc „zaoszczędzone" piksele wychodzą
   spod spodu i nachodzą na sąsiada. Lepiej, żeby zabrakło miejsca widocznie. */
.brand { flex: none; }

/* == 07. HERO ============================================================ */

.hero {
  position: relative;
  min-height: min(92vh, 50rem);
  padding-block: clamp(3.5rem, 8vh, 6rem) clamp(3rem, 10vh, 8rem);

  overflow: hidden;
  text-align: center;
}
.hero__inner { position: relative; z-index: var(--z-raised); display: flex; flex-direction: column; align-items: center; width: 100%; }

/* --- Zdjęcie jako tło hero ------------------------------------------------
   W hero stoi tylko logo i nazwa, więc kadr może być mocno widoczny:
   ok. 30 % za nazwą i do 75 % w dolnym pasie. Ku górze rozpływa się
   w niebie. Zdjęcie ma miejsca niemal czarne (włosy, cień), więc pod
   napisem leży zasłona w barwie nieba — kontrast jest policzony dla
   najciemniejszego realnego piksela pod nazwą.                          */
.hero__tlo {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
}
.hero__tlo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 38%;
  opacity: 0.92;
  -webkit-mask-image: var(--maska-tla);
  mask-image: var(--maska-tla);
}
.hero__tlo {
  /* Zdjęcie gaśnie długo, na przestrzeni ostatnich ~20 % wysokości hero,
     i jest już całkiem niewidoczne 2 % przed dolną krawędzią. Wcześniej
     schodziło z 98 % do zera na 47 px tuż nad granicą sekcji i ten skok
     było widać jako twarde przejście barw.                             */
  --maska-tla: linear-gradient(180deg,
    rgba(0, 0, 0, 0.10) 0%,
    rgba(0, 0, 0, 0.34) 28%,
    rgba(0, 0, 0, 0.58) 55%,
    rgba(0, 0, 0, 0.76) 70%,
    rgba(0, 0, 0, 0.92) 80%,
    rgba(0, 0, 0, 0.62) 88%,
    rgba(0, 0, 0, 0.22) 94%,
    rgba(0, 0, 0, 0)    98%,
    rgba(0, 0, 0, 0)   100%);
}
/* Zasłona nieba siedzi na wysokości napisów (ok. 60 %), a nie na twarzy —
   dzięki temu postać ze zdjęcia zostaje odsłonięta, a tekst ma kontrast.
   Pierwszy promień jest przesadnie szeroki celowo: inaczej litery przy
   lewej i prawej krawędzi wypadałyby poza zasłonę.                     */
.hero__tlo::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(200% 24% at 50% 72%,
      rgba(234, 247, 254, 0.72) 0%,
      rgba(234, 247, 254, 0.38) 60%,
      rgba(234, 247, 254, 0) 100%),
    linear-gradient(180deg,
      rgba(205, 234, 251, 0) 74%,
      rgba(205, 234, 251, 0.55) 88%,
      var(--niebo-2) 100%);
}
/* Bez maski (starsze przeglądarki) zdjęcie zostaje przygaszone,
   żeby nie przykryło nagłówka twardą krawędzią. */
@supports not ((mask-image: linear-gradient(#000, #000)) or (-webkit-mask-image: linear-gradient(#000, #000))) {
  .hero__tlo img { opacity: 0.28; }
}


/* Logo siedzi wysoko, nad głową postaci ze zdjęcia (twarz jest mniej
   więcej na 40 % wysokości hero). Odstęp pod logo zrzuca nazwę poniżej
   twarzy — dlatego jest tak duży i liczony w `vh`, a nie w `rem`.     */
.hero__logo {
  width: clamp(5.5rem, 13vw, 8.5rem);
  height: auto;
  margin-bottom: clamp(7rem, 28vh, 16rem);
}

/* Nazwa klubu. Nad zdjęciem tylko pełny granat: błękit z logo dałby
   tu ok. 1,7:1 i byłby nieczytelny. */
.hero__title {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(2.5rem, 11vw, 7rem);
  font-weight: 600;
  line-height: 1.02;
  letter-spacing: -0.02em;
  color: var(--ink);
}

.hero__pod {
  margin: clamp(0.75rem, 1.6vh, 1.25rem) 0 0;
  font-family: var(--font-body);
  font-size: clamp(0.9375rem, 2.4vw, 1.375rem);
  font-weight: 600;
  letter-spacing: clamp(0.14em, 0.5vw, 0.26em);
  text-transform: uppercase;
  color: var(--ink);
}

/* Szarfy — jedyny element dekoracyjny, w błękicie z logo */
.hero__silks { position: absolute; top: 0; width: min(18rem, 34vw); height: 130%; opacity: 0.5; pointer-events: none; }
.hero__silks--l { left: -4%; }
.hero__silks--r { right: -4%; transform: scaleX(-1); }

/* Telefon obrócony na bok. Duży odstęp pod logo ma sens tylko w pionie —
   zrzuca nazwę poniżej twarzy z kadru. W poziomie ta sama wartość (dolne
   ograniczenie 7rem) plus nazwa liczona z szerokości okna rozdymały hero
   do ok. 125 % ekranu, więc sama nazwa klubu nie mieściła się w widoku.  */
@media (max-height: 30rem) and (orientation: landscape) {
  .hero {
    min-height: 0;
    padding-block: var(--space-6) var(--space-7);
  }
  .hero__logo {
    width: clamp(3.5rem, 9vh, 5rem);
    margin-bottom: clamp(1.5rem, 9vh, 3.5rem);
  }
  .hero__title { font-size: clamp(2.25rem, 7vw, 3.5rem); }
  .hero__pod { font-size: clamp(0.8125rem, 1.5vw, 1rem); letter-spacing: 0.16em; }
}


/* Na najwęższych ekranach zostaje sam znak graficzny — nazwa i tak jest
   w logotypie, a miejsce jest potrzebne przyciskowi zapisów i menu.        */
@media (max-width: 22rem) {
  .brand__name { display: none; }
}
@media (max-width: 47.99rem) {
  .hero__silks { opacity: 0.32; width: 42vw; }
}

/* == 08. RAMKI NA ZDJĘCIA ================================================ */

.photo {
  position: relative;
  margin: 0;
  aspect-ratio: var(--ratio, 4 / 3);
  border-radius: var(--r-md);
  overflow: hidden;
  background: var(--karta);
  isolation: isolate;
}
.photo img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.photo.is-empty img { visibility: hidden; }

.photo__hint {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  padding: clamp(0.75rem, 3vw, 1.5rem);
  text-align: center;
  border: 1.5px dashed rgba(16, 126, 191, 0.45);
  border-radius: inherit;
  background: var(--karta);
}
.photo.is-loaded .photo__hint { display: none; }

.photo__label { max-width: 26ch; font-size: 0.8125rem; font-weight: 600; line-height: 1.4; color: var(--accent); }
.photo__file {
  padding: 0.2rem 0.55rem;
  border-radius: var(--r-pill);
  background: rgba(127, 203, 236, 0.1);
  color: var(--accent);
  font-family: ui-monospace, "Consolas", monospace;
  font-size: 0.75rem;
  overflow-wrap: anywhere;
}

/* Pas galerii — rząd zdjęć, jak na stronie-inspiracji */
.strip-pas { position: relative; }
.strip { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-3); }
.strip .photo { --ratio: 3 / 4; }
/* Kadry poziome docinamy do pionu tak, żeby postać została w kadrze */
.strip .photo--kadr img { object-position: 56% 42%; }
@media (min-width: 48rem) {
  /* Siatka bez JS — po włączeniu przesuwu układ przejmuje `.strip-pas`. */
  .strip { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  body { font-size: var(--step-1); line-height: 1.7; }
}

/* --- Galeria: dwa rzędy jadące powoli w bok -------------------------------
   Na każdej szerokości, nie tylko na telefonie. Czternaście kafli w siatce
   zajmowałoby kilka ekranów; tutaj widać dwa rzędy, a reszta sama nadjeżdża
   z prawej. Skrypt dokłada komplet kopii, więc `-50%` to dokładnie jeden
   zestaw i pętla nie ma szwu.

   Bez JS pas zostaje zwykłą siatką — układ dwurzędowy włącza się dopiero
   po ustawieniu `data-galeria-gotowy` przez skrypt.                       */
.strip-pas {
  overflow: hidden;
  /* Krawędzie rozmywają się, żeby zdjęcia nie były ucinane pionową linią */
  --maska-pasa: linear-gradient(90deg, rgba(0,0,0,0) 0%, rgba(0,0,0,1) 5%,
    rgba(0,0,0,1) 95%, rgba(0,0,0,0) 100%);
  mask-image: var(--maska-pasa);
}
.strip-pas[data-galeria-gotowy] .strip {
  grid-template-columns: none;
  grid-template-rows: repeat(2, auto);
  grid-auto-flow: column;
  /* Na telefonie kafel ma ok. 40 % szerokości ekranu, na dużym ekranie
     zatrzymuje się na 15 rem — inaczej dwa rzędy zajęłyby cały widok. */
  grid-auto-columns: clamp(9rem, 40vw, 15rem);
  width: max-content;
}
/* Własnościami długimi, nie skrótem `animation:` — skrót ustawiłby przy
   okazji `animation-play-state: running` i zatrzymanie pasa przy otwartym
   powiększeniu nie miałoby czego zatrzymać (ta sama pułapka co przy chmurach). */
.js .strip-pas[data-galeria-gotowy] .strip {
  animation-name: przesuw-galerii;
  animation-duration: var(--tempo-galerii, 48s);
  animation-timing-function: linear;
  animation-iteration-count: infinite;
}
/* Przesuw staje, gdy zdjęcie jest powiększone — inaczej pas jechałby
   dalej pod spodem i po zamknięciu kadr byłby w innym miejscu.         */
.strip-pas[data-zatrzymany] .strip { animation-play-state: paused; }

/* Kopie istnieją wyłącznie po to, żeby domknąć pętlę przesuwu. Poza nią —
   na dużym ekranie i przy „ogranicz ruch" — nie mogą dołożyć ośmiu kafli
   do siatki, więc domyślnie ich nie ma. */
.strip > [data-klon-galerii] { display: none; }
.strip-pas[data-galeria-gotowy] .strip > [data-klon-galerii] { display: block; }

/* --- Powiększanie zdjęć z galerii ---------------------------------------
   Przycisk dokłada skrypt i leży na całym kaflu. Jest przezroczysty —
   widać zdjęcie pod spodem — ale ma własne obramowanie fokusu, więc przy
   obsłudze klawiaturą widać, na którym zdjęciu się stoi.                 */
.photo__lupa {
  position: absolute;
  inset: 0;
  z-index: var(--z-raised);
  width: 100%;
  height: 100%;
  padding: 0;
  border: 0;
  border-radius: inherit;
  background: transparent;
  cursor: zoom-in;
}

.lupa {
  width: min(92vw, 60rem);
  max-width: none;
  max-height: 92vh;
  padding: 0;
  border: 0;
  border-radius: var(--r-lg, 1rem);
  background: transparent;
  overflow: visible;
}
.lupa::backdrop { background: rgba(3, 24, 41, 0.86); backdrop-filter: blur(6px); }
.lupa__foto {
  display: block;
  width: 100%;
  max-height: 82vh;
  object-fit: contain;
  border-radius: var(--r-lg, 1rem);
  background: var(--glebia-2);
}
.lupa__zamknij {
  position: absolute;
  top: -0.5rem;
  right: -0.5rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  border: 1px solid rgba(255, 255, 255, 0.35);
  border-radius: 50%;
  background: var(--otchlan);
  color: #FFFFFF;
  font-size: 1.125rem;
  line-height: 1;
  cursor: pointer;
}
.lupa__zamknij:hover { background: var(--glebia-1); }

/* Na wąskim ekranie krzyżyk nie może wystawać poza kadr zdjęcia. */
@media (max-width: 30rem) {
  .lupa__zamknij { top: 0.5rem; right: 0.5rem; }
}


@keyframes przesuw-galerii {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

/* Pas pełnoekranowy — zdjęcie na całą szerokość między sekcjami.
   Krawędzie wtapiają się w barwę sąsiednich sekcji (--pas-krawedz),
   dzięki czemu ciągły gradient nieba i wody nie zostaje przecięty. */
.pas-foto {
  position: relative;
  margin: 0;
  height: clamp(13rem, 32vw, 24rem);
  overflow: hidden;
  background: var(--pas-krawedz, var(--woda-1));
}
.pas-foto img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform: scale(1.06);
}
.pas-foto::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(180deg,
    var(--pas-krawedz, var(--woda-1)) 0%,
    rgba(0, 0, 0, 0) 30%,
    rgba(0, 0, 0, 0) 70%,
    var(--pas-krawedz, var(--woda-1)) 100%);
}

/* == 09. BLOKI ZAJĘĆ ===================================================== */

/* Karuzela zajęć — przewijanie w bok zamiast długiej listy w dół.
   Na telefonie strzałki stoją NAD slajdem, z licznikiem między nimi — na
   bokach zasłaniałyby zdjęcie. Od tabletu w górę wracają po bokach toru.
   W kodzie idą przed torem, więc kolejność fokusu zgadza się z układem.  */
.carousel {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-areas:
    "prev   status next"
    "track  track  track";
  align-items: center;
  column-gap: var(--space-3);
  row-gap: var(--space-5);
}
@media (min-width: 48rem) {
  .carousel {
    grid-template-areas:
      "prev track next"
      ".    status .";
    column-gap: clamp(0.75rem, 2vw, 1.75rem);
  }
}

.carousel__track {
  grid-area: track;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 100%;
  --slide-gap: clamp(1.5rem, 4vw, 3rem);
  gap: var(--slide-gap);
  padding-block: 0.25rem;
  overflow-x: auto;
  /* Bez tego przeglądarka włącza też pionowe przewijanie toru (overflow-x
     wymusza overflow-y: auto). Przy wysokiej karcie kadry robi się kilka
     pikseli pionowego zapasu, który przechwytuje przesunięcie palcem
     i strona przestaje się przewijać. */
  overflow-y: hidden;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
}
.carousel__track::-webkit-scrollbar { display: none; }
.carousel__track:focus-visible { outline: 3px solid var(--focus); outline-offset: 6px; border-radius: var(--r-lg); }

.carousel__arrow {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 3rem;
  height: 3rem;
  padding: 0;
  border: 1.5px solid var(--rule);
  border-radius: var(--r-pill);
  background: var(--karta);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  color: var(--heading);
  cursor: pointer;
  touch-action: manipulation;
  transition: border-color var(--t-fast) var(--ease-out),
              background-color var(--t-fast) var(--ease-out),
              opacity var(--t-fast) var(--ease-out);
}
.carousel__arrow--prev { grid-area: prev; justify-self: start; }
.carousel__arrow--next { grid-area: next; justify-self: end; }
.carousel__arrow:hover:not([disabled]) { border-color: var(--brand); background: var(--karta-obrys); }
.carousel__arrow[disabled] { opacity: 0.32; cursor: default; }
.carousel__arrow svg { width: 1.35rem; height: 1.35rem; }
.carousel__arrow--next svg { transform: rotate(180deg); }
@media (min-width: 48rem) {
  .carousel__arrow { width: 3.25rem; height: 3.25rem; box-shadow: 0 2px 14px rgba(6, 48, 74, 0.10); }
}

/* Tablet: mieści się jedna karta kadry, więc kolumna ma dokładnie jej
   szerokość, a resztę toru zjada symetryczne wcięcie. Bez tego karta
   lgnęła do lewej strzałki, a po prawej zostawało 258 px pustki.       */
@media (min-width: 48rem) and (max-width: 61.99rem) {
  .carousel--coaches .carousel__track {
    grid-auto-columns: 26rem;
    padding-inline: max(0px, calc((100% - 26rem) / 2));
    scroll-padding-inline: max(0px, calc((100% - 26rem) / 2));
  }
}

.carousel__status {
  grid-area: status;
  margin: 0;
  text-align: center;
  font-family: var(--font-body);
  font-size: 0.9375rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--heading);
  font-variant-numeric: tabular-nums;
}

.class-block {
  display: grid;
  gap: clamp(1.5rem, 4vw, 3rem);
  align-content: center;
  scroll-snap-align: start;
}
.class-block .prose { max-width: 50ch; }

@media (min-width: 62rem) {
  .class-block { grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr); align-items: center; }
  /* Co drugi slajd ma zdjęcie po lewej — rytm przy przewijaniu */
  .class-block:nth-child(even) .class-block__media { order: -1; }
}

/* Układ dwukolumnowy: tekst + zdjęcie */
.split { display: grid; gap: clamp(2rem, 5vw, 4rem); align-items: center; }
@media (min-width: 62rem) { .split { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } }

.pillars { margin: var(--space-6) 0 0; padding: 0; list-style: none; display: grid; gap: var(--space-5); }
@media (min-width: 40rem) { .pillars { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.pillar b { display: block; font-family: var(--font-display); font-size: 1.125rem; font-weight: 700; color: var(--heading); }
.pillar span { font-size: 0.9375rem; line-height: 1.55; color: var(--muted); }

/* == 9b. KOLONIE I URODZINY ==============================================
   Dwie oferty w jednej sekcji. Każda to tekst plus zdjęcia; na dużym
   ekranie stoją obok siebie, a druga ma odwróconą kolejność, żeby sekcja
   nie wyglądała jak dwa razy ten sam blok.                                */
/* Tło tej sekcji schodzi już do #7FCBEC, czyli najciemniejszego błękitu
   w strefie jasnej. Markowy `--brand-700` dawał tu 3,89:1 na etykiecie
   i obu odnośnikach — poniżej progu 4,5:1. Przyciemniamy akcent wyłącznie
   w tej sekcji, zamiast ruszać token używany na całej stronie.            */
#oferta {
  --accent: #07496C;
  --focus: #07496C;
}

.oferta {
  display: grid;
  gap: clamp(1.75rem, 4vw, 3rem);
  align-items: start;
}
.oferta + .oferta {
  margin-top: clamp(2.5rem, 6vw, 4.5rem);
  padding-top: clamp(2.5rem, 6vw, 4.5rem);
  border-top: 1px solid var(--rule);
}
.oferta__tekst > * + * { margin-top: var(--space-5); }
.oferta__tekst .prose { max-width: 54ch; }
.oferta__cta { margin: 0; }

.oferta__zdjecia {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-3);
  margin: 0;
  padding: 0;
  list-style: none;
}
.oferta__zdjecia .photo { --ratio: 3 / 4; }
/* Kadr poziomy w pionowym slocie ucinałby to, co najważniejsze — grupę
   ludzi. Takie zdjęcie dostaje więc obie kolumny i własne proporcje. */
.oferta__zdjecia .szeroki { grid-column: 1 / -1; }
.oferta__zdjecia .szeroki .photo { --ratio: 3 / 2; }
/* Jedno zdjęcie nie ma z czym tworzyć siatki — zajmuje całą szerokość. */
.oferta__zdjecia--jedno { grid-template-columns: minmax(0, 1fr); }
.oferta__zdjecia--jedno .photo { --ratio: 4 / 5; }

/* Kolumna ze zdjęciem, ceną i przyciskiem. */
.oferta__bok > * + * { margin-top: var(--space-5); }

@media (min-width: 62rem) {
  .oferta { grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr); column-gap: clamp(2.5rem, 5vw, 4.5rem); }
  .oferta--odwrotna .oferta__tekst { order: 2; }
  .oferta--odwrotna .oferta__zdjecia,
  .oferta--odwrotna .oferta__bok { order: 1; }
  /* Zdjęcie idzie górą, nie środkiem: pod nim stoi teraz cennik z przyciskiem,
     więc kolumna ma czym wypełnić wysokość. */
  .oferta__bok .oferta__zdjecia--jedno { align-self: start; }
}

/* Co jest w cenie i ile to kosztuje.

   Bez ramki i bez tła: pudełko odcinało się od reszty strony, bo nigdzie
   indziej takich nie ma — sekcje trzyma tu kreska i typografia, nie obrys.
   Rytm buduje więc podtytuł pod cienką linią, dokładnie jak w nagłówkach
   sekcji.                                                                 */
.podtytul {
  margin: 0 0 var(--space-3);
  padding-top: var(--space-3);
  border-top: 1px solid var(--rule);
  font-family: var(--font-body);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
}

/* Znacznik rysowany kreską, nie znakiem — nie zależy od kroju pisma
   i nie jest odczytywany przez czytnik ekranu jako treść.                */
.wcenie__lista { margin: 0; padding: 0; list-style: none; }
.wcenie__lista li {
  position: relative;
  padding-left: 1.6rem;
  margin-bottom: 0.45rem;
  font-size: 0.9375rem;
  line-height: 1.55;
  color: var(--on-surface);
}
.wcenie__lista li::before {
  content: "";
  position: absolute;
  left: 0.15rem;
  top: 0.42em;
  width: 0.55rem;
  height: 0.3rem;
  border-left: 2px solid var(--accent);
  border-bottom: 2px solid var(--accent);
  transform: rotate(-45deg);
}
@media (min-width: 30rem) {
  .wcenie__lista { columns: 2; column-gap: var(--space-5); }
  .wcenie__lista li { break-inside: avoid; }
}

.ceny__lista { margin: 0; padding: 0; list-style: none; }
.ceny__lista li {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.25rem 1.5rem;
  padding: 0.65rem 0;
}
.ceny__lista li + li { border-top: 1px solid var(--rule); }
.ceny__co { font-size: 0.9375rem; color: var(--muted); }
.ceny__ile {
  font-family: var(--font-display);
  font-size: var(--step-3);
  font-weight: 700;
  line-height: 1;
  color: var(--heading);
  font-variant-numeric: tabular-nums;
}

/* == 10. KADRA =========================================================== */

/* Kadra: jedna trenerka na ekranie na telefonie, dwie od dużego ekranu.
   Przesuw zawsze o jedną osobę — jedna znika, jedna wjeżdża.            */
.carousel--coaches .carousel__track { --slide-gap: var(--space-6); }
@media (min-width: 62rem) {
  .carousel--coaches .carousel__track { grid-auto-columns: calc((100% - var(--slide-gap)) / 2); }
}
/* Na desktopie strzałki nachodzą na krawędzie toru, żeby nie zjadały
   szerokości — dzięki temu zdjęcie trenerki może być większe.           */
@media (min-width: 62rem) {
  .carousel--coaches {
    position: relative;
    /* Karta ma stałą szerokość (26 rem), więc w pełnej szerokości kontenera
       zostawało po ok. 48 px luzu w każdej kolumnie — para kart rozjeżdżała
       się na 128 px i strzałki wisiały daleko od nich. Zwężenie samej
       karuzeli domyka przerwę i zbliża strzałki do kart.               */
    max-width: 56rem;
    margin-inline: auto;
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas:
      "track"
      "status";
  }
  .carousel--coaches .carousel__arrow {
    position: absolute;
    top: calc(50% - 1.5rem);
    transform: translateY(-50%);
    z-index: 3;
  }
  .carousel--coaches .carousel__arrow--prev { left: -1.5rem; }
  .carousel--coaches .carousel__arrow--next { right: -1.5rem; }
  /* Karta wypełnia kolumnę co do piksela — każdy luz przesuwał parę
     względem osi sekcji i psuł symetrię strzałek.                     */
  .carousel--coaches .coach { width: 100%; }
  .carousel--coaches .carousel__arrow:active { transform: translateY(-50%) scale(0.94); }
}

.coach__name { font-size: var(--step-2); }
.coach__role {
  margin-top: 0.2rem;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
}
.coach__text { margin-top: var(--space-3); font-size: 0.9375rem; line-height: 1.6; color: var(--muted); }

/* == 11. LOKALIZACJE ===================================================== */

.locations { display: grid; gap: var(--space-6); }
@media (min-width: 48rem) { .locations { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

.location { display: flex; flex-direction: column; border: 1px solid var(--rule); border-radius: var(--r-lg); background: var(--karta); backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); overflow: hidden; }
.location .photo { --ratio: 16 / 10; border-radius: 0; }
.location__body { display: flex; flex-direction: column; flex: 1; padding: clamp(1.25rem, 3vw, 1.75rem); }
.location__tag { margin-bottom: var(--space-3); font-size: 0.75rem; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; color: var(--accent); }
.location__addr { font-family: var(--font-display); font-size: var(--step-3); font-weight: 600; letter-spacing: -0.02em; line-height: 1.15; color: var(--heading); }
.location__hint { margin-top: 0.35rem; font-size: 0.9375rem; color: var(--muted); }
.location__link { margin-top: var(--space-4); }

/* == 12. OPINIE ========================================================== */

.reviews { display: grid; gap: var(--space-5); margin: 0; padding: 0; list-style: none; }
@media (min-width: 56rem) { .reviews { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.reviews > li { display: flex; }

.review {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: var(--space-4);
  margin: 0;
  padding: clamp(1.5rem, 3vw, 2rem);
  border: 1px solid var(--rule);
  border-radius: var(--r-lg);
  background: var(--karta);
}
.review__stars { display: flex; gap: 0.15rem; margin: 0; color: var(--gwiazdka); }
.review__stars svg { width: 1.1rem; height: 1.1rem; }
.review__text { margin: 0; font-size: 1rem; line-height: 1.65; color: var(--on-surface); }
.review__author {
  margin-top: auto;
  padding-top: var(--space-3);
  border-top: 1px solid var(--rule);
  font-size: 0.875rem;
  font-weight: 700;
  font-style: normal;
  color: var(--heading);
}
.review__author span {
  display: block;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent);
}

/* Pusta karta — miejsce na opinię do wklejenia z Google */
.review--empty {
  align-items: flex-start;
  justify-content: center;
  min-height: 11rem;
  border: 1.5px dashed rgba(16, 126, 191, 0.45);
  background: var(--karta);
}
.review__hint { margin: 0; font-size: 0.875rem; font-weight: 600; line-height: 1.5; color: var(--accent); }
.review__code {
  padding: 0.2rem 0.6rem;
  border-radius: var(--r-pill);
  background: rgba(127, 203, 236, 0.1);
  color: var(--accent);
  font-family: ui-monospace, "Consolas", monospace;
  font-size: 0.75rem;
}

.reviews__cta { margin: var(--space-6) 0 0; text-align: center; }

/* == 13. PASEK KONTAKTOWY ================================================ */

/* position + overflow: warstwa efektów (bąbelki) kotwiczy się na sekcji
   i nie może z niej wyciekać. */
.info-band { position: relative; overflow: hidden; color: #fff; padding-block: clamp(2.25rem, 5vw, 3.5rem); }
.info-band h2, .info-band h3 { color: #fff; }
.info-band > .container { position: relative; z-index: var(--z-raised); }
.info-band__grid { display: grid; gap: clamp(2rem, 5vw, 3rem); }
@media (min-width: 48rem) { .info-band__grid { grid-template-columns: 1.25fr 0.85fr 0.9fr; } }

.info-col h2,
.info-col h3 {
  margin-bottom: var(--space-4);
  font-size: 0.8125rem;
  font-family: var(--font-body);
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: #FFFFFF;
}
.info-col ul { margin: 0; padding: 0; list-style: none; }
.info-col address { font-style: normal; }
.info-col p { margin: 0 0 var(--space-2); color: #fff; }
.info-col .muted { color: var(--on-deep); font-size: 0.9375rem; }

.info-lines { display: grid; gap: var(--space-2); }
.info-lines a {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  min-height: 2.75rem;
  min-width: 2.75rem;
  color: #fff;
  font-weight: 600;
  text-decoration: none;
}
.info-lines a:hover { color: var(--sky); }

.info-big {
  display: block;
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 3vw, 2rem);
  font-weight: 800;
  letter-spacing: 0.01em;
  line-height: 1.15;
  text-transform: none;
  color: #fff;
  text-decoration: none;
}
.info-big:hover { color: var(--sky); }

.socials { display: flex; flex-wrap: wrap; gap: var(--space-3); margin: 0; padding: 0; list-style: none; }
.socials a {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  min-height: 2.75rem;
  padding: 0.5rem 1rem;
  border: 1px solid rgba(255, 255, 255, 0.38);
  border-radius: var(--r-pill);
  color: #fff;
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
  transition: background-color var(--t-fast) var(--ease-out);
}
.socials a:hover { background: rgba(255, 255, 255, 0.16); }

/* == 14. FORMULARZ ======================================================= */

.form { display: grid; gap: var(--space-5); }
.form__row { display: grid; gap: var(--space-5); }
@media (min-width: 40rem) { .form__row { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

.field { display: grid; gap: 0.4rem; align-content: start; }
.field > label,
.consent label { font-size: 0.875rem; font-weight: 600; color: var(--heading); }
.req { color: var(--danger); }

.field input,
.field select,
.field textarea {
  width: 100%;
  min-height: 3rem;
  padding: 0.7rem 0.95rem;
  border: 1.5px solid var(--rule);
  border-radius: var(--r-md);
  background: var(--karta);
  color: var(--on-surface);
  font-family: inherit;
  font-size: 1rem;          /* 16 px — powstrzymuje automatyczny zoom na iOS */
  line-height: 1.5;
  transition: border-color var(--t-fast) var(--ease-out);
}
.field textarea { min-height: 9.5rem; resize: vertical; }
.field select {
  appearance: none;
  padding-right: 2.6rem;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23FFFFFF' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.9rem center;
  background-size: 1.1rem;
}
/* Rozwinięta lista `select` jest rysowana przez system, a nie przez stronę:
   dostaje własne, jasne tło, ale kolor tekstu dziedziczy z pola. W strefie
   głębi tekst jest biały, więc pozycje robiły się białe na białym —
   widać było tylko tę pod wskaźnikiem, bo system podmienia jej barwy.
   Dlatego `option` dostaje własną, jawną parę kolorów.                    */
.field select option {
  background-color: #FFFFFF;
  color: var(--ink);
}

.field input:hover,
.field select:hover,
.field textarea:hover { border-color: var(--sky); }

.field__hint { margin: 0; font-size: 0.8125rem; line-height: 1.5; color: var(--muted); }
.field__error { display: none; margin: 0; font-size: 0.8125rem; font-weight: 600; line-height: 1.45; color: var(--danger); }

.field[data-invalid] .field__error { display: block; }
.field[data-invalid] input,
.field[data-invalid] select,
.field[data-invalid] textarea { border-color: var(--danger); }

/* Kwadracik pola wyboru ma 24 px i większy być nie powinien — dlatego
   celem dotyku jest cała etykieta. `padding-block` podnosi wiersz do
   ponad 44 px, a ujemny `margin-block` zdejmuje ten dodatek z układu,
   więc odstępy w formularzu wyglądają tak samo jak wcześniej.          */
.consent__pole {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--space-3);
  align-items: start;
  min-height: 2.75rem;
  padding-block: 0.6rem;
  margin-block: -0.6rem;
  cursor: pointer;
}
.consent input[type="checkbox"] {
  width: 1.5rem;
  height: 1.5rem;
  min-height: 0;
  margin: 0.2rem 0 0;
  padding: 0;
  accent-color: var(--brand-600);
}
.consent__pole > span { font-weight: 500; line-height: 1.55; color: var(--muted); }
.consent[data-invalid] input[type="checkbox"] { outline: 2px solid var(--danger); outline-offset: 3px; }

.form__actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-4) var(--space-5); }
.form__actions .btn { min-width: 13rem; }
.form__note { margin: 0; flex: 1 1 16rem; font-size: 0.8125rem; line-height: 1.5; color: var(--muted); }
.form__note a { display: inline-flex; align-items: center; min-height: 2.75rem; font-weight: 700; }

.form__status {
  display: none;
  margin: 0;
  padding: 0.85rem 1.1rem;
  border-radius: var(--r-md);
  font-size: 0.9375rem;
  font-weight: 600;
  line-height: 1.5;
}
.form__status.is-busy { display: block; background: var(--karta); color: var(--on-surface); }
.form__status.is-ok    { display: block; background: #E7F4EC; color: var(--ok); }
.form__status.is-error { display: block; background: #FBEAE9; color: var(--danger); }

.form button[disabled] { opacity: 0.55; cursor: not-allowed; }

/* == 15. STOPKA ========================================================== */

.site-footer {
  padding-block: var(--space-5);
  background: var(--otchlan);
  border-top: 1px solid rgba(255, 255, 255, 0.12);
  color: rgba(216, 236, 248, 0.75);
  font-size: 0.8125rem;
  --focus: #FFFFFF;
}
.site-footer__bar { display: flex; flex-wrap: wrap; gap: var(--space-3) var(--space-5); align-items: center; justify-content: space-between; }
.site-footer p { margin: 0; }
.site-footer nav ul { display: flex; flex-wrap: wrap; gap: var(--space-4); margin: 0; padding: 0; list-style: none; }
.site-footer a { display: inline-flex; align-items: center; justify-content: center; min-height: 2.75rem; min-width: 2.75rem; color: rgba(216, 236, 248, 0.75); text-decoration: none; }
.site-footer a:hover { color: #FFFFFF; }

/* == 16. ZNACZNIKI, NARZĘDZIA I ANIMACJE ================================= */

.tags { display: flex; flex-wrap: wrap; gap: var(--space-2); margin: var(--space-5) 0 0; padding: 0; list-style: none; }
.tags li {
  padding: 0.35rem 0.85rem;
  border: 1px solid var(--rule);
  border-radius: var(--r-pill);
  background: transparent;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--heading);
}

/* Narzędzia odstępów */
.mt-3 { margin-top: var(--space-3); }
.mt-4 { margin-top: var(--space-4); }
.mt-5 { margin-top: var(--space-5); }
.mt-6 { margin-top: var(--space-6); }
.measure-short { max-width: 34ch; }

/* Ruch */
.silk { transform-box: view-box; transform-origin: 50% 0; }
.silk--a { animation: sway 19s var(--ease-out) infinite alternate; }
.silk--b { animation: sway 24s var(--ease-out) -7s infinite alternate-reverse; }
@keyframes sway {
  from { transform: rotate(-0.9deg); }
  to   { transform: rotate(0.9deg); }
}

.js .reveal {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity var(--t-slow) var(--ease-out), transform var(--t-slow) var(--ease-out);
  transition-delay: var(--delay, 0ms);
}
.js .reveal.is-in { opacity: 1; transform: none; }

/* == 17. RUCH ============================================================
   Trzy rodzaje: wejście strony (raz, na starcie), reakcje na wskaźnik
   i pasek postępu przewijania. Wszystko na transform/opacity, wszystko
   znika przy ustawieniu „ogranicz ruch".                                    */

/* Wejście nagłówka strony korzysta z tego samego mechanizmu co reszta sekcji
   (klasa .reveal) — ma wbudowane zabezpieczenie, więc treść nie może
   zostać ukryta na stałe, gdyby animacje nie wystartowały.              */

/* Zdjęcie ożywa pod wskaźnikiem — sygnał „można tu popatrzeć".

   Tylko tam, gdzie wskaźnik naprawdę istnieje. Na dotyku przeglądarka
   udaje `:hover` po dotknięciu i zostawia go na ostatnio dotkniętym
   elemencie. Przy przewijaniu karuzeli palcem stan przeskakiwał z kafla
   na kafel i każdy z nich puchł o 4,5 % przez 600 ms — bloczki drgały.
   Kadra miała tę osłonę od początku, ta reguła nie.                     */
@media (hover: hover) {
  .photo img { transition: transform 600ms var(--ease-out); }
  .photo:hover img { transform: scale(1.045); }
}

/* Pas pełnoekranowy oddycha — bardzo powolny dryf kadru, tak żeby
   zdjęcie żyło jak woda, a nie żeby zwracało na siebie uwagę. */
.pas-foto img { animation: dryf-kadru 26s var(--ease-in-out, ease-in-out) infinite alternate; }
@keyframes dryf-kadru {
  from { transform: scale(1.06) translate3d(-0.8%, 0, 0); }
  to   { transform: scale(1.12) translate3d(0.8%, -1%, 0); }
}

/* Pasek postępu przewijania pod przyklejonym nagłówkiem */
.scroll-progress {
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 2px;
  overflow: hidden;
  pointer-events: none;
}
.scroll-progress i {
  display: block;
  height: 100%;
  background: var(--brand);
  transform: scaleX(var(--progress, 0));
  transform-origin: left center;
  transition: transform 90ms linear;
}

/* Pętla jest teraz bez szwu (komplet kopii slajdów po obu stronach taśmy),
   więc dawne wygaszanie toru przy przeskoku nie jest już potrzebne.        */

/* Kotwice celują w nagłówek sekcji, nie w jej górną krawędź — inaczej po
   kliknięciu w menu u góry ekranu zostawało puste pole na całą wysokość
   wewnętrznego marginesu sekcji.                                            */
.section[id] { scroll-margin-top: calc(1.5rem - var(--section-y)); }
.section--tight[id] { scroll-margin-top: calc(1.5rem - clamp(1.75rem, 4vw, 3rem)); }
.info-band[id] { scroll-margin-top: calc(1.5rem - clamp(2.25rem, 5vw, 3.5rem)); }
/* Slajdy zajęć siedzą już wewnątrz sekcji — im wystarczy zwykły odstęp. */
.class-block[id] { scroll-margin-top: 0; }

/* „O nas" ma się zmieścić w jednym ekranie telefonu po kliknięciu w menu.
   Dlatego na wąskich ekranach ta jedna sekcja dostaje własny, ciaśniejszy
   rytm, a zdjęcie sali pokazuje się dopiero od tabletu — zdjęć jest na
   stronie dużo w innych miejscach, a tutaj liczy się tekst.                 */
@media (max-width: 47.99rem) {
  .section--compact {
    padding-block: var(--space-6);
    scroll-margin-top: calc(1.5rem - var(--space-6));
  }
  .section--compact .split { row-gap: var(--space-5); }
  .section--compact .eyebrow { margin-bottom: var(--space-2); }
  .section--compact .h2 { font-size: 1.5rem; line-height: 1.15; }
  .section--compact .prose { margin-top: var(--space-4); font-size: 0.9375rem; line-height: 1.6; }
  .section--compact .prose p { margin-bottom: 0.7em; }
  .section--compact .pillars {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-4);
    margin-top: var(--space-5);
  }
  .section--compact .pillar b { font-size: 1rem; }
  .section--compact .pillar span { font-size: 0.8125rem; line-height: 1.45; }
  .section--compact .photo { display: none; }
}

/* Dwie kolumny filarów mają sens dopiero, gdy w kolumnie mieści się zdanie.
   Poniżej 480 px kolumna schodzi do ok. 130–160 px, czyli 18–20 znaków
   w wierszu — tekst rozsypuje się na pięć poszarpanych linijek. Jedna
   kolumna daje ok. 40 znaków przy niemal tej samej wysokości bloku.      */
@media (max-width: 29.99rem) {
  .section--compact .pillars { grid-template-columns: minmax(0, 1fr); }
}

/* == 18. GĘSTOŚĆ NA TELEFONIE ============================================
   Strona jest długa z natury (cztery opisy zajęć i osiem biogramów), więc
   na małym ekranie skracamy wszystko, co nie jest treścią: wysokie kadry,
   nadmiarowe odstępy i zbyt luźne pola formularza.                          */
@media (max-width: 47.99rem) {

  /* Zajęcia bez zdjęć. Każdy slajd to i tak trzy akapity opisu, a kadr
     zjadał pół ekranu i odsuwał treść. Zdjęcia tych samych zajęć są
     w galerii, więc nic nie przepada. Slajd schudł z 1041 do 599 px.    */
  .class-block__media { display: none; }

  /* Urodziny bez zdjęcia — z tego samego powodu. W jednej kolumnie kadr
     4:5 zajmował ponad 400 px, a pod nim i tak trzeba przewinąć cennik.
     Kolonie zdjęcia zachowują: tam obrazki NIOSĄ treść („zdjęcia najlepiej
     pokazują, jak wyglądają nasze wspólne wakacje”), przy urodzinach
     konkret jest w cenniku.                                             */
  .oferta__zdjecia--jedno { display: none; }

  /* Slajdy mają wysokość najwyższego z nich, a `align-content: center`
     spychał krótsze opisy w dół — nagłówki startowały na 4, 17, 69 i 87 px
     od góry toru, więc przy przewijaniu tytuł skakał. Do góry, równo.    */
  .class-block { align-content: start; }


  /* Portret trenerki — mniejszy kadr, bo obok i tak idą dwa akapity */
  .coach .photo { max-width: 11rem; }

  /* Sale: kadr panoramiczny zamiast wysokiego */
  .location .photo { --ratio: 2 / 1; }

  /* Pole wiadomości: cztery wiersze zamiast sześciu */
  .field textarea { min-height: 7rem; }

  /* Puste karty opinii nie muszą być tak wysokie */
  .review--empty { min-height: 7.5rem; }

  /* Pas kontaktowy: kolumny bliżej siebie */
  .info-band { padding-block: var(--space-7); }
  .info-band__grid { gap: var(--space-6); }

  /* Zapisy to główna akcja strony — na telefonie też muszą być widoczne od
     razu, bez otwierania menu. Miejsce robimy zwężając blok z logotypem.    */
  .site-header__bar { gap: var(--space-3); }
  .brand { gap: 0.5rem; }
  .brand__mark { width: 2.1rem; height: 2.1rem; }
  .brand__name b { font-size: 0.9375rem; }
  .brand__name span { display: none; }
  .header-cta { padding: 0.5rem 0.85rem; font-size: 0.75rem; letter-spacing: 0.04em; }

  /* Plakietki wieku: ciaśniej, żeby mieściły się w dwóch rzędach zamiast trzech */
  .tags { gap: 0.35rem; margin-top: var(--space-4); }
  .tags li { padding: 0.25rem 0.6rem; font-size: 0.75rem; letter-spacing: 0.04em; }
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-delay: 0ms !important;      /* bez tego kaskada w hero migałaby */
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  .js .reveal { opacity: 1; transform: none; }
  .photo:hover img { transform: none; }
  .chmura, .fala svg, .kaustyka, .promienie, .babelek { animation: none !important; }
  .pas-foto img { animation: none !important; transform: scale(1.06); }
  .babelek { opacity: 0.35; }
}

@media print {
  .site-header, .mobile-nav, .hero__silks, .page-hero__silks, .skip-link { display: none !important; }
  .efekt, .pas-foto, .carousel__arrow, .progress { display: none !important; }
  /* Na papierze gradient nieba i wody zjadłby tusz i czytelność tekstu */
  .section, .hero, .page-hero, .info-band, .pas-foto {
    background: #FFFFFF !important;
    color: #000000 !important;
  }
  .strefa--jasna, .strefa--zanurzenie, .strefa--glebia {
    --heading: #000000;
    --on-surface: #000000;
    --muted: #333333;
    --accent: #000000;
    --rule: #999999;
    --karta: transparent;
    --karta-obrys: #999999;
    --gwiazdka: #000000;   /* złoto jest nieczytelne na bieli wydruku */
  }
  .js .reveal { opacity: 1 !important; transform: none !important; }
}

/* == 19. NIEBO I OCEAN — WARSTWA EFEKTÓW =================================
   Wszystko jest dekoracją: aria-hidden, bez przechwytywania kliknięć,
   wyłącznie transform i opacity, i wszystko gaśnie przy „ogranicz ruch".
   Efekty siedzą pod treścią (z-index 1), treść ma z-index 10.             */

.efekt {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  overflow: hidden;
}
.section > .container,
.hero > .container { position: relative; z-index: var(--z-raised); }

/* --- Słońce nad horyzontem --- */
.slonce {
  position: absolute;
  top: -30%;
  right: -10%;
  width: min(40rem, 90vw);
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(closest-side,
    rgba(255, 255, 255, 0.9),
    rgba(255, 250, 225, 0.4) 45%,
    rgba(255, 255, 255, 0) 72%);
}

/* --- Chmury: płyną w poprzek nieba, każda w swoim tempie --- */
/* --- Sylwetka chmury -----------------------------------------------------
   Prawdziwy cumulus ma kilkanaście kłębów różnej wielkości wzdłuż krawędzi.
   Trzy gładkie elipsy tego nie oddadzą, więc bryły dokładamy `box-shadow`-em:
   każdy cień to kopia okręgu przesunięta i zmniejszona spreadem. Rozmycie
   jest umiarkowane — przy mocnym kłęby zlewały się z powrotem w mgłę.

   Cienie liczone są w `em`, a `font-size` chmury skaluje się z szerokością
   okna, więc bryły rosną razem z nią.                                     */
.chmura {
  position: absolute;
  left: 0;
  border-radius: 50%;
  background: #FFFFFF;
  font-size: clamp(0.55rem, 1.1vw, 1rem);
  filter: blur(7px);
  box-shadow:
     1.7em  0.30em 0 -0.20em #FFFFFF,
    -1.6em  0.45em 0 -0.28em #FFFFFF,
     3.1em  0.70em 0 -0.50em #FFFFFF,
    -3.0em  0.80em 0 -0.55em #FFFFFF,
     0.8em -0.45em 0 -0.30em #FFFFFF,
    -0.9em -0.30em 0 -0.26em #FFFFFF,
     2.3em -0.10em 0 -0.42em #FFFFFF,
    -2.2em  0.05em 0 -0.38em #FFFFFF,
     4.2em  0.95em 0 -0.72em #FFFFFF,
    -4.1em  1.00em 0 -0.74em #FFFFFF;
}
.chmura::before,
.chmura::after {
  content: "";
  position: absolute;
  border-radius: 50%;
  background: #FFFFFF;
}
.chmura::before {
  left: 4%; top: -38%; width: 46%; height: 92%;
  box-shadow: 1.5em 0.5em 0 -0.35em #FFFFFF, -1.2em 0.7em 0 -0.45em #FFFFFF;
}
.chmura::after {
  right: 6%; top: -18%; width: 38%; height: 74%;
  box-shadow: -1.3em 0.4em 0 -0.3em #FFFFFF, 1.1em 0.6em 0 -0.42em #FFFFFF;
}

/* Nie skrótem `animation:` — ma wyższą specyficzność niż `.chmura--N`
   i zerował im `animation-duration`, przez co wszystkie chmury stały
   nieruchomo w lewym rogu sekcji.                                     */
.js .chmura {
  animation-name: plynie;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
}
@keyframes plynie {
  from { transform: translateX(-35vw); }
  to   { transform: translateX(120vw); }
}

/* Sekcja: hero — ujemne opóźnienie ustawia chmurę w losowym punkcie jej
   własnego przelotu, więc strona otwiera się na niebie w ruchu.
   UWAGA: fazy (delay/duration) NIE mogą rosnąć razem z `top` — przy ruchu
   liniowym daje to chmury ustawione w równą ukośną linię. Tu są celowo
   przetasowane względem wysokości. */
.chmura--1  { top:  8%; width:  22.0rem; height:  6.0rem; opacity: 0.72; animation-duration: 95s; animation-delay: -59s; }
.chmura--2  { top: 19%; width:  12.0rem; height:  3.4rem; opacity: 0.60; animation-duration: 120s; animation-delay: -13s; }
.chmura--3  { top: 31%; width:  28.0rem; height:  7.0rem; opacity: 0.40; animation-duration: 175s; animation-delay: -152s; }
.chmura--4  { top: 43%; width:   9.0rem; height:  2.8rem; opacity: 0.66; animation-duration: 88s; animation-delay: -30s; }
.chmura--5  { top: 55%; width:  17.0rem; height:  5.0rem; opacity: 0.46; animation-duration: 150s; animation-delay: -8s; }
.chmura--6  { top: 64%; width:  24.0rem; height:  6.2rem; opacity: 0.34; animation-duration: 200s; animation-delay: -142s; }
.chmura--7  { top: 73%; width:  11.0rem; height:  3.2rem; opacity: 0.58; animation-duration: 105s; animation-delay: -29s; }
.chmura--8  { top: 84%; width:  20.0rem; height:  5.4rem; opacity: 0.42; animation-duration: 135s; animation-delay: -127s; }
.chmura--9  { top: 92%; width:  14.0rem; height:  4.0rem; opacity: 0.50; animation-duration: 160s; animation-delay: -75s; }

/* Sekcja: o-nas — ujemne opóźnienie ustawia chmurę w losowym punkcie jej
   własnego przelotu, więc strona otwiera się na niebie w ruchu.
   UWAGA: fazy (delay/duration) NIE mogą rosnąć razem z `top` — przy ruchu
   liniowym daje to chmury ustawione w równą ukośną linię. Tu są celowo
   przetasowane względem wysokości. */
.chmura--10 { top:  6%; width:  20.0rem; height:  5.5rem; opacity: 0.62; animation-duration: 120s; animation-delay: -23s; }
.chmura--11 { top: 17%; width:  12.0rem; height:  3.4rem; opacity: 0.52; animation-duration: 165s; animation-delay: -137s; }
.chmura--12 { top: 28%; width:  27.0rem; height:  7.0rem; opacity: 0.36; animation-duration: 210s; animation-delay: -86s; }
.chmura--13 { top: 39%; width:  15.0rem; height:  4.2rem; opacity: 0.56; animation-duration: 105s; animation-delay: -69s; }
.chmura--14 { top: 50%; width:   8.0rem; height:  2.6rem; opacity: 0.66; animation-duration: 82s; animation-delay: -2s; }
.chmura--15 { top: 61%; width:  22.0rem; height:  5.8rem; opacity: 0.32; animation-duration: 185s; animation-delay: -98s; }
.chmura--16 { top: 71%; width:  13.0rem; height:  3.6rem; opacity: 0.48; animation-duration: 140s; animation-delay: -127s; }
.chmura--17 { top: 81%; width:  18.0rem; height:  4.8rem; opacity: 0.40; animation-duration: 155s; animation-delay: -40s; }
.chmura--18 { top: 90%; width:  10.0rem; height:  3.0rem; opacity: 0.58; animation-duration: 98s; animation-delay: -73s; }

/* Sekcja: zajecia — ujemne opóźnienie ustawia chmurę w losowym punkcie jej
   własnego przelotu, więc strona otwiera się na niebie w ruchu.
   UWAGA: fazy (delay/duration) NIE mogą rosnąć razem z `top` — przy ruchu
   liniowym daje to chmury ustawione w równą ukośną linię. Tu są celowo
   przetasowane względem wysokości. */
.chmura--19 { top:  7%; width:  18.0rem; height:  5.0rem; opacity: 0.52; animation-duration: 140s; animation-delay: -108s; }
.chmura--20 { top: 17%; width:  10.0rem; height:  3.0rem; opacity: 0.46; animation-duration: 96s; animation-delay: -34s; }
.chmura--21 { top: 27%; width:  24.0rem; height:  6.2rem; opacity: 0.30; animation-duration: 195s; animation-delay: -16s; }
.chmura--22 { top: 37%; width:  13.0rem; height:  3.8rem; opacity: 0.36; animation-duration: 128s; animation-delay: -74s; }
.chmura--23 { top: 47%; width:   7.0rem; height:  2.4rem; opacity: 0.50; animation-duration: 158s; animation-delay: -145s; }
.chmura--24 { top: 57%; width:  21.0rem; height:  5.6rem; opacity: 0.26; animation-duration: 175s; animation-delay: -40s; }
.chmura--25 { top: 66%; width:  11.0rem; height:  3.2rem; opacity: 0.40; animation-duration: 112s; animation-delay: -55s; }
.chmura--26 { top: 76%; width:  16.0rem; height:  4.4rem; opacity: 0.30; animation-duration: 150s; animation-delay: -99s; }
.chmura--27 { top: 86%; width:   9.0rem; height:  2.8rem; opacity: 0.44; animation-duration: 124s; animation-delay: -17s; }

/* --- Tafla wody: dwie fale przesuwają się w przeciwne strony --- */
/* Ścieżka fali jest domknięta do dołu (`v40H0z`), więc SVG maluje pełny
   blok barwy pod linią wody. Bez maski jego dolna krawędź kończyła się
   prostą linią w poprzek sekcji — właśnie to widać było jako „odcięcie".
   Maska wygasza ten blok, zanim dojdzie do dołu.                        */
.fala {
  position: absolute;
  top: -1px;
  left: 0;
  right: 0;
  height: clamp(44px, 6vw, 88px);
  z-index: 2;
  pointer-events: none;
  overflow: hidden;
  --maska-fali: linear-gradient(180deg,
    rgba(0, 0, 0, 1) 0%,
    rgba(0, 0, 0, 1) 34%,
    rgba(0, 0, 0, 0.45) 68%,
    rgba(0, 0, 0, 0) 100%);
  -webkit-mask-image: var(--maska-fali);
  mask-image: var(--maska-fali);
}
.fala svg {
  position: absolute;
  top: 0;
  left: 0;
  width: 200%;
  height: 100%;
  color: var(--niebo-3);
}
.js .fala svg { animation: przesuw linear infinite; }
@keyframes przesuw {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}
.fala svg:nth-child(1) { opacity: 0.55; animation-duration: 24s; }
.fala svg:nth-child(2) { opacity: 0.35; animation-duration: 38s; animation-direction: reverse; }

/* --- Refleksy świetlne tuż pod taflą --- */
.kaustyka {
  position: absolute;
  inset: 0;
  opacity: 0.55;
  mix-blend-mode: soft-light;
  background:
    radial-gradient(58% 30% at 20% 26%, rgba(255, 255, 255, 0.6), transparent 62%),
    radial-gradient(44% 24% at 72% 52%, rgba(255, 255, 255, 0.5), transparent 64%),
    radial-gradient(50% 22% at 42% 82%, rgba(255, 255, 255, 0.42), transparent 62%);
}
.js .kaustyka { animation: falowanie 16s ease-in-out infinite alternate; }
@keyframes falowanie {
  from { transform: translate3d(-2%, 0, 0) scale(1.02); }
  to   { transform: translate3d(2%, 1.5%, 0) scale(1.07); }
}

/* --- Promienie światła wpadające pod wodę --- */
.promienie {
  position: absolute;
  inset: -15% 0 auto;
  height: 115%;
  opacity: 0.3;
  background:
    linear-gradient(173deg, rgba(255, 255, 255, 0.55) 0 3%, transparent 3.8%),
    linear-gradient(177deg, rgba(255, 255, 255, 0.4) 0 2%, transparent 2.8%),
    linear-gradient(169deg, rgba(255, 255, 255, 0.3) 0 4%, transparent 4.8%);
  background-repeat: no-repeat;
  background-position: 14% 0, 48% 0, 80% 0;
  background-size: 42% 100%, 34% 100%, 46% 100%;
}
.js .promienie { animation: chwianie 20s ease-in-out infinite alternate; }
@keyframes chwianie {
  from { transform: translateX(-3%) skewX(-1deg); }
  to   { transform: translateX(3%) skewX(1.5deg); }
}

/* --- Bąbelki wznoszące się ku powierzchni --- */
.babelek {
  position: absolute;
  bottom: -8%;
  border-radius: 50%;
  background: radial-gradient(circle at 32% 28%,
    rgba(255, 255, 255, 0.9),
    rgba(255, 255, 255, 0.2) 58%,
    rgba(255, 255, 255, 0.05));
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.28);
  opacity: 0;
}
.js .babelek { animation: wznosi ease-in-out infinite; }
/* Bąbelek nie płynie po prostej — w połowie drogi odbija w drugą stronę,
   więc tor jest wężykiem, tak jak w wodzie.                              */
@keyframes wznosi {
  0%   { transform: translate3d(0, 0, 0) scale(0.85); opacity: 0; }
  10%  { opacity: 0.5; }
  32%  { transform: translate3d(calc(var(--dryf, 2rem) * 0.85), calc(-0.28 * var(--droga, 50rem)), 0) scale(1.02); }
  58%  { transform: translate3d(calc(var(--dryf, 2rem) * -0.45), calc(-0.56 * var(--droga, 50rem)), 0) scale(1.07); }
  80%  { transform: translate3d(calc(var(--dryf, 2rem) * 0.7), calc(-0.8 * var(--droga, 50rem)), 0) scale(1.11); }
  85%  { opacity: 0.35; }
  100% { transform: translate3d(var(--dryf, 2rem), calc(-1 * var(--droga, 50rem)), 0) scale(1.15); opacity: 0; }
}
.babelek:nth-child(1) { left:  9%; width:  9px; height:  9px; animation-duration: 19s; animation-delay:  -3s; --dryf: 2.5rem; --droga: 46rem; }
.babelek:nth-child(2) { left: 24%; width:  5px; height:  5px; animation-duration: 26s; animation-delay: -11s; --dryf: -2rem;  --droga: 52rem; }
.babelek:nth-child(3) { left: 41%; width: 13px; height: 13px; animation-duration: 16s; animation-delay:  -7s; --dryf: 3.5rem; --droga: 40rem; }
.babelek:nth-child(4) { left: 58%; width:  7px; height:  7px; animation-duration: 23s; animation-delay: -15s; --dryf: -3rem;  --droga: 50rem; }
.babelek:nth-child(5) { left: 74%; width: 11px; height: 11px; animation-duration: 21s; animation-delay:  -2s; --dryf: 2rem;   --droga: 44rem; }
.babelek:nth-child(6) { left: 89%; width:  6px; height:  6px; animation-duration: 29s; animation-delay: -18s; --dryf: -1.5rem;--droga: 54rem; }



/* == 20. KADRA — KARTA, KTÓRA ZAMIENIA SIĘ W TEKST =======================
   Slajd trzyma stałe proporcje 4:5. W środku leżą dwie „strony" na tym
   samym miejscu: zdjęcie i opis. Kliknięcie przełącza widoczną stronę.
   Strona ukryta ma `visibility: hidden`, więc znika też dla czytnika
   ekranu i nie da się na nią wejść tabulatorem.
   Bez JavaScriptu obie strony są po prostu pod sobą — opis jest wtedy
   widoczny od razu i nic nie przepada.                                  */

/* `width: min()` zamiast `width: 100%` + `max-width`: przy tym drugim
   automatyczne marginesy wychodziły zerowe i karta lgnęła do lewej
   krawędzi toru zamiast stanąć na środku.                             */
/* `justify-self` zamiast `margin-inline: auto` — automatyczne marginesy
   w tym gridzie wychodziły zerowe i karta lgnęła do lewej krawędzi toru
   zamiast stanąć na środku.                                            */
.coach {
  scroll-snap-align: start;
  width: min(100%, 26rem);
  justify-self: center;
}

/* Bez sztywnych proporcji: wysokość karty wyznacza najdłuższy biogram,
   a zdjęcie ją wypełnia. Dzięki temu opisu nigdy nie trzeba przewijać. */
.js .coach {
  position: relative;
  display: grid;
}
.js .coach__strona {
  grid-area: 1 / 1;
  min-width: 0;
  border-radius: var(--r-lg);
  overflow: hidden;
}
.js .coach__strona--foto { position: relative; }
.js .coach__strona--foto .photo { aspect-ratio: auto; width: 100%; height: 100%; margin: 0; border-radius: 0; }
/* Kadr bywa wysoki (na telefonie ok. 3:5), więc trzymamy głowę w górnej
   części zdjęcia, zamiast wycinać ją przy środkowaniu. */
.js .coach__strona--foto .photo img { object-position: 50% 28%; }

/* Przełączanie: przenikanie z lekkim uniesieniem. Strona schowana
   wypada z drzewa dostępności (visibility), więc nie ma duchów w TAB-ie. */
.js .coach__strona {
  opacity: 1;
  visibility: visible;
  transform: none;
  transition: opacity 260ms var(--ease-out), transform 260ms var(--ease-out), visibility 0s;
}
.js .coach__strona[hidden] {
  display: grid;                 /* [hidden] chowamy sami, płynnie */
  opacity: 0;
  visibility: hidden;
  transform: translateY(0.6rem);
  transition: opacity 200ms var(--ease-out), transform 200ms var(--ease-out), visibility 0s linear 200ms;
  pointer-events: none;
}

/* Przycisk na zdjęciu — cała powierzchnia klikalna, nazwisko u dołu */
.js .coach__przycisk {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: flex-end;
  gap: 0.15rem;
  width: 100%;
  padding: 2.5rem 0.9rem 0.85rem;
  border: 0;
  border-radius: var(--r-lg);
  background: linear-gradient(180deg, rgba(4, 34, 54, 0) 45%, rgba(4, 34, 54, 0.88) 100%);
  color: #FFFFFF;
  font-family: var(--font-body);
  font-size: 0.9375rem;
  font-weight: 600;
  line-height: 1.3;
  text-align: left;
  cursor: pointer;
}
.js .coach__przycisk:focus-visible { outline: 3px solid var(--focus); outline-offset: -3px; }
.js .coach__przycisk .coach__imie { transition: transform 200ms var(--ease-out); }

/* Podpowiedź, że kafel się otwiera. Nie każdy zgadnie, że zdjęcie jest
   klikalne — sam obrazek niczego nie obiecuje. `aria-hidden`, bo przycisk
   ma już ukrytą etykietę „— pokaż opis" dla czytnika ekranu; bez tego
   ta sama informacja czytana byłaby dwa razy.                            */
.js .coach__zacheta {
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  /* Biel na 78 % zamiast osobnego koloru: gradient pod spodem jest ciemny
     i tak, a jaśniejszy odcień oddzieliłby podpowiedź od nazwiska. */
  color: rgba(255, 255, 255, 0.78);
}
@media (hover: hover) {
  .js .coach__przycisk:hover .coach__imie { transform: translateY(-0.15rem); }
  .js .coach__strona--foto img { transition: transform 500ms var(--ease-out); }
  .js .coach__przycisk:hover ~ .photo img,
  .js .coach__strona--foto:hover img { transform: scale(1.04); }
}

/* Strona z opisem — panel, który przewija się w środku, gdy tekst nie mieści */
.js .coach__strona--tekst {
  display: grid;
  align-content: start;
  gap: 0.15rem;
  padding: clamp(1rem, 3vw, 1.4rem);
  border: 1px solid var(--karta-obrys);
  background: var(--karta);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
.js .coach__strona--tekst .coach__text { font-size: 0.875rem; }
.js .coach__wroc {
  justify-self: start;
  margin-top: var(--space-3);
  min-height: 2.875rem;   /* 2,75rem wychodziło 43,99 px — poniżej progu 44 */
  padding: 0.5rem 1.1rem;
  border: 1px solid var(--rule);
  border-radius: var(--r-pill);
  background: transparent;
  color: var(--heading);
  font-family: var(--font-body);
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  cursor: pointer;
  transition: border-color 160ms var(--ease-out), background 160ms var(--ease-out);
}
.js .coach__wroc:hover { border-color: var(--accent); background: rgba(255, 255, 255, 0.08); }
.js .coach__wroc:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }

/* Bez JS: zdjęcie i opis jedno pod drugim, przyciski niepotrzebne */
.coach__przycisk, .coach__wroc { display: none; }
.js .coach__przycisk { display: flex; }
.js .coach__wroc { display: inline-flex; align-items: center; }
.coach__strona--foto .photo { --ratio: 4 / 5; }
.coach__strona--tekst { margin-top: var(--space-3); }

@media (prefers-reduced-motion: reduce) {
  .js .coach__strona { transition: none !important; }
  .js .coach__przycisk .coach__imie,
  .js .coach__strona--foto img { transition: none !important; }
}

/* Na najwęższych telefonach ten sam biogram potrzebuje o wiele więcej
   wierszy, przez co karta (a więc i zdjęcie) robi się bardzo wysoka.
   Drobniejszy stopień skraca ją, nie schodząc poniżej czytelnych 13 px. */
@media (max-width: 26rem) {
  .js .coach__strona--tekst { padding: 0.9rem; gap: 0; }
  .js .coach__strona--tekst .coach__text { font-size: 0.8125rem; line-height: 1.5; }
  .js .coach__strona--tekst .coach__text p { margin-bottom: 0.55em; }
  .js .coach__strona--tekst .coach__name { font-size: 1.0625rem; }
}

/* Bąbelki 7–12 — gęstsza smuga w głębi. Każdy ma własny tor, tempo
   i opóźnienie, żeby nie było widać rytmu.                              */
.babelek:nth-child(7)  { left:  4%; width:  8px; height:  8px; animation-duration: 24s; animation-delay:  -9s; --dryf: -2.5rem; --droga: 48rem; }
.babelek:nth-child(8)  { left: 17%; width: 12px; height: 12px; animation-duration: 18s; animation-delay: -14s; --dryf: 3rem;    --droga: 42rem; }
.babelek:nth-child(9)  { left: 33%; width:  6px; height:  6px; animation-duration: 27s; animation-delay:  -5s; --dryf: -1.5rem; --droga: 56rem; }
.babelek:nth-child(10) { left: 50%; width: 10px; height: 10px; animation-duration: 20s; animation-delay: -21s; --dryf: 2.5rem;  --droga: 45rem; }
.babelek:nth-child(11) { left: 66%; width:  5px; height:  5px; animation-duration: 30s; animation-delay: -12s; --dryf: -3.5rem; --droga: 58rem; }
.babelek:nth-child(12) { left: 82%; width:  9px; height:  9px; animation-duration: 22s; animation-delay:  -6s; --dryf: 2rem;    --droga: 50rem; }


/* Styk hero z sekcją „O nas": pas rozmycia narastający ku dołowi.
   `backdrop-filter` rozmywa to, co jest pod spodem (zdjęcie i gradient),
   a maska sprawia, że efekt wchodzi stopniowo, zamiast zaczynać się
   twardą krawędzią. Pas siedzi pod treścią (z-index 1, treść ma 10)
   i poniżej napisów, więc niczego nie przykrywa.                        */
.hero__rozmycie {
  position: absolute;
  inset: auto 0 0 0;
  /* Niższy niż napisy: przy 22vh pas wchodził na podpis i rozmywał mu
     dolne krawędzie liter.                                            */
  height: clamp(5rem, 16vh, 11rem);
  z-index: 1;
  pointer-events: none;
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  /* Rozmycie musi też WYGASNĄĆ przed dolną krawędzią hero. Gdy sięgało
     do 100 %, tło było rozmyte nad linią styku i ostre pod nią — i sam
     pas robił się widoczną krawędzią.                                  */
  --maska-rozm: linear-gradient(180deg,
    rgba(0, 0, 0, 0) 0%,
    rgba(0, 0, 0, 0.5) 40%,
    rgba(0, 0, 0, 1) 72%,
    rgba(0, 0, 0, 0.55) 90%,
    rgba(0, 0, 0, 0) 100%);
  -webkit-mask-image: var(--maska-rozm);
  mask-image: var(--maska-rozm);
  background: linear-gradient(180deg,
    rgba(205, 234, 251, 0) 0%,
    rgba(205, 234, 251, 0.55) 62%,
    var(--niebo-2) 100%);
}
@media (prefers-reduced-motion: reduce) {
  .hero__rozmycie { backdrop-filter: none; -webkit-backdrop-filter: none; }
}

/* Zdjęcie sali przy Bałtyckiej jest pionowe (3:4) w kadrze poziomym (16:10),
   więc `cover` pokazuje tylko środkowy pas. Przesunięcie w górę mieści w nim
   cały baner z logo, zamiast ucinać mu górę.                             */
.location .photo img[src$="sala-baltycka.jpg"] { object-position: 50% 42%; }

/* Warstwa efektów ma `overflow: hidden`, więc chmura sięgająca krawędzi
   sekcji była ścinana płaską linią. Przesuwanie chmur nie rozwiązuje tego
   na stałe: wysokość sekcji zależy od okna, więc przy niższym ekranie
   ucinałaby się inna. Zamiast tego warstwa wygasza się przy górnej i dolnej
   krawędzi — chmura po prostu rozpływa się, zanim dojdzie do cięcia.

   Maska tylko tam, gdzie są chmury: promienie w „Kadrze" i bąbelki niżej
   mają wychodzić z samej krawędzi i nie wolno ich przygaszać.            */
.efekt:has(.chmura) {
  --maska-efektu: linear-gradient(180deg,
    rgba(0, 0, 0, 0) 0%,
    rgba(0, 0, 0, 1) 8%,
    rgba(0, 0, 0, 1) 92%,
    rgba(0, 0, 0, 0) 100%);
  -webkit-mask-image: var(--maska-efektu);
  mask-image: var(--maska-efektu);
}
