/*
Theme Name: jkbnieruchomosci
Description: A child theme of Themify Basic
Template: basic
Author: Arkadiusz Malkowski (kontakt@amalkowski.pl)
Version: 1.6.2
*/

/* =========================================================================
   SPIS TREŚCI
   -------------------------------------------------------------------------
   01. Fonty (lokalne, bez CDN)
   02. Tokeny projektu (:root)
   03. Reset i typografia globalna
   04. Nagłówek: pasek kontaktowy + belka nawigacji
   05. Stopka
   06. Warstwa treści Buildera (klasy do pola "CSS Class")
   07. Przyciski i badge
   08. Sekcja: hero
   09. Sekcja: o nas
   10. Sekcja: usługi
   11. Sekcja: dlaczego JKB (kafelki)
   12. Sekcja: proces (kroki 01-04)
   13. Sekcja: nieruchomości (karty ofert)
   14. Sekcja: opinie
   15. Sekcja: kontakt
   16. Ikony SVG
   17. Responsywność
   18. Uzupełnienia (obejścia specyficzności i markupu Themify)
   19. Pojedyncza oferta (single-nieruchomosc.php)
   20. Galeria oferty (duże zdjęcie + miniatury + powiększenie)
   21. Moduł: opinie klientów (karuzela)
   ========================================================================= */


/* =========================================================================
   01. FONTY
   Pliki leżą w <motyw>/fonts/, bo tylko dla images/ i fonts/ Themify
   przelicza ścieżki względne przy sklejaniu arkusza do concate.css.
   ========================================================================= */

/* Lato - tekst czytelny */
@font-face {
	font-family: 'Lato';
	font-style: normal;
	font-weight: 400;
	font-display: swap;
	src: url('fonts/lato-400-latin-ext.woff2') format('woff2');
	unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
	font-family: 'Lato';
	font-style: normal;
	font-weight: 400;
	font-display: swap;
	src: url('fonts/lato-400-latin.woff2') format('woff2');
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
	font-family: 'Lato';
	font-style: italic;
	font-weight: 400;
	font-display: swap;
	src: url('fonts/lato-400i-latin-ext.woff2') format('woff2');
	unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
	font-family: 'Lato';
	font-style: italic;
	font-weight: 400;
	font-display: swap;
	src: url('fonts/lato-400i-latin.woff2') format('woff2');
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
	font-family: 'Lato';
	font-style: normal;
	font-weight: 700;
	font-display: swap;
	src: url('fonts/lato-700-latin-ext.woff2') format('woff2');
	unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
	font-family: 'Lato';
	font-style: normal;
	font-weight: 700;
	font-display: swap;
	src: url('fonts/lato-700-latin.woff2') format('woff2');
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Montserrat - nagłówki. Plik zmienny: jeden na cały zakres 400-800,
   dlatego font-weight to zakres, a nie pojedyncza wartość. */
@font-face {
	font-family: 'Montserrat';
	font-style: normal;
	font-weight: 400 800;
	font-display: swap;
	src: url('fonts/montserrat-var-latin-ext.woff2') format('woff2');
	unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
	font-family: 'Montserrat';
	font-style: normal;
	font-weight: 400 800;
	font-display: swap;
	src: url('fonts/montserrat-var-latin.woff2') format('woff2');
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}


/* =========================================================================
   02. TOKENY PROJEKTU
   Jedyne miejsce z wartościami. Reszta arkusza używa wyłącznie zmiennych,
   więc zmiana palety u klienta to edycja tego jednego bloku.
   ========================================================================= */

:root {
	/* --- Granat (kolor główny marki) --- */
	--jkb-navy-900: #071528;
	--jkb-navy-800: #0b2443;
	--jkb-navy-700: #14314f;
	--jkb-navy-600: #1d3f61;
	--jkb-ink: #111111;

	/* --- Złoto (kolor akcentu) --- */
	--jkb-gold-700: #8f7539;
	--jkb-gold-600: #a88b45;

	/* --- Ciepłe złoto: wyłącznie przycisk główny ---
	   Osobna skala, bo paleta akcentu (gold-*) jest przygaszona i szarawa -
	   dobrze wygląda na cienkich kreskach i obramowaniach, ale wypełniona
	   płaszczyzna robi się z niej wypłowiały brąz.
	   NIE używać tych kolorów do tekstu - jasny odcień jest za jaskrawy. */
	--jkb-btn-gold-light: #ffe55e;   /* jasny błysk pośrodku */
	--jkb-btn-gold-mid:   #bf953f;   /* ciepłe złoto */
	--jkb-btn-gold-dark:  #b38728;   /* ciemniejsze złoto, krawędzie */
	--jkb-gold-500: #c7a962;
	--jkb-gold-400: #d3ba7d;
	--jkb-gold-300: #e0cb9a;
	--jkb-gold-100: #f3ebda;

	/* --- Neutralne --- */
	--jkb-white: #ffffff;
	--jkb-grey-50: #f7f8f9;
	--jkb-grey-100: #eef1f3;
	--jkb-grey-200: #e7ebed;
	--jkb-grey-300: #d8dee3;
	--jkb-grey-500: #8c959e;
	--jkb-grey-700: #56606b;

	/* --- Semantyczne: powierzchnie --- */
	--jkb-surface-page: var(--jkb-white);
	--jkb-surface-section: var(--jkb-grey-200);
	--jkb-surface-card: var(--jkb-white);
	--jkb-surface-inverse: var(--jkb-navy-800);
	--jkb-surface-inverse-deep: var(--jkb-navy-900);
	--jkb-surface-bar: var(--jkb-ink);
	--jkb-surface-tile-inverse: rgba(255, 255, 255, 0.04);

	/* --- Semantyczne: tekst --- */
	--jkb-text-heading: var(--jkb-navy-800);
	--jkb-text-body: var(--jkb-grey-700);
	--jkb-text-muted: var(--jkb-grey-500);
	--jkb-text-on-inverse: var(--jkb-white);
	--jkb-text-on-inverse-muted: rgba(255, 255, 255, 0.72);
	--jkb-text-accent: var(--jkb-gold-500);
	--jkb-text-accent-on-inverse: var(--jkb-gold-400);

	/* --- Semantyczne: obramowania i linie --- */
	--jkb-border-subtle: var(--jkb-grey-300);
	--jkb-border-card: var(--jkb-grey-200);
	--jkb-border-accent: var(--jkb-gold-500);
	--jkb-border-on-inverse: rgba(199, 169, 98, 0.45);
	--jkb-rule-accent: var(--jkb-gold-500);

	/* --- Semantyczne: akcje --- */
	--jkb-action-primary-bg: var(--jkb-btn-gold-mid);
	--jkb-action-primary-fg: var(--jkb-navy-900);
	--jkb-action-primary-border: var(--jkb-btn-gold-dark);

	/* Gradient przycisku głównego: ukośna smuga jasnego złota przez środek,
	   ciemniejsze końce - efekt sztabki metalu. Kąt i punkty zatrzymania
	   pochodzą od klienta, nie zmieniaj ich bez uzgodnienia.
	   --jkb-action-primary-bg zostaje jako podkład, więc gdyby gradient nie
	   zadziałał, przycisk dalej jest złoty, a nie przezroczysty.

	   Animację hover robi background-size (patrz sekcja 07): background-image
	   nie interpoluje się między wartościami, więc podmiana gradientu dawałaby
	   skok zamiast płynnego przejścia. */
	--jkb-action-primary-gradient: linear-gradient(
		52deg,
		var(--jkb-btn-gold-mid) 0%,
		var(--jkb-btn-gold-light) 50%,
		var(--jkb-btn-gold-dark) 100%
	);
	--jkb-action-secondary-fg: var(--jkb-gold-500);
	--jkb-action-secondary-border: var(--jkb-gold-500);
	--jkb-action-quiet-fg: var(--jkb-navy-800);

	/* --- Overlay na zdjęciach (hero) --- */
	--jkb-overlay-hero: linear-gradient(90deg, rgba(7, 21, 40, 0.86) 0%, rgba(7, 21, 40, 0.62) 45%, rgba(7, 21, 40, 0.25) 100%);
	--jkb-overlay-image: rgba(7, 21, 40, 0.35);

	/* --- Gwiazdki ocen --- */
	--jkb-star: var(--jkb-gold-500);

	/* --- Typografia --- */
	--jkb-font-display: 'Montserrat', 'Segoe UI', system-ui, sans-serif;
	--jkb-font-body: 'Lato', 'Segoe UI', system-ui, sans-serif;

	--jkb-weight-regular: 400;
	--jkb-weight-medium: 500;
	--jkb-weight-semibold: 600;
	--jkb-weight-bold: 700;
	--jkb-weight-black: 800;

	--jkb-size-hero: 52px;
	--jkb-size-h1: 40px;
	--jkb-size-h2: 32px;
	--jkb-size-h3: 22px;
	--jkb-size-h4: 18px;
	--jkb-size-numeral: 56px;   /* liczby kroków 01-04 */
	--jkb-size-body: 16px;
	--jkb-size-small: 14px;
	--jkb-size-caption: 13px;
	--jkb-size-micro: 12px;

	--jkb-leading-tight: 1.15;
	--jkb-leading-heading: 1.25;
	--jkb-leading-body: 1.6;

	--jkb-tracking-heading: 0.02em;
	--jkb-tracking-caps: 0.08em;   /* nagłówki sekcji UPPERCASE */
	--jkb-tracking-button: 0.06em;

	/* --- Odstępy --- */
	--jkb-space-1: 4px;
	--jkb-space-2: 8px;
	--jkb-space-3: 12px;
	--jkb-space-4: 16px;
	--jkb-space-5: 24px;
	--jkb-space-6: 32px;
	--jkb-space-7: 40px;
	--jkb-space-8: 56px;
	--jkb-space-9: 72px;
	--jkb-space-10: 96px;

	--jkb-section-padding-y: var(--jkb-space-9);
	--jkb-container-max: 1200px;
	--jkb-grid-gap: var(--jkb-space-5);

	/* --- Promienie: projekt jest niemal ostrokątny --- */
	--jkb-radius-none: 0px;
	--jkb-radius-sm: 2px;
	--jkb-radius-md: 4px;
	--jkb-radius-image: 2px;
	--jkb-border-width: 1px;
	--jkb-border-width-accent: 2px;

	/* --- Cienie i ruch --- */
	--jkb-shadow-card: 0 1px 3px rgba(7, 21, 40, 0.06), 0 6px 18px rgba(7, 21, 40, 0.06);
	--jkb-shadow-card-hover: 0 2px 6px rgba(7, 21, 40, 0.08), 0 14px 32px rgba(7, 21, 40, 0.12);
	--jkb-shadow-header: 0 2px 12px rgba(7, 21, 40, 0.18);
	--jkb-shadow-inset-tile: inset 0 0 0 1px rgba(199, 169, 98, 0.35);

	--jkb-transition-fast: 120ms ease-out;
	--jkb-transition-base: 200ms ease-out;
	--jkb-transition-slow: 320ms cubic-bezier(0.22, 0.61, 0.36, 1);
	--jkb-hover-lift: translateY(-2px);
}


/* =========================================================================
   03. RESET I TYPOGRAFIA GLOBALNA
   Rodzic (Themify Basic) ma własną typografię; nadpisujemy ją tokenami.
   ========================================================================= */

/* UWAGA: NIE ustawiaj tu scroll-behavior: smooth.
   Themify doładowuje treść leniwie (data-lazy) i zmiany układu w trakcie
   przewijania anulują płynne przewijanie przeglądarki - kotwice przestają
   wtedy działać zupełnie, po cichu. Sprawdzone: scrollIntoView({behavior:
   'instant'}) przewija poprawnie, a to samo z 'smooth' kończy się na zerze.
   Skok do sekcji jest więc natychmiastowy i to jest świadomy wybór. */

body {
	font-family: var(--jkb-font-body);
	font-size: var(--jkb-size-body);
	line-height: var(--jkb-leading-body);
	color: var(--jkb-text-body);
	background: var(--jkb-surface-page);
	-webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4, h5, h6 {
	font-family: var(--jkb-font-display);
	color: var(--jkb-text-heading);
	line-height: var(--jkb-leading-heading);
	letter-spacing: var(--jkb-tracking-heading);
	font-weight: var(--jkb-weight-bold);
}

h1 { font-size: var(--jkb-size-h1); }
h2 { font-size: var(--jkb-size-h2); }
h3 { font-size: var(--jkb-size-h3); }
h4 { font-size: var(--jkb-size-h4); }

a {
	color: var(--jkb-gold-500);
	text-decoration: none;
	transition: color var(--jkb-transition-fast);
}
a:hover { color: var(--jkb-gold-600); }

/* Szerokość treści.
   NIE ograniczamy .pagewidth - rodzic wiesza tę klasę na #layout i trzyma na
   niej max-width:100%. Ustawienie tam 1200px zaklinowałoby całą stronę na
   1200px i tła sekcji przestałyby sięgać krawędzi ekranu.
   Limit szerokości nakładamy wyłącznie na wnętrze wiersza Buildera: rodzic
   daje .row_inner width:978px, a Builder width:min(1160px,100%) - to WIDTH,
   nie max-width, więc podnoszenie max-width nic by nie dało. Ich responsywne
   max-width (94% / 90% w media query) zostawiamy, bo robi boczne marginesy. */
#body .themify_builder_row > .row_inner {
	width: min(var(--jkb-container-max), 100%);
}

/* Odstęp między kolumnami wg projektu (24px). Builder liczy go w procentach
   (--colg: 3.2%), co przy 1200px daje ~38px. Zmienną trzeba nadpisać na tym
   samym elemencie, na którym ją definiuje, czyli na .row_inner. */
.module_row.jkb-grid > .row_inner {
	--colg: var(--jkb-grid-gap);
	--rowg: var(--jkb-grid-gap);
}

/* Rodzic rezerwuje miejsce na własny nagłówek i stopkę - kasujemy,
   bo child ma własne header.php / footer.php bez tych marginesów.
   #header ma u rodzica padding:1em 0 0 i border-bottom - to one dawały
   biały pasek tła strony nad czarną belką kontaktową. */
#headerwrap { margin: 0; padding: 0; }
#header { padding: 0; border: 0; }
#footerwrap { margin: 0; padding: 0; }


/* =========================================================================
   04. NAGŁÓWEK
   Dwie warstwy: czarny pasek kontaktowy (jkb-topbar) i granatowa belka
   nawigacji (jkb-nav). Treść pochodzi z menu WP i Customizera, nie z HTML-a.
   ========================================================================= */

.jkb-topbar {
	background: var(--jkb-surface-bar);
	color: var(--jkb-text-on-inverse);
	font-size: var(--jkb-size-micro);
}
.jkb-topbar__inner {
	max-width: var(--jkb-container-max);
	margin: 0 auto;
	padding: var(--jkb-space-2) var(--jkb-space-5);
	display: flex;
	align-items: center;
	justify-content: center;
	gap: var(--jkb-space-5);
	flex-wrap: wrap;
}
.jkb-topbar__licence { color: var(--jkb-text-on-inverse); }
.jkb-topbar__tel {
	display: inline-flex;
	align-items: center;
	gap: var(--jkb-space-1);
	color: var(--jkb-gold-400);
	font-weight: var(--jkb-weight-bold);
}
.jkb-topbar__tel:hover { color: var(--jkb-gold-300); }

.jkb-nav {
	background: var(--jkb-surface-inverse);
	box-shadow: var(--jkb-shadow-header);
	position: relative;
	z-index: 3;
}
.jkb-nav__inner {
	max-width: var(--jkb-container-max);
	margin: 0 auto;
	padding: var(--jkb-space-3) var(--jkb-space-5);
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--jkb-space-6);
}
/* Logo wprost na granatowej belce, bez białej płytki.
   Płytka była potrzebna tylko przy złoto-granatowej wersji znaku, która
   zlewała się z tłem. Wariant z białymi akcentami (logo-jkb_white.webp)
   czyta się sam z siebie i na granacie, i na czarnym pasku - dlatego może
   teraz wychodzić w górę bez żadnego podkładu.

   Ujemne marginesy: górny podnosi znak na czarny pasek, dolny oddaje część
   jego wysokości układowi flex, żeby powiększone logo nie rozepchnęło belki.
   Wartości --jkb-logo-* muszą zgadzać się z progami w sekcji 17. */
.jkb-nav__logo {
	--jkb-logo-h: 128px;     /* wysokość znaku */
	--jkb-logo-rise: 34px;   /* ile wystaje ponad belkę, na czarny pasek */
	--jkb-logo-sink: 8px;    /* ile wysokości oddaje układowi */

	display: block;
	flex: 0 0 auto;
	position: relative;
	z-index: 4;              /* nad belką (z-index 3), żeby jej cień nie przyciemniał znaku */
	/* Do podniesienia dolicza się górny padding belki, bo od niego liczy się
	   pozycja logo - inaczej --jkb-logo-rise nie zgadzałoby się z tym,
	   co widać na ekranie. */
	margin-top: calc(-1 * (var(--jkb-logo-rise) + var(--jkb-space-3)));
	margin-bottom: calc(-1 * var(--jkb-logo-sink));
	transition: opacity var(--jkb-transition-base);
}
.jkb-nav__logo:hover { opacity: 0.85; }
.jkb-nav__logo img {
	height: var(--jkb-logo-h);
	width: auto;
	display: block;
}

.jkb-nav__menu {
	display: flex;
	align-items: center;
	gap: var(--jkb-space-5);
	margin: 0;
	padding: 0;
	list-style: none;
	font-size: var(--jkb-size-small);
	font-family: var(--jkb-font-display);
	font-weight: var(--jkb-weight-medium);
}
.jkb-nav__menu li { position: relative; margin: 0; }
.jkb-nav__menu a { color: var(--jkb-text-on-inverse); display: block; }
.jkb-nav__menu a:hover,
.jkb-nav__menu .current-menu-item > a,
.jkb-nav__menu .current_page_item > a,
.jkb-nav__menu .current-menu-ancestor > a {
	color: var(--jkb-gold-400);
}

/* Podmenu */
.jkb-nav__menu .sub-menu {
	position: absolute;
	top: 100%;
	left: 0;
	min-width: 210px;
	margin: 0;
	padding: var(--jkb-space-2) 0;
	list-style: none;
	background: var(--jkb-navy-700);
	border: var(--jkb-border-width) solid var(--jkb-border-on-inverse);
	border-radius: var(--jkb-radius-md);
	box-shadow: var(--jkb-shadow-header);
	opacity: 0;
	visibility: hidden;
	transform: translateY(6px);
	transition: opacity var(--jkb-transition-base), transform var(--jkb-transition-base), visibility var(--jkb-transition-base);
	z-index: 10;
}
.jkb-nav__menu li:hover > .sub-menu,
.jkb-nav__menu li:focus-within > .sub-menu {
	opacity: 1;
	visibility: visible;
	transform: translateY(0);
}
.jkb-nav__menu .sub-menu a { padding: var(--jkb-space-2) var(--jkb-space-4); }

.jkb-nav__cta { flex: 0 0 auto; }

/* Hamburger - widoczny dopiero w media query (sekcja 17) */
.jkb-nav__toggle {
	display: none;
	width: 44px;
	height: 44px;
	padding: 0;
	background: none;
	border: var(--jkb-border-width) solid var(--jkb-border-on-inverse);
	border-radius: var(--jkb-radius-sm);
	cursor: pointer;
	align-items: center;
	justify-content: center;
	color: var(--jkb-text-on-inverse);
}
.jkb-nav__toggle span,
.jkb-nav__toggle span::before,
.jkb-nav__toggle span::after {
	display: block;
	width: 20px;
	height: 2px;
	background: currentColor;
	transition: transform var(--jkb-transition-base), opacity var(--jkb-transition-fast);
}
.jkb-nav__toggle span { position: relative; }
.jkb-nav__toggle span::before,
.jkb-nav__toggle span::after {
	content: '';
	position: absolute;
	left: 0;
}
.jkb-nav__toggle span::before { top: -6px; }
.jkb-nav__toggle span::after  { top: 6px; }
.jkb-nav__toggle[aria-expanded="true"] span { background: transparent; }
.jkb-nav__toggle[aria-expanded="true"] span::before { transform: translateY(6px) rotate(45deg); }
.jkb-nav__toggle[aria-expanded="true"] span::after  { transform: translateY(-6px) rotate(-45deg); }


/* =========================================================================
   05. STOPKA
   Trzy kolumny z obszarów widgetów - redaktor edytuje w Wygląd > Widgety.
   ========================================================================= */

.jkb-footer {
	background: var(--jkb-surface-inverse-deep);
	color: var(--jkb-text-on-inverse);
	padding: var(--jkb-space-9) 0 0;
}
.jkb-footer__inner {
	max-width: var(--jkb-container-max);
	margin: 0 auto;
	padding: 0 var(--jkb-space-5);
}
.jkb-footer__cols {
	display: grid;
	grid-template-columns: 1.2fr 1fr 1fr;
	gap: var(--jkb-space-7);
}
/* Logo w stopce bez płytki - tak jak w nagłówku, wariant z białymi akcentami
   czyta się na granacie sam z siebie. Span zostaje w markupie jako uchwyt
   na odstęp; gdyby kiedyś wróciła płytka, jest gdzie ją podpiąć. */
.jkb-footer__logo-plate {
	display: inline-block;
	margin-bottom: var(--jkb-space-4);
}
.jkb-footer__logo { height: 200px; width: auto; display: block; }

.jkb-footer .widget { margin: 0; }
.jkb-footer .widgettitle,
.jkb-footer h4 {
	margin: 0 0 var(--jkb-space-4);
	font-family: var(--jkb-font-display);
	font-size: var(--jkb-size-caption);
	font-weight: var(--jkb-weight-bold);
	letter-spacing: var(--jkb-tracking-caps);
	text-transform: uppercase;
	color: var(--jkb-text-on-inverse);
}
.jkb-footer ul {
	margin: 0;
	padding: 0;
	list-style: none;
	display: flex;
	flex-direction: column;
	gap: var(--jkb-space-2);
	font-size: var(--jkb-size-small);
	color: var(--jkb-text-on-inverse-muted);
}
.jkb-footer li { margin: 0; }
.jkb-footer a { color: var(--jkb-text-on-inverse-muted); }
.jkb-footer a:hover { color: var(--jkb-gold-400); }
.jkb-footer p { color: var(--jkb-text-on-inverse-muted); font-size: var(--jkb-size-small); }

.jkb-footer__bottom {
	margin-top: var(--jkb-space-8);
	border-top: var(--jkb-border-width) solid rgba(255, 255, 255, 0.12);
	padding: var(--jkb-space-4) 0;
	font-size: var(--jkb-size-micro);
	color: rgba(255, 255, 255, 0.55);
	display: flex;
	justify-content: space-between;
	gap: var(--jkb-space-5);
	flex-wrap: wrap;
}
.jkb-footer__bottom ul {
	flex-direction: row;
	gap: var(--jkb-space-4);
	font-size: var(--jkb-size-micro);
}


/* =========================================================================
   06. WARSTWA TREŚCI BUILDERA
   Klasy, które redaktor wpisuje w pole "CSS Class" wiersza lub modułu.
   Stylujemy po znacznikach w środku, żeby treść w module Text była zwykłym
   tekstem - taki HTML przeżywa czyszczenie przez TinyMCE przy zapisie strony.
   ========================================================================= */

/* --- Sekcja: pionowy oddech --- */
.jkb-sec { padding-top: var(--jkb-section-padding-y); padding-bottom: var(--jkb-section-padding-y); }
.jkb-sec--tight { padding-top: var(--jkb-space-7); padding-bottom: var(--jkb-space-7); }
.jkb-sec--flush-top { padding-top: 0; }

/* --- Sekcja: tło --- */
.jkb-bg-grey { background: var(--jkb-surface-section); }
.jkb-bg-navy { background: var(--jkb-surface-inverse); }
.jkb-bg-navy-deep { background: var(--jkb-surface-inverse-deep); }

/* --- Nagłówek sekcji: h2 w module Text dostaje wygląd z projektu --- */
.jkb-title h1,
.jkb-title h2,
.jkb-title h3 {
	margin: 0;
	font-family: var(--jkb-font-display);
	font-size: var(--jkb-size-h2);
	font-weight: var(--jkb-weight-bold);
	letter-spacing: var(--jkb-tracking-caps);
	text-transform: uppercase;
	color: var(--jkb-text-heading);
	text-align: center;
}
/* Złota kreska pod tytułem - pseudoelement, żeby redaktor nie musiał
   wstawiać pustego diva, który i tak zniknąłby przy zapisie strony. */
.jkb-title::after {
	content: '';
	display: block;
	width: 64px;
	height: var(--jkb-border-width-accent);
	background: var(--jkb-rule-accent);
	margin: var(--jkb-space-4) auto 0;
}

/* Wariant na ciemnym tle */
.jkb-title--inverse h1,
.jkb-title--inverse h2,
.jkb-title--inverse h3 { color: var(--jkb-text-on-inverse); }

/* --- Akapit wprowadzający pod tytułem --- */
.jkb-lead {
	max-width: 620px;
	margin-left: auto;
	margin-right: auto;
	text-align: center;
	text-wrap: pretty;
}
.jkb-lead p { margin: 0; }
.jkb-lead--inverse p { color: var(--jkb-text-on-inverse-muted); }

/* --- Tekst na ciemnym tle (ogólny) --- */
.jkb-inverse,
.jkb-inverse p,
.jkb-inverse li { color: var(--jkb-text-on-inverse-muted); }
.jkb-inverse h1,
.jkb-inverse h2,
.jkb-inverse h3,
.jkb-inverse h4 { color: var(--jkb-text-on-inverse); }

/* --- Odstępy pomocnicze --- */
.jkb-gap-sm { margin-top: var(--jkb-space-4); }
.jkb-gap-md { margin-top: var(--jkb-space-7); }
.jkb-gap-lg { margin-top: var(--jkb-space-9); }

/* --- Moduł Text a układ karty ---
   Moduł Text zawija treść w <div class="tb_text_wrap">. Bez obejścia
   display:flex na karcie układałby JEDEN element (właśnie ten wrapper),
   a nie ikonę, nagłówek i listę - gap i wyrównanie nie miałyby na co działać.
   display:contents wypina wrapper z układu i jego dzieci stają się
   bezpośrednimi elementami flex karty.
   UWAGA: to zmienia tylko LAYOUT, nie dopasowanie selektorów - w drzewie DOM
   p/h3/ul nadal są dziećmi wrappera. Dlatego reguły kart niżej używają
   :first-of-type / :nth-last-of-type, a nie :first-child. */
.jkb-svc > .tb_text_wrap,
.jkb-step > .tb_text_wrap,
.jkb-op > .tb_text_wrap,
.jkb-tile > .tb_text_wrap,
.jkb-hero__meta > .tb_text_wrap { display: contents; }

/* --- Karta: wspólna podstawa dla usług, kroków, ofert i opinii --- */
.jkb-card {
	background: var(--jkb-surface-card);
	border: var(--jkb-border-width) solid var(--jkb-border-card);
	border-radius: var(--jkb-radius-md);
	box-shadow: var(--jkb-shadow-card);
	transition: box-shadow var(--jkb-transition-base), transform var(--jkb-transition-base);
	height: 100%;
}
.jkb-card:hover {
	box-shadow: var(--jkb-shadow-card-hover);
	transform: var(--jkb-hover-lift);
}

/* Karta na pełną wysokość rzędu, żeby sąsiadujące karty kończyły się równo
   mimo różnej długości tekstu.

   Kolumna Buildera to grid, ale dziedziczy z wiersza align-content:start
   (klasa .col_align_top). Przy align-content:start ścieżka siatki ma wysokość
   treści, więc height:100% na module nie ma czego wypełnić - dlatego najpierw
   przestawiamy align-content na stretch. Selektor musi zawierać .module_column,
   bo rodzic ustawia te własności regułą div.module_column (0,1,1). */
.module_column.jkb-stretch { align-content: stretch; }
.module_column.jkb-stretch > .module { height: 100%; margin-bottom: 0; }


/* =========================================================================
   07. PRZYCISKI I BADGE

   Moduł Buttons renderuje <a class="ui builder_button tf_in_flx"> w kontenerze
   .module.module-buttons.jkb-btns. Themify styluje ten link regułą
   .module.module-buttons .ui (0,3,0) - dlatego nasze selektory startują od
   .module.module-buttons.jkb-btns (0,3,0 + element = 0,4,0). Bez tego kolor
   tekstu przycisku brałby się z --tb_pr_color, a nie z naszych tokenów.
   Klasa .jkb-btn to ten sam przycisk poza Builderem (karty ofert, nagłówek).
   ========================================================================= */

.module.module-buttons.jkb-btns .builder_button,
.jkb-btn {
	display: inline-flex;
	align-items: center;
	gap: var(--jkb-space-2);
	font-family: var(--jkb-font-display);
	font-weight: var(--jkb-weight-semibold);
	font-size: var(--jkb-size-small);
	letter-spacing: var(--jkb-tracking-button);
	text-transform: uppercase;
	padding: 12px 22px;
	border-radius: var(--jkb-radius-sm);
	border: var(--jkb-border-width) solid transparent;
	line-height: 1.35;
	cursor: pointer;
	text-decoration: none;
	transition: background-color var(--jkb-transition-base), color var(--jkb-transition-base), border-color var(--jkb-transition-base);
}

/* Główny: złoty gradient, granatowy tekst.
   background-image obok background-color: kolor zostaje podkładem, więc
   przycisk jest złoty także tam, gdzie gradient nie wejdzie.

   !important jest tu konieczny i dotyczy WYŁĄCZNIE przycisków modułu Buttons.
   Themify ładuje plugins/fake.css z regułą:
       .module[data-lazy] .ui { background-image: none !important }
   To część leniwego ładowania - ma powstrzymać pobieranie teł url() zanim
   moduł wjedzie w widok. Atrybut data-lazy zostaje na module NA STAŁE (nie
   znika po odsłonięciu), więc bez !important gradient nigdy by się nie pokazał.
   Nasz gradient nie pobiera niczego z sieci, więc nadpisanie tej reguły nie
   psuje mechanizmu, dla którego powstała.
   Przyciski .jkb-btn (karty ofert, nagłówek) nie mają klasy .ui i tej reguły
   nie łapią - dlatego mają własny blok bez !important. */
.module.module-buttons.jkb-btns--primary .builder_button {
	background-color: var(--jkb-action-primary-bg);
	background-image: var(--jkb-action-primary-gradient) !important;
	background-size: 100% 100%;
	background-position: center;
	color: var(--jkb-action-primary-fg);
	border-color: var(--jkb-action-primary-border);
	transition:
		background-size var(--jkb-transition-base),
		border-color var(--jkb-transition-base),
		color var(--jkb-transition-base);
}

/* Ten sam przycisk poza Builderem - bez !important, bo nie ma czego nadpisywać. */
.jkb-btn--primary {
	background-color: var(--jkb-action-primary-bg);
	background-image: var(--jkb-action-primary-gradient);
	background-size: 100% 100%;
	background-position: center;
	color: var(--jkb-action-primary-fg);
	border-color: var(--jkb-action-primary-border);
	transition:
		background-size var(--jkb-transition-base),
		border-color var(--jkb-transition-base),
		color var(--jkb-transition-base);
}

/* W spoczynku background-size to 100%, czyli przycisk wygląda dokładnie tak,
   jak gradient uzgodniony z klientem. Hover powiększa tło, więc w kadrze
   przycisku zostaje głównie jasna smuga ze środka gradientu i przycisk się
   rozświetla. background-size animuje się płynnie, w przeciwieństwie do
   background-image - dlatego rozjaśniamy skalą, a nie podmianą gradientu. */
.module.module-buttons.jkb-btns--primary .builder_button:hover,
.jkb-btn--primary:hover {
	background-size: 165% 165%;
	border-color: var(--jkb-btn-gold-mid);
	color: var(--jkb-action-primary-fg);
}

/* --- Przyciski obrysowane: wypełnienie gradientem na hover ---
   Gradient jest podpięty JUŻ W SPOCZYNKU, tylko o zerowej wysokości
   (background-size: 100% 0%) i zakotwiczony przy dolnej krawędzi. Hover
   rozciąga go do pełnej wysokości, więc złoto wjeżdża od dołu płynnie.

   Dlaczego tak, a nie po prostu background-image na :hover: obrazy tła
   NIE interpolują się między stanami, więc gradient pojawiałby się skokiem.
   Wcześniej wypełnienie było płaskim kolorem i ładnie się wtapiało -
   ta konstrukcja zachowuje tę płynność i dokłada gradient.

   !important z tego samego powodu co przy przycisku głównym: Themify ładuje
   regułę .module[data-lazy] .ui { background-image: none !important }. */
.module.module-buttons.jkb-btns--secondary .builder_button,
.jkb-btn--secondary,
.module.module-buttons.jkb-btns--secondary-dark .builder_button,
.jkb-btn--secondary-dark {
	background-color: transparent;
	background-image: var(--jkb-action-primary-gradient) !important;
	background-repeat: no-repeat;
	background-position: 50% 100%;
	background-size: 100% 0%;
	transition:
		background-size var(--jkb-transition-base),
		color var(--jkb-transition-base),
		border-color var(--jkb-transition-base);
}
.module.module-buttons.jkb-btns--secondary .builder_button:hover,
.jkb-btn--secondary:hover,
.module.module-buttons.jkb-btns--secondary-dark .builder_button:hover,
.jkb-btn--secondary-dark:hover {
	background-size: 100% 100%;
	/* Granat, nie biel: gradient jest jasny, więc biały napis by na nim zniknął. */
	color: var(--jkb-action-primary-fg);
	border-color: var(--jkb-btn-gold-dark);
}

/* Kolory obrysu w spoczynku - na ciemnym tle jaśniejsze złoto, na jasnym ciemniejsze */
.module.module-buttons.jkb-btns--secondary .builder_button,
.jkb-btn--secondary {
	color: var(--jkb-action-secondary-fg);
	border-color: var(--jkb-action-secondary-border);
}
/* Wariant na jasnym tle: obrys złoty, ale NAPIS GRANATOWY.
   Złoto gold-600 na bieli daje kontrast 3,26:1 przy wymaganych 4,5:1 - napis
   robi się nieczytelny, zwłaszcza że jest mały i w wersalikach. Granat daje
   ~15:1 i jest tym samym kolorem, co nagłówki sekcji, więc przycisk nadal
   należy do systemu. Złoto zostaje na obrysie, gdzie kontrast nie decyduje
   o czytelności treści.
   Po najechaniu tło wypełnia się gradientem, a napis i tak jest granatowy -
   stan spoczynku i hover mają teraz ten sam kolor tekstu. */
.module.module-buttons.jkb-btns--secondary-dark .builder_button,
.jkb-btn--secondary-dark {
	color: var(--jkb-text-heading);
	border-color: var(--jkb-gold-600);
}

/* Rozmiary */
.module.module-buttons.jkb-btns--sm .builder_button,
.jkb-btn--sm { padding: 8px 16px; font-size: var(--jkb-size-micro); }
.module.module-buttons.jkb-btns--lg .builder_button,
.jkb-btn--lg { padding: 15px 28px; font-size: var(--jkb-size-body); }

/* Rozstaw przycisków w grupie.
   Themify daje .module-buttons-item + .module-buttons-item margin-inline-start,
   więc zerujemy go i odstęp robimy gapem na kontenerze - inaczej dwie reguły
   o tej samej specyficzności zależałyby od kolejności w concate.css. */
.module.module-buttons.jkb-btns {
	display: flex;
	flex-wrap: wrap;
	gap: var(--jkb-space-4);
}
.module.module-buttons.jkb-btns .module-buttons-item,
.module.module-buttons.jkb-btns .module-buttons-item + .module-buttons-item {
	margin: 0;
	margin-inline-start: 0;
	padding: 0;
}
.module.module-buttons.jkb-btns--center { justify-content: center; }

/* Badge statusu oferty */
.jkb-badge {
	display: inline-block;
	font-family: var(--jkb-font-display);
	font-size: var(--jkb-size-micro);
	font-weight: var(--jkb-weight-bold);
	letter-spacing: var(--jkb-tracking-caps);
	text-transform: uppercase;
	padding: 6px 12px;
	border-radius: var(--jkb-radius-sm);
	line-height: 1;
}
.jkb-badge--sale { background: var(--jkb-navy-800); color: var(--jkb-white); }
.jkb-badge--rent { background: var(--jkb-gold-500); color: var(--jkb-navy-900); }


/* =========================================================================
   08. SEKCJA: HERO
   Wiersz Buildera z tłem-zdjęciem. Gradient kładziemy pseudoelementem,
   żeby redaktor mógł podmienić zdjęcie w panelu bez ruszania stylów.
   ========================================================================= */

.jkb-hero {
	position: relative;
	min-height: 520px;
	display: flex;
	align-items: center;
	overflow: hidden;
	background-color: var(--jkb-navy-900);
}
.jkb-hero::before {
	content: '';
	position: absolute;
	inset: 0;
	background: var(--jkb-overlay-hero);
	z-index: 1;
	pointer-events: none;
}
.jkb-hero > .row_inner { position: relative; z-index: 2; }

.jkb-hero__title h1,
.jkb-hero__title h2 {
	margin: 0;
	font-family: var(--jkb-font-display);
	font-size: var(--jkb-size-hero);
	font-weight: var(--jkb-weight-bold);
	line-height: var(--jkb-leading-tight);
	color: var(--jkb-text-on-inverse);
	max-width: 760px;
	text-align: left;
	text-transform: none;
	letter-spacing: var(--jkb-tracking-heading);
}
/* Wiersz nagłówka na złoto - redaktor zawija go w <em>, bo to jedyny
   znacznik inline, którego TinyMCE nie rozwija przy zapisie strony.
   Każdy <em> jest blokiem, więc staje się osobną linią; można ich użyć
   kilka i wyróżnić dowolne wiersze nagłówka. */
.jkb-hero__title em {
	color: var(--jkb-text-accent-on-inverse);
	display: block;
	font-style: normal;
}

.jkb-hero__meta p {
	margin: 0;
	color: var(--jkb-text-on-inverse);
	font-size: var(--jkb-size-body);
	display: flex;
	align-items: center;
	gap: var(--jkb-space-2);
	flex-wrap: wrap;
}
.jkb-hero__meta a { color: var(--jkb-text-on-inverse); }
.jkb-hero__meta a:hover { color: var(--jkb-gold-400); }


/* =========================================================================
   09. SEKCJA: O NAS
   Zdjęcie + opis obok siebie. Moduł Image w kolumnie, Text w drugiej.
   ========================================================================= */

/* Kolumna z tą klasą układa zdjęcie i opis w rzędzie.
   Selektor MUSI zawierać .module_column: Builder ustawia display:grid regułą
   div.module_column (0,1,1), która przebiłaby samą klasę (0,1,0). */
.module_column.jkb-person {
	display: flex;
	gap: var(--jkb-space-5);
	align-items: flex-start;
}

/* Portret pośrednika: kadr 190x250 z delikatnym cieniem.
   Wymiary siedzą na .image-wrap (wrapper modułu Image), a nie na samym <img>.
   To ta różnica pozwala zdjęciu powiększać się po najechaniu wewnątrz stałej
   ramki: wrapper przycina nadmiar, więc sąsiedni tekst nie drgnie.
   Rozmiar musi zgadzać się z add_image_size('jkb-person') w inc/setup.php -
   tam jest jego dwukrotność. */
.jkb-person__photo .image-wrap {
	width: 190px;
	height: 250px;
	overflow: hidden;
	border-radius: var(--jkb-radius-sm);
	background: var(--jkb-grey-300);
	box-shadow: 0 4px 14px rgba(7, 21, 40, 0.14);
	transition:
		box-shadow var(--jkb-transition-base),
		transform var(--jkb-transition-base);
}
.jkb-person__photo img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: top center;
	display: block;
	transition: transform var(--jkb-transition-slow);
}

/* Najechanie: zdjęcie lekko się przybliża, kadr unosi się i pogłębia cień.
   Hover łapiemy na całym module, żeby działał też na marginesie wokół kadru. */
.jkb-person__photo:hover .image-wrap {
	transform: translateY(-3px);
	box-shadow: 0 10px 26px rgba(7, 21, 40, 0.22);
}
.jkb-person__photo:hover img { transform: scale(1.06); }

.jkb-person__body h3,
.jkb-person__body h4 {
	margin: 0 0 var(--jkb-space-1);
	font-family: var(--jkb-font-display);
	font-size: var(--jkb-size-h4);
	font-weight: var(--jkb-weight-bold);
	letter-spacing: var(--jkb-tracking-caps);
	text-transform: uppercase;
	color: var(--jkb-text-heading);
}

/* Opis rozciąga się na całą wysokość kolumny, żeby margin-top:auto na linii
   z telefonem zepchnęło ją do dołu - numery obu pośredników wyrównują się
   wtedy w jednym rzędzie, mimo różnej długości opisów.
   display:contents na wrapperze, bo moduł Text owija treść w .tb_text_wrap
   i bez tego akapity nie byłyby dziećmi kontenera flex. */
.module_column.jkb-person > .jkb-person__body {
	display: flex;
	flex-direction: column;
}
.jkb-person__body > .tb_text_wrap { display: contents; }
/* Rola: kursywa na złoto. Redaktor pisze ją jako <em> pod nagłówkiem. */
.jkb-person__body h3 + p em,
.jkb-person__body h4 + p em {
	display: block;
	font-size: var(--jkb-size-caption);
	color: var(--jkb-text-accent);
	font-style: italic;
	margin-bottom: var(--jkb-space-3);
}
.jkb-person__body p {
	margin: 0;
	font-size: var(--jkb-size-small);
	text-wrap: pretty;
}

/* Telefon pośrednika - wstawiany shortcode'em [jkb_osoba_tel numer="..."].
   Osobna linia pod opisem, bo to najczęściej klikany element tej sekcji:
   ma być łatwy do znalezienia wzrokiem i wygodny do trafienia kciukiem.
   Wysokość 44px to minimalny cel dotykowy z wytycznych dostępności. */
.jkb-person__tel {
	display: block;
	margin-top: auto;
	padding-top: var(--jkb-space-4);
}
.jkb-person__tel-label {
	display: block;
	font-size: var(--jkb-size-micro);
	letter-spacing: var(--jkb-tracking-caps);
	text-transform: uppercase;
	color: var(--jkb-text-muted);
	margin-bottom: 2px;
}
.jkb-person__tel a {
	display: inline-flex;
	align-items: center;
	gap: var(--jkb-space-2);
	min-height: 44px;
	font-family: var(--jkb-font-display);
	font-size: var(--jkb-size-h4);
	font-weight: var(--jkb-weight-bold);
	color: var(--jkb-text-heading);
	/* Numer nie ma sensu łamany w połowie. */
	white-space: nowrap;
}
.jkb-person__tel a:hover { color: var(--jkb-text-accent); }
.jkb-person__tel .jkb-icon { color: var(--jkb-text-accent); }


/* =========================================================================
   10. SEKCJA: USŁUGI
   Karta: ikona, nagłówek, lista punktów. Wszystko w module Text.
   ========================================================================= */

.jkb-svc {
	padding: var(--jkb-space-6) var(--jkb-space-5);
	text-align: center;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: var(--jkb-space-4);
}
.jkb-svc .jkb-icon { color: var(--jkb-gold-500); }
.jkb-svc h3,
.jkb-svc h4 {
	margin: 0;
	font-family: var(--jkb-font-display);
	font-size: var(--jkb-size-h4);
	font-weight: var(--jkb-weight-bold);
	letter-spacing: var(--jkb-tracking-caps);
	text-transform: uppercase;
	color: var(--jkb-text-heading);
}
/* Lista punktów usługi: wiersze rozdzielone cienką linią zamiast myślników.
   Myślnik przed wyśrodkowanym tekstem wyglądał na niedokończony wypunktowanie -
   linia daje ten sam rytm, ale czyta się jak tabela, a nie jak lista z brakiem.

   width:100% jest potrzebne, bo karta to kolumna flex z align-items:center -
   bez tego <ul> skurczyłby się do najdłuższego wiersza i podkreślenia
   miałyby różną długość w każdej karcie. */
.jkb-svc ul {
	margin: 0;
	padding: 0;
	list-style: none;
	width: 100%;
	font-size: var(--jkb-size-body);
	/* Ciemniejszy niż złoto akcentu: to treść do czytania, a złoto na białej
	   karcie daje kontrast ok. 3:1 i punkty się gubiły. */
	color: var(--jkb-text-body);
}
.jkb-svc li {
	margin: 0;
	padding: var(--jkb-space-2) 0;
	border-bottom: var(--jkb-border-width) solid var(--jkb-border-card);
}
/* Ostatni wiersz bez linii - inaczej karta kończyłaby się kreską wiszącą
   nad pustym miejscem. */
.jkb-svc li:last-child { border-bottom: 0; padding-bottom: 0; }
.jkb-svc p { margin: 0; }


/* =========================================================================
   11. SEKCJA: DLACZEGO JKB (kafelki)
   Pięć kafelków w rzędzie na granacie.
   ========================================================================= */

.jkb-tile {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: var(--jkb-space-3);
	text-align: center;
	padding: var(--jkb-space-5) var(--jkb-space-4);
	min-height: 130px;
	height: 100%;
	background: var(--jkb-surface-tile-inverse);
	border: var(--jkb-border-width) solid var(--jkb-border-on-inverse);
	border-radius: var(--jkb-radius-md);
	transition: background-color var(--jkb-transition-base);
}
.jkb-tile:hover { background: rgba(199, 169, 98, 0.10); }
.jkb-tile .jkb-icon { color: var(--jkb-gold-400); }
.jkb-tile p,
.jkb-tile h4 {
	margin: 0;
	font-family: var(--jkb-font-display);
	font-size: var(--jkb-size-caption);
	font-weight: var(--jkb-weight-semibold);
	letter-spacing: var(--jkb-tracking-caps);
	text-transform: uppercase;
	color: var(--jkb-text-on-inverse);
}


/* =========================================================================
   12. SEKCJA: PROCES (kroki 01-04)
   ========================================================================= */

.jkb-step {
	padding: var(--jkb-space-6);
	display: flex;
	flex-direction: column;
	gap: var(--jkb-space-3);
}
/* Numer kroku: redaktor pisze go jako pierwszy akapit "01".
   Kreska pod numerem to pseudoelement, nie pusty div.
   :first-of-type, nie :first-child - akapit siedzi w .tb_text_wrap modułu. */
.jkb-step p:first-of-type {
	font-family: var(--jkb-font-display);
	font-size: var(--jkb-size-numeral);
	font-weight: var(--jkb-weight-bold);
	line-height: 1;
	color: var(--jkb-navy-800);
	margin: 0;
}
.jkb-step p:first-of-type::after {
	content: '';
	display: block;
	width: 40px;
	height: var(--jkb-border-width-accent);
	background: var(--jkb-rule-accent);
	margin-top: var(--jkb-space-3);
}
.jkb-step h3,
.jkb-step h4 {
	margin: 0;
	font-family: var(--jkb-font-display);
	font-size: var(--jkb-size-h4);
	font-weight: var(--jkb-weight-bold);
	letter-spacing: var(--jkb-tracking-caps);
	text-transform: uppercase;
	color: var(--jkb-text-heading);
}
.jkb-step p { margin: 0; font-size: var(--jkb-size-small); }


/* =========================================================================
   13. SEKCJA: NIERUCHOMOŚCI (karty ofert)
   Karty generuje shortcode [jkb_oferty] z CPT "nieruchomosc" - markup jest
   w PHP, więc redaktor edytuje ofertę w kokpicie, a nie w module Text.
   ========================================================================= */

/* Podtytuł grupy ofert ("Na sprzedaż" / "Na wynajem") */
.jkb-sub,
.jkb-oferty__group-title {
	font-family: var(--jkb-font-display);
	font-size: var(--jkb-size-h4);
	font-weight: var(--jkb-weight-bold);
	letter-spacing: var(--jkb-tracking-caps);
	text-transform: uppercase;
	color: var(--jkb-text-heading);
	margin: var(--jkb-space-8) 0 var(--jkb-space-4);
}
.jkb-oferty__group:first-child .jkb-oferty__group-title { margin-top: var(--jkb-space-7); }

.jkb-oferty__grid {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: var(--jkb-grid-gap);
}
.jkb-oferty__grid--3 { grid-template-columns: repeat(3, 1fr); }

.jkb-prop {
	overflow: hidden;
	display: flex;
	flex-direction: column;
	background: var(--jkb-surface-card);
	border: var(--jkb-border-width) solid var(--jkb-border-card);
	border-radius: var(--jkb-radius-md);
	box-shadow: var(--jkb-shadow-card);
	transition: box-shadow var(--jkb-transition-base), transform var(--jkb-transition-base);
}
.jkb-prop:hover {
	box-shadow: var(--jkb-shadow-card-hover);
	transform: var(--jkb-hover-lift);
}

.jkb-prop__img {
	position: relative;
	aspect-ratio: 3 / 2;
	background: var(--jkb-grey-200);
	overflow: hidden;
}
.jkb-prop__img img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
	transition: transform var(--jkb-transition-slow);
}
.jkb-prop:hover .jkb-prop__img img { transform: scale(1.03); }

/* Zastępnik, gdy oferta nie ma jeszcze zdjęcia */
.jkb-prop__img--empty {
	display: grid;
	place-items: center;
	color: var(--jkb-grey-500);
}

.jkb-prop__badge { position: absolute; top: 12px; left: 12px; z-index: 2; }

.jkb-prop__body {
	padding: var(--jkb-space-5);
	display: flex;
	flex-direction: column;
	gap: var(--jkb-space-3);
	align-items: flex-start;
	flex: 1 1 auto;
}
.jkb-prop__price {
	font-family: var(--jkb-font-display);
	font-size: var(--jkb-size-h3);
	font-weight: var(--jkb-weight-bold);
	color: var(--jkb-text-heading);
	line-height: 1.1;
}
.jkb-prop__title {
	font-size: var(--jkb-size-small);
	font-weight: var(--jkb-weight-bold);
	color: var(--jkb-text-heading);
	margin: 0;
}
.jkb-prop__title a { color: inherit; }
.jkb-prop__title a:hover { color: var(--jkb-gold-600); }

.jkb-prop__meta {
	display: flex;
	flex-wrap: wrap;
	gap: var(--jkb-space-4);
	font-size: var(--jkb-size-caption);
	color: var(--jkb-text-muted);
}
.jkb-prop__meta span {
	display: inline-flex;
	align-items: center;
	gap: var(--jkb-space-1);
}
.jkb-prop__cta { margin-top: auto; }

/* Odnośnik do pełnej listy pod grupą ofert - wyśrodkowany pod siatką kart,
   żeby czytał się jako domknięcie całej grupy, a nie przypis do pierwszej karty. */
.jkb-oferty__more {
	margin-top: var(--jkb-space-6);
	display: flex;
	justify-content: center;
}

/* Komunikat, gdy nie ma jeszcze żadnej oferty */
.jkb-oferty__empty {
	padding: var(--jkb-space-7);
	text-align: center;
	color: var(--jkb-text-muted);
	border: var(--jkb-border-width) dashed var(--jkb-border-subtle);
	border-radius: var(--jkb-radius-md);
}


/* =========================================================================
   14. SEKCJA: OPINIE
   ========================================================================= */

.jkb-op {
	padding: var(--jkb-space-5);
	display: flex;
	flex-direction: column;
	gap: var(--jkb-space-3);
}
.jkb-op p {
	margin: 0;
	font-style: italic;
	font-size: var(--jkb-size-small);
	color: var(--jkb-text-heading);
	text-wrap: pretty;
}
/* Autor i kontekst: dwa ostatnie akapity karty.
   -of-type, nie -child: akapity siedzą w .tb_text_wrap modułu Text. */
.jkb-op p:nth-last-of-type(2) {
	font-family: var(--jkb-font-display);
	font-size: var(--jkb-size-caption);
	font-weight: var(--jkb-weight-semibold);
	color: var(--jkb-text-heading);
	font-style: normal;
	margin-top: auto;
}
.jkb-op p:last-of-type {
	font-size: var(--jkb-size-micro);
	color: var(--jkb-text-muted);
	font-style: normal;
}
.jkb-stars {
	display: inline-flex;
	gap: 2px;
	color: var(--jkb-star);
}


/* =========================================================================
   15. SEKCJA: KONTAKT
   ========================================================================= */

/* Panel jest kolumną flex, a nie zwykłym blokiem, i to celowo.
   WordPress (shortcode_unautop) zdejmuje <p> z akapitu, w którym stoi sam
   shortcode - telefon i numer licencji trafiają do panelu jako goły <a>
   i goły tekst, bez własnych akapitów. W kolumnie flex każdy z nich staje się
   osobnym elementem (tekst jako anonimowy element flex), więc linie nie
   zlewają się w jedną niezależnie od tego, co wpautop zrobi z treścią. */
.jkb-panel {
	/* width, nie max-width: moduł jest elementem CSS Grid kolumny, a tam
	   margin-inline:auto zmienia rozciągnięty element w shrink-to-fit -
	   panel skurczyłby się do szerokości najdłuższej linii tekstu. */
	width: min(560px, 100%);
	margin: var(--jkb-space-7) auto 0;
	background: rgba(255, 255, 255, 0.06);
	border: var(--jkb-border-width) solid var(--jkb-border-on-inverse);
	border-radius: var(--jkb-radius-md);
	padding: var(--jkb-space-6);
	text-align: center;
	color: var(--jkb-text-on-inverse);
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: var(--jkb-space-3);
	font-size: var(--jkb-size-small);
}
.jkb-panel > .tb_text_wrap { display: contents; }
.jkb-panel p { margin: 0; font-size: var(--jkb-size-small); color: rgba(255, 255, 255, 0.78); }
.jkb-panel__tel {
	font-family: var(--jkb-font-display);
	font-size: var(--jkb-size-h3);
	font-weight: var(--jkb-weight-bold);
	color: var(--jkb-gold-400);
	display: inline-flex;
	align-items: center;
	gap: var(--jkb-space-2);
}
.jkb-panel__tel:hover { color: var(--jkb-gold-300); }


/* =========================================================================
   16. IKONY SVG
   Zestaw z makiety, wstawiany shortcodem [jkb_icon]. Kolor dziedziczy
   z rodzica przez currentColor, więc jedna ikona działa na każdym tle.
   ========================================================================= */

.jkb-icon {
	display: inline-block;
	flex: 0 0 auto;
	width: 1em;
	height: 1em;
	vertical-align: -0.125em;
	color: inherit;
}
.jkb-icon svg {
	width: 100%;
	height: 100%;
	display: block;
	stroke: currentColor;
	fill: none;
}


/* =========================================================================
   17. RESPONSYWNOŚĆ
   Progi zgodne z domyślnymi Themify (Theme Settings > Responsive Design):
   mobile <=600px, tablet 601-768px, tablet landscape 769-1024px.
   Jeśli klient zmieni je w panelu, trzeba poprawić też te media query.
   ========================================================================= */

/* --- Tablet poziomy i mniej --- */
@media screen and (max-width: 1024px) {
	:root {
		--jkb-size-hero: 40px;
		--jkb-size-h1: 32px;
		--jkb-size-h2: 26px;
		--jkb-size-numeral: 44px;
		--jkb-section-padding-y: var(--jkb-space-8);
	}

	.jkb-nav__inner { gap: var(--jkb-space-4); }
	.jkb-nav__menu { gap: var(--jkb-space-4); }

	/* Płytka logo zmniejsza się razem z belką: mniejszy znak potrzebuje
	   węższego marginesu i płycej wchodzi na czarny pasek. */
	.jkb-nav__logo {
		--jkb-logo-h: 96px;
		--jkb-logo-rise: 24px;
		--jkb-logo-sink: 8px;
	}

	.jkb-footer__cols { grid-template-columns: 1fr 1fr; }

	/* Zdjęcie pośrednika nad opisem, nie obok.
	   Kolumna osoby to połowa szerokości wiersza: poniżej mniej więcej
	   1000px robi się węższa niż 440px, a że sam kadr zajmuje 190px, na
	   opis zostaje niecałe 200px i tekst łamie się po dwa słowa w linii.
	   Ustawienie w pionie zdejmuje ten konflikt - kadr i opis dostają
	   wtedy pełną szerokość kolumny.
	   Selektor MUSI zawierać .module_column, patrz komentarz w sekcji 09. */
	.module_column.jkb-person {
		flex-direction: column;
		gap: var(--jkb-space-4);
	}
}

/* --- Tablet pionowy i mniej: menu chowa się pod hamburger --- */
@media screen and (max-width: 768px) {
	.jkb-nav__toggle { display: inline-flex; }

	.jkb-nav__menu {
		position: absolute;
		top: 100%;
		left: 0;
		right: 0;
		flex-direction: column;
		align-items: stretch;
		gap: 0;
		background: var(--jkb-navy-700);
		border-top: var(--jkb-border-width) solid var(--jkb-border-on-inverse);
		box-shadow: var(--jkb-shadow-header);
		padding: var(--jkb-space-2) 0;
		display: none;
	}
	.jkb-nav__menu.is-open { display: flex; }
	.jkb-nav__menu > li > a { padding: var(--jkb-space-3) var(--jkb-space-5); }

	/* Podmenu na dotyku rozwija się w pionie, bez hovera */
	.jkb-nav__menu .sub-menu {
		position: static;
		opacity: 1;
		visibility: visible;
		transform: none;
		border: 0;
		box-shadow: none;
		background: rgba(0, 0, 0, 0.18);
		border-radius: 0;
		padding: 0;
	}
	.jkb-nav__menu .sub-menu a { padding-left: var(--jkb-space-8); }

	.jkb-nav__cta { display: none; }

	.jkb-hero { min-height: 420px; }
	.jkb-hero__title h1,
	.jkb-hero__title h2 { max-width: none; }

	.jkb-oferty__grid,
	.jkb-oferty__grid--3 { grid-template-columns: 1fr; }

	/* --- Zawijanie kolumn wierszy Buildera ---
	   Themify układa kolumny wiersza przez grid-template-areas: var(--area),
	   a domyślne --area ("col1 col2 col3 col4") trzyma je w jednym rzędzie
	   niezależnie od szerokości ekranu. Zawijanie ustawia się osobno w panelu
	   KAŻDEGO wiersza, więc łatwo o nim zapomnieć przy dodawaniu nowej sekcji
	   - i wtedy cztery karty ściskają się do 130px, a nagłówki wychodzą poza
	   kolumnę. Przedefiniowanie --area dla naszych wierszy .jkb-grid załatwia
	   to raz, dla wszystkich - i korzysta z własnego mechanizmu Themify,
	   zamiast nadpisywać grid-template-columns (nazwane linie col1..colN
	   biorą się właśnie z tych obszarów).

	   Wiersz dwukolumnowy zostaje 2-kolumnowy - to sekcja "O nas", gdzie
	   zdjęcie ustawia się już nad opisem i miejsca wystarcza.

	   Wiersze 4- i 5-kolumnowe łamią się wcześniej - patrz blok 900px niżej.

	   #body w selektorze to nie ozdoba. Themify generuje dla KAŻDEGO wiersza
	   regułę ".themify_builder_content-N .tb_XXXX > .row_inner { --area: ... }"
	   (0,3,1) i to ona pilnuje układu kolumn. Bez podbicia wagi selektorem
	   id nasze ".jkb-grid .tb_col_count_4" (0,2,0) przegrywa i karty zostają
	   w jednym rzędzie mimo media query. */
	#body .jkb-grid .tb_col_count_3 { --area: "col1 col2" "col3 col3"; }
}

/* --- Gęste wiersze kart: łamanie już poniżej 900px ---
   Próg 768px jest dla nich za niski. W oknie 800px (viewport ~780px po
   odjęciu paska przewijania) cztery karty usług dostają po ~137px: "Sesja
   zdjęciowa i marketing" łamie się po dwa słowa, a jednowyrazowe podpisy
   kafelków "Dlaczego JKB" (PROFESJONALIZM, BEZPIECZEŃSTWO) są szersze niż
   kafelek i wychodzą poza ramkę. Karta usługi czyta się dobrze od ok. 240px,
   więc cztery w rzędzie potrzebują ~1000px - stąd zawijanie do dwóch kolumn
   poniżej 900px, z zapasem na pasek przewijania.

   Osobny blok zamiast obniżenia całego progu 768px, bo pozostałe reguły tego
   bloku (menu pod hamburgerem, hero) mają trzymać się progów z panelu
   Themify. */
@media screen and (max-width: 900px) {
	#body .jkb-grid .tb_col_count_4 { --area: "col1 col2" "col3 col4"; }
	#body .jkb-grid .tb_col_count_5 { --area: "col1 col2" "col3 col4" "col5 col5"; }
}

/* --- Telefon --- */
@media screen and (max-width: 600px) {
	:root {
		/* Jedyny boczny margines treści na telefonie - patrz reguła
		   .row_inner niżej w tym bloku. */
		--jkb-gutter-mobile: var(--jkb-space-4);

		--jkb-size-hero: 32px;
		--jkb-size-h2: 22px;
		--jkb-size-numeral: 38px;
		--jkb-section-padding-y: var(--jkb-space-7);
	}

	/* --- Sekcje od krawędzi do krawędzi ---
	   Na telefonie margines boczny naliczał się dwa razy: rodzic trzyma
	   #layout.pagewidth na max-width:90%, a Themify daje jeszcze .row_inner
	   własne max-width:90%. Przy ekranie 365px zjadało to ~35px z każdej
	   strony, a tła sekcji (granat, szarość) i zdjęcie hero kończyły się
	   białym paskiem zamiast dochodzić do krawędzi ekranu.

	   Zdejmujemy oba ograniczenia i oddajemy jeden wspólny margines
	   wewnętrzny na .row_inner: tło idzie na pełną szerokość, a tekst
	   i karty zachowują 16px oddechu od krawędzi. Pasek górny i stopka są
	   pełnej szerokości od początku i mają własny padding (24px), więc ich
	   ta reguła nie dotyczy.

	   #body podbija wagę selektora, bo max-width:90% siedzi w responsywnym
	   CSS Themify pod selektorem o wyższej specyficzności niż sama klasa. */
	#layout.pagewidth,
	#body #content {
		width: 100%;
		max-width: none;
	}
	#body .themify_builder_row > .row_inner {
		width: 100%;
		max-width: 100%;
		padding-left: var(--jkb-gutter-mobile);
		padding-right: var(--jkb-gutter-mobile);
	}

	.jkb-topbar__inner {
		flex-direction: column;
		gap: var(--jkb-space-1);
		text-align: center;
	}

	.jkb-nav__logo {
		--jkb-logo-h: 68px;
		--jkb-logo-rise: 16px;
		--jkb-logo-sink: 6px;
	}

	/* Układ pionowy wchodzi już przy 1024px; tu tylko zmniejszamy kadr.
	   Ta sama proporcja 190:250 co na desktopie, tylko mniejsza - inaczej
	   kadr twarzy przycinałby się inaczej niż na szerokim ekranie. */
	.jkb-person__photo .image-wrap {
		width: 150px;
		height: 197px;
		box-shadow: 0 3px 10px rgba(7, 21, 40, 0.14);
	}

	.jkb-footer__cols { grid-template-columns: 1fr; gap: var(--jkb-space-6); }
	.jkb-footer__bottom { flex-direction: column; gap: var(--jkb-space-2); }

	.jkb-panel { padding: var(--jkb-space-5); }

	/* Na telefonie każda kolumna dostaje własny rząd - także "O nas". */
	#body .jkb-grid .tb_col_count_2 { --area: "col1" "col2"; }
	#body .jkb-grid .tb_col_count_3 { --area: "col1" "col2" "col3"; }
	#body .jkb-grid .tb_col_count_4 { --area: "col1" "col2" "col3" "col4"; }
	#body .jkb-grid .tb_col_count_5 { --area: "col1" "col2" "col3" "col4" "col5"; }

	/* Przyciski na pełną szerokość - łatwiej trafić kciukiem.
	   Kontener jest kolumną flex, bo same width:100% na linku nie wystarczy:
	   szerokość bierze się z elementu .module-buttons-item, który przy
	   flex-wrap dopasowuje się do długości etykiety. */
	.module.module-buttons.jkb-btns { flex-direction: column; }
	.module.module-buttons.jkb-btns .module-buttons-item { width: 100%; }
	.module.module-buttons.jkb-btns .builder_button {
		width: 100%;
		justify-content: center;
	}
}

/* --- Szanuj ustawienie systemowe: mniej ruchu --- */
@media (prefers-reduced-motion: reduce) {
	.jkb-card,
	.jkb-prop,
	.jkb-prop__img img,
	.jkb-tile,
	.jkb-nav__menu .sub-menu,
	.jkb-person__photo .image-wrap,
	.jkb-person__photo img {
		transition: none;
	}
	.jkb-card:hover,
	.jkb-prop:hover { transform: none; }
	.jkb-prop:hover .jkb-prop__img img { transform: none; }
	.jkb-person__photo:hover .image-wrap,
	.jkb-person__photo:hover img { transform: none; }
}


/* =========================================================================
   18. UZUPEŁNIENIA
   ========================================================================= */

/* Kotwice: żeby nagłówek nie zasłaniał początku sekcji po przeskoku */
.themify_builder_row[id] { scroll-margin-top: var(--jkb-space-5); }

/* Para przycisków w jednym module Buttons: pierwszy główny, kolejne poboczne.
   Themify nie daje osobnej klasy na przycisk, a dwa moduły Buttons ustawiłyby
   się jeden pod drugim - stąd rozróżnienie kolejnością. */
.module.module-buttons.jkb-btns--duo .module-buttons-item:first-child .builder_button {
	background-color: var(--jkb-action-primary-bg);
	/* !important z tego samego powodu co wyżej: .module[data-lazy] .ui */
	background-image: var(--jkb-action-primary-gradient) !important;
	background-size: 100% 100%;
	background-position: center;
	color: var(--jkb-action-primary-fg);
	border-color: var(--jkb-action-primary-border);
	transition:
		background-size var(--jkb-transition-base),
		border-color var(--jkb-transition-base),
		color var(--jkb-transition-base);
}
.module.module-buttons.jkb-btns--duo .module-buttons-item:first-child .builder_button:hover {
	background-size: 165% 165%;
	border-color: var(--jkb-btn-gold-mid);
}
/* Drugi i kolejne przyciski w parze: obrys, a na hover to samo wypełnienie
   gradientem co przy wariantach --secondary (wjeżdża od dołu, patrz sekcja 07). */
.module.module-buttons.jkb-btns--duo .module-buttons-item + .module-buttons-item .builder_button {
	background-color: transparent;
	background-image: var(--jkb-action-primary-gradient) !important;
	background-repeat: no-repeat;
	background-position: 50% 100%;
	background-size: 100% 0%;
	color: var(--jkb-action-secondary-fg);
	border-color: var(--jkb-action-secondary-border);
	transition:
		background-size var(--jkb-transition-base),
		color var(--jkb-transition-base),
		border-color var(--jkb-transition-base);
}
.module.module-buttons.jkb-btns--duo .module-buttons-item + .module-buttons-item .builder_button:hover {
	background-size: 100% 100%;
	color: var(--jkb-action-primary-fg);
	border-color: var(--jkb-btn-gold-dark);
}
/* Na jasnym tle napis jest granatowy, a nie złoty - to samo uzasadnienie
   co przy .jkb-btn--secondary-dark w sekcji 07: złoto na bieli daje 3,26:1
   i napis staje się nieczytelny. Obrys zostaje złoty.
   Wypełnienie na hover bez zmian. */
.module.module-buttons.jkb-btns--duo.jkb-btns--on-light .module-buttons-item + .module-buttons-item .builder_button {
	color: var(--jkb-text-heading);
	border-color: var(--jkb-gold-600);
}

/* Moduły Buildera są bezpośrednimi dziećmi kolumny, więc flex działa wprost. */
.module_column.jkb-person > .module { margin-bottom: 0; }
.module_column.jkb-person > .module-image { flex: 0 0 auto; }
.module_column.jkb-person > .module-text { flex: 1 1 auto; }

/* Builder dokleja do każdego modułu .module:after (clear:both, display:table).
   W module, który zrobiliśmy kontenerem flex, ten pseudoelement staje się
   dodatkowym dzieckiem i dokłada jeden gap na końcu karty. Wyłączamy go tam,
   gdzie sami zarządzamy układem; selektor z .module bije .module:after (0,1,1). */
.module.jkb-svc::after,
.module.jkb-step::after,
.module.jkb-op::after,
.module.jkb-tile::after,
.module.jkb-hero__meta::after,
.module.jkb-stars::after { display: none; }

/* Ostatni element w karcie bez zbędnego marginesu pod spodem.
   Bez ">", bo treść modułu Text jest owinięta w .tb_text_wrap. */
.jkb-svc *:last-child,
.jkb-step *:last-child,
.jkb-op *:last-child { margin-bottom: 0; }


/* =========================================================================
   19. POJEDYNCZA OFERTA (single-nieruchomosc.php)
   Układ własnego szablonu: nagłówek z ceną i danymi, zdjęcie, opis, CTA.
   #content jest tu pełnej szerokości (body.full_width), więc kontener
   i pionowy oddech musi dać ten blok - nie ma wiersza Buildera, który by to zrobił.
   ========================================================================= */

.jkb-single {
	width: min(860px, 100%);
	margin: 0 auto;
	padding: var(--jkb-section-padding-y) var(--jkb-space-5);
	/* Rodzic nie ustawia globalnego border-box, a bez tego width:100%
	   i boczny padding sumują się: na telefonie oferta wychodziła
	   48px poza ekran i tytuł urywał się przy prawej krawędzi. */
	box-sizing: border-box;
}

.jkb-single__head {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: var(--jkb-space-3);
	margin-bottom: var(--jkb-space-6);
}
.jkb-single__title {
	margin: 0;
	font-family: var(--jkb-font-display);
	font-size: var(--jkb-size-h1);
	font-weight: var(--jkb-weight-bold);
	color: var(--jkb-text-heading);
	line-height: var(--jkb-leading-heading);
}
.jkb-single__price {
	margin: 0;
	font-family: var(--jkb-font-display);
	font-size: var(--jkb-size-h2);
	font-weight: var(--jkb-weight-bold);
	color: var(--jkb-text-accent);
	line-height: 1.1;
}
.jkb-single__meta {
	display: flex;
	flex-wrap: wrap;
	gap: var(--jkb-space-5);
	font-size: var(--jkb-size-small);
	color: var(--jkb-text-muted);
	padding-top: var(--jkb-space-2);
	border-top: var(--jkb-border-width) solid var(--jkb-border-subtle);
	width: 100%;
}
.jkb-single__meta span { display: inline-flex; align-items: center; gap: var(--jkb-space-2); }

.jkb-single__image {
	margin: 0 0 var(--jkb-space-6);
	border-radius: var(--jkb-radius-image);
	overflow: hidden;
}
.jkb-single__image img { width: 100%; height: auto; display: block; }

.jkb-single__body { margin-bottom: var(--jkb-space-7); }
.jkb-single__body p { margin: 0 0 var(--jkb-space-4); text-wrap: pretty; }
.jkb-single__body p:last-child { margin-bottom: 0; }

/* CTA na granacie, ten sam język wizualny co panel w sekcji Kontakt */
.jkb-single__cta {
	background: var(--jkb-surface-inverse);
	border: var(--jkb-border-width) solid var(--jkb-border-on-inverse);
	border-radius: var(--jkb-radius-md);
	padding: var(--jkb-space-6);
	text-align: center;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: var(--jkb-space-3);
	margin-bottom: var(--jkb-space-6);
}
.jkb-single__cta p {
	margin: 0;
	font-size: var(--jkb-size-small);
	color: rgba(255, 255, 255, 0.78);
}

.jkb-single__back { margin: 0; }

@media screen and (max-width: 600px) {
	.jkb-single__title { font-size: var(--jkb-size-h2); }
	.jkb-single__meta { gap: var(--jkb-space-4); }
}


/* =========================================================================
   20. GALERIA OFERTY
   Duże zdjęcie + pasek miniatur, klik otwiera powiększenie na pełny ekran.
   Nazwy pomieszczeń pochodzą z pola Podpis załącznika.
   ========================================================================= */

.jkb-gallery { margin: 0 0 var(--jkb-space-6); }

/* --- Zdjęcie główne --- */
.jkb-gallery__main { margin: 0; }

.jkb-gallery__zoom {
	display: block;
	width: 100%;
	padding: 0;
	border: 0;
	background: var(--jkb-grey-200);
	border-radius: var(--jkb-radius-image);
	overflow: hidden;
	cursor: zoom-in;
	aspect-ratio: 16 / 10;
}
.jkb-gallery__zoom img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
	transition: transform var(--jkb-transition-slow);
}
.jkb-gallery__zoom:hover img { transform: scale(1.02); }
.jkb-gallery__zoom:focus-visible {
	outline: var(--jkb-border-width-accent) solid var(--jkb-border-accent);
	outline-offset: 2px;
}

.jkb-gallery__main figcaption {
	margin-top: var(--jkb-space-3);
	font-family: var(--jkb-font-display);
	font-size: var(--jkb-size-caption);
	font-weight: var(--jkb-weight-semibold);
	letter-spacing: var(--jkb-tracking-caps);
	text-transform: uppercase;
	color: var(--jkb-text-accent);
	min-height: 1.2em;
}

/* --- Pasek miniatur --- */
.jkb-gallery__thumbs {
	display: grid;
	grid-template-columns: repeat(5, 1fr);
	gap: var(--jkb-space-2);
	margin: var(--jkb-space-3) 0 0;
	padding: 0;
	list-style: none;
}
.jkb-gallery__thumb { margin: 0; }
.jkb-gallery__thumb button {
	position: relative;
	display: block;
	width: 100%;
	padding: 0;
	border: var(--jkb-border-width-accent) solid transparent;
	border-radius: var(--jkb-radius-image);
	overflow: hidden;
	background: var(--jkb-grey-200);
	cursor: pointer;
	aspect-ratio: 3 / 2;
	transition: border-color var(--jkb-transition-base), opacity var(--jkb-transition-base);
}
.jkb-gallery__thumb img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}
.jkb-gallery__thumb button:hover { opacity: 0.85; }
.jkb-gallery__thumb.is-active button { border-color: var(--jkb-border-accent); }
.jkb-gallery__thumb button:focus-visible {
	outline: var(--jkb-border-width-accent) solid var(--jkb-border-accent);
	outline-offset: 2px;
}

/* Ostatnia kafla przy większej liczbie zdjęć: przygaszone tło i licznik */
.jkb-gallery__thumb--more button { cursor: zoom-in; }
.jkb-gallery__thumb--more img { filter: brightness(0.45); }
.jkb-gallery__thumb--more span {
	position: absolute;
	inset: 0;
	display: grid;
	place-items: center;
	font-family: var(--jkb-font-display);
	font-size: var(--jkb-size-h4);
	font-weight: var(--jkb-weight-bold);
	color: var(--jkb-white);
}

/* --- Powiększenie na pełny ekran --- */
body.jkb-lightbox-open { overflow: hidden; }

.jkb-lightbox {
	position: fixed;
	inset: 0;
	z-index: 100000;
	background: rgba(7, 21, 40, 0.975);
	display: grid;
	grid-template-columns: auto 1fr auto;
	align-items: center;
	gap: var(--jkb-space-4);
	padding: var(--jkb-space-5);
}
.jkb-lightbox[hidden] { display: none; }

.jkb-lightbox__figure {
	margin: 0;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: var(--jkb-space-4);
	min-width: 0;
	max-height: 100%;
}
.jkb-lightbox__figure img {
	max-width: 100%;
	max-height: 78vh;
	width: auto;
	height: auto;
	display: block;
	border-radius: var(--jkb-radius-image);
}
.jkb-lightbox__figure figcaption {
	display: flex;
	align-items: baseline;
	gap: var(--jkb-space-4);
	color: var(--jkb-text-on-inverse);
}
.jkb-lightbox__label {
	font-family: var(--jkb-font-display);
	font-size: var(--jkb-size-h4);
	font-weight: var(--jkb-weight-semibold);
	letter-spacing: var(--jkb-tracking-caps);
	text-transform: uppercase;
	color: var(--jkb-text-accent-on-inverse);
}
.jkb-lightbox__count {
	font-size: var(--jkb-size-small);
	color: rgba(255, 255, 255, 0.6);
}

.jkb-lightbox__nav,
.jkb-lightbox__close {
	display: grid;
	place-items: center;
	background: rgba(255, 255, 255, 0.08);
	border: var(--jkb-border-width) solid var(--jkb-border-on-inverse);
	border-radius: var(--jkb-radius-sm);
	color: var(--jkb-white);
	cursor: pointer;
	transition: background-color var(--jkb-transition-base);
}
.jkb-lightbox__nav:hover,
.jkb-lightbox__close:hover { background: rgba(199, 169, 98, 0.25); }

.jkb-lightbox__nav {
	width: 48px;
	height: 72px;
	font-size: 32px;
	line-height: 1;
}
.jkb-lightbox__close {
	position: absolute;
	top: var(--jkb-space-4);
	right: var(--jkb-space-4);
	width: 44px;
	height: 44px;
	font-size: 26px;
	line-height: 1;
}

/* --- Plakietka z liczbą zdjęć na karcie w listingu --- */
.jkb-prop__count {
	position: absolute;
	bottom: 12px;
	right: 12px;
	z-index: 2;
	display: inline-flex;
	align-items: center;
	gap: var(--jkb-space-1);
	padding: 4px 10px;
	border-radius: var(--jkb-radius-sm);
	background: rgba(7, 21, 40, 0.72);
	color: var(--jkb-white);
	font-family: var(--jkb-font-display);
	font-size: var(--jkb-size-micro);
	font-weight: var(--jkb-weight-semibold);
	line-height: 1;
}

@media screen and (max-width: 600px) {
	/* Na telefonie strzałki pod zdjęciem, nie po bokach - inaczej zabierają
	   szerokość, której i tak jest mało. Przewijanie palcem działa zawsze. */
	.jkb-lightbox {
		grid-template-columns: 1fr 1fr;
		grid-template-rows: 1fr auto;
		padding: var(--jkb-space-4);
	}
	.jkb-lightbox__figure { grid-column: 1 / -1; }
	.jkb-lightbox__figure img { max-height: 64vh; }
	.jkb-lightbox__nav { width: 100%; height: 52px; }

	/* Miniatur nie ukrywamy: ostatnia kafla to przycisk "+N", jedyne wejście
	   w powiększenie z paska. Pięć kafli po ~70px mieści się bez problemu. */
	.jkb-gallery__thumbs { gap: var(--jkb-space-1); }
}


/* =========================================================================
   21. MODUŁ: OPINIE KLIENTÓW (KARUZELA)
   Własny moduł Buildera (builder-modules/). Przewijanie oparte na natywnym
   scroll-snap - stąd overflow-x na kadrze zamiast transformu na torze.
   Stylujemy po klasach .jkb-carousel__* i .jkb-op-card__*, nie po
   .module-jkb-opinie: nazwa techniczna modułu nie powinna wchodzić do stylów.
   ========================================================================= */

.jkb-carousel {
	position: relative;
	--jkb-carousel-per-view: 3;
}

/* --- Kadr --- */
.jkb-carousel__viewport {
	overflow-x: auto;
	overflow-y: hidden;
	scroll-snap-type: x mandatory;
	scroll-behavior: smooth;
	/* Pasek przewijania chowamy: nawigacja idzie strzałkami i kropkami,
	   a natywny pasek psułby rytm kart. Przewijanie palcem działa dalej. */
	scrollbar-width: none;
	-ms-overflow-style: none;
	margin: 0 calc(-1 * var(--jkb-space-2));
	padding: var(--jkb-space-2);
}
.jkb-carousel__viewport::-webkit-scrollbar { display: none; }
.jkb-carousel__viewport:focus-visible {
	outline: var(--jkb-border-width-accent) solid var(--jkb-border-accent);
	outline-offset: 2px;
	border-radius: var(--jkb-radius-md);
}

/* --- Tor --- */
.jkb-carousel__track {
	display: flex;
	gap: var(--jkb-grid-gap);
	margin: 0;
	padding: 0;
	list-style: none;
}

.jkb-carousel__slide {
	/* Szerokość karty liczona z liczby widocznych kart minus przerwy między nimi. */
	flex: 0 0 calc(
		(100% - (var(--jkb-carousel-per-view) - 1) * var(--jkb-grid-gap))
		/ var(--jkb-carousel-per-view)
	);
	margin: 0;
	scroll-snap-align: start;
	display: flex;
}

/* --- Karta opinii --- */
.jkb-op-card {
	margin: 0;
	padding: var(--jkb-space-5);
	display: flex;
	flex-direction: column;
	gap: var(--jkb-space-3);
	width: 100%;
	background: var(--jkb-surface-card);
	border: var(--jkb-border-width) solid var(--jkb-border-card);
	border-radius: var(--jkb-radius-md);
	box-shadow: var(--jkb-shadow-card);
	transition: box-shadow var(--jkb-transition-base), transform var(--jkb-transition-base);
}
.jkb-op-card:hover {
	box-shadow: var(--jkb-shadow-card-hover);
	transform: var(--jkb-hover-lift);
}

.jkb-op-card__quote { margin: 0; }
.jkb-op-card__quote p {
	margin: 0 0 var(--jkb-space-2);
	font-style: italic;
	font-size: var(--jkb-size-small);
	color: var(--jkb-text-heading);
	text-wrap: pretty;
}
.jkb-op-card__quote p:last-child { margin-bottom: 0; }

/* Cudzysłowy z projektu dokładamy pseudoelementami, żeby redaktor wpisywał
   w panelu samą treść opinii, bez pilnowania znaków „ i ”. */
.jkb-op-card__quote p:first-child::before { content: '\201E'; }
.jkb-op-card__quote p:last-child::after { content: '\201D'; }

/* Autor i kontekst dosuwane do dołu, żeby karty o różnej długości cytatu
   miały stopkę na tej samej wysokości. */
.jkb-op-card__who {
	margin-top: auto;
	display: flex;
	flex-direction: column;
	gap: var(--jkb-space-1);
}
.jkb-op-card__author {
	font-family: var(--jkb-font-display);
	font-size: var(--jkb-size-caption);
	font-weight: var(--jkb-weight-semibold);
	color: var(--jkb-text-heading);
}
.jkb-op-card__meta {
	font-size: var(--jkb-size-micro);
	color: var(--jkb-text-muted);
}

/* --- Strzałki --- */
.jkb-carousel__arrow {
	position: absolute;
	top: 50%;
	transform: translateY(-50%);
	z-index: 2;
	width: 44px;
	height: 44px;
	display: grid;
	place-items: center;
	padding: 0;
	/* font-size steruje teraz wielkością ikony SVG (.jkb-icon ma 1em x 1em),
	   a nie glifem tekstowym - stąd 20px zamiast dawnych 26px. */
	font-size: 20px;
	line-height: 1;
	background: var(--jkb-surface-card);
	color: var(--jkb-text-heading);
	border: var(--jkb-border-width) solid var(--jkb-border-subtle);
	border-radius: 50%;
	box-shadow: var(--jkb-shadow-card);
	cursor: pointer;
	transition: background-color var(--jkb-transition-base), color var(--jkb-transition-base), border-color var(--jkb-transition-base);
}
/* Ikona dziedziczy kolor przycisku, więc hover przemalowuje ją razem z tłem. */
.jkb-carousel__arrow .jkb-icon { display: block; }
.jkb-carousel__arrow:hover {
	background: var(--jkb-gold-500);
	border-color: var(--jkb-gold-500);
	color: var(--jkb-navy-900);
}
.jkb-carousel__arrow--prev { left: calc(-1 * var(--jkb-space-6)); }
.jkb-carousel__arrow--next { right: calc(-1 * var(--jkb-space-6)); }

/* Na ciemnym tle sekcji strzałki muszą być widoczne */
.jkb-bg-navy .jkb-carousel__arrow,
.jkb-bg-navy-deep .jkb-carousel__arrow {
	background: rgba(255, 255, 255, 0.08);
	border-color: var(--jkb-border-on-inverse);
	color: var(--jkb-text-on-inverse);
}

/* --- Kropki --- */
.jkb-carousel__dots {
	display: flex;
	justify-content: center;
	gap: var(--jkb-space-2);
	margin-top: var(--jkb-space-5);
}
.jkb-carousel__dot {
	width: 10px;
	height: 10px;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: var(--jkb-grey-300);
	cursor: pointer;
	transition: background-color var(--jkb-transition-base), transform var(--jkb-transition-base);
}
.jkb-carousel__dot:hover { background: var(--jkb-gold-400); }
.jkb-carousel__dot.is-active {
	background: var(--jkb-gold-500);
	transform: scale(1.3);
}
.jkb-bg-navy .jkb-carousel__dot { background: rgba(255, 255, 255, 0.28); }
.jkb-bg-navy .jkb-carousel__dot.is-active { background: var(--jkb-gold-400); }

/* --- Responsywność karuzeli --- */
@media screen and (max-width: 1024px) {
	/* Strzałki wchodzą do środka kadru - poza nim nie ma już miejsca */
	.jkb-carousel__arrow--prev { left: 0; }
	.jkb-carousel__arrow--next { right: 0; }

	.jkb-carousel {
		--jkb-carousel-per-view: min(var(--jkb-carousel-per-view), 2);
	}
	.jkb-carousel__slide {
		flex-basis: calc((100% - var(--jkb-grid-gap)) / 2);
	}
}

@media screen and (max-width: 600px) {
	/* Jedna karta na ekran; strzałki chowamy, bo przewijanie palcem
	   jest tu naturalniejsze, a przyciski zasłaniałyby treść karty. */
	.jkb-carousel__slide { flex-basis: 100%; }
	.jkb-carousel__arrow { display: none; }
}

@media (prefers-reduced-motion: reduce) {
	.jkb-carousel__viewport { scroll-behavior: auto; }
	.jkb-op-card { transition: none; }
	.jkb-op-card:hover { transform: none; }
	.jkb-carousel__dot.is-active { transform: none; }
}
