/* ============================================================
   Design tokens (verbatim from DESIGN-SYSTEM.md §2–§6)
   ============================================================ */
:root{
  /* brand colors */
  --a-cream:#F1EDE7;
  --a-olive-black:#161810;
  --a-olive:#3A412A;
  --a-olive-deep:#232715;
  --a-ink-warm:#3F3D3B;
  --a-border-gray:#696969;
  --a-gray:#7A7772;
  --a-taupe:#D6D0C5;
  --a-lime:#BFF751;
  --a-white:#FFFFFF;
  --a-rust:#C7642D;
  /* measured directly on the reference site's benefits ticker dot (--green-yellow-2) —
     a light peach, not rust; used only for that one dot separator */
  --a-peach:#FFC8AA;

  /* spacing scale (8px based) */
  --sp-8:8px;
  --sp-16:16px;
  --sp-24:24px;
  --sp-40:40px;
  --sp-64:64px;
  --sp-80:80px;
  --sp-120:120px;

  --container-max:1440px;
  --a-shadow:24px 0px 64px 0px rgba(112,108,105,0.1);
}

/* ============================================================
   Reset / base
   ============================================================ */
*,*::before,*::after{ box-sizing:border-box; }
html{ scroll-behavior:auto; }
body{
  margin:0;
  background:var(--a-cream);
  color:var(--a-ink-warm);
  font-family:"Inter",system-ui,-apple-system,sans-serif;
  font-size:16px;
  line-height:1.7;
  -webkit-font-smoothing:antialiased;
}
img{ max-width:100%; display:block; }
a{ color:inherit; text-decoration:none; }
button{ font-family:inherit; cursor:pointer; border:0; background:none; padding:0; }
ul{ margin:0; padding:0; list-style:none; }
::selection{ background:var(--a-olive); color:var(--a-cream); }

.progress-bar{
  position:fixed;
  top:0;
  left:0;
  width:0%;
  height:5px; /* zmierzone na żywej archon.au (getComputedStyle .progress-bar): 5px, nie 3px */
  background:var(--a-olive-black);
  z-index:999;
  /* animowane przez JS jako `width` (layout), NIE `transform:scaleX()` — scaleX
     renderuje się przez kompozytor GPU jako przeskalowana tekstura, co przy
     ułamkowych współczynnikach dawało realnie widoczną, miękką/rozmytą krawędź
     paska (zrzut ekranu użytkownika, potwierdzone też własnym zrzutem); `width`
     idzie przez zwykły layout/paint, więc krawędź jest zawsze ostra. */
}

.skip-link{
  position:absolute;
  left:-9999px;
  top:0;
  z-index:999;
  background:var(--a-olive);
  color:var(--a-cream);
  padding:.75rem 1.25rem;
  border-radius:2px;
}
.skip-link:focus{ left:var(--sp-16); top:var(--sp-16); }

:focus-visible{
  outline:2px solid var(--a-rust);
  outline-offset:2px;
}

.container{
  /* archon.au's real .main-container has no max-width at all — verified live
     at 1440/2560/3840px (width always tracks the viewport minus a constant
     ~15px, never plateaus). Removed sitewide (header/footer included), not
     just on the treatment page — confirmed archon.au's own nav is uncapped
     too (.nav-container: 3825px at a 3840px viewport). */
  margin:0 auto;
  padding:0 max(20px, 5%);
}

/* ============================================================
   Typography (DESIGN-SYSTEM.md §3)
   ============================================================ */
h1,h2,h3{
  font-family:"Tenor Sans",Georgia,serif;
  font-weight:400;
  margin:0;
  text-wrap:balance;
}
.h-display{
  /* the reference site's real .h1-heading.max-width-medium (hero title), measured directly
     at multiple viewport widths — flat per-breakpoint values, not a fluid vw/clamp scale:
     64px above 767px, 48px at 480-767px, 38px at ≤479px. line-height is always 1.2x and
     letter-spacing always -0.04em of font-size at every breakpoint (76.8/57.6/45.6px and
     -2.56/-1.92/-1.52px respectively), so only font-size needs to change per breakpoint. */
  font-size:64px;
  line-height:1.2;
  letter-spacing:-0.04em;
}
@media (max-width:767px){
  .h-display{ font-size:48px; }
}
@media (max-width:479px){
  .h-display{ font-size:38px; }
}
.h-section{
  /* the reference site's real .heading.h2 (measured directly, not estimated): flat 30px
     at every viewport width — no clamp/vw scaling at all — font-weight 500
     (h1,h2,h3 default above is 400, so this must override it explicitly) */
  font-size:30px;
  font-weight:500;
  line-height:36px;
  letter-spacing:-1px;
  margin-bottom:var(--sp-24);
}
.h-hero{
  /* the reference site's real .heading.hero (measured directly): flat 60px, font-weight 500,
     line-height:1 (tracks font-size 1:1), letter-spacing -2px, margin-bottom 35px */
  font-size:60px;
  font-weight:500;
  line-height:1;
  letter-spacing:-2px;
  margin-bottom:35px;
}
.h-hero.center{ text-align:center; }
@media (max-width:479px){
  .h-hero{ font-size:42px; }
}
.h-quote{
  /* the reference site's real .heading.display (Booking Banner "Take a moment outside
     your usual."): flat 60px/waga 500/-1px above 991px, but grows to 72px on
     tablet and shrinks to 51px on mobile (measured directly incl. source media
     queries — a real, deliberate responsive quirk in the reference site, not a guess) */
  font-size:60px;
  font-weight:500;
  line-height:94px;
  letter-spacing:-1px;
  margin-top:20px;
  margin-bottom:52px;
}
@media (max-width:991px){
  .h-quote{ font-size:72px; line-height:71px; }
}
@media (max-width:479px){
  .h-quote{ font-size:51px; line-height:52px; }
}
/* the reference site's real color here is pure white (not the usual --a-cream text on
   black-olive sections) — max contrast against the parallax photo behind it */
#book .h-quote{ color:var(--a-white); }

/* the reference site's real legal/policy-page H1 (archon.au/privacy-policy,
   class "heading h1-split") — a distinct size from both .h-hero (64px) and
   .h-section (30px), measured directly: flat 35px/500/-1px/line-height 42px,
   no responsive scaling found in its own stylesheet. Shared template for every
   "regulamin"/"zasady" page, not just this one. */
.h-legal{
  font-family:"Tenor Sans",serif;
  font-weight:500;
  font-size:35px;
  line-height:42px;
  letter-spacing:-1px;
  /* no color set here — inherits the sitewide .section--cream h1/h2 rule
     (olive-black) below, the same established convention every other
     heading on a cream section already follows, rather than the raw
     archon.au measurement (ink-warm) that would fight it on specificity. */
  margin:0;
}
/* the reference site's real in-body subheading on that same page (a plain
   ".heading.h3"-classed <p>, not a real heading element there — reproduced
   here as a real <h2> for accessibility, same visual result): Inter 700 15px/
   21px, identical values to .treatment-card h3 elsewhere on this site — the
   same underlying archon.au component recurring in a third place. */
.legal-content h2{
  font-family:"Inter",sans-serif;
  font-weight:700;
  font-size:15px;
  line-height:21px;
  margin:20px 0 10px;
}
.legal-content h2:first-child{ margin-top:0; }
.legal-content p{
  /* color not set — inherits .section--cream's own ink-warm base text color */
  font-family:"Inter",sans-serif;
  font-weight:400;
  font-size:16px;
  line-height:27.2px;
  margin:0 0 10px;
}
.legal-content a{ color:inherit; text-decoration:underline; text-underline-offset:2px; }
.legal-content a:hover{ color:var(--a-rust); }
/* reuses .price-package-list's own hyphen-bullet pattern (rust "–" marker,
   list-style:none) for plain sub-lists, and adds a matching rust-numbered
   variant for the one real ordered list (Polityka Cookies) — same visual
   language, not a new one. */
.legal-content ul, .legal-content ol{
  margin:0 0 10px;
  padding-left:0;
  list-style:none;
}
.legal-content ul li, .legal-content ol > li{
  font-family:"Inter",sans-serif;
  font-weight:400;
  font-size:16px;
  line-height:27.2px;
  padding-left:22px;
  position:relative;
  margin-bottom:6px;
}
.legal-content ul li::before{ content:"–"; position:absolute; left:2px; color:var(--a-rust); }
.legal-content ol{ counter-reset:legal-ol; }
.legal-content ol > li{ counter-increment:legal-ol; }
.legal-content ol > li::before{ content:counter(legal-ol)"."; position:absolute; left:0; color:var(--a-rust); font-weight:600; }
.legal-content ol > li ul{ margin:6px 0 0; }

.eyebrow{
  font-family:"Inter",sans-serif;
  font-weight:600;
  font-size:.75rem;
  letter-spacing:0.5px;
  text-transform:uppercase;
  color:var(--a-gray);
}
/* the reference site's real eyebrow/paragraph color on black-olive sections is cream,
   not taupe (measured directly on .uppercase/.paragraph in the Gift Cards
   section) — taupe was an unmeasured guess, wrong everywhere it's used */
.section--olive .eyebrow{ color:var(--a-cream); }

.lede{
  font-family:"Inter",sans-serif;
  font-weight:400;
  font-size:16px;
  line-height:27.2px;
  /* the reference site's real paragraph has no character-based cap at all (max-width:none)
     — it just fills its 2fr grid column. 60ch was an unmeasured guess. */
  max-width:none;
  /* browsers give <p> a default 1em top+bottom margin — with no reset, that
     default TOP margin pushed the paragraph below the grid row's start line,
     visibly lower than the heading it's meant to align with (align-items:start
     aligns the grid ITEM, not the text inside it, so the item's own child
     margin still shows as a gap). the reference site's own paragraph has margin:0 top. */
  margin:0;
}

.nav-type{
  font-family:"Inter",sans-serif;
  font-weight:500;
  font-size:14px;
}

/* ============================================================
   Section background pairing (DESIGN-SYSTEM.md §7 hard rule)
   ============================================================ */
.section--cream{ background:var(--a-cream); color:var(--a-ink-warm); }
.section--cream h1, .section--cream h2{ color:var(--a-olive-black); }
.section--olive{ background:var(--a-olive-black); color:var(--a-cream); }
.section--olive h1, .section--olive h2{ color:var(--a-cream); }
.section--olive .lede{ color:var(--a-cream); }

.section-pad{ padding-top:var(--sp-80); padding-bottom:var(--sp-80); }
@media (max-width:640px){ .section-pad{ padding-top:var(--sp-64); padding-bottom:var(--sp-64); } }

/* ============================================================
   Buttons (DESIGN-SYSTEM.md §4)
   ============================================================ */
.abtn{
  display:inline-flex;
  align-items:center;
  justify-content:center;
  height:44px;
  padding:0 27px;
  font-family:"Inter",sans-serif;
  font-size:.875rem;
  font-weight:500;
  white-space:nowrap;
  border-radius:2px;
  border:0;
  transition:transform .3s cubic-bezier(.25,.46,.45,.94), box-shadow .3s cubic-bezier(.25,.46,.45,.94);
}
.abtn:hover{
  transform:translateY(-8px);
  box-shadow:0 9px 11px -2px rgba(0,0,0,.38);
}
@media (prefers-reduced-motion: reduce){
  .abtn{ transition:none; }
  .abtn:hover{ transform:none; }
}
.abtn.primary-black{ background:var(--a-olive-black); color:var(--a-white); }
.abtn.primary-olive{ background:var(--a-olive); color:var(--a-cream); border-radius:3px; padding:0 23px; }
.abtn.outline-dark{ background:transparent; color:var(--a-olive-deep); border:1px solid var(--a-olive-deep); border-radius:3px; padding:0 23px; }
.abtn.outline-light{ background:transparent; color:var(--a-white); border:1px solid var(--a-cream); }
.abtn.white{ background:var(--a-white); color:var(--a-olive-black); }
.abtn.gray{ background:var(--a-gray); color:var(--a-white); }
.abtn.outline-gray{ background:transparent; color:var(--a-ink-warm); border:1px solid var(--a-border-gray); }

/* ============================================================
   Shapes
   ============================================================ */
.arch-img{
  border-radius:150px 150px 20px 20px;
  overflow:hidden;
}

.ph-gradient{
  background:
    radial-gradient(circle at 30% 20%, #4a5033, transparent 60%),
    linear-gradient(160deg,#3a412a,#161810 70%);
  position:relative;
}
.ph-gradient::after{
  content:"";
  position:absolute; inset:0;
  background-image:repeating-linear-gradient(115deg, rgba(191,247,81,0.05) 0 2px, transparent 2px 16px);
}
.ph-gradient.warm{
  background:
    radial-gradient(circle at 70% 30%, #5b4a2a, transparent 55%),
    linear-gradient(200deg,#3a412a,#161810 75%);
}

/* ============================================================
   Nav
   ============================================================ */
/* Runda 165: header.html (Runda 164) is injected into a plain wrapper
   <div data-partial="...">, since <header> and .mobile-drawer are two sibling
   top-level elements that need one shared injection point — but that wrapper
   quietly broke .site-nav's position:sticky below. Root cause: sticky needs
   its CONTAINING BLOCK (nearest ancestor box) to be taller than itself for
   there to be any scroll distance to "stick" through — before Runda 164,
   that containing block was <body> (thousands of px tall); after wrapping,
   it became this wrapper div, whose own height collapses to fit its content
   (~80px, same as .site-nav itself, since .mobile-drawer contributes 0px
   while [hidden]) — zero room to stick, so it never visibly did. display:contents
   removes the wrapper's own box from rendering entirely, so .site-nav and
   .mobile-drawer behave exactly as if they were direct children of <body>
   again (their real, original DOM position) — scoped to div[data-partial]
   specifically (a plain <div>) so it does NOT reach #promo (<section>) or
   the footer (<footer>), which also carry data-partial but must stay real,
   styled boxes. */
div[data-partial]{ display:contents; }

.site-nav{
  position:sticky;
  top:0;
  z-index:100;
  background:var(--a-cream);
  /* no border-bottom — the reference site's own nav has none (measured:
     border/box-shadow both "none" on every nav-related element), this was
     an unmeasured guess, removed on request */
}
.nav-row{
  display:flex;
  align-items:center;
  justify-content:space-between;
  /* floor gap so the logo and nav group never crowd together as the viewport
     narrows toward the mobile breakpoint — justify-content:space-between alone
     lets them touch once combined content exactly fills the row */
  gap:24px;
  height:80px;
}
.logo{
  display:inline-flex;
  align-items:center;
  flex-shrink:0;
}
.logo-mark{ height:44px; width:auto; }

.nav-right{ display:flex; align-items:center; gap:12px; }

.nav-links{
  display:flex;
  align-items:center;
  gap:0;
}
.nav-links > li{ position:relative; }
.nav-link{
  display:flex;
  align-items:center;
  gap:.3rem;
  padding:.5rem 7px;
  color:var(--a-olive-black);
  line-height:1;
  white-space:nowrap;
  transition:color .2s;
}
/* desktop nav toggles fill the full 80px header height (matches the reference site's .dropdown-menu-toggle)
   so an open mega-panel's top:100% lands exactly at the header's bottom edge, not mid-header */
.nav-links > li > .nav-link{ height:80px; padding:0 7px; }
.nav-link:hover{ color:var(--a-rust); }
.nav-link[aria-expanded="true"]{ box-shadow:inset 0 -4px 0 -2px var(--a-olive); }
.nav-link .caret{ width:10px; height:6px; flex-shrink:0; transition:transform .15s ease; opacity:.62; }
.nav-link[aria-expanded="true"] .caret{ transform:rotate(180deg); }

.nav-ctas{ display:flex; align-items:center; gap:10px; }

.hamburger{
  display:none;
  background:none;
  border:0;
  padding:.4rem;
}
.hamburger span{
  display:block;
  width:22px;
  height:2px;
  background:var(--a-olive-black);
  margin:5px 0;
  transition:transform .2s ease, opacity .2s ease;
}
.hamburger[aria-expanded="true"] span:nth-child(1){ transform:translateY(7px) rotate(45deg); }
.hamburger[aria-expanded="true"] span:nth-child(2){ opacity:0; }
.hamburger[aria-expanded="true"] span:nth-child(3){ transform:translateY(-7px) rotate(-45deg); }

/* mega menu — panel of side-by-side columns (one per category), left-aligned under its toggle */
.mega-panel{
  position:absolute;
  top:100%;
  left:0;
  display:flex;
  gap:32px;
  background:var(--a-white);
  box-shadow:0 16px 20px -4px rgba(121,120,118,.15);
  border-radius:0 0 5px 5px;
  padding:20px 48px 36px;
}
.mega-panel[hidden]{ display:none; }
/* horizontal position is clamped within the viewport dynamically in js/main.js —
   a wide 3-column panel would otherwise overflow past the screen edge depending on
   where its toggle sits in the nav */
.mega-group{ width:220px; flex-shrink:0; }
.mega-group .cat{
  font-family:"Inter",sans-serif;
  font-size:10px;
  font-weight:600;
  letter-spacing:1px;
  text-transform:uppercase;
  color:var(--a-gray);
  padding-top:20px;
  padding-bottom:10px;
  margin-bottom:6px;
  border-bottom:1px solid rgba(122,119,114,.41);
}
.mega-group ul{ display:flex; flex-direction:column; }
.mega-group a{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:8px;
  padding:4px 0;
  font-size:14px;
  font-weight:500;
  line-height:1.3;
  color:var(--a-olive-black);
  transform:translateX(0);
  transition:color .2s, transform .2s ease;
}
.mega-group a:hover{ color:var(--a-rust); transform:translateX(3px); }
/* small reveal arrow, matches the reference site's mega-menu link interaction (fades in + slides right on hover) */
.mega-group a::after{
  content:"";
  flex-shrink:0;
  width:14px;
  height:10px;
  background-color:currentColor;
  -webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 12'%3E%3Cpath d='M15 6H1M10 11l5-5M10 1l5 5' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat center / contain;
  mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 12'%3E%3Cpath d='M15 6H1M10 11l5-5M10 1l5 5' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat center / contain;
  opacity:0;
  transform:translateX(0);
  transition:opacity .2s ease, transform .2s ease;
}
.mega-group a:hover::after{
  opacity:1;
  transform:translateX(4px);
}

/* breakpoint measured against the real content width of the desktop nav (logo +
   6 links + 2 CTA buttons + the .nav-row floor gap, ~892px unconstrained) — below
   ~991px the row runs out of room and would overflow/compress, so the switch to
   hamburger happens with a small margin (~33px) to spare rather than at the exact
   pixel it starts breaking, without giving up more horizontal-nav range than needed */
@media (max-width:1024px){
  .nav-links, .nav-ctas .abtn.outline-dark{ display:none; }
  .hamburger{ display:block; }
  /* dock "Rezerwuj online" right next to the hamburger instead of letting
     justify-content:space-between spread it out in the middle of the row */
  .nav-row{ justify-content:flex-start; gap:12px; }
  .logo{ margin-right:auto; }
}

/* mobile drawer */
.mobile-drawer{
  position:fixed;
  top:80px;
  left:0;
  right:0;
  bottom:0;
  background:var(--a-cream);
  z-index:90;
  padding:1.5rem max(20px, 5%);
  overflow-y:auto;
  transform:translateY(-100%);
  transition:transform .3s ease;
}
.mobile-drawer.open{ transform:translateY(0); }
.mobile-drawer[hidden]{ display:none; }
.mobile-drawer nav ul{ display:flex; flex-direction:column; }
/* top-level rows: 30px vertical padding + hairline divider, measured 1:1 from the reference site's mobile nav
   (.dropdown-menu-toggle padding:30px 0, .dropdown-menu border-bottom:1px solid rgba(202,199,192,.16)) */
.mobile-drawer nav > ul > li{ border-bottom:1px solid rgba(202,199,192,.16); }
.mobile-drawer nav > ul > li:last-of-type{ border-bottom:none; }
.mobile-drawer .nav-link{
  width:100%;
  justify-content:space-between;
  padding:30px 0;
  font-size:16px;
  line-height:24px;
  letter-spacing:.5px;
  text-transform:capitalize;
}
/* the visible label is a nested .nav-type span, whose own global rule (font-size:14px,
   used by the desktop nav) otherwise wins over the 16px set above — measured directly
   against the reference site's real ".dropdown-menu-text" (font-size:16px, line-height:24px,
   letter-spacing:0.5px, weight:500), so this must match, not inherit the desktop value */
.mobile-drawer .nav-link .nav-type{ font-size:inherit; }
.mobile-drawer summary.nav-link{ cursor:pointer; list-style:none; }
.mobile-drawer summary.nav-link::-webkit-details-marker{ display:none; }
.mobile-drawer .nav-link .caret{ opacity:1; }
.mobile-drawer details[open] > summary .caret{ transform:rotate(180deg); }
.mobile-drawer details ul{ padding-left:1rem; padding-bottom:24px; gap:.75rem; }
/* sub-items must read as clearly smaller than the 16px top-level rows they expand from,
   so the hierarchy (main item → category) feels natural at a glance */
.mobile-drawer details ul a{ font-size:14px; font-weight:500; color:var(--a-ink-warm); transition:color .2s; }
.mobile-drawer details ul a:hover{ color:var(--a-rust); }
.mobile-drawer .cat-label{
  font-family:"Inter",sans-serif;
  font-size:10px;
  font-weight:600;
  letter-spacing:1px;
  text-transform:uppercase;
  color:var(--a-gray);
  margin-top:.5rem;
}
.mobile-drawer .cat-label:first-child{ margin-top:0; }
/* three CTAs sit in a single row (matches the reference site's real mobile menu), not stacked —
   each button shares the row equally instead of taking a fixed width. font-size:14px
   and height:43px are the reference site's real measured values for this button row, kept
   identical here; only the horizontal padding is reduced from their 18-23px so the
   longer Polish button labels ("Rezerwuj online") still fit one row without wrapping */
.mobile-drawer .drawer-ctas{ display:flex; flex-direction:row; gap:8px; margin-top:2.5rem; }
.mobile-drawer .abtn{ flex:1; width:auto; padding:0 6px; }

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

/* ============================================================
   Hero
   ============================================================ */
.hero{
  position:relative;
  min-height:620px;
  color:var(--a-cream);
  overflow:hidden;
  background:var(--a-olive-black);
}
.hero-video{
  position:absolute; inset:0;
  width:100%; height:100%;
  object-fit:cover;
}
.hero-bg{
  position:absolute; inset:0;
  background:linear-gradient(180deg, rgba(22,24,16,.35), rgba(22,24,16,.85));
}
.hero-content{
  position:absolute;
  inset:0;
  max-width:var(--container-max);
  margin:0 auto;
  display:flex;
  align-items:center;
  padding:max(20px, 5%);
}
.hero-content-inner{ width:100%; }
.hero-content h1{ max-width:720px; }
.hero-actions{ display:flex; gap:1rem; margin-top:var(--sp-24); flex-wrap:wrap; }

/* ============================================================
   Marquee — the reference site's real ".text-rotator" is scroll-linked, not a
   self-playing timed loop (measured directly: position is frozen while the
   page is still, only ever moves in response to a real scroll event, in
   both directions) — driven by js/main.js, not a CSS @keyframes animation.
   ============================================================ */
.marquee{
  overflow:hidden;
  /* the reference site's real .text-rotator-first: padding-top/bottom 20px */
  padding:20px 0;
}
/* tło paska na /o-nas — zmierzone bezpośrednio NA TEJ podstronie archon.au
   (.section.dark-cream, rgb(214,208,197)) — inne niż tło paska na stronie głównej
   (tam cream), bo archon reużywa tego komponentu z różnym tłem per strona. */
.o-nas-marquee{ background:var(--a-taupe); }
.marquee-track{
  display:flex;
  align-items:center;
  width:max-content;
}
.marquee-phrase{
  font-family:"Inter",sans-serif;
  font-weight:600;
  text-transform:uppercase;
  color:var(--a-gray);
  white-space:nowrap;
  /* the reference site's real .text-rotator font-size is viewport-relative, with 3
     distinct breakpoints (measured directly in source media queries) —
     counter-intuitively LARGER on tablet than on desktop */
  font-size:1vw;
}
@media (min-width:1440px){
  .marquee-phrase{ font-size:.7vw; }
}
@media (max-width:991px){
  .marquee-phrase{ font-size:2vw; }
}
@media (max-width:479px){
  .marquee-phrase{ font-size:3vw; }
}
.marquee-dot{
  /* the reference site's real .start-icon: 4x4px circle, 20px margin each side */
  width:4px;
  height:4px;
  border-radius:100%;
  background:var(--a-peach);
  margin:0 20px;
  flex:0 0 auto;
}

/* ============================================================
   Philosophy — treatments row (measured 1:1 from the reference site's .homegallery / .tricks-slider)
   ============================================================ */
/* Scroll-jack: pins the row in place (vertically centered in the viewport,
   never above the nav) while vertical scroll drives it sideways, revealing a
   few extra cards before the page continues down. Height/top/margin of these
   two are all set by JS (main.js) — see the comment there for why. */
.trick-pin-outer{
  position:relative;
}
.trick-pin-inner{
  position:sticky;
  top:80px; /* JS overrides this to center the row; this is just the no-JS fallback */
}
.trick-wrap{
  margin-top:var(--sp-64);
}
.trick-row{
  display:flex;
  gap:1em;
  overflow-x:auto;
  /* left gutter matches the heading above (site container's own gutter) — but
     it's real padding on the scrollable element itself, not a margin on the
     outer wrapper, so it scrolls away with everything before it and never
     reappears once the user scrolls. the reference site itself has no right padding
     (cards run flush to the true viewport edge) — deliberate deviation here,
     requested in chat, so the last card gets breathing room once fully
     scrolled instead of touching the edge; mirrors the left gutter formula.
     No longer adds a centering offset past --container-max — .container
     itself has no max-width any more (Round 48), so this row's gutter just
     matches .container's own padding directly, same as everything else. */
  padding-left:max(20px, 5%);
  padding-right:max(20px, 5%);
  padding-bottom:var(--sp-16);
  cursor:grab;
  user-select:none;
  -webkit-user-select:none;
  /* hide native scrollbar — this row is driven by drag-to-scroll, not a visible track */
  scrollbar-width:none;
  -ms-overflow-style:none;
}
.trick-row::-webkit-scrollbar{ display:none; }
.trick-row.dragging{ cursor:grabbing; }
.trick-card{
  flex:0 0 auto;
  /* base 22% is the real value measured on the reference site (see bounds below) — JS
     (main.js, layoutCardHalfCut) overrides this with a nudged px value so
     the row starts scrolled to 0 with an exact half-card cut off at the
     right edge, never a random sliver — the signal that there's more to
     scroll. Deliberate deviation from the reference site, requested in chat; the
     nudge is small enough (a few px) that it doesn't visibly depart from
     the measured proportions. Deliberately no scroll-snap to hold this
     same fraction at every later scroll position too — tried that
     (scroll-snap-type/-align), but it broke free dragging (settled with a
     visible jump instead of following the cursor) and ate the left gutter
     (snap-align:start pulled the resting scroll position past the padding,
     flush to the browser edge, inconsistent with the rest of the page).
     Reverted; the guarantee only holds for the first view now, which is
     also where it matters most. */
  width:var(--tc-card-w, 22%);
  /* bounds measured directly off the reference site across viewport widths, not guessed:
     314–315px is the real peak card width (occurs ~1700px viewport — beyond
     .homegallery's own max-width:1600px cap, its padding keeps growing with the
     ever-wider viewport while the box itself stays capped, so the card actually
     *shrinks* again past that point); 173px is their real width at 320px
     viewport (the narrowest common device, using their ≤479px 60% rule) —
     also the safety clamp on the JS-computed --tc-card-w above. */
  min-width:173px;
  max-width:315px;
  height:50vh;
  position:relative;
  overflow:hidden;
  border-radius:150px 150px 20px 20px;
  transition:.5s;
}
.trick-card:hover{
  /* the reference site also lifts translateY(-30px) here — dropped on explicit request
     for this site; the arch-inversion + darkening overlay hover stays */
  border-radius:20px 20px 150px 150px;
}
/* marks where the next treatment category starts (requested in chat, not on
   the reference site) — a thin rule, same weight/color/opacity as .progress-tick
   below (the matching mark on the progress bar's category map) and as
   .divider-rule elsewhere, just vertical. A flex sibling of .trick-card
   rather than a pseudo-element on it, so it isn't clipped by the card's
   own overflow:hidden, and so the half-cut/scroll-jack math (which only
   ever queries .trick-card) never has to account for it. */
.trick-cat-divider{
  flex:0 0 auto;
  align-self:stretch;
  width:1px;
  margin:0 1.125em; /* +50% again on request, was .75em (originally .5em) */
  background:var(--a-gray);
  opacity:.4;
}
.trick-img{
  /* 200% width (matches the reference site's .parallaxhero exactly) gives the image room
     to slide via JS translateX without ever exposing an edge — the visible
     100%-wide window always stays inside this oversized image. right must stay
     auto (not part of the inset shorthand) so left:0 + width:200% aren't
     over-constrained by an implicit right:0. */
  position:absolute;
  top:0; left:0; right:auto; bottom:0;
  z-index:1;
  width:200%;
  max-width:none;
  height:100%;
  object-fit:cover;
  -webkit-user-drag:none;
  pointer-events:none;
}
.trick-link{
  position:absolute;
  inset:0;
  z-index:2;
  display:flex;
  align-items:center;
  justify-content:center;
  transition:background-color .5s;
  /* this <a> sits on top of the whole card (z-index above the image), so it's
     what actually receives the mousedown that starts a drag-scroll — without
     this, the browser's native "drag this link" gesture pre-empts our JS drag
     the moment the pointer moves, so dragging only worked from the gaps
     between cards (not covered by any link) instead of the cards themselves */
  -webkit-user-drag:none;
  user-select:none;
}
.trick-link:hover{ background-color:rgba(33,34,31,.31); }
.trick-cap{
  margin:0;
  padding:0 10px;
  max-width:100%;
  /* flex items default to min-width:auto (the width of their widest unbreakable
     content), which silently overrides max-width/overflow-wrap and lets the
     caption overflow its flex parent (.trick-link) instead of shrinking */
  min-width:0;
  text-align:center;
  font-family:"Tenor Sans",serif;
  font-weight:400;
  line-height:1;
  letter-spacing:-1px;
  text-transform:capitalize;
  color:var(--a-white);
  font-size:2rem;
  /* some real treatment names join two words with "/" (e.g. "Peelingi
     medyczne/chemiczne") with no space either side — browsers don't reliably
     treat "/" as a line-break opportunity, so that whole run can overflow the
     narrow card on mobile widths unless breaking is explicitly allowed */
  overflow-wrap:break-word;
}
/* category label + progress "map" (requested in chat, not on the reference site):
   one small label per category (Zabiegi Hi-Tech / Iniekcyjne / Manualne —
   the same 3 groups as the "Zabiegi" nav menu), each a <button> fixed at
   the start of its own segment of the bar below (small left margin, not
   flush with the tick), styled with the same eyebrow type and neutral gray
   already used elsewhere. Clicking one scrolls the row to that category
   (main.js) — same rust hover as every other clickable text link
   sitewide (§8 of DESIGN-SYSTEM.md). The label matching whichever card is
   centered in the viewport is highlighted (full opacity); the other two
   stay dimmed, same 40% as the category dividers between cards and the
   tick marks on the bar itself — one consistent "dimmed unless
   active/present" visual language tying all three (divider, tick, label)
   together, not three unrelated devices. */
.trick-cat-label-wrap{
  /* same width/centering formula as .progress-wrap directly below — the
     labels' 0–100% positioning has to share the bar's own visible footprint,
     not the full-bleed row, or they land outside where the bar actually is.
     On request: matches .container's own gutter exactly (width/max-width
     via calc instead of padding — .progress-ticks below is `inset:0`, which
     ignores an ancestor's own padding, so the gutter has to come from a
     narrower width here, not from padding, or ticks/labels would spill past
     the visible bar). */
  width:calc(100% - 2 * max(20px, 5%));
  margin:var(--sp-16) auto 0;
  position:relative;
  height:1em;
}
.trick-cat-label{
  /* <button> reset — browser defaults (border/background) otherwise leak
     through, see CLAUDE.md's note on this exact class of bug. NOT `font:
     inherit` — that shorthand resets font-family/size/weight too, and
     because this rule comes after .eyebrow in the stylesheet it silently
     overrode .eyebrow's explicit values with the button's plain default
     font instead of the intended small-caps label look. */
  background:none;
  border:none;
  cursor:pointer;
  position:absolute;
  top:0;
  margin:0;
  margin-left:var(--sp-8); /* breathing room from its segment's own start/tick */
  padding:0;
  white-space:nowrap;
  /* left (JS-set %) marks its segment's start, not its center — this label
     reads left-to-right from where its category begins on the bar */
  opacity:.4;
  transition:opacity .2s, color .2s;
}
.trick-cat-label.is-active{ opacity:1; }
.trick-cat-label:hover{ color:var(--a-rust); }
@media (max-width:767px){
  /* 3 fixed labels this close together overlap once "Zabiegi Iniekcyjne"/
     "Zabiegi Manualne" are wide enough relative to the narrower row — show
     only the active one; the tick marks still carry the segment map. */
  .trick-cat-label:not(.is-active){ display:none; }
}
.progress-wrap{
  /* on request: same viewport-width + gutter formula as .trick-cat-label-wrap
     above (which itself matches .container) — always full viewport width
     with the same margins as the rest of the page's content, not a fixed 80%.
     No longer capped at --container-max — .container itself has no
     max-width any more (Round 48), so this stays consistent with it. */
  width:calc(100% - 2 * max(20px, 5%));
  margin:var(--sp-16) auto 0;
  position:relative;
}
.progress{
  background-color:rgba(0,0,0,.09);
  width:100%;
  height:1.5px;
  position:relative;
  overflow:hidden;
}
.progress-fill{
  background:var(--a-ink-warm);
  width:0%;
  height:100%;
  position:relative;
}
.progress-ticks{
  position:absolute;
  inset:0;
  pointer-events:none;
}
.progress-tick{
  position:absolute;
  top:50%;
  transform:translate(-50%, -50%);
  width:1px;
  height:8px;
  background:var(--a-gray);
  opacity:.4; /* same weight as .trick-cat-divider — same mark, two places */
}
/* Below 992px, height switches from vh to aspect-ratio (0.64, the real desktop
   width/height ratio measured live at 1440px: 286.6/450) so it tracks the
   card's own WIDTH instead of the viewport's height. A vh-based height and a
   %-based width move independently — on a phone or tablet held in LANDSCAPE
   (viewport height shrinks, width grows) that combination flipped the cards
   from tall arches into short, wide rectangles (measured: 812x375 landscape
   gave ratio 1.29, i.e. wider than tall, vs desktop's 0.64). aspect-ratio
   keeps the same proportions as desktop in every orientation, portrait or
   landscape, without needing separate per-orientation rules. */
@media (max-width:991px){
  .trick-card{ width:var(--tc-card-w, 38%); height:auto; aspect-ratio:0.64; }
  .trick-cap{ font-size:2.4rem; }
}
@media (max-width:767px){
  .trick-cap{ font-size:1.6rem; }
}
@media (max-width:479px){
  .trick-card{
    width:var(--tc-card-w, 60%);
    /* on request: 2.5 cards visible on mobile instead of the reference-site-
       matched 1.5 (see main.js layoutCardHalfCut) — narrower cards than the
       173px reference-site minimum below need their own, smaller floor here. */
    min-width:100px;
  }
  .trick-cap{ font-size:1.4rem; }
}

/* ============================================================
   Rekomendacje sezonowe (dawniej "RX Facials")
   Reuses .treatment-cards/.treatment-card verbatim — the SAME component
   already built for the S/M/L cards on the strona zabiegu — but that shared
   component's own base background/:hover (transparent at rest, lifts
   translateY(-8px) + white tint + shadow on hover) was itself measured off a
   DIFFERENT archon.au card ("15/30/1-Hour Block" cards, per the comment on
   .treatment-cards below) that happens to reuse the same Webflow class name.
   THIS section's real archon.au component (.treatment-cards-wrapper.dark) has
   its own, different real values, confirmed via genuine synthetic-pointer
   :hover (a plain CSS :hover, not IX2 — dispatched JS mouseenter events don't
   trigger it, which is why an earlier pass here missed it): rgba(58,56,52,.2)
   background AT REST (not just on hover), fading to fully transparent on
   hover with border-radius softening 0→4px — no lift, no shadow, no tint.
   All scoped to .section--olive so the S/M/L cards (always in a
   .section--cream context) keep their own, untouched behavior. Price color
   also deviates here on request (rust, not archon's real white/the old lime). */
.section--olive .treatment-card-price{ color:var(--a-rust); }
.section--olive .treatment-card{
  background:rgba(58,56,52,.2);
  border-radius:0;
}
.section--olive .treatment-card:hover{
  background:transparent;
  border-radius:4px;
  transform:none;
  box-shadow:none;
}
/* archon.au's real margin above this specific card row (measured directly on
   its "winter recommendations" section: 100px) — .treatment-cards' own 24px
   was measured off a different archon.au component (see comment on that rule)
   that happens to share the same Webflow class name; scoped the same way as
   the price override above so the S/M/L cards keep their own 24px. */
.section--olive .treatment-cards{ margin-top:100px; }

/* ============================================================
   Testimonials
   ============================================================ */
.testimonial-section .h-section{
  text-align:center;
}
.t-shell{
  display:flex;
  align-items:center;
  justify-content:center;
  gap:37px;
}
.t-arrow{
  flex:0 0 auto;
  width:55px; height:55px;
  display:flex;
  align-items:center;
  justify-content:center;
  background:transparent;
  border:0;
  padding:0;
  color:var(--a-cream);
  cursor:pointer;
}
.t-arrow:hover{ color:var(--a-taupe); }
.t-arrow-icon{ width:22px; height:16px; }
.t-mask{
  width:800px;
  max-width:100%;
  overflow:hidden;
  position:relative;
  transition:height .3s ease;
}
.t-track{
  display:flex;
  align-items:flex-start; /* flex row's default cross-axis stretch was forcing every
    .t-slide to the height of the TALLEST slide, so main.js's per-slide
    mask.style.height = slides[current].offsetHeight always read that same stretched
    height regardless of which slide was current — a short review sat top-aligned in
    a box sized for the longest one, leaving a gap before .t-dots/.t-cta below. Each
    slide now reports its own intrinsic height. */
  width:700%;
  transition:transform .5s ease;
}
.t-slide{
  flex:0 0 calc(100% / 7);
  width:calc(100% / 7);
  display:flex;
  flex-direction:column;
  align-items:center;
  padding-top:70px;
  text-align:center;
}
.t-slide blockquote{
  margin:0 0 36px;
  font-family:"Inter",sans-serif;
  font-weight:400;
  font-size:16px;
  line-height:30px;
  color:var(--a-cream);
}
.testimonial-name{
  margin:0 0 20px;
  font-family:"Inter",sans-serif;
  font-weight:600;
  font-size:12px;
  letter-spacing:.5px;
  text-transform:uppercase;
  color:var(--a-cream);
}
.t-stars{
  display:flex;
  gap:4px;
  margin-bottom:5px;
  color:var(--a-white);
}
.t-stars svg{ width:16px; height:20px; }
.t-source{
  margin:0;
  font-family:"Inter",sans-serif;
  font-weight:600;
  font-size:12px;
  line-height:24px;
  color:var(--a-cream);
}
.t-dots{
  display:flex;
  align-items:center;
  justify-content:center;
  gap:12px;
  margin-top:22px;
}
.t-cta{
  display:flex;
  align-items:center;
  justify-content:center;
  gap:16px;
  margin-top:40px;
}
.t-dot{
  width:7px; height:7px;
  border-radius:50%;
  background:rgba(255,255,255,.4);
  border:0;
  padding:0;
  cursor:pointer;
}
.t-dot.active{ background:#fff; }

/* light ("cream") variant of the testimonial component — archon.au's real
   .section.testimonial.cream (measured live, getComputedStyle): heading/quote/
   name/source all rgb(63,61,59) = --a-ink-warm, stars rgb(58,65,42) = --a-olive.
   Their arrows/dots use white icons + filter:invert(1) to read dark on a light
   section (measured: .dark wrapper classes carry that filter) — we reuse our
   own currentColor-based icons instead (simpler, same convention already used
   for the mega-menu arrow) and set the color directly rather than inverting. */
.section--cream .testimonial-section .h-section{ color:var(--a-ink-warm); }
.section--cream .t-slide blockquote{ color:var(--a-ink-warm); }
.section--cream .testimonial-name{ color:var(--a-ink-warm); }
.section--cream .t-source{ color:var(--a-ink-warm); }
.section--cream .t-stars{ color:var(--a-olive); }
.section--cream .t-arrow{ color:var(--a-olive-black); }
.section--cream .t-arrow:hover{ color:var(--a-rust); }
.section--cream .t-dot{ background:rgba(22,24,16,.3); }
.section--cream .t-dot.active{ background:var(--a-olive-black); }

/* ============================================================
   Contact
   ============================================================ */
#contact .eyebrow{ text-align:center; }
.contact-grid{
  display:grid;
  grid-template-columns:repeat(3,1fr);
  gap:var(--sp-40);
  /* the reference site's real gap between "Get in touch" and the 3 contact columns
     (.spacer.xlarge, measured directly) is 150px, not the 40px generic token */
  margin-top:150px;
}
.contact-box{
  border:1px solid var(--a-gray);
  padding:1.25rem;
  display:flex;
  flex-direction:column;
}
.contact-box h3{
  font-family:"Inter",sans-serif;
  font-weight:600;
  font-size:1rem;
  color:var(--a-cream);
}
.contact-box p{ font-size:.9rem; color:var(--a-taupe); margin-top:.6rem; flex:1; }
.contact-box .abtn{ margin-top:1.25rem; width:100%; }
@media (max-width:800px){ .contact-grid{ grid-template-columns:1fr; gap:var(--sp-24); } }

/* ============================================================
   Gift cards / Booking banner
   ============================================================ */
/* the reference site's real gap between the divider rule and the 2-column content
   below it in this section is 55px (measured directly), not the shared
   .title-rule 40px used elsewhere — scoped here since only this instance
   is verified, not Philosophy/RX Facials */
#gift-card .title-rule{ margin-bottom:55px; }

.banner-cta{
  text-align:center;
  position:relative;
  /* the reference site's real .main-container.display: fixed 600px height, flex-
     centered content — flat across every breakpoint (measured directly,
     confirmed in source media queries too) — not a padding-driven section */
  height:600px;
  display:flex;
  flex-direction:column;
  align-items:center;
  justify-content:center;
}
/* no separate button margin — the h-quote heading's own 52px margin-bottom
   already accounts for the full gap to the button (the reference site's button-wrapper
   itself has margin:0) */

.fine-print{
  /* the reference site's real .paragraph.small: 50px gap from the button above it,
     flat 12px (not .78rem), cream at 52% opacity (not the taupe token) —
     all measured directly, not estimated */
  margin-top:50px;
  font-size:12px;
  color:rgba(241,237,231,.52);
}

.banner-photo{ position:relative; overflow:hidden; color:var(--a-white); }
.banner-photo-bg{
  position:absolute; inset:0;
  z-index:0;
  background-image:url("../assets/images/booking-banner.jpg");
  background-size:cover;
  /* top-aligned: the section is much wider than the photo's own aspect ratio,
     so "cover" crops height — anchoring to the top keeps the face/phone in
     frame and crops the lap/knee area at the bottom instead */
  background-position:center top;
}
.banner-photo-bg::before{
  content:"";
  position:absolute; inset:0;
  background:rgba(22,24,16,.45);
}
.banner-photo .container{ position:relative; z-index:1; }
/* was color:var(--a-taupe) — measured directly on the reference site's "easy online
   bookings" label, real color is cream, same fix as Round 35 elsewhere */

/* ============================================================
   Newsletter — 1:1 with the reference site's .footer-cta (a cream card
   full-bleed on a dark olive-deep section, not a heading floating on the
   page's own cream background like the rest of the site). Measured
   directly at 375/479/767/991/1425/2000px viewport widths.
   ============================================================ */
.newsletter-box{
  background:var(--a-cream);
  /* uncapped 5%/10%/50px — deliberately NOT the sitewide clamp(20px,5%,72px)
     gutter: measured directly up to 2000px viewport and it just keeps
     growing with width, no cap, unlike .container elsewhere on the page. */
  padding:5%;
  transition:background-color .7s cubic-bezier(.25,.46,.45,.94);
}
.newsletter-box:hover{
  /* the reference site's real .footer-cta:hover — measured via its
     stylesheet rules (--dark-cream custom property), same value as our
     existing --a-taupe token */
  background:var(--a-taupe);
}
@media (max-width:991px){
  .newsletter-box{ padding-top:10%; padding-bottom:10%; }
}
@media (max-width:767px){
  .newsletter-box{ padding-top:50px; padding-bottom:50px; }
}
.newsletter-title .eyebrow{
  /* base .eyebrow is --a-gray (right for the cream *page* background
     elsewhere) — this eyebrow sits on the newsletter's own cream *card*,
     where the reference site's real color is ink-warm, same family as its
     other cream-on-cream text. Also wins over .section--olive .eyebrow
     (cream) below it in source order — this card isn't olive itself. */
  color:var(--a-ink-warm);
  margin-bottom:20px;
}
.newsletter-heading{
  font-family:"Tenor Sans",Georgia,serif;
  font-weight:400;
  font-size:28px;
  line-height:1.7;
  letter-spacing:-1px;
  color:var(--a-ink-warm);
  margin:0 0 10px;
}
@media (max-width:479px){
  .newsletter-heading{ font-size:22px; }
}
.newsletter-form{
  display:flex;
  gap:1rem;
  margin-top:var(--sp-24);
}
.newsletter-form input[type="email"]{
  flex:1;
  min-width:0;
  height:44px;
  padding:8px 12px 8px 0;
  border:0;
  border-bottom:1px solid var(--a-ink-warm);
  border-radius:0;
  background:none;
  font-family:"Inter",sans-serif;
  font-size:14px;
  font-weight:600;
  color:var(--a-ink-warm);
}
.newsletter-form input[type="email"]::placeholder{
  color:var(--a-ink-warm);
  opacity:1;
  text-transform:uppercase;
  letter-spacing:1px;
  font-size:11px;
}
.newsletter-form input[type="email"]:focus{
  /* the reference site's real focus state — from its own stylesheet
     (.w-input:focus{border-color:#3898EC; outline:0}), a stock Webflow blue
     not in our brand palette. Only the underline visibly reacts because the
     other 3 border sides are already border-style:none above. */
  outline:none;
  border-bottom-color:#3898EC;
}
.newsletter-form .abtn{
  /* .primary-olive already gives the right background (var(--a-olive)) and
     border-radius (3px) — measured this button's own text color/size/padding
     separately since they differ from that shared button's other use (nav
     "Book Online"), a distinct component on the reference site too. */
  color:var(--a-white);
  font-size:15px;
  padding:9px 15px;
}
.newsletter-form .abtn:hover{
  background:var(--a-olive-deep);
}
.form-note{
  margin-top:.75rem;
  font-size:12px;
  line-height:20.4px;
  color:var(--a-ink-warm);
}
.form-note a{ text-decoration:underline; }
.form-status{
  margin-top:.75rem;
  font-size:.85rem;
  color:var(--a-olive-deep);
}
.form-status[hidden]{ display:none; }

/* ============================================================
   Footer
   ============================================================ */
/* .site-footer: no border-top — the reference site's real .footer-base/
   .footer-cta have no border/box-shadow between them (measured directly),
   this was an unmeasured guess, removed on request */
.footer-grid{
  display:grid;
  grid-template-columns:1.2fr repeat(4,1fr);
  gap:var(--sp-40) var(--sp-24);
}
.footer-col h4{
  font-family:"Inter",sans-serif;
  font-weight:700;
  font-size:.7rem;
  letter-spacing:.09em;
  text-transform:uppercase;
  color:var(--a-gray);
  margin-bottom:1rem;
}
.footer-col ul{ display:flex; flex-direction:column; gap:.65rem; }
.footer-col .cat-label{
  font-family:"Inter",sans-serif;
  font-size:10px;
  font-weight:600;
  letter-spacing:1px;
  text-transform:uppercase;
  color:var(--a-gray);
  margin-top:1.25rem;
  padding-bottom:8px;
  border-bottom:1px solid rgba(122,119,114,.41);
}
.footer-col .cat-label:first-child{ margin-top:0; }
.footer-social{ display:flex; gap:1rem; margin-top:1.25rem; color:var(--a-ink-warm); }
.footer-social a{ display:inline-flex; }
.footer-social a:hover{ color:var(--a-olive); }
.footer-col a{ display:block; font-size:.85rem; line-height:1.3; transition:color .2s; }
.footer-col a:hover{ color:var(--a-rust); }
.footer-bottom{
  margin-top:var(--sp-64);
  padding-top:var(--sp-24);
  border-top:1px solid var(--a-taupe);
  display:flex;
  justify-content:space-between;
  flex-wrap:wrap;
  gap:1rem;
  font-size:.78rem;
  color:var(--a-gray);
}
.footer-bottom a{ margin-left:1rem; transition:color .2s; }
.footer-bottom a:hover{ color:var(--a-rust); }
@media (max-width:1024px){
  /* logo/contact column spans full width above; the 4 menu columns
     (Konsultacje/Problem/Zabiegi/O nas) stay together in one row */
  .footer-grid{ grid-template-columns:repeat(4,1fr); }
  .footer-grid > .footer-col:first-child{ grid-column:1 / -1; }
}
@media (max-width:600px){
  .footer-grid{ grid-template-columns:1fr 1fr; }
}
@media (max-width:480px){
  .footer-grid{ grid-template-columns:1fr; }
}

/* ============================================================
   Utility
   ============================================================ */
.title-rule{ margin-bottom:var(--sp-40); }
.title-rule .divider-rule{
  width:100%;
  height:1px;
  background:var(--a-gray);
  /* the reference site's real gap between the eyebrow label and the rule below it
     (measured directly, also matches the Kontakt eyebrow's own margin) */
  margin-top:20px;
}
/* the reference site's real divider on black-olive sections is a faint translucent
   cream line (rgba(241,237,231,.16)), not the solid gray used on cream
   sections — measured directly on the Gift Cards section's .divider-line.light */
.section--olive .title-rule .divider-rule{ background:rgba(241,237,231,.16); }

.two-col-grid{
  display:grid;
  grid-template-columns:1fr 2fr;
  gap:64px 40px;
  align-items:start;
}
@media (max-width:900px){
  .two-col-grid{ grid-template-columns:1fr; gap:var(--sp-24); }
}
.visually-hidden{
  position:absolute;
  width:1px; height:1px;
  overflow:hidden;
  clip:rect(0,0,0,0);
  white-space:nowrap;
}

/* ============================================================
   Strona zabiegu (usługi) — styl 1:1 z archon.au (podstrona przykładowa:
   /treatments/women/womens-laser-hair-removal), treść z instytutem.pl.
   Domyślny szablon dla wszystkich przyszłych podstron zabiegów.
   Pełny zapis pomiarów i decyzji: DOKUMENTACJA.md.
   ============================================================ */
/* on request: hero + price strip together always exactly fill the viewport
   (100vh), so the fold ends flush with the bottom of the dark price strip —
   a deliberate departure from the reference site, whose own hero (90vh) +
   price strip together run slightly taller than 100vh. The wrap is the 100vh
   box; the hero flexes to fill whatever the strip's own content height
   doesn't use, instead of the reference site's flat 90vh.
   ONLY above 991px, though — the reference site's own hero is a completely
   different, content-driven (not vh-locked) layout at ≤991px (see below), so
   forcing 100vh there would fight the real structure instead of matching it. */
.treatment-hero-wrap{
  /* 100vh minus the sticky nav's own 80px — .site-nav sits in normal document
     flow above this (position:sticky, not fixed/overlay), so it already
     consumes 80px of the visible viewport before this wrap even starts */
  height:calc(100vh - 80px);
  display:flex;
  flex-direction:column;
  /* the reference site's real 20px gap to the sticky tabs bar (.section-links),
     measured identically at both mobile and desktop — lives on the WRAP itself
     (not on .treatment-price-strip, its last child) so pages without a price
     strip (e.g. a promo/explainer page whose hero is the wrap's only child)
     still get the same gap before .treatment-tabs, instead of the tabs sitting
     flush against the hero (Runda 172, reported by user as "za mało powietrza") */
  margin-bottom:20px;
}
@media (max-width:991px){ .treatment-hero-wrap{ height:auto; } }
.treatment-hero{
  position:relative;
  flex:1 1 auto;
  min-height:0;
  display:flex;
  align-items:center;
  color:var(--a-cream);
  overflow:hidden;
}
.treatment-hero-bg{
  position:absolute; inset:0;
  background-size:cover;
  background-position:center;
}
.treatment-hero-bg::before{
  /* the reference site's real overlay: flat linear-gradient(rgba(0,0,0,.5),rgba(0,0,0,.5))
     — i.e. a uniform 50% black wash, not a top-to-bottom gradient. Only above
     991px — the reference site's own overlay is display:none at ≤991px (see below). */
  content:"";
  position:absolute; inset:0;
  background:rgba(0,0,0,.5);
}
.treatment-hero .container{ position:relative; z-index:1; }
.treatment-hero-inner{
  /* the reference site's real hero text column: a centered 720px box (measured:
     equal ~281px gaps on both sides within the wider container at 1440px),
     h1/lede text-align:center inside it too — but only above 991px (measured
     breakpoint: text-align switches to left at ≤991px, confirmed at 767/991
     both left, 1200 already center); eyebrow stays centered at every width. */
  max-width:720px;
  margin:0 auto;
  display:flex;
  flex-direction:column;
  align-items:center;
  text-align:center;
}
@media (max-width:991px){
  /* the reference site's real hero column at ≤991px: still capped at 720px,
     but no longer centered (margin-left:0, not auto) — measured directly at
     970px, where our leftover margin:0 auto was adding a real, visible
     ~70px extra left indent versus the rest of the page's content. */
  .treatment-hero-inner{ align-items:flex-start; text-align:left; margin:0; }
}
.treatment-hero .eyebrow{
  color:var(--a-cream);
  margin-bottom:var(--sp-16);
  /* always centered regardless of breakpoint — measured directly, unlike h1/lede below */
  text-align:center;
  align-self:center;
}
.treatment-hero h1{
  /* the reference site's real .heading.h1.treatment: 50px/weight 500/line-height
     60px (1.2×) — measured directly, distinct from the homepage hero's .h-display.
     Mobile size (32px) measured to switch at ≤479px, the sitewide breakpoint. */
  font-family:"Tenor Sans",Georgia,serif;
  font-weight:500;
  font-size:50px;
  line-height:1.2;
  margin:0 0 var(--sp-24);
}
@media (max-width:479px){ .treatment-hero h1{ font-size:32px; } }
.treatment-hero .lede{
  /* the reference site's real intro paragraph on the photo is weight 500, not
     the sitewide .lede's 400 — same size/line-height otherwise. margin-bottom
     measured directly (26px, flat across breakpoints) — this is the paragraph's
     OWN contribution to the gap above the buttons, on top of the button
     wrapper's own margin-top below; missing this the first time is why that
     gap read as too tight. */
  font-weight:500;
  color:var(--a-cream);
  margin-bottom:26px;
}

/* ≤991px: a COMPLETELY different, content-driven layout on the reference
   site — not a smaller version of the desktop overlay. Confirmed by direct
   screenshot + DOM inspection (not just individual property checks, which
   is how this got missed the first time): the photo becomes a plain 45vh
   block at the top (position:static, no overlay — the reference site's own
   .image-overlay-layer is display:none here), and the text sits BELOW it in
   normal flow on the page's own cream background, dark ink text, left-
   aligned. The breakpoint is exactly 991/992px (measured), matching this
   project's existing tier. The text panel overlaps up into the bottom of
   the photo by a measured ~84px at a 812px-tall viewport (~10vh) — a
   deliberate overlapping-card effect, approximated here as a clean -10vh
   (exact Webflow nested-wrapper padding math not fully reverse-engineered,
   but this is visually within a few px of the real site). */
@media (max-width:991px){
  .treatment-hero{
    position:static;
    display:block;
    overflow:visible;
    color:var(--a-olive-black);
  }
  .treatment-hero-bg{
    position:static;
    height:45vh;
    width:100%;
  }
  .treatment-hero-bg::before{ display:none; }
  .treatment-hero .container{
    position:relative;
    margin-top:-10vh;
    background:var(--a-cream);
    padding-top:var(--sp-40);
    padding-bottom:var(--sp-40);
  }
  .treatment-hero .eyebrow{
    color:var(--a-olive-black);
    /* archon.au's own eyebrow at this breakpoint is left-aligned with the
       heading, not centered like the desktop overlay version — measured
       directly (text-align:left) on the reference site's ≤991px layout. */
    text-align:left;
    align-self:flex-start;
  }
  .treatment-hero .lede{ color:var(--a-olive-black); }
  .treatment-hero-ctas{
    /* .treatment-hero-inner switches to align-items:flex-start above (for the
       left-aligned text), but that also makes a flex row CHILD like this one
       shrink-wrap to its own content width instead of filling the column —
       confirmed as the real cause of the buttons not reaching the container's
       right edge (measured: ctas stopped 20px short of h1/lede's own right
       edge). archon.au's equivalent button-wrapper has an explicit width
       instead of relying on stretch, so it isn't affected by the same
       shrink-wrap — same fix here. */
    width:100%;
  }
}

/* the reference site's real hero CTA row — re-measured precisely (these are
   NOT the shared .abtn.primary-black, they have their own distinct padding):
   both 43px tall, radius 2px, 14px/500 white-on-olive-black — identical to
   .abtn EXCEPT padding, which is 0 18px (plain button) and 0 13px 0 18px
   (button with the arrow icon, asymmetric to keep the icon visually centered
   in its own 24px box). Wrapper: margin-top 25px (>479px) / 10px (≤479px,
   both measured directly), gap 20px between the two buttons. */
.treatment-hero-ctas{
  display:flex;
  gap:20px;
  margin-top:25px;
}
@media (max-width:479px){ .treatment-hero-ctas{ margin-top:10px; } }
.treatment-hero-ctas .abtn{
  padding:0 18px;
}
.treatment-hero-ctas .abtn.has-arrow{ padding:0 13px 0 18px; }
@media (max-width:767px){
  /* the reference site's real mobile behaviour, measured directly (both
     buttons flex:1 1 0% — confirmed exactly at ≤767px, still content-width
     at 768px+): buttons stretch to share the full row width equally,
     "rozciągnięte na całą szerokość viewportu z uwzględnieniem marginesu".
     white-space:normal + min-width:0 override the shared .abtn's nowrap/auto —
     on archon.au the label wraps to 2 lines at very narrow widths (confirmed
     at 320px: "View prices" wraps, button height stays fixed) instead of the
     row overflowing past the container edge. */
  .treatment-hero-ctas .abtn{ flex:1 1 0%; min-width:0; white-space:normal; text-align:center; }
}
/* the reference site's real arrow: an actual asset ("Arrow long - right.svg",
   fetched and inlined here as the same path data — not a hand-drawn chevron),
   in a 24×24 box with the 12×12 glyph centered, rotated 90deg to point down.
   The reference site's own asset has a hardcoded near-black fill and uses
   filter:invert(1) to read white on the dark button — our inlined copy uses
   fill="currentColor" instead (inherits the button's own white text color
   directly), same visual result without the redundant invert. Spacing to
   the button text: display:flex + justify-content:space-around on the
   button (not a fixed gap) — measured ~11.5px in practice. */
.treatment-hero-ctas .abtn.has-arrow{
  justify-content:space-around;
}
.treatment-hero-ctas .down-arrow-wrap{
  width:24px;
  height:24px;
  display:flex;
  align-items:center;
  justify-content:center;
  overflow:hidden; /* archon.au's .down_arrow_wrapper: overflow:hidden — clips the arrow
                       during the jump so it never visibly leaves the button */
}
.treatment-hero-ctas .down-arrow{
  width:12px;
  height:12px;
  transform:rotate(90deg);
}
/* the reference site's real hover animation on this arrow — read directly out
   of its Webflow IX2 action list ("Jump Arrow Down", triggered on MOUSE_OVER):
   translateY 0→30px (200ms) → instantly to -30px (0ms, a teleport) → back to
   0 (200ms), both eased "easeInOut". Net visual effect: the arrow drops down
   and bounces back on hover. Expressed here as one CSS keyframe animation
   played on :hover (the instant jump has to land on an exact keyframe
   percentage, hence 50%/50.01%). */
@keyframes treatment-arrow-jump{
  0%{ transform:translateY(0) rotate(90deg); }
  50%{ transform:translateY(30px) rotate(90deg); }
  50.01%{ transform:translateY(-30px) rotate(90deg); }
  100%{ transform:translateY(0) rotate(90deg); }
}
.treatment-hero-ctas .abtn:hover .down-arrow{
  animation:treatment-arrow-jump .4s ease-in-out;
}

/* dark price/financing strip directly under the hero — the reference site's
   real .treatment-cta-block (measured 1:1): flex space-between, padding
   20px + the sitewide 5% gutter (71.25px measured, matches clamp(20px,5%,72px)
   used everywhere else), "Treatments from: $80 / 15 Minutes" + Afterpay logo
   (image wrapper with filter:invert(1) to read white on the dark strip,
   measured 1:1) + note. Adapted for a price RANGE ("od X zł", not a fixed $
   figure) and MediRaty instead of Afterpay. The 20px gap to the sticky tabs
   bar below lives on .treatment-hero-wrap itself now (Runda 172), not here. */
.treatment-price-strip{
  background:var(--a-olive-black);
  color:var(--a-cream);
  flex:0 0 auto;
}
.treatment-price-strip-inner{
  display:flex;
  justify-content:space-between;
  align-items:center;
  padding:20px max(20px, 5%);
}
.treatment-price-strip-row{
  display:flex;
  align-items:center;
  gap:8px;
}
@media (max-width:767px){
  /* the reference site's real mobile layout (measured at 375/767, breakpoint
     confirmed exactly at 767/768): stacks into 2 rows, flat 160px height
     (not content-driven), space-between distributes the rows within it,
     no vertical padding needed (space-between handles the spacing). Each row
     is itself 80px tall; the price row gets a bottom divider (real color:
     var(--a-gray) — measured rgb(122,119,114), exactly this token — with
     20px padding-bottom creating the gap above it), and its price (giant+
     suffix) becomes flex:1 with justify-content:flex-end so it's pushed to
     the row's right edge while the label stays left — real technique on the
     reference site, not space-between on the row itself. */
  .treatment-price-strip-inner{
    flex-direction:column;
    align-items:stretch;
    height:160px;
    padding-top:0;
    padding-bottom:0;
  }
  /* Strony bez .treatment-financing-wrap (na razie tylko /konsultacje/dermokonsultacja,
     na wyraźną prośbę użytkownika: "usuńmy dopisek o mediratach" — nie dotyczy
     usługi za 149 zł) — 160px zakłada 2 rzędy po 80px (cena + raty), z jednym
     rzędem zostawiałoby to pustą, czarną przestrzeń pod separatorem. */
  .treatment-price-strip.no-financing .treatment-price-strip-inner{ height:80px; }
  .treatment-price-strip.no-financing .treatment-price-strip-row{ border-bottom:none; }
  .treatment-price-strip-row{
    height:80px;
    border-bottom:1px solid var(--a-gray);
    /* archon.au's real .price-block: fixed height:80px PLUS padding:20px 0,
       centering its content instead of leaving it flush to one edge —
       measured directly. padding-bottom stacks with the divider gap below. */
    padding:20px 0;
  }
  .treatment-price-wrap{
    flex:1 1 0%;
    justify-content:flex-end;
  }
  .treatment-financing-wrap{
    height:80px;
    /* same fix as the row above (archon.au's .afterpay-wrapper: height:80px +
       padding:20px 0 + align-items:center) — our version keeps align-items:
       flex-end (not center) because the MediRaty baseline trick above needs
       a flex-end reference; adding this padding still centers the block as a
       whole within the 80px row (both bottom-aligned img/text move up
       together, off the row's bottom edge, so their relative — and already
       measured — baseline alignment is unaffected). */
    padding:20px 0;
  }
  /* on request: mirror the price row's left-label/right-value layout — the
     logo stays pinned to the row's left edge (same column as "Cena już od:"),
     the caption is pushed to the row's right edge (same column as "179 zł")
     instead of trailing right after the logo with dead space beyond it. The
     available width for the caption to wrap within doesn't change (still the
     row's width minus the logo minus the gap), so this only repositions the
     already-decided wrapped lines — the JS baseline alignment measures the
     result live regardless of text-align, so it needs no change here. */
  .treatment-financing{
    flex:1 1 0%;
    text-align:right;
  }
}
.treatment-financing-wrap{
  display:flex;
  /* archon.au's real .afterpay-wrapper uses plain align-items:center (measured
     directly) — earlier rounds here tried to match the caption's text
     baseline to the MediRaty wordmark's own letter-baseline specifically
     (excluding the heart icon), which needed a live JS measurement to get
     right and never looked as level as simple centering. Matching the
     reference site's simpler approach instead, on request. */
  align-items:center;
  gap:24px;
}
.treatment-financing-logo{
  /* the reference site's real Afterpay logo: filter:invert(1) on the wrapper
     (not the img itself) so a dark-on-transparent logo reads white on this
     dark strip — same technique applied to the MediRaty logo here */
  filter:invert(1);
  display:flex;
  align-items:center;
}
.treatment-financing-logo img{
  /* on request: bigger than the Afterpay-matched 17px for legibility — MediRaty's
     mark has more visual detail than Afterpay's simple wordmark and reads poorly
     that small. The row/strip height itself stays as measured from Afterpay
     (94px desktop / 160px mobile) — only the logo image grows within it.
     Bumped +15% twice on request (28px→32px→37px). */
  height:37px;
  width:auto;
}
.treatment-price-label{
  font-family:"Inter",sans-serif;
  font-weight:600;
  font-size:14px;
  line-height:23.8px;
  margin:0;
}
.treatment-price-wrap{
  display:flex;
  align-items:baseline;
  gap:2px;
}
.treatment-price-giant{
  font-family:"Inter",sans-serif;
  font-weight:400;
  font-size:44.8px;
  line-height:53.76px;
  margin:0;
}
@media (max-width:767px){ .treatment-price-giant{ font-size:40px; } }
.treatment-price-suffix{
  font-family:"Inter",sans-serif;
  font-weight:400;
  font-size:14px;
  line-height:23.8px;
  margin:0;
}
.treatment-financing{
  font-family:"Inter",sans-serif;
  font-weight:500;
  font-size:12px;
  line-height:20.4px;
  margin:0;
}

.treatment-tabs{
  position:sticky;
  top:80px; /* JS overrides to sit flush under the real nav height, same pattern as elsewhere */
  z-index:50;
  background:var(--a-cream);
}
.treatment-tabs-inner{
  display:flex;
  gap:5px; /* zmierzone na żywej archon.au (getBoundingClientRect między kolejnymi
              linkami FAQ/CONCERNS/COSTS/CARE): 5px, nie sitewide --sp-24 (24px) */
  overflow-x:auto;
  /* stays scrollable (touch swipe, trackpad, click-drag) but hides the
     browser's own scrollbar chrome underneath it, on request — the tab
     labels are longer here than on archon.au's own shortest labels ("faq",
     "care"), which never need to scroll at any width there, so there's no
     1:1 reference for this specific bar; hiding the scrollbar UI while
     keeping the scroll behavior is the standard technique for this. */
  scrollbar-width:none;
  -ms-overflow-style:none;
}
.treatment-tabs-inner::-webkit-scrollbar{ display:none; }
.treatment-tab{
  font-family:"Inter",sans-serif;
  font-weight:600;
  font-size:12px;
  letter-spacing:0.5px;
  text-transform:uppercase;
  color:var(--a-ink-warm);
  white-space:nowrap;
  padding:5px;
}
/* archon.au's real first tab has margin-left:-5px (measured live), canceling
   its own 5px left padding so the text lines up with the container's edge
   like the rest of the page — without it the first tab's text sits 5px right
   of everything else. Only the first tab needs this; the others' spacing is
   already correct via .treatment-tabs-inner's own gap. */
.treatment-tab:first-child{ margin-left:-5px; }

.treatment-accordion details{
  /* the reference site's real .accordion-item divider color, measured directly:
     rgba(212,212,212,.15) — a faint light-gray hairline, same family as --a-gray */
  border-bottom:1px solid rgba(212,212,212,.15);
}
.section--cream .treatment-accordion details{
  /* on cream sections the same hairline needs a dark-family color instead —
     no reference-site cream instance of this component to measure, so this
     mirrors the existing dark-on-cream divider already used elsewhere
     (.title-rule .divider-rule) rather than reusing the olive-section value verbatim */
  border-bottom-color:var(--a-taupe);
}
.treatment-accordion summary{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:var(--sp-16);
  padding:20px 0;
  cursor:pointer;
  list-style:none;
}
.treatment-accordion summary::-webkit-details-marker{ display:none; }
.treatment-accordion-q{
  /* the reference site's real .faq-title: Inter 500 16px/24px — matches the
     "Nagłówek karty (H4)" row in DESIGN-SYSTEM.md §3, but without the
     text-transform:capitalize that .h-card carries (would mangle real
     sentence-case question text), so a dedicated class instead of reusing .h-card */
  font-family:"Inter",sans-serif;
  font-weight:500;
  font-size:16px;
  line-height:24px;
  margin:0;
}
.treatment-accordion summary .caret{
  width:12px; height:8px;
  flex:0 0 auto;
  /* the reference site's real "Accordion Open/Close" arrow rotate (measured via
     ix2 store): 300ms, not the previously-unmeasured 200ms this had before */
  transition:transform .3s;
}
/* Must be details[open] > summary > .caret (direct-child, not descendant)
   everywhere. cennik/index.html nests a .price-tier inside a "group" .price-tier's
   own .price-tier-rows (Round 135) — with a bare descendant selector, ANY caret
   inside an open details anywhere below .treatment-accordion matches once the
   OUTER group is open, because the selector only needs SOME open-details
   ancestor, not the caret's own immediate details — so a closed inner accordion's
   caret rotated as soon as its outer group opened, and toggling the inner one
   itself did nothing more (already "wrongly" rotated). Direct-child combinators
   pin the match to the caret's own details specifically. */
.treatment-accordion details[open] > summary > .caret{ transform:rotate(180deg); }
.treatment-accordion-body{
  /* the reference site's real .accordion-content-wrapper (measured via ix2 store):
     height 0↔auto and opacity 0↔1, both 300ms outQuad — driven here by JS
     (main.js) since native <details> can't transition its own show/hide; outQuad's
     CSS equivalent is the same cubic-bezier already used elsewhere on this site.
     Rest-state height/opacity keyed off [open] (not a JS-only default) so a
     details that starts open renders correctly before main.js even runs — no
     flash of hidden content while the script loads. */
  overflow:hidden;
  height:0;
  opacity:0;
  transition:height .3s cubic-bezier(.25,.46,.45,.94), opacity .3s;
}
.treatment-accordion details[open] .treatment-accordion-body{
  height:auto;
  opacity:1;
}
.treatment-accordion-body-inner{ padding:0 0 var(--sp-24); max-width:720px; }
.treatment-accordion-teaser{
  /* collapsed-state one-line teaser under the question, shown only while closed */
  color:var(--a-gray);
  font-size:14px;
  margin-top:4px;
}
.treatment-accordion details[open] .treatment-accordion-teaser{ display:none; }

/* the reference site's real "Women's laser hair removal in Brisbane" intro
   section (.content-wrapper): a small uppercase eyebrow label, a full-width
   1px divider line below it, then a 2-column grid (heading left, paragraph
   right) — all measured directly. Reuses the sitewide .eyebrow/.lede classes
   (already matching this section's exact type: 12px/600/uppercase and
   16px/400/27.2px respectively) rather than introducing duplicate rules. */
.treatment-intro-title-line .eyebrow{
  /* this section's real eyebrow color is the darker ink-warm, not the
     sitewide .eyebrow default (gray) — measured directly, distinct from the
     Gift Cards section's own eyebrow that set that default. */
  color:var(--a-ink-warm);
  margin-bottom:20px;
}
/* this title-line+divider combo was only ever used on .section--cream (Opis
   zabiegu, Cennik) until Runda 172 put it on a .section--olive section
   ("Zasady promocji") for the first time — the hardcoded dark ink-warm/near-black
   colors above are invisible on that dark background, so a light-on-dark pair
   is needed too, same pattern as every other cream/olive component override
   on this page. */
.section--olive .treatment-intro-title-line .eyebrow{ color:var(--a-cream); }
.section--olive .treatment-intro-divider{ background:var(--a-taupe); }
.treatment-intro-divider{
  height:1px;
  background:#1E1D1D;
}
.treatment-intro-grid{
  display:grid;
  grid-template-columns:1fr 2fr;
  column-gap:40px;
  row-gap:64px;
  align-items:start;
  /* measured directly on the reference site: divider→heading gap is 25px at
     every width, PLUS an extra 30px only ≥992px (55px total there) — on
     archon.au that's the divider's own margin-bottom (25px) plus a separate
     margin-bottom on its parent .section-title-line (30px, desktop-only),
     which for some reason don't collapse into each other there. Standard CSS
     margin collapsing (adjacent-sibling AND parent↔last-child) would merge
     those two into whichever is larger instead of summing them if split back
     out into two separate margins here, so the combined totals are set once,
     directly, on this grid's own margin-top instead — avoids depending on a
     collapsing quirk we can't explain, for the same visual result. */
  margin-top:55px;
}
.treatment-intro-grid h2{
  font-family:"Tenor Sans",Georgia,serif;
  font-weight:500;
  font-size:30px;
  line-height:36px;
  letter-spacing:-1px;
  margin:0;
  /* explicit, not relying on cascade order to beat .section--cream h2's
     olive-black default — this section's real heading color is ink-warm,
     measured directly (matches the eyebrow/paragraph color here too). */
  color:var(--a-ink-warm);
}
@media (max-width:991px){
  /* the reference site's real breakpoint for this grid is 991/992px — the
     same tablet tier used by the hero's own restructuring, NOT the 767px
     used elsewhere on this page (buttons, price strip). Confirmed by
     bisecting: still 2-column at 991px, switches to 1-column exactly at
     992px. Using 767px here left a cramped ~213px heading column between
     768–991px that the reference site doesn't have at all. */
  .treatment-intro-grid{
    grid-template-columns:1fr;
    row-gap:40px;
    margin-top:25px;
  }
}

/* TECHNOLOGIA (#technologia) — new editorial "hairline grid" component (Runda 104), no
   archon.au equivalent to measure. 1 column on mobile → 4 on desktop, thin --a-taupe
   dividers between cells (bottom on mobile since cells stack, right on desktop since
   they sit side by side) instead of boxed cards — the "zero krzykliwych boksów" luxury-
   minimal look the brief asked for. Kicker/title/body inside each cell reuse .eyebrow/
   .treatment-accordion-q/.lede verbatim (see comment on the section in the HTML) — only
   their margins needed resetting here, since those classes are normally used standalone,
   not stacked three deep inside one grid cell. */
.tech-grid{
  display:grid;
  grid-template-columns:1fr;
  margin-top:var(--sp-64);
  border-top:1px solid var(--a-taupe);
}
@media (min-width:992px){
  .tech-grid{ grid-template-columns:repeat(4,1fr); }
}
.tech-item{
  padding:var(--sp-64) var(--sp-40);
  border-bottom:1px solid var(--a-taupe);
}
.tech-item:last-child{ border-bottom:none; }
@media (min-width:992px){
  .tech-item{ border-bottom:none; border-right:1px solid var(--a-taupe); }
  .tech-item:first-child{ padding-left:0; }
  .tech-item:last-child{ padding-right:0; border-right:none; }
}
.tech-item .eyebrow{ margin:0 0 var(--sp-24); }
.tech-item .treatment-accordion-q{ margin:0 0 var(--sp-24); }
.tech-trust-bar{
  display:flex;
  flex-wrap:wrap;
  justify-content:center;
  gap:var(--sp-16) var(--sp-40);
  margin-top:var(--sp-64);
  padding-top:var(--sp-40);
  border-top:1px solid var(--a-taupe);
}
.tech-trust-bar span{
  font-family:"Inter",sans-serif;
  font-weight:600;
  font-size:12px;
  letter-spacing:.04em;
  text-transform:uppercase;
  color:var(--a-gray);
  white-space:nowrap;
}

/* FAQ section (#faq): reuses .treatment-intro-grid (same measured 1fr/2fr ratio and
   40px/64px gaps as archon.au's own #faq ._2-column-grid — confirmed identical via
   getComputedStyle, not a new component) but on a dark .section--olive background
   with no divider above it (archon.au's real #faq has ~0px gap between its eyebrow
   and the grid — margin-top:0 here, relying on the eyebrow's own margin-bottom
   instead of the intro section's divider-driven 55px). */
#faq .treatment-intro-grid{ margin-top:0; }
#faq .eyebrow{ margin:0 0 20px; }
.section--olive .treatment-intro-grid h2{ color:var(--a-cream); }
/* archon.au's real #faq accordion colors (measured via getComputedStyle on
   .accordion-item/.faq-title/.accordion-paragraph/.accordion-title), distinct
   from the rgba(212,212,212,.15) divider already measured for a different real
   accordion instance (Efekty/Technologia) — not overwriting that shared rule. */
/* archon.au's real #faq accordion divider is a LEADING element (.divider-line,
   first child of each .accordion-item) — not a trailing border like our shared
   .treatment-accordion rule. Confirmed live: every item (incl. the first) has
   one before it, the last item has none after it. border-top replicates that
   exactly: a divider before every details, nothing after the final one. */
#faq .treatment-accordion details{ border-bottom:none; border-top:1px solid var(--a-gray); }
#faq .treatment-accordion-body-inner .lede{ color:var(--a-taupe); }
/* the taupe answer color above assumed #faq is always .section--olive (true on
   every page until Runda 172's promo/explainer page put FAQ on .section--cream
   instead) — taupe reads as a deliberate light-on-dark muted tone there, but
   washes out to near-invisible on a light cream background, so it needs the
   dark ink-warm counterpart in that context, same as every other cream/olive
   pair on this page. */
#faq.section--cream .treatment-accordion-body-inner .lede{ color:var(--a-ink-warm); }
#faq .treatment-accordion summary{ opacity:.8; transition:opacity .2s; }
#faq .treatment-accordion summary:hover{ opacity:1; }

/* archon.au's real #concerns (measured directly, live): heading→list gap is
   64px at every width (not the sitewide --sp-24=24px this had before); each
   item's divider is a LEADING element (border-top, same pattern as #faq's
   accordion — a divider before every item including the first, none after
   the last), color rgb(122,119,114)=--a-gray (not the faint rgba(212,212,212,.15)
   or --a-taupe this had before, which were never actually measured for THIS
   component); 24px gap from divider to the number/text row; number+paragraph
   are both --a-cream (not --a-gray for the number — also unmeasured before). */
.treatment-benefits{ margin-top:64px; }
.treatment-benefit{
  display:flex;
  gap:15px;
  align-items:baseline;
  border-top:1px solid var(--a-gray);
  padding-top:24px;
}
.treatment-benefit .lede{ margin:0 0 10px; }
.treatment-benefit-num{
  font-family:"Inter",sans-serif;
  font-weight:600;
  font-size:12px;
  color:var(--a-cream);
  flex:0 0 auto;
}
.section--cream .treatment-benefit-num{ color:var(--a-olive-black); }
/* the reference site's real .number grows on mobile (12px→15px, measured
   directly at 375px) — a real, deliberate quirk, not a guess */
@media (max-width:767px){ .treatment-benefit-num{ font-size:15px; } }
/* eyebrow→heading gap for THIS section specifically (measured live: 47px at
   1440px, 17px at 375px) — distinct from other sections' own measured gaps
   for the same eyebrow/heading pattern elsewhere on this page. */
#wskazania .eyebrow{ margin-bottom:47px; }
@media (max-width:767px){ #wskazania .eyebrow{ margin-bottom:17px; } }

/* CENNIK (#cennik): reuses .treatment-intro-grid (same as FAQ) + .treatment-accordion
   (same details/summary mechanism as FAQ) for the S/M/L price tiers, styled after
   archon.au's real #cost price list — now on a light .section--cream, matching
   archon.au's own real #cost (a plain, light .section, not black-olive; the first
   version of this section wrongly stayed dark "to match this page's rhythm" —
   corrected on request to the actual measured archon.au style). Eyebrow+divider
   reuses .treatment-intro-title-line/.treatment-intro-divider (same component as
   the "Zabiegi Hi-Tech" intro higher up), but with the divider color measured
   directly on archon.au's own #cost .section-title-line .divider-line
   (rgb(122,119,114)=--a-gray), not that other section's #1E1D1D — two different
   real measurements, not one value reused as a guess for the other. */
#cennik .treatment-intro-divider{ background:var(--a-gray); }
/* heading→list gap matches the sitewide convention already established for the
   analogous "heading+intro-text → item list below" pattern (#wskazania's
   .treatment-benefits, measured 64px from archon.au's #concerns) — the previous
   24px reused .treatment-cards' own gap, a different, unrelated component. */
.price-list{ margin-top:64px; }
/* Round 146 (user: cennik's top-level division must match the header nav's
   own main-category + level-1 structure 1:1) — the header's "Zabiegi" mega-
   menu has ONE main entry with 3 level-1 sub-groups (Hi-Tech/Iniekcyjne/
   Manualne), and "Konsultacje" has 2 (Dla Twarzy/Dla Ciała); cennik had
   these as 4 separate flat top-level SECTIONS instead. Merged into 2
   sections (one per real header main-category) with a plain, un-styled-
   as-a-component label marking each level-1 sub-group inside — reuses
   .eyebrow's own type scale (12px/600/uppercase/gray) rather than a new
   size, so it reads as "a label", consistent with every other small caps
   label already on the page, not a new visual language. A divider line
   above each one but the first in its list (that one already gets its
   separation from .price-list's own 64px margin-top above the whole
   list) marks where one sub-group's rows end and the next begins — the
   same divider color/weight .price-tier and .price-row already use for
   their own row-to-row lines, just spaced further apart (40px) since this
   is a bigger structural break than a plain row boundary. */
/* Round 148 (user: "nad eyebrow niech nie będzie separatora"): dropped the
   border-top + its padding-top — the label itself, plus the margin-top gap
   above it, is enough to read as a new sub-group without a literal line on
   top of it (a line already exists below every row it follows anyway, so a
   second one right above the label doubled up). */
.price-list-subheading{
  font-family:"Inter",sans-serif;
  font-weight:600;
  font-size:.75rem;
  letter-spacing:0.5px;
  text-transform:uppercase;
  color:var(--a-gray);
  margin:var(--sp-40) 0 var(--sp-16);
}
.price-list-subheading--first{ margin-top:0; padding-top:0; border-top:none; }
/* cennik/index.html only (Round 139, user: "zmniejsz o 50% odstęp między
   najwyższymi kategoriami") — the top-level category sections are plain
   .section-pad, whose sitewide padding-top+padding-bottom (80/80, halved to
   64/64 ≤640px — used on every other page too, so not touched there) stacks
   between two adjacent sections into a 160px (or 128px) gap. ID selectors
   here so they win over the shared .section-pad class without needing
   !important, scoped to just these ids so no other page's section spacing
   changes. Halving each section's own padding halves the STACKED gap
   between any two of them by the same 50%, front and back alike.
   Round 146 merged what was 4 sections (Konsultacje/Hi-Tech/Iniekcyjne/
   Manualne) into 2 (#konsultacje-i-diagnostyka, #zabiegi) — updated the
   selector list to match the current ids, not the 3 removed ones (which
   would just silently stop matching anything and quietly undo this fix). */
#konsultacje-i-diagnostyka, #zabiegi{
  padding-top:var(--sp-40);
  padding-bottom:var(--sp-40);
}
@media (max-width:640px){
  #konsultacje-i-diagnostyka, #zabiegi{
    padding-top:32px;
    padding-bottom:32px;
  }
}
.price-tier summary{ gap:var(--sp-16); }
/* flex-grow:1 (default is 0, i.e. hug-content) so this always fills the row up
   to the caret even when the title is short — otherwise its own box only ever
   grew as wide as the title needed, and a SHORT title left the icon+"od X zł"
   cluster stranded right after the text instead of pinned to the row's real
   right edge (see .price-tier-label .treatment-accordion-q below, which
   handles the matching case of a LONG title). */
.price-tier-label{ display:flex; align-items:center; gap:var(--sp-16); flex-grow:1; }
/* archon.au's real #cost accordion group title (e.g. "Treatment Blocks", measured
   directly on its own h3, live): Inter 15px/700/21px — distinct from FAQ's own
   .faq-title (500/16/24, Round 43), which .treatment-accordion-q was tuned for.
   Skips the real text-transform:capitalize for the same reason as the row text
   above (would mangle our correctly-cased Polish tier names). Scoped to
   .price-tier-label (the actual semantic wrapper this value belongs to) rather
   than the treatment page's own #cennik id, so cennik/index.html's identical
   .price-tier-label markup (Round 131 — reusing this exact accordion pattern
   1:1, on request, instead of the earlier custom .price-tier--row hack) gets it
   too, without also reaching unrelated .treatment-accordion-q uses (FAQ, the
   Round 104 tech section) that were never meant to have it. */
.price-tier-label .treatment-accordion-q{
  font-family:"Inter",sans-serif;
  font-weight:700;
  font-size:15px;
  line-height:21px;
  /* .price-tier-label is a nowrap flex row of [title, info-icon, price badge]
     sharing one line — with the title on default flex-basis:auto (sized by its
     own content, then shrunk if needed), how much room a long title got to
     shrink into (and where that left the icon+badge on wide-title rows) varied
     row to row, so on mobile the icon+"od X zł" cluster didn't land at a
     consistent x-position — it trailed wherever THIS row's particular title
     text happened to end, not lined up with the caret above/below it. Giving
     the title flex-basis:0 + flex-grow:1 (with min-width:0 so it can still
     shrink/wrap past its own min-content) makes it the one item that absorbs
     all the leftover space instead of just shrinking proportionally to its own
     size — so the icon+badge (both already flex-shrink:0, their own natural
     width) always end up flush against the row's real right edge, i.e.
     directly against the caret, on every row regardless of title length. */
  flex:1 1 0%;
  min-width:0;
}
/* archon.au's real #cost .price-table price value (measured directly, live:
   getComputedStyle on the 2nd <p> of a .price-table): Inter 16px/400/27.2px, NOT
   bold — the 700 this had before was an unmeasured guess. Our own inline S/M/L
   price badge (not a literal archon element — archon never shows a price next to
   its group h3) reuses that same real "price value" typography for consistency,
   since it displays the same kind of value. */
.price-tier-badge{
  font-family:"Inter",sans-serif;
  font-weight:400;
  font-size:16px;
  color:var(--a-ink-warm);
  /* on narrow viewports a long accordion title (e.g. "LUMIVEX® - laser tulowy
     (erbowo-szklany)") wraps to 2 lines inside .price-tier-label's flex row —
     expected/fine. Without this, the price badge (a plain flex item with the
     browser's default flex-shrink:1) got squeezed along with it, narrow enough
     that its own "od 299 zł" text wrapped mid-price onto a second line. The
     title should be the one that flexes/wraps; the price reads as a single
     unbreakable value. */
  flex-shrink:0;
  white-space:nowrap;
}
/* rust "promocja" flag for the consultation price-tier — same rust pill treatment
   as .price-package-badge (bg var(--a-rust), cream uppercase text) but inline in
   normal flow instead of absolutely positioned, so it can sit next to the price
   badge in the collapsed summary AND next to a specific row once expanded. */
.promo-badge{
  display:inline-flex;
  align-items:center;
  gap:4px;
  white-space:nowrap;
  font-family:"Inter",sans-serif;
  font-weight:700;
  font-size:11px;
  letter-spacing:.04em;
  text-transform:uppercase;
  color:var(--a-cream);
  background:var(--a-rust);
  padding:4px 10px;
  border-radius:2px;
  margin:0 0 0 10px;
  vertical-align:middle;
}
/* optional leading icon (Runda 177: gift-box icon on a "Promocja" badge,
   ties it visually to the matching .price-row-note below, which uses the
   same icon) — inline-flex above already lays out icon+text on one line for
   every existing badge too (text-only ones are unaffected: a single child
   in an inline-flex box renders identically to inline-block). currentColor
   picks up the badge's own cream text color automatically. */
.promo-badge svg{ width:15px; height:15px; flex:none; }
/* two badges on the same row (Runda 177: "Pakiet Powitalny" + "Promocja")
   need their own tight gap between them, distinct from .price-row's own
   larger gap to the row's label/price — wrapped in one flex item so the
   pair reads as a group instead of being spread apart by .price-row's own
   justify-content:space-between (which only expects 3 children: badges,
   label, price). The individual .promo-badge's own margin-left:10px would
   double up with this wrapper's gap, so it's reset to 0 here. */
.price-row-badges{ display:inline-flex; align-items:center; gap:8px; }
.price-row-badges .promo-badge{ margin-left:0; }
/* Runda 184 (user: "te plakietki zrób w widoku mobilnym nad nazwą kategorii") —
   on .price-tier-label (the "Konsultacje" summary row), badges + h3 + price
   all fighting for one nowrap-ish row got cramped on narrow phones. flex-wrap
   + order:-1 + flex-basis:100% forces .price-row-badges onto its own full-width
   line FIRST; the title (already flex-grow:1) and price badge then continue
   together on the next line, keeping their usual name-left/price-right layout
   — same breakpoint as the rest of the page's other mobile reflows (767px). */
@media (max-width:767px){
  .price-tier-label{ flex-wrap:wrap; row-gap:8px; }
  .price-tier-label > .price-row-badges{ order:-1; flex-basis:100%; }
}
/* Runda 178: only the inline-in-<p> usage (laser-tulowy-plock's flat .price-row,
   no automatic gap mechanism in text flow) needs its own left margin to clear
   the preceding text. Inside .price-tier-label (Runda 179's use on the
   depilacja-laserowa summary line) the parent is already display:flex with its
   own gap — an extra margin here would double up with that gap (measured:
   26px before the badges vs. 16px after, instead of an even 16px/16px). */
p .price-row-badges{ margin-left:10px; }
/* struck-through regular price next to the current, promotional one in a
   .price-row's price column — reuses the same de-emphasized gray/14px
   treatment already used for the row LABEL's own duration/description
   span (.price-row p:first-child span), just applied to the price side. */
.price-row .price-old{
  text-decoration:line-through;
  color:var(--a-gray);
  font-size:14px;
  margin-right:6px;
}
/* .price-tier--row existed briefly (Rounds 128-129) as a workaround so a
   details/summary accordion could sit among plain .price-row siblings on
   cennik/index.html, styled by reusing .price-row on <summary> — it needed 3
   rounds of increasingly narrow fixes (double borders, uneven row heights,
   margin lost to a :first-child collision, spacing wrong only in the [open]
   state) because it was fighting the existing .treatment-accordion/.price-tier
   system instead of using it. Round 131 (user: "zastosuj taki sam styl jak
   tutaj", pointing at the treatment page's own #cennik accordion) replaced it:
   cennik/index.html's rows now use the EXACT SAME markup as the treatment page
   (<summary><span class="price-tier-label"><h3 class="treatment-accordion-q">
   + .price-tier-badge, no .price-row class on summary at all) — so all of the
   above bugs stop applying by construction, not by patching, and this whole
   modifier class and its fixes are removed as dead code. See
   .price-tier-label .treatment-accordion-q above for the one rule that moved
   (was #cennik-scoped, now .price-tier-label-scoped) so the reused markup gets
   the same typography without depending on the treatment page's own id. This
   DID surface one new, genuine mismatch (user, Round 132, screenshot): the
   treatment page's own #cennik accordion is ALL .price-tier — every boundary is
   tier-to-tier, so its default trailing border-bottom (base rule above) reads
   as exactly one line regardless of which side "owns" it. cennik/index.html
   mixes .price-tier with plain .price-row (which draws a LEADING border-top on
   itself instead) in the same flat list — at a .price-row→.price-tier boundary
   NEITHER contributes a line (the row has no border-bottom, the tier has no
   border-top: gap with nothing), and at a .price-tier→.price-row boundary BOTH
   do (the tier's own trailing border-bottom, immediately followed by the row's
   own leading border-top: two hairlines close together). Fix: give
   .price-list's own .price-tier the SAME leading-border convention as its
   plain .price-row siblings — scoped to .price-list (not the treatment page's
   #cennik id, and not a bare ".price-list .treatment-accordion details" like
   the invalid Round 128 attempt — .treatment-accordion is combined on the same
   element as .price-list, not a separate ancestor, so that space-separated
   form never matches; this one skips it and targets .price-tier directly). */
.price-list details.price-tier{ border-bottom:none; border-top:1px solid var(--a-taupe); }
/* Fixing the border alone still left uneven row RHYTHM on cennik/index.html: a
   plain top-level .price-row is 44px tall (border 1 + padding-top 16 + a
   27.2px content line) with a real 16px margin-top stacked on top of that; an
   accordion .price-tier's <summary> is ~68px tall (border 1 + padding 20/20,
   .treatment-accordion summary's own real measured value — unmodified here,
   since Round 131 reuses the treatment page's summary verbatim) with NO margin
   at all (nothing on <summary> or bare <details> sets one). Mixed in one list
   that gave visibly different gaps depending on which two row types happened
   to be adjacent (45px / 60px / 68px / 83px, all in the same short list).
   Rather than shrink the accordion summary to match the plain row (that's the
   .price-tier--row road already tried and reverted above), give a top-level
   plain .price-row the accordion summary's own real padding/margin instead —
   scoped to being a DIRECT child of .price-list, so nested variant rows inside
   .price-tier-rows (which must keep their own compact 16px rhythm, matching
   the treatment page's real variant rows exactly) are untouched. */
.price-list > .price-row{ padding:20px 0; margin-top:0; }
/* cennik/index.html: small "i in a circle" link next to an accordion's own
   title, shown only when that price group has a real matching subpage under
   /zabiegi (or a standalone treatment URL) — subtle by default (--a-gray,
   the same muted tone as a row's duration text), darkens to --a-olive on
   hover/focus so it reads as interactive without competing with the price
   badge next to it. main.js's accordion click handler skips its own
   preventDefault()/toggle when the click target is inside an <a> (see the
   .treatment-accordion details click listener), so this link — and the
   pre-existing whole-title links this replaced on the 3 LightSheer®
   body-area accordions — actually navigates instead of just toggling the
   accordion open/closed.
   Round 138 (user: "przyklej ikonę do nazwy, nie do ceny"): moved from being
   a third flex child of .price-tier-label (sharing space with the price
   badge, so .treatment-accordion-q's own flex-grow:1 — added to fix the
   badge's right-edge alignment — pushed the icon along with the badge over
   to the row's right edge, away from the title it's meant to annotate) to
   living INSIDE the <h3> itself, right after the title text. inline-flex so
   it flows as part of the text (wraps with a long title, sits immediately
   after wherever the title's own text ends) instead of being a separate
   flex item positioned by the row's own layout. */
.accordion-info-link{
  display:inline-flex;
  align-items:center;
  height:18px;
  max-width:18px;
  overflow:hidden;
  margin-left:6px;
  vertical-align:-3px;
  flex:none;
  color:var(--a-gray);
  border-radius:999px;
  white-space:nowrap;
  transition:max-width .25s ease;
}
.accordion-info-link svg{ width:18px; height:18px; flex:none; display:block; }
/* Round 149 (user: "na desktopie po najechaniu na ikonę 'i' niech wyjeżdża z
   niej też klikalny napis 'INFORMACJE O ZABIEGU'"): the label sits inside the
   SAME <a>, right after the svg, always in the DOM — .accordion-info-link's
   own max-width (18px, exactly the icon's width) clips it out of view by
   default via overflow:hidden, so nothing needs to be hidden/shown with
   display or visibility. On hover/focus, max-width eases open to fit both
   icon and label, sliding the text out from behind the circle rather than
   popping it in.
   Round 153: two follow-ups. (1) Dropped the hover/focus color:var(--a-olive)
   swap — user wants icon + label to read as the SAME gray as a row's own
   duration text (--a-gray, .price-row p:first-child span's real color) at
   all times, not shift to the site's link-hover accent once expanded; color
   is no longer part of the transition either since it no longer changes.
   (2) (hover:hover) and (pointer:fine) alone still let the expand trigger at
   any width on a real desktop browser — e.g. a narrow, resized window still
   has a mouse — so added min-width:1025px, the site's own real desktop
   breakpoint (.nav-links's own switch point, see the comment above its
   @media (max-width:1024px) rule) rather than a made-up number, so "desktop"
   means the same thing here as it does for the nav itself. */
.accordion-info-link-label{
  font-family:"Inter",sans-serif;
  font-size:11px;
  font-weight:600;
  letter-spacing:.04em;
  text-transform:uppercase;
  color:var(--a-gray);
  padding:0 10px 0 6px;
}
@media (hover:hover) and (pointer:fine) and (min-width:1025px){
  .accordion-info-link:hover,
  .accordion-info-link:focus-visible{ max-width:220px; }
}
/* cennik/index.html (Round 135): a "group" accordion (e.g. "Epilacja laserowa
   LightSheer®") nests further .price-tier accordions inside its own
   .price-tier-rows (the S/M/L/Pakiety sub-items) instead of plain .price-row
   lines — reusing .price-tier-label/.price-tier-badge verbatim made this
   second level visually IDENTICAL to the outer one (same 15px/700 title, same
   20px summary padding, same ink-warm price), so there was no way to tell at a
   glance which accordion you'd already opened. Scaled down one notch instead
   of restyling from scratch: smaller/lighter title weight (14px/600, still
   Inter) and the price badge de-emphasized to --a-gray (the same muted tone
   already used for a row's own duration text). Compact 16px summary padding to
   match the surrounding .price-row rhythm one level deeper, rather than the
   roomier top-level 20px.
   Round 137 (user: "dodaj wcięcie od drugiego poziomu"): indentation added on
   the CONTAINER (.price-tier-rows--nested itself), not on the individual
   .price-tier children — a mixed group like Karboksyterapia bezigłowa CO2
   nests both a plain .price-row (its own single price line) AND a nested
   .price-tier (its Pakiety) as siblings inside the same container, so indenting
   the container shifts both of them in together and keeps them aligned with
   each other; indenting only .price-tier would have pushed the accordion in
   while leaving the plain row's price line flush with the group title above it.
   Round 147 (user: "szerokość wiersza w drugim poziomie niech będzie taka jak
   w pierwszym i trzecim"): padding-left on the CONTAINER shrinks every CHILD's
   own box from the left (their own right edge stays put, so their own width —
   and the border-top line drawn on that same box — shrinks by the full 24px),
   so a level-2 row's divider visibly stopped 24px short of where a level-1 or
   level-3 divider on either side of it reached. Moved the padding onto each
   child's own box instead (below) — padding sits INSIDE an element's own
   border, so it shifts that element's TEXT content right without moving the
   element's own edges at all: every row's box/divider now spans the exact
   same width regardless of level, only the text inside indents. */
.price-tier-rows--nested > .price-tier > summary{ padding-left:var(--sp-24); }
.price-tier-rows--nested > .price-row{ padding-left:var(--sp-24); }
/* Round 147 only indented level 2's OWN row — its content (e.g. "(L) duża
   partia ciała"'s own variant rows "Całe nogi"/"Całe ręce", or "Pakiety
   Elastyczne"'s package rows) lives inside THAT accordion's own
   .price-tier-rows, a plain one levels deeper again, so it never picked up
   any indent at all and rendered flush with level 1 — undoing the "wcięcie"
   from Round 137 for exactly the rows it was meant to cover, caught in a
   screenshot right after (user: "zobacz jakie tu kwiaty wyszły"). Same fix,
   one level deeper: padding-left on level 3's own row box, not a shared
   ancestor, so its own border/width still matches level 1 and 2 too. */
.price-tier-rows--nested > .price-tier .price-row{ padding-left:var(--sp-24); }
/* Round 145 (user: "tu się nie zgadzają odległości od separatorów" — a plain
   .price-row directly followed by a nested .price-tier, e.g. Karboksyterapia
   bezigłowa CO2's own line then its "Pakiety łączone"): .price-row's real,
   sitewide box model is padding-TOP only (16px) — the gap below its own text
   comes entirely from the NEXT sibling's border-top + padding-top, so its own
   text sits flush against its row's bottom edge. This nested summary instead
   had symmetric padding:16px 0 (top AND bottom), so its own text floated with
   air on both sides — right under a row whose text had none below it, the two
   adjacent lines read at visibly different distances from the divider between
   them even though the divider itself sits in the same place either way.
   Round 151 (user: "wysokość wierszy drugiego poziomu... mają być jak 1
   poziom"): matched level 2's own row height to level 1's real, symmetric
   padding:20px 0 (.treatment-accordion summary) instead of keeping it
   compact — level 1 and level 2 never sit as direct siblings (level 2 always
   lives inside level 1's own body), so there's no boundary between THEM to
   keep flush; the boundary Round 145 actually needed flush is level 2's own
   plain-row sibling within the same --nested container (e.g. Karboksyterapia
   bezigłowa CO2's line next to its own "Pakiety łączone") — matched together
   below, both now symmetric like level 1 instead of both top-only, so that
   pairing still reads consistently, just at the taller rhythm. Depth still
   reads from typography (14px/600, --a-gray badge) alone, not height. */
.price-tier-rows--nested > .price-tier > summary{ padding-top:20px; padding-bottom:20px; }
.price-tier-rows--nested > .price-row{ padding-top:20px; padding-bottom:20px; }
.price-tier-rows--nested > .price-tier .price-tier-label .treatment-accordion-q{
  font-size:14px;
  font-weight:600;
}
/* Round 142 (user: "w drugim poziomie może też nie pokazujmy cen"): a level-2
   sub-accordion's own "od X zł" badge was redundant/noisy right above its own
   variant rows, each already showing its own real price — hidden rather than
   just de-emphasized.
   Round 151: visibility:hidden, not display:none — the badge's own real,
   archon.au-measured line-height (16px/400/27.2px) is TALLER than the level-2
   title's (14px/600/21px), so on a level-1 row (badge still shown) the whole
   flex row's height is driven by the badge, not the title; once level-2's
   badge stopped rendering at all, its row shrank to just the shorter title's
   height, landing 6px shorter than level 1 even after matching their padding
   in the rule above this one. Keeping the badge in layout (space reserved,
   pixels invisible) restores the same height without putting the price back
   on screen. */
.price-tier-rows--nested > .price-tier > summary .price-tier-badge{ visibility:hidden; }
/* Round 138 (user: level 1 > level 2 in font size, but then level 3 came out
   BIGGER than both — confusing): a group's own price line — either the plain
   .price-row sitting directly in .price-tier-rows--nested (e.g. Karboksyterapia
   bezigłowa CO2's own line, a sibling of its nested Pakiety) or a variant row
   one level deeper inside that nested accordion's own .price-tier-rows (e.g.
   Epilacja laserowa's "Szpara międzypośladkowa" inside its "(S)" sub-accordion)
   — was still using the sitewide base .price-row p size (16px, archon.au's
   real measured #cost row value, left alone everywhere else on the site).
   Inside a group specifically, that made actual bookable price lines render
   LARGER than both the 15px group title above them and the 14px sub-accordion
   title directly above THEM, breaking the size ladder a reader would expect
   (bigger title → smaller sub-title → smaller still row text).
   Round 141 (user: an accordion with no group/level-2 at all — e.g. "Radio-
   frekwencja mikroigłowa RF", header straight to its own variant rows —
   still used the sitewide 16px, LARGER than a level-3 row one of the 5
   grouped accordions gets right next to it in the same list, even though
   both are exactly the same kind of content: the deepest, most granular
   bookable line under a top-level category). Widened from
   .price-tier-rows--nested specifically to .cennik-page's every
   .price-tier-rows, so any variant row nested inside ANY accordion on this
   page — grouped or not — reads at the same 13px, matching level 3 whether
   or not a level 2 happens to sit between it and the top. Scoped to
   .cennik-page (a class added only on cennik/index.html's <main>) rather than
   widened sitewide — the treatment page's own #cennik accordion rows keep
   their real, archon.au-measured 16px untouched; this is cennik's own,
   locally-introduced 3-tier hierarchy problem, not a sitewide one. */
.cennik-page .price-tier-rows .price-row p{ font-size:13px; }
/* main.js wraps EVERY .treatment-accordion-body's children in its own freshly
   created .treatment-accordion-body-inner div (for the height-animation system —
   see main.js, "document.querySelectorAll('.treatment-accordion-body').forEach"),
   regardless of section. That wrapper's own max-width:720px (sized for FAQ's prose
   answers) was still capping the price rows even after giving .price-tier-rows
   itself max-width:none, because the JS-made wrapper is a SEPARATE, outer element —
   not the one carrying that class in this file. .price-list-scoped override (same
   reasoning as the border-fix above — moved off the treatment page's #cennik id so
   it also reaches cennik/index.html's 8 sections, Round 128) removes the cap only
   where it doesn't belong, so the price rows span the full .container width like
   every other full-width element on the page, not a narrow reading column. */
.price-list .treatment-accordion-body-inner{ max-width:none; }
.price-tier-rows{ display:flex; flex-direction:column; }
.price-row{
  display:flex;
  justify-content:space-between;
  align-items:center;
  gap:var(--sp-16);
  padding-top:var(--sp-16);
  margin-top:var(--sp-16);
  border-top:1px solid var(--a-taupe);
}
.price-row:first-child{ margin-top:0; }
/* archon.au's real #cost .price-table row text (measured directly, live): Inter
   16px/400/27.2px for BOTH the name and the price — 15px/1.4 and a bold price
   were unmeasured guesses. Skips the real text-transform:capitalize measured on
   archon's own item names (an English title-case convention) — same documented
   exception already applied to FAQ's own dedicated heading class, since our real
   Polish body-area names are already correctly cased and capitalize would mangle
   them word-by-word. */
.price-row p{
  margin:0;
  font-family:"Inter",sans-serif;
  font-size:16px;
  font-weight:400;
  line-height:27.2px;
  color:var(--a-ink-warm);
}
/* :first-of-type (not :first-child) — a leading .promo-badge sibling (Round 140+
   package rows, e.g. "Pakiet 10x Endermologia") pushes the label <p> to be the
   row's 2nd child, so :first-child silently missed it (label text rendered full
   ink-warm/16px instead of gray/14px, unnoticed until Round 193 flagged it on a
   newly-built page — turned out to already be broken sitewide on every existing
   promo-badge package row too). :first-of-type still correctly targets ONLY the
   first <p> (the label) among .price-row's children regardless of what non-<p>
   siblings precede it. */
.price-row p:first-of-type span{ color:var(--a-gray); font-size:14px; }
.price-row > :last-child{ flex:0 0 auto; }
/* Round 159 (user: DERMOkonsultacja's real Fresha service description — "149 zł
   zaliczane na poczet zabiegu w ciągu 14 dni") — a short explanatory note tied
   to one specific price-row, on its own line below it (prose, not a name/price
   pair, so it doesn't fit .price-row's own flex layout). Italic + muted gray so
   it reads as commentary, distinct from the row itself; pulled up close to that
   row (negative margin-top) so it visually belongs to it, not to whatever comes
   next. Small gift-box icon reuses the site's own minimal stroke-icon language
   (16px viewBox, ~1.2px stroke, currentColor — same idiom as .accordion-info-link's
   circle-and-dot "i") instead of a system emoji, on request ("użyj ikony, która
   pasuje do stylu strony"). First attempt used a negative margin-top to pull it
   close to the row above, but that overlapped the row's own text/price/button
   (measured: -10px margin gave a -10px actual gap, i.e. real overlap, not just a
   tight visual pairing) — a small positive margin reads as "attached" without
   colliding. */
.price-row-note{
  display:flex;
  align-items:flex-start;
  gap:6px;
  margin:14px 0 var(--sp-16);
  font-family:"Inter",sans-serif;
  font-style:italic;
  font-size:13px;
  line-height:1.5;
  color:var(--a-gray);
}
.price-row-note svg{ flex:none; width:15px; height:15px; margin-top:1px; }
/* current, bookable price next to a struck-through .price-old regular price —
   rust ties it back visually to the "Promocja" badge on the Konsultacje
   accordion header itself, without repeating the badge on every row. Full size
   (16px, matching every other .price-row price), not the .price-old's de-emphasized
   14px — this is the real, payable price, not a secondary detail.
   Selector needs p:first-child + the class (not just .price-row .price-promo)
   because the price <p> sits inside .price-row-buy, making it a :first-child
   itself — .price-row p:first-child span (the row-label's gray/14px duration
   span rule, above) outranks a plain two-class selector and was winning. Same
   specificity pitfall as the original badge-inside-.price-row bug this session. */
.price-row p:first-child .price-promo{ color:var(--a-rust); font-size:16px; }
/* Round 157 (user: "dostosuj wielkość ceny w przypadku konsultacji dot.
   depilacji laserowej tak jak jest wszędzie w trzecim poziomie"): the rule
   above sets 16px sitewide, matching the treatment page's own #cennik
   accordion (its native, measured size) — but this promo price now also
   lives inside cennik/index.html's own nested .price-tier-rows (Round 156's
   Konsultacje→accordion conversion), where every other row's price is 13px
   (.cennik-page .price-tier-rows .price-row p, Round 141). Scoped override
   wins by extra specificity (adds .cennik-page + .price-tier-rows), not
   source order, so it stays correct regardless of future edits above.
   .price-old brought down to 11px in the same scope to keep the original
   16px/14px "promo price bigger than the struck-through old price"
   proportion at the smaller size, instead of ending up backwards. */
.cennik-page .price-tier-rows .price-row p:first-child .price-promo{ font-size:13px; }
.cennik-page .price-tier-rows .price-row .price-old{ font-size:11px; }
/* Round 133 (user: "ten rdzawy badge niech ma styl jak w pakietach depilacji
   laserowej taki sam kolor i rozmiar"): cennik/index.html's .promo-badge sits
   inside the SAME p:first-child as the row's gray/14px duration span (the
   generator puts name + duration + badge in one <p>, since .price-row only
   supports exactly 2 flex children — name and price), so the row above
   silently overrode it to gray/14px, exactly the same specificity pitfall
   already hit twice before by .price-promo and the original 0 zł bug — the
   base .promo-badge rule (own file, single class, specificity 0,1,0) never
   had a chance against .price-row p:first-child span (0,2,2). Restored here
   at higher specificity, matching .price-package-badge's real values (rust
   bg, cream text, 11px/700/uppercase) exactly, per the request. */
.price-row p:first-child .promo-badge{ color:var(--a-cream); font-size:11px; }
/* Round 140: .promo-badge moved OUT of the row's <p> (see below) — no longer a
   descendant of p:first-child at all, so the specificity fight this rule
   existed to win never happens anymore and the rule above is dead code. Left
   in place (harmless — it simply can't match anything now) rather than
   deleted, since the reasoning above is still useful history; the base
   .promo-badge rule's own color/size now apply untouched, uncontested. */
/* Round 152 (user: "jeśli jakaś pozycja ma rdzawy badge to cena tej pozycji
   też niech będzie rdzawa"): :has() so this applies to every current AND
   future promo-badge row automatically instead of hand-tagging each price
   with .price-promo one at a time — two selectors for the row's two real
   shapes (see the Round 140 comment above .price-row-buy): with a booking
   button, the price is .price-row-buy's own <p>; without one (the 2 combo
   deals with no serviceId), it's the row's bare 2nd <p> sibling. */
.price-row:has(.promo-badge) .price-row-buy > p,
.price-row:has(.promo-badge) > p:nth-of-type(2){ color:var(--a-rust); }

/* cennik/index.html: a treatment with several real Fresha positions (e.g. Epilacja
   laserowa LightSheer®'s S/M/L body areas, or any other multi-variant service in the
   full Fresha catalog aggregated here — Round 127) expands ONCE (single .price-tier
   details/summary, reusing the exact same mechanism/JS animation as the treatment
   page's own #cennik accordion) to reveal every real position at once — no nested
   per-tier accordions. Single-price items reuse the plain .price-row directly. */

/* Per-row booking button: reuses .treatment-card-cta verbatim (same "Kup pakiet"
   link style as the package cards) — wrapped with its price in .price-row-buy so
   .price-row keeps exactly two flex children and its existing space-between/
   :last-child rules above still apply unchanged. */
.price-row-buy{ display:flex; align-items:center; gap:var(--sp-24); }
/* Runda 181: a row with no CTA (just a bare price <p> as the row's own
   :last-child, e.g. "Wizyta kontrolna" · 0 zł, "+50 zł" add-ons) sits flush
   against the row's own right edge — but every OTHER row's price text sits
   ~119px further left, making room for its own .treatment-card-cta button
   (measured live: button ~95px + the row's own 24px gap). Down a list that
   mixes both row shapes, the no-button price visibly "jumps" right instead
   of reading as part of the same price column — reserve that same ~119px on
   the right of a bare price so it lines up with where prices sit elsewhere,
   instead of guessing at a single fixed price-column width for every row
   (button widths do vary a little by their own text, but they're all
   "Zarezerwuj" in every list this currently applies to). */
.price-row > p:last-child{ margin-right:119px; }
.price-row .treatment-card-cta{ margin-top:0; align-self:center; }
/* Round 140 (user: Round 139's "give the badge its own line" fix (below,
   narrowed to ≤767px) still looked broken between ~767–991px — wide enough
   that .price-row-buy stays inline instead of dropping to its own full-width
   line, so the row tried to fit name+duration+badge+price+button on one row,
   and only the badge (least essential, needing ~140px it couldn't get) spilled
   alone onto a 2nd line, vertically centered by align-items:center against the
   WHOLE row's height — reading as an accidentally stray, un-anchored chip
   rather than a positioned element. Root cause: the badge lived INSIDE the
   row's <p> as inline content (see gen_cennik_v2.py's `name + duration +
   badge` note above), so its position could only ever be wherever THAT
   specific text happened to wrap, never something CSS could pin. Moved out of
   <p> to be its own flex sibling (now the row's first DOM child, before <p>)
   so it can be positioned independent of the name text's own line breaks:
   ordered back to sit after the name on desktop (order:2, matching where it
   visually sat before) via :has() so ONLY badge-bearing rows get this
   restructuring — plain rows keep the original 2-child space-between exactly
   as before — and ordered FIRST (order:-1, row user asked for: "na górze
   wiersza a nie na dole czy po środku") below desktop's 991px breakpoint,
   where the row also stacks to one column per line: badge, then name, then
   price+button, always in that predictable order regardless of text length. */
/* Runda 180: all the reordering rules below use :has(> .promo-badge) — DIRECT
   child only — not the bare :has(.promo-badge) descendant match used by the
   .price-old/.price-promo/rust-price rules above. Runda 177/178 introduced a
   SECOND badge shape (.price-row-badges wrapper nested INSIDE the row's <p>,
   after the name/duration text, on laser-tulowy-plock) that :has(.promo-badge)
   would also match — but that shape already sits correctly via the row's
   plain 2-child space-between layout (name-<p>, .price-row-buy), the same as
   any badge-less row, so re-running this old shape's column-stacking at
   ≤991px (built only for the OLD direct-child shape below) broke it: price
   fully justified. */
.price-row:has(> .promo-badge){ justify-content:flex-start; }
.price-row:has(> .promo-badge) > :last-child{ margin-left:auto; }
.price-row .promo-badge{ order:2; margin-left:0; }
/* two shapes of row share this markup: [badge, name-<p>, .price-row-buy] when
   there's a booking button, or [badge, name-<p>, price-<p>] for the 2 combo
   deals that have none (see the generator note above .price-row-buy) — :nth-
   of-type(2) only ever matches a SECOND <p>, so it's a no-op in the first
   shape (there's only one <p>) and correctly targets the price line in the
   second, without two separate rules needing to know which shape they're in. */
.price-row:has(> .promo-badge) > p:first-of-type{ order:1; }
.price-row:has(> .promo-badge) > p:nth-of-type(2){ order:3; }
.price-row:has(> .promo-badge) > .price-row-buy{ order:3; }
@media (max-width:991px){
  .price-row:has(> .promo-badge){ flex-direction:column; align-items:flex-start; row-gap:var(--sp-8); }
  .price-row:has(> .promo-badge) > :last-child{ margin-left:0; }
  .price-row .promo-badge{ order:-1; }
}
@media (max-width:767px){
  .price-row{ flex-wrap:wrap; row-gap:var(--sp-8); }
  .price-row-buy{ width:100%; justify-content:space-between; }
}

/* PAKIETY sub-section: real data from instytutem.pl/pakiety, not archon.au (archon
   has no package-pricing equivalent — its whole pitch is "one price for all"). Reuses
   .treatment-cards/.treatment-card verbatim (same component as the S/M/L cards
   higher up this page) without the image block, so no new card visual language is
   introduced for content this page-specific. */
/* more air on request: bumped from the sitewide sp-80 section gap to sp-120 —
   Pakiety reads as its own distinct block, not just a continuation of the price
   list right above it. */
.price-packages{ margin-top:var(--sp-120); }
/* same real #cost divider color as the Cennik eyebrow above — reused here for
   visual consistency between the two sub-sections sharing this one light section
   (archon.au has no packages equivalent to measure directly for this one). */
.price-packages .treatment-intro-divider{ background:var(--a-gray); }
.price-package-card h3{ margin-top:0; }
/* on request: the per-treatment price is the main thing a customer's eye should
   land on in each card (it's the number that actually communicates the discount
   — "315 zł / zabieg" vs the regular 349 zł — better than the total package price
   does on its own), so it gets the biggest, boldest treatment in the card, well
   above the now-secondary total/count/validity line (reusing .treatment-card-time
   for that, unchanged). */
.price-package-per-treatment{
  display:flex;
  align-items:baseline;
  gap:6px;
  margin:16px 0 4px;
}
.price-package-per-treatment-num{
  font-family:"Inter",sans-serif;
  font-weight:700;
  font-size:36px;
  line-height:1.15;
  color:var(--a-ink-warm);
}
.price-package-per-treatment-suffix{
  font-family:"Inter",sans-serif;
  font-weight:400;
  font-size:15px;
  color:var(--a-gray);
}
.price-package-per-treatment-compare{
  font-family:"Inter",sans-serif;
  font-size:13px;
  color:var(--a-gray);
  margin:0 0 16px;
}
.price-package-card{ position:relative; }
/* on the light section, the featured card needs real contrast against the cream
   page instead of the rgba(255,255,255,.66) lift used elsewhere (that trick is for
   OLIVE backgrounds — on cream it would barely register): a solid white card with
   a taupe border, same shadow already used sitewide for lifted cards. */
.price-package-card--featured{
  border-radius:4px;
  background-color:var(--a-white);
  border:1px solid var(--a-taupe);
  box-shadow:0 12px 14px -7px rgba(122,119,114,.26);
}
/* on request: the 3 package names should sit at the same level across cards. The
   badge used to be an in-flow first child, pushing "comfort 10" down below where
   "mini 6"/"premium 20" start (they carry no badge) — positioned as an absolute
   "ribbon" hanging off the card's top edge instead, so it no longer consumes flow
   height and every card's h3 starts at the same padding-top position. Centered
   (left:50%/translateX(-50%), on request) rather than pinned to the card's own
   left padding. Accent color is the sitewide rust hover/accent (--a-rust, already
   used for nav-link/mega-menu/footer hovers and this section's own bullet dashes)
   — not the brand lime, which was only ever used here as an unrelated one-off pick. */
.price-package-badge{
  position:absolute;
  top:-13px;
  left:50%;
  transform:translateX(-50%);
  /* absolutely-positioned + left:50% (no matching `right`) shrink-to-fit sizing
     measures its "available width" from `left` to the containing block's right
     edge — effectively half the card's width — so at card widths around 900px
     viewport (~250px), the badge text wrapped to 2 lines even though it fits
     comfortably on one. That taller, wrapped badge poked further above the card
     (fixed top:-13px), eating into the gap from the paragraph above and reading
     as "too close" exactly at that range. nowrap sizes it to its real content
     width regardless of that constraint, keeping badge height constant. */
  white-space:nowrap;
  font-family:"Inter",sans-serif;
  font-weight:700;
  font-size:11px;
  letter-spacing:.04em;
  text-transform:uppercase;
  color:var(--a-cream);
  background:var(--a-rust);
  display:inline-block;
  padding:4px 10px;
  border-radius:2px;
  margin:0;
}
/* .treatment-card-cta's own margin-top:auto already pins the button to the card's
   bottom edge, but since .treatment-cards stretches all 3 cards to equal height,
   the tallest card (comfort 10, with the most list items) ends up with almost no
   gap between its list and button — the auto margin has nothing left to consume.
   Both margins here guarantee real breathing room on both sides of the list
   (description→list, list→button) in every card, not just the shorter ones that
   already had slack from the equal-height stretch. */
.price-package-list{
  list-style:none;
  margin:var(--sp-24) 0 var(--sp-40);
  padding:0;
  display:flex;
  flex-direction:column;
  gap:6px;
}
.price-package-list li{
  font-family:"Inter",sans-serif;
  font-size:14px;
  line-height:20px;
  color:var(--a-ink-warm);
  padding-left:16px;
  position:relative;
}
.price-package-list li::before{ content:"–"; position:absolute; left:0; color:var(--a-rust); }
/* archon.au's real fine-print asterisk note (measured directly on #cost
   .paragraph.asterisk.dark, live): Inter 12px/400/20.4px, color rgb(63,61,59)
   = --a-ink-warm — NOT the muted --a-gray/13px/1.5 this had before, which was
   never actually measured for this specific component. margin-top 40px already
   matched (--sp-40). */
.price-packages-note{
  font-family:"Inter",sans-serif;
  font-size:12px;
  font-weight:400;
  line-height:20.4px;
  color:var(--a-ink-warm);
  margin:var(--sp-40) 0 0;
}

/* the reference site's real "15-Minute Block" / "30-Minute Block" / "1-Hour Block"
   cards (.treatment-cards): square photo, bold 15px h3, 1px divider, bold 16px
   price, 14px duration, 14px description, then an underlined "Book Just this"
   link with a trailing arrow pinned to the card's bottom — all measured
   directly on archon.au. display:flex + flex-wrap:wrap (not grid) is archon's
   own mechanism for going from 3-across to stacked at narrow widths, so this
   reuses the same approach instead of a media query. */
.treatment-cards{
  display:flex;
  flex-wrap:wrap;
  gap:30px 20px;
  margin-top:var(--sp-24);
}
/* more air on request, one step up the sitewide 8px spacing scale from the 64px
   "heading→list" convention used elsewhere (#wskazania, .price-list above) — this
   particular gap (description paragraph → cards) reads tighter than those since
   the cards themselves are visually heavier (bordered/padded boxes, not bare text
   rows), so it earns the extra room. Placed AFTER .treatment-cards (same
   specificity, so source order decides) — an earlier attempt at this same
   position lost to .treatment-cards' own 24px and never actually took effect,
   the same class-ordering bug already found and fixed for the mobile breakpoint
   below (Round 70). */
.price-package-cards{ margin-top:var(--sp-120); }
.treatment-card{
  /* the reference site's real flex sizing (measured directly, not the
     flex-basis:300px this had before): flex-basis:0%, min-width:31%,
     max-width:50% — the max-width is what matters: it caps a lone card
     wrapped onto its own row at half-width instead of flex-grow stretching
     it to fill the whole row, which is what a bare `flex:1 1 300px` (no
     upper bound) was doing here. */
  flex:1 1 0%;
  min-width:31%;
  max-width:50%;
  display:flex;
  flex-direction:column;
  /* the reference site's real hover: measured directly on archon.au as a
     plain CSS :hover (not a Webflow IX2 interaction) on .treatment-cards-wrapper
     — padding:20px is part of that same rule (the card lifts and a white
     card-shape appears behind the padded content, not flush against the
     photo's edge), transition 0.3s cubic-bezier(.25,.46,.45,.94) (the same
     easing already used elsewhere on this site, e.g. .abtn:hover). */
  padding:20px;
  transition:transform .3s cubic-bezier(.25,.46,.45,.94), box-shadow .3s cubic-bezier(.25,.46,.45,.94), background-color .3s cubic-bezier(.25,.46,.45,.94);
}
.treatment-card:hover{
  transform:translateY(-8px);
  transform-origin:50% 100%;
  border-radius:4px;
  background-color:rgba(255,255,255,.66);
  box-shadow:0 12px 14px -7px rgba(122,119,114,.26);
}
@media (max-width:479px){
  /* the reference site's real breakpoint (measured: still 31%/50% at 480px,
     switches to 100%/100% exactly at 479px) — same tier used sitewide for
     the narrowest mobile rules. */
  .treatment-card{ min-width:100%; max-width:100%; }
}
/* on request: one package box per row on mobile (3 stacked rows), not the shared
   .treatment-card breakpoint above (479px, measured for the S/M/L cards higher up
   this page — a different, archon-original component this must not affect) —
   package cards are our own content and, being 3-wide with generous 32px padding,
   read as cramped in the ~480-767px range where the shared component still shows
   2-up. Placed after .treatment-card's own rules (same specificity, so source
   order decides) so this actually wins in that range. */
@media (max-width:767px){
  .price-package-card{ min-width:100%; max-width:100%; }
}
/* package cards are our own content, not a literal archon.au component (unlike the
   S/M/L cards, which reuse this same .treatment-card class 1:1 from a measured
   archon element) — safe to give them more interior breathing room on request
   without touching that shared, measured padding used by the S/M/L cards too.
   Extra bottom padding specifically for more air below the "Kup pakiet" button.
   Placed after .treatment-card's own padding:20px rule above (equal specificity,
   so source order decides) — an earlier attempt at this same position lost to
   that rule and never actually took effect; verified this time via
   getComputedStyle, not just a screenshot (same class-ordering pitfall as
   Rounds 70/72, logged as lesson #20 in the "Ważne odkrycia" section above). */
.price-package-card{ padding:32px 32px 56px; }
.treatment-card-image-link{
  position:relative;
  overflow:hidden;
  aspect-ratio:1/1;
  display:block;
}
.treatment-card-image{ width:100%; height:100%; object-fit:cover; }
.treatment-card h3{
  font-family:"Inter",sans-serif;
  font-weight:700;
  font-size:15px;
  color:var(--a-cream);
  margin:20px 0 10px;
}
.section--cream .treatment-card h3{ color:var(--a-ink-warm); }
.treatment-card-divider{
  height:1px;
  background:rgba(212,212,212,.15);
  margin-bottom:10px;
}
.section--cream .treatment-card-divider{ background:var(--a-taupe); }
.treatment-card-price{
  font-family:"Inter",sans-serif;
  font-weight:700;
  font-size:16px;
  color:var(--a-cream);
  margin:0;
}
.section--cream .treatment-card-price{ color:var(--a-olive-black); }
.treatment-card-time{
  font-family:"Inter",sans-serif;
  font-weight:400;
  font-size:14px;
  /* dimmed cream, as an actual color value rather than element opacity — an
     opacity:.8 here would collide with the scroll-reveal system's own
     opacity toggle on this same element ([data-reveal], added below), since
     both would fight over the one CSS property. */
  color:rgba(241,237,231,.8);
  margin:0 0 20px;
}
.section--cream .treatment-card-time{ color:var(--a-ink-warm); }
.treatment-card-desc{
  font-family:"Inter",sans-serif;
  font-weight:400;
  font-size:14px;
  color:rgba(241,237,231,.8);
  margin:0 0 20px;
}
.section--cream .treatment-card-desc{ color:var(--a-ink-warm); }
.treatment-card-cta{
  display:flex;
  flex-direction:column;
  align-items:flex-start;
  overflow:hidden; /* archon.au's .arrow-button: clips the underline's horizontal
                       hover-jump, measured live (getComputedStyle) rather than guessed */
  align-self:flex-start;
  margin-top:auto;
  font-family:"Inter",sans-serif;
  font-weight:500;
  font-size:14px;
  color:var(--a-cream);
}
.section--cream .treatment-card-cta{ color:var(--a-olive-black); }
.treatment-card-cta-title-wrap{
  display:flex;
  align-items:center;
  gap:6px; /* archon.au .title-wrapper: measured gap between text and arrow is 6px, not 8px */
}
.treatment-card-cta-underline{
  width:100%;
  height:1px;
  background:var(--a-cream);
}
.section--cream .treatment-card-cta-underline{ background:var(--a-olive-black); }
@keyframes cta-underline-jump{
  0%{ transform:translateX(0); }
  50%{ transform:translateX(100%); }
  50.01%{ transform:translateX(-100%); }
  100%{ transform:translateX(0); }
}
.treatment-card-cta:hover .treatment-card-cta-underline{
  animation:cta-underline-jump .6s ease-out; /* archon.au IX2 "Arrow Button Hover In"
    (a-33): TRANSFORM_MOVE .button-underline x:100% 300ms easeOut, teleport to
    -100%, slide back to 0 in 300ms easeOut — runs in parallel with the arrow */
}
.treatment-card-cta-arrow{
  width:14px;
  height:10px;
  display:flex;
  align-items:center;
  justify-content:center;
  overflow:hidden; /* archon.au's .button-arrow-3 wrapper: clips the arrow during
                       the hover jump so it never visibly leaves the button */
  flex:0 0 auto;
}
.treatment-card-cta-arrow svg{ width:14px; height:10px; }
@keyframes cta-arrow-jump{
  0%{ transform:translateX(0); }
  50%{ transform:translateX(15px); }
  50.01%{ transform:translateX(-15px); }
  100%{ transform:translateX(0); }
}
.treatment-card-cta:hover .treatment-card-cta-arrow svg{
  animation:cta-arrow-jump .6s ease-out; /* archon.au IX2 "Arrow Button Hover In"
    (a-33): TRANSFORM_MOVE .button-arrow-3 x:15px 300ms easeOut, teleport to
    -15px, slide back to 0 in 300ms easeOut — measured via ix2 store, not guessed */
}

/* the reference site's real "Never had Laser? Get 50% off..." split-2 promo:
   text column left (eyebrow+divider+h2+paragraph+CTA) / photo column right,
   both full section height — all measured directly, including the ≥992px
   breakpoint (the same tablet tier as the intro grid and hero, confirmed
   again here rather than assumed) and the mobile column-reverse stacking
   (photo first, text below, not the other way round). No .container/max-width
   here on purpose — archon.au's own version has none either (confirmed: its
   image column runs flush to the viewport edge on the right, zero gutter).
   A prior round wrapped this in the sitewide .container to give it the same
   margins as the rest of the page, which technically worked but produced a
   visible dark gap between the photo and the viewport edge that archon.au
   doesn't have — reverted on request, back to archon.au's real mechanism:
   the LEFT gutter comes from .treatment-split-content's own padding-left
   (equal to the sitewide clamp(20px,5%,72px), same value, just applied here
   as padding instead of a wrapping container), while the RIGHT side (the
   photo) bleeds all the way to the viewport edge with no cap, matching. */
.treatment-split{
  display:flex;
  flex-direction:column-reverse;
}
@media (min-width:992px){
  .treatment-split{
    display:grid;
    grid-template-columns:1fr 2fr;
  }
}
.treatment-split-content{
  /* horizontal was a fixed 18.75px, only correct at the 375px width it was
     originally measured at — it's really the same sitewide gutter formula
     as everywhere else (measured directly on archon.au's .left-content at
     815px: 40px = max(20px,5%), same mechanism as .container), just never
     switched from the flat px value to the formula. Vertical (56.25px)
     left as-is — that one genuinely isn't a simple %-of-width formula. */
  padding:56.25px max(20px, 5%);
  display:flex;
  flex-direction:column;
}
@media (min-width:992px){
  /* clamp() here must use vw, not the sitewide %, unlike .container's own
     clamp(20px,5%,72px) — that % correctly resolves against the viewport
     because .container has no narrower ancestor constraining it, but this
     element is a grid ITEM inside .treatment-split (a 1fr column, 475px at
     1440px wide), so a % here would resolve against that narrow column
     instead (measured bug: 24px instead of ~72px) — vw always resolves
     against the viewport regardless of nesting, giving the same real gutter. */
  .treatment-split-content{
    padding:47.5px 47.5px 47.5px max(20px, 5vw);
    /* the reference site's real mechanism for "paragraph+button stuck to the
     bottom of the banner": .left-content is a 2-row CSS grid (measured:
     grid-template-rows come out as two near-identical halves, i.e. 1fr 1fr)
     — NOT a fixed margin-top on the heading. A fixed px gap (what this used
     to be) only ever matches archon.au's own photo's specific height; with a
     different photo (different aspect ratio → different section height) the
     footer would sit at the wrong spot. The 1fr/1fr split + the footer's own
     justify-content:flex-end (below) reproduces the real, height-independent
     behavior instead. */
    display:grid;
    grid-template-rows:1fr 1fr;
    /* Real bug found at tablet widths (~1080px): this row-split trick only
     produces visible spacing when there's slack left over in each row after
     its own content — but our heading is real Polish marketing copy, much
     longer than archon's own short English original, so at some widths it
     wraps to just enough lines to fill its entire 1fr row with zero slack
     left (measured directly: heading's own bottom edge and the paragraph's
     own top edge landed on the exact same pixel, 0px gap — not a rounding
     artifact). A guaranteed minimum row-gap fixes it at every width without
     touching the row-split mechanism itself, which still does its job
     whenever there IS slack (e.g. shorter headings, wider desktop columns). */
    row-gap:32px;
  }
}
.treatment-split-top{ margin-bottom:44px; }
@media (min-width:992px){
  /* the grid row split above already provides the spacing on desktop —
     measured directly as 0 extra margin between the two halves. */
  .treatment-split-top{ margin-bottom:0; }
}
.treatment-split-title-line{ margin-bottom:20px; }
.treatment-split-divider{
  height:1px;
  background:#1E1D1D;
  margin-bottom:22px;
}
@media (min-width:992px){ .treatment-split-divider{ margin-bottom:27px; } }
.treatment-split-heading{
  font-family:"Tenor Sans",Georgia,serif;
  font-weight:500;
  font-size:30px;
  line-height:36px;
  letter-spacing:-1px;
  color:var(--a-cream);
  margin:0;
}
.treatment-split-footer{
  display:flex;
  flex-direction:column;
  align-items:flex-start;
}
@media (min-width:992px){
  /* pushes the paragraph+CTA to the bottom of this row's own half of the
     content box — measured directly (button's own bottom edge sits flush
     with the row's bottom edge, 0px gap) — this is the real "stuck to the
     bottom" archon.au behavior. */
  .treatment-split-footer{ justify-content:flex-end; }
  /* real bug found: .treatment-card-cta (shared with the S/M/L/package cards,
     where margin-top:auto is the ONLY bottom-pinning mechanism) also carries
     that auto margin here — an auto margin on a flex item takes priority over
     the parent's own justify-content for distributing free space, so inside
     this now grid-stretched, taller-than-its-content footer box it swallowed
     ALL the slack itself and dragged the button away from the paragraph
     (measured: 93.5px gap instead of the real 10px). justify-content:flex-end
     above already does the "stick to bottom of the banner" job on its own;
     this cancels the competing auto margin so the button sits its normal
     10px (the paragraph's own margin-bottom) below the paragraph instead. */
  .treatment-split-footer .treatment-card-cta{ margin-top:0; }
}
.treatment-split-footer p{
  font-family:"Inter",sans-serif;
  font-size:16px;
  line-height:27.2px;
  color:var(--a-cream);
  margin:0 0 10px;
}
/* #promo (Pakiet Powitalny) needs more breathing room than the archon.au-measured
   10px — scoped to this section only, .treatment-split--price keeps the original
   10px. Since Runda 161 this also does double duty as the visible gap the user
   asked for between the two <p> the copy is now split into ("Zarezerwuj termin
   we Fresha..." on its own paragraph) — no extra CSS needed, this rule already
   applies its margin-bottom to every <p> in the section, including that one. */
#promo .treatment-split-footer p{ margin-bottom:var(--sp-24); }
/* Runda 161 (użytkownik: "wyróżnij coś ważnego na rdzawy nasz kolor") — zastępuje
   dawny .promo-code (kod rabatowy usunięty z treści #promo w Rundzie 160, ta sama
   idea rdzawego wyróżnienia zastosowana teraz do konkretnych kwot). */
#promo .promo-highlight{ color:var(--a-rust); font-weight:600; }
.treatment-split-image-wrapper{
  position:relative;
  overflow:hidden;
  height:450px;
}
@media (min-width:992px){ .treatment-split-image-wrapper{ height:auto; } }
.treatment-split-image{ width:100%; height:100%; object-fit:cover; display:block; }

/* .treatment-split--price: mirrored variant for the "ONE PRICE FOR ALL"-style
   banner (archon.au's real .split-1 — measured live: image LEFT/text RIGHT,
   grid-template-columns:2fr 1fr at ≥992px, i.e. the exact opposite ratio and
   side of the promo section's .split-2). Image already comes first in the
   HTML here, so mobile just needs plain column (not column-reverse — no flip
   needed, unlike the promo section where DOM order was text-then-photo). */
.treatment-split--price{ flex-direction:column; }
@media (min-width:992px){
  .treatment-split--price{ grid-template-columns:2fr 1fr; }
  /* mirrored padding: small inner gap on the left (next to the image), the
     real sitewide gutter on the right (outer edge) — measured directly on
     archon.au's .right-content: 47.5px 71.25px 47.5px 47.5px. */
  .treatment-split--price .treatment-split-content{ padding:47.5px max(20px, 5vw) 47.5px 47.5px; }
}
/* archon.au's real text here is ink-warm (rgb(63,61,59)), not the cream this
   component's base rules assume (built for the dark promo section only) —
   this is a light .section--cream context, so override explicitly. Simpler
   content split than the promo section too: real archon.au groups the
   paragraph with the eyebrow/heading (not with the button), and its footer
   row isn't an even 1fr/1fr split (measured: 279px/45px, content-sized, not
   halves) — reusing .treatment-split-top/-footer as generic "text block" and
   "button block" containers instead of replicating that exact asymmetric
   grid, since the visual difference is negligible on a section this short. */
.treatment-split--price .eyebrow{ color:var(--a-ink-warm); }
.treatment-split--price .treatment-split-heading{ color:var(--a-ink-warm); }
.treatment-split-top p:not(.eyebrow){
  /* :not(.eyebrow) matters — the eyebrow is also a bare <p>, and without this
     exclusion this rule's font-size (16px) was winning over .eyebrow's own
     .75rem (higher specificity: class+element beats class alone), silently
     resizing the eyebrow instead of just styling the description paragraph. */
  font-family:"Inter",sans-serif;
  font-size:16px;
  line-height:27.2px;
  color:var(--a-ink-warm);
  margin:16px 0 0;
}

/* archon.au's real #care ("treatment recommendations") tab component, measured
   directly: eyebrow→heading gap 47px (same value already used for #wskazania —
   consistent, not coincidence), heading→tab-menu gap 104px, tab-menu→content gap
   50px. 3 equal-width columns (flex:1, not sized to text), each with its own
   border-bottom acting as an underline — active tab: cream/600, its own
   full-width cream underline; inactive: taupe/400, gray underline. On request,
   the underline segments now have a visible gap between them: the 30px spacing
   moved from each tab's own right padding into the flex container's own `gap`,
   so that gap sits OUTSIDE every tab's border-box and the border-bottom simply
   doesn't reach across it — no separate pseudo-element needed. */
#postepowanie .eyebrow{ margin-bottom:47px; }
#postepowanie .h-section{ margin-bottom:0; }
.care-tabs{
  display:flex;
  gap:30px;
  margin-top:104px;
  margin-bottom:50px;
}
.care-tab{
  flex:1 1 0%;
  text-align:left;
  background:none;
  border:none;
  border-bottom:1px solid var(--a-gray);
  padding:9px 0;
  font-family:"Inter",sans-serif;
  font-size:16px;
  line-height:27.2px;
  font-weight:400;
  color:var(--a-taupe);
  cursor:pointer;
}
.care-tab.is-active{ color:var(--a-cream); font-weight:600; border-bottom-color:var(--a-cream); }
.section--cream .care-tab{ color:var(--a-gray); border-bottom-color:var(--a-taupe); }
.section--cream .care-tab.is-active{ color:var(--a-ink-warm); border-bottom-color:var(--a-ink-warm); }
/* archon.au's real tab-pane switch (measured on the live Webflow w-tabs element:
   data-duration-in="300" data-duration-out="100" data-easing="ease") — main.js
   cross-fades via inline opacity/transition (asymmetric durations each direction,
   can't be done with one CSS transition rule), not an instant hidden-attribute
   swap. [hidden] stays as the reduced-motion / no-JS fallback. */
.care-panel[hidden]{ display:none; }
/* archon.au's real list marker: a plain disc bullet (list-style:disc), not a
   custom dash — measured, not guessed, unlike most other lists on this page
   which deliberately use a leading-divider pattern instead. */
.care-panel{
  list-style:disc;
  padding-left:20px;
  margin:0;
}
/* archon.au's real mobile behaviour for this component (measured live at ≤767px,
   the same breakpoint already used sitewide, e.g. #wskazania): the 3 tabs stack
   vertically instead of sitting in equal-width columns, each getting its own
   full-width underline — not just the row wrapping under narrow flex-wrap. The
   30px column gap doesn't carry over as a row gap either (measured: adjacent
   stacked tabs touch exactly, spacing comes only from each tab's own 9px
   padding) — so `gap` is reset to 0, not left at 30px. Surrounding spacing also
   shrinks (eyebrow→heading 17px — same value as #wskazania's own mobile
   override; heading→tabs 74px; tabs→content 25px), all measured, not scaled by
   a guessed ratio. */
@media (max-width:767px){
  #postepowanie .eyebrow{ margin-bottom:17px; }
  .care-tabs{ flex-direction:column; gap:0; margin-top:74px; margin-bottom:25px; }
}
.care-panel li{
  font-family:"Inter",sans-serif;
  font-size:16px;
  line-height:27.2px;
  color:var(--a-taupe);
  padding-bottom:10px;
}
.section--cream .care-panel li{ color:var(--a-ink-warm); }

/* archon.au's real #Solution (.section-parallax) — full-bleed photo banner CTA,
   measured directly: fixed height 400px, centered content, heading Tenor Sans
   36px/400/43.2px/cream/center, button-wrapper margin-top 50px (gap to button).
   No separate dark overlay in the real component (measured: fully transparent,
   .abtn's own hover hasn't been paired with a magnetic-cursor JS effect archon
   uses — same reasoning as skipping that elsewhere on this page: a genuine
   Webflow interaction detail already scoped out of this project's animation
   budget, not an oversight). Button reuses the already-existing, already-
   measured .abtn.outline-light 1:1 (same 44px height/27px padding/2px radius/
   cream border as archon's real .button.outline). */
.cta-banner{
  position:relative;
  height:400px;
  display:flex;
  align-items:center;
  justify-content:center;
  overflow:hidden;
}
.cta-banner-image{
  position:absolute;
  top:-90px;
  left:0;
  width:100%;
  height:calc(100% + 180px);
  object-fit:cover;
  will-change:transform;
}
.cta-banner-content{
  position:relative;
  z-index:1;
  text-align:center;
  padding:0 20px;
}
.cta-banner-heading{
  font-family:"Tenor Sans",Georgia,serif;
  font-weight:400;
  font-size:36px;
  line-height:43.2px;
  color:var(--a-cream);
  margin:0;
}
.cta-banner-content .abtn{ margin-top:50px; }

/* scroll-reveal — the reference site's own real, confirmed IX2 presets
   ("slideInBottom"/"fadeIn"), read directly out of its Webflow.require('ix2')
   store rather than guessed: opacity 0→1 (+ translateY(100px)→0 for the
   "slide" variant), duration 1000ms, easing "outQuart" (the standard
   ease-out-quartic curve, cubic-bezier(.25,1,.5,1)). JS (main.js) adds
   .is-revealed via IntersectionObserver, which fires immediately for
   anything already in view on load — so nothing gets stuck invisible if a
   user never scrolls, unlike the scroll-reveal mistake documented in
   CLAUDE.md's "Błędy, które popełniliśmy" #4. */
[data-reveal]{ opacity:0; }
[data-reveal="slide"]{ transform:translateY(100px); }
[data-reveal].is-revealed{
  opacity:1;
  transform:none;
  transition:opacity 1s cubic-bezier(.25,1,.5,1), transform 1s cubic-bezier(.25,1,.5,1);
}
/* the reference site's real "Divider Scroll into View" preset (read the same
   way, via ix2 store, not guessed): width 0%→100%, 300ms, "easeIn" (the
   standard CSS ease-in curve). Unlike the fade/slide variants above, the
   reference site's own divider never has opacity:0 — only width animates —
   so this variant overrides the shared opacity:0 back to fully opaque. */
[data-reveal="grow"]{ opacity:1; width:0%; }
[data-reveal="grow"].is-revealed{
  width:100%;
  transition:width .3s ease-in;
}
/* the reference site's real image reveal on the "Rekomendacje sezonowe" cards
   (`.treatment-cards-wrapper.dark img`): opacity stays at 1 throughout — only a
   slow scale-in, measured by sampling its live computed transform every ~50ms
   during the actual scroll-into-view transition (not guessed): scale(1) settling
   to scale(1.085) over roughly 2.5s, easing slow→fast→slow (approximated here
   with a symmetric ease-in-out cubic-bezier — Webflow's exact internal curve for
   this specific effect isn't exposed via its IX2 store, unlike the shared fade/
   slide/grow presets above, which are read directly from it). */
[data-reveal="zoom"]{ opacity:1; transform:scale(1); }
[data-reveal="zoom"].is-revealed{
  transform:scale(1.085);
  transition:transform 2.5s cubic-bezier(.65,0,.35,1);
}
@media (prefers-reduced-motion: reduce){
  [data-reveal]{ opacity:1 !important; transform:none !important; width:100% !important; }
}

/* ============ BLOG (2026-09-09) ============
   Zmierzone na żywym archon.au: listing "/articles/skincare" (nav "Articles & News")
   i pojedynczy wpis "/articles/skincare-and-grooming-essentials-guide-for-australian-men"
   — desktop viewport 1440px (resize_window, nie domyślny wąski panel podglądu, który
   fałszywie wygląda jak układ 1-kolumnowy mobile). Kolor tekstu ujednolicony na
   --a-ink-warm (zasada "jedna czerń na całej stronie") — archon w tym jednym komponencie
   listy miał inny odcień (rgb(30,30,32)), ale na stronie pojedynczego wpisu H1 i akapity
   już używają dokładnie #3F3D3B, więc to prawdopodobnie niezamierzona niekonsekwencja
   źródła, nie świadomy wybór do skopiowania. */

.blog-grid{
  display:grid;
  grid-template-columns:repeat(2, 1fr);
  gap:var(--sp-64);
}
@media (max-width:767px){
  .blog-grid{ grid-template-columns:1fr; }
}

.blog-card{ display:block; color:inherit; text-decoration:none; }
.blog-card-thumb{
  display:block;
  width:100%;
  aspect-ratio:621/400;
  border-radius:20px;
  overflow:hidden;
  margin-bottom:24px;
}
.blog-card-thumb img{ width:100%; height:100%; object-fit:cover; display:block; filter:grayscale(85%) sepia(8%); }
.blog-card-meta{
  display:flex; align-items:center; gap:8px;
  font-family:"Inter",sans-serif; font-size:12px; font-weight:400; line-height:16px;
  color:var(--a-ink-warm);
  margin-bottom:8px;
}
.blog-card-meta .dot-small{ width:4px; height:4px; border-radius:100px; background:var(--a-ink-warm); flex:none; }
.blog-card-title{
  font-family:"Inter",sans-serif; font-size:24px; font-weight:500; line-height:31.2px;
  letter-spacing:-0.48px; color:var(--a-ink-warm); margin:0 0 10px;
}
.blog-card-line{ display:block; width:100%; height:1px; background:#D2D2D7; margin:24px 0 8px; }

/* Pojedynczy wpis — struktura DOKŁADNIE odtworzona z żywego archon.au (2026-09-09, druga
   runda pomiarów po uwadze użytkownika "1:1, żebym nie mógł się do niczego przyczepić").
   Pierwsza runda pomiarów złapała tylko powierzchowne wartości typograficzne i pominęła
   prawdziwy układ: archon NIE ma linku powrotu przed hero (usunięty), tytuł siedzi w gridzie
   2-kolumnowym (druga kolumna pusta — prawdopodobnie zarezerwowana pod nagłówek/cytat na
   innych wpisach), data+autor to OSOBNY wiersz PO tytule (nie przed nim, nie przy zdjęciu),
   w formacie "DATA / AUTOR" z ukośnikiem (nie kropką) i własnym podkreśleniem (divider-line),
   a sama treść artykułu siedzi w DRUGIEJ kolumnie 2-kolumnowego gridu — pierwsza kolumna to
   pusty "spacer" (weryfikowane wprost w DOM, nie domysł). Wartości opacity:0/width:0% złapane
   przy pomiarze to niewystrzelone jeszcze animacje wejścia (Webflow IX2, ten sam mechanizm co
   nasze [data-reveal]) — nie mają wpływu na finalne, docelowe wartości typografii/koloru/
   marginesów użyte tutaj. */
/* Pionowa paralaksa (2026-09-09) — ten sam wzorzec co już istniejący .cta-banner-image
   (przewymiarowany <img> przesuwany transformem na scroll, patrz main.js), zastosowany na
   zdjęciu hero wpisu blogowego: kontener position:relative/overflow:hidden, obraz o 100px
   większy niż kontener (50px zapasu na górze i dole) żeby przesunięcie nigdy nie odkryło
   pustej krawędzi. */
.blog-hero-image{
  position:relative; display:block; width:100%; aspect-ratio:1283/640; border-radius:20px;
  overflow:hidden; margin-bottom:32px;
}
.blog-hero-image img{
  position:absolute; top:-50px; left:0; width:100%; height:calc(100% + 100px);
  object-fit:cover; display:block; will-change:transform; filter:grayscale(85%) sepia(8%);
}

.blog-post-header{
  display:grid; grid-template-columns:3fr 2fr; column-gap:72px; margin:0 0 50px;
}
.blog-post-header h1{
  font-family:"Inter",sans-serif; font-size:56px; font-weight:400; line-height:61.6px;
  letter-spacing:-2px; color:var(--a-ink-warm); margin:0;
}

.blog-byline-row{ display:grid; grid-template-columns:1fr 2fr; column-gap:40px; }
.blog-byline{
  font-family:"Inter",sans-serif; font-size:12px; font-weight:600; letter-spacing:0.5px;
  text-transform:uppercase; color:var(--a-ink-warm); margin:0;
}
/* Linia pod datą/autorem jest SIOSTRĄ gridu .blog-byline-row (pełna szerokość kontenera),
   NIE elementem wewnątrz jego wąskiej kolumny — zweryfikowane wprost w DOM archon.au
   (.divider-line jest bezpośrednim dzieckiem pełnoszerokiego .section-title-line.home,
   nie zagnieżdżone w jego wewnętrznym _2-column-grid) i potwierdzone przez użytkownika
   po zrzucie ekranu z pierwszej (błędnej) wersji, 2026-09-09. */
.blog-byline-divider{ height:1px; width:100%; background:var(--a-gray); margin:20px 0 25px; }

.blog-content-row{ display:grid; grid-template-columns:1fr 2fr; column-gap:40px; }
.blog-content-row .blog-spacer{ display:block; }
.blog-article-body .blog-lede{
  font-family:"Inter",sans-serif; font-size:28px; font-weight:500; line-height:40px;
  color:var(--a-ink-warm); margin:0 0 10px;
}
.blog-article-body p{
  font-family:"Inter",sans-serif; font-size:16px; font-weight:400; line-height:27.2px;
  color:var(--a-ink-warm); margin:0 0 10px;
}
.blog-article-body h2{
  font-family:"Inter",sans-serif; font-size:24px; font-weight:500; line-height:28.8px;
  letter-spacing:-0.5px; color:var(--a-ink-warm); margin:60px 0 20px;
}
.blog-article-body h3{
  font-family:"Inter",sans-serif; font-size:16px; font-weight:600; line-height:19.2px;
  color:var(--a-ink-warm); margin:30px 0 10px;
}
/* Numerowany ranking (np. "Ranking najskuteczniejszych laserów") — pozycja jako
   stonowany numer obok nagłówka podsekcji, zamiast gołego h3. Reużywa wzorca
   liczb .treatment-benefit-num (waga/kolor), dopasowany do rozmiaru h3 wpisu. */
.blog-rank-item{ display:flex; align-items:baseline; gap:16px; margin:30px 0 10px; }
.blog-rank-item h3{ margin:0; }
.blog-rank-num{
  font-family:"Inter",sans-serif; font-weight:600; font-size:20px; line-height:19.2px;
  color:var(--a-rust); flex:0 0 auto;
}
.blog-article-body ul{ list-style:disc; margin:0 0 20px; padding-left:20px; }
.blog-article-body ol{ list-style:decimal; margin:0 0 20px; padding-left:20px; }
.blog-article-body li{
  font-family:"Inter",sans-serif; font-size:16px; font-weight:400; line-height:27.2px;
  color:var(--a-ink-warm); margin-bottom:6px;
}
.blog-article-body li::marker{ color:var(--a-rust); }
/* linki w treści wpisu — sitewide wzorzec spod .legal-content a: domyślnie
   podkreślenie w kolorze tekstu, kolor rdzawy (--a-rust) dopiero na hover.
   :not(.abtn) wyklucza przycisk CTA (.blog-cta a) — ten ma wyglądać i
   zachowywać się 1:1 jak przycisk "Rezerwuj online" w headerze, bez
   podkreślenia tekstu. */
.blog-article-body a:not(.abtn){ color:inherit; text-decoration:underline; text-underline-offset:2px; }
.blog-article-body a:not(.abtn):hover{ color:var(--a-rust); }
.blog-article-body .blog-cta{ margin-top:32px; }
@media (max-width:767px){
  .blog-post-header, .blog-byline-row, .blog-content-row{ grid-template-columns:1fr; column-gap:0; }
  .blog-content-row .blog-spacer{ display:none; }
  .blog-post-header h1{ font-size:36px; line-height:41px; letter-spacing:-1px; }
}

/* ============ STRONA "O NAS" (2026-09-10) — 1:1 z archon.au /about/about-us ============
   Struktura zmierzona bezpośrednio na żywej archon.au: ciemne hero (.section--olive)
   z wyśrodkowanym eyebrow+H1+lede, potem zdjęcie, potem dalej na ciemnym tle sekcja
   "HISTORY" (H2 statyczny + 3 zakładki), potem marquee (jasne tło), potem "OUR VALUES"
   (jasne tło, siatka 4 wartości w układzie schodkowym), potem baner CTA (.cta-banner,
   już istniejący komponent .section-parallax), newsletter, stopka.
   Świadome odejście od 1:1: hero na żywej archon.au ma zdjęcie jako background-image
   całej (bardzo wysokiej) sekcji hero z overlayem — u nasto osobny blok zdjęcia
   bezpośrednio pod tekstem hero, bo realne zdjęcie dostarczone przez użytkownika jest
   w orientacji pionowej (portret gabinetu), nie nadaje się na szerokie tło całej sekcji. */
.about-hero-intro{ max-width:640px; margin:0 auto; text-align:center; }
.about-hero-intro .eyebrow{ margin-bottom:20px; }
.about-hero-heading{
  font-family:"Tenor Sans",Georgia,serif; font-weight:500; font-size:60px; line-height:60px;
  letter-spacing:-2px; margin:0 0 35px;
}
.about-hero-intro .lede{ margin:0 auto; }
.about-hero-photo{
  position:relative; margin-top:64px; border-radius:20px; overflow:hidden; aspect-ratio:3/2;
}
/* Mocna pionowa paralaksa (na wyraźną prośbę użytkownika) — ten sam wzorzec co
   .cta-banner-image/.blog-hero-image (przewymiarowany <img>, JS translateY na
   scroll w main.js), ale z większym zapasem (160px zamiast 100/180px gdzie indziej)
   i mocniejszym współczynnikiem (-0.4 zamiast standardowych -0.22), żeby ruch był
   wyraźnie odczuwalny, nie subtelny jak w pozostałych miejscach. */
.about-hero-photo img, .about-hero-photo video{
  position:absolute; top:-80px; left:0; width:100%; height:calc(100% + 160px);
  object-fit:cover; display:block; will-change:transform;
}
/* Kadr wideo /salon (2026-09-11, użytkownik: "wykadruj ten film tak żeby było
   widać twarz i głowę Julii bo teraz ją obcina") — domyślne object-position:50%
   50% (center) + silna paralaksa powyżej (-80px w spoczynku, patrz main.js) razem
   ucinały górę kadru: źródłowe wideo 1080×1920 (pion) wewnątrz szerokiego,
   niskiego kontenera .about-hero-photo (3:2 desktop, 4:5 mobile) jest i tak mocno
   przycinane przez object-fit:cover, a paralaksa w spoczynku dodatkowo przesuwa
   widoczne okno w górę o ~80px — zmierzone bezpośrednio (przewijanie <video> do
   różnych klatek + zrzuty ekranu): przy domyślnym center najgorszy moment (t≈2s,
   ujęcie szerokie przed zbliżeniem) obcinał całą głowę Julii powyżej brwi na
   desktopie. object-position:center 20% (zamiast 50%) przesuwa widoczne okno w
   dół względem źródła — z zapasem na ten sam -80px odjazd paralaksy w spoczynku —
   zweryfikowane na obu breakpointach i kilku klatkach (0.1s/2s/4s/6s), że twarz
   widoczna przez cały 8-sekundowy loop, nie tylko w pojedynczej klatce. Dotyczy
   wyłącznie <video> (jedyne bieżące użycie na /salon) — <img> na /o-nas i /zespol
   bez zmian, tam nie ma tego problemu (statyczne, wcześniej zweryfikowane zdjęcia
   dobrze wykadrowane pod center). */
.about-hero-photo video{ object-position:center 20%; }
@media (max-width:767px){
  .about-hero-heading{ font-size:36px; line-height:41px; letter-spacing:-1px; }
  .about-hero-photo{ margin-top:40px; aspect-ratio:4/5; }
}

/* nagłówek h2 w .treatment-intro-grid jest domyślnie ink-warm (myślany pod .section--cream)
   — na ciemnej sekcji "Nasza Historia" musi być cream, tak jak eyebrow/divider już mają
   swoje istniejące .section--olive .treatment-intro-* override'y wyżej w pliku. */
.section--olive .treatment-intro-grid h2{ color:var(--a-cream); }
/* Odstęp eyebrow→H2 na TEJ konkretnej stronie zmierzony jako 73px CAŁKOWITE (nie 55px
   z bazowej .treatment-intro-grid, ustalonych na innych stronach — np. blog/FAQ) —
   potwierdzone dwukrotnie (sekcja Historia i Nasze Wartości dają identyczny wynik na
   żywym archon.au, PO odczekaniu na zakończenie animacji wejścia — pierwszy pomiar
   złapał stan w trakcie [data-reveal], dający fałszywie ujemny/za duży wynik, ten sam
   błąd co już udokumentowany w DOKUMENTACJA.md). 73px to already uwzględnia istniejący
   .treatment-intro-title-line .eyebrow{margin-bottom:20px} + divider (1px) — więc
   margin-top na samym gridzie to różnica: 73-20-1=52px, nie 73px wprost (inaczej
   sumowałoby się z tamtym marginesem i dawało 94px zamiast 73px). */
#historia .treatment-intro-grid, #wartosci .treatment-intro-grid{ margin-top:52px; }

/* Zakładki "Nasza Historia" — REUŻYWA istniejącego mechanizmu .care-tab/.care-panel
   (main.js, ta sama logika przełączania co na stronach zabiegów) — łącznie z jego
   domyślnym POZIOMYM układem (flex row, 3 równe kolumny), bo to dokładnie ten sam
   układ co na tej podstronie archon.au: zmierzone przy 1440px (nie w wąskim panelu
   podglądu, który poniżej 767px pokazuje już mobilny, skolapsowany do kolumny widok
   — pierwsza wersja tej sekcji pomyłkowo wzięła TEN widok za desktopowy) — 3 zakładki
   flex:1 1 0% po 256px, odstęp przez padding-right:30px na każdej (nie gap), dokładnie
   jak już istniejące .care-tabs/.care-tab. Jedyna różnica względem stron zabiegów:
   brak górnego/dolnego marginesu 104px/50px (tu zakładki siedzą od razu pod H2 "Nasza
   Historia" w prawej kolumnie .treatment-intro-grid, nie pod osobnym nagłówkiem sekcji). */
.about-tabs.care-tabs{ margin:0; }
.about-tab-panel{ margin-top:50px; }
.about-tab-panel p{
  font-family:"Inter",sans-serif; font-size:16px; font-weight:400; line-height:27.2px;
  color:var(--a-cream); margin:0 0 10px;
}
.about-tab-panel p:last-child{ margin-bottom:0; }
.about-tab-panel ul{ list-style:disc; margin:0; padding-left:24px; }
.about-tab-panel li{
  font-family:"Inter",sans-serif; font-size:16px; font-weight:400; line-height:27.2px;
  color:var(--a-cream); margin-bottom:20px;
}
.about-tab-panel li:last-child{ margin-bottom:0; }
.about-tab-panel strong{ font-weight:700; }

/* Siatka "Nasze Wartości" — układ schodkowy zmierzony bezpośrednio na archon.au
   (getBoundingClientRect 4 kart w 4-kolumnowym gridzie 1440px: 01/02 w rzędzie 1
   (kolumny 1-2), 03/04 w rzędzie 2 przesunięte o jedną kolumnę w prawo (kolumny 2-3)
   — nie zwykła siatka 2x2). Numery/nagłówki/opisy kolory ink-warm (mierzone na
   .section--cream, tej samej, na której cała sekcja tu siedzi). POPRAWKA: siatka
   NIE jest zagnieżdżona w wąskiej (828px) prawej kolumnie .treatment-intro-grid —
   to osobny, PEŁNOSZEROKI blok bezpośrednio w .container, rodzeństwo
   .treatment-intro-grid (który tu zawiera tylko H2+lede). Zmierzony odstęp między
   dołem tego gridu a górem siatki wartości: 0px (bezpośrednio przylegają). */
.value-grid{
  display:grid; grid-template-columns:repeat(4,1fr); column-gap:40px; row-gap:64px;
  /* zmierzone na archon.au PO odczekaniu na zakończenie animacji wejścia (pierwszy
     pomiar, jak przy eyebrow→H2, złapał stan w trakcie [data-reveal]/IX2 i dał
     fałszywe 0px) — realny odstęp lede→górna krawędź gridu to 10px. ALE realny
     odstęp lede→pierwszy WIDOCZNY numer "01" to 110px, bo ._4-column-grid ma
     DODATKOWO padding-top:100px na samym kontenerze — pierwszy pomiar sprawdzał
     tylko margin-top gridu, nie jego własny padding, więc te 100px umknęły. */
  margin-top:10px;
  padding-top:100px;
  /* UWAGA: świadomie BEZ align-items:start — użytkownik chce linie-separatory pod
     wszystkimi boksami W TYM SAMYM RZĘDZIE na jednym poziomie (jak na archon.au,
     gdzie treść ma zbliżoną długość), a nie każdą "przyklejoną" do własnego,
     różnej długości tekstu. Domyślne align-items:stretch (rozciąganie do wysokości
     najwyższego sąsiada w rzędzie) daje ten efekt automatycznie. */
}
.value-item:nth-child(1){ grid-column:1; grid-row:1; }
.value-item:nth-child(2){ grid-column:2; grid-row:1; }
.value-item:nth-child(3){ grid-column:2; grid-row:2; }
.value-item:nth-child(4){ grid-column:3; grid-row:2; }
/* archon.au's real .value-wrapper: 32px padding-bottom + 1px border-bottom pod
   każdym boksem (zmierzone: border czarny na żywej stronie, ale zgodnie z regułą
   "jedna czerń na stronie" z CLAUDE.md użyty tu --a-ink-warm zamiast surowego #000). */
.value-item{ padding-bottom:32px; border-bottom:1px solid var(--a-ink-warm); }
.value-num{
  font-family:"Inter",sans-serif; font-weight:400; font-size:15px; line-height:1;
  color:var(--a-ink-warm); margin:0 0 20px;
}
.value-item h3{
  font-family:"Inter",sans-serif; font-weight:700; font-size:15px; line-height:1.2;
  color:var(--a-ink-warm); margin:0 0 10px;
}
/* :not(.value-num) — bez tego ta reguła (ta sama specyficzność co .value-num,
   ale zdefiniowana później) nadpisywała font-size/line-height/margin numeru
   pozycji, bo <p class="value-num"> pasuje też do zwykłego selektora .value-item p.
   Realny błąd znaleziony przy weryfikacji odstępu num→h3 (wychodziło 0px
   zamiast zmierzonych na archon.au 20px). */
.value-item p:not(.value-num){
  font-family:"Inter",sans-serif; font-size:16px; font-weight:400; line-height:27.2px;
  color:var(--a-ink-warm); margin:0;
}
@media (max-width:767px){
  .value-grid{ grid-template-columns:1fr; row-gap:40px; }
  .value-item:nth-child(1), .value-item:nth-child(2), .value-item:nth-child(3), .value-item:nth-child(4){
    grid-column:1; grid-row:auto;
  }
}

/* Zespół (/zespol) — nowa strona, brak odpowiednika na archon.au (nie ma tam dedykowanej
   podstrony zespołu, potwierdzone przeglądem pełnej listy linków nawigacji); zaprojektowana
   od zera z tych samych tokenów co reszta strony (kolory/typografia/spacing z
   DESIGN-SYSTEM.md). Przebudowana (Runda 2/2026-09-10) z pierwotnej płaskiej siatki
   5 równych kart na 3-poziomową hierarchię ról, na wyraźną prośbę użytkownika:
   Poziom 1 Założycielka (split 50/50) → Poziom 2 Praktyka kosmetologiczna (siatka 3
   kolumn) → Poziom 3 Zarządzanie marką (dyskretny pasek), patrz DOKUMENTACJA.md.
   Bez zdjęć nigdzie (decyzja użytkownika, potwierdzona ponownie przy przebudowie) —
   wszędzie okrągły/prostokątny placeholder z inicjałem zamiast <img> — TODO w PLAN.md:
   podmienić na realne zdjęcia, gdy będą dostępne. */

/* Zespół (/zespol) — 3-poziomowa hierarchia. Przebudowana (Runda 6/2026-09-10) —
   usunięte obwódki wokół zdjęć i border-radius ujednolicony na 20px, dokładnie tak
   jak każdy inny zaokrąglony portret/miniatura na stronie (.about-hero-photo,
   .blog-card-thumb, .blog-hero-image — wszystkie 20px, sprawdzone w CSS przed tą
   zmianą, nie zgadnięte na nowo). Przyciski "Zarezerwuj termin" reużywają WPROST
   klasę .abtn.primary-olive — dokładnie tę samą, której używa "Rezerwuj online" w
   nagłówku (partials/header.html) — więc są 1:1 identyczne (ten sam selektor CSS),
   nie osobno dostrojone przybliżenie. .team-tags (linia ról/specjalizacji, pisana z
   małych liter) dostrojona do już istniejącego wzorca małego, wyciszonego tekstu
   meta na stronie (.blog-card-meta/.form-note/.t-source — wszystkie 12px, sprawdzone
   przed tą zmianą), nie własny, nowo wymyślony rozmiar. Patrz DOKUMENTACJA.md po
   pełny log tej i poprzednich rund (okrągłe kadry, kadrowanie Nikoli/Krzysztofa,
   itd. — historia, nie duplikować tu). */

/* POZIOM 1 — Założycielka: split 50/50, zdjęcie po lewej, treść po prawej. */
.team-founder-grid{
  display:grid; grid-template-columns:1fr 1fr; column-gap:64px; align-items:center;
}
.team-founder-photo{
  aspect-ratio:4/5; border-radius:20px; background:var(--a-taupe); overflow:hidden;
}
.team-founder-photo img{
  /* object-position:top: cała głowa musi być widoczna w każdym widoku (ustalone
     wcześniej, patrz DOKUMENTACJA.md) — cover zawsze skaluje wg szerokości, nadmiar
     przycina się w pionie, "top" kotwiczy głowę, przycina wyłącznie dół.
     filter — dokładnie ten sam ton co blog (.blog-card-thumb/.blog-hero-image img),
     ujednolica kolorystykę wszystkich zdjęć zespołu. */
  width:100%; height:100%; object-fit:cover; object-position:center top; display:block;
  filter:grayscale(85%) sepia(8%);
}
.team-founder-content .eyebrow{ margin-bottom:20px; }
.team-founder-content .h-section{ margin-bottom:8px; }
.team-founder-content .lede{ margin:0 0 20px; }
.team-founder-content .abtn{ margin-top:4px; }
@media (max-width:767px){
  .team-founder-grid{ grid-template-columns:1fr; row-gap:32px; }
}

/* Tagi ról/specjalizacji — jedna linia tekstu z kropkami "·" jako separatorami wprost
   w treści (nie lista + pseudo-elementy, prostsze), pisana z małych liter (poza
   markami własnymi jak LightSheer®). Rozmiar/waga/kolor 1:1 z już istniejącym wzorcem
   małego, wyciszonego tekstu meta na stronie (.blog-card-meta/.form-note: 12px/400,
   .a-gray) — bez własnego, nowo wymyślonego letter-spacingu. Reużywana dla linii
   "rola" (pod imieniem) i linii "specjalizacje" (niżej, przed/po biogramie). */
.team-tags{
  font-family:"Inter",sans-serif; font-size:12px; font-weight:400; line-height:16px;
  color:var(--a-gray); margin:0 0 20px;
}

/* POZIOM 2 — Praktyka kosmetologiczna: nagłówek własny + siatka 3 kolumn pionowych
   portretów (editorial rounded-rect 4:5 — NIE kółka, świadoma zmiana kierunku
   2026-09-10 po wcześniejszej rundzie z okrągłym kadrem, patrz DOKUMENTACJA.md). */
.team-practitioners-header{ max-width:640px; margin:0 0 52px; }
.team-practitioners-header .eyebrow{ margin-bottom:20px; }
.team-practitioners-header .h-section{ margin-bottom:16px; }
.team-grid{
  display:grid; grid-template-columns:repeat(3,1fr); column-gap:40px; row-gap:64px;
  align-items:stretch;
}
.team-card{
  display:flex; flex-direction:column; padding-bottom:32px;
  border-bottom:1px solid var(--a-ink-warm);
}
.team-portrait{
  aspect-ratio:4/5; border-radius:20px; background:var(--a-taupe); overflow:hidden;
  margin:0 0 24px;
}
.team-portrait img{
  width:100%; height:100%; object-fit:cover; object-position:center top; display:block;
  filter:grayscale(85%) sepia(8%);
}
.team-card h3{
  /* Tenor Sans (nie Inter) — ten sam krój co każdy inny nagłówek na stronie (h1/h2/h3
     mają Tenor Sans w bazowym resecie). font-size 35px = 20px +75%, na wyraźną
     prośbę użytkownika (2026-09-10, kolejna runda). */
  font-family:"Tenor Sans",Georgia,serif; font-weight:500; font-size:35px; line-height:1.2;
  color:var(--a-ink-warm); margin:0 0 8px;
}
.team-card .team-tags{ margin:0 0 12px; }
.team-specialty{
  font-family:"Inter",sans-serif; font-size:15px; font-weight:400; line-height:1.6;
  color:var(--a-ink-warm); margin:0;
  /* min-height:96px = 4 linie × 24px (15px×1.6 line-height) — dokładnie tyle, ile
     zajmuje najdłuższy opis w tym rzędzie (Nikola, 4 linie), zmierzone bezpośrednio
     na żywo. Na wyraźną prośbę użytkownika: przyciski wszystkich 3 kart mają być na
     tym samym poziomie co u Nikoli — skoro jej opis jest najdłuższy, krótsze opisy
     (Patrycja/Julia, 3 linie/72px) muszą rezerwować tyle samo miejsca, żeby stały
     margin-top:32px na przycisku (patrz niżej) wylądował w tym samym miejscu u
     wszystkich. Jeśli treść opisu się zmieni i ktoś przekroczy 4 linie, przelicz tę
     wartość na nowo (nie zgaduj) i zaktualizuj ten komentarz. */
  min-height:96px;
}
/* CTA — STAŁY odstęp 32px od opisu (margin-top:auto z 2 rund temu cofnięte — dawało
   0px u Nikoli, bo jej opis jest najdłuższy i nie zostawiał "luzu" w wyciągniętej
   fleksowo karcie). W POŁĄCZENIU z .team-specialty{min-height:96px} wyżej (rezerwuje
   tyle miejsca, ile zajmuje NAJDŁUŻSZY opis w rzędzie) ten stały margin-top ląduje
   teraz w TYM SAMYM miejscu na wszystkich 3 kartach — na wyraźną prośbę użytkownika
   "wyrównaj przyciski na tym samym poziomie wszystkie co u Nikoli" — zamiast
   wcześniejszego wyrównania do dolnego separatora (Runda 7, zarzucone), bo tamto
   dawało różny odstęp od tekstu przy różnej długości opisu. WYŁĄCZNIE margin (nigdy
   padding) na samym .abtn — patrz błąd "rozjechanych" przycisków z wcześniejszej
   rundy (padding-top ściskał stałą wysokość 44px). */
.team-card .abtn{ margin-top:32px; align-self:flex-start; }
/* Patrycja — przycisk stylowo identyczny z "Kup Kartę Podarunkową" (.abtn.outline-dark)
   ale wyszarzony i nieaktywny (nie <a>, tylko <span>, bez href) — na wyraźną prośbę
   użytkownika: komunikuje "obecnie niedostępna" wizualnie, bez ujawniania powodu w
   tekście (patrz DOKUMENTACJA.md, prywatna sprawa). Nadpisuje tylko kolor/border na
   --a-gray i wyłącza interakcję — struktura (padding/radius/rozmiar) ta sama co
   .outline-dark, więc karta ma identyczny rytm co karty z aktywnym CTA. */
.abtn.outline-dark.is-disabled{
  color:var(--a-gray); border-color:var(--a-gray); cursor:default; pointer-events:none;
}
.abtn.outline-dark.is-disabled:hover{ transform:none; box-shadow:none; }
@media (max-width:767px){
  .team-grid{ grid-template-columns:1fr; row-gap:40px; }
}

/* POZIOM 3 — Zarządzanie marką: stonowany panel (tło --a-taupe) z pionowym portretem
   4:5 po lewej (NIE okrągły — poprzednia okrągła wersja .team-avatar w tym miejscu
   zarzucona na rzecz spójnego języka z Poziomem 1/2, 2026-09-10) i treścią po prawej. */
.team-leadership{ background:var(--a-taupe); }
.team-leadership-row{
  display:grid; grid-template-columns:240px 1fr; column-gap:48px; align-items:center;
}
.team-leadership-photo{
  aspect-ratio:4/5; border-radius:20px; overflow:hidden;
}
.team-leadership-photo img{
  width:100%; height:100%; object-fit:cover; object-position:center top; display:block;
  filter:grayscale(85%) sepia(8%);
}
.team-leadership-row h3{
  /* Tenor Sans, dostrojone do kart praktyczek (.team-card h3). Poprzednia runda
     świadomie zostawiła 20px (bez +75% jak w kartach) — kolejna, osobna prośba
     użytkownika teraz jawnie chce +50% tutaj: 20px→30px. */
  font-family:"Tenor Sans",Georgia,serif; font-weight:500; font-size:30px; line-height:1.2;
  color:var(--a-ink-warm); margin:0 0 4px;
}
.team-leadership-row .team-tags{ margin:0 0 12px; }
.team-leadership-bio{
  font-family:"Inter",sans-serif; font-size:15px; font-weight:400; line-height:1.6;
  color:var(--a-ink-warm); margin:0; max-width:560px;
}
@media (max-width:767px){
  .team-leadership-row{ grid-template-columns:1fr; row-gap:24px; }
  .team-leadership-photo{ max-width:240px; }
}

/* Baner CTA "Umów się na bezpłatną konsultację" — ten sam .cta-banner co na stronach
   zabiegów, tylko wyższy (600px, zmierzone bezpośrednio na tej konkretnej sekcji
   archon.au — inne strony/instancje tego komponentu mają zmierzone 400px, więc
   nadpisujemy scoped klasą zamiast zmieniać bazową .cta-banner). */
.o-nas-cta.cta-banner{ height:600px; }

/* Salon (/salon) — nowa strona, brak odpowiednika na archon.au (ten sam przypadek co
   /zespol — sprawdzone wcześniej, że grupa "About" nie ma osobnej podstrony
   lokalizacji/wnętrza). Hero-photo reużywa 1:1 .about-hero-photo (ta sama klasa —
   automatycznie dziedziczy paralaksę z main.js, selektor ".about-hero-photo img").
   Galeria wnętrza i karty sprzętu pożyczają dokładnie ten sam język wizualny co
   portrety zespołu na /zespol (.team-portrait): rounded-rect 4:5, border-radius 20px,
   ten sam filtr grayscale(85%) sepia(8%) co blog/zespół — spójny ton fotografii w
   całym serwisie. Zdjęcia realne, dostarczone przez użytkownika (sesja "Sesja salon
   2026"), sprzęt podpisany wyłącznie zweryfikowanymi, już ustalonymi w projekcie
   nazwami marek (LightSheer®/cooltech®/Dermalux®) — bez zgadywania nienazwanych
   urządzeń widocznych na innych zdjęciach z sesji.
   Odstępy siatek (2026-09-11, „za ciasno, dodaj powietrza jak na innych stronach"):
   pierwotne 24px column/row-gap były wartością wymyśloną od zera (brak odpowiednika
   na archon.au dla tej strony) i wyraźnie węższą niż ustalony sitewide rytm siatek
   kart z opisem — .team-grid/.value-grid używają 40px/64px wszędzie indziej.
   .salon-equipment-grid (karty ze zdjęciem+h3+opisem, ta sama struktura co
   .team-card) podniesiony do DOKŁADNIE tych samych 40px/64px; .salon-gallery (czyste
   zdjęcia bez tekstu pod spodem, mniej potrzebują pionowego oddechu niż karty z
   tekstem) do umiarkowanych 32px/32px — więcej powietrza niż pierwotne 24px, ale
   celowo mniej niż 64px, żeby nie rozjechać czystej siatki zdjęć pustym miejscem. */
.salon-gallery{
  display:grid; grid-template-columns:repeat(4,1fr); column-gap:32px; row-gap:32px;
  margin-top:52px;
}
.salon-photo{
  display:block; aspect-ratio:4/5; border-radius:20px; background:var(--a-taupe); overflow:hidden;
}
.salon-photo img{
  width:100%; height:100%; object-fit:cover; object-position:center top; display:block;
  filter:grayscale(85%) sepia(8%);
}
@media (max-width:1023px){
  .salon-gallery{ grid-template-columns:repeat(2,1fr); }
}
@media (max-width:479px){
  .salon-gallery{ grid-template-columns:1fr; }
}

.salon-equipment-grid{
  display:grid; grid-template-columns:repeat(4,1fr); column-gap:40px; row-gap:64px;
  margin-top:52px;
}
.salon-equipment-card .salon-photo{ margin-bottom:24px; }
.salon-equipment-card h3{
  font-family:"Tenor Sans",Georgia,serif; font-weight:500; font-size:20px; line-height:1.2;
  color:var(--a-ink-warm); margin:0 0 8px;
}
.salon-equipment-card p{
  font-family:"Inter",sans-serif; font-size:14px; font-weight:400; line-height:1.5;
  color:var(--a-gray); margin:0;
}
@media (max-width:1023px){
  .salon-equipment-grid{ grid-template-columns:repeat(2,1fr); }
}
@media (max-width:479px){
  .salon-equipment-grid{ grid-template-columns:1fr; }
}
/* Ruchomy pasek dodatkowych technologii pod głównymi 4 kartami — na kolejną
   prośbę użytkownika (2026-09-10): zamiast samej linii tekstu ("opcja 1"),
   docelowo realny scroll-linked marquee z logotypami marek, reużywający 1:1
   mechanizm .marquee/.marquee-track z js/main.js (ten sam kod co pasek
   korzyści na stronie głównej i /o-nas — JS jest treściowo-agnostyczny,
   klonuje dowolne dzieci #marqueeTrack, więc kafle z <img> zamiast
   .marquee-phrase/.marquee-dot działają bez zmian w main.js). Logotypy
   dostarczone przez użytkownika (zapisane w assets/images/logos/), każdy na
   białym zaokrąglonym kaflu żeby ujednolicić różne tła źródłowych plików
   (np. LPG ma wbudowane czarne tło w pliku źródłowym). Hebe nie ma jeszcze
   dostarczonego logotypu — kafel tekstowy zamiast obrazka, ten sam styl co
   .marquee-phrase na innych podstronach. */
.salon-tech-marquee{ margin-top:40px; background:var(--a-white); }
.salon-tech-marquee .marquee-logo{
  display:flex; align-items:center; justify-content:center;
  height:64px; margin:0 28px;
  flex:0 0 auto;
}
.salon-tech-marquee .marquee-logo img{
  display:block; width:auto;
  /* Skala szarości (2026-09-11, na prośbę użytkownika) — loga dostarczone przez
     użytkownika są w oryginalnych kolorach marek (granat LightSheer, turkus
     cooltech/Lumiderm, czarno-białe LPG/SkinPen) — ujednolicone na wyciszony,
     monochromatyczny pasek, ten sam kierunek co filtr grayscale/sepia już
     użyty na wszystkich zdjęciach w serwisie (spójny, stonowany ton). */
  filter:grayscale(100%);
}
/* Wysokości dobrane per-logo, NIE jedna wspólna max-height — każdy plik ma
   inny udział właściwego napisu w wysokości całego kadru (np. lightsheer.png
   ma duży abstrakcyjny znak NAD wordmarkiem, lpg.png duży czarny margines
   wokół napisu, skinpen.webp dopisek "PRECISION" pod głównym kursywnym
   wordmarkiem) — zmierzone wprost pasami pikseli (PIL, gęstość alfa/jasność
   na wiersz), żeby sam widoczny napis wychodził optycznie w tym samym
   rozmiarze u wszystkich, zamiast całego obrazka.
   lightsheer: 55px→40px (2026-09-11, użytkownik: "lightsheer jest ewidentnie
   za duży w stosunku do innych") — dopasowana wysokość samego NAPISU nie
   uwzględniała, że duży abstrakcyjny znak NAD nim wciąż dodaje wizualną "masę"
   nieproporcjonalną do reszty paska (płaskie wordmarki bez ikon) — skorygowane
   w dół empirycznie (zrzut ekranu po każdej zmianie), nie przeliczone wzorem. */
.logo-lightsheer{ height:40px; }
.logo-cooltech{ height:15px; }
.logo-lpg{ height:39px; }
.logo-skinpen{ height:21px; }
.logo-lumiderm{ height:20px; }
.salon-tech-marquee .marquee-logo-text{
  font-family:"Inter",sans-serif; font-weight:600; text-transform:uppercase;
  font-size:13px; letter-spacing:.02em; color:var(--a-ink-warm); white-space:nowrap;
}
.salon-tech-marquee .marquee-dot{ margin:0 16px; }
