/* ==========================================================================
   webvweb.net — Design System
   Apple-inspired: minimalizm, precyzyjna typografia, glassmorphism, 60fps
   ========================================================================== */

/* ---------- Font loading (self-hosted fallback stack to SF Pro clones) --- */
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&display=swap');

:root{
  /* Colors — Light */
  --c-bg: #ffffff;
  --c-bg-alt: #f5f5f7;
  --c-bg-elevated: #ffffff;
  --c-text: #1d1d1f;
  --c-text-secondary: #6e6e73;
  --c-text-tertiary: #86868b;
  --c-border: rgba(0,0,0,0.08);
  --c-border-strong: rgba(0,0,0,0.14);

  /* Colors — Dark sections (used regardless of OS theme, per Apple dark blocks) */
  --c-dark-bg: #000000;
  --c-dark-bg-alt: #0a0a0c;
  --c-dark-surface: #1d1d1f;
  --c-dark-text: #f5f5f7;
  --c-dark-text-secondary: #a1a1a6;
  --c-dark-border: rgba(255,255,255,0.12);

  /* Brand */
  --brand-blue: #0071e3;
  --brand-blue-dark: #0058b3;
  --brand-blue-light: #2997ff;
  --brand-glow: rgba(0,113,227,0.35);

  /* Semantic */
  --success: #34c759;
  --error: #ff3b30;
  --warning: #ff9f0a;

  /* Type */
  --font-display: 'Inter', -apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  --font-text: 'Inter', -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  --font-mono: 'SF Mono', 'JetBrains Mono', ui-monospace, Menlo, Consolas, monospace;

  /* Spacing scale */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;
  --space-8: 64px;
  --space-9: 96px;
  --space-10: 128px;

  /* Radii */
  --r-sm: 10px;
  --r-md: 18px;
  --r-lg: 28px;
  --r-xl: 40px;
  --r-pill: 980px;

  /* Motion */
  --ease-apple: cubic-bezier(0.28, 0.11, 0.32, 1);
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --dur-fast: 180ms;
  --dur-base: 320ms;
  --dur-slow: 560ms;

  /* Layout */
  --nav-h: 52px;
  --container-w: 1200px;
  --z-nav: 500;
  --z-modal: 900;
  --z-cookie: 950;
  --z-overlay: 800;
}

/* ---------- Reset ---------- */
*, *::before, *::after{ box-sizing: border-box; }
html{
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
  /* Reserves the vertical scrollbar's width permanently, whether or not
     it's currently needed. Without this, body.no-scroll below (toggled
     when the audit modal or the cookie-settings popup opens) removes the
     scrollbar entirely, so the viewport gets a few extra pixels back and
     everything - navbar, page content, the modal itself - visibly jumps
     sideways for a frame. Reserving the gutter up front means that width
     never changes, open or closed, so nothing shifts. */
  scrollbar-gutter: stable;
}
@media (prefers-reduced-motion: reduce){
  html{ scroll-behavior: auto; }
  *, *::before, *::after{
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}
body{
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  font-family: var(--font-text);
  background: var(--c-bg);
  color: var(--c-text);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
  line-height: 1.5;
}
/* Sticky footer: on short pages (e.g. 404) #main grows to push the footer
   to the bottom of the viewport instead of leaving empty space beneath it. */
#main{ flex: 1 0 auto; }
.site-footer{ flex: 0 0 auto; }
body.no-scroll{ overflow: hidden; height: 100%; }
img, svg, video, canvas{ display: block; max-width: 100%; }
a{ color: inherit; text-decoration: none; }
button{ font-family: inherit; cursor: pointer; }
ul{ margin: 0; padding: 0; list-style: none; }
h1,h2,h3,h4,h5,p{ margin: 0; }
input, textarea, select{ font-family: inherit; font-size: inherit; }

/* ---------- Typography ---------- */
h1, .h1{
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.022em;
  font-size: clamp(2.4rem, 5vw, 4.4rem);
  line-height: 1.05;
}
h2, .h2{
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.02em;
  font-size: clamp(1.9rem, 3.4vw, 3rem);
  line-height: 1.08;
}
h3, .h3{
  font-family: var(--font-display);
  font-weight: 600;
  letter-spacing: -0.012em;
  font-size: clamp(1.25rem, 1.8vw, 1.6rem);
  line-height: 1.2;
}
.eyebrow{
  display: inline-block;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--brand-blue);
  margin-bottom: var(--space-3);
}
.lede{
  font-size: clamp(1.05rem, 1.4vw, 1.3rem);
  color: var(--c-text-secondary);
  line-height: 1.5;
  font-weight: 400;
}
.section-dark .lede{ color: var(--c-dark-text-secondary); }

/* ---------- Layout helpers ---------- */
.container{
  width: 100%;
  max-width: var(--container-w);
  margin: 0 auto;
  padding: 0 var(--space-5);
}
.section{ padding: var(--space-9) 0; }
@media (max-width: 640px){ .section{ padding: var(--space-8) 0; } }
.section-dark{ background: var(--c-dark-bg); color: var(--c-dark-text); }
.section-alt{ background: var(--c-bg-alt); }
.text-center{ text-align: center; }
.stack-center{ display:flex; flex-direction:column; align-items:center; text-align:center; }
.visually-hidden{
  position:absolute !important; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap; border:0;
}
.skip-link{
  position:absolute; left:8px; top:-60px; background:var(--brand-blue); color:#fff;
  padding:10px 18px; border-radius:var(--r-sm); z-index:2000; transition: top var(--dur-base) var(--ease-out);
}
.skip-link:focus{ top:8px; }

/* ---------- Buttons ---------- */
.btn{
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  height: 44px;
  padding: 0 24px;
  border-radius: var(--r-pill);
  border: 1px solid transparent;
  font-weight: 500;
  font-size: 15px;
  white-space: nowrap;
  transition: transform var(--dur-fast) var(--ease-out), background var(--dur-base) var(--ease-apple), box-shadow var(--dur-base) var(--ease-apple), border-color var(--dur-base);
}
.btn:active{ transform: scale(0.96); }
.btn-primary{
  background: var(--brand-blue);
  color: #fff;
  box-shadow: 0 1px 2px rgba(0,0,0,0.08);
}
.btn-primary:hover{ background: var(--brand-blue-dark); }
.btn-glow{
  box-shadow: 0 0 0 0 var(--brand-glow);
}
.btn-glow:hover{ box-shadow: 0 4px 24px var(--brand-glow); }
.btn-secondary{
  background: rgba(0,0,0,0.05);
  color: var(--c-text);
}
.btn-secondary:hover{ background: rgba(0,0,0,0.09); }
.section-dark .btn-secondary{ background: rgba(255,255,255,0.1); color:#fff; }
.section-dark .btn-secondary:hover{ background: rgba(255,255,255,0.16); }
.btn-white{ background:#fff; color:#000; }
.btn-white:hover{ background:#e8e8ed; }
.btn-ghost{
  background: transparent;
  color: var(--brand-blue);
  height: auto; padding: 0;
  font-weight: 500;
}
.btn-ghost .arrow{ transition: transform var(--dur-fast) var(--ease-out); display:inline-block; }
.btn-ghost:hover .arrow{ transform: translateX(4px); }
.btn-lg{ height: 52px; padding: 0 32px; font-size: 17px; }
.btn-block{ width: 100%; }
.btn .arrow{ display: inline-block; transition: transform var(--dur-fast) var(--ease-out); }
.btn:hover .arrow{ transform: translateX(4px); }

/* Na bardzo wąskich ekranach nawet krótkie etykiety przycisków (np. długie
   CTA w .cta-banner) mogą być szersze niż dostępna przestrzeń, bo .btn ma
   white-space:nowrap i stałą wysokość. Pozwalamy wtedy etykiecie zawinąć się
   do dwóch linii zamiast wystawać poza kartę/sekcję - działa dla dowolnej
   długości tekstu, nie tylko dzisiejszej. */
@media (max-width: 480px){
  .btn{
    white-space: normal;
    text-align: center;
    height: auto;
    min-height: 44px;
    padding-top: 11px;
    padding-bottom: 11px;
    line-height: 1.3;
    max-width: 100%;
  }
  .btn-lg{ min-height: 52px; padding-left: 20px; padding-right: 20px; }
}

/* ---------- Inline text accent ---------- */
.text-accent{ color: var(--brand-blue); }
.section-dark .text-accent, .cta-banner .text-accent{ color: var(--brand-blue-light); }

/* ---------- Navbar ---------- */
.navbar{
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: var(--z-nav);
  height: var(--nav-h);
  display: flex;
  align-items: center;
  background: rgba(255,255,255,0.72);
  backdrop-filter: saturate(180%) blur(20px);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  border-bottom: 1px solid rgba(0,0,0,0.06);
  transition: background var(--dur-base) var(--ease-apple), border-color var(--dur-base);
}
.navbar.is-dark{
  background: rgba(0,0,0,0.55);
  border-bottom-color: rgba(255,255,255,0.1);
  color: #fff;
}
.navbar.is-dark .nav-link:hover{ color:#fff; }
.navbar.is-dark .nav-burger span{ background:#fff; }
.nav-inner{
  width: 100%;
  max-width: var(--container-w);
  margin: 0 auto;
  padding: 0 var(--space-5);
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.nav-logo{
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 19px;
  letter-spacing: -0.01em;
  display:flex; align-items:center;
}
.nav-logo .web-1, .nav-logo .v-sep{ color: var(--c-text); }
.navbar.is-dark .nav-logo .web-1, .navbar.is-dark .nav-logo .v-sep{ color:#fff; }
.nav-logo .web-2{ color: var(--brand-blue); }
.footer-brand .nav-logo .web-1, .footer-brand .nav-logo .v-sep{ color: #fff; }

/* Reusable "webvweb" wordmark styling (same recipe as .nav-logo) for use
   outside the navbar/footer — e.g. when the brand name appears as a heading
   or inline mention in body copy and should read as the logo, not plain text. */
.brand-wordmark{
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.01em;
}
.brand-wordmark .web-1, .brand-wordmark .v-sep{ color: var(--c-text); }
.brand-wordmark .web-2{ color: var(--brand-blue); }
.nav-links{
  display: flex;
  align-items: center;
  gap: var(--space-6);
}
.nav-link{
  font-size: 13px;
  font-weight: 400;
  color: var(--c-text-secondary);
  transition: color var(--dur-fast);
  position: relative;
}
.nav-link:hover{ color: var(--c-text); }
.navbar.is-dark .nav-link{ color: rgba(255,255,255,0.75); }
.nav-link.is-active{ color: var(--c-text); font-weight: 500; }
.navbar.is-dark .nav-link.is-active{ color: #fff; }
.nav-cta{ display:flex; align-items:center; gap: var(--space-4); }
.nav-cta .btn{ height: 34px; padding: 0 18px; font-size: 13px; }
.nav-burger{
  display: none;
  width: 36px; height: 36px;
  border: none; background: transparent;
  flex-direction: column; align-items: center; justify-content: center; gap: 5px;
}
.nav-burger span{
  width: 20px; height: 2px; background: var(--c-text); border-radius: 2px;
  transition: transform var(--dur-base) var(--ease-apple), opacity var(--dur-fast);
}
.nav-burger.is-open span:nth-child(1){ transform: translateY(7px) rotate(45deg); }
.nav-burger.is-open span:nth-child(2){ opacity: 0; }
.nav-burger.is-open span:nth-child(3){ transform: translateY(-7px) rotate(-45deg); }

.mobile-menu{
  position: fixed; inset: var(--nav-h) 0 0 0;
  background: rgba(255,255,255,0.98);
  backdrop-filter: blur(20px);
  z-index: calc(var(--z-nav) - 1);
  display: flex; flex-direction: column;
  padding: var(--space-6) var(--space-5);
  gap: var(--space-2);
  transform: translateY(-8px);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-base) var(--ease-apple), transform var(--dur-base) var(--ease-apple);
}
.mobile-menu.is-open{ opacity:1; transform:none; pointer-events:auto; }
.mobile-menu a{
  font-size: 28px; font-weight: 600; padding: var(--space-3) 0;
  border-bottom: 1px solid var(--c-border);
  font-family: var(--font-display);
}
.mobile-menu .btn{ margin-top: var(--space-5); }

@media (max-width: 900px){
  .nav-links{ display: none; }
  .nav-cta .btn-secondary-link{ display:none; }
  .nav-burger{ display: flex; }
}

/* ---------- Stats ---------- */
.stats-grid{
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-5);
}
.stat-tile{
  --accent: var(--brand-blue);
  --accent-soft: rgba(0,113,227,0.1);
  --accent-glow: rgba(0,113,227,0.22);
  position: relative;
  overflow: hidden;
  background: var(--c-bg-elevated);
  border: 1px solid var(--c-border);
  border-radius: var(--r-lg);
  padding: var(--space-7) var(--space-5);
  text-align: center;
  transition: transform var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out), border-color var(--dur-base);
}
.stat-tile::after{
  content: '';
  position: absolute; top: 0; left: 0; right: 0; height: 3px;
  background: linear-gradient(90deg, var(--brand-blue), var(--brand-blue-light));
}
.stat-tile::before{
  content: '';
  position: absolute; top: -60px; left: 50%; transform: translateX(-50%);
  width: 200px; height: 160px;
  background: radial-gradient(ellipse 50% 50% at 50% 0%, var(--accent-glow), transparent 70%);
  opacity: 0.7;
  pointer-events: none;
}
.stat-tile:hover{ transform: translateY(-6px); border-color: transparent; box-shadow: 0 24px 48px -12px var(--accent-glow); }
.stat-icon{
  position: relative;
  width: 46px; height: 46px;
  border-radius: 13px;
  background: linear-gradient(135deg, var(--brand-blue), var(--brand-blue-light));
  color: #fff;
  display: flex; align-items: center; justify-content: center;
  margin: 0 auto var(--space-4);
  transition: transform var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out);
}
.stat-tile:hover .stat-icon{ transform: scale(1.08) rotate(-4deg); box-shadow: 0 10px 24px -6px var(--accent-glow); }
.stat-num{
  position: relative;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(2.6rem, 5vw, 3.6rem);
  letter-spacing: -0.03em;
  background: linear-gradient(135deg, var(--brand-blue), var(--brand-blue-light));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.stat-label{
  position: relative;
  margin-top: var(--space-2);
  font-size: 14px;
  color: var(--c-text-secondary);
  font-weight: 500;
}
@media (max-width: 700px){ .stats-grid{ grid-template-columns: 1fr; } }

/* ---------- Promise tiles (4-up) ---------- */
.promise-grid{
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-5);
}
.promise-tile{
  position: relative;
  background: var(--c-bg-elevated);
  border: 1px solid var(--c-border);
  border-radius: var(--r-lg);
  padding: var(--space-6) var(--space-5);
  transition: transform var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out), border-color var(--dur-base);
}
.promise-tile:hover{ transform: translateY(-6px); border-color: transparent; box-shadow: 0 24px 48px -12px rgba(0,113,227,0.18); }
.promise-icon{
  width: 44px; height: 44px;
  border-radius: 12px;
  background: linear-gradient(135deg, var(--brand-blue), var(--brand-blue-light));
  color: #fff;
  display: flex; align-items: center; justify-content: center;
  margin-bottom: var(--space-4);
  transition: transform var(--dur-base) var(--ease-out);
}
.promise-tile:hover .promise-icon{ transform: scale(1.08) rotate(-4deg); }
.promise-tile h3{ font-size: 17px; margin-bottom: var(--space-2); }
.promise-tile p{ font-size: 14.5px; color: var(--c-text-secondary); line-height: 1.6; }
.ways-grid{ grid-template-columns: repeat(3, 1fr); }
.ways-grid .promise-tile{ display: flex; flex-direction: column; }
.ways-grid .promise-tile p{ flex: 1; }
.ways-grid .transform-panel-link{ margin-top: var(--space-3); }
@media (max-width: 900px){ .promise-grid{ grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px){ .promise-grid{ grid-template-columns: 1fr; } }

/* ---------- Transformation carousel ----------
   One panel active in the centre; the other two sit stacked behind it,
   scaled down, blurred and dimmed, peeking out on each side - like a
   shallow card deck rather than a plain one-at-a-time slider. Navigated by
   the arrow buttons, the dots, or a drag/swipe directly on the active card
   (mouse-drag on desktop, touch-swipe on mobile - one Pointer Events
   handler in main.js covers both, see "Jak pracujemy carousel"). All three
   panels sit stacked in the same grid cell (grid-row/column: 1) so the
   stage's height always equals the tallest panel, whichever is active. */
.transform-carousel{
  position: relative;
  margin-top: var(--space-8);
}
.transform-stage{
  position: relative;
  overflow: hidden;
  cursor: grab;
  touch-action: pan-y;
  -webkit-user-select: none; user-select: none;
  padding: var(--space-4) 0;
}
.transform-stage.is-dragging{ cursor: grabbing; }
.transform-track{
  display: grid;
  grid-template-columns: 100%;
}
.transform-panel{
  grid-column: 1;
  grid-row: 1;
  width: 100%;
  max-width: 680px;
  margin: 0 auto;
  background: #fff;
  border: 1px solid var(--c-border);
  border-radius: var(--r-lg);
  box-shadow: 0 2px 8px rgba(0,0,0,0.04), 0 20px 40px -20px rgba(0,0,0,0.08);
  padding: var(--space-8) var(--space-6);
  pointer-events: none;
  /* The active card tracks the drag 1:1 (--drag-rate:1); the peeking cards
     move at a fraction of that (--drag-rate:0.45) - without this split, a
     drag translated the whole stack together by the same amount, so
     nothing moved *relative* to anything else and it read as if dragging
     did nothing. With it, the front card visibly pulls away from the
     stack as you drag, which is the actual "yes, this is being dragged"
     feedback. */
  transform: translateX(calc(var(--drag, 0px) * var(--drag-rate, 1) + var(--tx, 0%))) scale(var(--sc, 1));
  opacity: var(--op, 0);
  filter: blur(var(--bl, 0px));
  transition: transform 480ms var(--ease-apple), opacity 480ms var(--ease-apple), filter 480ms var(--ease-apple);
  z-index: var(--zi, 0);
}
.transform-stage.is-dragging .transform-panel{ transition: none; }
.transform-panel.is-active{ --tx: 0%; --sc: 1; --op: 1; --bl: 0px; --zi: 3; --drag-rate: 1; pointer-events: auto; }
.transform-panel.is-prev{ --tx: -16%; --sc: 0.92; --op: 0.55; --bl: 2px; --zi: 1; --drag-rate: 0.45; }
.transform-panel.is-next{ --tx: 16%; --sc: 0.92; --op: 0.55; --bl: 2px; --zi: 1; --drag-rate: 0.45; }
.transform-panel img{ -webkit-user-drag: none; user-drag: none; pointer-events: none; }
.transform-panel-inner{
  max-width: 620px;
  margin: 0 auto;
  display: flex; flex-direction: column; align-items: center;
  text-align: center;
}
.transform-panel-icon{ margin-bottom: var(--space-5); }
.transform-panel-icon .icon-3d{ height: 56px; width: auto; }
.transform-panel-inner h3{ margin-bottom: var(--space-5); }
.transform-panel-pse{
  /* No explicit width - shrinks to its widest row (Problem/Rozwiązanie/
     Efekt lines still line up in a tidy label:value column internally),
     then align-items:center on .transform-panel-inner centres the whole
     block under the title instead of it hugging the card's left edge. */
  align-self: center;
  text-align: left;
  display: flex; flex-direction: column; gap: var(--space-2);
  margin-bottom: var(--space-6);
}
.pse-row{
  display: grid;
  grid-template-columns: 84px 1fr;
  column-gap: var(--space-3);
  font-size: 13px; margin-bottom: var(--space-2);
  line-height: 1.5;
}
.pse-row b{ font-weight: 700; }
.pse-row b::after{ content: ':'; }
.pse-row span{ color: var(--c-text-secondary); }
.pse-label-problem, .pse-label-solution, .pse-label-effect{ color: var(--brand-blue); }
.transform-panel-link{
  font-size: 15px;
  font-weight: 600;
  color: var(--brand-blue);
  display: inline-flex; align-items: center; gap: 6px;
}
.transform-panel-link .arrow{ transition: transform var(--dur-fast) var(--ease-out); }
.transform-panel-link:hover .arrow{ transform: translateX(4px); }

.transform-arrow{
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 44px; height: 44px;
  border-radius: 50%;
  background: #fff;
  border: 1px solid var(--c-border);
  box-shadow: 0 8px 20px -8px rgba(0,0,0,0.28);
  display: flex; align-items: center; justify-content: center;
  color: var(--c-text);
  cursor: pointer;
  z-index: 4;
  transition: background-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out);
}
.transform-arrow:hover{ background: var(--brand-blue); color: #fff; box-shadow: 0 10px 26px -8px rgba(0,113,227,0.5); }
.transform-arrow--prev{ left: -22px; }
.transform-arrow--next{ right: -22px; }
.transform-dots{ display: flex; justify-content: center; gap: 8px; margin-top: var(--space-5); }
.transform-dot{
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--c-border);
  border: none; padding: 0; cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
}
.transform-dot.is-active{ background: var(--brand-blue); transform: scale(1.35); }

@media (max-width: 700px){
  .transform-arrow{ width: 38px; height: 38px; }
  .transform-arrow--prev{ left: 8px; }
  .transform-arrow--next{ right: 8px; }
  .transform-panel{ padding: var(--space-7) var(--space-5); }
  .transform-panel.is-prev{ --tx: -10%; --sc: 0.94; }
  .transform-panel.is-next{ --tx: 10%; --sc: 0.94; }
}
@media (max-width: 560px){
  .pse-row{ grid-template-columns: 72px 1fr; }
}
@media (max-width: 480px){
  .transform-panel.is-prev{ --tx: -6%; --sc: 0.96; --op: 0.45; --bl: 1.5px; }
  .transform-panel.is-next{ --tx: 6%; --sc: 0.96; --op: 0.45; --bl: 1.5px; }
}

/* ---------- Kim jesteśmy (intro split) ---------- */
.intro-split{
  display: grid;
  grid-template-columns: 0.88fr 1.12fr;
  gap: var(--space-8);
  align-items: center;
}
.intro-split p{ font-size: 17px; line-height: 1.7; color: var(--c-text-secondary); margin-bottom: var(--space-5); }
/* No card/box around the photo, and the WHOLE image shows - no cropping.
   Sized by the column's own width, so the whole photo is always visible -
   never stretched/overflowed past it (that was tried and cropped Jakub off
   the viewport edge, which is worse than too small).
   Desktop: align-self:start puts the photo's top flush with the row's own
   top edge. That only lines it up with the heading because the text
   column is the taller of the two here (it fills the whole row height,
   so align-items:center's default centering gives it zero offset from the
   row top) - if the text ever becomes shorter than the photo, this
   stops being exact. This is a trade-off against the photo bleeding down
   to touch the next section (still true on mobile, see below) - matching
   both the top AND the bottom exactly isn't possible for a fixed-ratio,
   uncropped image without fragile per-viewport magic numbers. */
.founders-visual{
  align-self: start;
}
/* .founders-visual-frame exists purely so the accent line below can anchor
   to the photo's own true bottom edge - the mobile bleed margin lives here
   (not on the img itself) so the frame's own box always hugs the img
   exactly, regardless of any negative margin pulling it past the section's
   padding. Positioning the ::after off .founders-visual directly would be
   off by that same bleed amount on mobile. */
.founders-visual-frame{
  position: relative;
}
.founders-visual-photo{
  display: block;
  width: 100%;
  height: auto;
}
/* Thin brand-blue accent line under the photo, a bit wider than it and
   fading out at both ends rather than a flat, hard-edged bar. */
.founders-visual-frame::after{
  content: '';
  position: absolute;
  left: 50%;
  bottom: 0;
  transform: translateX(-50%);
  width: 112%;
  height: 3px;
  background: linear-gradient(90deg, transparent, var(--brand-blue) 50%, transparent);
}
@media (max-width: 860px){
  .intro-split{ grid-template-columns: 1fr; }
  /* Stacked single column: there's no heading to line up with beside it,
     so keep the original "touch the next section" bleed here instead. */
  .founders-visual{ align-self: auto; }
  .founders-visual-frame{ margin-bottom: calc(-1 * var(--space-9)); }
}
@media (max-width: 640px){
  .founders-visual-frame{ margin-bottom: calc(-1 * var(--space-8)); }
}

/* ---------- Porównanie stron (desktop-only, live scrollable preview) ----------
   Hidden by default; shown only once there's genuinely enough room for two
   side-by-side browser panes — both on phones (media query never matches)
   and on a desktop window shrunk narrower/shorter than that. */
.compare-section{ display: none; }
@media (min-width: 1100px) and (min-height: 720px){
  .compare-section{ display: block; }
}
.compare-section .container{ max-width: 90vw; }
.compare-disclaimer{
  text-align: center;
  font-size: 12.5px;
  color: var(--c-text-tertiary);
  margin: var(--space-5) auto 0;
  max-width: 640px;
}
.compare-grid{
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-5);
}
.compare-pane{
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--c-bg-elevated);
  border: 1px solid var(--c-border);
  box-shadow: 0 20px 50px -24px rgba(0,0,0,0.18);
  display: flex;
  flex-direction: column;
}
.compare-pane-label{
  display: flex; align-items: center;
  padding: 15px var(--space-5);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 13px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  border-bottom: 1px solid var(--c-border);
}
.compare-pane-label--before{ color: var(--c-text-secondary); }
.compare-pane-label--after{
  color: #fff;
  background: linear-gradient(135deg, var(--brand-blue), var(--brand-blue-light));
  border-bottom-color: transparent;
}
/* The "Po" tile is the one we want you to walk away remembering — it gets
   the brand-blue treatment (border, glow, tinted panels) so it visually
   wins against the neutral "Przed" tile beside it. */
.compare-pane--after{
  border-color: var(--brand-blue);
  box-shadow: 0 8px 40px -14px rgba(0,113,227,0.38), 0 20px 50px -24px rgba(0,0,0,0.18);
}
/* Large, legible live preview — the real page loads at the frame's actual
   width (so it reflows and reads correctly) and scrolls natively inside
   its own scrollbar when taller than the box. Taller box = more visible
   at a glance before you need to scroll. */
.compare-frame{
  position: relative;
  width: 100%;
  aspect-ratio: 1 / 1;
  overflow: hidden;
  background: #fff;
  cursor: pointer;
}
/* The iframe stays inert (pointer-events: none) until clicked, so a mouse
   wheel passing over the live preview scrolls the page underneath it
   instead of getting trapped inside the embedded site - only an explicit
   click hands scroll/interaction control to the iframe itself. */
.compare-frame iframe{
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: none;
  background: #fff;
  pointer-events: none;
}
.compare-frame.is-active{ cursor: default; }
.compare-frame.is-active iframe{ pointer-events: auto; }
.compare-frame-hint{
  position: absolute;
  inset: auto 0 0 0;
  display: flex; align-items: center; justify-content: center;
  padding: 11px var(--space-4);
  background: linear-gradient(0deg, rgba(0,0,0,0.6), transparent);
  color: #fff;
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0.02em;
  opacity: 1;
  transition: opacity var(--dur-base) var(--ease-out);
  pointer-events: none;
}
.compare-frame.is-active .compare-frame-hint{ opacity: 0; }
.compare-verdict{
  padding: var(--space-6) var(--space-6);
  border-top: 1px solid var(--c-border);
  flex: 1;
}
.compare-verdict h4{
  font-family: var(--font-display);
  font-size: 15px;
  font-weight: 700;
  margin-bottom: var(--space-4);
}
.compare-verdict--before h4{ color: var(--c-text-secondary); }
.compare-verdict--after{ background: rgba(0,113,227,0.045); }
.compare-verdict--after h4{ color: var(--brand-blue); }
.compare-verdict ul{ list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 10px; }
.compare-verdict li{
  display: flex; align-items: flex-start; gap: 10px;
  font-size: 14.5px; line-height: 1.5;
  color: var(--c-text-secondary);
}
.compare-verdict li svg{ flex: none; margin-top: 2px; }
.compare-verdict--before li svg{ color: var(--c-text-tertiary); }
.compare-verdict--after li svg{ color: var(--brand-blue); }

/* ---------- FAQ (shared, animated accordion — used on every page) ----------
   Markup rendered by build.py's faq_section(); accordion open/close handled
   in js/main.js (single item open per .faq-list, aria-expanded toggling).
   The answer panel animates via a CSS grid-template-rows 0fr→1fr trick, so
   height animates smoothly without ever measuring scrollHeight in JS. */
.faq-list{
  max-width: 820px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.faq-item{
  position: relative;
  background: var(--c-bg-elevated);
  border: 1px solid var(--c-border);
  border-radius: var(--r-lg);
  overflow: hidden;
  box-shadow: 0 2px 10px -6px rgba(0,0,0,0.06);
  transition: border-color var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out);
}
.faq-item:hover{ border-color: var(--brand-blue); transform: translateY(-2px); box-shadow: 0 16px 34px -18px rgba(0,113,227,0.26); }
.faq-item::before{
  content: '';
  position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: linear-gradient(180deg, var(--brand-blue), var(--brand-blue-light));
  transform: scaleY(0);
  transform-origin: top;
  transition: transform 420ms var(--ease-apple);
}
.faq-item.is-open{ border-color: var(--brand-blue); box-shadow: 0 18px 40px -20px rgba(0,113,227,0.3); }
.faq-item.is-open::before{ transform: scaleY(1); }

.faq-q{
  width: 100%;
  display: flex; align-items: center; gap: var(--space-4);
  padding: var(--space-5) var(--space-6);
  background: none; border: none; margin: 0;
  text-align: left; cursor: pointer;
  font-family: var(--font-display); font-weight: 600; font-size: 16px; color: var(--c-text);
  -webkit-appearance: none; appearance: none;
}
.faq-q-num{
  flex: none;
  font-family: var(--font-mono); font-size: 12px; font-weight: 700;
  color: var(--brand-blue); background: rgba(0,113,227,0.08);
  width: 30px; height: 30px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  transition: background var(--dur-base) var(--ease-out), color var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-apple);
}
.faq-item.is-open .faq-q-num{
  background: linear-gradient(135deg, var(--brand-blue), var(--brand-blue-light));
  color: #fff;
  transform: scale(1.1);
}
.faq-q-text{ flex: 1; line-height: 1.45; transition: color var(--dur-base) var(--ease-out); }
.faq-item:hover .faq-q-text{ color: var(--brand-blue); }
.faq-q-icon{
  flex: none; display: flex; color: var(--c-text-tertiary);
  transition: transform 420ms var(--ease-apple), color var(--dur-base) var(--ease-out);
}
.faq-item.is-open .faq-q-icon{ transform: rotate(180deg); color: var(--brand-blue); }

.faq-a{
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 420ms var(--ease-apple);
}
.faq-a-inner{ overflow: hidden; min-height: 0; }
.faq-a-inner p{
  margin: 0;
  padding: 0 var(--space-6) var(--space-6) calc(30px + var(--space-4) + var(--space-6));
  color: var(--c-text-secondary); font-size: 14.5px; line-height: 1.75;
  opacity: 0; transform: translateY(-8px);
  transition: opacity 320ms var(--ease-out), transform 320ms var(--ease-out);
}
.faq-item.is-open .faq-a{ grid-template-rows: 1fr; }
.faq-item.is-open .faq-a-inner p{ opacity: 1; transform: none; transition-delay: 120ms; }

.faq-cta{ margin-top: var(--space-7); text-align: center; }
.faq-cta p{ color: var(--c-text-secondary); font-size: 15px; margin-bottom: var(--space-4); }

/* ---------- FAQ "show more" (progressive reveal) ----------
   Items beyond faq_section()'s visible_count render with .faq-extra and
   stay display:none until js/main.js reveals them in batches on click of
   .faq-more-btn — see the accordion + show-more handler in main.js. The
   button removes itself (.is-hidden) once nothing is left to reveal. */
.faq-wrap{ max-width: 820px; margin: 0 auto; }
.faq-wrap .faq-list{ max-width: none; }
/* Extra items grow open smoothly (max-height + opacity) instead of
   snapping straight to their full height - display:none can't be
   transitioned, so max-height stands in for it. 200px comfortably clears
   even a two-line question row; the transition simply keeps running past
   the real content height with nothing left to reveal, which reads as a
   normal ease-out rather than a visible overshoot. */
.faq-item.faq-extra{
  max-height: 0;
  opacity: 0;
  overflow: hidden;
  pointer-events: none;
  transition: max-height 620ms var(--ease-apple), opacity 460ms var(--ease-apple) 60ms,
              border-color var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out);
}
.faq-item.faq-extra.is-revealed{
  max-height: 200px;
  opacity: 1;
  pointer-events: auto;
}
/* Once the reveal transition finishes (main.js listens for it), the cap
   is lifted way past any realistic content height so opening this item's
   own accordion afterwards - which can be much taller than 200px - never
   gets clipped by the outer reveal transition. */
.faq-item.faq-extra.is-revealed.is-settled{ max-height: 3000px; }
.faq-more-wrap{ text-align: center; margin-top: var(--space-5); }
.faq-more-btn{
  display: inline-flex; align-items: center; gap: 9px;
  padding: 12px 24px;
  border-radius: var(--r-pill);
  border: 1px solid var(--c-border);
  background: var(--c-bg-elevated);
  color: var(--c-text);
  font-family: var(--font-display); font-weight: 600; font-size: 14.5px;
  cursor: pointer;
  -webkit-appearance: none; appearance: none;
  transition: border-color var(--dur-base) var(--ease-out), color var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out);
}
.faq-more-btn svg{ transition: transform var(--dur-base) var(--ease-apple); }
.faq-more-btn:hover{
  border-color: var(--brand-blue);
  color: var(--brand-blue);
  transform: translateY(-2px);
  box-shadow: 0 14px 30px -18px rgba(0,113,227,0.32);
}
.faq-more-btn:hover svg{ transform: translateY(2px); }
.faq-more-btn.is-hidden{ display: none; }

@media (max-width: 640px){
  .faq-a-inner p{ padding-left: var(--space-6); }
}

/* ---------- CTA banner ---------- */
.cta-banner{
  background: #000;
  border-radius: var(--r-xl);
  padding: var(--space-9) var(--space-6);
  text-align: center;
  position: relative;
  overflow: hidden;
  color: #fff;
}
.cta-banner::before{
  content:'';
  position:absolute; inset:0;
  background: radial-gradient(ellipse 70% 100% at 50% 0%, rgba(0,113,227,0.4), transparent 70%);
}
.cta-banner > *{ position: relative; }
.cta-banner h2{ color:#fff; margin-bottom: var(--space-5); }
.cta-banner .btn{ margin-top: var(--space-2); }

/* ---------- Blog: card grid (blog.php + Grav /blog list page) ----------
   Przeniesione tu z inline <style> na blog.php (patrz pages_3.py,
   blog_extra_css) - globalne, żeby motyw Grav (user/themes/webvweb-blog)
   mógł korzystać z dokładnie tych samych reguł bez własnego pliku CSS. */
.blog-grid{ display:grid; grid-template-columns:repeat(3,1fr); gap: var(--space-5); }
.blog-card{
  position:relative;
  background:#fff; border:1px solid var(--c-border); border-radius: var(--r-lg);
  overflow:hidden; display:flex; flex-direction:column;
  transition: transform .35s cubic-bezier(.2,.8,.2,1), box-shadow .35s ease, border-color .35s ease;
}
.blog-card:hover{ transform: translateY(-8px) scale(1.015); box-shadow: 0 34px 60px -22px rgba(0,0,0,0.22); border-color: rgba(0,113,227,0.25); }
.blog-card-media{
  aspect-ratio: 16/10;
  background: linear-gradient(135deg, var(--c1,#0071e3), var(--c2,#7b2ff7));
  position:relative;
  overflow:hidden;
}
.blog-card-media .tag{
  position:absolute; top:14px; left:14px; background:rgba(0,0,0,0.35); color:#fff;
  font-size:11.5px; font-weight:600; padding:5px 12px; border-radius:var(--r-pill);
  backdrop-filter: blur(6px);
  z-index:2;
}
.blog-card-media img{
  position:absolute; inset:0; width:100%; height:100%; object-fit:cover;
  transition: transform .5s ease;
}
.blog-card:hover .blog-card-media img{ transform: scale(1.06); }
.blog-card-new{
  position:absolute; top:14px; right:14px; z-index:2;
  background: linear-gradient(120deg, #fdf1c8, #f6c453 35%, #e8a415 55%, #f6c453 70%, #fdf1c8);
  background-size: 240% 100%;
  color:#5a3d00; font-size:11.5px; font-weight:800; letter-spacing:.03em; text-transform:uppercase;
  padding:5px 13px; border-radius:var(--r-pill);
  box-shadow: 0 0 0 1px rgba(255,255,255,0.6) inset, 0 8px 20px -6px rgba(232,164,21,0.65);
  animation: blogNewShine 3.2s ease-in-out infinite, blogNewGlow 2.4s ease-in-out infinite;
}
@keyframes blogNewShine{
  0%{ background-position: 0% 50%; }
  50%{ background-position: 100% 50%; }
  100%{ background-position: 0% 50%; }
}
@keyframes blogNewGlow{
  0%, 100%{ box-shadow: 0 0 0 1px rgba(255,255,255,0.6) inset, 0 8px 18px -6px rgba(232,164,21,0.55); }
  50%{ box-shadow: 0 0 0 1px rgba(255,255,255,0.85) inset, 0 10px 26px -4px rgba(232,164,21,0.9); }
}
@media (prefers-reduced-motion: reduce){
  .blog-card-new{ animation:none; }
}
.blog-card-body{ padding: var(--space-5); display:flex; flex-direction:column; flex:1; }
.blog-card-meta{ font-size:12.5px; color: var(--c-text-tertiary); margin-bottom: var(--space-3); font-family: var(--font-mono); }
.blog-card h3{ margin-bottom: var(--space-3); font-size:1.2rem; transition: color .2s ease; }
.blog-card:hover h3{ color: var(--brand-blue); }
.blog-card p{ color: var(--c-text-secondary); font-size:14.5px; line-height:1.6; flex:1; margin-bottom: var(--space-4); }
.blog-card .card-link{ position:relative; font-size:14px; font-weight:600; color: var(--brand-blue); display:inline-flex; align-items:center; gap:6px; }
.blog-card .card-link::before{
  content:''; position:absolute; inset:0; z-index:1;
}
.blog-card .card-link .arrow{ transition: transform var(--dur-fast) var(--ease-out); }
.blog-card:hover .card-link .arrow{ transform: translateX(4px); }
@media (max-width: 900px){ .blog-grid{ grid-template-columns:1fr; } }

/* ---------- Blog: filter bar (wyszukiwanie + filtr kategorii/tagów) ----------
   Wyłącznie na Grav /blog - patrz templates/blog.html.twig, blok bottom_scripts
   (czysty JS, bez zależności) filtruje karty .blog-card po atrybutach
   data-filter-tags/data-filter-text ustawianych przez Twig. */
.blog-filter-bar{
  display:flex; flex-wrap:wrap; align-items:center; gap: var(--space-4);
  margin-bottom: var(--space-6);
}
.blog-search{
  display:flex; align-items:center; gap:10px;
  background: var(--c-bg-alt);
  border:1px solid transparent; border-radius: var(--r-pill);
  padding: 11px 18px; min-width: 260px; flex: 0 1 320px;
  color: var(--c-text-tertiary);
  transition: border-color var(--dur-fast) var(--ease-out), background var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out);
}
.blog-search:focus-within{
  background:#fff; border-color: var(--brand-blue); color: var(--brand-blue);
  box-shadow: 0 0 0 4px rgba(0,113,227,0.12);
}
.blog-search svg{ flex-shrink:0; color: var(--c-text-tertiary); transition: color var(--dur-fast) var(--ease-out); }
.blog-search:focus-within svg{ color: var(--brand-blue); }
.blog-search input{
  border:0; outline:0; background:transparent; width:100%;
  font-size:14.5px; color: var(--c-text-primary); font-family: inherit;
}
.blog-search input::placeholder{ color: var(--c-text-tertiary); }
.blog-filter-tags{ display:flex; flex-wrap:wrap; gap:8px; }
.blog-filter-pill{
  border:1px solid var(--c-border); background:#fff; color: var(--c-text-secondary);
  font-size:13px; font-weight:600; padding:8px 16px; border-radius: var(--r-pill);
  cursor:pointer; transition: border-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out), background var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
}
.blog-filter-pill:hover{ border-color: var(--brand-blue); color: var(--brand-blue); transform: translateY(-1px); }
.blog-filter-pill.is-active{ background: var(--brand-blue); border-color: var(--brand-blue); color:#fff; }
.blog-card[hidden]{ display:none; }
@media (max-width: 640px){ .blog-search{ flex-basis: 100%; } }

/* ---------- Blog: single article shell (blog/*.php + Grav /blog/* posts) ----------
   Przeniesione tu z inline <style> na blog/*.php (patrz pages_3.py,
   article_extra_css) - z tych samych powodów co blok wyżej. */
.article-hero{ padding: calc(var(--nav-h) + var(--space-8)) 0 var(--space-6); }
.article-meta{ font-family:var(--font-mono); font-size:13px; color:var(--c-text-tertiary); margin-bottom:var(--space-4); }
.article-tag{ display:inline-block; background:var(--c-bg-alt); color:var(--brand-blue); font-size:12px; font-weight:600; padding:4px 12px; border-radius:var(--r-pill); }
.article-featured-image{
  width:100%; max-height: 460px; object-fit:cover;
  border-radius: var(--r-lg); margin-bottom: var(--space-6);
}
.related-box{ background:var(--c-bg-alt); border-radius:var(--r-lg); padding:var(--space-6); margin-top:var(--space-8); }
.related-box h4{ margin-bottom:var(--space-3); }
.related-box a{ color:var(--brand-blue); font-weight:500; }

/* ---------- Blog: breadcrumb na jasnym tle (.article-hero) ----------
   .breadcrumb bazowo jest stylowany pod ciemne tlo .page-hero (bialy tekst
   na granatowym tle listy bloga/podstron) - na stronie POJEDYNCZEGO wpisu
   tlo jest jasne, wiec potrzebuje wlasnych, ciemnych kolorow. Separator
   ustawiony w Twigu jako <span class="sep"> zeby dalo sie go ostylowac
   osobno od linkow i ostatniego, nieklikalnego elementu (tytul wpisu). */
.article-hero .breadcrumb{ color: var(--c-text-tertiary); display:flex; align-items:center; flex-wrap:wrap; gap:2px; }
.article-hero .breadcrumb a{ color: var(--c-text-secondary); }
.article-hero .breadcrumb a:hover{ color: var(--brand-blue); }
.article-hero .breadcrumb .sep{ margin:0 6px; opacity:.5; }
.article-hero .breadcrumb .current{
  color: var(--c-text-primary); font-weight:500;
  max-width: 320px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}

/* ---------- Blog: boks meta wpisu (autor + avatar, data, czas czytania, kategoria) ---------- */
.article-meta-box{
  display:flex; flex-wrap:wrap; align-items:center; gap:12px;
  background: var(--c-bg-alt); border-radius: var(--r-lg);
  padding: 14px 20px; margin: var(--space-5) 0 var(--space-6);
  font-size:13.5px; color: var(--c-text-secondary);
}
.article-meta-author{ display:flex; align-items:center; gap:9px; font-weight:600; color: var(--c-text-primary); }
.author-avatar{
  width:30px; height:30px; border-radius:50%; object-fit:cover; flex-shrink:0;
  display:inline-flex; align-items:center; justify-content:center;
}
.author-avatar-initial{
  background: linear-gradient(135deg, var(--brand-blue), #7b2ff7);
  color:#fff; font-size:13px; font-weight:700;
}
.article-meta-box .meta-sep{ color: var(--c-border); }
.article-meta-box .article-tag{ margin:0; }

/* ---------- Blog: "To moze Cie zainteresowac" (sekcja pod wpisem) ---------- */
.you-might-like{ margin-top: var(--space-9); }
.you-might-like > .container > h3{ margin-bottom: var(--space-5); }
.you-might-like .blog-grid{ grid-template-columns: repeat(3, 1fr); }
@media (max-width: 900px){ .you-might-like .blog-grid{ grid-template-columns:1fr; } }

/* ---------- Blog: pagination (Grav /blog list page, gdy wpisów > posts_per_page) ---------- */
.pagination{ display:flex; justify-content:center; align-items:center; gap: var(--space-2); margin-top: var(--space-8); flex-wrap: wrap; }
.pagination a, .pagination span{
  display:inline-flex; align-items:center; justify-content:center;
  min-width: 40px; height: 40px; padding: 0 var(--space-3);
  border: 1px solid var(--c-border); border-radius: var(--r-pill);
  font-family: var(--font-mono); font-size: 13.5px; color: var(--c-text-secondary);
  transition: border-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.pagination a:hover{ border-color: var(--brand-blue); color: var(--brand-blue); }
.pagination .active, .pagination [aria-current="page"]{
  background: var(--brand-blue); border-color: var(--brand-blue); color:#fff;
}

/* ---------- AI Fatigue banner (home page, right under hero) ---------- */
.ai-fatigue-section{
  position: relative;
  overflow: hidden;
  background: linear-gradient(135deg, var(--brand-blue-dark), var(--brand-blue) 55%, var(--brand-blue-light));
  color: #fff;
}
.ai-fatigue-section::before{
  content:'';
  position:absolute; inset:0;
  background: radial-gradient(ellipse 60% 90% at 85% 0%, rgba(255,255,255,0.22), transparent 60%);
  pointer-events: none;
}
.ai-fatigue-section .container{ position: relative; }
.ai-fatigue-section h2{ color: #fff; }
.ai-fatigue-section .lede{ color: rgba(255,255,255,0.88); }
.ai-fatigue-grid{
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-4);
  margin-top: var(--space-7);
  align-items: start;
}

/* Collapsed by default (button row only) - expands on click. Sized to its
   actual content (button row height, or button + answer once open), not a
   fixed box, so it never carries empty space. */
.ai-fatigue-point{
  position: relative;
  overflow: hidden;
  background: rgba(255,255,255,0.08);
  border: 1px solid rgba(255,255,255,0.18);
  border-radius: var(--r-md);
  backdrop-filter: blur(6px);
  transition: transform 380ms var(--ease-apple), background-color 380ms var(--ease-out), border-color 380ms var(--ease-out), box-shadow 380ms var(--ease-apple);
}
/* Diagonal light sweep on hover - more character than a flat highlight. */
.ai-fatigue-point::after{
  content: '';
  position: absolute; top: 0; left: -60%; width: 45%; height: 100%;
  background: linear-gradient(115deg, transparent, rgba(255,255,255,0.22), transparent);
  transform: skewX(-18deg);
  transition: left 650ms var(--ease-apple);
  pointer-events: none;
}
.ai-fatigue-point:hover{
  transform: translateY(-5px);
  background: rgba(255,255,255,0.13);
  border-color: rgba(255,255,255,0.34);
  box-shadow: 0 18px 36px -18px rgba(0,0,0,0.4);
}
.ai-fatigue-point:hover::after{ left: 130%; }
.ai-fatigue-point:hover .ai-fatigue-point-icon{ transform: scale(1.1) rotate(-6deg); background: rgba(255,255,255,0.26); }

.ai-fatigue-point-q{
  width: 100%;
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-4) var(--space-4);
  background: none; border: none; margin: 0;
  text-align: left; cursor: pointer;
  font-family: var(--font-display); font-weight: 600; font-size: 15px; color: #fff;
  position: relative;
}
.ai-fatigue-point-icon{
  flex: none;
  width: 36px; height: 36px;
  border-radius: 10px;
  background: rgba(255,255,255,0.16);
  color: #fff;
  display: flex; align-items: center; justify-content: center;
  transition: transform 380ms var(--ease-apple), background-color 380ms var(--ease-out);
}
.ai-fatigue-point-q-text{ flex: 1; line-height: 1.35; }
.ai-fatigue-point-chevron{
  flex: none; display: flex; color: rgba(255,255,255,0.6);
  transition: transform 420ms var(--ease-apple), color 380ms var(--ease-out);
}
.ai-fatigue-point.is-open .ai-fatigue-point-chevron{ transform: rotate(180deg); color: #fff; }

.ai-fatigue-point-a{
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 420ms var(--ease-apple);
}
.ai-fatigue-point-a-inner{ overflow: hidden; min-height: 0; }
.ai-fatigue-point-a-inner p{
  margin: 0;
  padding: 0 var(--space-4) var(--space-4) calc(36px + var(--space-3) + var(--space-4));
  color: rgba(255,255,255,0.78); font-size: 13.5px; line-height: 1.6;
  opacity: 0; transform: translateY(-6px);
  transition: opacity 300ms var(--ease-out), transform 300ms var(--ease-out);
}
.ai-fatigue-point.is-open .ai-fatigue-point-a{ grid-template-rows: 1fr; }
.ai-fatigue-point.is-open .ai-fatigue-point-a-inner p{ opacity: 1; transform: none; transition-delay: 110ms; }

@media (max-width: 900px){ .ai-fatigue-grid{ grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px){
  .ai-fatigue-grid{ grid-template-columns: 1fr; }
  .ai-fatigue-point-a-inner p{ padding-left: var(--space-4); }
}

/* ---------- Koncepty promo (home page - bold, brand-colour banner that
   pushes toward /koncepty) ----------
   Deliberately as loud as .ai-fatigue-section near the top of the page -
   by design, this is the one moment between the hero and the footer where
   the page breaks from white/neutral sections to grab attention again,
   right before asking for the click through to the Koncepty gallery. */
.koncepty-promo-section{
  position: relative;
  overflow: hidden;
  background: linear-gradient(135deg, var(--brand-blue-light), var(--brand-blue) 55%, var(--brand-blue-dark));
  color: #fff;
}
.koncepty-promo-section::before{
  content:'';
  position:absolute; inset:0;
  background: radial-gradient(ellipse 60% 90% at 12% 100%, rgba(255,255,255,0.22), transparent 60%);
  pointer-events: none;
}
.koncepty-promo-section .container{ position: relative; }
.koncepty-promo-inner{
  display: grid;
  grid-template-columns: 1.1fr 0.9fr;
  gap: var(--space-8);
  align-items: center;
}
.koncepty-promo-copy .eyebrow{ color: rgba(255,255,255,0.85); }
.koncepty-promo-copy h2{ color: #fff; margin-bottom: var(--space-4); }
.koncepty-promo-copy .lede{ color: rgba(255,255,255,0.88); margin-bottom: var(--space-6); }
.koncepty-promo-chips{
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-4);
}
/* Real screenshots from assets/concept-websites/ - the gradient (--c1/--c2)
   stays underneath as the background, so it still reads fine as a coloured
   tile in the split-second before the (fairly large, lazy-loaded) thumbnail
   decodes, and keeps the tile branded even if an image ever fails to load. */
.koncepty-chip{
  --c1: var(--brand-blue-dark);
  --c2: var(--brand-blue-light);
  position: relative;
  display: block;
  aspect-ratio: 16 / 10;
  min-height: 92px;
  overflow: hidden;
  border-radius: var(--r-md);
  background: linear-gradient(135deg, var(--c1), var(--c2));
  border: 1px solid rgba(255,255,255,0.28);
  box-shadow: 0 18px 34px -18px rgba(0,0,0,0.45);
  transition: transform 380ms var(--ease-apple), box-shadow 380ms var(--ease-apple);
}
.koncepty-chip img{
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover; object-position: top center;
  transition: transform 380ms var(--ease-apple);
}
.koncepty-chip-label{
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: 22px var(--space-3) 8px;
  background: linear-gradient(0deg, rgba(0,0,0,0.65), transparent);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 13.5px;
  color: #fff;
}
.koncepty-chip:nth-child(1){ transform: rotate(-2deg); }
.koncepty-chip:nth-child(2){ transform: rotate(1.5deg); margin-top: var(--space-4); }
.koncepty-chip:nth-child(3){ transform: rotate(1deg); margin-top: calc(-1 * var(--space-4)); }
.koncepty-chip:nth-child(4){ transform: rotate(-1.5deg); }
.koncepty-chip:nth-child(5){ grid-column: 1 / -1; transform: rotate(-0.5deg); }
.koncepty-chip:hover{ transform: translateY(-4px) rotate(0deg) !important; box-shadow: 0 22px 40px -16px rgba(0,0,0,0.5); }
.koncepty-chip:hover img{ transform: scale(1.06); }

@media (max-width: 900px){
  .koncepty-promo-inner{ grid-template-columns: 1fr; }
  .koncepty-promo-chips{ margin-top: var(--space-2); }
}
@media (max-width: 560px){
  .koncepty-promo-chips{ grid-template-columns: repeat(2, 1fr); }
  .koncepty-chip{ min-height: 76px; transform: none !important; margin-top: 0 !important; }
}

/* ---------- Footer ---------- */
.site-footer{
  background: var(--c-dark-bg);
  color: var(--c-dark-text-secondary);
  padding: var(--space-8) 0 var(--space-5);
}
.footer-grid{
  display: grid;
  grid-template-columns: 1.6fr 1fr 0.9fr 0.9fr;
  gap: var(--space-7);
  padding-bottom: var(--space-7);
  border-bottom: 1px solid var(--c-dark-border);
}
.footer-brand .nav-logo{ font-size: 22px; margin-bottom: var(--space-4); }
.footer-brand p{ font-size: 14px; line-height: 1.7; max-width: 320px; }
.footer-col h4{
  color: #fff; font-size: 13px; font-weight: 600;
  letter-spacing: 0.05em; text-transform: uppercase; margin-bottom: var(--space-4);
}
.footer-col li{ margin-bottom: var(--space-3); font-size: 14px; }
.footer-col a{ transition: color var(--dur-fast); }
.footer-col a:hover{ color: #fff; }
.footer-cookie-link{
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: none;
  border: none;
  padding: 0;
  margin: 0;
  font: inherit;
  font-size: 14px;
  line-height: inherit;
  color: inherit;
  cursor: pointer;
  text-align: left;
  transition: color var(--dur-fast);
}
.footer-cookie-link::before{
  content: '';
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--brand-blue-light);
  flex: none;
}
.footer-cookie-link:hover{ color: #fff; }
.footer-bottom{
  padding-top: var(--space-5);
  display: flex; justify-content: center; align-items:center;
  flex-wrap: wrap; gap: var(--space-3) var(--space-5);
  font-size: 12.5px;
  text-align: center;
}
.footer-bottom .legal-links{ display:flex; gap: var(--space-5); }
@media (max-width: 860px){ .footer-grid{ grid-template-columns: 1fr; gap: var(--space-6); } }

/* ---------- Modal (Audyt) ---------- */
.modal-overlay{
  position: fixed; inset: 0;
  background: rgba(0,0,0,0.5);
  backdrop-filter: blur(6px);
  z-index: var(--z-modal);
  display: flex; align-items: center; justify-content: center;
  padding: var(--space-5);
  opacity: 0; pointer-events: none;
  transition: opacity var(--dur-base) var(--ease-apple);
}
.modal-overlay.is-open{ opacity: 1; pointer-events: auto; }
.modal-box{
  background: #fff;
  border-radius: var(--r-lg);
  max-width: 520px; width: 100%;
  /* overflow:hidden (not auto) here, with the actual scrolling delegated
     to .modal-scroll one level down, is what keeps the native scrollbar
     from ever poking past the rounded corners: a child's own scrollbar
     ignores its element's border-radius, but an ANCESTOR's overflow:hidden
     still clips it. */
  overflow: hidden;
  position: relative;
  transform: scale(0.94) translateY(10px);
  transition: transform var(--dur-base) var(--ease-apple);
  box-shadow: 0 40px 100px rgba(0,0,0,0.3);
}
.modal-overlay.is-open .modal-box{ transform: none; }
.modal-scroll{
  max-height: 88vh;
  overflow-y: auto;
  padding: var(--space-7) var(--space-6);
}
.modal-close{
  position: absolute; top: var(--space-5); right: var(--space-5);
  width: 32px; height: 32px; border-radius: 50%;
  background: var(--c-bg-alt); border: none;
  z-index: 1;
  display: flex; align-items: center; justify-content: center;
  color: var(--c-text-secondary);
  transition: background var(--dur-fast);
}
.modal-close:hover{ background: var(--c-border-strong); }
.modal-box h2{ font-size: 1.6rem; margin-bottom: var(--space-2); }
.modal-box .lede{ font-size: 15px; margin-bottom: var(--space-6); }

/* Shown only when the modal is opened from a "Zapytaj o pakiet" button on
   Cennik (see #auditPackageNote in build.py + setModalPackage() in
   main.js) - [hidden] keeps it out of layout entirely the rest of the
   time, so it never reserves empty space in the generic modal.
   IMPORTANT: the :not([hidden]) is required, not decorative - an element's
   own `display` set here in the AUTHOR stylesheet always wins over the
   browser's built-in `[hidden]{display:none}` UA-stylesheet rule (author
   styles beat UA styles regardless of selector specificity), so without
   this guard the hidden attribute set in build.py/main.js was silently
   ignored and the empty pill showed on every open, not just "Zapytaj o
   pakiet" ones. */
.modal-package-note:not([hidden]){
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: rgba(0, 113, 227, 0.08);
  color: var(--brand-blue-dark);
  border: 1px solid rgba(0, 113, 227, 0.18);
  border-radius: 980px;
  padding: 6px 14px;
  font-size: 12.5px;
  font-weight: 600;
  margin-bottom: var(--space-3);
}

/* Success state: once a submission succeeds, initAuditForm() (main.js)
   adds .is-submitted to #auditModal so only the checkmark/thank-you block
   (.form-success) shows - the generic intro (icon badge, package-context
   pill, title, lede) above the form must disappear along with the form
   itself, not just sit there next to "Dziękujemy...". Scoped to
   #auditModal specifically (not .modal-box in general) so it never
   touches the separate, always-visible heading/lede on the Kontakt page's
   own inline copy of this form. ".modal-scroll > .lede" (direct-child
   combinator) targets only the intro paragraph, not the near-identical
   .lede that lives INSIDE .form-success itself (the "Sprawdź folder
   SPAM..." text), which must stay visible. */
#auditModal.is-submitted .modal-badge,
#auditModal.is-submitted .modal-package-note,
#auditModal.is-submitted #auditTitle,
#auditModal.is-submitted .modal-scroll > .lede{
  display: none;
}

.modal-badge{
  width: 52px; height: 52px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--brand-blue), var(--brand-blue-light));
  display: flex; align-items: center; justify-content: center;
  margin-bottom: var(--space-4);
  box-shadow: 0 10px 26px -8px rgba(0,113,227,0.5);
}

/* ---------- Input icons (name / email / website / phone) ----------
   Fades out once the field is focused or already has text in it (toggled
   via .icon-hidden in main.js - :placeholder-shown alone can't drive this
   reliably since some of these inputs have no placeholder text). */
.input-icon-wrap{ position: relative; }
.input-icon-wrap .input-icon{
  position: absolute; left: 14px; top: 50%; transform: translateY(-50%);
  width: 18px; height: 18px;
  color: var(--c-text-tertiary);
  pointer-events: none;
  opacity: 1;
  transition: opacity var(--dur-fast) var(--ease-out);
}
.input-icon-wrap.icon-hidden .input-icon{ opacity: 0; }
/* Specificity has to beat .form-group input (same selector weight, but
   declared later in this file) - otherwise that rule's padding: 13px 16px
   silently wins and the icon ends up overlapping the field's text. Padding
   itself also collapses back to the normal 16px once the icon is hidden
   (focused or already has text) so typing doesn't leave a dead gap where
   the icon used to be - it and the reserved space disappear together. */
.form-group .input-icon-wrap input{ padding-left: 42px; transition: padding-left var(--dur-fast) var(--ease-out); }
.form-group .input-icon-wrap.icon-hidden input{ padding-left: 16px; }

/* ---------- Honeypot (spam-bot trap, invisible to real visitors) ----------
   Off-screen rather than display:none - some basic bots skip fields
   hidden that way but still fill in ones merely moved out of the
   viewport. Never shown, never focusable by a real (tab-navigating)
   visitor. */
.form-hp{
  position: absolute;
  left: -9999px;
  top: -9999px;
  width: 1px; height: 1px;
  overflow: hidden;
}

/* ---------- File upload (photos, max 3 files, 5MB each - enforced in
   main.js) ---------- */
.file-upload{ display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-3); }
.file-input{
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}
.file-upload-btn{
  display: inline-flex; align-items: center; gap: 8px;
  padding: 11px 18px;
  border-radius: var(--r-pill);
  border: 1.5px dashed var(--c-border-strong);
  background: var(--c-bg-alt);
  color: var(--c-text-secondary);
  font-size: 14px; font-weight: 600;
  cursor: pointer;
  transition: border-color var(--dur-fast), color var(--dur-fast), background var(--dur-fast), opacity var(--dur-fast);
}
.file-upload-btn:hover{ border-color: var(--brand-blue); color: var(--brand-blue); background: #fff; }
.form-group.has-error .file-upload-btn{ border-color: var(--error); color: var(--error); }
.file-input:focus-visible ~ .file-upload-btn{ outline: 2px solid var(--brand-blue); outline-offset: 2px; }
.file-upload-btn.is-disabled{ opacity: 0.55; cursor: not-allowed; pointer-events: none; }

.file-upload-list{
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-direction: column; gap: 8px;
  width: 100%;
}
.file-upload-chip{
  display: flex; align-items: center; gap: 10px;
  padding: 9px 10px 9px 12px;
  border-radius: var(--r-md);
  background: rgba(52,199,89,0.07);
  border: 1px solid rgba(52,199,89,0.24);
  animation: fileChipIn 320ms var(--ease-apple) both;
}
@keyframes fileChipIn{
  from{ opacity: 0; transform: translateY(-6px); }
  to{ opacity: 1; transform: none; }
}
.file-upload-chip-status{
  flex: none;
  width: 20px; height: 20px; border-radius: 50%;
  background: var(--success); color: #fff;
  display: flex; align-items: center; justify-content: center;
}
.file-upload-chip-text{ flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.file-upload-chip-name{
  font-size: 13.5px; font-weight: 600; color: var(--c-text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.file-upload-chip-meta{ font-size: 11.5px; color: var(--success); font-weight: 600; }
.file-upload-chip-remove{
  flex: none;
  display: flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; border-radius: 50%;
  background: rgba(0,0,0,0.06); color: var(--c-text-tertiary);
  border: none; cursor: pointer;
  transition: background var(--dur-fast), color var(--dur-fast);
}
.file-upload-chip-remove:hover{ background: rgba(220,38,38,0.14); color: #dc2626; }

.form-group{ margin-bottom: var(--space-5); position: relative; }
.form-group label{
  display: block; font-size: 13px; font-weight: 600;
  margin-bottom: var(--space-2); color: var(--c-text);
}
.form-group .req{ color: var(--brand-blue); }
.form-group input, .form-group textarea, .form-group select{
  width: 100%;
  padding: 13px 16px;
  border-radius: var(--r-sm);
  border: 1.5px solid var(--c-border-strong);
  background: var(--c-bg-alt);
  font-size: 15px;
  color: var(--c-text);
  transition: border-color var(--dur-fast), background var(--dur-fast);
}
.form-group textarea{ resize: vertical; min-height: 90px; }
.form-group select{
  padding-right: 40px;
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='18' height='18' viewBox='0 0 24 24' fill='none' stroke='%236e6e73' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
  background-size: 16px;
}
.form-group select:invalid{ color: var(--c-text-tertiary); }
.form-group input:focus, .form-group textarea:focus, .form-group select:focus{
  outline: none; border-color: var(--brand-blue); background-color: #fff;
}
.form-group input.is-invalid, .form-group textarea.is-invalid, .form-group select.is-invalid{ border-color: var(--error); }
.form-group input.is-valid, .form-group textarea.is-valid, .form-group select.is-valid{ border-color: var(--success); }
.form-group.is-hidden{ display: none; }
.field-error{
  display: none;
  font-size: 12.5px; color: var(--error); margin-top: 6px;
}
.form-group.has-error .field-error{ display: block; }
.form-submit-error{
  display: none;
  font-size: 13px; color: var(--error); font-weight: 500;
  background: rgba(255,59,48,0.08); border: 1px solid rgba(255,59,48,0.25);
  border-radius: var(--r-md); padding: 10px 14px; margin-bottom: var(--space-4);
}
.form-submit-error.is-visible{ display: block; }
.form-note{ font-size: 12px; color: var(--c-text-tertiary); margin-top: var(--space-4); line-height: 1.6; }
.form-success{
  display: none;
  text-align: center;
  padding: var(--space-6) 0;
}
.form-success.is-visible{ display: block; }
.form-success .icon-check{
  width: 64px; height: 64px; border-radius: 50%;
  background: rgba(52,199,89,0.12); color: var(--success);
  display: flex; align-items: center; justify-content: center;
  margin: 0 auto var(--space-5);
}
.audit-form.is-hidden{ display: none; }

/* ---------- Form consent checkboxes (newsletter / oferty) ---------- */
.form-check{
  display: flex; align-items: flex-start; gap: 10px;
  margin-bottom: var(--space-4);
}
.form-check input[type="checkbox"]{
  appearance: none; -webkit-appearance: none; -moz-appearance: none;
  flex: none; width: 19px; height: 19px; margin-top: 2px;
  border: 1.5px solid var(--c-border-strong); border-radius: 5px;
  background: var(--c-bg-alt); cursor: pointer;
  background-repeat: no-repeat; background-position: center; background-size: 13px;
  transition: background-color var(--dur-fast), border-color var(--dur-fast);
}
.form-check input[type="checkbox"]:checked{
  background-color: var(--brand-blue); border-color: var(--brand-blue);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='13' height='13' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6L9 17l-5-5'/%3E%3C/svg%3E");
}
.form-check input[type="checkbox"]:focus-visible{ outline: 2px solid var(--brand-blue); outline-offset: 2px; }
.form-check label{
  font-size: 12.5px; line-height: 1.55; color: var(--c-text-secondary);
  cursor: pointer; margin: 0; font-weight: 400;
}

/* ---------- Cookie banner & preferences ---------- */
.cookie-banner{
  position: fixed; left: var(--space-5); right: var(--space-5); bottom: var(--space-5);
  max-width: 620px; margin: 0 auto;
  background: rgba(29,29,31,0.92);
  backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px);
  color: #fff;
  border-radius: var(--r-lg);
  padding: var(--space-5) var(--space-6);
  z-index: var(--z-cookie);
  box-shadow: 0 20px 60px rgba(0,0,0,0.35);
  transform: translateY(140%);
  transition: transform var(--dur-slow) var(--ease-apple);
}
.cookie-banner.is-visible{ transform: none; }
.cookie-banner p{ font-size: 13.5px; line-height: 1.6; color: rgba(255,255,255,0.82); margin-bottom: var(--space-4); }
.cookie-banner a{ color: var(--brand-blue-light); text-decoration: underline; }
.cookie-actions{ display: flex; gap: var(--space-3); flex-wrap: wrap; }
.cookie-actions .btn{ flex: 1 1 auto; height: 40px; font-size: 13.5px; }
/* .cookie-banner has a dark background but isn't wrapped in .section-dark,
   so .btn-secondary was falling back to its light-mode style (near-black
   text on a near-black tint) - invisible against the dark banner. Scope
   the same light-on-dark treatment .section-dark already uses elsewhere. */
.cookie-banner .btn-secondary{ background: rgba(255,255,255,0.1); color: #fff; }
.cookie-banner .btn-secondary:hover{ background: rgba(255,255,255,0.18); }

.cookie-modal .modal-box{ max-width: 560px; }
.consent-row{
  display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-4);
  padding: var(--space-4) 0; border-bottom: 1px solid var(--c-border);
}
.consent-row:last-of-type{ border-bottom: none; }
.consent-row h4{ font-size: 15px; margin-bottom: 4px; }
.consent-row p{ font-size: 13px; color: var(--c-text-secondary); line-height: 1.5; }
.switch{ position: relative; width: 46px; height: 27px; flex: none; }
.switch input{ opacity: 0; width: 0; height: 0; position: absolute; }
.switch .track{
  position: absolute; inset: 0; background: #dcdce0; border-radius: 999px;
  transition: background var(--dur-base) var(--ease-apple); cursor: pointer;
}
.switch .track::before{
  content:''; position: absolute; width: 23px; height: 23px; left: 2px; top: 2px;
  background: #fff; border-radius: 50%; box-shadow: 0 1px 3px rgba(0,0,0,0.3);
  transition: transform var(--dur-base) var(--ease-apple);
}
.switch input:checked + .track{ background: var(--success); }
.switch input:checked + .track::before{ transform: translateX(19px); }
.switch input:disabled + .track{ opacity: 0.6; cursor: not-allowed; }
.cookie-modal-actions{ display:flex; gap: var(--space-3); margin-top: var(--space-6); flex-wrap: wrap; }
.cookie-modal-actions .btn{ flex: 1 1 auto; }

/* cookie settings floating re-open button */
.cookie-reopen{
  position: fixed; left: var(--space-5); bottom: var(--space-5); z-index: 400;
  width: 44px; height: 44px; border-radius: 50%;
  background: rgba(29,29,31,0.85); color:#fff; border:none;
  display:flex; align-items:center; justify-content:center;
  backdrop-filter: blur(10px);
  box-shadow: 0 8px 24px rgba(0,0,0,0.2);
  opacity: 0; pointer-events: none;
  transition: opacity var(--dur-base);
}
.cookie-reopen.is-visible{ opacity: 1; pointer-events: auto; }

/* ---------- Page header (subpages) ---------- */
.page-hero{
  padding: calc(var(--nav-h) + var(--space-9)) 0 var(--space-8);
  background: var(--c-dark-bg);
  color: #fff;
  position: relative;
  overflow: hidden;
}
.page-hero::before{
  content:'';
  position:absolute; inset:0;
  background: radial-gradient(ellipse 60% 80% at 50% 0%, rgba(0,113,227,0.35), transparent 65%);
  pointer-events:none;
}
.page-hero > .container{ position:relative; }
.page-hero .eyebrow{ color: var(--brand-blue-light); }
.page-hero h1{ color:#fff; max-width: 780px; }
.page-hero .lede{ margin-top: var(--space-5); max-width: 620px; }
.breadcrumb{ font-size:13px; color: rgba(255,255,255,0.5); margin-bottom: var(--space-4); }
.breadcrumb a{ color: rgba(255,255,255,0.75); }
.breadcrumb a:hover{ color:#fff; }

/* ---------- Kontakt page (contact info + inline audit-form card) ----------
   Two columns on desktop: a sticky info card (email/phone/contact person)
   next to a card wrapping an inline audit_form_fields() instance (see
   build.py's kontakt_body — same field set, same JS via .audit-form, just
   embedded directly on the page instead of behind the modal). Collapses to
   a single column - info card first, form below - once there's no room
   for both side by side. */
.contact-split{
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-8);
  align-items: start;
}
.contact-info-card{
  background: var(--c-bg-elevated);
  border: 1px solid var(--c-border);
  border-radius: var(--r-lg);
  padding: var(--space-7) var(--space-6);
  position: sticky;
  top: calc(var(--nav-h) + var(--space-6));
}
.contact-info-card h2{ font-size: 1.4rem; margin-bottom: var(--space-2); }
.contact-info-card > .lede{ margin-bottom: var(--space-6); }
.contact-info-list{ display: flex; flex-direction: column; gap: var(--space-5); }
.contact-info-item{ display: flex; align-items: flex-start; gap: var(--space-4); }
.contact-info-icon{
  flex: none;
  width: 44px; height: 44px;
  border-radius: 12px;
  background: linear-gradient(135deg, var(--brand-blue), var(--brand-blue-light));
  color: #fff;
  display: flex; align-items: center; justify-content: center;
}
.contact-info-item h3{ font-size: 15px; margin-bottom: 2px; }
.contact-info-item p{ font-size: 14.5px; color: var(--c-text-secondary); line-height: 1.5; }
.contact-info-item a{ font-size: 14.5px; font-weight: 600; color: var(--c-text); }
.contact-info-item a:hover{ color: var(--brand-blue); }
.contact-form-card{
  background: var(--c-bg-elevated);
  border: 1px solid var(--c-border);
  border-radius: var(--r-lg);
  padding: var(--space-7) var(--space-6);
  box-shadow: 0 2px 8px rgba(0,0,0,0.04), 0 20px 40px -20px rgba(0,0,0,0.08);
}
.contact-form-card h2{ font-size: 1.3rem; margin-bottom: var(--space-2); }
.contact-form-card > .lede{ margin-bottom: var(--space-6); }
@media (max-width: 860px){
  .contact-split{ grid-template-columns: 1fr; }
  .contact-info-card{ position: static; }
}

/* ---------- Utility: fade-in-on-scroll ---------- */
.reveal{
  opacity: 0; transform: translateY(28px);
  transition: opacity 700ms var(--ease-out), transform 700ms var(--ease-out);
}
.reveal.is-in{ opacity: 1; transform: none; }
.reveal-stagger > * { transition-delay: calc(var(--i, 0) * 80ms); }

/* ---------- Line-drawn micro animation (O nas) ---------- */
.line-draw{
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  animation: line-draw-in 1.6s var(--ease-out) forwards;
}
@keyframes line-draw-in{ to{ stroke-dashoffset: 0; } }

/* ---------- Generic content page prose ---------- */
.prose{ max-width: 760px; margin: 0 auto; }
.prose h2{ margin-top: var(--space-8); margin-bottom: var(--space-4); font-size: 1.6rem; }
.prose h3{ margin-top: var(--space-6); margin-bottom: var(--space-3); }
.prose p{ margin-bottom: var(--space-4); color: var(--c-text-secondary); line-height: 1.75; font-size: 16px; }
.prose ul{ margin-bottom: var(--space-4); padding-left: 1.2em; list-style: disc; color: var(--c-text-secondary); }
.prose li{ margin-bottom: var(--space-2); line-height: 1.7; }
.prose a{ color: var(--brand-blue); text-decoration: underline; }
.prose table{ width:100%; border-collapse: collapse; margin-bottom: var(--space-5); font-size: 14px; }
.prose th, .prose td{ text-align:left; padding: 10px 12px; border-bottom: 1px solid var(--c-border); }
.prose strong{ color: var(--c-text); }

/* ---------- 3D balloon accents (scrapbook-style contrast icons) ----------
   Glossy inflatable-look PNGs dropped into an otherwise flat/minimal design
   system on purpose — the point is the contrast between the two languages,
   not blending them in. Hue-rotate values below nudge a few source renders
   toward the brand blue/violet range; icons already in-family are left
   untouched so their natural gradient shading stays intact. */
.icon-3d{
  display: block;
  width: auto;
  pointer-events: none;
  user-select: none;
  transition: transform var(--dur-base) var(--ease-out);
}
.i-quatrefoil{ filter: hue-rotate(35deg) saturate(1.05) drop-shadow(0 12px 18px rgba(0,60,160,0.28)); }
.i-plain{ filter: drop-shadow(0 12px 18px rgba(0,40,120,0.24)); }

/* Promise tiles (4-up) — balloon icon replaces the flat gradient square */
.promise-icon{
  width: auto; height: 64px;
  display: flex; align-items: flex-end;
  margin-bottom: var(--space-4);
  background: none; border-radius: 0;
}
.promise-icon .icon-3d{ height: 100%; width: auto; }

/* O nas — Misja / Wizja icons */
.mv-card .icon-3d{ height: 56px; margin-bottom: var(--space-4); }

/* Historia — timeline markers become small balloon badges */
.tl-dot{
  background: none; border: none;
  width: 40px; height: 40px;
  left: 0; top: -8px;
  display: flex; align-items: center; justify-content: center;
}
.tl-dot .icon-3d{ height: 38px; width: auto; }

@media (max-width: 640px){
  .promise-icon{ height: 52px; }
}

/* ---------- Ambient floating balloons (page background) ----------
   A field of small, low-opacity balloon icons drifts up through the page
   at once, scattered across the full width, each on its own size/speed/
   sway/delay so the field feels alive rather than mechanically repeated.
   Fixed + negative z-index so it sits behind normal-flow content — visible
   in the plain white sections, naturally covered by cards, dark sections
   and the footer. Per-balloon --bx/--bw/--bdur/--bdelay/--sway/--bo custom
   properties are set inline by js/main.js at injection time (one layer per
   page, randomised on every load). */
.bg-balloons{
  position: fixed;
  inset: 0;
  z-index: -1;
  overflow: hidden;
  pointer-events: none;
}
.bg-balloon{
  position: absolute;
  top: 0;
  left: var(--bx, 50%);
  width: var(--bw, 10vmin);
  height: auto;
  transform: translate(-50%, 10vh) scale(0.85);
  opacity: 0;
  filter: saturate(0.55) blur(1px);
  animation: balloon-rise var(--bdur, 24s) linear infinite;
  animation-delay: var(--bdelay, 0s);
}
/* linear timing (not ease-in-out) is deliberate: an eased multi-keyframe
   animation decelerates at every keyframe boundary, which reads as the
   balloon repeatedly stalling on its way up. Linear keeps a constant,
   uninterrupted rise at all times; position keyframes below are spaced at
   an even vh-per-% rate so the constant time-rate also reads as a constant
   visual speed instead of speeding up/slowing down between segments.
   translateX only ever walks toward var(--sway) — never back the other
   way — so a balloon drifting left/right holds that one direction for its
   whole rise instead of zig-zagging; js/main.js randomises --sway's SIGN
   (not just magnitude) so different balloons drift different ways. Same
   idea for rotate: it turns one way, 0deg → var(--spin), never reversing. */
@keyframes balloon-rise{
  0%   { transform: translate(-50%, 112vh) translateX(0) rotate(0deg) scale(0.85); opacity: 0; }
  3%   { opacity: var(--bo, 0.08); }
  21%  { transform: translate(-50%, 74vh) translateX(calc(var(--sway, 3vw) * 0.2)) rotate(calc(var(--spin, 6deg) * 0.2)) scale(0.92); }
  41%  { transform: translate(-50%, 36vh) translateX(calc(var(--sway, 3vw) * 0.45)) rotate(calc(var(--spin, 6deg) * 0.45)) scale(0.98); }
  61%  { transform: translate(-50%, -2vh) translateX(calc(var(--sway, 3vw) * 0.7)) rotate(calc(var(--spin, 6deg) * 0.7)) scale(1.02); }
  81%  { transform: translate(-50%, -40vh) translateX(calc(var(--sway, 3vw) * 0.9)) rotate(calc(var(--spin, 6deg) * 0.9)) scale(1.06); }
  97%  { opacity: var(--bo, 0.08); }
  100% { transform: translate(-50%, -72vh) translateX(var(--sway, 3vw)) rotate(var(--spin, 6deg)) scale(1.1); opacity: 0; }
}
@media (prefers-reduced-motion: reduce){
  .bg-balloon{ animation: none; opacity: 0; }
}

/* ---------- Focus states (a11y) ---------- */
a:focus-visible, button:focus-visible, input:focus-visible, textarea:focus-visible{
  outline: 2px solid var(--brand-blue);
  outline-offset: 2px;
}

/* ---------- Scrollbar polish (webkit) ---------- */
::-webkit-scrollbar{ width: 12px; }
::-webkit-scrollbar-track{ background: transparent; }
::-webkit-scrollbar-thumb{ background: rgba(0,0,0,0.18); border-radius: 8px; border: 3px solid #fff; }

/* ---------- Print ---------- */
@media print{
  .navbar, .cookie-banner, .cookie-reopen, .modal-overlay{ display:none !important; }
}