/* =========================================================
   Pan Pieseł — style.css
   Źródło prawdy dla UI: DESIGN.md v1.0 (zamrożony 02.09.2026).
   Poprzedni kierunek (design-system.md v3, playful/graficzny —
   Bricolage Grotesque + Manrope, mocne kolory, grube obrysy) jest
   NIEAKTUALNY. Wszystkie sekcje homepage są już przebudowane pod
   DESIGN.md v1.0 (etapy 1–10). Etap 12A (global cleanup) usunął z
   :root stare tokeny kolorów/kontenera/radiusów, które nie miały już
   żadnego aktywnego użycia (--cream, --charcoal, --pink, --pink-dark,
   --yellow, --aqua, --blush, --ink, --container-w, --container-w-wide,
   --r-sm, --r-md, --r-lg). Pozostałe aktywne stare referencje (jest
   ich niewiele) są opisane w TASKS.md wraz z uzasadnieniem, dlaczego
   zostały — to celowe, zgłoszone wyjątki, nie przeoczenia.
   ========================================================= */

:root {
  --r-pill: 999px;

  --ease: cubic-bezier(.22,.68,.24,1);

  --section-pad: 56px;

  /* ---------- Fonty — przełączone na docelowe już teraz ---------- */
  --font-display: 'Fraunces', Georgia, serif;
  --font-body: 'DM Sans', Arial, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;

  /* ---------- NOWE TOKENY — DESIGN.md v1.0 ---------- */
  --color-bg: #F1F1F3;
  --color-surface: #FFFFFF;
  --color-surface-alt: #E7E7EA;
  --color-ink: #222126;
  --color-text: #4F4B53;
  --color-muted: #746F78;
  --color-line: #D4D1D7;

  --color-fuchsia: #D52D8B;
  --color-fuchsia-hover: #B92373;
  --color-fuchsia-soft: #F9DCEA;

  --color-aqua: #46CFC8;
  --color-aqua-soft: #D9F4F2;

  --color-yellow: #F2DF46;
  --color-yellow-soft: #FBF5BF;

  /* Dodane etapem 17F.3 dla hover 3 sytuacji klienta w hero — kolory
     jawnie podane wprost w poleceniu (pomarańcz / pudrowy róż),
     nie istniały wcześniej w palecie. */
  --color-orange: #F0923D;
  --color-orange-soft: #FBE3CC;
  --color-orange-hover: #FF7A1F;

  --color-powder-pink: #E8AAB4;
  --color-powder-pink-soft: #FBE9EC;
  --color-powder-pink-hover: #FF8FAE;

  /* Wariant hover żółtego (etap 17F.5) — sam --color-yellow jest już
     jasny/nasycony, "neonowy" efekt to głównie mocniejsze nasycenie
     względem dotychczasowego bardzo jasnego --color-yellow-soft. */
  --color-yellow-hover: #FFDD00;

  --color-graphite: #232127;
  --color-white: #FFFFFF;

  /* Jedyny nowy token spoza DESIGN.md §5.1 — dodany w etapie 15, bo
     §13 "Formularze" wprost wymaga czerwonego komunikatu błędu, a
     system kolorów nie miał dotąd czerwieni. Kontrast na bieli
     zweryfikowany: ~6.5:1 (WCAG AA dla zwykłego tekstu). */
  --color-error: #B3261E;

  --container: 1200px;
  --container-text: 760px;
  --gutter-desktop: 32px;
  --gutter-tablet: 24px;
  --gutter-mobile: 18px;

  --section-space-desktop: 112px;
  --section-space-tablet: 88px;
  --section-space-mobile: 68px;

  --radius-sm: 14px;
  --radius-md: 24px;
  --radius-lg: 36px;
  --radius-pill: 999px;

  --border-width: 1px;
  --border-color: var(--color-line);
  --shadow-elevated: 0 18px 48px rgba(28, 24, 31, 0.08);
  --shadow-none: none;

  /* Skala typografii, desktop (DESIGN.md §6.2); mobile via clamp(), patrz §6.3 */
  --fs-hero: clamp(4rem, 7vw, 6.5rem);
  --fs-h2: clamp(2.625rem, 5vw, 4.25rem);
  --fs-h3: clamp(2rem, 3vw, 2.5rem);
  --fs-lead: clamp(1.1875rem, 1.6vw, 1.3125rem);
  --fs-body: clamp(1rem, 1.2vw, 1.125rem);
  --fs-button: clamp(0.875rem, 1vw, 1rem);
  --fs-eyebrow: clamp(0.6875rem, 0.8vw, 0.75rem);

  /* Breakpointy robocze (DESIGN.md §16) — dokumentacyjne;
     CSS nie pozwala użyć var() w warunku @media, więc @media
     w tym pliku nadal używają literalnych px zgodnych z tymi wartościami. */
  --bp-mobile: 480px;
  --bp-tablet: 768px;
  --bp-small-desktop: 1050px;
  --bp-wide: 1280px;
}

@media (min-width: 768px) { :root { --section-pad: 84px; } }
@media (min-width: 1024px) { :root { --section-pad: 120px; } }
@media (min-width: 1440px) { :root { --section-pad: 136px; } }

/* ---------- Reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  margin: 0;
  background: var(--color-bg);
  color: var(--color-ink);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.6;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
}
@media (min-width: 768px) { body { font-size: 17px; } }
@media (min-width: 1024px) { body { font-size: 18px; } }
@media (min-width: 1440px) { body { font-size: 19px; } }

img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
ul, ol { margin: 0; padding: 0; list-style: none; }
h1, h2, h3, h4, p, blockquote, figure { margin: 0; }
button { font: inherit; background: none; border: none; cursor: pointer; color: inherit; }
sup { font-size: .6em; }

.wrap {
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: 24px;
}
@media (min-width: 768px) { .wrap { padding-inline: 40px; } }
@media (min-width: 1280px) { .wrap { padding-inline: 64px; } }

.skip-link {
  position: absolute;
  left: -999px;
  top: 0;
  background: var(--color-fuchsia);
  color: var(--color-white);
  font-weight: 700;
  padding: 14px 22px;
  border-radius: 0 0 10px 0;
  z-index: 1000;
}
.skip-link:focus { left: 0; }

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

section { padding-block: var(--section-pad); position: relative; }

/* ---------- Type ---------- */
.eyebrow {
  font-family: var(--font-body);
  font-weight: 800;
  font-size: var(--fs-eyebrow);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--color-muted);
}
.eyebrow span { color: var(--color-muted); font-weight: 700; letter-spacing: .1em; }

.section-heading {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(2.3rem, 4vw, 4.6rem);
  line-height: 1.02;
  color: var(--color-ink);
  letter-spacing: -.02em;
  /* etap 17F.6 — nagłówki nie mają łamać się na 3 linie tylko dlatego,
     że element ma niepotrzebnie wąską szerokość; naturalne 2 linie
     zostają, ale bez wymuszania krótszych łamań niż to konieczne. */
  word-break: normal;
  overflow-wrap: normal;
  hyphens: none;
  text-wrap: balance;
}
.section-heading--onlight { color: var(--color-white); }
.section-heading--onphoto { color: var(--color-white); max-width: 20ch; }

em, strong { font-family: inherit; }

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  flex-shrink: 0;
  white-space: nowrap;
  font-family: var(--font-body);
  font-weight: 800;
  font-size: 15px;
  padding: 15px 28px;
  border-radius: var(--r-pill);
  transition: transform .18s var(--ease), background-color .18s var(--ease), box-shadow .18s var(--ease), color .18s var(--ease);
  min-height: 48px;
  border: 2px solid transparent;
}
/* .btn ustawia display:inline-flex, więc bije domyślne [hidden]{display:none}
   przeglądarki (ta sama specyficzność, reguła autorska zawsze wygrywa) -
   ten sam, wcześniej już znaleziony wzorzec błędu co .field/.field__error
   (etap 15) i .pricing-group (etap 32). Jawny override raz, dla całego
   .btn w każdym miejscu, gdzie kod ustawia .hidden na przycisku
   (np. panel/dyspozycyjnosc - stan zamknięty ukrywa CTA zapisu). */
.btn[hidden] { display: none; }
.btn--large { font-size: 16px; padding: 18px 34px; min-height: 56px; }
.btn--small { padding: 11px 20px; font-size: 13px; min-height: 40px; }
.btn__arrow { width: 16px; height: 16px; flex-shrink: 0; transition: transform .18s var(--ease); }

.btn--primary { background: var(--color-fuchsia); color: var(--color-white); }
.btn--primary:hover, .btn--primary:focus-visible {
  background: var(--color-fuchsia-hover);
  color: var(--color-white);
  transform: translateY(-3px);
  box-shadow: 0 14px 28px -10px rgba(30,26,26,.4);
}
.btn--primary:hover .btn__arrow { transform: translateX(4px); }

.btn--outline {
  background: transparent;
  color: var(--color-ink);
  border-width: var(--border-width);
  border-color: var(--color-line);
}
.btn--outline:hover, .btn--outline:focus-visible {
  background: var(--color-fuchsia);
  border-color: var(--color-fuchsia);
  color: var(--color-white);
  transform: translateY(-3px);
}

/* =========================================================
   LOCATION BAR + HEADER
   DESIGN.md §12.1 — pasek lokalizacji nad headerem; header sticky,
   jasny, subtelny blur dopiero po scrollu; logo w całości; maks.
   5 linków + 1 CTA na desktopie; sticky ≤ ~88px wysokości.
   ========================================================= */
.location-bar {
  background: var(--color-graphite);
  color: var(--color-white);
  text-align: center;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 12px;
  letter-spacing: .02em;
  padding: 9px 12px;
}
@media (min-width: 768px) { .location-bar { font-size: 13px; } }

.site-header {
  background: var(--color-surface);
  border-bottom: var(--border-width) solid var(--color-line);
  position: sticky;
  top: 0;
  z-index: 200;
  transition: box-shadow .2s var(--ease), background-color .2s var(--ease);
}
.site-header.is-scrolled {
  background: rgba(255, 255, 255, .92);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  box-shadow: 0 12px 24px -18px rgba(34, 33, 38, .18);
}

.header-inner, .hero-inner {
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter-mobile);
}
@media (min-width: 768px) { .header-inner, .hero-inner { padding-inline: var(--gutter-tablet); } }
@media (min-width: 1280px) { .header-inner, .hero-inner { padding-inline: var(--gutter-desktop); } }

.header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  min-height: 76px;
}
@media (min-width: 1280px) { .header-inner { min-height: 84px; } }

/* Etap 17C: header nie ma już podpisu "trening i behawior" — logo samo
   ma nieść markę, więc przeszliśmy z małej wersji zbiorczej (ikona+napis
   w kwadracie) na assets/logo-pan-piesel-wordmark.png (sam kolorowy
   napis, format poziomy) w większym rozmiarze niż poprzednio. */
.wordmark { display: flex; align-items: center; flex-shrink: 0; gap: 8px; }
/* Ikona psa + wordmark obok siebie, etap 17F.6A — zastępuje pojedynczy
   niemal-kwadratowy plik logo-pan-piesel.png z etapu 17F.6, w którym
   ograniczenie wysokością ściskało tekst do nieczytelności (ten sam
   problem, co przy dawnym wordmark-only w stopce). Oba assety istniały
   już w projekcie nieużywane — łączymy je flexboxem, bez tworzenia
   nowego pliku/logo i bez zmiany typografii/proporcji żadnego z nich. */
.wordmark__icon { height: 38px; width: auto; max-width: 100%; object-fit: contain; display: block; }
.wordmark__logo { height: 30px; width: auto; max-width: 100%; object-fit: contain; display: block; }
@media (min-width: 768px) { .wordmark__icon { height: 44px; } .wordmark__logo { height: 34px; } }
@media (min-width: 1280px) { .wordmark__icon { height: 46px; } .wordmark__logo { height: 36px; } }

.header-actions { display: flex; align-items: center; gap: 12px; flex-shrink: 0; }
.header-cta { display: none; }

.menu-toggle {
  width: 44px;
  height: 44px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 5px;
  border-radius: var(--radius-sm);
  flex-shrink: 0;
  transition: background-color .15s var(--ease);
}
.menu-toggle:hover, .menu-toggle:focus-visible { background: var(--color-surface-alt); }
.menu-toggle span {
  width: 20px;
  height: 2px;
  background: var(--color-ink);
  transition: transform .2s var(--ease), opacity .2s var(--ease);
}
.menu-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.menu-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.menu-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

.nav-scrim {
  position: fixed;
  inset: 0;
  background: rgba(34, 33, 38, .45);
  z-index: 150;
}
.nav-scrim[hidden] { display: none; }

@media (max-width: 1279px) {
  .site-nav {
    position: fixed;
    top: 0; right: 0; bottom: 0;
    width: min(360px, 88vw);
    background: var(--color-surface);
    border-left: var(--border-width) solid var(--color-line);
    box-shadow: -24px 0 48px -24px rgba(34, 33, 38, .18);
    padding: 96px 28px 32px;
    transform: translateX(100%);
    transition: transform .28s var(--ease);
    overflow-y: auto;
    z-index: 200;
  }
  .site-nav.is-open { transform: translateX(0); }
  .site-nav__list { display: flex; flex-direction: column; gap: 4px; margin-bottom: 28px; }
  .site-nav__list a {
    font-family: var(--font-display);
    font-size: 26px;
    font-weight: 600;
    display: block;
    padding-block: 8px;
    color: var(--color-ink);
  }
  .site-nav__cta { display: inline-flex; }
}

@media (min-width: 1280px) {
  .menu-toggle { display: none; }
  .header-cta { display: inline-flex; }
  .site-nav { display: flex; align-items: center; gap: 28px; }
  .site-nav__list { display: flex; gap: 22px; }
  .site-nav__list a {
    font-size: 15px;
    font-weight: 600;
    white-space: nowrap;
    color: var(--color-ink);
    transition: color .15s var(--ease);
    position: relative;
  }
  .site-nav__list a::after {
    content: "";
    position: absolute;
    left: 0; right: 0; bottom: -4px;
    height: 2px;
    background: var(--color-fuchsia);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform .18s var(--ease);
  }
  .site-nav__list a:hover::after, .site-nav__list a:focus-visible::after { transform: scaleX(1); }
  .site-nav__cta { display: none; }
}
@media (min-width: 1440px) {
  .site-nav { gap: 34px; }
  .site-nav__list { gap: 28px; }
  .site-nav__list a { font-size: 16px; }
}

/* body scroll lock while mobile menu open */
body.menu-open { overflow: hidden; }

/* =========================================================
   HERO — PHOTO ONLY (etap 17F.6) — dogs-on-sofa.jpg jako tło sekcji
   zdjęciowej, H1 wyrównany do GÓRY zdjęcia (dawniej do dołu — zmiana
   17F.6, żeby pasować do nowej kolejności: zdjęcie → biała sekcja
   "Co najlepiej..." → kafle, patrz .hero-choices niżej). Na mobile
   zdjęcie NIE jest croppowane, patrz media query (max-width:767px).
   ========================================================= */
.hero { position: relative; overflow: hidden; padding-top: 40px; padding-bottom: 40px; min-height: 480px; display: flex; align-items: flex-start; }
@media (min-width: 768px) { .hero { min-height: 560px; padding-top: 56px; padding-bottom: 56px; } }
@media (min-width: 1024px) { .hero { min-height: 620px; } }

.hero__bg { position: absolute; inset: 0; z-index: 0; }
.hero__bg img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 38%; display: block; }
/* delikatny gradient wyłącznie od góry (gdzie teraz siedzi H1) —
   zastępuje dawny gradient od dołu, bo tekst przeniósł się na górę
   zdjęcia (etap 17F.6). Zdjęcie poniżej zostaje w pełni odsłonięte. */
.hero__bg::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(20,17,16,.34) 0%, rgba(20,17,16,.06) 40%, rgba(20,17,16,0) 60%);
}

.hero-inner { position: relative; z-index: 1; width: 100%; }

/* Mobile: zdjęcie w naturalnych proporcjach, bez przycinania (etap
   17F.6 — wymóg "widać WSZYSTKIE psy z kanapy"). .hero__bg wraca do
   normalnego przepływu (nie position:absolute), więc .hero rośnie do
   wysokości zdjęcia; H1 zostaje nałożony na górę przez position:absolute
   na .hero-inner, niezależnie od faktycznej wysokości obrazu. */
@media (max-width: 767px) {
  .hero { min-height: 0; padding: 0; display: block; overflow: visible; }
  .hero__bg { position: static; }
  .hero__bg img { position: static; width: 100%; height: auto; object-fit: initial; object-position: initial; }
  .hero__bg::after { content: none; }
  .hero-inner { position: absolute; top: 0; left: 0; right: 0; padding: 20px var(--gutter-mobile) 0; }
}

/* ---------- Headline bezpośrednio na zdjęciu (etap 17F.3) ----------
   Zastępuje wcześniejszy frosted .hero__panel (białą kartę z eyebrow +
   H1 + lead, etap 17F) — na zdjęciu ma zostać wyłącznie mocny headline,
   biały z czarną obwódką, bez karty/tła/dodatkowego tekstu. Lokalizacje
   (dawny .hero__eyebrow) i lead nie mają dziś innego miejsca na
   homepage — świadomie usunięte z hero, nie przeniesione gdzie indziej
   (poza zakresem tej poprawki, patrz CLAUDE.md/TASKS.md). */
.hero__heading--onphoto {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(2.4rem, 7vw, 5rem);
  line-height: 1.18;
  letter-spacing: -.01em;
  color: var(--color-white);
  -webkit-text-stroke: 1.5px var(--color-graphite);
  text-stroke: 1.5px var(--color-graphite);
  paint-order: stroke fill;
  text-shadow: 0 2px 8px rgba(0, 0, 0, .3);
  max-width: 14ch;
  margin: 0;
}
/* Jedna linia od tabletu w górę (etap 17F.5) — mniejsza, dedykowana
   skala fontu (nie ta sama co mobile 2-liniowe clamp) + wymuszone
   nie-zawijanie, żeby "Opowiedz mi o swoim psie." zmieściło się w
   .hero-inner bez overflow na 768/1024/1440. */
@media (min-width: 768px) {
  .hero__heading--onphoto {
    font-size: clamp(2.4rem, 4.6vw, 4.4rem);
    white-space: nowrap;
    max-width: none;
    -webkit-text-stroke-width: 2px;
  }
  .hero__heading-break { display: none; }
}

/* ---------- "Co najlepiej opisuje Was dzisiaj?" + 3 kafle — biała
   sekcja pod zdjęciem hero (etap 17F.6, zastępuje wersję na zdjęciu z
   17F/17F.3/17F.5). Czyste białe tło gwarantuje czytelność niezależnie
   od treści fotografii nad nią. ---------- */
.hero-choices { background: var(--color-surface); padding-top: 40px; padding-bottom: var(--section-space-mobile); }
@media (min-width: 768px) { .hero-choices { padding-top: 48px; padding-bottom: var(--section-space-tablet); } }
@media (min-width: 1024px) { .hero-choices { padding-top: 56px; } }

.hero-choices__intro {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.15rem, 1.8vw, 1.5rem);
  color: var(--color-ink);
  margin-bottom: 20px;
}

.intent-list { display: flex; flex-direction: column; gap: 12px; max-width: 720px; }

.intent-choice {
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 18px 22px;
  border-radius: var(--radius-md);
  border: var(--border-width) solid var(--color-line);
  background: rgba(255, 255, 255, .96);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  box-shadow: 0 10px 28px -14px rgba(20, 17, 16, .35);
  transition: border-color .18s var(--ease), background-color .18s var(--ease), transform .18s var(--ease);
}
.intent-choice:hover, .intent-choice:focus-visible, .intent-choice:active {
  border-color: var(--color-ink);
  transform: translateX(4px);
}
.intent-choice__dot { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; }
.intent-choice--orange .intent-choice__dot { background: var(--color-orange); }
.intent-choice--yellow .intent-choice__dot { background: var(--color-yellow); }
.intent-choice--pink .intent-choice__dot { background: var(--color-powder-pink); }
/* Mocniejsze, bardziej nasycone kolory hover/focus/active (etap 17F.5)
   — poprzednie -soft warianty oceniono jako za delikatne. Tekst na
   tych tłach przechodzi na --color-ink (zamiast --color-text) na
   hover, żeby zachować bardzo dobrą czytelność bez glow/efektów. */
.intent-choice--orange:hover, .intent-choice--orange:focus-visible, .intent-choice--orange:active { background: var(--color-orange-hover); }
.intent-choice--yellow:hover, .intent-choice--yellow:focus-visible, .intent-choice--yellow:active { background: var(--color-yellow-hover); }
.intent-choice--pink:hover, .intent-choice--pink:focus-visible, .intent-choice--pink:active { background: var(--color-powder-pink-hover); }
.intent-choice:hover .intent-choice__desc, .intent-choice:focus-visible .intent-choice__desc, .intent-choice:active .intent-choice__desc { color: var(--color-ink); }

.intent-choice__body { display: flex; flex-direction: column; gap: 4px; flex: 1; min-width: 0; }
.intent-choice__title { font-family: var(--font-display); font-weight: 600; font-size: clamp(1.02rem, 1.5vw, 1.2rem); color: var(--color-ink); line-height: 1.2; }
.intent-choice__desc { font-size: .86em; line-height: 1.4; color: var(--color-text); transition: color .18s var(--ease); }
.intent-choice__arrow { width: 18px; height: 18px; flex-shrink: 0; color: var(--color-ink); transition: transform .18s var(--ease); }
.intent-choice:hover .intent-choice__arrow, .intent-choice:focus-visible .intent-choice__arrow, .intent-choice:active .intent-choice__arrow { transform: translateX(4px); }

@media (min-width: 640px) {
  .intent-choice { padding: 20px 26px; }
  .intent-choice__desc { max-width: 44ch; }
}

/* Desktop: 3 zbliżone do kwadratu kafle w jednym rzędzie (etap 18) —
   zastępuje poziome rzędy z mobile/tablet tylko od 1024px. Mobile/tablet
   układ (flex column, wiersze) zostaje BEZ ZMIAN — jawne polecenie
   "na telefonie obecna forma jest dobra". */
@media (min-width: 1024px) {
  .intent-list { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; max-width: none; }
  .intent-choice {
    flex-direction: column;
    align-items: flex-start;
    justify-content: space-between;
    aspect-ratio: 1 / 1;
    padding: 32px 30px;
    gap: 20px;
  }
  .intent-choice__dot { width: 12px; height: 12px; }
  .intent-choice__body { gap: 10px; }
  .intent-choice__title { font-size: clamp(1.15rem, 1.6vw, 1.35rem); }
  .intent-choice__desc { max-width: none; }
  .intent-choice__arrow { align-self: flex-end; }
  .intent-choice:hover, .intent-choice:focus-visible, .intent-choice:active { transform: translateY(-4px); }
}

/* =========================================================
   "MA BYĆ WAM PO PROSTU ŁATWIEJ ŻYĆ RAZEM" (etap 17D — skrócone do
   jednego kompaktowego editorial bandu, bez card-chrome; poprzednia
   wersja z trzema pełnymi kartami — etap 17C — zastąpiona).
   ========================================================= */
.benefits { background: var(--color-aqua-soft); padding-block: var(--section-space-mobile); overflow: hidden; }
@media (min-width: 768px) { .benefits { padding-block: var(--section-space-tablet); } }
@media (min-width: 1024px) { .benefits { padding-block: var(--section-space-desktop); } }

.benefits__heading { max-width: 32ch; }
.benefits__lead { font-size: var(--fs-lead); line-height: 1.55; color: var(--color-text); max-width: 62ch; margin-top: 24px; }

.benefit-row { display: grid; gap: 28px; margin-top: 48px; }
.benefit-point { padding-top: 20px; border-top: 2px solid rgba(34, 33, 38, .14); }
.benefit-point__num { display: block; font-family: var(--font-display); font-weight: 600; font-size: 1.05rem; color: var(--color-ink); opacity: .5; margin-bottom: 10px; }
.benefit-point__title { font-family: var(--font-display); font-weight: 600; font-size: 1.2rem; color: var(--color-ink); margin-bottom: 8px; }
.benefit-point__text { font-size: .95em; line-height: 1.5; color: var(--color-text); }

@media (min-width: 768px) { .benefit-row { grid-template-columns: repeat(3, 1fr); gap: 32px; } }

/* =========================================================
   JAK MOŻEMY PRACOWAĆ? (etap 13) — DESIGN.md §12.4
   Trzy zróżnicowane kafle (nie identyczne białe SaaS cards, nie kopia
   kart "Od czego chcesz zacząć") — wspólny system (biała powierzchnia,
   cienka linia, radius-md), ale różny akcent koloru na każdym i lekki
   pionowy offset środkowego kafla dla odmiany rytmu.
   ========================================================= */
.work { background: var(--color-bg); padding-block: var(--section-space-mobile); }
@media (min-width: 768px) { .work { padding-block: var(--section-space-tablet); } }
@media (min-width: 1024px) { .work { padding-block: var(--section-space-desktop); } }

.work-tiles { display: grid; gap: 20px; margin-top: 48px; }
.work-tile {
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-line);
  border-radius: var(--radius-md);
  padding: 32px 28px;
}
.work-tile::before {
  content: "";
  display: block;
  height: 3px;
  width: 56px;
  border-radius: var(--radius-pill);
  margin-bottom: 24px;
}
.work-tile--a::before { background: var(--color-aqua); }
.work-tile--b::before { background: var(--color-fuchsia); }
.work-tile--c::before { background: var(--color-yellow); }

.work-tile__num {
  display: block;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(2.2rem, 3.5vw, 3rem);
  color: var(--color-line);
  line-height: 1;
  margin-bottom: 16px;
}
.work-tile h3 { font-family: var(--font-display); font-size: clamp(1.5rem, 2.2vw, 1.9rem); font-weight: 600; line-height: 1.1; color: var(--color-ink); margin-bottom: 14px; }
.work-tile p { font-size: 1em; line-height: 1.55; color: var(--color-text); }
.work-tile__note { margin-top: 12px; font-weight: 700; font-size: .85em; color: var(--color-muted); }
.work-tile__cta {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 18px;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: .85em;
  color: var(--color-ink);
}
.work-tile__cta svg { width: 14px; height: 14px; transition: transform .18s var(--ease); }
.work-tile__cta:hover, .work-tile__cta:focus-visible { color: var(--color-fuchsia); }
.work-tile__cta:hover svg, .work-tile__cta:focus-visible svg { transform: translateX(3px); }

/* Rozszerzenia .work-tile dla pełnej treści /szkolenia/ (etap 18) —
   badge trybu pracy, lista cech/sytuacji, wiersz z dwoma CTA. Homepage
   nadal używa samego podstawowego .work-tile (num/h3/p/note/cta), te
   klasy są dla niego martwym, nieużywanym CSS — nic tu nie zmienia
   wyglądu istniejących kafli homepage. */
.work-tile__badge {
  display: inline-flex;
  align-items: center;
  padding: 4px 14px;
  margin-bottom: 16px;
  border-radius: var(--radius-pill);
  background: var(--color-aqua-soft);
  color: var(--color-ink);
  font-family: var(--font-body);
  font-weight: 700;
  font-size: .76em;
  letter-spacing: .02em;
}
.work-tile__list { display: flex; flex-direction: column; gap: 8px; margin: 16px 0; }
.work-tile__list li { position: relative; padding-left: 20px; font-size: .92em; line-height: 1.5; color: var(--color-text); }
.work-tile__list li::before { content: ""; position: absolute; left: 0; top: .55em; width: 6px; height: 6px; border-radius: 50%; background: var(--color-fuchsia); }
.work-tile__cta-row { display: flex; flex-wrap: wrap; align-items: center; gap: 20px; margin-top: 18px; }
.work-tile__cta-row .work-tile__cta { margin-top: 0; }

/* Krótki lead pod H2 "Jak możemy pracować?" na /szkolenia/ (etap 18) —
   homepage nie ma tego akapitu, klasa tam nieużywana. */
.work__lead { font-size: var(--fs-lead); line-height: 1.55; color: var(--color-text); max-width: 62ch; margin-top: 20px; }

/* Wariant .work-tiles na 2 kolumny (etap 19, /klasy/ i /obrona/) — moduły
   "pies-pies"/"pies-człowiek" itp. Reużywa dokładnie .work-tile (karta,
   akcent, h3, p), tylko inna liczba kolumn na desktopie. */
@media (min-width: 768px) { .work-tiles.work-tiles--2 { grid-template-columns: repeat(2, 1fr); } }

/* =========================================================
   /KLASY/, /OBRONA/ (etap 19) — podstrony w tym samym kierunku
   wizualnym co homepage/szkolenia, zero nowego systemu designu.
   ========================================================= */
/* Hero z zdjęciem obok tekstu (reużywa .apply-hero__heading/__text/
   __actions/__link z /szkolenia/, .eyebrow, .btn — tylko układ 2-kolumnowy
   i kadr zdjęcia są nowe, oparte o --radius-lg i istniejące zdjęcia
   assets/communication-classes.jpg, assets/sport-defense.jpg). */
.subpage-hero { background: var(--color-bg); padding-block: var(--section-space-mobile); }
@media (min-width: 768px) { .subpage-hero { padding-block: var(--section-space-tablet); } }
.subpage-hero__grid { display: grid; gap: 32px; align-items: center; }
@media (min-width: 1024px) { .subpage-hero__grid { grid-template-columns: 1fr 1fr; gap: 56px; } }
.subpage-hero__photo { border-radius: var(--radius-lg); overflow: hidden; aspect-ratio: 16 / 10; margin: 0; }
.subpage-hero__photo img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Uniwersalna sekcja treściowa (etap 19) — H2 + opcjonalny .work__lead +
   opcjonalna .work-tile__list/.work-tiles, naprzemienne tło z istniejących
   tokenów dla rytmu kolorystycznego (DESIGN.md), bez nowych kolorów. */
.info-section { padding-block: var(--section-space-mobile); }
@media (min-width: 768px) { .info-section { padding-block: var(--section-space-tablet); } }
@media (min-width: 1024px) { .info-section { padding-block: var(--section-space-desktop); } }
.info-section--bg { background: var(--color-bg); }
.info-section--surface { background: var(--color-surface); }
.info-section--aqua { background: var(--color-aqua-soft); }
.info-section--yellow { background: var(--color-yellow-soft); }

@media (min-width: 768px) { .work-tiles { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1024px) { .work-tile--b { margin-top: -20px; padding-top: 48px; padding-bottom: 48px; } }

/* Informacja o zapisie bezpośrednim na Klasy/Obronę (etap 18) —
   zastępuje dawny .work-callout (fuksjowy box+ikona+border, etap 17F.6),
   uznany za zbyt bannerowy/niejasny co do tego, czego dotyczy. Zwykły
   tekst BEZ boxa/tła/ramki, bezpośrednio nad kartami Klasy/Obrona — sama
   bliskość ma tłumaczyć relację. Współdzielone z homepage i /szkolenia/.
   Homepage: <p><strong>...</strong> ...</p>. /szkolenia/ (osobna sekcja,
   wymaga własnego H2 dla hierarchii H1→H2→H3): .direct-booking-note__heading. */
.direct-booking-note { margin-top: 32px; max-width: 64ch; }
.direct-booking-note p { font-size: 1.02em; line-height: 1.5; color: var(--color-ink); }
.direct-booking-note strong { font-weight: 800; }
.direct-booking-note__heading {
  font-family: var(--font-body);
  font-weight: 800;
  font-size: 1.02em;
  line-height: 1.5;
  color: var(--color-ink);
  margin-bottom: 2px;
}

/* /szkolenia/ (etap 18): Klasy/Obrona jako OSOBNA sekcja (nie zagnieżdżona
   w .work jak na homepage) — jawne polecenie tego etapu. Naprzemienne tło
   względem .work (--color-bg) dla zachowania rytmu kolorystycznego. */
.work-direct { background: var(--color-surface); padding-block: var(--section-space-mobile); }
@media (min-width: 768px) { .work-direct { padding-block: var(--section-space-tablet); } }
@media (min-width: 1024px) { .work-direct { padding-block: var(--section-space-desktop); } }

/* etap 17F — Klasy komunikacji / Obrona jako widoczne, fotograficzne
   moduły WEWNĄTRZ tej samej sekcji oferty (nie osobna sekcja) */
.work-specialties { display: grid; gap: 20px; margin-top: 28px; }
@media (min-width: 768px) { .work-specialties { grid-template-columns: 1fr 1fr; gap: 24px; } }

.work-specialty { background: var(--color-surface); border-radius: var(--radius-lg); overflow: hidden; border: var(--border-width) solid var(--color-line); }
.work-specialty__photo { aspect-ratio: 16 / 10; margin: 0; }
.work-specialty__photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.work-specialty__copy { padding: 24px 24px 28px; }
.work-specialty__accent { display: block; height: 4px; width: 52px; border-radius: var(--radius-pill); margin-bottom: 16px; background: var(--color-fuchsia); }
.work-specialty__accent--aqua { background: var(--color-aqua); }
.work-specialty__title { font-family: var(--font-display); font-weight: 600; font-size: clamp(1.3rem, 2vw, 1.6rem); color: var(--color-ink); margin-bottom: 10px; }
.work-specialty__text { font-size: .98em; line-height: 1.5; color: var(--color-text); }
.work-specialty__cta-row { display: flex; flex-wrap: wrap; align-items: center; gap: 18px; margin-top: 18px; }
.work-specialty__link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: .88em;
  color: var(--color-ink);
}
.work-specialty__link svg { width: 14px; height: 14px; transition: transform .18s var(--ease); }
.work-specialty__link:hover, .work-specialty__link:focus-visible { color: var(--color-fuchsia); }
.work-specialty__link:hover svg, .work-specialty__link:focus-visible svg { transform: translateX(3px); }

/* =========================================================
   CENNIK CTA (etap 17E) — zastępuje ceny pokazywane bezpośrednio przy
   formach współpracy. Jeden wyraźny pas, nie kolejna duża sekcja.
   ========================================================= */
.pricing-cta { background: var(--color-fuchsia-soft); padding-block: 80px; }
@media (min-width: 1024px) { .pricing-cta { padding-block: 100px; } }
.pricing-cta__inner {
  display: flex;
  flex-direction: column;
  gap: 20px;
}
@media (min-width: 640px) { .pricing-cta__inner { flex-direction: row; align-items: center; justify-content: space-between; gap: 32px; } }
.pricing-cta__heading { font-family: var(--font-display); font-weight: 600; font-size: clamp(1.4rem, 2.2vw, 1.8rem); color: var(--color-ink); margin-bottom: 4px; }
.pricing-cta__text { font-size: .95em; color: var(--color-text); }
.pricing-cta .btn--primary { flex-shrink: 0; }

/* =========================================================
   CO SIĘ TERAZ DZIEJE? (etap 17C §15-18) — komponent wydarzeń, dziś
   zawsze pusty/hidden (patrz komentarz w index.html i EVENTS w
   script.js). Style przygotowane pod przyszłe realne dane.
   ========================================================= */
.events { background: var(--color-yellow-soft); padding-block: var(--section-space-mobile); }
@media (min-width: 768px) { .events { padding-block: var(--section-space-tablet); } }
@media (min-width: 1024px) { .events { padding-block: var(--section-space-desktop); } }

.events__grid { display: grid; gap: 20px; margin-top: 40px; }
@media (min-width: 768px) { .events__grid { grid-template-columns: repeat(var(--events-cols, 1), 1fr); } }

.event-card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 28px 26px;
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-line);
  border-radius: var(--radius-md);
}
.event-card__type { font-family: var(--font-body); font-weight: 800; font-size: 12px; letter-spacing: .06em; text-transform: uppercase; color: var(--color-fuchsia); }
.event-card__title { font-family: var(--font-display); font-weight: 600; font-size: clamp(1.2rem, 2vw, 1.5rem); color: var(--color-ink); }
.event-card__meta { font-size: .9em; color: var(--color-muted); font-weight: 600; }
.event-card__desc { font-size: .95em; color: var(--color-text); line-height: 1.5; }
.event-card__cta { margin-top: 10px; font-weight: 700; color: var(--color-ink); display: inline-flex; align-items: center; gap: 6px; }

.events__more { margin-top: 32px; }
.events__more a {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  font-weight: 700;
  color: var(--color-ink);
}
.events__more a:hover, .events__more a:focus-visible { color: var(--color-fuchsia); }

/* =========================================================
   OPINIE (etap 13) — DESIGN.md §12.7. Kompozycja "unoszących się"
   karteczek zamiast slidera: wszystkie widoczne naraz, różne wielkości,
   lekka rotacja/asymetria (CSS columns = naturalna masonry bez JS),
   miękkie cienie, subtelne pionowe unoszenie (translate, niezależne od
   statycznej rotacji na transform). prefers-reduced-motion wyłącza
   unoszenie całkowicie. Mobile: pojedyncza kolumna = czytelny strumień.
   ========================================================= */
.testimonials { position: relative; padding-top: 140px; padding-bottom: 64px; scroll-margin-top: 96px; }
@media (min-width: 1024px) { .testimonials { padding-top: 168px; padding-bottom: 80px; } }
.testimonials__bg { position: absolute; inset: 0; background: url("assets/testimonials-background.jpg") center 30% / cover no-repeat; }
.testimonials__bg::after { content: ""; position: absolute; inset: 0; background: linear-gradient(165deg, rgba(20,17,16,.82), rgba(20,17,16,.6) 55%, rgba(20,17,16,.85)); }
.testimonials__inner { position: relative; z-index: 1; }
.testimonials .section-heading { margin-bottom: 40px; }

.quote-cloud {
  margin-top: 48px;
  column-count: 1;
  column-gap: 24px;
}
@media (min-width: 640px) { .quote-cloud { column-count: 2; } }
@media (min-width: 1100px) { .quote-cloud { column-count: 3; column-gap: 28px; } }

.quote-card {
  display: inline-block;
  width: 100%;
  break-inside: avoid;
  margin-bottom: 24px;
  background: var(--color-surface);
  border-radius: var(--radius-md);
  padding: 28px 26px;
  box-shadow: 0 16px 32px -14px rgba(20, 17, 16, .2);
}
.quote-card--featured { padding: 36px 32px; }

/* lekkie, zróżnicowane rotacje — delikatna asymetria, nie chaos */
.quote-card--a { transform: rotate(-1deg); }
.quote-card--b { transform: rotate(1.2deg); }
.quote-card--c { transform: rotate(-0.8deg); }
.quote-card--d { transform: rotate(1deg); }
.quote-card--e { transform: rotate(-1.3deg); }
.quote-card--f { transform: rotate(0.7deg); }
@media (max-width: 639px) { .quote-card { transform: none !important; } }

.quote-card p {
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 500;
  font-size: clamp(1.1rem, 2vw, 1.4rem);
  line-height: 1.35;
  color: var(--color-ink);
  margin-bottom: 18px;
}
.quote-card--featured p { font-size: clamp(1.25rem, 2.6vw, 1.9rem); }
@media (max-width: 479px) {
  .quote-card p { font-size: 1.05rem; line-height: 1.42; }
}
.quote-card footer { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.quote-card cite { font-style: normal; font-family: var(--font-body); font-weight: 700; color: var(--color-ink); }
.quote-card footer span { font-size: .85em; color: var(--color-muted); font-weight: 600; }

/* delikatne unoszenie — niezależne od statycznej rotacji dzięki
   CSS Individual Transform Properties (translate osobno od transform) */
@media (prefers-reduced-motion: no-preference) {
  .quote-card--a { animation: quote-float 7.5s ease-in-out .1s infinite; }
  .quote-card--b { animation: quote-float 8.5s ease-in-out .6s infinite; }
  .quote-card--c { animation: quote-float 6.8s ease-in-out 1.1s infinite; }
  .quote-card--d { animation: quote-float 9s ease-in-out .3s infinite; }
  .quote-card--e { animation: quote-float 7.8s ease-in-out .8s infinite; }
  .quote-card--f { animation: quote-float 8.2s ease-in-out 1.4s infinite; }
  @keyframes quote-float {
    0%, 100% { translate: 0 0; }
    50% { translate: 0 -8px; }
  }
}
@media (prefers-reduced-motion: reduce) {
  .quote-card { animation: none !important; }
}

/* =========================================================
   O MNIE (DESIGN.md §12.7)
   Zdjęcie 42–46% / treść 54–58% na desktopie; kwalifikacje jako ciche,
   uporządkowane tagi — element drugorzędny wizualnie, nie ściana
   certyfikatów. Hierarchia: główny opis (H2 + tekst) → CTA →
   kwalifikacje → nota prawna, w tej kolejności malejącej wagi.
   ========================================================= */
.about { background: var(--color-bg); padding-block: var(--section-space-mobile); }
@media (min-width: 768px) { .about { padding-block: var(--section-space-tablet); } }
@media (min-width: 1024px) { .about { padding-block: var(--section-space-desktop); } }

.about__grid { display: grid; gap: 40px; align-items: start; }
.about__photo {
  border-radius: var(--radius-lg);
  overflow: hidden;
  border: var(--border-width) solid var(--color-line);
  box-shadow: var(--shadow-elevated);
  aspect-ratio: 3 / 4;
}
/* etap 17F: było 4/5 + object-position 50% 20% — ucinało nogi w
   nienaturalnym miejscu (kadr skupiony zbyt wysoko na zdjęciu pełnej
   sylwetki). Zdjęcie asset/about-martyna-baldur.webp to Martyna z psem
   w pełnej sylwetce na chodniku (pion 1206×2117) — 3/4 (mniej agresywny
   crop niż 4/5) + object-position Y 38% pokazuje więcej dołu kadru,
   obejmując buty/nogi, kosztem odrobiny nieba nad czapką. */
.about__photo img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 38%; }
.about__eyebrow { margin-bottom: 6px; }
.about__text { font-size: clamp(1.05rem, 1.5vw, 1.3rem); line-height: 1.55; margin-top: 20px; max-width: 52ch; color: var(--color-text); }
.about__highlight {
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 700;
  font-size: clamp(1.4rem, 2.2vw, 1.9rem);
  line-height: 1.35;
  color: var(--color-fuchsia);
  margin-top: 24px;
  max-width: 46ch;
}
.about__copy .btn { margin-top: 32px; }

.about__more { margin-top: 64px; padding-top: 40px; border-top: var(--border-width) solid var(--color-line); }
.about__more-heading {
  font-family: var(--font-display);
  font-size: 1rem;
  font-weight: 600;
  color: var(--color-muted);
  margin-bottom: 20px;
}
.credentials {
  display: grid;
  gap: 16px 32px;
}
@media (min-width: 768px) { .credentials { grid-template-columns: 1fr 1fr; } }
.credentials li { display: flex; flex-direction: column; gap: 4px; }
.credentials__name { font-family: var(--font-display); font-weight: 600; font-size: 1.02rem; color: var(--color-ink); }
/* "Wkrótce" pozycja (etap 17F.6) — spójna z resztą listy, subtelnie
   wyróżniona kursywą + przygaszonym kolorem, nie osobnym badge'em. */
.credentials__name--soon { font-style: italic; color: var(--color-muted); font-weight: 500; }
.credentials__desc { font-family: var(--font-body); font-size: .85em; color: var(--color-muted); }
.disclaimer { margin-top: 20px; font-size: 12px; color: var(--color-muted); max-width: 60ch; }

/* etap 17D — wariant skrócony, użyty bezpośrednio w .about__copy (bez
   .about__more wrappera i bez nagłówka "Moje zaplecze"), lista pozioma
   zamiast siatki 2-kolumnowej z opisami pod każdą pozycją */
.credentials--compact { display: flex; flex-wrap: wrap; gap: 10px 24px; margin-top: 28px; }
.credentials--compact li { flex-direction: row; align-items: baseline; gap: 8px; }
.credentials--compact .credentials__name { font-size: .96rem; }
.credentials--compact .credentials__desc { font-size: .87em; }

@media (min-width: 1024px) { .about__grid { grid-template-columns: 4fr 5fr; gap: 64px; } }

/* =========================================================
   GROOMER — mały cross-sell blok (etap 17D, zastępuje pełną sekcję
   editorial 50/50 z etapu 12B/17C — groomer nie jest głównym celem
   homepage szkoleń, nie potrzebuje dużego zdjęcia ani rozbudowanego copy).
   ========================================================= */
.groomer-teaser {
  background: var(--color-surface);
  border-top: var(--border-width) solid var(--color-line);
  padding-block: 40px;
}
.groomer-teaser__inner {
  display: flex;
  flex-direction: column;
  gap: 20px;
}
@media (min-width: 640px) { .groomer-teaser__inner { flex-direction: row; align-items: center; justify-content: space-between; gap: 32px; } }

.groomer-teaser__heading { font-family: var(--font-display); font-weight: 600; font-size: clamp(1.3rem, 2vw, 1.6rem); color: var(--color-ink); margin-bottom: 4px; }
.groomer-teaser__text { font-size: .95em; color: var(--color-text); }

.groomer-teaser__cta-row { display: flex; flex-wrap: wrap; align-items: center; gap: 20px; flex-shrink: 0; }
.groomer-teaser__link { font-family: var(--font-body); font-weight: 700; font-size: .9em; color: var(--color-ink); }
.groomer-teaser__link:hover, .groomer-teaser__link:focus-visible { color: var(--color-fuchsia); }

@media (min-width: 1024px) {
  .groomer__grid { grid-template-columns: 4fr 5fr; gap: 64px; }
  .groomer__photo { order: 2; }
  .groomer__copy { order: 1; }
}

/* =========================================================
   FAQ
   ========================================================= */
/* DESIGN.md §12.8 — wstęp po lewej, accordion po prawej; cienkie linie
   1px zamiast kart; plus obraca się do × (rotacja 45°); fuksja tylko
   jako akcent hover/focus/otwartego stanu, nie kolor statyczny. */
/* Sekcja wysmuklona etapem 17F.6 — dawny wspólny --section-space-*
   token (68-112px) oceniony jako za duży dla FAQ, własny, mniejszy
   padding tylko tutaj. */
.faq { background: var(--color-bg); padding-block: 32px; }
@media (min-width: 768px) { .faq { padding-block: 48px; } }
@media (min-width: 1024px) { .faq { padding-block: 56px; } }

/* Ułożenie w jednej kolumnie na wszystkich szerokościach (etap 17F.6A)
   — zastępuje dawny 2-kolumnowy układ na desktopie (wstęp po lewej,
   accordion po prawej, od etapu 17D). Jawne nowe polecenie: eyebrow
   ma siedzieć BEZPOŚREDNIO nad accordionem, bez osobnej kolumny i bez
   pustej przestrzeni między nimi. */
.faq__grid { display: block; }
.faq__intro { margin-bottom: 20px; }

/* Mały eyebrow zamiast dawnego ogromnego section-heading (etap 17F.6),
   wielkość skorygowana etapem 18 — ma być TYLKO delikatnie większy od
   pytań accordionu, nie mały label. Hierarchia: heading > pytania >
   odpowiedzi. Desktop ~24px, mobile ~19px (patrz .accordion__trigger
   niżej dla porównania: ~19-21px desktop, ~17px mobile). */
.faq__eyebrow {
  font-family: var(--font-body);
  font-weight: 800;
  font-size: clamp(1.2rem, 2.6vw, 1.5rem);
  letter-spacing: 0;
  color: var(--color-fuchsia);
  line-height: 1.3;
  max-width: 34ch;
}

.accordion { border-top: var(--border-width) solid var(--color-line); }
.accordion__item { border-bottom: var(--border-width) solid var(--color-line); }
.accordion__trigger {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding-block: 16px;
  text-align: left;
  font-family: var(--font-display);
  font-size: clamp(1.0625rem, 1.6vw, 1.3rem);
  font-weight: 600;
  color: var(--color-ink);
}
.accordion__icon { width: 20px; height: 20px; flex-shrink: 0; color: var(--color-muted); transition: transform .22s var(--ease), color .18s var(--ease); }
.accordion__trigger:hover .accordion__icon,
.accordion__trigger:focus-visible .accordion__icon,
.accordion__trigger[aria-expanded="true"] .accordion__icon { color: var(--color-fuchsia); }
.accordion__trigger[aria-expanded="true"] .accordion__icon { transform: rotate(45deg); }
.accordion__trigger:hover span { text-decoration: underline; text-decoration-color: var(--color-fuchsia); text-decoration-thickness: 2px; text-underline-offset: 5px; }
.accordion__panel { padding-bottom: 16px; max-width: 68ch; }
.accordion__panel p { font-size: .92em; line-height: 1.55; color: var(--color-text); }
.accordion__panel p + p { margin-top: 10px; }
/* Linki wewnątrz odpowiedzi akordeonu (np. panel/zasady/) - globalny
   `a { color:inherit }` (reset u góry pliku) zostawiałby je wizualnie
   nieodróżnialne od zwykłego tekstu. */
.accordion__panel a { color: var(--color-fuchsia); font-weight: 700; }
.accordion__panel a:hover, .accordion__panel a:focus-visible { color: var(--color-fuchsia-hover); }

@media (prefers-reduced-motion: no-preference) {
  .accordion__panel:not([hidden]) { animation: faq-in .28s var(--ease); }
  @keyframes faq-in { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }
}

/* =========================================================
   FINAL CTA (DESIGN.md §12.11, etap 17C) — mocny fuksjowy blok
   (wcześniej grafitowy — grafit zarezerwowany teraz dla stopki, patrz
   DESIGN.md §12). Przycisk primary i link secondary dostają lokalne
   nadpisania, bo domyślny .btn--primary (fuksja na białym) i domyślny
   hover .final-cta__secondary (fuksja) znikałyby na fuksjowym tle.
   ========================================================= */
.final-cta {
  background: var(--color-fuchsia);
  text-align: center;
  padding-block: var(--section-space-mobile);
}
@media (min-width: 768px) { .final-cta { padding-block: var(--section-space-tablet); } }
@media (min-width: 1024px) { .final-cta { padding-block: var(--section-space-desktop); } }

.final-cta__inner { display: flex; flex-direction: column; align-items: center; }
.final-cta .eyebrow,
.final-cta .eyebrow span { color: rgba(255, 255, 255, .75); }
.final-cta__eyebrow { margin-bottom: 4px; }
.final-cta .section-heading { color: var(--color-white); }
.final-cta__text {
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 500;
  font-size: clamp(1.3rem, 2vw, 1.8rem);
  color: rgba(255, 255, 255, .92);
  margin-block: 22px 40px;
}

.final-cta .btn--primary {
  background: var(--color-white);
  color: var(--color-fuchsia);
}
.final-cta .btn--primary:hover, .final-cta .btn--primary:focus-visible {
  background: var(--color-ink);
  color: var(--color-white);
}
/* domyślny :focus-visible (fuksjowy outline) byłby niewidoczny na fuksjowym
   tle tej sekcji — biały outline zamiast tego, tylko tutaj */
.final-cta :focus-visible { outline-color: var(--color-white); }

.final-cta__row {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 20px;
}
@media (min-width: 480px) { .final-cta__row { flex-direction: row; justify-content: center; gap: 32px; } }

.final-cta__secondary {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 15px;
  color: rgba(255, 255, 255, .85);
  transition: color .18s var(--ease);
}
.final-cta__secondary svg { width: 16px; height: 16px; transition: transform .18s var(--ease); }
.final-cta__secondary:hover, .final-cta__secondary:focus-visible { color: var(--color-white); text-decoration: underline; }
.final-cta__secondary:hover svg, .final-cta__secondary:focus-visible svg { transform: translateX(3px); }

/* =========================================================
   FOOTER (etap 17F — całkowity redesign) — poprzednia wersja (DESIGN.md
   §12.10, etap 17C) oceniona jako za ciemna/ciasna/mało czytelna.
   Nadal grafit, ale: wyższy kontrast tekstu (.7→.82 opacity na tekście
   pomocniczym), większy font, znacznie więcej przestrzeni pionowej i
   poziomej, wyraźne nagłówki kolumn z cienką linią pod spodem (nie
   tylko waga fontu), pełne logo z psem większe niż poprzedni sam
   wordmark. Wysokość celowo NIE jest minimalizowana — czytelność ważniejsza.
   ========================================================= */
/* Wysmuklone etapem 17F.6 — logo usunięte (branding jest już widoczny
   w headerze, patrz .wordmark__logo), mniejsze paddingi/odstępy/fonty
   na całej stopce. Footer ma być lekki, nie kolejna duża sekcja. */
.site-footer { background: var(--color-graphite); color: var(--color-white); padding-top: 40px; }
.site-footer__inner { padding-bottom: 28px; border-bottom: var(--border-width) solid rgba(255, 255, 255, .2); }

.site-footer__location { color: rgba(255, 255, 255, .82); font-size: .9em; font-weight: 700; margin-bottom: 6px; }
.site-footer__address { color: rgba(255, 255, 255, .82); font-size: .9em; line-height: 1.5; margin: 10px 0 8px; }
.site-footer__social { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; margin-top: 10px; }
.site-footer__social a { margin: 0; min-height: 36px; display: inline-flex; align-items: center; }

/* Link Booksy w stopce jako klikalny obrazek (etap 18.2) — zastępuje
   oficjalny widget Booksy (etap 18), oceniony jako wizualnie niepasujący
   do stopki. assets/booksy.png (dostarczony asset), skalowany po
   wysokości, proporcje zachowane (bez deformacji), kompaktowy rozmiar
   dopasowany do rzędu ikon social. URL bez zmian — ten sam, którego
   projekt już używa (CTA "Sprawdź usługi / umów wizytę" w groomer-teaser). */
.site-footer__booksy-link { display: inline-flex; align-items: center; min-height: 36px; }
.site-footer__booksy-link img { height: 32px; width: auto; display: block; }

/* Ikony social media (etap 17F.6A) — prawdziwe assety dostarczone w projekcie
   (assets/instagram.svg, facebook.svg, tiktok.svg, Bootstrap Icons, fill="currentColor"),
   przebarwione na kolor footeru przez CSS mask zamiast inline SVG/sprite'a.
   Mask jako base64 data-URI (dokładna, niezmieniona zawartość tych samych
   plików assets/*.svg) — url(assets/*.svg) w mask-image jest blokowane przez
   CORS przy otwarciu strony bezpośrednio z dysku (protokół file://, origin
   "null"), co czyniło ikony niewidoczne przy takim uruchomieniu (wymóg
   projektu, patrz CLAUDE.md §3). Data-URI nie ma tego problemu. */
.social-icon { display: inline-block; width: 21px; height: 21px; background-color: rgba(255, 255, 255, .82); mask-repeat: no-repeat; mask-position: center; mask-size: contain; -webkit-mask-repeat: no-repeat; -webkit-mask-position: center; -webkit-mask-size: contain; transition: background-color .15s ease; }
.site-footer__social a:hover .social-icon,
.site-footer__social a:focus-visible .social-icon { background-color: var(--color-white); }
.social-icon--instagram { mask-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgZmlsbD0iY3VycmVudENvbG9yIiBjbGFzcz0iYmkgYmktaW5zdGFncmFtIiB2aWV3Qm94PSIwIDAgMTYgMTYiPgogIDxwYXRoIGQ9Ik04IDBDNS44MjkgMCA1LjU1Ni4wMSA0LjcwMy4wNDggMy44NS4wODggMy4yNjkuMjIyIDIuNzYuNDJhMy45IDMuOSAwIDAgMC0xLjQxNy45MjNBMy45IDMuOSAwIDAgMCAuNDIgMi43NkMuMjIyIDMuMjY4LjA4NyAzLjg1LjA0OCA0LjcuMDEgNS41NTUgMCA1LjgyNyAwIDguMDAxYzAgMi4xNzIuMDEgMi40NDQuMDQ4IDMuMjk3LjA0Ljg1Mi4xNzQgMS40MzMuMzcyIDEuOTQyLjIwNS41MjYuNDc4Ljk3Mi45MjMgMS40MTcuNDQ0LjQ0NS44OS43MTkgMS40MTYuOTIzLjUxLjE5OCAxLjA5LjMzMyAxLjk0Mi4zNzJDNS41NTUgMTUuOTkgNS44MjcgMTYgOCAxNnMyLjQ0NC0uMDEgMy4yOTgtLjA0OGMuODUxLS4wNCAxLjQzNC0uMTc0IDEuOTQzLS4zNzJhMy45IDMuOSAwIDAgMCAxLjQxNi0uOTIzYy40NDUtLjQ0NS43MTgtLjg5MS45MjMtMS40MTcuMTk3LS41MDkuMzMyLTEuMDkuMzcyLTEuOTQyQzE1Ljk5IDEwLjQ0NSAxNiAxMC4xNzMgMTYgOHMtLjAxLTIuNDQ1LS4wNDgtMy4yOTljLS4wNC0uODUxLS4xNzUtMS40MzMtLjM3Mi0xLjk0MWEzLjkgMy45IDAgMCAwLS45MjMtMS40MTdBMy45IDMuOSAwIDAgMCAxMy4yNC40MmMtLjUxLS4xOTgtMS4wOTItLjMzMy0xLjk0My0uMzcyQzEwLjQ0My4wMSAxMC4xNzIgMCA3Ljk5OCAwem0tLjcxNyAxLjQ0MmguNzE4YzIuMTM2IDAgMi4zODkuMDA3IDMuMjMyLjA0Ni43OC4wMzUgMS4yMDQuMTY2IDEuNDg2LjI3NS4zNzMuMTQ1LjY0LjMxOS45Mi41OTlzLjQ1My41NDYuNTk4LjkyYy4xMS4yODEuMjQuNzA1LjI3NSAxLjQ4NS4wMzkuODQzLjA0NyAxLjA5Ni4wNDcgMy4yMzFzLS4wMDggMi4zODktLjA0NyAzLjIzMmMtLjAzNS43OC0uMTY2IDEuMjAzLS4yNzUgMS40ODVhMi41IDIuNSAwIDAgMS0uNTk5LjkxOWMtLjI4LjI4LS41NDYuNDUzLS45Mi41OTgtLjI4LjExLS43MDQuMjQtMS40ODUuMjc2LS44NDMuMDM4LTEuMDk2LjA0Ny0zLjIzMi4wNDdzLTIuMzktLjAwOS0zLjIzMy0uMDQ3Yy0uNzgtLjAzNi0xLjIwMy0uMTY2LTEuNDg1LS4yNzZhMi41IDIuNSAwIDAgMS0uOTItLjU5OCAyLjUgMi41IDAgMCAxLS42LS45MmMtLjEwOS0uMjgxLS4yNC0uNzA1LS4yNzUtMS40ODUtLjAzOC0uODQzLS4wNDYtMS4wOTYtLjA0Ni0zLjIzM3MuMDA4LTIuMzg4LjA0Ni0zLjIzMWMuMDM2LS43OC4xNjYtMS4yMDQuMjc2LTEuNDg2LjE0NS0uMzczLjMxOS0uNjQuNTk5LS45MnMuNTQ2LS40NTMuOTItLjU5OGMuMjgyLS4xMS43MDUtLjI0IDEuNDg1LS4yNzYuNzM4LS4wMzQgMS4wMjQtLjA0NCAyLjUxNS0uMDQ1em00Ljk4OCAxLjMyOGEuOTYuOTYgMCAxIDAgMCAxLjkyLjk2Ljk2IDAgMCAwIDAtMS45Mm0tNC4yNyAxLjEyMmE0LjEwOSA0LjEwOSAwIDEgMCAwIDguMjE3IDQuMTA5IDQuMTA5IDAgMCAwIDAtOC4yMTdtMCAxLjQ0MWEyLjY2NyAyLjY2NyAwIDEgMSAwIDUuMzM0IDIuNjY3IDIuNjY3IDAgMCAxIDAtNS4zMzQiLz4KPC9zdmc+); -webkit-mask-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgZmlsbD0iY3VycmVudENvbG9yIiBjbGFzcz0iYmkgYmktaW5zdGFncmFtIiB2aWV3Qm94PSIwIDAgMTYgMTYiPgogIDxwYXRoIGQ9Ik04IDBDNS44MjkgMCA1LjU1Ni4wMSA0LjcwMy4wNDggMy44NS4wODggMy4yNjkuMjIyIDIuNzYuNDJhMy45IDMuOSAwIDAgMC0xLjQxNy45MjNBMy45IDMuOSAwIDAgMCAuNDIgMi43NkMuMjIyIDMuMjY4LjA4NyAzLjg1LjA0OCA0LjcuMDEgNS41NTUgMCA1LjgyNyAwIDguMDAxYzAgMi4xNzIuMDEgMi40NDQuMDQ4IDMuMjk3LjA0Ljg1Mi4xNzQgMS40MzMuMzcyIDEuOTQyLjIwNS41MjYuNDc4Ljk3Mi45MjMgMS40MTcuNDQ0LjQ0NS44OS43MTkgMS40MTYuOTIzLjUxLjE5OCAxLjA5LjMzMyAxLjk0Mi4zNzJDNS41NTUgMTUuOTkgNS44MjcgMTYgOCAxNnMyLjQ0NC0uMDEgMy4yOTgtLjA0OGMuODUxLS4wNCAxLjQzNC0uMTc0IDEuOTQzLS4zNzJhMy45IDMuOSAwIDAgMCAxLjQxNi0uOTIzYy40NDUtLjQ0NS43MTgtLjg5MS45MjMtMS40MTcuMTk3LS41MDkuMzMyLTEuMDkuMzcyLTEuOTQyQzE1Ljk5IDEwLjQ0NSAxNiAxMC4xNzMgMTYgOHMtLjAxLTIuNDQ1LS4wNDgtMy4yOTljLS4wNC0uODUxLS4xNzUtMS40MzMtLjM3Mi0xLjk0MWEzLjkgMy45IDAgMCAwLS45MjMtMS40MTdBMy45IDMuOSAwIDAgMCAxMy4yNC40MmMtLjUxLS4xOTgtMS4wOTItLjMzMy0xLjk0My0uMzcyQzEwLjQ0My4wMSAxMC4xNzIgMCA3Ljk5OCAwem0tLjcxNyAxLjQ0MmguNzE4YzIuMTM2IDAgMi4zODkuMDA3IDMuMjMyLjA0Ni43OC4wMzUgMS4yMDQuMTY2IDEuNDg2LjI3NS4zNzMuMTQ1LjY0LjMxOS45Mi41OTlzLjQ1My41NDYuNTk4LjkyYy4xMS4yODEuMjQuNzA1LjI3NSAxLjQ4NS4wMzkuODQzLjA0NyAxLjA5Ni4wNDcgMy4yMzFzLS4wMDggMi4zODktLjA0NyAzLjIzMmMtLjAzNS43OC0uMTY2IDEuMjAzLS4yNzUgMS40ODVhMi41IDIuNSAwIDAgMS0uNTk5LjkxOWMtLjI4LjI4LS41NDYuNDUzLS45Mi41OTgtLjI4LjExLS43MDQuMjQtMS40ODUuMjc2LS44NDMuMDM4LTEuMDk2LjA0Ny0zLjIzMi4wNDdzLTIuMzktLjAwOS0zLjIzMy0uMDQ3Yy0uNzgtLjAzNi0xLjIwMy0uMTY2LTEuNDg1LS4yNzZhMi41IDIuNSAwIDAgMS0uOTItLjU5OCAyLjUgMi41IDAgMCAxLS42LS45MmMtLjEwOS0uMjgxLS4yNC0uNzA1LS4yNzUtMS40ODUtLjAzOC0uODQzLS4wNDYtMS4wOTYtLjA0Ni0zLjIzM3MuMDA4LTIuMzg4LjA0Ni0zLjIzMWMuMDM2LS43OC4xNjYtMS4yMDQuMjc2LTEuNDg2LjE0NS0uMzczLjMxOS0uNjQuNTk5LS45MnMuNTQ2LS40NTMuOTItLjU5OGMuMjgyLS4xMS43MDUtLjI0IDEuNDg1LS4yNzYuNzM4LS4wMzQgMS4wMjQtLjA0NCAyLjUxNS0uMDQ1em00Ljk4OCAxLjMyOGEuOTYuOTYgMCAxIDAgMCAxLjkyLjk2Ljk2IDAgMCAwIDAtMS45Mm0tNC4yNyAxLjEyMmE0LjEwOSA0LjEwOSAwIDEgMCAwIDguMjE3IDQuMTA5IDQuMTA5IDAgMCAwIDAtOC4yMTdtMCAxLjQ0MWEyLjY2NyAyLjY2NyAwIDEgMSAwIDUuMzM0IDIuNjY3IDIuNjY3IDAgMCAxIDAtNS4zMzQiLz4KPC9zdmc+); }
.social-icon--facebook { mask-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgZmlsbD0iY3VycmVudENvbG9yIiBjbGFzcz0iYmkgYmktZmFjZWJvb2siIHZpZXdCb3g9IjAgMCAxNiAxNiI+CiAgPHBhdGggZD0iTTE2IDguMDQ5YzAtNC40NDYtMy41ODItOC4wNS04LTguMDVDMy41OCAwLS4wMDIgMy42MDMtLjAwMiA4LjA1YzAgNC4wMTcgMi45MjYgNy4zNDcgNi43NSA3Ljk1MXYtNS42MjVoLTIuMDNWOC4wNUg2Ljc1VjYuMjc1YzAtMi4wMTcgMS4xOTUtMy4xMzEgMy4wMjItMy4xMzEuODc2IDAgMS43OTEuMTU3IDEuNzkxLjE1N3YxLjk4aC0xLjAwOWMtLjk5MyAwLTEuMzAzLjYyMS0xLjMwMyAxLjI1OHYxLjUxaDIuMjE4bC0uMzU0IDIuMzI2SDkuMjVWMTZjMy44MjQtLjYwNCA2Ljc1LTMuOTM0IDYuNzUtNy45NTEiLz4KPC9zdmc+); -webkit-mask-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgZmlsbD0iY3VycmVudENvbG9yIiBjbGFzcz0iYmkgYmktZmFjZWJvb2siIHZpZXdCb3g9IjAgMCAxNiAxNiI+CiAgPHBhdGggZD0iTTE2IDguMDQ5YzAtNC40NDYtMy41ODItOC4wNS04LTguMDVDMy41OCAwLS4wMDIgMy42MDMtLjAwMiA4LjA1YzAgNC4wMTcgMi45MjYgNy4zNDcgNi43NSA3Ljk1MXYtNS42MjVoLTIuMDNWOC4wNUg2Ljc1VjYuMjc1YzAtMi4wMTcgMS4xOTUtMy4xMzEgMy4wMjItMy4xMzEuODc2IDAgMS43OTEuMTU3IDEuNzkxLjE1N3YxLjk4aC0xLjAwOWMtLjk5MyAwLTEuMzAzLjYyMS0xLjMwMyAxLjI1OHYxLjUxaDIuMjE4bC0uMzU0IDIuMzI2SDkuMjVWMTZjMy44MjQtLjYwNCA2Ljc1LTMuOTM0IDYuNzUtNy45NTEiLz4KPC9zdmc+); }
.social-icon--tiktok { mask-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgZmlsbD0iY3VycmVudENvbG9yIiBjbGFzcz0iYmkgYmktdGlrdG9rIiB2aWV3Qm94PSIwIDAgMTYgMTYiPgogIDxwYXRoIGQ9Ik05IDBoMS45OGMuMTQ0LjcxNS41NCAxLjYxNyAxLjIzNSAyLjUxMkMxMi44OTUgMy4zODkgMTMuNzk3IDQgMTUgNHYyYy0xLjc1MyAwLTMuMDctLjgxNC00LTEuODI5VjExYTUgNSAwIDEgMS01LTV2MmEzIDMgMCAxIDAgMyAzeiIvPgo8L3N2Zz4=); -webkit-mask-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgZmlsbD0iY3VycmVudENvbG9yIiBjbGFzcz0iYmkgYmktdGlrdG9rIiB2aWV3Qm94PSIwIDAgMTYgMTYiPgogIDxwYXRoIGQ9Ik05IDBoMS45OGMuMTQ0LjcxNS41NCAxLjYxNyAxLjIzNSAyLjUxMkMxMi44OTUgMy4zODkgMTMuNzk3IDQgMTUgNHYyYy0xLjc1MyAwLTMuMDctLjgxNC00LTEuODI5VjExYTUgNSAwIDEgMS01LTV2MmEzIDMgMCAxIDAgMyAzeiIvPgo8L3N2Zz4=); }

/* Wiersz kontaktowy z małą ikoną (etap 17F.5, zagęszczone 17F.6) */
.site-footer__contact-row { display: flex; align-items: center; gap: 9px; color: rgba(255, 255, 255, .85); font-size: .92em; font-weight: 600; margin: 0 0 8px; min-height: 0; line-height: 1.3; }
.site-footer__contact-row span { min-width: 0; }
.site-footer__contact-icon { width: 15px; height: 15px; flex-shrink: 0; color: var(--color-orange); }
a.site-footer__contact-row { width: fit-content; }

.site-footer__col h3 {
  font-family: var(--font-body);
  font-weight: 800;
  font-size: 12px;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--color-white);
  padding-bottom: 8px;
  margin-bottom: 10px;
  border-bottom: var(--border-width) solid rgba(255, 255, 255, .22);
}
.site-footer__col p { color: rgba(255, 255, 255, .82); font-size: .92em; }

.site-footer__col a {
  display: flex;
  align-items: center;
  width: fit-content;
  min-height: 36px;
  color: rgba(255, 255, 255, .9);
  font-size: .96em;
  font-weight: 600;
  margin: 0 0 -4px -2px;
  padding: 0 2px;
  border-bottom: var(--border-width) solid transparent;
  transition: color .15s var(--ease), border-color .15s var(--ease);
}
.site-footer__col a:hover, .site-footer__col a:focus-visible {
  color: var(--color-white);
  border-color: var(--color-fuchsia);
}
.site-footer__col a.site-footer__contact-row:hover, .site-footer__col a.site-footer__contact-row:focus-visible { border-color: transparent; text-decoration: underline; }

.site-footer__bottom { padding-block: 16px; font-size: 12px; color: rgba(255, 255, 255, .65); }

/* 3 RÓWNOWAŻNE kolumny — ta sama szerokość dla wszystkich trzech,
   odstępy zmniejszone etapem 17F.6. */
.site-footer__columns { display: grid; gap: 28px; }
@media (min-width: 768px) { .site-footer__columns { grid-template-columns: repeat(3, 1fr); gap: 28px; } }
@media (min-width: 1024px) { .site-footer__columns { gap: 40px; } }

/* =========================================================
   /ZAPISZ-SIĘ — formularz zgłoszeniowy (etap 15, DESIGN.md §13)
   Editorialowa kontynuacja homepage: krótki hero (skala H2, bez
   zdjęcia), formularz jako biała, uniesiona karta na jasnym tle,
   pola pogrupowane w 4 fieldsety. Token --color-error zdefiniowany
   w głównym :root na górze pliku.
   ========================================================= */
.apply-hero { background: var(--color-bg); padding-top: 56px; padding-bottom: var(--section-space-mobile); }
@media (min-width: 768px) { .apply-hero { padding-bottom: var(--section-space-tablet); } }
.apply-hero__inner { max-width: var(--container-text); }
.apply-hero__heading {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--fs-h2);
  line-height: 1.02;
  letter-spacing: -.01em;
  color: var(--color-ink);
  margin-block: 16px 20px;
}
.apply-hero__text { font-size: var(--fs-lead); line-height: 1.55; color: var(--color-text); max-width: 56ch; }

/* Krótka linia lokalizacji pod leadem hero /szkolenia/ (etap 18) —
   zapisz-sie/co-wybrac nie mają tego elementu, klasa tam nieużywana. */
.apply-hero__meta { font-size: .88em; font-weight: 700; color: var(--color-muted); margin-top: 14px; }

/* Hero /szkolenia/ ze zdjęciem (etap 18.4) — grid-template-areas
   zamiast .subpage-hero (klasy/obrona), bo tu zdjęcie ma zajmować
   ok. 40-48% (nie 50/50) I kolejność mobile musi wstawić zdjęcie
   MIĘDZY tekst a CTA, nie tylko obok tekstu — stąd CTA jako osobny
   obszar grida, nie część .szkolenia-hero__copy. Nietknięte .apply-hero
   i .apply-hero__inner zostają używane bez zmian przez /zapisz-sie/. */
.szkolenia-hero__grid {
  display: grid;
  grid-template-columns: 1fr;
  grid-template-areas: "copy" "photo" "actions";
  gap: 28px;
  align-items: center;
}
.szkolenia-hero__copy { grid-area: copy; }
.szkolenia-hero__photo {
  grid-area: photo;
  margin: 0;
  aspect-ratio: 3 / 4;
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-elevated);
}
.szkolenia-hero__photo img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 20%; display: block; }
.szkolenia-hero__actions { grid-area: actions; margin-top: 0; }

@media (min-width: 1024px) {
  .szkolenia-hero__grid {
    grid-template-columns: 1.25fr 1fr;
    grid-template-areas: "copy photo" "actions photo";
    gap: 56px;
  }
}

/* /szkolenia/ placeholder (etap 17F.6A) — dwa CTA pod krótkim tekstem,
   reużywa istniejący .btn i prosty wzorzec tekstowego linku ze strzałką
   już użyty gdzie indziej (np. .groomer-teaser__link). */
.apply-hero__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 24px; margin-top: 32px; }
.apply-hero__link { display: inline-flex; align-items: center; gap: 8px; font-weight: 700; color: var(--color-ink); border-bottom: var(--border-width) solid var(--color-ink); transition: color .15s var(--ease); }
.apply-hero__link svg { width: 18px; height: 18px; transition: transform .18s var(--ease); }
.apply-hero__link:hover, .apply-hero__link:focus-visible { color: var(--color-fuchsia); border-color: var(--color-fuchsia); }
.apply-hero__link:hover svg, .apply-hero__link:focus-visible svg { transform: translateX(3px); }

.apply-form-section { background: var(--color-bg); padding-top: 0; padding-bottom: var(--section-space-mobile); }
@media (min-width: 768px) { .apply-form-section { padding-bottom: var(--section-space-tablet); } }
@media (min-width: 1024px) { .apply-form-section { padding-bottom: var(--section-space-desktop); } }
.apply-form-section__inner { max-width: 760px; }

/* Podsumowanie wyboru z /cennik-szkolen (etap 24) — lekki, jasny box nad
   formularzem (nie kolejna pełna .form-owa karta), fuksjowy tint spina
   wizualnie z .price-option/.pricing-summary na samym cenniku. */
.pricing-recap { background: var(--color-fuchsia-soft); border-radius: var(--radius-sm); padding: 20px 24px; margin-bottom: 24px; }
.pricing-recap .eyebrow { margin-bottom: 6px; }
.pricing-recap__variant { font-family: var(--font-display); font-weight: 700; font-size: clamp(1.15rem, 2vw, 1.4rem); color: var(--color-ink); margin-bottom: 6px; }
.pricing-recap__addon { font-size: .92em; color: var(--color-text); margin-bottom: 4px; }
.pricing-recap__total { margin-bottom: 10px; }
.pricing-recap__total strong { font-family: var(--font-display); font-weight: 700; font-size: clamp(1.25rem, 2.2vw, 1.55rem); color: var(--color-fuchsia); }
.pricing-recap__note { font-size: .88em; color: var(--color-text); }

.form, .quiz-card {
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-line);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-elevated);
  padding: 28px 20px;
}
@media (min-width: 640px) { .form, .quiz-card { padding: 40px; } }
@media (min-width: 1024px) { .form, .quiz-card { padding: 56px; } }
/* formularz kontaktowy w /co-wybrac żyje już wewnątrz .quiz-card —
   zdejmujemy własny card-chrome .form, żeby nie powielać karty w karcie;
   stylowanie pól (.form input itd.) działa dalej przez selektory potomne */
.quiz-card .form { background: none; border: none; box-shadow: none; padding: 0; }

/* honeypot antyspamowy (etap 17) — niewidoczny dla ludzi i czytników
   ekranu (aria-hidden na wrapperze, poza kolejnością Tab), ale obecny w
   DOM, więc naiwne boty wciąż go wypełniają */
.hp-field { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.form__summary {
  background: var(--color-error);
  color: var(--color-white);
  font-weight: 700;
  font-size: 14px;
  line-height: 1.4;
  padding: 14px 18px;
  border-radius: var(--radius-sm);
  margin-bottom: 28px;
}

fieldset { border: none; margin: 0; padding: 0; min-width: 0; }
legend { padding: 0; }

.form__group { margin-bottom: 40px; }
.form__legend {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.15rem;
  color: var(--color-ink);
  margin-bottom: 20px;
  padding-bottom: 12px;
  border-bottom: var(--border-width) solid var(--color-line);
  width: 100%;
}

.field { display: flex; flex-direction: column; gap: 8px; margin-bottom: 22px; }
/* etap 17C: pola warunkowe (#f-duration-wrap, #f-previous-work-wrap) łączą
   class="field" z atrybutem [hidden] — bez tego override .field { display:
   flex } (reguła autorska) wygrywa z domyślną regułą UA [hidden]{display:
   none}, bo reguły autorskie zawsze biją UA niezależnie od specyficzności.
   Ten sam wzorzec błędu co .field__error[hidden] wyżej w pliku (etap 15). */
.field[hidden] { display: none; }
.field:last-child { margin-bottom: 0; }
.field > label, .field > legend {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 15px;
  color: var(--color-ink);
}
.field__optional { font-weight: 500; color: var(--color-muted); }

.field-row { display: grid; gap: 20px; margin-bottom: 22px; }
.field-row .field { margin-bottom: 0; }
@media (min-width: 640px) { .field-row { grid-template-columns: 1fr 1fr; } }

/* Etap 9E.4 §16/§17/§18/§19 polecenia - GLOBAL FORM POLISH. Panel pages
   (cele/psy/dyspozycyjność/notatki/ustaw-hasło i in.) w większości NIE
   opakowują swoich pól w klasę `.form` (używają wyłącznie `.field` jako
   wrappera na pojedyncze pole) - dlatego runtime pokazał "zbyt kanciaste"
   pola: input/textarea/select bez `.form` w drzewie spadały na goły,
   nieostylowany wygląd przeglądarki. Selektor rozszerzony o `.field` jako
   RÓWNORZĘDNY kontekst (nie zamiennik) - te same miękkie zaokrąglenia
   (--radius-sm, 14px - już w duchu poleconych 14-18px) i wygląd wszędzie,
   bez zmiany istniejącego layoutu/rozmiarów tam, gdzie `.form` już działało. */
.form input[type="text"],
.form input[type="tel"],
.form input[type="email"],
.form input[type="time"],
.form input[type="password"],
.form input[type="date"],
.form select,
.form textarea,
.field input[type="text"],
.field input[type="tel"],
.field input[type="email"],
.field input[type="time"],
.field input[type="password"],
.field input[type="date"],
.field select,
.field textarea,
input.panel-control[type="text"],
input.panel-control[type="tel"],
input.panel-control[type="email"],
input.panel-control[type="time"],
input.panel-control[type="password"],
input.panel-control[type="date"],
select.panel-control,
textarea.panel-control {
  min-height: 48px;
  padding: 12px 16px;
  background: var(--color-surface);
  color: var(--color-ink);
  border: var(--border-width) solid var(--color-line);
  border-radius: var(--radius-sm);
  font-family: var(--font-body);
  font-size: 16px;
  width: 100%;
  transition: border-color .15s var(--ease), box-shadow .15s var(--ease);
}
.form textarea, .field textarea, textarea.panel-control { min-height: 120px; padding-top: 14px; resize: vertical; }
.form select, .field select, select.panel-control {
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M6 9l6 6 6-6' fill='none' stroke='%23222126' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 16px center;
  background-size: 18px;
  padding-right: 44px;
}
.form input::placeholder, .form textarea::placeholder,
.field input::placeholder, .field textarea::placeholder,
input.panel-control::placeholder, textarea.panel-control::placeholder { color: var(--color-muted); opacity: 1; }

.form input:focus-visible,
.form select:focus-visible,
.form textarea:focus-visible,
.field input:focus-visible,
.field select:focus-visible,
.field textarea:focus-visible,
input.panel-control:focus-visible,
select.panel-control:focus-visible,
textarea.panel-control:focus-visible {
  outline: none;
  border-color: var(--color-fuchsia);
  box-shadow: 0 0 0 4px var(--color-fuchsia-soft);
}

.radio-group { display: flex; flex-direction: column; gap: 4px; }
.radio-group--inline { flex-direction: row; flex-wrap: wrap; gap: 8px 28px; }

.radio-option {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 44px;
  font-family: var(--font-body);
  font-size: 15px;
  font-weight: 500;
  color: var(--color-text);
  cursor: pointer;
}
.radio-option input[type="radio"] {
  width: 20px;
  height: 20px;
  flex-shrink: 0;
  accent-color: var(--color-fuchsia);
}
.radio-option input[type="radio"]:focus-visible { outline: 3px solid var(--color-fuchsia); outline-offset: 3px; }

.field--invalid input[type="text"],
.field--invalid input[type="tel"],
.field--invalid input[type="email"],
.field--invalid input[type="time"],
.field--invalid select,
.field--invalid textarea {
  border-color: var(--color-error);
}

.field__error {
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--color-error);
  font-size: 13px;
  font-weight: 600;
}
.field__error[hidden] { display: none; }
.field__error-icon { width: 16px; height: 16px; flex-shrink: 0; }

.apply-form__note { font-size: 14px; line-height: 1.5; color: var(--color-muted); margin-bottom: 24px; }
.apply-form__privacy { font-size: 13px; line-height: 1.5; color: var(--color-muted); margin: -12px 0 24px; }

.apply-form__submit { width: 100%; justify-content: center; }
@media (min-width: 480px) { .apply-form__submit { width: auto; } }

.apply-success {
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-line);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-elevated);
  padding: 48px 28px;
  text-align: center;
}
.apply-success h2 {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.6rem, 3vw, 2.2rem);
  color: var(--color-ink);
  margin-bottom: 12px;
}
.apply-success p { color: var(--color-text); font-size: 1.05rem; max-width: 46ch; margin-inline: auto; }

/* =========================================================
   /CO-WYBRAC — krótka ścieżka decyzyjna (etap 16)
   Jeden krok na ekran, karta w stylu /zapisz-sie (.quiz-card dzieli
   card-chrome z .form, patrz wyżej). Odpowiedzi jako duże karty radio
   (.answer-card) — prawdziwe kontrolki formularza, nie div-y.
   ========================================================= */
.quiz-hero { background: var(--color-bg); padding-top: 56px; padding-bottom: 40px; }
.quiz-hero__inner { max-width: var(--container-text); }
.quiz-hero__heading {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--fs-h2);
  line-height: 1.02;
  letter-spacing: -.01em;
  color: var(--color-ink);
  margin-block: 16px 20px;
}
.quiz-hero__text { font-size: var(--fs-lead); line-height: 1.55; color: var(--color-text); max-width: 56ch; }
.quiz-hero__note { margin-top: 10px; font-size: 14px; color: var(--color-muted); max-width: 56ch; }

.quiz-section { background: var(--color-bg); padding-top: 0; padding-bottom: var(--section-space-mobile); }
@media (min-width: 768px) { .quiz-section { padding-bottom: var(--section-space-tablet); } }
@media (min-width: 1024px) { .quiz-section { padding-bottom: var(--section-space-desktop); } }
.quiz-section__inner { max-width: 760px; }

.quiz-noscript { background: var(--color-surface-alt); border-radius: var(--radius-sm); padding: 16px 20px; margin-bottom: 24px; font-size: 14px; color: var(--color-text); }
.quiz-noscript a { font-weight: 700; color: var(--color-ink); text-decoration: underline; }

.quiz-progress {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 13px;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--color-muted);
  margin-bottom: 24px;
  min-height: 1em;
}

/* nadpisanie globalnego "section { padding-block: var(--section-pad) }"
   — kroki quizu to zagnieżdżone stany UI wewnątrz .quiz-card, nie
   sekcje strony, więc nie mają dostawać sekcyjnego odstępu */
.quiz-step { padding-block: 0; }

.quiz-step__question {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.5rem, 2.6vw, 2.1rem);
  line-height: 1.15;
  color: var(--color-ink);
}

.answer-list { display: flex; flex-direction: column; gap: 12px; margin-top: 24px; }
.answer-card {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  padding: 16px 18px;
  background: var(--color-surface-alt);
  border: var(--border-width) solid var(--color-line);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: border-color .15s var(--ease), background-color .15s var(--ease);
}
.answer-card:hover { border-color: var(--color-fuchsia); background: var(--color-surface); }
.answer-card:has(input:checked) { border-color: var(--color-fuchsia); background: var(--color-fuchsia-soft); }
.answer-card input[type="radio"] {
  width: 22px;
  height: 22px;
  flex-shrink: 0;
  margin-top: 2px;
  accent-color: var(--color-fuchsia);
}
.answer-card input[type="radio"]:focus-visible { outline: 3px solid var(--color-fuchsia); outline-offset: 3px; }
.answer-card__body { display: flex; flex-direction: column; gap: 4px; }
.answer-card__title { font-family: var(--font-body); font-weight: 700; font-size: 16px; color: var(--color-ink); line-height: 1.35; }
.answer-card__desc { font-size: 14px; color: var(--color-text); line-height: 1.45; }

.quiz-nav { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px; margin-top: 28px; }
.quiz-nav__back {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 15px;
  color: var(--color-muted);
}
.quiz-nav__back:hover, .quiz-nav__back:focus-visible { color: var(--color-ink); }

.quiz-result__heading {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.8rem, 3.2vw, 2.6rem);
  color: var(--color-ink);
  margin-block: 6px 16px;
}
.quiz-result__text { font-size: 1.05rem; line-height: 1.55; color: var(--color-text); max-width: 60ch; margin-bottom: 16px; }
.quiz-result__disclaimer { font-size: 13px; color: var(--color-muted); max-width: 60ch; margin-bottom: 20px; }
.quiz-result__change { margin-bottom: 4px; }

.quiz-decision { margin-top: 32px; padding-top: 28px; border-top: var(--border-width) solid var(--color-line); }
.quiz-decision__question {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.1rem, 1.8vw, 1.4rem);
  color: var(--color-ink);
  margin-bottom: 8px;
}
.quiz-decision__note { font-size: 14px; line-height: 1.5; color: var(--color-muted); margin-bottom: 20px; max-width: 56ch; }
.quiz-decision__row { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 24px; }
.quiz-decision__no {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 15px;
  color: var(--color-muted);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.quiz-decision__no:hover, .quiz-decision__no:focus-visible { color: var(--color-ink); }

.quiz-declined { margin-top: 32px; padding-top: 28px; border-top: var(--border-width) solid var(--color-line); }
.quiz-declined p { color: var(--color-text); margin-bottom: 14px; }
.quiz-declined__link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  font-weight: 700;
  color: var(--color-ink);
}
.quiz-declined__link svg { width: 16px; height: 16px; transition: transform .18s var(--ease); }
.quiz-declined__link:hover, .quiz-declined__link:focus-visible { color: var(--color-fuchsia); }
.quiz-declined__link:hover svg, .quiz-declined__link:focus-visible svg { transform: translateX(3px); }

.quiz-success h2 {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.6rem, 3vw, 2.2rem);
  color: var(--color-ink);
  margin-bottom: 12px;
}
.quiz-success p { color: var(--color-text); font-size: 1.05rem; max-width: 52ch; }

/* =========================================================
   /CENNIK-SZKOLEN — premium redesign (etap 26)
   Wyłącznie warstwa wizualna/layout - JS (script.js, blok
   "/CENNIK-SZKOLEN") NIETKNIĘTY, wszystkie ID/klasy poniżej istnieją
   dokładnie tam, gdzie JS ich szuka. Kierunek: dużo bieli, cienkie
   obrysy zamiast wypełnień --color-surface-alt (dawny "szary na
   szarym"), fuksja jako jedyny mocny akcent, premium przez typografię/
   proporcje/światło, nie przez nowe kolory czy ciężkie cienie. Zdjęcia
   (assets/cennik/) użyte 1:1, bez modyfikacji.
   ========================================================= */

/* HERO — ≥768px (tablet+desktop) ZAMROŻONY od etapu 34/35/36/37
   (polecenie: "nie zmieniaj ani jednej reguły wizualnej"). .pricing-
   hero__photo (background z etapu 30, oparty na cennik-hero-dog-mobile
   .webp/-desktop.webp) i jego reguły @media (min-width:768px)/
   (min-width:1024px) niżej są bit-w-bit takie same jak przed etapem 37.
   Telefon (≤767px) — etap 37, PIĄTA i ostateczna zmiana koncepcji:
   etap 36 (CSS-owe kadrowanie samego cennik-hero.jpg) matematycznie
   potwierdził, że przy tym zdjęciu oko psa zawsze zaczyna się przed
   końcem 62%-owej kolumny tekstu, niezależnie od doboru background-
   size - dlatego zamiast dalszego dobierania CSS, powstał DEDYKOWANY,
   raz wygenerowany asset assets/cennik/cennik-hero-mobile-final.webp
   (860×1200, programowo skomponowany z tego samego, niezmienionego
   cennik-hero.jpg - pies dosunięty w prawo + naturalne tło stopione w
   jedną kompozycję przez piórkowanie (feather) lewej/górnej/dolnej
   krawędzi, tło canvasa próbkowanym kolorem #F8F3EF). Bezpieczna strefa
   dla tekstu (0-500px z 860 bez sierści/oka/nosa/ucha, zweryfikowana
   programowo na gotowym pliku) jest już zaszyta w SAMYM assetcie -
   CSS wyłącznie go pokazuje: `background-image` wprost na .pricing-hero
   (nie .pricing-hero__photo - ten div zostaje wyłącznie mechanizmem
   ≥768px, nietkniętym), `background-size:100% auto` (skalowanie po
   szerokości, zero dodatkowego CSS-owego kadrowania/pozycjonowania).
   Nad zdjęciem: .pricing-hero::before (biała/kremowa mgła, ten sam
   sampled kolor) i .pricing-hero::after (wąska strefa backdrop-filter
   :blur, zamaskowana gradientową maską po obu krawędziach - kończy się
   bezpiecznie przed sierścią/okiem). Tekst (.pricing-hero__inner) ma
   z-index wyższy niż obie warstwy. Reguły @media (max-width:767px)
   niżej są jedynym miejscem definiującym ten mechanizm. */
.pricing-hero { position: relative; overflow: hidden; isolation: isolate; min-height: 540px; display: flex; align-items: center; background: var(--color-bg); }
.pricing-hero__photo { display: none; }

.pricing-hero__inner { position: relative; z-index: 2; width: 100%; padding-block: 32px; }
.pricing-hero__heading-col { margin-bottom: 16px; }
.pricing-hero__heading {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(1.6rem, 6.4vw, 2rem);
  line-height: 1.08;
  letter-spacing: -.01em;
  color: var(--color-ink);
  margin-block: 8px 0;
}
.pricing-hero__text { font-size: .88rem; line-height: 1.48; color: var(--color-text); }
.pricing-hero__text + .pricing-hero__text { margin-top: 8px; }

@media (min-width: 480px) {
  .pricing-hero__heading { font-size: clamp(1.9rem, 6vw, 2.3rem); }
  .pricing-hero__text { font-size: .95rem; }
}

/* Telefon (≤767px), etap 38 — cofnięcie koncepcji "safe zone" z etapu
   37 (wymusiła zbyt małego psa, ocenione jako wyglądające jak doklejony
   fragment). Powrót do oryginalnego assets/cennik/cennik-hero.jpg jako
   prawdziwego background-image CAŁEGO .pricing-hero, tym razem z
   background-size:cover (dozwolony kontrolowany crop tułowia/boku/tła,
   NIE oczu/nosa/pyska/uszu) - pies renderuje się znacznie większy.
   Mgła (::before) MOŻE teraz zachodzić na sierść (jawnie dozwolone) -
   zapewnia kontrast tekstu bez wymogu czystego "pustego" pasa pod nim.
   Blur (::after) to wąska, zamaskowana na obu krawędziach strefa
   ustawiona tak, by nie dotykać oka/pyska. */
@media (max-width: 767px) {
  .pricing-hero {
    min-height: 460px;
    background-color: #F8F3EF;
    background-image: url("assets/cennik/cennik-hero.jpg");
    background-repeat: no-repeat;
    background-position: 78% center;
    background-size: cover;
  }
  .pricing-hero::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 1;
    pointer-events: none;
    background: linear-gradient(
      90deg,
      rgba(248, 243, 239, .97) 0%,
      rgba(248, 243, 239, .93) 28%,
      rgba(248, 243, 239, .8) 43%,
      rgba(248, 243, 239, .48) 54%,
      rgba(248, 243, 239, .22) 63%,
      rgba(248, 243, 239, .06) 72%,
      rgba(248, 243, 239, 0) 80%
    );
  }
  .pricing-hero::after {
    content: "";
    position: absolute;
    inset: 0;
    left: 53%;
    width: 18%;
    z-index: 1;
    pointer-events: none;
    -webkit-mask-image: linear-gradient(to right, transparent 0%, black 35%, black 65%, transparent 100%);
    mask-image: linear-gradient(to right, transparent 0%, black 35%, black 65%, transparent 100%);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
  }
  .pricing-hero__inner { max-width: 62%; margin-inline: 0; }
}

@media (min-width: 768px) {
  .pricing-hero { min-height: 520px; }
  .pricing-hero__photo {
    display: block;
    position: absolute;
    right: 0;
    bottom: 0;
    height: 100%;
    width: 42%;
    z-index: 0;
    pointer-events: none;
    background-image: url("assets/cennik/cennik-hero-dog-mobile.webp");
    background-repeat: no-repeat;
    background-position: right bottom;
    background-size: contain;
  }
  .pricing-hero__inner { padding-block: 40px; }
  .pricing-hero__grid { max-width: 54%; }
  .pricing-hero__heading { font-size: clamp(2.1rem, 4.4vw, 2.5rem); }
  .pricing-hero__text { font-size: 1rem; }
}

/* Desktop od 1024px — prawdziwy grid 52%/48% WEWNĄTRZ strefy tekstowej
   (H1 po lewej, lead bardziej z boku/środka, nie pod H1), pies jako
   niezależna warstwa tła po prawej, poza tym gridem - patrz sekcja 3/5
   polecenia. Od tej szerokości używamy kadru desktopowego (więcej
   widocznego tułowia/kontekstu, nie tylko blisko twarzy). */
@media (min-width: 1024px) {
  .pricing-hero { min-height: 560px; }
  .pricing-hero__inner { padding-block: 0; }
  .pricing-hero__photo {
    /* Desktop (zaakceptowany, etap 30) ma WŁASNY, pełny mechanizm
       pozycjonowania niezależny od reguły bazowej mobile/tablet z
       etapu 32 (bottom:0/height:100%/contain) - stąd jawny reset
       top/transform/bottom/height/background-size tutaj, żeby zmiana
       reguły bazowej dla mobile nie zepsuła tego, co tu już działa. */
    top: 50%;
    bottom: auto;
    height: auto;
    transform: translateY(-50%);
    width: 40%;
    aspect-ratio: 1000 / 1023;
    background-image:
      linear-gradient(90deg, var(--color-bg) 0%, rgba(241, 241, 243, 0) 32%),
      linear-gradient(180deg, var(--color-bg) 0%, rgba(241, 241, 243, 0) 18%, rgba(241, 241, 243, 0) 82%, var(--color-bg) 100%),
      url("assets/cennik/cennik-hero-dog-desktop.webp");
    background-repeat: no-repeat, no-repeat, no-repeat;
    background-position: center, center, center;
    background-size: 100% 100%, 100% 100%, cover;
  }
  .pricing-hero__grid {
    max-width: 58%;
    display: grid;
    grid-template-columns: 52% 48%;
    column-gap: 24px;
    align-items: center;
  }
  .pricing-hero__heading-col { margin-bottom: 0; }
  .pricing-hero__heading { font-size: var(--fs-h2); margin-block: 14px 0; }
  .pricing-hero__lead-col { max-width: 300px; }
  .pricing-hero__text { font-size: .95rem; line-height: 1.55; }
  .pricing-hero__text + .pricing-hero__text { margin-top: 12px; }
}
@media (min-width: 1280px) {
  .pricing-hero { min-height: 600px; }
  .pricing-hero__photo { width: 38%; }
  .pricing-hero__grid { max-width: 60%; }
  .pricing-hero__lead-col { max-width: 340px; }
  .pricing-hero__text { font-size: var(--fs-lead); }
}

.pricing-section { background: var(--color-surface); padding-top: var(--section-space-mobile); padding-bottom: var(--section-space-mobile); }
@media (min-width: 768px) { .pricing-section { padding-top: var(--section-space-tablet); padding-bottom: var(--section-space-tablet); } }
@media (min-width: 1024px) { .pricing-section { padding-top: var(--section-space-desktop); padding-bottom: var(--section-space-desktop); } }
.pricing-section__inner { max-width: 960px; }

/* Wprowadzenie przed wyborem formy pracy (etap 28) — zwykły tekst
   zgodny z typografią homepage (ten sam przepis co .work__lead), nie
   nagłówek/alert/box. */
.pricing-choices__intro { font-size: var(--fs-lead); line-height: 1.55; color: var(--color-text); margin-bottom: 24px; }

/* KROK 1 — trzy duże, numerowane karty (jak .work-tile na homepage:
   num + tytuł + opis), zamiast klasycznego widocznego radia. Input
   zostaje prawdziwym, dostępnym radiem (klawiatura, focus-visible),
   tylko wizualnie ukryty - stan aktywny idzie przez :has(input:checked)
   na całej karcie, czytelny bez hovera. */
.pricing-choices { display: grid; gap: 20px; margin-top: 8px; }
@media (min-width: 1024px) { .pricing-choices { grid-template-columns: repeat(3, 1fr); gap: 24px; } }

.pricing-choice {
  position: relative;
  display: block;
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-line);
  border-radius: var(--radius-md);
  padding: 32px 28px;
  cursor: pointer;
  transition: border-color .18s var(--ease), background-color .18s var(--ease), box-shadow .18s var(--ease);
}
.pricing-choice:hover { border-color: var(--color-fuchsia); }
.pricing-choice:has(input:checked) { border-color: var(--color-fuchsia); background: var(--color-fuchsia-soft); box-shadow: 0 14px 34px rgba(213, 45, 139, .10); }
.pricing-choice:has(input:focus-visible) { outline: 3px solid var(--color-fuchsia); outline-offset: 3px; }
.pricing-choice input[type="radio"] { position: absolute; opacity: 0; width: 1px; height: 1px; margin: 0; }
.pricing-choice__num {
  display: block;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(2.2rem, 3.5vw, 3rem);
  color: var(--color-line);
  line-height: 1;
  margin-bottom: 18px;
  transition: color .18s var(--ease);
}
.pricing-choice:has(input:checked) .pricing-choice__num { color: var(--color-fuchsia); }
.pricing-choice__title { display: block; font-family: var(--font-display); font-weight: 600; font-size: clamp(1.3rem, 2vw, 1.6rem); color: var(--color-ink); margin-bottom: 10px; }
.pricing-choice__desc { display: block; font-size: .92em; line-height: 1.5; color: var(--color-text); }

/* KROK 2 — grupy wariantów, jedna na formę pracy. Ukrywane w runtime
   przez script.js (hidden), widoczne wszystkie w bazowym HTML. */
.pricing-group { margin-top: 64px; padding-top: 44px; border-top: var(--border-width) solid var(--color-line); }
/* Zabezpieczenie jak przy .field[hidden]/.field__error[hidden] wyżej w
   tym pliku - żadna reguła tutaj nie ustawia własnego "display" na
   .pricing-group, więc [hidden] z UA stylesheet powinno wystarczyć,
   ale jawna reguła to gwarantuje niezależnie od kolejności/specyfiki
   (etap 32, stan początkowy cennika musi być ukryty w samym HTML). */
.pricing-group[hidden] { display: none; }
.pricing-group .eyebrow { margin-bottom: 10px; }
.pricing-group__heading {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(1.7rem, 2.8vw, 2.3rem);
  color: var(--color-ink);
  margin-bottom: 4px;
}

.price-options { display: grid; gap: 18px; margin-top: 28px; }
@media (min-width: 640px) { .price-options { grid-template-columns: repeat(2, 1fr); gap: 20px; } }

.price-option {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 28px 26px;
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-line);
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: border-color .15s var(--ease), background-color .15s var(--ease), box-shadow .15s var(--ease);
}
.price-option:hover { border-color: var(--color-fuchsia); }
.price-option:has(input:checked) { border-color: var(--color-fuchsia); background: var(--color-fuchsia-soft); box-shadow: 0 12px 30px rgba(213, 45, 139, .10); }
.price-option__row { display: flex; align-items: center; gap: 12px; }
.price-option input[type="radio"] { width: 22px; height: 22px; flex-shrink: 0; accent-color: var(--color-fuchsia); }
.price-option input[type="radio"]:focus-visible { outline: 3px solid var(--color-fuchsia); outline-offset: 3px; }
.price-option__title { font-family: var(--font-body); font-weight: 700; font-size: 17px; color: var(--color-ink); }
.price-option__price { display: flex; align-items: baseline; flex-wrap: wrap; gap: 12px; margin-top: 2px; }
.price-option__old { font-size: .85em; font-weight: 600; color: var(--color-muted); }
.price-option__current {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.9rem, 3.2vw, 2.5rem);
  color: var(--color-ink);
  transition: color .15s var(--ease);
}
.price-option:has(input:checked) .price-option__current { color: var(--color-fuchsia); }
/* .price-option__save (badge "Oszczędzasz X zł") usunięty etapem 31 na
   polecenie - regularPrice zostaje w PRICING (script.js) wyłącznie do
   przekreślonej ceny standardowej powyżej. */
.pricing-note { font-size: .82em; line-height: 1.5; color: var(--color-muted); }

/* KROK 3 — prowadzenie: lekkie, bezwypełnieniowe pigułki (biel + cienki
   obrys), nie ciężkie szare przyciski. */
.pricing-addon { margin-top: 64px; padding-top: 44px; border-top: var(--border-width) solid var(--color-line); }
.pricing-addon[hidden] { display: none; }
.pricing-addon .eyebrow { margin-bottom: 10px; }
.addon-options { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 24px; }
.addon-option {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 48px;
  padding: 12px 22px;
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-line);
  border-radius: var(--radius-pill);
  cursor: pointer;
  transition: border-color .15s var(--ease), background-color .15s var(--ease);
}
.addon-option:hover { border-color: var(--color-fuchsia); }
.addon-option:has(input:checked) { border-color: var(--color-fuchsia); background: var(--color-fuchsia-soft); }
.addon-option input[type="radio"] { width: 18px; height: 18px; flex-shrink: 0; accent-color: var(--color-fuchsia); }
.addon-option input[type="radio"]:focus-visible { outline: 3px solid var(--color-fuchsia); outline-offset: 3px; }
.addon-option__title { font-family: var(--font-body); font-weight: 700; font-size: .95em; color: var(--color-ink); }
.addon-option__price { font-family: var(--font-body); font-weight: 700; font-size: .85em; color: var(--color-muted); }
.addon-option:has(input:checked) .addon-option__price { color: var(--color-fuchsia); }

/* Delikatny fade/slide przy odsłonięciu kroku (etap 26, §14) - ten sam
   wzorzec co .accordion__panel/faq-in, wyłączony pod reduced-motion. */
@media (prefers-reduced-motion: no-preference) {
  .pricing-group:not([hidden]),
  .pricing-addon:not([hidden]),
  .pricing-summary:not([hidden]) { animation: pricing-reveal .32s var(--ease); }
  @keyframes pricing-reveal { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
}

/* PODSUMOWANIE — osobna, pełnoszeroka sekcja premium (nie wnętrze
   #pricing-config), fuksjowy tint, duża cena, dyskretna grafika
   dog-line.png w tle (nigdy nie zasłania tekstu/CTA - niski z-index,
   niska opacity, position:absolute poza obszarem treści). */
.pricing-summary { background: var(--color-fuchsia-soft); padding-block: 56px; position: relative; overflow: hidden; }
.pricing-summary[hidden] { display: none; }
@media (min-width: 768px) { .pricing-summary { padding-block: 72px; } }
@media (min-width: 1024px) { .pricing-summary { padding-block: 96px; } }
.pricing-summary__inner { position: relative; z-index: 1; display: flex; flex-direction: column; gap: 32px; }
@media (min-width: 768px) { .pricing-summary__inner { flex-direction: row; align-items: center; justify-content: space-between; gap: 48px; } }
.pricing-summary__copy { max-width: 480px; }
.pricing-summary__variant {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.8rem, 3.2vw, 2.6rem);
  color: var(--color-ink);
  margin-block: 6px 10px;
  line-height: 1.1;
}
.pricing-summary__addon { font-size: 1.05em; color: var(--color-text); }
.pricing-summary__price { flex-shrink: 0; }
@media (min-width: 768px) { .pricing-summary__price { text-align: right; } }
.pricing-summary__total-label { font-size: .95em; font-weight: 700; color: var(--color-text); margin-bottom: 2px; }
.pricing-summary__total { margin-bottom: 22px; }
.pricing-summary__total strong { font-family: var(--font-display); font-weight: 700; font-size: clamp(2.6rem, 5.5vw, 4rem); color: var(--color-fuchsia); line-height: 1; }
.pricing-summary__actions { display: flex; flex-direction: column; align-items: flex-start; gap: 14px; }
@media (min-width: 768px) { .pricing-summary__actions { align-items: flex-end; } }
.pricing-summary__link { font-family: var(--font-body); font-weight: 700; font-size: 15px; color: var(--color-muted); text-decoration: underline; text-underline-offset: 3px; }
.pricing-summary__link:hover, .pricing-summary__link:focus-visible { color: var(--color-ink); }

.pricing-summary__dog {
  position: absolute;
  right: 6px;
  bottom: 0;
  width: 100px;
  opacity: .14;
  pointer-events: none;
  z-index: 0;
}
@media (min-width: 768px) { .pricing-summary__dog { width: 160px; right: 16px; } }
@media (min-width: 1024px) { .pricing-summary__dog { width: 220px; right: 24px; } }

/* CO MASZ OPRÓCZ ZAJĘĆ — lekkie kolumny z ikonami zamiast ciężkich
   kart. 1 kolumna mobile, 2x2 tablet, 4 z cienkimi separatorami od
   1024px. */
.pricing-benefits { background: var(--color-surface); padding-block: var(--section-space-mobile); }
@media (min-width: 768px) { .pricing-benefits { padding-block: var(--section-space-tablet); } }
@media (min-width: 1024px) { .pricing-benefits { padding-block: var(--section-space-desktop); } }
.pricing-benefits__row { display: grid; gap: 36px; margin-top: 40px; }
@media (min-width: 640px) { .pricing-benefits__row { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) {
  .pricing-benefits__row { grid-template-columns: repeat(4, 1fr); gap: 0; }
  .pricing-benefit { padding-inline: 28px; border-left: var(--border-width) solid var(--color-line); }
  .pricing-benefit:first-child { border-left: none; padding-left: 0; }
}
.pricing-benefit__icon { display: block; width: 40px; height: 40px; margin-bottom: 20px; }
.pricing-benefit h3 { font-family: var(--font-display); font-weight: 600; font-size: clamp(1.1rem, 1.6vw, 1.3rem); color: var(--color-ink); margin-bottom: 8px; }
.pricing-benefit p { font-size: .92em; line-height: 1.5; color: var(--color-text); }

/* Fallback statyczny /cennik_szkolenia/ → /cennik-szkolen/ (etap 23) -
   sama strona nie ma headera/footera (to techniczny stub przekierowania,
   nie strona treściowa), tylko krótki komunikat na wypadek, gdy meta
   refresh/.htaccess nie zadziała od razu. */
.redirect-notice { max-width: 480px; margin: 18vh auto; padding: 0 24px; text-align: center; }
.redirect-notice p { color: var(--color-text); margin-bottom: 12px; }
.redirect-notice a { font-weight: 700; color: var(--color-fuchsia); }

/* =========================================================
   Reveal + reduced motion
   ========================================================= */
@media (prefers-reduced-motion: no-preference) {
  .reveal { opacity: 0; transform: translateY(20px); transition: opacity .6s var(--ease), transform .6s var(--ease); }
  .reveal.is-visible { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .site-nav { transition: none !important; }
}

/* =========================================================
   Panel podopiecznego (Panel MVP — etap 1, patrz PANEL_KLIENTA.md)
   Osobny, minimalny "app chrome" — nie reużywa .site-header/.site-nav
   marketingowych (te obsługują lejek sprzedażowy z pełną nawigacją do
   sekcji homepage; panel jest osobną, zalogowaną częścią systemu z inną
   listą pozycji nawigacji). Reużywa wyłącznie globalne tokeny i istniejące
   klasy komponentów (.wrap, .btn, .field, .field__error, .form__summary,
   .eyebrow, .wordmark) — zero nowych wariantów tych komponentów.
   ========================================================= */

/* Finalny redesign (patrz CLAUDE.md, "Finalne wdrożenie — panel zgodny z
   WWW") — poprzednia, ciepła kremowo-beżowa "brandowa" paleta panelu
   (etap 9D) jest COFNIĘTA. Audyt wykazał, że łamała DESIGN.md §4 (twardy
   zakaz "beżowej, kremowej... dominanty") i wprowadzała kolory marki
   (--panel-brown/--panel-sage) nigdzie w DESIGN.md niezatwierdzone. Panel
   dziś NIE nadpisuje już kolorów tokenów globalnych — dziedziczy dokładnie
   tę samą jasnoszaro-białą paletę co reszta strony (--color-bg:#F1F1F3,
   --color-surface:#FFFFFF, itd. z :root). Jedyny override, który zostaje,
   to --container (patrz niżej) - czysto funkcjonalna potrzeba szerszego
   contentu dla layoutu z sidebarem, nie kwestia koloru/marki. */
.panel-page {
  /* Popr. po live review (2 tury) — panel wyglądał zbyt drobno na dużych
     ekranach. Szerszy content (bez zmiany --container na reszcie serwisu -
     nadpisanie WYŁĄCZNIE w zasięgu .panel-page), doprecyzowany do
     1180-1280px zakresu po drugiej turze feedbacku. */
  --container: 1240px;

  background: var(--color-bg);
}

/* ---- Ekran ładowania, zanim frontend potwierdzi token (panel/index.html) ----
   [hidden] override konieczny - .panel-loading{display:flex} ma tę samą
   specyficzność co domyślne [hidden]{display:none} przeglądarki i jako
   późniejsza reguła autorska wygrywa (ten sam błąd znaleziony wcześniej
   przy .pricing-group, etap 32 - patrz CLAUDE.md). */
.panel-loading { min-height: 60vh; display: flex; align-items: center; justify-content: center; padding: 24px; text-align: center; }
.panel-loading[hidden] { display: none; }
.panel-loading p { color: var(--color-muted); font-size: .95em; }

/* Logo w headerze stron BEZ sidebara/nawigacji (wyłącznie panel/onboarding/
   - świadomie bez .panel-nav, patrz sekcja "Onboarding" niżej w pliku) -
   te strony nie mają .panel-sidebar__brand, więc marka zostaje w
   .panel-header jak dotychczas, w niezmienionym, mniejszym rozmiarze. */
.panel-header__wordmark .wordmark__icon,
.panel-header__wordmark .wordmark__logo { height: 32px; width: auto; }

/* ---- Sidebar (marka + nawigacja) ----
   KOREKTA "Content + Mobile + Panel UX" §5 — poniżej 1024px pasek linków
   poziomo przewijalny (dawny "bez hamburgera" mechanizm) jest teraz
   ZASTĄPIONY mobilnym drawerem (patrz .panel-drawer* wyżej) jako główny
   sposób nawigacji - sam <nav class="panel-nav"> zostaje w HTML (żeby nie
   duplikować logiki JS ani ryzykować rozjazdu treści), ale jest ukryty na
   tej szerokości (patrz reguła `.panel-sidebar > .panel-nav` niżej) - jego
   treść żyje teraz w .panel-drawer__nav (dokładna kopia tego samego
   markupu). Marka/logo zostaje widoczna na górze strony niezależnie od
   drawera. Od 1024px: pełnowymiarowy, stały pionowy sidebar (patrz siatka
   .panel-shell niżej) z dekoracją psa na kocyku u dołu
   (dog-decoration-sidebar-blanket, WYŁĄCZNIE jako mały background-image
   lokalnej dekoracji). ---- */
/* "Final background cleanup" (13.09.2026) - sidebar (mobile pasek u góry
   I desktopowa kolumna, ta sama klasa) dostaje jasnoróżowe tło #FFF3F8 -
   jedyny kolor panelu poza fuksją-akcentem, patrz .panel-nav__link niżej. */
.panel-sidebar { background: #FFF3F8; border-bottom: var(--border-width) solid var(--color-line); }
.panel-sidebar__brand { display: flex; align-items: center; gap: 10px; padding: 16px 20px; }
.panel-sidebar__brand-icon { height: 44px; width: auto; }
.panel-sidebar__brand-logo { height: 30px; width: auto; }
@media (max-width: 1023.98px) {
  .panel-sidebar > .panel-nav { display: none; }
  /* Hamburger siedzi teraz OBOK loga w tym samym wierszu (poprzednio osobny
     wiersz w .panel-header, z tekstem "Menu") - .panel-sidebar staje się
     poziomym paskiem brand+przycisk, justify-content:space-between rozpycha
     je do przeciwległych krawędzi bez potrzeby margin-left:auto na
     przycisku. */
  .panel-sidebar { display: flex; align-items: center; justify-content: space-between; padding-right: 16px; }
}
/* Ikony liniowe przy pozycjach nawigacji (patrz sprite SVG na każdej
   stronie panelu, symbole #icon-nav-*) - proste, generyczne piktogramy
   (dom/łapa/zegar/kalendarz/cel/gwiazda/dokument/play/książka/koperta),
   NIE loga marek - to jedyny przypadek, gdzie hand-drawn SVG jest bezpieczne
   (zasada z CLAUDE.md dot. etapu 17F.6 zabraniała odtwarzania Z PAMIĘCI
   kształtów LOGO Instagram/Facebook/TikTok, nie generycznych piktogramów). */
.panel-nav__icon { width: 20px; height: 20px; flex-shrink: 0; }

/* ---- Nagłówek panelu ("topbar" prawej kolumny od 1024px) ---- */
.panel-header {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 16px;
  padding: 14px 20px;
  background: var(--color-surface);
  border-bottom: var(--border-width) solid var(--color-line);
}
@media (min-width: 768px) { .panel-header { padding-inline: 40px; } }
@media (min-width: 1024px) { .panel-header { min-height: 76px; padding-block: 14px; } }
.panel-header__greeting-wrap { display: flex; flex-direction: column; gap: 2px; }
.panel-header__greeting { font-family: var(--font-display); font-weight: 600; font-size: 1.25rem; color: var(--color-ink); margin: 0; }
@media (min-width: 1024px) { .panel-header__greeting { font-size: 1.6rem; } }
.panel-header__subgreeting { font-size: .9em; color: var(--color-muted); margin: 0; }
/* margin-left:auto (nie justify-content:space-between na rodzicu) - status
   i wylogowanie zawsze przy prawej krawędzi, niezależnie od szerokości
   powitania po lewej. KOREKTA po 2. turze live review §4 — powitanie jest
   teraz w topbarze na WSZYSTKICH stronach z sidebarem, w tym na
   Dashboardzie (wcześniej Dashboard miał je wyłącznie jako duży H1 w
   treści - usunięte stamtąd, patrz panel/index.html, żeby nie dublować
   tego samego "Cześć, [Imię]!" w dwóch miejscach na tej samej stronie). */
.panel-header__actions { display: flex; align-items: center; gap: 12px; margin-left: auto; }
/* KOREKTA "kontrola po live review" §4 - status współpracy i "Wyloguj się"
   nie mają zajmować miejsca w głównym mobile headerze <1024px (oba
   dostępne w drawerze: #panel-drawer-status-badge/#panel-drawer-logout-btn,
   mirrorowane przez script.js). Powitanie (.panel-header__greeting-wrap)
   zostaje widoczne - dotyczy wyłącznie statusu/wylogowania. Od 1024px
   (brak drawera) oba wracają jako jedyny sposób ich pokazania. */
@media (max-width: 1023.98px) { .panel-header__actions { display: none; } }

/* Przycisk otwierający mobilny drawer (polecenie "Content + Mobile + Panel
   UX" §5, ikonka-bez-podpisu i pozycja obok loga - poprawka live review) -
   żyje dziś jako bezpośrednie dziecko .panel-sidebar (obok
   .panel-sidebar__brand, patrz reguła @media wyżej), nie .panel-header.
   Widoczny WYŁĄCZNIE <1024px - na desktopie sidebar jest już zawsze
   widoczny więc hamburger jest zbędny i jawnie ukryty (reguła @media
   niżej), zamiast dublować całą nawigację jako drugi, zbędny napis "Menu"
   w topbarze. Tylko 3 kreski, bez tekstu - aria-label niesie nazwę dla
   czytników ekranu. */
.panel-header__menu-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 40px;
  height: 40px;
  background: none;
  border: var(--border-width) solid var(--color-line);
  border-radius: var(--radius-pill);
  color: var(--color-ink);
  cursor: pointer;
}
.panel-header__menu-btn:hover, .panel-header__menu-btn:focus-visible { background: var(--color-surface-alt); }
.panel-header__menu-icon { width: 20px; height: 20px; flex-shrink: 0; }
@media (min-width: 1024px) { .panel-header__menu-btn { display: none; } }

/* Etap 9D — "aktywny" traktowany jako stan pozytywny/premium (miękki
   różowy tint zamiast zimnego turkusu), spójny z resztą palety. */
.panel-status-badge {
  display: inline-flex;
  align-items: center;
  padding: 6px 14px;
  border-radius: var(--radius-pill);
  background: var(--color-fuchsia-soft);
  color: var(--color-ink);
  font-weight: 700;
  font-size: 12px;
  white-space: nowrap;
}
.panel-status-badge[hidden] { display: none; }
.panel-status-badge--inactive { background: var(--color-surface-alt); color: var(--color-muted); }

.panel-nav {
  display: flex;
  gap: 6px;
  padding: 10px 24px;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
@media (min-width: 768px) { .panel-nav { padding-inline: 40px; } }
.panel-nav__link {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 16px;
  border-radius: var(--radius-pill);
  font-size: 13px;
  font-weight: 700;
  color: var(--color-text);
  text-decoration: none;
  white-space: nowrap;
  transition: background-color .15s var(--ease), color .15s var(--ease);
}
/* "Final background cleanup" (13.09.2026) - hover subtelnie ciemniejszy
   od jasnoróżowego tła sidebara (#FFF3F8), ale wyraźnie słabszy niż
   aktywna pozycja (#F8D9E9) - hover nie może wyglądać jak "prawie
   aktywne". */
a.panel-nav__link:hover, a.panel-nav__link:focus-visible { background: #FCE5F0; color: var(--color-ink); }
.panel-nav__link.is-active { background: #F8D9E9; color: var(--color-fuchsia-hover); font-weight: 800; }
.panel-nav__link--soon { color: var(--color-muted); cursor: default; }
.panel-nav__link--soon em { font-style: normal; font-weight: 500; opacity: .7; font-size: .9em; }

/* =========================================================
   Mobilny drawer (polecenie "Content + Mobile + Panel UX" §5-6) - JEDEN
   spójny komponent (te same klasy/CSS/JS) na wszystkich 10 stronach z
   sidebarem. Zastępuje pozioty, przewijalny pasek nawigacji <1024px jako
   GŁÓWNY sposób nawigacji na telefonie/tablecie (sam .panel-nav zostaje w
   DOM z tych samych powodów co dotychczas - fallback bez JS, patrz niżej -
   ale drawer jest tym, czego użytkownik faktycznie dotyka). Wyłączony
   całkowicie od 1024px (desktop ma stały sidebar, drawer jest zbędny).
   Markup: .panel-drawer (fixed, position:relative dla dzieci) >
   .panel-drawer__overlay (tło) + .panel-drawer__panel (właściwy wysuwany
   panel, position:absolute left:0). Stan otwarty/zamknięty to WYŁĄCZNIE
   klasa .is-open (nie atrybut [hidden] - hidden blokowałby animację
   transform/opacity, [hidden] nie da się animować). ========================================================= */
.panel-drawer { position: fixed; inset: 0; z-index: 60; }
@media (min-width: 1024px) { .panel-drawer { display: none; } }
.panel-drawer:not(.is-open) { pointer-events: none; }
.panel-drawer__overlay {
  position: absolute;
  inset: 0;
  background: rgba(34, 33, 39, .45);
  opacity: 0;
  visibility: hidden;
  transition: opacity .2s var(--ease), visibility .2s var(--ease);
}
.panel-drawer.is-open .panel-drawer__overlay { opacity: 1; visibility: visible; }
.panel-drawer__panel {
  position: absolute;
  top: 0;
  left: 0;
  height: 100dvh;
  width: min(86vw, 340px);
  background: #FFF3F8;
  box-shadow: 0 0 48px rgba(28, 24, 31, .22);
  display: flex;
  flex-direction: column;
  transform: translateX(-100%);
  transition: transform .25s var(--ease);
  overflow-y: auto;
}
.panel-drawer.is-open .panel-drawer__panel { transform: translateX(0); }
@media (prefers-reduced-motion: reduce) {
  .panel-drawer__overlay, .panel-drawer__panel { transition: none; }
}
.panel-drawer__header { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 20px; border-bottom: var(--border-width) solid var(--color-line); flex-shrink: 0; }
.panel-drawer__brand { padding: 0; }
.panel-drawer__brand .panel-sidebar__brand-icon { height: 40px; }
.panel-drawer__brand .panel-sidebar__brand-logo { height: 28px; }
.panel-drawer__close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  flex-shrink: 0;
  background: none;
  border: none;
  border-radius: var(--radius-sm);
  color: var(--color-ink);
  cursor: pointer;
}
.panel-drawer__close:hover, .panel-drawer__close:focus-visible { background: var(--color-surface-alt); }
.panel-drawer__close svg { width: 22px; height: 22px; display: block; }
/* Nav wewnątrz drawera reużywa dokładnie .panel-nav/.panel-nav__link (te
   same klasy co pasek pod topbarem i desktopowy sidebar) - nadpisany
   wyłącznie układ na pionową listę pełnej szerokości. */
.panel-drawer__nav {
  flex: 1;
  flex-direction: column;
  align-items: stretch;
  gap: 4px;
  padding: 14px;
  overflow: visible;
}
.panel-drawer__nav .panel-nav__link, .panel-drawer__nav .panel-nav__link--soon {
  width: 100%;
  justify-content: flex-start;
  gap: 12px;
  padding: 13px 16px;
  font-size: 15px;
  white-space: normal;
}
.panel-drawer__footer { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 16px 20px; border-top: var(--border-width) solid var(--color-line); flex-shrink: 0; }

/* Siatka "sidebar + content" od 1024px.
   KOREKTA po live review §1 — poprzednia wersja opierała się na
   ":has(> .panel-sidebar)" I NIEZALEŻNIE, bezwarunkowo stylowała
   .panel-sidebar/.panel-nav jako pionowy flex w tym samym media query.
   To dwie osobne reguły, które MUSIAŁY zadziałać razem, żeby wyglądać
   poprawnie - a nie były do siebie w żaden sposób "spięte". Jeśli z
   jakiegokolwiek powodu selektor grida nie dopasował się (np. inna wersja
   przeglądarki/silnika w Local, kolejność przetwarzania :has()), sidebar
   i tak dostawał display:flex/flex-direction:column i rozciągał się na
   PEŁNĄ szerokość strony (bo rodzic .panel-shell zostawał zwykłym
   display:block, nie gridem) - dokładnie zgłoszony błąd. Naprawione przez
   jawną klasę .has-sidebar na #panel-shell (dodaną w HTML na wszystkich
   10 stronach z nawigacją, brak na panel/onboarding/) - WSZYSTKIE reguły
   niżej są teraz zagnieżdżone pod TYM SAMYM selektorem `.panel-shell.
   has-sidebar`, więc siatka i wygląd sidebara stosują się ZAWSZE razem,
   nigdy częściowo. Krócej: grid i "pionowy sidebar" są teraz jedną,
   atomową regułą zamiast dwóch osobnych, które musiały się zgadzać. */
@media (min-width: 1024px) {
  .panel-shell.has-sidebar:not([hidden]) {
    display: grid;
    grid-template-columns: 300px minmax(0, 1fr);
    align-items: stretch;
    min-height: 100vh;
  }
  /* KOREKTA "ostatnia korekta sidebara" - zastępuje CAŁY mechanizm
     max-height/padding-bottom-rezerwa z poprzedniej tury (zgadywany
     breakpoint 950px fałszywie łapał typowe ekrany ok. 900px wysokości).
     Dziś sidebar to zwykły, stabilny flex-column BEZ żadnego breakpointu
     wysokości: brand (flex:0 0 auto, naturalna wysokość) → nav (flex:1 1
     auto + min-height:0, wypełnia CAŁĄ resztę dostępnej przestrzeni) →
     decor (flex:0 0 auto, stała wysokość ~260px, NORMALNY ostatni element
     kolumny, nie position:absolute/fixed). `min-height:0` na nav jest tu
     kluczowe - bez tego flex item domyślnie nie kurczy się poniżej
     wysokości własnej treści, więc `overflow-y:auto` nigdy by się nie
     uruchomił. Z `min-height:0` nav faktycznie przyjmuje dokładnie tyle
     miejsca, ile zostaje po brand+decor, i dopiero gdy jego RZECZYWISTA
     treść (10 pozycji) jest wyższa niż ta przestrzeń, samoistnie
     uruchamia się wewnętrzny scroll - bez zgadywania żadnej konkretnej
     wysokości viewportu, działa poprawnie na każdej. `position:sticky;
     top:0; height:100dvh` na samym sidebarze (bez zmian) - box zawsze ma
     wysokość viewportu i zostaje przyklejony do góry podczas
     scrollowania długiej strony głównej treści. */
  .panel-shell.has-sidebar > .panel-sidebar {
    display: flex;
    flex-direction: column;
    position: sticky;
    top: 0;
    height: 100dvh;
    overflow: hidden;
    border-bottom: none;
    border-right: var(--border-width) solid var(--color-line);
    background-color: #FFF3F8;
  }
  /* KOREKTA "live review 3" - logo/wordmark było przycinane. Prawdziwa
     przyczyna: `logo-pan-piesel-icon.png` (kwadrat 1:1) w wysokości 70px
     ma szerokość 70px, a `logo-pan-piesel-wordmark.png` (proporcje 6.4:1)
     w wysokości 46px ma szerokość 46×6.4≈294px - razem z gapem 18px i
     paddingiem 32px×2 to ~446px potrzebnej szerokości W KOLUMNIE SZEROKIEJ
     NA 300px. Wcześniej (bez overflow:hidden na .panel-sidebar) ten
     nadmiar po prostu wylewał się poza sidebar bez wizualnej skargi -
     odkąd sidebar dostał `overflow:hidden` (poprawka sticky/decor, patrz
     niżej), ten sam nadmiar zaczął być realnie ucinany. Naprawione
     ZMNIEJSZENIEM wysokości obu obrazków (NIE assetów - te same pliki,
     mniejszy render) tak, żeby całość + padding mieściła się w 300px z
     zapasem: icon 38px (szer. 38px) + logo 28px (szer. 28×6.4≈179px) +
     gap 10px + padding 24px×2 = ok. 275px - mieści się z ~25px zapasu,
     bez cropu, bez rozciągania, proporcje bez zmian (height/width:auto). */
  .panel-shell.has-sidebar .panel-sidebar__brand { position: relative; z-index: 1; padding: 32px 24px 26px; gap: 10px; flex: 0 0 auto; }
  .panel-shell.has-sidebar .panel-sidebar__brand-icon { height: 38px; }
  .panel-shell.has-sidebar .panel-sidebar__brand-logo { height: 28px; }
  /* flex:1 1 auto + min-height:0 - nav wypełnia dokładnie tyle miejsca,
     ile zostaje w kolumnie po brand i decor (oba flex:0 0 auto, stała
     wysokość). Bez żadnego breakpointu: jeśli 10 pozycji nav mieści się
     w tej przestrzeni, stoi nieruchomo (overflow-y:auto nic nie robi,
     bo nie ma czego przewijać); jeśli nie mieści się (bardzo niski
     viewport), scrolluje się WEWNĘTRZNIE samoistnie - przeglądarka sama
     to wykrywa z realnej wysokości treści, nie z zgadywanego px. */
  .panel-shell.has-sidebar .panel-nav {
    flex: 1 1 auto;
    min-height: 0;
    flex-direction: column;
    align-items: stretch;
    gap: 6px;
    padding: 10px 18px;
    position: relative;
    z-index: 1;
    overflow-y: auto;
    overflow-x: hidden;
  }
  .panel-shell.has-sidebar .panel-nav__link,
  .panel-shell.has-sidebar .panel-nav__link--soon {
    width: 100%;
    justify-content: flex-start;
    gap: 12px;
    padding: 13px 16px;
    font-size: 15px;
  }
  /* Aktywna pozycja w desktopowym sidebarze - świadomie NIE typowa SaaS
     pigułka (polecenie §3): mniejszy, "chip" radius zamiast pełnej
     pigułki + cienki fuksjowy marker po lewej krawędzi. padding-left
     zmniejszony o dokładnie szerokość markera, żeby tekst nie "skakał"
     względem nieaktywnych pozycji. */
  .panel-shell.has-sidebar .panel-nav__link.is-active {
    border-radius: var(--radius-sm);
    padding-left: 13px;
    border-left: 3px solid var(--color-fuchsia);
  }
  .panel-shell.has-sidebar .panel-shell__content { display: flex; flex-direction: column; min-height: 100vh; }

  /* Editorial dolny blok sidebara (pies na kocyku + "dobrze, że tu jesteś" +
     serduszko) - dekoracja jest NORMALNYM, ostatnim elementem flex-column
     sidebara (flex:0 0 auto, stała wysokość - patrz komentarz "§M" niżej
     za aktualną wartość i historię kolejnych korekt), nie position:
     absolute/fixed nachodzącym na nav. Efekt: brand na górze, nav w
     środku (wypełnia resztę, przewija się WEWNĘTRZNIE tylko gdy realnie
     potrzeba - patrz .panel-nav wyżej), dekoracja zawsze na samym dole -
     trzy zwykłe bloki jeden pod drugim, zero nakładania z definicji (nie
     z rezerwowanego marginesu). `position:relative` zostaje - to kontekst
     dla trzech obrazków w środku (handwriting/heart/dog), które nadal są
     position:absolute WZGLĘDEM TEGO diva. `overflow:hidden` -
     zabezpieczenie, gdyby któryś z trzech obrazków w środku wystawał poza
     własny box. pointer-events:none - to czysta dekoracja, nigdy nie
     przechwytuje kliknięć. */
  /* "Finalna ankieta startowa" §M - wysokość zmniejszona 265px→200px (w
     żądanym zakresie 190-215px). Sam dog (bottom:0, wysokość ~106px przy
     szerokości 185px, 700×400 oryginał) NIETKNIĘTY - kompresji podlega
     wyłącznie pusta przestrzeń MIĘDZY psem a napisem (było 79px, jest
     14px), żeby napis był bliżej psa, tak jak explicite poproszono. */
  .panel-shell.has-sidebar .panel-sidebar__decor {
    display: block;
    flex: 0 0 auto;
    position: relative;
    left: auto;
    right: auto;
    bottom: auto;
    width: 100%;
    height: 200px;
    pointer-events: none;
    z-index: 0;
    overflow: hidden;
  }
  .panel-shell.has-sidebar .panel-sidebar__decor-handwriting {
    position: absolute;
    left: 38px;
    bottom: 120px;
    width: 140px;
    height: auto;
    display: block;
  }
  .panel-shell.has-sidebar .panel-sidebar__decor-heart {
    position: absolute;
    left: 157px;
    bottom: 110px;
    width: 24px;
    height: auto;
    display: block;
  }
  .panel-shell.has-sidebar .panel-sidebar__decor-dog {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    bottom: 0;
    width: 185px;
    height: auto;
    display: block;
  }
}
/* Poza desktopowym sidebarem (<1024px, gdzie .panel-sidebar jest poziomym
   paskiem na górze strony) dekoracja jest całkowicie ukryta - ten sam
   .panel-sidebar__decor div istnieje w HTML na wszystkich stronach, ale
   nie renderuje się poniżej 1024px. */
.panel-sidebar__decor { display: none; }
@media (min-width: 1024px) {
  .panel-shell.has-sidebar .panel-main { flex: 1; }
}

/* ---- Treść dashboardu ---- */
.panel-main { padding-block: 40px 64px; }
@media (min-width: 1024px) { .panel-main { padding-block: 56px 80px; } }
@media (min-width: 1440px) { .panel-main { padding-block: 64px 96px; } }

/* "Final background cleanup" (13.09.2026) - REZYGNACJA z całego systemu
   pastelowych teł per strona / Dalmatian spots / pattern A/B/C (obie
   poprzednie tury tego kierunku, "pastel page backgrounds" i "white +
   dalmatian spots" + "shape correction", USUNIĘTE CAŁKOWICIE, łącznie z
   --spot-1/--spot-2/--spot-graphite, .panel-spots--a/--b/--c i
   .panel-main::before). Finalny kierunek jest prosty: jednolite białe
   .panel-main na wszystkich stronach panelu - kolor/charakter żyje dziś
   wyłącznie w sidebarze (patrz .panel-shell.has-sidebar > .panel-sidebar
   niżej). */
.panel-main { background: #FFFFFF; }
.panel-main__heading {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(2rem, 4vw, 3.4rem);
  letter-spacing: -.01em;
  color: var(--color-ink);
  margin-top: 10px;
}
.panel-main__lead { font-size: 1.15rem; line-height: 1.6; color: var(--color-text); max-width: 68ch; margin-top: 14px; margin-bottom: 40px; }
/* Drugorzędna notatka pod leadem (np. "Moje cele" - limit 2 aktywnych na
   psa) - mniejsza i przygaszona, nie konkuruje z głównym leadem. Odstęp
   od bezpośrednio poprzedzającego leadu zmniejszony WYŁĄCZNIE w tej
   konkretnej kombinacji (sąsiedzki selektor), nie dotyka .panel-main__lead
   używanego samodzielnie na innych stronach panelu. */
.panel-main__lead + .panel-main__note { margin-top: -26px; }
.panel-main__note { font-size: .95em; color: var(--color-muted); margin-bottom: 40px; }

/* Friends × Premium (polecenie §4) — hero to teraz OTWARTA sekcja, bez
   karty/obrysu/tła (poprzednia "banner-karta" z poprzedniej tury świadomie
   cofnięta). Dużo white space zamiast card chrome; jedyny akcent to ten
   sam CSS-owy fuksjowy marker pod H1 co na "Moje psy" (spójny, systemowy
   sygnet dwóch analogicznych intro bloków aplikacji) - żadnego obrazka
   underline. */
.panel-hero { margin-bottom: 48px; }
@media (min-width: 1024px) { .panel-hero { margin-bottom: 56px; } }
.panel-hero .panel-main__heading { position: relative; display: inline-block; padding-bottom: 14px; }
.panel-hero .panel-main__heading::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 64px;
  height: 4px;
  border-radius: var(--radius-pill);
  background: var(--color-fuchsia);
}
.panel-hero .panel-main__lead { margin-bottom: 0; }

/* "Final UI pass - full section shells" (13.09.2026) - ZASTĘPUJE poprzednią
   turę ("friendly premium pass"): małe pastelowe page-hero (WYŁĄCZNIE
   H1+lead+decor) uznane za niewystarczające - CAŁA zawartość każdej z 9
   głównych stron panelu (poza Dashboardem, który ma własny
   .panel-hero/.panel-card--featured wyżej i tej tury nie dotyczy) żyje
   dziś w JEDNYM dużym pastelowym prostokącie: intro (tekst+decor) na
   górze, właściwa treść strony (listy/formularze/accordiony, wszystkie
   BIAŁE) poniżej, w tym samym boxie. `.page-hero*` (poprzednia tura)
   USUNIĘTE CAŁKOWICIE, zastąpione przez `.section-shell*` niżej. */
.section-shell {
  width: 100%;
  box-sizing: border-box;
  border-radius: 30px;
  padding: 38px;
}
@media (max-width: 767px) {
  /* "Mobile shell fix" (13.09.2026) - §3 polecenia: mniejszy poziomy
     padding na mobile (18px zamiast 23px na obu bokach) odzyskuje ~10px
     szerokości contentu - niewielka, celowa korekta, nie rezygnacja z
     "oddechu" (pionowy padding zostaje praktycznie bez zmian). */
  .section-shell { border-radius: 24px; padding: 22px 18px; }
}
/* "Mobile shell fix" (13.09.2026) - ZNALEZIONA PRAWDZIWA PRZYCZYNA "tekst
   łamie się za wcześnie mimo widocznego miejsca": poprzednia wersja
   trzymała H1+lead+note RAZEM w jednym .section-shell__text, które na
   mobile było CAŁYM grid-itemem w kolumnie 1fr obok ikony - więc nie
   tylko H1, ale też lead/note (którym ikona wcale nie przeszkadza) były
   ściśnięte do tej samej wąskiej kolumny przez CAŁĄ wysokość nagłówka.
   Naprawione podziałem nagłówka na 3 niezależne obszary grida: "title"
   (H1, ew. eyebrow) i "decor" dzielą górny wiersz na WSZYSTKICH
   szerokościach; "text" (lead/note) na desktopie zostaje w tej samej
   wąskiej kolumnie co dawniej (decor rozciąga się na oba wiersze, patrz
   niżej - zero zmiany wizualnej na desktopie), ale na mobile (patrz
   @media niżej) dostaje WŁASNY, PEŁNOSZEROKI wiersz - tylko H1 faktycznie
   sąsiaduje z ikoną, lead/note dostają tam pełną szerokość shellu.
   Wymagało to drobnej zmiany HTML na wszystkich 9 stronach shellowych
   (nowy wrapper .section-shell__title wokół H1/eyebrow, .section-shell__
   text zostaje wyłącznie na lead/note) - ten sam jeden system na
   wszystkich, zero nowej treści/kopii poza Celami. */
.section-shell__header {
  display: grid;
  grid-template-columns: 1fr auto;
  grid-template-areas: "title decor" "text decor";
  column-gap: 24px;
  margin-bottom: 32px;
}
.section-shell__title { grid-area: title; min-width: 0; }
.section-shell__title .panel-main__heading { margin-top: 0; }
.section-shell__title .eyebrow { margin-bottom: 6px; }
.section-shell__text { grid-area: text; max-width: 620px; min-width: 0; }
.section-shell__text .panel-main__lead { margin-bottom: 0; }
.section-shell__text .panel-main__note { margin-bottom: 0; }
/* Naprawia znaleziony overlap na "Moje cele" (poprzednia tura) - stary
   `.panel-main__lead + .panel-main__note { margin-top: -26px; }` (patrz
   niżej w pliku) był skalibrowany pod DAWNY margin-bottom:40px leadu;
   wewnątrz shellu lead ma margin-bottom:0 (wyżej), więc ten sam -26px
   ciągnął notatkę wprost NA tekst leadu, nie pod niego. Tekst pozostaje
   w normalnym block flow (żadnego position:absolute) - to była wyłącznie
   kolizja dwóch marginesów, nie błąd pozycjonowania. */
.section-shell__text .panel-main__lead + .panel-main__note { margin-top: 6px; }
/* Dekoracja spina OBA wiersze kolumny 2 na desktopie (ta sama nazwa
   obszaru "decor" powtórzona w obu wierszach grid-template-areas wyżej =
   jeden item rozciągnięty na oba wiersze) - `align-self:center` centruje
   ją pionowo względem całej wysokości title+text, dokładnie jak poprzedni
   flex `align-items:center`. Style/rozmiar ikon bez zmian względem
   poprzedniej tury ("osadzona" w boxie dzięki własnemu marginesowi). */
.section-shell__decor { grid-area: decor; align-self: center; flex-shrink: 0; margin-right: 10px; margin-top: 6px; }
/* Dwie kategorie źródłowych rozmiarów assetów: "mini" ilustracje 512×512
   (mini-availability/next-session/goals/next-event/courses) dostają
   większy render niż płaskie doodle 200-300×200-300 (doodle-heart-
   graphite-single/hearts-graphite-trio/pair, zarowka-brown) - inaczej te
   drugie wyglądałyby nienaturalnie duże/pikselowe względem swojej
   faktycznej szczegółowości. */
.section-shell__decor--mini { width: 122px; height: auto; }
.section-shell__decor--doodle { width: 112px; height: auto; }
@media (max-width: 767px) {
  /* Na mobile dekoracja NIE spina już 2 wierszy (w odróżnieniu od
     desktopu, gdzie zostaje pionowo wyśrodkowana względem title+text) -
     "text" (lead/note) dostaje WŁASNY wiersz na PEŁNĄ szerokość, dekoracja
     zostaje wyłącznie w wierszu z H1. To jest kluczowa różnica względem
     desktopu, nie tylko dostrojenie odstępów. Ikona: `align-self:start`
     przypina ją do SAMEJ GÓRY tego wiersza, czyli wizualnie w linii z H1,
     nigdy niżej (dawny bug: cały tekst nad ikoną w flex-column). */
  .section-shell__header { grid-template-areas: "title decor" "text text"; column-gap: 14px; row-gap: 6px; }
  .section-shell__decor { align-self: start; margin-right: 0; margin-top: 2px; }
  .section-shell__decor--mini { width: 70px; }
  .section-shell__decor--doodle { width: 64px; }
}
/* "Final micro fix - availability mobile" (13.09.2026) - poprzednia tura
   podniosła ikonę Dyspozycyjności do 92px na mobile (patrz historia wyżej),
   co przy realnym teście na 360px nachodziło na H1 "Dyspozycyjność".
   Zmniejszona do 66px (mieści się w żądanym zakresie 64-68px, nadal
   wyraźnie większa niż bazowe 70px innych mini-ikon... nie, mniejsza -
   ale nadal czytelna) + H1 tej jednej strony zmniejszony do 28px (z
   ogólnego ~32px na mobile) + gap w górnym rzędzie title/decor zawężony
   do 8px - WYŁĄCZNIE dla .section-shell--availability, inne strony z
   mini-ilustracjami (grafik/cele/wydarzenia/kursy) zostają nietknięte
   przy 70px/domyślnym H1/14px gap. */
@media (max-width: 767px) {
  .section-shell--availability .section-shell__decor--mini { width: 60px; }
  .section-shell--availability .section-shell__title .panel-main__heading { font-size: 28px; }
  .section-shell--availability .section-shell__header { column-gap: 14px; }
}
.section-shell--dogs { background: #EDF7FC; }
.section-shell--availability { background: #EEF8F2; }
.section-shell--schedule { background: #FFF3EA; }
.section-shell--goals { background: #FCEEF5; }
.section-shell--events { background: #FFF8D9; }
.section-shell--materials { background: #F8F3E9; }
.section-shell--courses { background: #EDF7F1; }
.section-shell--rules { background: #F3EEFB; }
.section-shell--contact { background: #FFF0F6; }
/* Kontakt (§12 polecenia) - jeden CTA, teraz WEWNĄTRZ shellu, bez
   własnego drugiego kolorowego boxu (`.contact-community` traciło tu
   swoje tło/padding - patrz reguła niżej w pliku, sekcja "Panel — Kontakt") -
   sam wyśrodkowuje się w normalnym block flow shellu. */
.section-shell__body { margin-top: 8px; }
/* Formularze BEZ własnej karty (avail-form/goals-custom-form - reszta,
   np. .dog-add__form, już ma białe tło) dostają je tu, jawnie i wąsko
   (WYŁĄCZNIE te dwa ID, nie generyczne `.form` sitewide - login/kontakt/
   inne formularze poza shellami mają zostać dokładnie takie, jak są). */
#avail-form, #goals-custom-form {
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-line);
  border-radius: var(--radius-lg);
  padding: 28px;
}
#goals-custom-form { margin-top: 16px; }

/* Dashboard — hierarchia zamiast ściany identycznych kafelków (DESIGN.md
   zakazuje "layoutu złożonego wyłącznie z podobnych białych kafelków").
   Etap 9E.3a - .panel-dashboard jest teraz JEDNĄ kolumną na każdej
   szerokości (featured karta zajęć -> opcjonalna karta "po zajęciach" ->
   sekcja skrótów), zastępuje dawny układ 2fr/1fr z wąską kolumną po prawej
   (skróty siedziały OBOK karty zajęć, nie pod nią) - jawne polecenie:
   sekcja skrótów ma być bezpośrednio POD główną kartą. Dawny pasek "Szybkie
   skróty" USUNIĘTY całkowicie wcześniej (patrz CLAUDE.md) - te linki są już
   dostępne w głównym menu; TA sekcja (.panel-dashboard__secondary) to
   osobny, treściowy zestaw 4 kart (cele/dyspozycyjność/wydarzenia/notatki). */
.panel-dashboard { display: grid; gap: 24px; }

/* Etap 9E.3a - 4 karty skrótów: 1 kolumna mobile (<640px), 2 kolumny od
   640px wzwyż (włącznie z desktopem - zastępuje dawne repeat(3,1fr) na
   tablecie + powrót do 1 kolumny na desktopie, bo skróty nie są już wąską
   kolumną boczną). */
.panel-dashboard__secondary { display: grid; gap: 20px; grid-template-columns: 1fr; }
@media (min-width: 640px) { .panel-dashboard__secondary { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
/* Karty skrótów nie mają wyglądać jak kopie tej samej karty - polecenie
   "Friends × Premium" §6 zastępuje kolorowe kropki (poprzednia tura)
   prawdziwymi mini-ilustracjami (mini-goals/mini-availability/
   mini-next-event/mini-notes.png). Wydarzenie dostaje dodatkowo mały akcent
   doodle-star-yellow.png w rogu ikony - drobny editorialowy detal, nie
   główna ilustracja. */
/* KOREKTA "live review 3" §8 - ikona i nazwa karty są teraz jednym wierszem
   (.panel-card__heading-row) zamiast miniatury osobno NAD nazwą. Rozmiary
   ikon dopasowane do nowego, mniejszego kontekstu w jednym rzędzie z
   tekstem (44-52px cele/dyspozycyjność, 48-56px wydarzenie - to drugie
   dostaje dodatkowo mały akcent doodle-star-yellow.png w rogu). */
.panel-card__heading-row { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; }
.panel-card__heading-row .panel-card__heading { margin-bottom: 0; }
.panel-card__icon { display: block; width: 48px; height: 48px; object-fit: contain; margin-bottom: 14px; flex-shrink: 0; }
.panel-card__heading-row .panel-card__icon { margin-bottom: 0; }
.panel-card__icon-wrap { position: relative; display: inline-block; margin-bottom: 14px; flex-shrink: 0; }
.panel-card__heading-row .panel-card__icon-wrap { margin-bottom: 0; }
.panel-card__icon-wrap .panel-card__icon { margin-bottom: 0; width: 52px; height: 52px; }
.panel-card__icon-accent { position: absolute; top: -8px; right: -12px; width: 26px; height: 26px; object-fit: contain; }
.panel-card__empty--emphasis { font-weight: 600; color: var(--color-ink); }
/* KOREKTA "live review 4" §2 - na 390px długie nazwy ("Moja dyspozycyjność",
   "Najbliższe wydarzenie") łamały się w sposób kolidujący z ikoną (ikona
   i heading nie miały jawnego flex-basis, więc wiersz zachowywał się
   nieprzewidywalnie przy zawijaniu). `min-width:0` na headingu jest tu
   kluczowe - bez tego flex item domyślnie nie kurczy się poniżej długości
   najdłuższego słowa, co mogło rozpychać kartę/viewport. Ikona ma stały
   flex-basis (flex-shrink:0, ustawiony wyżej) - tekst łamie się WYŁĄCZNIE
   we własnej kolumnie po prawej, nigdy pod/na ikonę. */
@media (max-width: 640px) {
  .panel-card__heading-row { gap: 10px; width: 100%; }
  .panel-card__heading-row .panel-card__icon,
  .panel-card__heading-row .panel-card__icon-wrap .panel-card__icon {
    width: 38px;
    height: 38px;
  }
  .panel-card__heading-row .panel-card__heading {
    flex: 1;
    min-width: 0;
    font-size: 1.125rem;
    line-height: 1.2;
  }
}

/* Karta podstawowa = dokładnie system strony WWW (DESIGN.md §8.1): biały
   surface, cienka linia, radius, ZERO cienia. Cień wolno tylko jednej
   wyróżnionej karcie na widok (--shadow-elevated, ten sam token co reszta
   strony) - tu dostaje go wyłącznie .panel-card--featured. */
.panel-card {
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-line);
  border-radius: var(--radius-lg);
  padding: 28px;
}
@media (min-width: 1024px) { .panel-card { padding: 34px; } }
.panel-card__heading { font-family: var(--font-display); font-weight: 600; font-size: 1.3rem; color: var(--color-ink); margin-bottom: 12px; }
.panel-card__empty { font-size: 1em; line-height: 1.55; color: var(--color-muted); }
.panel-card__link { display: inline-flex; margin-top: 14px; font-weight: 700; font-size: .95em; color: var(--color-fuchsia); }
.panel-card__link[hidden] { display: none; }
.panel-card__link:hover, .panel-card__link:focus-visible { color: var(--color-fuchsia-hover); }

/* Etap 9E.4e §18/§19 polecenia - PRZEBUDOWANE: zamiast wspólnego przycisku +
   pickera "Dla którego celu?", >1 aktywny cel dostaje osobny, kompaktowy
   blok PER cel (.panel-quick-goal-block) - każda akcja od razu zna właściwe
   goal_id, zero dodatkowego kroku wyboru. Mobile-first: pełna szerokość,
   duże tap-targety, kolejne bloki pod sobą (nigdy nested cards w cards). */
.panel-quick-goal-block { margin-top: 16px; padding-top: 16px; border-top: var(--border-width) solid var(--color-line); }
.panel-quick-goal-block:first-child { margin-top: 14px; padding-top: 0; border-top: none; }
.panel-quick-goal-block__title { font-weight: 700; font-size: .95em; color: var(--color-ink); margin-bottom: 2px; }
.panel-quick-goal-block__context { font-size: .85em; color: var(--color-muted); margin-bottom: 10px; }
.panel-quick-goal-actions { display: flex; flex-direction: column; gap: 10px; }
.panel-quick-goal-actions .btn { width: 100%; min-height: 44px; }
@media (min-width: 480px) { .panel-quick-goal-actions { flex-direction: row; } .panel-quick-goal-actions .btn { width: auto; flex: 1 1 0; } }
.panel-quick-goal-panel { margin-top: 12px; }
.panel-quick-goal-panel:empty { margin-top: 0; }
/* "Moja dyspozycyjność" ma być bardziej "action oriented" (polecenie §6) -
   CTA jako prawdziwy wypełniony przycisk zamiast gołego linku. Zadeklarowana
   PO .panel-card__link, więc wygrywa w kaskadzie przy tej samej
   specyficzności - bez !important, bez mieszania z globalnym .btn (który
   ma inną, sprzeczną regułę koloru zdefiniowaną wcześniej w pliku). */
.panel-card__link--cta {
  background: var(--color-fuchsia);
  color: var(--color-white);
  padding: 11px 20px;
  border-radius: var(--radius-pill);
  font-weight: 800;
}
.panel-card__link--cta:hover, .panel-card__link--cta:focus-visible { background: var(--color-fuchsia-hover); color: var(--color-white); }

/* Etap 9E.2 §41/§47 polecenia - karta "Jesteś po zajęciach ♡" na dashboardzie,
   widoczna WYŁĄCZNIE gdy jest zakończona sesja bez notatki/bez "Nie teraz". */
.panel-card--note-prompt { background: var(--color-fuchsia-soft); border-color: var(--color-fuchsia-soft); margin-bottom: 24px; }
.panel-card--note-prompt[hidden] { display: none; }
.panel-card__actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 14px; }

/* Główny, wyróżniony blok dashboardu ("Najbliższe zajęcia") - wizualny
   bohater dashboardu, przebudowany pod zaakceptowaną makietę "Friends ×
   Premium" (polecenie §5): poziomy blok, bardzo lekkie fuchsia-soft tło
   (NIE biel + border-left jak w poprzedniej turze), bez cienia, tekst po
   lewej / pies + odręczne hasło + serca po prawej na desktopie, tekst nad
   psem na mobile. */
.panel-card--featured {
  background: var(--color-fuchsia-soft);
  border: none;
  box-shadow: none;
  padding: 32px 28px;
  display: grid;
  grid-template-columns: 1fr;
  gap: 28px;
}
/* KOREKTA "precyzyjne pozycjonowanie" §3 — jawne minmax na obu kolumnach
   (nie "1.3fr 1fr" bez dolnej granicy): kolumna art nigdy nie skurczy się
   poniżej 280px, kolumna treści nigdy nie zabierze jej całej szerokości.
   align-items:center dotyczy kolumny treści (naturalnie krótsza); art
   dostaje własny align-self:stretch niżej, żeby mieć pełną wysokość
   wiersza niezależnie od tego, jak krótki jest tekst. */
@media (min-width: 1024px) {
  .panel-card--featured { grid-template-columns: minmax(0, 1.25fr) minmax(280px, .75fr); align-items: center; gap: 32px; padding: 48px; min-height: 320px; }
}
/* Szerokość zwiększona z 460px (poprzednia tura, przypadkowo za wąska -
   wymuszała niepotrzebne dodatkowe łamanie H2) - polecenie §6 dopuszcza
   zmianę proporcji kolumn, jeśli treść łamie się nienaturalnie. Font H2
   BEZ ZMIAN (2.2rem), tylko więcej miejsca na tę samą treść. */
.panel-card--featured__body { max-width: 520px; }
.panel-card--featured__eyebrow { color: var(--color-fuchsia-hover); }
.panel-card--featured__heading { font-family: var(--font-display); font-weight: 600; font-size: 1.9rem; color: var(--color-ink); margin-top: 10px; }
@media (min-width: 1024px) { .panel-card--featured__heading { font-size: 2.2rem; } }
/* "Friendly premium pass" (13.09.2026) - godzina jest RÓWNIE dużym tekstem
   co data (§1 polecenia - "duży tekst: data / godzina"), tuż pod nią, bez
   dodatkowego odstępu (ta sama wizualna "jedna duża informacja" w dwóch
   liniach). [hidden] w stanie pustym/błędu/ładowania. */
.panel-card--featured__time { font-family: var(--font-display); font-weight: 600; font-size: 1.9rem; color: var(--color-ink); margin-top: 0; }
@media (min-width: 1024px) { .panel-card--featured__time { font-size: 2.2rem; } }
.panel-card--featured__time[hidden] { display: none; }
.panel-card--featured__lead { font-size: 1.05rem; color: var(--color-text); margin-top: 10px; }
.panel-card--featured__location { font-size: .92rem; color: var(--color-muted); margin-top: 4px; }
.panel-card--featured__location[hidden] { display: none; }
.panel-card--featured .panel-card__link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 22px;
  padding: 12px 22px;
  border: var(--border-width) solid var(--color-fuchsia);
  border-radius: var(--radius-pill);
  font-weight: 800;
  color: var(--color-fuchsia);
  transition: background-color .15s var(--ease), color .15s var(--ease);
}
.panel-card--featured .panel-card__link:hover, .panel-card--featured .panel-card__link:focus-visible {
  background: var(--color-fuchsia);
  color: var(--color-white);
}
/* Prawa kolumna (<1024px, jedna kolumna, art POD tekstem) - KOREKTA "live
   review 3": poprzednia wersja kładła hasło absolutnie w lewym górnym rogu
   (left:4%;top:2%), co realnie nachodziło na twarz wyśrodkowanego psa.
   Dziś .panel-card--featured__art jest kolumnowym flexem: 1) pies (zwykły
   flow, wyśrodkowany), 2) hasło POD psem (też zwykły flow, nie absolute) -
   kolejność w DOM = kolejność wizualna, zero nachodzenia z definicji.
   Serce zostaje jedynym elementem position:absolute - mały akcent w
   górnym prawym rogu kompozycji, poza obszarem psa. */
.panel-card--featured__art {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-top: 8px;
  min-height: 200px;
}
.panel-card--featured__dog { position: relative; width: 240px; max-width: 70%; height: auto; display: block; }
.panel-card--featured__handwriting {
  position: relative;
  margin-top: 12px;
  width: 140px;
  max-width: 55%;
  height: auto;
  transform: rotate(-2deg);
}
.panel-card--featured__heart { position: absolute; right: 10%; top: 0; width: 26px; height: auto; }
@media (max-width: 640px) {
  .panel-card--featured__dog { max-width: 230px; }
  .panel-card--featured__handwriting { width: 132px; }
}

/* KOREKTA "precyzyjne pozycjonowanie" §3-§5 — desktop (≥1024px): jawny art
   container zamiast luźnych procentów względem całej karty. min-height +
   align-self:stretch (nadpisuje align-items:center rodzica WYŁĄCZNIE dla
   tego dziecka) - art ma zawsze pełną wysokość wiersza, niezależnie od
   długości tekstu po lewej. overflow:hidden - wyłącznie zabezpieczenie na
   wypadek skrajnie wąskiej kolumny (grid ma minmax(280px,...)), NIE
   mechanizm przycinania psa (dog ma object-fit:contain + max-height
   dobrany tak, żeby zmieścić się w całości, patrz niżej). */
@media (min-width: 1024px) {
  .panel-card--featured__art {
    position: relative;
    display: block;
    min-height: 300px;
    align-self: stretch;
    overflow: hidden;
    margin-top: 0;
  }
  /* Pies zakotwiczony bottom-right, NIE centrowany, NIE procentami
     viewportu. max-height (nie height:100%) celowo zostawia czyste pole
     u góry art containera dla hasła/serc - inaczej pies (portretowe
     zdjęcie, wysoki format) wypełniłby całą wysokość kolumny aż po sam
     szczyt i wszedł pod hasło. object-fit:contain gwarantuje, że głowa/
     uszy nigdy nie są przycięte niezależnie od finalnych proporcji boxu. */
  .panel-card--featured__dog {
    position: absolute;
    right: 24px;
    bottom: 0;
    top: auto;
    left: auto;
    width: 295px;
    max-width: 85%;
    height: auto;
    max-height: 235px;
    object-fit: contain;
    object-position: bottom right;
  }
  /* KOREKTA "kontrola po live review" - poprzednia wersja kotwiczyła
     hasło/serca do PRAWEJ krawędzi (`right:215px`/`right:185px`), co
     zakładało szeroki art container (~430-460px, jak na bardzo szerokim
     desktopie). Przy węższym art containerze (kolumna ma tylko
     minmax(280px,...) - realny floor przy 1024-1280px) ten sam `right`
     w pikselach przesuwał lewą krawędź hasła POZA container (280-215-155
     = -90px), a `.panel-card--featured__art` ma `overflow:hidden` - ok.
     90px szerokości hasła było ucinane, zostawał tylko wąski, ledwo
     widoczny skrawek. Naprawione kotwiczeniem do LEWEJ krawędzi małymi,
     stałymi wartościami - matematycznie mieści się w KAŻDEJ szerokości
     art containera (floor 280px), niezależnie od proporcji. Pies jest
     zakotwiczony do DOŁU (bottom:0, max-height:235 w kontenerze
     min-height:300) - jego górna krawędź jest zawsze ≥65px od góry, więc
     hasło/serca umieszczone w paśmie y:0-60px nigdy nie nachodzą na psa,
     niezależnie od szerokości art containera. */
  .panel-card--featured__handwriting {
    left: 20px;
    right: auto;
    top: 18px;
    width: 150px;
    max-width: 55%;
    height: auto;
  }
  .panel-card--featured__heart {
    left: 150px;
    right: auto;
    top: 6px;
    width: 30px;
    height: auto;
  }
}

.panel-footer { padding: 24px 24px 40px; text-align: center; }
.panel-footer p { font-size: .85em; color: var(--color-muted); }
.panel-footer a { color: var(--color-text); font-weight: 700; }

/* Etap 9D — drugorzędne przyciski panelu ("Edytuj", "+ Dodaj psa", "Wybierz
   zdjęcie" itd.) dostają delikatniejszy, "soft premium" hover niż globalny
   .btn--outline (który na reszcie serwisu zalewa się pełnym różem + unosi -
   dobre dla marketingowych CTA, zbyt mocne dla gęstego UI panelu z wieloma
   drugorzędnymi przyciskami obok siebie). WYŁĄCZNIE nadpisanie hover/focus w
   zasięgu .panel-page - globalny .btn/.btn--outline/.btn--primary używany
   na reszcie serwisu pozostaje w 100% nietknięty. */
.panel-page .btn--outline:hover, .panel-page .btn--outline:focus-visible {
  background: var(--color-fuchsia-soft);
  border-color: var(--color-fuchsia);
  color: var(--color-ink);
  transform: none;
}

/* ---- Ekran logowania (panel/logowanie/index.html) ---- */
.panel-auth-header { padding: 20px 24px; }
@media (min-width: 768px) { .panel-auth-header { padding-inline: 40px; } }
/* Wordmark trochę większy niż w reszcie serwisu (polecenie §6
   "czytelniejszy wordmark") - login jest samodzielną, prawie pustą stroną,
   może sobie na to pozwolić bez konfliktu z resztą layoutu jak w headerze
   marketingowym. Scope wyłącznie do .panel-auth-header - globalny
   .wordmark używany w reszcie serwisu nietknięty. */
.panel-auth-header .wordmark__icon { height: 48px; }
.panel-auth-header .wordmark__logo { height: 36px; }
@media (min-width: 768px) { .panel-auth-header .wordmark__icon { height: 54px; } .panel-auth-header .wordmark__logo { height: 40px; } }
/* Sekcja loginu dostaje własne, lekko odróżnione tło (--color-surface-alt,
   istniejący token) zamiast jednolitego --color-bg całej reszty panelu -
   daje "obecność" bloku zamiast wrażenia przypadkowej pustki wokół
   pływającej białej karty (polecenie §6), bez żadnego nowego koloru. */
.panel-auth { min-height: 70vh; display: flex; align-items: center; padding-block: 24px 64px; background: var(--color-surface-alt); }
.panel-auth__wrap { display: flex; justify-content: center; }
.panel-auth__card {
  width: 100%;
  max-width: 620px;
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-line);
  border-radius: var(--radius-lg);
  padding: 48px 44px;
}
.panel-auth__heading { position: relative; display: inline-block; padding-bottom: 12px; font-family: var(--font-display); font-weight: 600; font-size: clamp(1.7rem, 2.8vw, 2.1rem); color: var(--color-ink); margin-top: 8px; }
.panel-auth__heading::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 56px;
  height: 4px;
  border-radius: var(--radius-pill);
  background: var(--color-fuchsia);
}
.panel-auth__lead { font-size: 1em; line-height: 1.55; color: var(--color-text); margin-top: 12px; margin-bottom: 6px; }
.panel-auth__lead-note { font-size: .92em; line-height: 1.5; color: var(--color-muted); margin-bottom: 30px; }
/* KOREKTA po live review §2 — przyczyna "karty w karcie": globalna reguła
   .form (patrz góra pliku) nadaje KAŻDEMU elementowi z klasą "form" WŁASNE
   tło/obrys/cień/padding (ten sam mechanizm, który już wcześniej wymagał
   analogicznego zdjęcia stylu dla .quiz-card .form w /co-wybrac). Formularz
   logowania/ustawiania hasła dostał klasę "form" (żeby odziedziczyć
   stylowanie inputów), ale nigdy nie dostał zdjęcia WŁASNEGO card-chrome -
   stąd druga, wewnętrzna karta. Formularz ma być teraz bezpośrednią
   częścią .panel-auth__card, bez własnego tła/obrysu/cienia/paddingu. */
.panel-auth__card .form { background: none; border: none; box-shadow: none; padding: 0; }
.panel-auth__form .field { margin-bottom: 22px; gap: 10px; }
.panel-auth__form .field:last-of-type { margin-bottom: 28px; }
.panel-auth__form input[type="text"], .panel-auth__form input[type="password"] { min-height: 54px; padding: 15px 18px; font-size: 17px; }
.panel-auth__submit { width: 100%; justify-content: center; min-height: 54px; font-size: 16px; }
.panel-auth-footer { padding: 24px 24px 40px; text-align: center; }
.panel-auth-footer p { font-size: .85em; color: var(--color-muted); }
.panel-auth-footer a { color: var(--color-text); font-weight: 700; }

/* =========================================================
   Panel — Moja dyspozycyjność (Panel MVP — etap 2, panel/dyspozycyjnosc/)
   Reużywa .field/.field__error/.form__summary/.btn/.panel-card - zero
   nowego systemu wizualnego, wyłącznie układ specyficzny dla tego
   formularza (karty dni, przedziały godzinowe).
   ========================================================= */

.avail-closed-notice {
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-line);
  border-radius: var(--radius-md);
  padding: 24px;
  margin-bottom: 28px;
}
.avail-closed-notice p:first-child { font-weight: 700; color: var(--color-ink); margin-bottom: 12px; }
.avail-closed-notice__contacts { display: flex; flex-wrap: wrap; gap: 10px 24px; }
.avail-closed-notice__contacts a { font-weight: 700; color: var(--color-fuchsia); }
.avail-closed-notice__contacts a:hover, .avail-closed-notice__contacts a:focus-visible { color: var(--color-fuchsia-hover); }

.avail-saved-note { font-size: .9em; color: var(--color-muted); margin: -10px 0 24px; }
.avail-saved-note[hidden] { display: none; }

/* "Micro fix - availability mobile header" (13.09.2026) - H1 #avail-heading
   ma dwa warianty tekstu (patrz HTML) - dokładnie jeden widoczny na raz.
   Desktop (domyślnie): pełne zdanie "Podaj dyspozycyjność na X" widoczne,
   #avail-week-range (osobny, samodzielny zakres dat pod H1) ukryty - był
   nadmiarowy, skoro ta sama informacja już jest w H1. */
.avail-heading__mobile { display: none; }
.avail-week-range { display: none; margin: 0; }
@media (max-width: 767px) {
  /* Mobile: H1 pokazuje WYŁĄCZNIE stałe "Dyspozycyjność" (krótkie, nie
     łamie się przy ikonie) - pełne zdanie z zakresem dat chowa się, jego
     miejsce przejmuje #avail-week-range, osobny wiersz pod tytułem, na
     pełnej szerokości .section-shell__text (nie ściśnięty obok ikony). */
  .avail-heading__desktop { display: none; }
  .avail-heading__mobile { display: inline; }
  .avail-week-range {
    display: block;
    font-family: var(--font-display);
    font-weight: 600;
    font-size: clamp(22px, 6vw, 24px);
    color: var(--color-graphite);
    margin-top: 5px;
  }
}

/* Etap 9 §1 — stan sukcesu po zapisie dyspozycyjności, zastępuje formularz (nie usuwa go z DOM). */
.avail-success {
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-line);
  border-radius: var(--radius-md);
  padding: 28px 24px;
  max-width: 60ch;
}
.avail-success[hidden] { display: none; }
.avail-success__heading { font-family: var(--font-display); font-weight: 600; font-size: 1.4rem; color: var(--color-ink); margin-bottom: 14px; }
.avail-success p { font-size: .96em; line-height: 1.55; color: var(--color-text); margin-bottom: 12px; }
.avail-success__actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 18px; }

/* Etap 9 §2 — rodzaje zajęć, multi-select checkboxy. */
.avail-activities { border: none; padding: 0; margin: 0 0 28px; }
.avail-activities__grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 10px 16px; margin-top: 12px; }
.avail-activity-checkbox { display: flex; align-items: center; gap: 10px; cursor: pointer; font-size: .95em; color: var(--color-ink); }
.avail-activity-checkbox input { width: 18px; height: 18px; flex-shrink: 0; accent-color: var(--color-fuchsia); }
.avail-activity-checkbox input:focus-visible { outline: 3px solid var(--color-fuchsia); outline-offset: 3px; }
.avail-activities__error { margin-top: 10px; }

/* "Micro polish" (13.09.2026) - selektor psa jako chips/karty zamiast
   natywnego <select> (§2 polecenia), pokazywany dla KAŻDEJ liczby psów
   ≥1. Pusty stan (0 psów) spójny z resztą prostych pól formularza
   (.field) i istniejącym wzorcem pustego stanu (.dogs-empty). */
.avail-no-dogs { color: var(--color-muted); margin-bottom: 24px; }
.avail-dog-field { margin-bottom: 28px; }
.avail-dog-field[hidden] { display: none; }
.avail-dog-field__label { font-family: var(--font-body); font-weight: 700; font-size: .95em; color: var(--color-ink); margin: 0 0 10px; }
.avail-dog-chips { display: flex; flex-wrap: wrap; gap: 10px; }
.avail-dog-chip {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 16px 8px 8px;
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-line);
  border-radius: var(--radius-pill);
  cursor: pointer;
  transition: background-color .15s var(--ease), border-color .15s var(--ease);
}
.avail-dog-chip:has(.avail-dog-chip__input:checked) { background: var(--color-fuchsia-soft); border-color: var(--color-fuchsia); }
.avail-dog-chip:has(.avail-dog-chip__input:focus-visible) { outline: 2px solid var(--color-fuchsia); outline-offset: 2px; }
.avail-dog-chip__input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.avail-dog-chip__avatar { position: relative; flex: 0 0 auto; width: 32px; height: 32px; border-radius: 50%; overflow: hidden; background: var(--color-surface-alt); }
.avail-dog-chip__photo, .avail-dog-chip__placeholder { width: 32px; height: 32px; border-radius: 50%; }
.avail-dog-chip__photo { display: block; object-fit: cover; }
.avail-dog-chip__photo[hidden] { display: none; }
.avail-dog-chip__placeholder { display: flex; align-items: center; justify-content: center; font-family: var(--font-display); font-weight: 600; font-size: .9em; color: var(--color-fuchsia); }
.avail-dog-chip__placeholder[hidden] { display: none; }
.avail-dog-chip__name { font-weight: 700; font-size: .95em; color: var(--color-ink); }

/* "Copy availability between dogs" (13.09.2026) - §3 polecenia: sekcja
   "Skopiuj też dla" reużywa DOKŁADNIE .avail-dog-chips/.avail-dog-chip*
   wyżej (patrz script.js) - te dwie reguły to WYŁĄCZNIE wrapper spacing +
   mały hint tekst, zero nowego komponentu. Widoczność (>1 pies, wyklucza
   aktualnego) sterowana z JS przez atrybut [hidden]. */
.avail-copy-field { margin: -8px 0 28px; }
.avail-copy-field[hidden] { display: none; }
.avail-copy-field__hint { font-size: .9em; color: var(--color-muted); margin: 0 0 10px; }

/* "W tym tygodniu nie mam możliwości..." - traktowana jak zwykły checkbox
   w karcie, spójnie z resztą formularza (nie osobny komponent "switch"). */
.avail-no-availability {
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-line);
  border-radius: var(--radius-md);
  padding: 18px 20px;
  margin-bottom: 24px;
}
.avail-checkbox { display: flex; align-items: flex-start; gap: 12px; cursor: pointer; font-family: var(--font-body); font-weight: 600; font-size: 15px; color: var(--color-ink); }
.avail-checkbox input[type="checkbox"] { width: 20px; height: 20px; flex-shrink: 0; margin-top: 1px; accent-color: var(--color-fuchsia); }
.avail-checkbox input[type="checkbox"]:focus-visible { outline: 3px solid var(--color-fuchsia); outline-offset: 3px; }

.avail-days { display: flex; flex-direction: column; gap: 16px; margin-bottom: 28px; }
.avail-days[hidden] { display: none; }

.avail-day {
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-line);
  border-radius: var(--radius-md);
  padding: 18px 20px;
  margin: 0;
  transition: border-color .15s var(--ease);
}
.avail-day:has(.avail-day__checkbox:checked) { border-color: var(--color-fuchsia); }

.avail-day__legend {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  padding: 0;
}
.avail-day__toggle { display: flex; align-items: center; gap: 12px; cursor: pointer; }
.avail-day__checkbox { width: 22px; height: 22px; flex-shrink: 0; accent-color: var(--color-fuchsia); }
.avail-day__checkbox:focus-visible { outline: 3px solid var(--color-fuchsia); outline-offset: 3px; }
.avail-day__name { font-family: var(--font-display); font-weight: 600; font-size: 1.05rem; color: var(--color-ink); }
.avail-day__state { font-size: 13px; font-weight: 700; color: var(--color-muted); white-space: nowrap; }
.avail-day:has(.avail-day__checkbox:checked) .avail-day__state { color: var(--color-fuchsia); }

.avail-day__body { margin-top: 16px; padding-top: 16px; border-top: var(--border-width) solid var(--color-line); }
.avail-day__body[hidden] { display: none; }

.avail-day__slots { display: flex; flex-direction: column; gap: 12px; margin-bottom: 14px; }

.avail-slot { display: flex; align-items: flex-end; gap: 12px; flex-wrap: wrap; }
.avail-slot__field { flex: 1 1 110px; min-width: 110px; margin-bottom: 0; }
.avail-slot__field label { font-size: 13px; }
.avail-slot__remove {
  flex-shrink: 0;
  width: 40px;
  height: 48px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-sm);
  color: var(--color-muted);
  border: var(--border-width) solid transparent;
}
.avail-slot__remove svg { width: 18px; height: 18px; }
.avail-slot__remove:hover, .avail-slot__remove:focus-visible { color: var(--color-error); border-color: var(--color-line); }
.avail-slot__remove[hidden] { display: none; }

.avail-day__error { margin-top: 10px; margin-bottom: 0; }

.avail-note-field textarea { min-height: 88px; }
/* KOREKTA "final polish" §14 - pole istniało już wcześniej ("Dodatkowa
   informacja"), backend (kolumna `note` na ppfb_availability) już je
   czytał/zapisywał - WYŁĄCZNIE relabeling, zero zmian backendu/migracji. */
.avail-note-field__eyebrow { margin-bottom: 6px; color: var(--color-fuchsia-hover); }
.avail-note-counter { font-size: 12px; color: var(--color-muted); text-align: right; margin-top: 6px; }
.avail-note-counter--limit { color: var(--color-error); font-weight: 700; }

@media (max-width: 389px) {
  .avail-slot__field { flex-basis: 100%; }
  .avail-slot__remove { align-self: flex-end; }
}

/* =========================================================
   Panel — Mój grafik (Panel MVP — etap 3, panel/grafik/) i karta
   "Najbliższe zajęcia" na Dashboardzie. Read-only dla klienta — karty
   zamiast tabeli, żeby dobrze skanować się na telefonie (§23 polecenia).
   ========================================================= */

.schedule-list { display: flex; flex-direction: column; gap: 16px; }

.schedule-empty {
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-line);
  border-radius: var(--radius-md);
  padding: 28px 24px;
  color: var(--color-muted);
  font-size: .95em;
  line-height: 1.5;
}

.schedule-card {
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-line);
  border-radius: var(--radius-md);
  padding: 22px 24px;
}
.schedule-card--cancelled { background: var(--color-surface-alt); border-color: var(--color-line); }

.schedule-card__day { font-family: var(--font-display); font-weight: 600; font-size: 1.1rem; color: var(--color-ink); }
.schedule-card__time { font-size: .95em; color: var(--color-text); margin-top: 2px; }

.schedule-card__badge {
  display: inline-flex;
  align-items: center;
  margin-top: 10px;
  padding: 5px 12px;
  border-radius: var(--radius-pill);
  background: var(--color-error);
  color: var(--color-white);
  font-size: 12px;
  font-weight: 700;
}
.schedule-card__badge[hidden] { display: none; }

.schedule-card__body { margin-top: 14px; padding-top: 14px; border-top: var(--border-width) solid var(--color-line); }
.schedule-card__title { font-weight: 700; color: var(--color-ink); }
.schedule-card__location { font-size: .92em; color: var(--color-text); margin-top: 4px; }
.schedule-card__note { font-size: .9em; color: var(--color-muted); margin-top: 10px; }

/* ---- Karta "Najbliższe zajęcia" na Dashboardzie (panel/index.html) ---- */
.panel-card__schedule-day { font-family: var(--font-display); font-weight: 600; color: var(--color-ink); }
.panel-card__schedule-meta { font-size: .92em; color: var(--color-text); margin-top: 4px; }

/* =========================================================
   Panel — Moje cele — FINALNY MODEL (etap 9E, panel/cele/). Cele są per
   user_id+dog_id (nie per miesiąc) - patrz CLAUDE.md. Etap pracy pokazany
   jako spokojny badge (albo neutralny tekst, gdy jeszcze nieustalony,
   §21 polecenia) - nigdy "brak danych"/"null". Historia (completed/
   archived) NEUTRALNA - nigdy czerwony komunikat "nie udało się"
   (--color-error zarezerwowany dla błędów formularzy, nie dla tego).
   ========================================================= */

.goals-current { display: flex; flex-direction: column; gap: 16px; margin-bottom: 32px; }
#goals-paused { display: flex; flex-direction: column; gap: 16px; margin-bottom: 32px; }

.goal-card {
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-line);
  border-radius: var(--radius-md);
  padding: 22px 24px;
}
/* Etap 9E.4a §7 polecenia - mobile spacing: mniej pionowych odstępów na
   360-390px, bez ściskania samego tekstu (font-size/line-height bez zmian) -
   karta ma być krótka, ale nadal czytelna z dużymi tap-targetami. */
@media (max-width: 480px) {
  .goal-card { padding: 18px 18px; }
  .goal-card__text { margin-bottom: 8px; }
  .goal-card__element-row, .goal-card__desired-outcome { margin-bottom: 8px; }
  /* Etap 9E.4d §1/§2 polecenia - stage-row zaczyna nowy "blok" karty
     (stage badge + opis), stąd większy odstęp niż zwykłe 8px na mobile -
     margin-top+margin-bottom collapsują z sąsiadami do tej większej wartości
     niezależnie od tego, czym kończy się poprzedni blok (edycja celu głównego
     otwarta czy nie, element-row obecny czy nie). */
  .goal-card__stage-row { margin-top: 18px; margin-bottom: 18px; }
  .goal-card__stage { margin-bottom: 6px; }
  .goal-card__training-count { margin-bottom: 10px; }
}
.goal-card__text { font-size: 1.05em; line-height: 1.5; color: var(--color-ink); margin-bottom: 12px; }

.goal-card__stage {
  display: inline-flex;
  align-items: center;
  padding: 5px 14px;
  border-radius: var(--radius-pill);
  font-size: 13px;
  font-weight: 700;
  background: var(--color-yellow-soft);
  color: var(--color-ink);
  margin-bottom: 12px;
}
/* Etap jeszcze nieustalony (stage IS NULL) - ten sam neutralny, przygaszony
   chip co status ankiety startowej w innych miejscach panelu, nigdy alarm. */
.goal-card__stage--pending { background: var(--color-surface-alt); color: var(--color-muted); font-weight: 600; }

.goal-card__meta { font-size: .82em; color: var(--color-muted); margin-bottom: 4px; }
.goal-card__training-count { font-size: .9em; color: var(--color-text); margin-bottom: 14px; }

/* Etap 9E.2 - desired_outcome/element/target/stage-picker na karcie celu. */
.goal-card__desired-outcome { font-size: .92em; color: var(--color-text); margin-bottom: 10px; }
.goal-card__desired-outcome[hidden] { display: none; }
.goal-card__element-row { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-bottom: 12px; font-size: .9em; color: var(--color-text); }
.goal-card__element-row[hidden] { display: none; }
.goal-card__element-picker { margin: 4px 0 12px; }
.goal-card__element-picker[hidden] { display: none; }
/* Etap 9E.4d §1 polecenia - edycja "Jaki jest Twój główny cel?" na karcie:
   mały odstęp Edytuj->label, normalny odstęp helper->textarea, mały odstęp
   textarea->Zapisz. Traktowana jako blok A razem z current_element/
   desired_outcome nad nią. */
.goal-card__do-edit { margin-top: 4px; }
.goal-card__do-form { margin-top: 8px; }
.goal-card__do-form[hidden] { display: none; }
.goal-card__do-form > .goals-question__label { margin-bottom: 4px; }
.goal-card__do-form > .field__hint { margin-bottom: 12px; }
.goal-card__do-form > textarea { margin-bottom: 8px; }
/* Etap 9E.4d §1/§2 polecenia - stage-row (blok B: badge+opis etapu) dostaje
   WIĘKSZY odstęp od bloku A (desired_outcome/edycja) i od bloku C (training
   count + "Trening zrobiony") niż zwykłe odstępy wewnątrz bloku - margin-top
   collapsuje z margin-bottom poprzedniego elementu do wartości większej z
   dwóch, więc gap jest zagwarantowany niezależnie od tego, czym kończy się
   blok A (sam desired_outcome, otwarta edycja, czy element-row). */
.goal-card__stage-row { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-top: 24px; margin-bottom: 24px; }
.goal-card__stage-row[hidden] { display: none; }
.btn--link { background: none; border: none; padding: 0; color: var(--color-fuchsia); font-weight: 600; font-size: .85em; text-decoration: underline; cursor: pointer; }
.goal-card__stage-hint { flex-basis: 100%; font-size: .88em; color: var(--color-muted); line-height: 1.5; margin: 0; }
.goal-card__stage-hint[hidden] { display: none; }
.goal-card__stage-picker { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; flex-basis: 100%; }
.goal-card__stage-picker select { max-width: 260px; }
.goal-card__checkin-panel { margin-top: 14px; padding: 16px; background: var(--color-surface-alt); border-radius: var(--radius-md); }
.goal-card__checkin-panel[hidden] { display: none; }
/* Etap 9E.4e §10 polecenia - resume choice cards: CAŁY kafelek klikalny
   (nie osobny przycisk + akapit obok), jedna karta pod drugą, min. 44px
   tap-target - dotyczy WYŁĄCZNIE wyboru "Szybkie sprawdzenie"/"Przejdź
   pełną ankietę" po kliknięciu "Wznów". */
.resume-choice-list { display: flex; flex-direction: column; gap: 10px; margin-top: 4px; }
.resume-choice-card {
  display: block;
  width: 100%;
  min-height: 44px;
  text-align: left;
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-line);
  border-radius: var(--radius-md);
  padding: 14px 16px;
  cursor: pointer;
  transition: border-color .15s var(--ease);
}
.resume-choice-card:hover, .resume-choice-card:focus-visible { border-color: var(--color-fuchsia); outline: none; }
.resume-choice-card__title { display: block; font-weight: 700; font-size: .95em; color: var(--color-ink); margin-bottom: 4px; }
.resume-choice-card__desc { display: block; font-size: .85em; color: var(--color-muted); line-height: 1.4; }
.goal-card__foundations-note { font-size: .85em; color: var(--color-muted); font-style: italic; margin-top: 10px; }
.goal-card__foundations-note[hidden] { display: none; }
.goal-card--paused { opacity: .92; }

.goal-card__actions { display: flex; flex-wrap: wrap; gap: 12px; }
/* Etap 9E.4 §10/§11 polecenia - hierarchia zamiast rzędu jednakowych
   przycisków: "Trening zrobiony" duże, prawie pełna szerokość, łatwy tap
   jednym kciukiem; "Dodaj notatkę" drugorzędne pod nim; reszta akcji
   (checkin/pauza/cel osiągnięty) dyskretnie niżej jako tekstowe linki. */
.goal-card__training-btn--primary { display: block; width: 100%; text-align: center; margin-bottom: 10px; padding-top: 14px; padding-bottom: 14px; font-size: 1.02em; }
.goal-card__note-btn { display: block; width: 100%; text-align: center; margin-bottom: 14px; }
.goal-card__note-panel { margin-bottom: 14px; }
.goal-card__note-panel[hidden] { display: none; }
.goal-card__note-panel textarea { width: 100%; }
/* Etap 9E.4b §2/§3 polecenia - WYŁĄCZNIE 2 linki w tym rzędzie ("Sprawdź,
   gdzie jesteśmy" / "Więcej") - blisko siebie, nie rozrzucone po karcie
   (mniejszy gap niż dawne 16px na 4 linki); reszta rzadkich akcji chowa się
   w .goal-card__more-panel, lekkie rozwinięcie pod linkiem, bez modala.
   §4 polecenia - min. 44px tappable mimo wizualnie małego linku (padding
   niewidoczny, bez tła) - scoped tylko do tej karty, nie globalnie .btn--link. */
.goal-card__actions--secondary { gap: 10px; padding-top: 4px; border-top: var(--border-width) solid var(--color-line); }
.goal-card__actions--secondary .btn--link,
.goal-card__more-panel .btn--link { display: inline-flex; align-items: center; min-height: 44px; padding: 10px 2px; }
.goal-card__more-panel { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; margin-top: 6px; }
.goal-card__more-panel[hidden] { display: none; }
.goal-card__more-toggle[hidden] { display: none; }
/* Etap 9E.4c §3/§4/§6 polecenia - na mobile "Sprawdź, gdzie jesteśmy" i
   "Więcej" też jedna akcja na linię (nie w jednym rzędzie) - karta ma nie
   rozciągać linków na pełną szerokość, tylko ułożyć je pionowo, zwarcie. */
@media (max-width: 480px) {
  .goal-card__actions--secondary { flex-direction: column; align-items: flex-start; gap: 2px; }
}
@media (min-width: 640px) {
  .goal-card__training-btn--primary, .goal-card__note-btn { width: auto; display: inline-flex; justify-content: center; }
  .goal-card__training-btn--primary { min-width: 220px; }
}

/* Etap 9E.4 §12 polecenia - krótka, lekka celebracja po "Trening zrobiony"
   (kilka serduszek unoszących się znad przycisku) - nigdy pełnoekranowa,
   nie wymaga zamykania, pointer-events:none żeby nigdy nie blokować tapów. */
.training-celebration { position: fixed; transform: translate(-50%, -8px); pointer-events: none; z-index: 999; width: 1px; height: 1px; }
/* Etap 9E.4d §4 polecenia - WYŁĄCZNIE serduszka (♡/♥), różne rozmiary
   (ustawiane inline per-piece w JS), rotacja/czas trwania też per-piece -
   efekt ma czuć się jak wysłanie serca w Messengerze, nie konfetti. */
.training-celebration__piece {
  position: absolute;
  left: 0;
  top: 0;
  line-height: 1;
  color: var(--color-fuchsia);
  opacity: 0;
  animation-name: training-celebration-float;
  animation-timing-function: ease-out;
  animation-fill-mode: forwards;
}
@keyframes training-celebration-float {
  0% { opacity: 0; transform: translate(0, 0) scale(.5) rotate(0deg); }
  15% { opacity: 1; }
  100% { opacity: 0; transform: translate(var(--tc-dx, 0px), -92px) scale(1.1) rotate(var(--tc-rot, 0deg)); }
}
@media (prefers-reduced-motion: reduce) {
  .training-celebration { display: none; }
}
.goal-card__confirm {
  margin-top: 14px;
  padding: 14px 16px;
  background: var(--color-fuchsia-soft);
  border-radius: var(--radius-md);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
}
.goal-card__confirm[hidden] { display: none; }
.goal-card__confirm-text { flex: 1 1 100%; font-size: .95em; color: var(--color-ink); margin: 0; }

.goal-card__saved-note { font-size: .85em; color: var(--color-muted); margin-top: 12px; }
.goal-card__saved-note[hidden] { display: none; }

/* Etap 9E §24 polecenia - CTA "Dodaj cel" / komunikat limitu (2 aktywne/psa).
   Etap 9E.4b §5 polecenia - wyraźny odstęp po "Dodaj cel", żeby nie stykał
   się wizualnie z nagłówkiem "Wstrzymane cele" niżej na stronie. */
#goals-add-trigger { margin-bottom: 32px; }
#goals-add-trigger[hidden] { display: none; }
.goals-limit-note { font-size: .9em; color: var(--color-muted); margin-bottom: 32px; }
.goals-limit-note[hidden] { display: none; }

/* Etap 9E.1 §6/§7 polecenia - mini wizard 3 kroki (Wybierz cel -> Kilka
   pytań -> Podsumowanie), NIE jeden ciągły formularz - każdy krok to
   osobny, chowany blok w tej samej karcie/section-shell. */
#goals-add-section { margin-bottom: 40px; }
#goals-add-section[hidden] { display: none; }
.goals-wizard__step-label { font-size: .82em; font-weight: 700; color: var(--color-muted); text-transform: uppercase; letter-spacing: .04em; margin-bottom: 14px; }
.goals-wizard__step[hidden] { display: none; }
.goals-wizard__nav { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 24px; }
.goals-picker { border: none; padding: 0; margin: 0 0 20px; }
#goals-library-list { display: flex; flex-direction: column; gap: 10px; margin-bottom: 10px; }
.goals-picker__custom-option { margin-bottom: 10px; }
.goals-custom-field { margin: 12px 0 0 4px; }
.goals-custom-field[hidden] { display: none; }
.goals-question { margin-bottom: 20px; }
.goals-question__label { font-weight: 700; font-size: .95em; color: var(--color-ink); margin-bottom: 8px; display: block; }
.goals-question__pills { margin-bottom: 8px; }
/* Krok 3 - podsumowanie (pies/cel/odpowiedzi ankiety) przed finalnym zapisem. */
.goals-summary__line { font-size: .95em; color: var(--color-text); line-height: 1.6; margin-bottom: 8px; }
.goals-summary__line strong { color: var(--color-ink); }

.goals-empty {
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-line);
  border-radius: var(--radius-md);
  padding: 28px 24px;
  color: var(--color-muted);
  font-size: .95em;
  line-height: 1.5;
  margin-bottom: 32px;
}

/* Historia (completed/archived) - lista prosta, bez miesięcznego
   grupowania jako głównej logiki (§22 polecenia), od najnowszych. */
.goals-history__item {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 16px;
  padding: 12px 0;
  border-top: var(--border-width) solid var(--color-line);
}
.goals-history__item-text { color: var(--color-text); font-size: .95em; }
.goals-history__item-status { flex-shrink: 0; font-size: .85em; font-weight: 700; color: var(--color-muted); white-space: nowrap; }
.goals-history__item-date { flex-basis: 100%; font-size: .8em; color: var(--color-muted); margin-top: 2px; }
/* Etap 9E.2 §31 - "Wznów" (WYŁĄCZNIE completed, nigdy archived/foundations). */
.goals-history__item-resume-btn { flex-basis: 100%; align-self: flex-start; margin-top: 6px; }
.goals-history__item-resume-btn[hidden] { display: none; }

@media (max-width: 389px) {
  .goals-history__item { flex-direction: column; gap: 4px; }
}

/* =========================================================
   Panel — Moje notatki (etap 9E.2 §35-46, panel/notatki/).
   ========================================================= */

/* Etap 9E.4i §7/§22 polecenia - segmented control "Treningi własne"/
   "Zajęcia" - mobile-first, dwie duże, równe, czytelne zakładki. */
.notes-tabs { display: flex; gap: 8px; margin-bottom: 20px; }
.notes-tabs__btn {
  flex: 1 1 0;
  min-height: 48px;
  padding: 10px 12px;
  border: var(--border-width) solid var(--color-line);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  color: var(--color-ink);
  font-weight: 700;
  font-size: .95em;
  cursor: pointer;
  text-align: center;
}
.notes-tabs__btn.is-active { border-color: var(--color-fuchsia); background: var(--color-fuchsia-soft); color: var(--color-fuchsia); }
.notes-tabs__btn:focus-visible { outline: 2px solid var(--color-fuchsia); outline-offset: 2px; }

.notes-latest-stale { font-size: .88em; color: var(--color-muted); font-style: italic; margin-bottom: 10px; }
.notes-latest-stale[hidden] { display: none; }
.note-item {
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-line);
  border-radius: var(--radius-md);
  padding: 16px 18px;
  margin-bottom: 12px;
}
.note-item__meta { font-size: .8em; color: var(--color-muted); margin-bottom: 6px; text-transform: uppercase; letter-spacing: .02em; }
/* Etap 9E.4e §31 polecenia - "Jak poszło"/"Na następny raz" WYŁĄCZNIE gdy
   dana ma realną wartość (historyczne notatki sprzed tej tury jej nie mają)
   - [hidden] jawnie, zgodnie z resztą projektu (attribute selector nie
   wystarcza samo z siebie bez tej reguły w kilku miejscach tego pliku). */
.note-item__rating { font-size: .85em; font-weight: 700; color: var(--color-ink); margin-bottom: 6px; }
.note-item__rating[hidden] { display: none; }
.note-item__text { font-size: .95em; color: var(--color-text); line-height: 1.6; white-space: pre-wrap; }
.note-item__text[hidden] { display: none; }
/* Etap 9E.4j §1 polecenia - "Co zrobiłbyś inaczej?" PRZYWRÓCONE, wyłącznie
   dla notatek własnego treningu (.note-item, nie .note-item--session). */
.note-item__next { margin-top: 10px; padding-top: 10px; border-top: var(--border-width) solid var(--color-line); }
.note-item__next[hidden] { display: none; }
.note-item__next-label { font-size: .78em; font-weight: 700; text-transform: uppercase; letter-spacing: .02em; color: var(--color-muted); margin-bottom: 4px; }
.note-item__next-text { font-size: .92em; color: var(--color-text); line-height: 1.5; white-space: pre-wrap; }

/* Etap 9E.4i §9/§18 polecenia - notatka Z ZAJĘĆ: pierwsza warstwa (data/typ/
   temat/ocena) w <summary> zawsze widoczna, "Powiązany cel" i treść dopiero
   po rozwinięciu - ten sam <details> wzorzec co .notes-older-details. */
.note-item--session { padding: 0; }
.note-item__session-summary {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 10px;
  padding: 16px 18px;
  cursor: pointer;
  list-style: none;
}
.note-item__session-summary::-webkit-details-marker { display: none; }
.note-item__session-summary .note-item__meta { margin-bottom: 0; }
.note-item__session-focus { font-size: .95em; font-weight: 700; color: var(--color-ink); flex: 1 1 100%; }
.note-item__session-body { padding: 0 18px 16px; }
.note-item__goal-link { font-size: .82em; color: var(--color-muted); margin-bottom: 8px; }
.note-item__goal-link[hidden] { display: none; }

/* Etap 9E.4e §21/§25 polecenia - ocena treningu: 5 kolumn x 2 rzędy na
   mobile, duże tap-targety (min. ~44px) - "Trudno ocenić" jako osobna,
   równorzędna opcja pod spodem (reużywa .choice-list__option). */
.note-rating-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 8px; margin: 8px 0 6px; }
.note-rating-grid__option {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  border: var(--border-width) solid var(--color-line);
  border-radius: var(--radius-sm);
  font-weight: 700;
  font-size: .95em;
  color: var(--color-ink);
  cursor: pointer;
}
.note-rating-grid__option input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.note-rating-grid__option:has(input:checked) { border-color: var(--color-fuchsia); background: var(--color-fuchsia-soft); color: var(--color-fuchsia); }
.note-rating-grid__option:has(input:focus-visible) { outline: 2px solid var(--color-fuchsia); outline-offset: 2px; }
.note-rating-scale-labels { display: flex; justify-content: space-between; font-size: .8em; color: var(--color-muted); margin-bottom: 10px; }
/* Etap 9E.4d §18 polecenia - .notes-older-details/-summary/-list zastępują
   dawne, sztywne ID (#notes-older-details itd.) - renderGoalNotesBlock()
   tworzy te elementy dynamicznie, reużywany zarówno dla aktualnej pracy,
   jak i dla historii (paused/completed/archived), stąd klasy, nie ID. */
.notes-older-details { margin-top: 8px; margin-bottom: 8px; }
.notes-older-summary { cursor: pointer; font-weight: 700; color: var(--color-fuchsia); font-size: .9em; margin-bottom: 10px; }
.notes-older-list { margin-top: 12px; }

/* Etap 9E.4d §9/§10 polecenia - "Nad czym teraz pracujecie" (1 active goal =
   auto-wybór, tekst only; 2 = duże choice cards, ten sam wzorzec co
   .choice-list gdzie indziej w panelu - reużyte 1:1, zero nowego CSS). */
#notes-active-goal-info { margin-bottom: 20px; }
#notes-active-picker { max-width: 520px; margin-bottom: 20px; }
#notes-older-goals-list { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; margin-bottom: 16px; }
#notes-older-goal-notes:empty { display: none; }

/* =========================================================
   Panel — Wydarzenia (Panel MVP — etap 5, panel/wydarzenia/).
   UWAGA NAZEWNICZA: świadomie NIE `.event-card` — ta nazwa jest już zajęta
   przez istniejący, niezwiązany komponent "Co się teraz dzieje?" na
   homepage (`.events`/`.event-card`, etap 17C, dziś zawsze pusty/hidden).
   Użycie tej samej nazwy klasy powodowało realną kolizję w kaskadzie
   (obie reguły `.event-card` łączyły się we wspólny zestaw właściwości —
   `display:flex;flex-direction:column` z homepage'owej reguły przeciekało
   też tutaj, przez co `.event-card__badge` z `align-items:stretch`
   rozciągał się na całą szerokość karty zamiast być małą pigułką) —
   znalezione i naprawione przed oddaniem, patrz PANEL_KLIENTA.md §18.10.
   Stąd `.wydarzenie-card` jako osobna, jednoznaczna nazwa.
   ========================================================= */

.events-list { display: flex; flex-direction: column; gap: 16px; }

.events-empty {
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-line);
  border-radius: var(--radius-md);
  padding: 28px 24px;
  color: var(--color-muted);
  font-size: .95em;
  line-height: 1.5;
}

.wydarzenie-card {
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-line);
  border-radius: var(--radius-md);
  padding: 22px 24px;
}
.wydarzenie-card--cancelled { background: var(--color-surface-alt); }

.wydarzenie-card__type { font-size: 12px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--color-fuchsia); }
.wydarzenie-card__title { font-family: var(--font-display); font-weight: 600; font-size: 1.15rem; color: var(--color-ink); margin-top: 6px; }
.wydarzenie-card__day { font-size: .95em; color: var(--color-text); margin-top: 8px; }
.wydarzenie-card__time { font-size: .95em; color: var(--color-text); }
.wydarzenie-card__location { font-size: .92em; color: var(--color-text); margin-top: 2px; }

.wydarzenie-card__badge {
  display: inline-flex;
  align-items: center;
  margin-top: 10px;
  padding: 5px 12px;
  border-radius: var(--radius-pill);
  background: var(--color-error);
  color: var(--color-white);
  font-size: 12px;
  font-weight: 700;
}
.wydarzenie-card__badge[hidden] { display: none; }

.wydarzenie-card__benefit {
  display: inline-flex;
  align-items: center;
  margin-top: 12px;
  padding: 6px 14px;
  border-radius: var(--radius-pill);
  font-size: 13px;
  font-weight: 700;
}
.wydarzenie-card__benefit[hidden] { display: none; }
.wydarzenie-card__benefit--free { background: var(--color-aqua-soft); color: var(--color-ink); }
.wydarzenie-card__benefit--discount { background: var(--color-yellow-soft); color: var(--color-ink); }

.wydarzenie-card__description { font-size: .92em; line-height: 1.5; color: var(--color-text); margin-top: 14px; padding-top: 14px; border-top: var(--border-width) solid var(--color-line); }
.wydarzenie-card__description[hidden] { display: none; }

/* Etap 9 §10-14 — dołączanie/limit miejsc/cel klas komunikacji/instrukcja. */
.wydarzenie-card__target { font-size: .85em; font-weight: 700; color: var(--color-muted); margin-top: 8px; }
.wydarzenie-card__target[hidden] { display: none; }
.wydarzenie-card__capacity { font-size: .85em; color: var(--color-muted); margin-top: 8px; }
.wydarzenie-card__capacity[hidden] { display: none; }
.wydarzenie-card__instruction-link { display: inline-flex; margin-top: 12px; font-weight: 700; font-size: .9em; color: var(--color-fuchsia); }
.wydarzenie-card__instruction-link[hidden] { display: none; }
.wydarzenie-card__instruction-link:hover, .wydarzenie-card__instruction-link:focus-visible { color: var(--color-fuchsia-hover); }
.wydarzenie-card__join-row { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-top: 16px; }
.wydarzenie-card__join-row[hidden] { display: none; }
.wydarzenie-card__dog-select[hidden] { display: none; }
.wydarzenie-card__join-error { margin-top: 8px; flex-basis: 100%; }
.wydarzenie-card__join-error[hidden] { display: none; }
.wydarzenie-card__joined-note { font-size: .9em; font-weight: 700; color: var(--color-fuchsia); margin-top: 14px; }
.wydarzenie-card__joined-note[hidden] { display: none; }

/* Etap 9 §9/§18 — link instrukcji + notatka po zajęciach na kartach grafiku. */
.schedule-card__dog { font-size: .9em; color: var(--color-text); margin-top: 4px; }
.schedule-card__dog[hidden] { display: none; }
.schedule-card__personal-note { font-size: .9em; color: var(--color-text); margin-top: 10px; padding-top: 10px; border-top: var(--border-width) solid var(--color-line); }
.schedule-card__personal-note[hidden] { display: none; }
.schedule-card__instruction-link { display: inline-flex; margin-top: 10px; font-weight: 700; font-size: .9em; color: var(--color-fuchsia); }
.schedule-card__instruction-link[hidden] { display: none; }
.schedule-card__instruction-link:hover, .schedule-card__instruction-link:focus-visible { color: var(--color-fuchsia-hover); }

/* =========================================================
   Panel — Materiały (Panel MVP — etap 7, panel/materialy/). Sprawdzone
   grepem przed użyciem: ".material" nie występuje nigdzie indziej w tym
   pliku ani w HTML strony — brak ryzyka kolizji nazw jak przy
   ".event-card" w etapie 5 (patrz komentarz przy .wydarzenie-card wyżej).
   ========================================================= */

.materials-list { display: flex; flex-direction: column; gap: 16px; }

.materials-empty {
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-line);
  border-radius: var(--radius-md);
  padding: 28px 24px;
  color: var(--color-muted);
  font-size: .95em;
  line-height: 1.5;
}

.material-card {
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-line);
  border-radius: var(--radius-md);
  padding: 22px 24px;
}
.material-card__type { font-size: 12px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--color-fuchsia); }
.material-card__title { font-family: var(--font-display); font-weight: 600; font-size: 1.15rem; color: var(--color-ink); margin-top: 6px; }
.material-card__description { font-size: .92em; line-height: 1.5; color: var(--color-text); margin-top: 10px; }
.material-card__description[hidden] { display: none; }
.material-card__meta { font-size: .85em; color: var(--color-muted); margin-top: 10px; }
.material-card__file-meta { font-size: .85em; color: var(--color-muted); margin-top: 4px; }
.material-card__file-meta[hidden] { display: none; }

/* Etap 9 §21 — obrazy wyświetlane inline, bez CTA "Pobierz". */
.material-card__image { display: block; max-width: 100%; height: auto; border-radius: var(--radius-md); margin-top: 12px; }
.material-card__image[hidden] { display: none; }

.material-card__actions { margin-top: 16px; }
.material-card__error { margin-top: 12px; }
.material-card__error[hidden] { display: none; }

/* =========================================================
   Panel — Psy + ankieta startowa (etap 9 §5-6; profil psa,
   wiele psów i zdjęcie profilowe: etap 9C; skrócony finalny
   zakres profilu: etap 9C.3, panel/psy/).
   ========================================================= */
/* Etap 9C.3 — krótka podpowiedź pod polem (np. "jeśli nie znasz dokładnej
   daty..."), ten sam ton co .field__optional, ale jako osobny akapit pod
   inputem zamiast fragmentu labelki. */
.field__hint { margin: 6px 0 0; font-size: 13px; font-weight: 500; color: var(--color-muted); }

/* Finalny redesign — audyt wykazał nadmiar dekoracji (7+ doodli na jednej
   stronie, w tym kształty wprost zakazane przez DESIGN.md §4 - łapka,
   serduszko). Wszystkie doodle poza jednym (pies na kocyku w sidebarze,
   patrz sekcja sidebara wyżej) COFNIĘTE z "Moje psy" - .dogs-eyebrow i
   .dogs-lead wracają do zwykłego .eyebrow/.panel-main__lead bez żadnej
   dodatkowej dekoracji. Same pliki PNG zostają w assets/images/panel/,
   tylko przestały być renderowane w tym UI (patrz CLAUDE.md). ID/klasy
   używane przez script.js (.dogs-list/.dog-card*/.dog-add*/#dog-add-form/
   itd.) zostają nietknięte funkcjonalnie. */
.dogs-empty { color: var(--color-muted); margin-bottom: 20px; }

/* "Final UI pass" (13.09.2026) - H1+lead+CTA "+Dodaj psa"+karty psów żyją
   dziś razem w .section-shell--dogs (patrz wyżej), więc .dogs-header to
   wewnątrz shellu WYŁĄCZNIE przycisk/formularz "+ Dodaj psa" - zachowuje
   tylko odstęp + cienką linię oddzielającą od gridu kart poniżej (flex/
   justify-content/align-items/gap z jeszcze wcześniejszej wersji
   USUNIĘTE jako martwe przy pojedynczym dziecku). Dawny akcent-heart w
   H1 (.dogs-header__accent-heart) i fuksjowy underline pod H1
   (.dogs-header__intro .panel-main__heading::after) USUNIĘTE razem z
   .dogs-header__intro - to samo serce żyje dziś w .section-shell__decor,
   kolorowy box shellu zastępuje underline. */
.dogs-header {
  padding-bottom: 28px;
  margin-bottom: 32px;
  border-bottom: var(--border-width) solid var(--color-line);
}

/* KOREKTA "friendly editorial" — karty psa powiększone (zdjęcie ma być
   bohaterem, nie avatarem), minmax podniesiony z 340px do 440px: przy
   szerokości contentu panelu (~1240px) daje to dokładnie 2 karty w rzędzie
   (nie 3 jak poprzednio), 3+ psów naturalnie przechodzi do kolejnego rzędu.
   .dog-card max-width podniesiony do 640px - przy 1 psie karta jest duża i
   wyraźna, nie sztucznie ograniczona jak poprzednio (560px). */
.dogs-list { display: grid; grid-template-columns: repeat(auto-fit, minmax(440px, 1fr)); gap: 28px; margin-bottom: 24px; width: 100%; max-width: 100%; min-width: 0; }

/* KOREKTA "final polish" §6 - na ≤640px `minmax(440px,...)` wymuszał ślad
   kolumny SZERSZY niż sam viewport (440px > 360-390px dostępnej
   szerokości) - grid nie mógł się skurczyć poniżej tej wartości, więc
   `.dog-card` (naturalnie rozciągnięty na szerokość swojej kolumny)
   wychodził poza ekran ("ucięty prostokąt", zgłoszony błąd). Naprawione
   jawnym, węższym breakpointem: jedna kolumna, `minmax(0,1fr)` (nie
   sztywne px), plus zmniejszony padding karty (40px→24px, zbyt duży na
   360-390px) i twarde `max-width:100%` na obu poziomach - karta i CTA w
   jej środku nigdy nie mogą być szersze niż viewport. */
@media (max-width: 640px) {
  .dogs-list { grid-template-columns: minmax(0, 1fr); }
  .dog-card { max-width: 100%; padding: 24px; gap: 20px; }
}

/* Jedyny editorialowy akcent strony (patrz .section-shell__decor wyżej) -
   "Psy zmieniają wszystko" + wcześniejszy blok pod gridem kart USUNIĘTE
   (kontrola po live review) - mały graphite heart żyje dziś w page hero
   zamiast osobnego bloku pod listą kart. */

/* Karta psa = system strony WWW (DESIGN.md §8.1): biały surface, cienka
   linia, radius, ZERO cienia. Jedyny akcent to bardzo subtelna fuksja-soft
   "aureola" wokół zdjęcia (patrz .dog-card__media niżej) - NIE całe różowe
   tło karty. Bez dekoracji korony/serca/scribble - te trzy COFNIĘTE (patrz
   CLAUDE.md, audyt: łapka/serduszko to kształty wprost zakazane w
   DESIGN.md §4). Więcej paddingu ("dużo oddechu", polecenie §1). */
.dog-card {
  position: relative;
  width: 100%;
  max-width: 640px;
  min-width: 0;
  margin-inline: 0;
  box-sizing: border-box;
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-line);
  border-radius: var(--radius-lg);
  padding: 40px;
  display: flex;
  gap: 28px;
  align-items: flex-start;
  flex-wrap: wrap;
}
/* Zdjęcie psa jest głównym elementem wizualnym karty (polecenie "friendly
   editorial" §1) - powiększone ze 124px do 150px, object-fit:cover.
   .dog-card__media dostaje bardzo lekką fuksja-soft "aureolę" (padding +
   tło + border-radius:50% wokół samego zdjęcia/placeholdera) - jedyny
   kolorowy akcent karty, celowo nie całe różowe tło. Etap 9C §7/§16 -
   miniatura albo neutralny placeholder (inicjał imienia), nigdy
   broken-image: <img> zostaje [hidden] dopóki fetch()+Blob nie dostarczy
   prawdziwego zdjęcia (patrz script.js, "sam <img src>" nie wysłałby
   nagłówka Authorization). */
.dog-card__media {
  position: relative;
  flex: 0 0 auto;
  padding: 8px;
  background: var(--color-fuchsia-soft);
  border-radius: 50%;
}
.dog-card__photo, .dog-card__photo-placeholder {
  width: 150px;
  height: 150px;
  border-radius: 50%;
  border: 3px solid var(--color-surface);
}
.dog-card__photo { display: block; object-fit: cover; }
.dog-card__photo[hidden] { display: none; }
.dog-card__photo-placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--color-surface-alt);
  color: var(--color-fuchsia);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 2.8rem;
}
.dog-card__photo-placeholder[hidden] { display: none; }
.dog-card__body { flex: 1 1 240px; min-width: 0; }
/* Imię wyraźnie większe (1.7rem -> 2.1rem) - ma dominować nad danymi i
   statusem ankiety, nie odwrotnie (polecenie §1 "Treść"). */
.dog-card__name { font-family: var(--font-display); font-weight: 600; font-size: 2.1rem; color: var(--color-ink); }
/* "Dane psa spokojniejsze i czytelniejsze" - przygaszony kolor
   (--color-muted zamiast --color-text) i odstęp od imienia. */
.dog-card__details { font-size: 1em; color: var(--color-muted); margin-top: 10px; line-height: 1.5; }
/* Status ankiety ma być "mały i pomocniczy, nie dominować nad imieniem i
   zdjęciem" (polecenie §1 "Treść") - zmniejszony font/padding względem
   poprzedniej wersji. Fuksja "soft" = jeszcze nie wypełniona (wymaga
   uwagi/akcji), neutralny grafitowy chip = wypełniona (zamknięty temat) -
   żadnej wymyślonej zieleni, oba warianty to istniejące tokeny globalnego
   systemu. Klasa modyfikatora przełączana w script.js
   (statusEl.classList.toggle - WYŁĄCZNIE zmiana klasy prezentacyjnej, ten
   sam fetch/te same dane co dotychczas, zero nowej logiki/endpointów). */
.dog-card__questionnaire-status {
  display: inline-flex;
  align-items: center;
  margin-top: 12px;
  padding: 5px 13px;
  border-radius: var(--radius-pill);
  background: var(--color-surface-alt);
  color: var(--color-muted);
  font-size: .78em;
  font-weight: 600;
}
.dog-card__questionnaire-status--pending { background: var(--color-fuchsia-soft); color: var(--color-fuchsia-hover); }
.dog-card__questionnaire-status--done { background: var(--color-surface-alt); color: var(--color-ink); }
.dog-card__actions { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 22px; }
.dog-card__edit-form, .dog-card__questionnaire, .dog-card__photo-upload { margin-top: 20px; padding-top: 20px; border-top: var(--border-width) solid var(--color-line); }
.dog-card__edit-form[hidden], .dog-card__questionnaire[hidden], .dog-card__photo-upload[hidden] { display: none; }
.dog-card__photo-summary[hidden] { display: none; }
/* Etap 9C.3 §7 — proste 2-krokowe UI: "Wybierz zdjęcie" (label udający
   przycisk, opakowuje wizualnie ukryty <input type=file> - kliknięcie
   gdziekolwiek na labelce otwiera natywny picker plików) + nazwa wybranego
   pliku jako potwierdzenie + "Zapisz zdjęcie". Zero wzmianki o MB/limicie
   w widocznym UI (§7 polecenia - klient nie ma wiedzieć, ile waży zdjęcie). */
.dog-card__photo-upload {
  background: var(--color-bg);
  padding: 18px 18px 20px;
  border-radius: var(--radius-md);
  border-top: none;
}
.dog-card__photo-upload-heading { font-family: var(--font-body); font-weight: 700; font-size: 15px; color: var(--color-ink); margin: 0 0 10px; }
.dog-card__photo-upload-row { display: flex; align-items: center; flex-wrap: wrap; gap: 12px; margin-bottom: 14px; }
.dog-card__photo-choose-label { cursor: pointer; }
.dog-card__photo-filename { font-size: .9em; color: var(--color-muted); word-break: break-all; }
/* Wzorzec "visually hidden, ale nadal dostępny klawiaturą/czytnikiem ekranu"
   (sr-only) - w odróżnieniu od .hp-field (honeypot) to jest prawdziwe,
   używane pole formularza, tylko wizualnie zastąpione przyciskiem-labelką. */
.file-input-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Popr. po live review — usunięty duży, pusty różowy pasek. "+ Dodaj psa"
   to teraz WYŁĄCZNIE duży różowy przycisk (.btn.btn--primary.btn--large na
   <summary> w HTML) osadzony w rzędzie obok nagłówka sekcji (.dogs-header
   wyżej). Domknięty .dog-add zajmuje tylko szerokość przycisku
   (flex: 0 0 auto - dziedziczone z domyślnego zachowania flex item), więc
   nie ma już efektu "wielkiego pustego pudła". Otwarty (klient kliknął
   przycisk) rozciąga się na pełny wiersz (flex-basis:100%) i formularz
   dostaje własną, jasną kartę - <details>/<summary> i cała reszta
   zachowania BEZ ZMIAN (natywny toggle, ten sam #dog-add-form, te same ID
   pól) - wyłącznie warstwa wizualna. */
.dog-add { position: relative; flex: 0 0 auto; }
.dog-add[open] { flex-basis: 100%; }
.dog-add summary { cursor: pointer; list-style: none; }
.dog-add summary::-webkit-details-marker { display: none; }
.dog-add__form {
  margin-top: 24px;
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-line);
  border-radius: var(--radius-lg);
  padding: 28px;
}
.questionnaire-section { border: none; padding: 0; margin: 0 0 24px; }
.questionnaire-section__fields { display: flex; flex-direction: column; gap: 14px; margin-top: 10px; }

/* KOREKTA "final polish" §38 - nowe typy pytań ankiety startowej (scale/
   single/multi/yesno) - proste, dostępne (radio/checkbox+label, klawiatura
   działa natywnie), spójne z resztą systemu formularzy (.field, kolory
   fuksji przy zaznaczeniu). */
.field__question-label { font-family: var(--font-body); font-weight: 700; font-size: .95em; color: var(--color-ink); margin: 0 0 8px; }
.scale-pills { display: flex; flex-wrap: wrap; gap: 6px; }
.scale-pills__option {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  border: var(--border-width) solid var(--color-line);
  font-size: .85em;
  font-weight: 700;
  color: var(--color-text);
  cursor: pointer;
  transition: background-color .15s var(--ease), border-color .15s var(--ease), color .15s var(--ease);
}
.scale-pills__option input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.scale-pills__option:has(input:checked) { background: var(--color-fuchsia); border-color: var(--color-fuchsia); color: var(--color-white); }
.scale-pills__option:has(input:focus-visible) { outline: 2px solid var(--color-fuchsia); outline-offset: 2px; }
.scale-pills__anchors { display: flex; flex-direction: column; gap: 2px; margin-top: 8px; font-size: .82em; color: var(--color-muted); }
.choice-list { display: flex; flex-direction: column; gap: 8px; }
.choice-list__option {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  border: var(--border-width) solid var(--color-line);
  /* Etap 9E.4 §17 polecenia - choice cards ok. 14-16px, --radius-md (24px)
     wyglądał zbyt "pigułkowo" na tak kompaktowym elemencie listy. */
  border-radius: var(--radius-sm);
  font-size: .92em;
  color: var(--color-text);
  cursor: pointer;
  transition: background-color .15s var(--ease), border-color .15s var(--ease);
}
.choice-list__option:has(input:checked) { background: var(--color-fuchsia-soft); border-color: var(--color-fuchsia); color: var(--color-ink); font-weight: 700; }
.choice-list__option:has(input:focus-visible) { outline: 2px solid var(--color-fuchsia); outline-offset: 2px; }

/* "Finalna ankieta startowa" (13.09.2026) - wizard "jedno pytanie na
   ekran" (panel/psy/index.html, script.js buildQuestionnaireWizard()),
   zastępuje poprzedni jednoekranowy formularz ze wszystkimi sekcjami
   naraz. Reużywa istniejących .scale-pills/.choice-list/.field/
   .form__summary (zero nowego systemu formularzy) - poniższe klasy to
   wyłącznie powłoka/layout wokół tych już istniejących komponentów. */
.questionnaire-wizard { max-width: 520px; }
.questionnaire-wizard__category { margin: 0 0 6px; }
.questionnaire-wizard__progress-label { font-size: .82em; color: var(--color-muted); margin: 0 0 8px; }
.questionnaire-wizard__progress-bar { height: 6px; border-radius: 999px; background: var(--color-surface-alt); overflow: hidden; margin-bottom: 22px; }
.questionnaire-wizard__progress-fill { height: 100%; background: var(--color-fuchsia); border-radius: 999px; transition: width .2s var(--ease); }
/* "Questionnaire optional/skip flow" (13.09.2026) - §2 polecenia: spokojny
   helper text pod "Pytanie X z 22", świadomie ten sam przygaszony,
   drobny styl co reszta pomocniczych podpowiedzi w tym komponencie
   (.questionnaire-wizard__helper niżej) - NIE wielki alert/box. */
.questionnaire-wizard__skip-hint { font-size: .85em; color: var(--color-muted); margin: 0 0 18px; }
.questionnaire-wizard__question { margin-bottom: 18px; }
.questionnaire-wizard__question-label { font-size: 1.05em; margin-bottom: 14px; }
.questionnaire-wizard__helper { font-size: .85em; color: var(--color-muted); margin: -10px 0 14px; }
.questionnaire-wizard__scale-extra { margin-top: 10px; width: 100%; box-sizing: border-box; }
.questionnaire-wizard__subfield { margin-top: 14px; }
.questionnaire-wizard__main-textarea textarea { min-height: 4.5em; }
/* "Questionnaire final 15" (13.09.2026) - nagłówek podpytania wewnątrz
   złożonych kroków `dual-scale` (krok 3: "W domu"/"Poza domem") i
   `compound` (krok 15: prior_work/anything_else) - mały eyebrow-podobny
   label oddzielający kolejne pod-pytania na tym samym ekranie. */
.questionnaire-wizard__sub-heading { font-weight: 700; font-size: .95em; color: var(--color-ink); margin: 22px 0 10px; }
/* §8 polecenia - "Pomiń to pytanie": subtelny tekstowy link, NIGDY drugi
   duży primary button - stąd zwykły <button> odchudzony do wyglądu linku
   (bez tła/ramki/paddingu), nie .btn--outline/.btn--primary. */
.questionnaire-wizard__skip-link {
  display: inline-block;
  margin-top: 16px;
  background: none;
  border: none;
  padding: 0;
  font-size: .9em;
  color: var(--color-muted);
  text-decoration: underline;
  cursor: pointer;
}
.questionnaire-wizard__skip-link:hover, .questionnaire-wizard__skip-link:focus-visible { color: var(--color-fuchsia-hover); }
.questionnaire-wizard__skip-link:focus-visible { outline: 2px solid var(--color-fuchsia); outline-offset: 3px; }
.questionnaire-wizard__error { margin-bottom: 18px; }
.questionnaire-wizard__nav { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.questionnaire-wizard__back:only-child { margin-left: 0; }
.questionnaire-wizard__nav .questionnaire-wizard__back[hidden] { display: none; }
.questionnaire-wizard__nav .questionnaire-wizard__next { margin-left: auto; }
.questionnaire-wizard__next:disabled { opacity: .5; cursor: not-allowed; }
.questionnaire-resume { display: flex; flex-direction: column; align-items: flex-start; gap: 14px; max-width: 480px; }
.questionnaire-resume .btn { align-self: flex-start; }
.questionnaire-success { max-width: 480px; }
.questionnaire-success__heading { font-family: var(--font-display); font-size: 1.4em; margin: 0 0 10px; }
.questionnaire-success .btn { margin-top: 16px; }
@media (prefers-reduced-motion: reduce) {
  .questionnaire-wizard__progress-fill { transition: none; }
}

/* =========================================================
   Panel — Zasady i instrukcje (etap 9 §8-9, panel/zasady/).
   PRZEBUDOWANE "live review 3" - dedykowany, page-scoped komponent
   (.rules-section/.rules-accordion*) zamiast reużycia globalnego
   .accordion (poprzednia tura) - jawne żądanie tej tury, niezależne od
   FAQ homepage. Wcześniejsze `.rules-group`/`.rules-group__heading`
   USUNIĘTE jako martwy kod (HTML już ich nie używa).
   ========================================================= */
/* "Final UI pass" (13.09.2026) - CAŁA strona (intro + obie grupy
   accordionów) żyje dziś w JEDNYM .section-shell--rules (patrz wyżej) -
   odstęp intro→pierwsza sekcja liczy się z .section-shell__header{margin-
   bottom:32px}, nie z samego leadu. Poprzednia reguła `.rules-page
   .panel-main__lead { margin-bottom: 40px; }` jest USUNIĘTA (nadawałaby
   margines WEWNĄTRZ kolorowego boxu, nie pod nim). Sam spacing MIĘDZY
   dwiema grupami accordionów (.rules-section margin-bottom, patrz niżej)
   jest CAŁKOWICIE nietknięty tą turą. */
/* "Visual polish" (13.09.2026) - ZNALEZIONA PRZYCZYNA "ogromnych przerw"
   (nie tylko mobile): globalna, sitewide reguła elementu `section {
   padding-block: var(--section-pad) }` (56px, pomyślana dla dużych
   sekcji marketingowych homepage) cicho stosowała się też TUTAJ, bo
   `.rules-section` jest semantycznie `<section>`. Efekt: każda grupa
   dostawała DODATKOWE 56px paddingu na górze I na dole, ponad własny
   margin-bottom (36px) - między ostatnim akordeonem grupy a kolejnym
   nagłówkiem realnie było blisko 150px, nie 36px zadeklarowane w tym
   komponencie. Jawny reset do 0 usuwa tę ukrytą, przypadkową warstwę -
   cała reszta odstępu poniżej jest już w pełni jawna/zamierzona. */
.rules-section { padding-block: 0; margin-bottom: 32px; }
.rules-section:last-child { margin-bottom: 0; }
@media (min-width: 768px) { .rules-section { margin-bottom: 44px; } }
.rules-section__heading { font-family: var(--font-display); font-weight: 600; font-size: 1.6rem; color: var(--color-ink); margin-bottom: 14px; }
@media (min-width: 768px) { .rules-section__heading { font-size: 1.85rem; margin-bottom: 20px; } }

/* Zwarty akordeon: każda pozycja to WŁASNA biała karta (border+radius
   panelu), nie płaska lista z border-top/border-bottom (jak FAQ) - stąd
   osobny komponent zamiast .accordion. Karty mają naturalną wysokość
   (brak min-height) i małe odstępy (gap), więc bez "ogromnych przerw"
   znanych z poprzedniej wersji. */
.rules-accordion { display: flex; flex-direction: column; gap: 8px; }
@media (min-width: 768px) { .rules-accordion { gap: 12px; } }
.rules-accordion__item {
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-line);
  border-radius: var(--radius-lg);
  overflow: hidden;
}
.rules-accordion__trigger {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 16px 18px;
  text-align: left;
  background: none;
  border: none;
  font-family: var(--font-display);
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--color-ink);
  cursor: pointer;
}
@media (min-width: 768px) { .rules-accordion__trigger { padding: 20px 22px; } }
.rules-accordion__icon { width: 20px; height: 20px; flex-shrink: 0; color: var(--color-muted); transition: transform .22s var(--ease), color .18s var(--ease); }
.rules-accordion__trigger:hover .rules-accordion__icon,
.rules-accordion__trigger:focus-visible .rules-accordion__icon,
.rules-accordion__trigger[aria-expanded="true"] .rules-accordion__icon { color: var(--color-fuchsia); }
.rules-accordion__trigger[aria-expanded="true"] .rules-accordion__icon { transform: rotate(45deg); }
.rules-accordion__trigger:hover span { text-decoration: underline; text-decoration-color: var(--color-fuchsia); text-decoration-thickness: 2px; text-underline-offset: 5px; }
.rules-accordion__panel { padding: 0 18px 18px; max-width: 68ch; }
@media (min-width: 768px) { .rules-accordion__panel { padding: 0 22px 20px; } }
.rules-accordion__panel p { font-size: .95em; line-height: 1.55; color: var(--color-text); }
.rules-accordion__panel p + p { margin-top: 10px; }
/* KOREKTA "final polish" §21 - `.rules-accordion__panel a{color:fuchsia}`
   (bez :not(.btn)) miało WYŻSZĄ specyficzność (0,1,1) niż `.btn--primary`
   (0,1,0), więc wygrywał na CTA "Napisz do Martyny" - tekst fuksja NA
   tle fuksja, czyli wizualnie pusty, różowy przycisk (dokładnie zgłoszony
   błąd). `:not(.btn)` ogranicza tę regułę do zwykłych tekstowych linków,
   `.btn--primary`/`:hover`/`:focus-visible` (globalne, białe na fuksji)
   znów w pełni rządzą przyciskiem - widoczny tekst, prawidłowy kontrast,
   normalny hover/focus (dziedziczone z komponentu .btn, nietknięte). */
.rules-accordion__panel a:not(.btn) { color: var(--color-fuchsia); font-weight: 700; }
.rules-accordion__panel a:not(.btn):hover, .rules-accordion__panel a:not(.btn):focus-visible { color: var(--color-fuchsia-hover); }
@media (prefers-reduced-motion: reduce) {
  .rules-accordion__icon { transition: none; }
}

/* KOREKTA "live review 4" §5-§7 - instrukcje zajęć priorytetyzują "Jak się
   przygotować?" (zwarta, skanowalna lista) nad opisem przebiegu zajęć.
   .rules-prep__heading/__list to GŁÓWNA treść panelu (zawsze widoczna po
   otwarciu akordeonu); .rules-details to natywny <details>/<summary> -
   drugorzędny, domyślnie zwinięty blok "Jak wyglądają zajęcia?" - zero
   nowego JS (natywna funkcja przeglądarki), dodawany WYŁĄCZNIE gdy wnosi
   realną wartość (część typów zajęć go nie ma). */
.rules-prep__heading { font-family: var(--font-display); font-weight: 600; font-size: 1em; color: var(--color-ink); margin: 0 0 8px; }
.rules-prep__list { margin: 0; padding-left: 20px; display: flex; flex-direction: column; gap: 6px; }
.rules-prep__list li { font-size: .95em; line-height: 1.5; color: var(--color-text); }
.rules-prep__list + .rules-details { margin-top: 14px; }
.rules-details summary {
  font-size: .92em;
  font-weight: 700;
  color: var(--color-fuchsia);
  cursor: pointer;
  list-style: none;
}
.rules-details summary::-webkit-details-marker { display: none; }
.rules-details summary::before { content: "+ "; }
.rules-details[open] summary::before { content: "- "; }
.rules-details p { font-size: .92em; line-height: 1.5; color: var(--color-text); margin-top: 8px; }

/* =========================================================
   Panel — Kontakt i społeczność (etap 9 §23, przebudowane turą
   "Content + Mobile + Panel UX", panel/kontakt/).
   ========================================================= */
/* "Final UI pass" (13.09.2026) - CTA żyje teraz WEWNĄTRZ .section-shell--
   contact (§12 polecenia - "nie może zostać drugi osobny różowy box").
   .contact-community traci własne tło/padding - zostaje WYŁĄCZNIE
   wyśrodkowującym wrapperem, bez żadnego koloru/karty na drugim poziomie. */
.contact-community {
  margin-top: 8px;
  display: flex;
  justify-content: center;
  align-items: center;
  text-align: center;
}

/* =========================================================
   Panel — Kursy online (etap 9 §22, panel/kursy/).
   ========================================================= */
.courses-grid { display: grid; gap: 20px; grid-template-columns: 1fr; }
@media (min-width: 640px) { .courses-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .courses-grid { grid-template-columns: repeat(3, 1fr); } }
.course-card {
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-line);
  border-radius: var(--radius-lg);
  padding: 24px;
  text-align: center;
}
.course-card--locked { opacity: .92; }
/* Status "Masz dostęp"/"Dostęp do kupienia" (polecenie "Content + Mobile +
   Panel UX" §17-18) - subtelna ikona kłódki wyłącznie przy braku dostępu,
   jako wizualna informacja, nie zabezpieczenie (patrz komentarz w HTML). */
.course-card__status {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 5px 14px;
  border-radius: var(--radius-pill);
  font-size: .8em;
  font-weight: 700;
  margin-bottom: 14px;
  background: var(--color-fuchsia-soft);
  color: var(--color-fuchsia-hover);
}
.course-card--locked .course-card__status { background: var(--color-surface-alt); color: var(--color-muted); }
.course-card__lock { width: 14px; height: 14px; flex-shrink: 0; }
.course-card__lock[hidden] { display: none; }
.course-card__title { font-family: var(--font-display); font-weight: 600; font-size: 1.1rem; color: var(--color-ink); margin-bottom: 12px; }
.courses-empty {
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-line);
  border-radius: var(--radius-md);
  padding: 28px 24px;
  color: var(--color-muted);
  font-size: .95em;
}

/* =========================================================
   Panel — Onboarding (etap 9 §7, panel/onboarding/). Świadomie BEZ
   .panel-nav/.panel-status-badge - onboarding poprzedza zwykły Dashboard.
   ========================================================= */
.onboarding-page { max-width: 640px; }
.onboarding-step { margin-top: 32px; }
.onboarding-step[hidden] { display: none; }
.onboarding-step h2 { font-family: var(--font-display); font-weight: 600; font-size: 1.2rem; color: var(--color-ink); margin-bottom: 14px; }
.onboarding-rules-list { display: flex; flex-direction: column; gap: 12px; margin: 0 0 24px; padding-left: 20px; }
.onboarding-rules-list li { font-size: .95em; line-height: 1.5; color: var(--color-text); }
#onboarding-dog-added { font-weight: 700; color: var(--color-fuchsia); margin-top: 12px; }
#onboarding-dog-added[hidden] { display: none; }
