/* =============================================================================
   Безопасность в Польше — landing page.

   ONE palette, and it lives entirely in the :root block below. The page used to mix
   a warm beige (#f4f3ef) with a cool lavender (#eceaf0) and a cool navy accent, which
   read as two different sites stitched together. Everything is on one neutral grey
   ramp now.

   THREE surfaces, and only three, alternating so no two neighbours share one:
     dark   #0f1114  — hero, beat
     white  #ffffff  — situations, plans, footer
     grey   #f3f4f6  — why, form, FAQ (and the page default)
   There is no 1px rule between a white section and a grey one: the tone step IS the
   division. The only hairline left is between the two GREY sections that touch
   (form → FAQ), which would otherwise run together as one long block.

   TWO accents, because one colour cannot be read on both ends of that ramp:
   --accent-deep on light, --accent-on-dark on dark. The dark sections re-point the
   token rather than hardcoding a colour, so this block stays the only place to edit.
   ============================================================================= */

:root{
  /* ---- surfaces ---- */
  --bg:#f3f4f6;            /* GREY sections, and the page default */
  --bg-2:#ffffff;          /* WHITE sections, and every card that sits on grey */
  --bg-dark:#0f1114;       /* DARK sections: hero and beat */
  --bg-dark-rgb:15,17,20;
  /* A component fill for things that sit ON white — chips, badges, the good column.
     Deliberately NOT equal to --bg: a --bg chip on a --bg card is invisible, which is
     exactly what happened when both were flattened to one grey. */
  --bg-3:#e9ebef;

  /* ---- ink ---- */
  --ink-rgb:20,22,26;
  --ink:#14161a;           /* near-black — headings, CTA buttons */
  --ink-2:#3a3f47;         /* body copy */
  --muted:#5f6673;         /* was #787f8b: 3.9:1 on white, under the 4.5 floor. This is 5.9 */
  --ink-on-dark:#f1f2f4;
  --ink-on-dark-rgb:241,242,244;

  /* ---- lines ---- */
  --line:#e5e7eb;          /* hairlines between light surfaces */
  --line-2:#dcdfe4;        /* the heavier one: inputs, chips, the picker */
  --line-on-dark:rgba(255,255,255,.14);

  /* Periwinkle, lifted from the design reference. It is a SURFACE TINT ONLY:
     at ~1.7:1 on white it fails every text contrast rule. Anything that has to be
     READ in the accent colour uses --accent-deep (on light) or --accent-on-dark. */
  --accent:#b8c4dc;
  --accent-rgb:184,196,220;   /* every rgba() tint reads this — see CLAUDE.md */
  --accent-deep:#2f4a73;      /* the accent that is READABLE on a light surface */
  --accent-deep-rgb:47,74,115;/* ...and the same navy as a WASH on a dark one */
  /* ...and its twin for the dark sections. #2f4a73 on #0f1114 is 1.6:1, i.e. invisible;
     this is 8.2:1. The hero pill and the beat's accents are this colour. */
  --accent-on-dark:#9db8e6;
  --accent-on-dark-rgb:157,184,230;

  /* CTAs are near-black pills, as in the reference — not the accent. */
  --cta:#14161a;
  --cta-ink:#ffffff;

  --ok:#1f7a4d;            /* the ✓ in a plan's feature list */
  --bad:#b3261e;           /* errors, and the ✕ in the «without a subscription» column */
  --placeholder:#9aa1ad;  /* input placeholders */
  /* Messenger brand colour - fixed, never themed, same value as thank-you.css. It is a MARK,
     not a fourth page hue: it appears only on the Telegram float and nowhere else. */
  --tg:#229ED9;
  --ok-on-dark:#5ec98f;    /* both are tuned for white and go muddy on near-black */
  --bad-on-dark:#ff9a92;

  --radius:18px;
  --radius-sm:12px;
  --radius-pill:999px;
  --maxw:1180px;
  --head-h:64px;

  /* lets the FAQ panel animate to block-size:auto — see ::details-content below */
  interpolate-size:allow-keywords;
}

*{box-sizing:border-box}
html{scroll-behavior:smooth}
body{
  margin:0;
  background:var(--bg);
  color:var(--ink-2);
  font-family:Inter,system-ui,-apple-system,"Segoe UI",Roboto,Arial,sans-serif;
  font-size:16px;
  line-height:1.6;
  -webkit-font-smoothing:antialiased;
}
img{max-width:100%;display:block}

.wrap{max-width:var(--maxw);margin:0 auto;padding:0 20px;position:relative}

/* Every anchor target clears the fixed header. Without this, jumping to #plans or #form —
   from the nav, from a tariff card, or from a shared link — parks the section heading
   underneath the 64px header strip. Same fix admin.css uses for its comment anchors. */
section[id], [id]:target{scroll-margin-top:calc(var(--head-h) + 20px)}
.sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}

/* Skip link — visible only when focused */
/* Hidden by sliding it up out of the viewport, NOT by parking it at left:-9999px.
   An absolutely positioned element 9999px to the left still belongs to the document, and it
   showed up two ways on a real device: the bar appeared as a stray button at the top-left when
   DevTools switched viewport and moved focus onto it (it IS the first tab stop, and :focus
   brought it to left:0), and the page could be pinched out to reveal empty canvas beside it.
   position:fixed keeps it out of the document's overflow entirely; the transform hides it
   without moving it anywhere a layout can find. It still appears on focus, which is the whole
   point of a skip link. */
.skip{
  position:fixed;left:0;top:0;z-index:100;
  transform:translateY(-120%);
  background:var(--cta);color:var(--cta-ink);
  padding:12px 18px;border-radius:0 0 var(--radius-sm) 0;font-weight:600;text-decoration:none;
  transition:transform .15s ease;
}
.skip:focus{transform:none}
/* ...but only when the focus was actually keyboard-driven. Toggling DevTools' device mode moves
   focus into the page, and this is the first tab stop, so the bar slid down and sat over the
   logo on every phone/desktop switch - reported twice.
   Written as "reveal on :focus, then take it back when the focus is not :focus-visible" rather
   than as `.skip:focus-visible`, because a browser that does not know :focus-visible drops this
   whole rule as an invalid selector and keeps the plain :focus behaviour. The other way round
   it would lose the skip link entirely. */
.skip:focus:not(:focus-visible){transform:translateY(-120%)}

/* ============================== HEADER ============================== */

/* THREE states, not two:
     (base)                     transparent, light type   — at the top of the dark hero
     .scrolled.over-dark        dark translucent, light   — scrolled, still over a dark section
     .scrolled:not(.over-dark)  light bar, dark type      — over a white or grey section
   The light bar used to come on as soon as you scrolled 10px, which put a pale strip across
   the dark hero and across .beat. So the LIGHT state is the qualified one and the dark type is
   the base: every light-bar rule below is :not(.over-dark), and adding a dark section means
   adding it to the JS list in index.html, not writing new colour rules.
   The Dobry Piec original probed rects on every scroll frame; this probes two elements and
   only on the same scroll handler .scrolled already uses. */
.site-header{
  position:fixed;top:0;left:0;right:0;z-index:50;
  height:var(--head-h);
  display:flex;align-items:center;
  background:transparent;
  border-bottom:1px solid transparent;
  /* ONE duration for everything that changes with the state, here and on the children below.
     It was .25/.2/.2 with several properties not transitioning at all, so the bar faded while
     the type, the picker's fill and the brand mark all snapped - which is what read as a cut.
     --head-fade is the single knob; anything added to the header flip must use it. */
  --head-fade:.28s;
  transition:background var(--head-fade) ease,
             border-color var(--head-fade) ease,
             box-shadow var(--head-fade) ease;
}
.site-header .main-nav a{color:rgba(var(--ink-on-dark-rgb),.86)}
.site-header .main-nav a:hover,
.site-header .main-nav a.active{color:#fff}
/* The picker's parts are coloured EXPLICITLY, not by inheritance from the summary. The globe
   and the chevron are stroke="currentColor" and the code is in a <span>, and relying on the
   summary's colour to reach them left the whole control invisible on the light bar - white on
   white - even with !important on the parent. Two extra selectors, no guessing. */
.site-header .lang-btn,
.site-header .lang-btn span{color:#fff}
.site-header .lang-btn{
  border-color:rgba(255,255,255,.26);background:rgba(255,255,255,.08);
}
.site-header .lang-btn svg{stroke:#fff}
/* The picker changes FOUR things between states - fill, border, label colour and icon stroke -
   and the base rule only transitioned two of them, so the pill's fill and its globe snapped
   while the bar behind them faded. The hover transitions stay short; this is the state flip. */
.site-header .lang-btn{
  transition:background var(--head-fade) ease, border-color var(--head-fade) ease,
             color var(--head-fade) ease;
}
.site-header .lang-btn span{transition:color var(--head-fade) ease}
.site-header .lang-btn svg{transition:stroke var(--head-fade) ease}
.site-header .lang-btn:hover{border-color:rgba(255,255,255,.5)}

.site-header.scrolled{
  -webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);
}
/* Over the hero or the beat: the bar darkens rather than lightening, and every base rule above
   (light nav, light picker, light brand mark) still applies because none of them was scoped. */
.site-header.scrolled.over-dark{
  background:rgba(var(--bg-dark-rgb),.72);
  border-bottom-color:var(--line-on-dark);
  box-shadow:none;
}
.site-header.scrolled:not(.over-dark){
  background:rgba(255,255,255,.86);
}
.site-header.scrolled:not(.over-dark) .main-nav a{color:var(--muted)}
.site-header.scrolled:not(.over-dark) .main-nav a:hover,
.site-header.scrolled:not(.over-dark) .main-nav a.active{color:var(--ink)}
.site-header.scrolled:not(.over-dark) .lang-btn,
.site-header.scrolled:not(.over-dark) .lang-btn span{color:var(--ink-2)}
.site-header.scrolled:not(.over-dark) .lang-btn{
  border-color:var(--line-2);background:var(--bg-2);
}
.site-header.scrolled:not(.over-dark) .lang-btn svg{stroke:var(--ink-2)}
.site-header.scrolled:not(.over-dark) .lang-btn:hover,
.site-header.scrolled:not(.over-dark) .lang-btn:hover span{color:var(--ink)}
.site-header.scrolled:not(.over-dark) .lang-btn:hover{border-color:var(--accent-deep)}
.site-header.scrolled:not(.over-dark){
  border-bottom-color:var(--line);
  box-shadow:0 1px 20px rgba(var(--ink-rgb),.05);
}
/* Over the dark hero the near-black shield would all but vanish, so the header shows the LIGHT
   twin instead and swaps back on .scrolled. A white plate behind the dark mark was tried first
   and read as a sticker; filtering the mark is not an option, it carries its own colours.

   The two marks CROSS-FADE. This used to be display:none/block, and `display` is not an
   animatable property - the mark snapped from one file to the other in a single frame while
   everything around it faded, which was the most visible part of the cut. They are stacked
   instead: the dark one stays in flow and holds the layout, the light one sits on top of it. */
.brand-mark-light{display:none}
.site-header .logo{position:relative}
.site-header .logo .brand-mark,
.site-header .logo .brand-mark-light{
  display:block;
  transition:opacity var(--head-fade) ease;
}
.site-header .logo .brand-mark-light{
  position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
}
.site-header .logo .brand-mark{opacity:0}
.site-header .logo .brand-mark-light{opacity:1}
.site-header.scrolled:not(.over-dark) .logo .brand-mark{opacity:1}
.site-header.scrolled:not(.over-dark) .logo .brand-mark-light{opacity:0}
.site-header .wrap{display:flex;align-items:center;gap:20px;width:100%}

.logo{display:flex;align-items:center;gap:9px;text-decoration:none;flex:none}
/* The brand mark carries its OWN colours, so it must never inherit a monochrome
   filter. Higher specificity (3 classes) beats `.site-header .logo img`. */
/* The mark is the whole logo now, so it is sized to carry the header on its own. */
.site-header .logo .brand-mark{height:38px;width:38px;flex:none;filter:none}
/* The header sits over both light and dark sections and carries a backdrop-filter. Giving it
   its own compositing layer stops Chrome repainting the blurred strip against stale content
   while scrolling, which shows up as the bar flickering or briefly going blank. */
.site-header{will-change:transform}

/* Nav links follow the Dobry Piec (kotly) site: the underline GROWS from zero rather than
   fading a border in, and the same rule serves the scroll-spy .active state. The bar is a
   pseudo-element so it can animate width without nudging the text. */
.main-nav{display:none;gap:22px}
.main-nav a{
  position:relative;white-space:nowrap;
  color:var(--muted);text-decoration:none;
  font-size:14.5px;font-weight:600;
  transition:color var(--head-fade, .28s) ease;
}
.main-nav a::after{
  content:"";position:absolute;left:0;bottom:-6px;
  height:2px;width:0;border-radius:2px;
  background:var(--accent-deep);
  transition:width .25s cubic-bezier(.4,0,.2,1);
}
.main-nav a:hover{color:var(--ink)}
.main-nav a.active{color:var(--ink)}
.main-nav a:hover::after,
.main-nav a.active::after{width:100%}

.head-right{display:flex;align-items:center;gap:10px;margin-left:auto}

/* --- language picker (native <details>, no JS) --- */
.lang-picker{position:relative;flex:none}
.lang-btn{
  list-style:none;cursor:pointer;
  display:flex;align-items:center;gap:6px;
  padding:7px 11px;border-radius:var(--radius-pill);
  border:1px solid var(--line-2);background:var(--bg-2);
  color:var(--ink-2);font-size:13px;font-weight:600;
  transition:border-color .15s, color .15s;
}
.lang-btn::-webkit-details-marker{display:none}
.lang-btn:hover{border-color:var(--accent-deep);color:var(--ink)}
.lang-btn svg{width:15px;height:15px;flex:none}
.lang-chevron{transition:transform .2s ease}
.lang-picker[open] .lang-chevron{transform:rotate(180deg)}
.lang-menu{
  position:absolute;right:0;top:calc(100% + 8px);min-width:170px;
  background:var(--bg-2);border:1px solid var(--line);border-radius:var(--radius-sm);
  box-shadow:0 12px 34px rgba(var(--ink-rgb),.12);
  padding:6px;display:flex;flex-direction:column;
}
.lang-menu a{
  padding:9px 12px;border-radius:8px;text-decoration:none;
  color:var(--ink-2);font-size:14px;
}
.lang-menu a:hover{background:var(--bg);color:var(--ink)}
.lang-menu a[aria-current]{background:var(--bg-3);color:var(--ink);font-weight:600}

/* ============================== SHARED SECTION FURNITURE ============================== */

section{padding:72px 0}
.eyebrow{
  display:block;
  /* 12px is the floor for uppercase at this tracking: below it the letterforms stop
     resolving and the label reads as texture. Was 11. */
  font-size:12px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;
  color:var(--muted);margin-bottom:14px;
}
h2{
  margin:0 0 12px;
  font-size:clamp(28px,4.4vw,44px);line-height:1.1;letter-spacing:-.03em;
  font-weight:800;color:var(--ink);
}
h3{color:var(--ink);letter-spacing:-.01em}
.sec-sub{margin:0 0 36px;max-width:60ch;color:var(--muted);font-size:17px}

/* The pill-highlighted word, straight from the reference. */
.mark{
  display:inline-block;
  background:var(--bg-3);
  border-radius:var(--radius-pill);
  padding:0 .34em;
  box-decoration-break:clone;
  -webkit-box-decoration-break:clone;
}

/* ============================== HERO ============================== */

/* DARK, to the client's mock, and the second dark block on the page after .beat. Everything
   inside re-points the accent the same way .beat does: --accent-deep is the readable accent on
   white and the pale --accent is the readable one on near-black, so one scoping line saves
   hand-picking a colour for every child. Never hand-edit the colours below it. */
.hero{
  /* Briefed for this slot: a night road check, officer from behind in a lime POLICJA vest,
     blue strobes behind, a car framing the right edge, and the LEFT HALF deliberately empty
     because the copy column sits there. Swapping it is this one line. */
  --hero-shot:url("/images/hero-bg-ca9bd9bffde7c16b0cdf6bd8fe8ae454.webp");
  /* The whole section runs on the dark-surface accent. --accent (#b8c4dc) is a desaturated
     blue-grey: a surface tint on white, which is all it was ever asked to be, and as an accent
     on near-black it reads as grey however much of it you use. Re-pointing --accent, its -rgb
     and --accent-deep together means every tint inside the hero follows from the one token in
     :root, so no rule below has to know which surface it is on. */
  --accent:var(--accent-on-dark);
  --accent-rgb:var(--accent-on-dark-rgb);
  --accent-deep:var(--accent-on-dark);
  /* The FILLED accent surfaces - the pill on the headline, the advocate's tick. Same colour
     as everything else accented in here; because it is a BACKGROUND, its type goes dark
     (#0f1114 on #9db8e6 is 8.2:1; white on it would be 1.9:1). */
  --accent-fill:var(--accent-on-dark);
  --accent-fill-ink:var(--bg-dark);
  position:relative;isolation:isolate;overflow:hidden;
  background:var(--bg-dark);color:rgba(var(--ink-on-dark-rgb),.9);
  padding-top:calc(var(--head-h) + clamp(20px,5vh,56px));padding-bottom:0;
  /* Fill the screen. The section used to be only as tall as its content, so on a big monitor it
     sat in the top two thirds with the next section already showing - it read as a small block
     rather than an opening.
     svh, not vh, with vh first as the fallback: on mobile 100vh is the viewport with the
     browser chrome RETRACTED, so a vh-only hero is taller than the screen at rest and the stats
     strip hides under the address bar. min-height, never height, so a short laptop screen or a
     long translation grows the section instead of overflowing it. */
  min-height:100vh;
  min-height:100svh;
  display:flex;flex-direction:column;
}
/* The copy row takes the slack, and it already centres its own content, so everything sits in
   the optical middle while the stats strip stays pinned to the foot. */
.hero > .wrap{width:100%}   /* see the note above: flex items shrink to fit without this */
.hero > .hero-grid{flex:1}
/* The photograph, plus the scrim that makes the copy readable over it. Two gradients: one from
   the left so the text column sits on near-solid ink, one from the bottom so the stats strip
   does. --hero-shot is the only thing to change to swap the picture. */
.hero-bg{
  position:absolute;inset:0;z-index:-1;
  background-image:
    linear-gradient(90deg, var(--bg-dark) 0%, rgba(var(--bg-dark-rgb),.9) 34%,
                rgba(var(--bg-dark-rgb),.35) 66%, rgba(var(--bg-dark-rgb),.55) 100%),
    linear-gradient(180deg, rgba(var(--bg-dark-rgb),.42) 0%, transparent 34%,
                rgba(var(--bg-dark-rgb),.88) 100%),
    var(--hero-shot);
  background-size:cover, cover, cover;
  /* 34% vertical, not centre: on a wide-but-short window `cover` scales to the width and
     crops the height, and a centred crop takes the officer's head off. 64% horizontal
     keeps him in frame on a phone, where the crop is the other way round. */
  background-position:center, center, 64% 34%;
}
/* A cool wash over the right half, which is what gives the mock its depth. Periwinkle, not the
   mock's green: the accent stays ours. */
.hero::after{
  content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:radial-gradient(62% 72% at 76% 30%, rgba(var(--accent-rgb),.42), transparent 72%);
}

/* Two rows: the copy row takes all the slack (the grid is the flex:1 child of .hero, so the
   1fr row is what makes the copy sit in the optical middle), and the stats strip is an auto row
   pinned under it. The strip used to be a separate .wrap; it is in here so that on a phone it
   is a SIBLING of the advocate card and `order` can put it first. */
.hero-grid{
  display:grid;
  grid-template-rows:1fr auto;
  column-gap:clamp(28px,4vw,64px);
  row-gap:clamp(20px,4vh,48px);
  align-items:center;
}
.hero-stats{grid-column:1/-1}

/* There is no .hero-eyebrow any more. It was a three-part slogan above the headline and it
   cost two reserved lines at the very top of a phone screen for copy that said nothing the
   headline does not. `hero.eyebrow` is still in all three bundles, unused - the key sets have
   to match each other, and an unused key costs nothing. */
.hero h1{
  margin:0 0 clamp(14px,2.4vh,22px);
  /* The 70px cap is set by the widest pill word at the widest the copy column ever gets:
     the .wrap stops at 1180px, so above ~1220px viewport the column is a fixed 585px and the
     Polish pill word has to fit it. At 74px it did not, which is what pushed the grid; 70px
     fitted with 4px to spare, which is not a margin, so this is 68px (21px spare). If the
     headline copy ever changes, re-measure `.hero h1 > span.mark` against `.hero-copy`. */
  font-size:clamp(34px,min(4.6vw,8.2vh),68px);line-height:1.04;letter-spacing:-.035em;
  font-weight:800;color:#fff;
  /* Reserve three lines so the column below cannot shift when the language changes. */
  min-height:3.12em;
}
/* One line per part, in every language: left to wrap naturally the headline broke differently
   per language and moved everything under it. .mark stays inline-block so the pill hugs the
   word instead of stretching the line. */
.hero h1 > span{display:block}
.hero h1 > span.mark{display:inline-block;background:var(--accent-fill);color:var(--accent-fill-ink)}
/* THE FLOORS. Nothing in the hero may change height between languages - the column is
   vertically centred, so a block that wraps one line further in Polish moves everything above
   it too. Each floor is the MAXIMUM any of ru/uk/pl needs anywhere in that band, measured
   (scratchpad/natural.py), not guessed: too low and the hero jumps on a language switch, too
   high and a phone screen fills with reserved blank. */
.hero .sub{margin:0 0 clamp(18px,3.2vh,30px);max-width:52ch;
  min-height:6.4em;   /* four lines x 1.6 */font-size:clamp(16px,1.3vw,18.5px);color:rgba(var(--ink-on-dark-rgb),.86)}

/* The advocate card. White on the dark section so it reads as a note laid on top, and it
   carries the one genuinely concrete line on the page. */
.advocate{
  background:rgba(255,255,255,.11);
  border:1px solid rgba(255,255,255,.24);
  border-radius:var(--radius);padding:20px 22px;
  -webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);
}
.advocate-head{display:flex;align-items:center;gap:12px;margin-bottom:14px}
.advocate-mark{
  flex:none;width:34px;height:34px;border-radius:10px;
  background:var(--accent-fill);color:var(--accent-fill-ink);
  display:grid;place-items:center;font-style:normal;font-size:16px;font-weight:700;
}
/* The text block FILLS the row rather than shrink-wrapping its content. It was the last thing
   in this card whose size still followed the language - 184px in ru and pl, 163px in uk - and
   the same trap as the hero buttons before it: a flex item with no basis is as wide as its
   longest word happens to be in that translation. */
.advocate-head > span{flex:1;min-width:0}
/* Both lines are short labels and are pinned to exactly one line: a wrap here would push the
   quote down, and since the hero column is vertically CENTRED it would move the whole hero,
   headline included. The floor keeps the height when the type is short, nowrap keeps it when
   a translation is long, and the ellipsis is the safety net for a translation longer than the
   card - the alternative is the card silently changing height again. */
.advocate-head b,
.advocate-head small{
  display:block;min-height:1.6em;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.advocate-head b{font-size:15px;color:#fff}
.advocate-head small{margin-top:1px;font-size:12.5px;color:rgba(var(--ink-on-dark-rgb),.72)}
.advocate-quote{
  margin:0;padding-left:14px;border-left:2px solid var(--accent);
  font-size:14px;line-height:1.55;color:rgba(var(--ink-on-dark-rgb),.92);font-style:italic;
  min-height:4.65em;   /* three lines: the card must not change height per language */
}

/* Stats strip along the foot, above a hairline, as in the mock. */
.hero-stats{
  list-style:none;margin:0;padding:clamp(14px,2.4vh,22px) 0 clamp(18px,3vh,28px);
  border-top:1px solid rgba(255,255,255,.2);
  display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:16px;
  align-self:end;
}
.hero-stats li{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap}
.hero-stats b{font-size:clamp(20px,1.7vw,26px);font-weight:800;letter-spacing:-.03em;color:#fff}
.hero-stats span{font-size:13px;color:rgba(var(--ink-on-dark-rgb),.9)}

/* --- CTAs. The primary is white on the dark section; the ghost is an outline. --- */
.hero-actions{display:flex;flex-wrap:wrap;align-items:center;gap:12px}
.cta-primary{
  display:flex;align-items:center;gap:12px;
  min-width:320px;
  background:#fff;color:var(--ink);
  padding:12px 12px 12px 26px;border-radius:var(--radius-pill);
  font-weight:600;font-size:15px;text-decoration:none;
  transition:opacity .15s, transform .15s;
}
.cta-primary:hover{opacity:.9;transform:translateY(-1px)}
.cta-price{margin-left:auto;font-weight:500;color:var(--muted);white-space:nowrap}
.cta-arrow{
  flex:none;width:34px;height:34px;border-radius:50%;
  display:grid;place-items:center;
  background:var(--ink);color:#fff;font-size:15px;line-height:1;
  transition:transform .15s ease;
}
.cta-primary:hover .cta-arrow{transform:translateX(2px)}
.cta-ghost{
  display:flex;align-items:center;justify-content:center;
  padding:14px 26px;border-radius:var(--radius-pill);
  border:1px solid rgba(255,255,255,.28);background:transparent;
  color:#fff;font-weight:600;font-size:15px;text-decoration:none;
  transition:border-color .15s, background .15s;
}
.cta-ghost:hover{border-color:#fff;background:rgba(255,255,255,.08)}
.cta-ghost{gap:9px}
.cta-ghost .cta-tg{width:17px;height:17px;flex:none;fill:currentColor;margin-left:-3px}

/* ============================== SITUATIONS ============================== */

/* WHITE. No rule above or below it: the step from the dark hero and down to the grey
   #why section is the division, and a hairline on top of a tone change reads as a seam. */
.sit{background:var(--bg-2)}
.sit-grid{display:grid;gap:16px;margin-bottom:28px}

/* Tall dark cards, after the LegalOne reference: title at the top, one line of copy and a round
   arrow at the foot, a photograph filling the whole card behind a scrim. They are the only dark
   thing on a light section, which is the point — this is the "is this for me?" content and it
   was disappearing as three pale panels.

   NO PHOTOGRAPHS SHIP YET. --shot is unset, so each card falls back to the tinted near-black
   panel below and nothing 404s. Adding a photo is one line per card, at the bottom of this
   block. The reference has no icons on its cards; the badge is kept here because these three
   glyphs are drawn to the logo's rule and are the only place that family appears.

   The card is a LINK to the form. An arrow button that goes nowhere is worse than no arrow,
   and it turns the whole card into conversion surface. */
.sit-card{
  position:relative;isolation:isolate;overflow:hidden;
  display:flex;flex-direction:column;
  min-height:clamp(300px,30vw,400px);
  padding:26px;
  border-radius:24px;
  background-color:var(--ink);
  /* the no-photo state: a periwinkle wash off the top edge so the panel is not a flat slab */
  background-image:radial-gradient(120% 90% at 50% -10%,
                   rgba(var(--accent-rgb),.20), transparent 62%);
  color:#fff;text-decoration:none;
  transition:transform .2s ease, box-shadow .2s ease;
}
/* the photograph */
.sit-card::before{
  content:"";position:absolute;inset:0;z-index:-2;
  background-image:var(--shot,none);
  background-size:cover;background-position:center;
  transform:scale(1.02);
  transition:transform .55s ease;
}
/* Legibility scrim. Dark at BOTH ends because the title sits at the top and the copy at the
   foot; a single top-down gradient leaves the bottom line floating on whatever the photo does. */
.sit-card::after{
  content:"";position:absolute;inset:0;z-index:-1;
  background:linear-gradient(180deg,
             rgba(10,12,15,.60) 0%, rgba(10,12,15,.20) 38%, rgba(10,12,15,.88) 100%);
}
.sit-card:hover{transform:translateY(-3px);box-shadow:0 18px 40px rgba(var(--ink-rgb),.18)}
.sit-card:hover::before{transform:scale(1.06)}

/* No icon badge: the reference puts nothing above the title, and on a photograph a second
   framed object next to the headline is one element too many. The three glyphs that used to
   sit here (handcuffs, document, collision) are gone from the page entirely. */
.sit-card h3{
  margin:0;max-width:13ch;
  font-size:clamp(21px,1.9vw,27px);line-height:1.14;letter-spacing:-.025em;
  font-weight:800;color:#fff;
}
.sit-foot{
  margin-top:auto;padding-top:26px;
  display:flex;align-items:flex-end;justify-content:space-between;gap:14px;
}
/* min-width:0 because .sit-foot is a flex row and a flex item's default min-width is auto -
   it refuses to shrink below its longest word and pushes the arrow button out of the card
   instead. break-word is the second half: a long Polish compound then breaks rather than
   sticking out on its own. */
.sit-card p{margin:0;min-width:0;overflow-wrap:break-word;
  font-size:14.5px;line-height:1.5;color:rgba(255,255,255,.76)}
.sit-go{
  flex:none;width:44px;height:44px;border-radius:50%;
  display:grid;place-items:center;
  background:rgba(255,255,255,.18);border:1px solid rgba(255,255,255,.30);
  backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
  color:#fff;font-size:17px;line-height:1;
  transition:background .2s ease, color .2s ease, border-color .2s ease, transform .2s ease;
}
.sit-card:hover .sit-go{background:#fff;border-color:#fff;color:var(--ink);transform:translate(2px,-2px)}

/* PHOTOGRAPHS. Square 1:1 crops of the same three Gemini frames the hero uses — the hero takes
   wide slices of them, these take square ones, so the two sections show different regions rather
   than the identical picture twice. Generated by scratchpad/make_sit_shots.py.
   1:1 because the card is near square on desktop but crops to a landscape band on phones, and
   background-size:cover crops from the centre. The fingerprinting resource chain rewrites these
   url()s automatically — never reference them any other way. */
.sit-1{--shot:url("/images/sit-detention-c6b1ef5ce76f74c6e8669b3c67485ece.webp")}
.sit-2{--shot:url("/images/sit-documents-34716c651338ff44ae64865ec8f7e872.webp")}
.sit-3{--shot:url("/images/sit-accident-3997bf3e8ca2f35e8cd7e3645694e123.webp")}

/* ============================== WHY IN ADVANCE ============================== */

.np-grid{display:grid;gap:16px;margin-bottom:22px}
.np-col{border-radius:var(--radius);padding:26px;border:1px solid var(--line)}
.np-col h3{
  margin:0 0 16px;font-size:13px;font-weight:700;
  letter-spacing:.08em;text-transform:uppercase;
}
.np-col ul{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:12px}
.np-col li{position:relative;padding-left:26px;font-size:15px}
.np-col li::before{
  position:absolute;left:0;top:0;font-weight:700;font-size:15px;line-height:1.6;
}

/* BOTH columns are white panels, and that is deliberate. `.np-bad` was transparent for a
   while, on the theory that the column you are being talked out of should not be the brightest
   surface in the section. On a grey section that made it a 5% step from its own background with
   a 5% border - it stopped reading as a panel at all, and the comparison lost one of its two
   halves. This is a COMPARISON: the two sides have to carry equal weight or there is nothing to
   compare. What separates them is the mark, the heading colour and the border, not the fill. */
.np-bad{background:var(--bg-2);border-color:var(--line-2)}
.np-bad h3{color:var(--muted)}
.np-bad li{color:var(--ink-2)}
.np-bad li::before{content:"✕";color:var(--bad)}

/* The answer side is the one that lifts: the accent border it already had, plus a shadow. */
.np-good{
  background:var(--bg-2);border-color:var(--accent-deep);
  box-shadow:0 14px 34px -18px rgba(var(--ink-rgb),.28);
}
.np-good h3{color:var(--accent-deep)}
.np-good li{color:var(--ink-2)}
.np-good li::before{content:"✓";color:var(--ok)}

.np-note{
  margin:0;text-align:center;font-size:15px;color:var(--muted);
}

/* ============================== PLANS ============================== */

.plans{background:var(--bg-2)}   /* WHITE, between the dark beat and the grey form */
.plan-grid{display:grid;gap:16px;margin-bottom:24px;align-items:stretch}
/* The cards carry the WHOLE offer now. The comparison table that used to sit under them is
   gone: it repeated every feature name four times, was the one thing on the page that had to
   scroll sideways on a phone, and the same rows read better inside the card they belong to.
   The feature labels still come from the cmp.r* keys, so there is one source for them. */
.plan{
  display:flex;flex-direction:column;
  /* White on the white section, held by a hairline - NOT a grey fill. A recessed grey card
     beside a solid black one is what made these two look switched off. */
  background:var(--bg-2);border:1px solid var(--line-2);
  border-radius:var(--radius);padding:26px 24px;
}
/* The featured card is near-black, as in the mock. It is the only dark card on a light
   section, which is what "popular" has to look like without inventing a second accent. */
.plan-hl{
  /* Lighter status tints for the dark card: --ok and --bad are tuned for white and go
     muddy on near-black. Scoped, so nothing else sees them. */
  --ok:var(--ok-on-dark);
  --bad:var(--bad-on-dark);
  /* --accent only. NOT --accent-deep: the «popular» badge is a child of this card but it
     straddles the top edge and is painted on the WHITE section behind it, so it needs the
     light-surface accent. Re-pointing --accent-deep here turned it into pale blue on white. */
  --accent:var(--accent-on-dark);
  position:relative;
  background:var(--ink);border-color:var(--ink);color:rgba(255,255,255,.82);
  box-shadow:0 24px 50px -28px rgba(var(--ink-rgb),.6);
}
.plan-badge{
  position:absolute;top:-13px;left:50%;transform:translateX(-50%);
  background:var(--accent-deep);color:#fff;white-space:nowrap;
  border-radius:var(--radius-pill);padding:5px 14px;
  font-size:12px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
}
.plan-head{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:10px}
.plan-name{margin:0;font-size:19px;font-weight:800;letter-spacing:-.02em}
.plan-hl .plan-name{color:#fff}
.plan-for{
  flex:none;background:var(--bg-3);color:var(--ink-2);
  border-radius:var(--radius-pill);padding:4px 10px;
  /* 12px, the same floor the uppercase labels have. It was the last thing on the page under
     it, and on a phone 11.5px is where a badge stops being readable at arm's length. */
  font-size:12px;font-weight:600;white-space:nowrap;
}
.plan-hl .plan-for{background:rgba(255,255,255,.14);color:#fff}
.plan-desc{margin:0 0 18px;font-size:13.5px;line-height:1.5;color:var(--muted);min-height:2.9em}
.plan-hl .plan-desc{color:rgba(255,255,255,.66)}
.plan-price{margin:0 0 4px;display:flex;align-items:baseline;gap:8px;flex-wrap:wrap}
.plan-price b{font-size:40px;font-weight:800;letter-spacing:-.04em;color:var(--ink);line-height:1}
.plan-hl .plan-price b{color:#fff}
/* The slash is punctuation, so it lives in CSS rather than in three translations that
   would each have to remember it. */
.plan-price span{font-size:14px;color:var(--muted)}
.plan-price span::before{content:"/ "}
.plan-hl .plan-price span{color:rgba(255,255,255,.6)}
/* The per-month figure is the number that makes 2490 zl feel payable. */
.plan-permonth{margin:0 0 20px;font-size:12.5px;font-weight:600;color:var(--accent-deep)}
.plan-hl .plan-permonth{color:var(--accent)}
.plan-cta{
  display:flex;align-items:center;justify-content:center;gap:8px;
  background:var(--cta);color:var(--cta-ink);
  padding:13px 18px;border-radius:var(--radius-pill);
  font-weight:600;font-size:14.5px;text-decoration:none;text-align:center;
  transition:opacity .15s, transform .15s;
}
.plan-cta::after{content:"→";font-size:15px;line-height:1}
.plan-cta:hover{opacity:.88;transform:translateY(-1px)}
.plan-hl .plan-cta{background:#fff;color:var(--ink)}

/* PREMIUM. Its copy runs at full strength - the muted description and the grey card together
   read as "unavailable" rather than "the expensive one" - and its CTA is an OUTLINE of the
   same near-black instead of a third filled button, so the eye still lands on the featured
   card first. Colour only: the card keeps every metric the other two have. */
.plan-premium .plan-desc{color:var(--ink-2)}
.plan-premium .plan-feats li{color:var(--ink)}
.plan-premium .plan-price span{color:var(--ink-2)}
.plan-premium .plan-cta{
  background:transparent;color:var(--ink);
  border:1px solid var(--ink);
  padding:12px 18px;   /* the border eats a pixel top and bottom */
}
.plan-premium .plan-cta:hover{background:var(--ink);color:var(--cta-ink);opacity:1}

.plan-feats-h{
  margin:22px 0 12px;font-size:12px;font-weight:700;
  letter-spacing:.12em;text-transform:uppercase;color:var(--muted);
}
/* 15px, not the 11 it started at: nine rows at 11px packed into one block that read as a
   wall rather than a list. */
.plan-feats{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:15px;flex:1}
.plan-feats li{
  display:flex;align-items:center;gap:10px;
  font-size:14.5px;line-height:1.4;color:var(--ink-2);
}
.plan-hl .plan-feats li{color:rgba(255,255,255,.88)}
/* A tick for what a plan includes and a grey EM DASH for what it does not. It was a red ✕,
   which made a tariff card look like a list of failures: red is an error colour, and nothing
   is wrong with a cheaper plan not carrying a feature. The red ✕ survives in exactly one
   place - the «without a subscription» column in #why - where being alarming is the point.
   Green is still a STATUS, the only thing --ok is ever allowed to be. The dark featured card
   re-points the tints (see .plan-hl) the way .beat re-points --accent-deep: #1f7a4d on
   near-black is unreadable. */
.plan-feats i{
  flex:none;width:16px;text-align:center;
  font-style:normal;font-size:15px;font-weight:700;line-height:1.35;
  color:var(--ok);
}
.plan-feats i.y::before{content:"✓"}
/* The same red ✕ (U+2715) the «без подписки» column uses, at the client's request — it was a
   grey em dash for a while, on the argument that red is an error colour and nothing is wrong
   with a cheaper tariff not carrying a feature. Same glyph and same token as #why, so the two
   sections cannot drift apart.
   The ROW text stays muted: the cross marks the absence, the muted line keeps a cheaper card
   from reading as a list of failures. --bad is re-pointed on .plan-hl, so the dark card gets
   the lighter #ff9a92 tint automatically. */
.plan-feats i.n::before{content:"✕"}
.plan-feats i.n{color:var(--bad);font-weight:700}
.plan-feats li.off{color:var(--muted)}
.plan-hl .plan-feats li.off{color:rgba(255,255,255,.42)}
/* The per-plan value that used to live in a table cell: "1", "extended limit", "basic". */
.feat-tag{
  margin-left:auto;flex:none;font-style:normal;
  background:var(--bg-3);color:var(--ink-2);
  border-radius:var(--radius-pill);padding:3px 9px;
  font-size:11px;font-weight:600;white-space:nowrap;
}
.plan-hl .feat-tag{background:rgba(255,255,255,.14);color:#fff}

/* ============================== EDITORIAL BEAT ==============================
   The one dark section on a light page. That means the accent has to flip: --accent-deep
   (#2f4a73) is the READABLE accent on white and is nearly invisible on near-black, while
   --accent-on-dark is the reverse. One scoping rule re-points it for everything inside, so no
   rule below has to know which surface it is on. This is the dual-accent machinery CLAUDE.md
   warns about — a third dark section joins this selector rather than hand-editing colours. */
.beat{
  --accent:var(--accent-on-dark);
  --accent-rgb:var(--accent-on-dark-rgb);
  --accent-deep:var(--accent-on-dark);
  background:var(--bg-dark);
  color:var(--ink-on-dark);
  overflow:hidden;
  padding:clamp(44px,5.5vw,72px) 0;
}
.beat .wrap{display:flex;flex-direction:column;gap:clamp(18px,2.6vw,30px)}

.beat-kicker{
  margin:0;display:flex;align-items:center;gap:10px;
  font-size:12px;font-weight:700;letter-spacing:.16em;text-transform:uppercase;
  color:rgba(var(--ink-on-dark-rgb),.62);
}
.beat-kicker .arr{color:var(--accent)}

/* --- the stage: marquee word, column centred on top --- */
.beat-stage{position:relative;display:grid;place-items:center;min-height:clamp(220px,34vw,440px)}

/* The word scrolls. Four identical copies sit on one track; translating the track by exactly
   -50% lands copy 3 where copy 1 started, so the loop has no seam. Sized so a WHOLE word is
   legible at any width — oversizing it was what made the first cut read as letter soup. */
.beat-word{
  position:absolute;inset:0;
  display:flex;align-items:center;
  overflow:hidden;pointer-events:none;user-select:none;
  /* IN FRONT of the column, and translucent — so the word reads as frosted glass laid over the
     marble and you can still see the carving through it. Behind the column it just occluded,
     which is not what the reference does. The opacity is what does the work: over the black
     ground the grey still reads, over the lit marble it becomes a haze. */
  z-index:2;
  /* The letters are near-WHITE on purpose. Mid-grey letters over lit marble can only ever read
     as a shadow falling on the stone — nothing is darker than the stone except shadow. Near
     white at partial opacity washes the marble brighter instead, so the letterforms come
     forward and stay readable across the column. Over the black ground the same fill simply
     reads as a bright grey.
     Two knobs: this opacity is how much marble shows through; the gradient on
     .beat-word-track span is how bright the letters start. */
  opacity:.72;
  /* SCREEN is what makes the word read over the marble. Normal compositing paints a grey
     letter at 72% onto lit stone, and grey on bright stone can only ever look like a shadow
     falling across it — that is why this got harder to read once the column arrived. Screen can
     only ever lighten: over the black ground screen(black, letter) IS the letter, so the part
     of the marquee off the image is pixel-identical to before, while over the marble the same
     letter washes the stone brighter and the letterforms come forward.

     This blends against whatever is painted below it in the nearest isolation group — the
     column and the section's background. Give .beat-stage or .beat an `isolation`, a `filter`,
     a `transform` or an opacity below 1 and the group changes under it and the effect quietly
     dies. */
  mix-blend-mode:screen;
  /* fades the ends into the background instead of chopping them */
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 12%,#000 88%,transparent);
  mask-image:linear-gradient(90deg,transparent,#000 12%,#000 88%,transparent);
}
.beat-word-track{
  display:flex;width:max-content;
  animation:beatScroll 34s linear infinite;
}
.beat-word-track span{
  /* the gap is padding on each copy, not a flex gap — the track is translated by exactly -50%,
     so every repeated unit has to be identical in width for the loop to be seamless */
  padding-right:.26em;
  font-size:clamp(46px,10.5vw,150px);font-weight:800;letter-spacing:-.045em;line-height:.95;
  background:linear-gradient(180deg,#ffffff 0%,#aeb4be 100%);
  -webkit-background-clip:text;background-clip:text;
  color:transparent;
}
@keyframes beatScroll{
  from{transform:translateX(0)}
  to{transform:translateX(-50%)}
}

.beat-object{
  position:relative;z-index:1;   /* under .beat-word, which is z-index:2 */
  /* The column is the subject, not an ornament — in the reference it is roughly a third of the
     frame. Sized in vw so it holds that proportion at any width. */
  /* Width is the only thing that grew. The crop box height and the stage below are
     deliberately unchanged, so a wider column fills the same vertical band rather than making
     the whole section taller. The floor matters on phones, where a small column left the
     section looking like an accident. */
  width:clamp(240px,42vw,570px);
  /* Cropped, like the reference: capital and upper shaft, with the column running off the
     bottom. The box is shorter than the image, overflow clips it, and the mask dissolves the
     cut into the background rather than leaving a hard horizontal edge. */
  height:clamp(200px,32vw,420px);
  overflow:hidden;
  -webkit-mask-image:linear-gradient(180deg,#000 74%,transparent 99%);
  mask-image:linear-gradient(180deg,#000 74%,transparent 99%);
}
.pillar{
  display:block;width:100%;height:auto;
  /* the engraving is pure white on transparent; a faint glow seats it on the black */
}/* --- the labels pinned around the frame --- */
.beat-meta{
  display:grid;gap:26px;
  border-top:1px solid rgba(255,255,255,.14);
  padding-top:clamp(22px,3vw,32px);
}
.beat-stat b{display:block;font-size:30px;font-weight:800;letter-spacing:-.03em;color:#fff;line-height:1}
.beat-stat span{display:block;margin-top:5px;font-size:13.5px;color:rgba(var(--ink-on-dark-rgb),.6);max-width:22ch}

.beat-copy h2{
  margin:0 0 10px;color:#fff;
  font-size:clamp(22px,2.6vw,32px);line-height:1.15;letter-spacing:-.025em;
}
.beat-copy p{margin:0;font-size:15.5px;color:rgba(var(--ink-on-dark-rgb),.66);max-width:48ch}

.beat-aside{
  margin:0 0 14px;
  font-size:12px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;
  color:rgba(var(--ink-on-dark-rgb),.5);max-width:20ch;
}
.beat-cta{
  /* 174-184px across the three languages; the floor holds it still. */
  min-width:200px;
  display:inline-flex;align-items:center;justify-content:center;gap:10px;
  background:#fff;color:var(--bg-dark);
  padding:13px 24px;border-radius:var(--radius-pill);
  font-weight:600;font-size:15px;text-decoration:none;white-space:nowrap;
  transition:transform .15s ease, box-shadow .15s ease;
}
.beat-cta:hover{transform:translateY(-1px);box-shadow:0 12px 30px rgba(0,0,0,.45)}
.beat-cta .arr{font-size:15px}

/* ============================== FAQ ============================== */

/* The heading and the column are centred; the question and answer text inside each item
   stays left-aligned, because centred body copy is measurably harder to read. */
.faq .eyebrow,
.faq h2{text-align:center}

.faq-list{
  display:flex;flex-direction:column;gap:10px;
  max-width:820px;margin:0 auto;
}
/* The FAQ is the only section with no .sec-sub under its heading, so it was left with just the
   h2's 12px where every other section gets 12 + 36. The adjacent-sibling selector puts that air
   back ONLY when the list follows the heading directly — add a sub-paragraph later and this
   rule stops applying instead of stacking on top of it. */
.faq h2 + .faq-list{margin-top:clamp(26px,3.6vw,40px)}
.faq-item{
  background:var(--bg-2);border:1px solid var(--line);border-radius:var(--radius-sm);
  padding:0 20px;
  transition:border-color .2s ease, box-shadow .2s ease, background .2s ease;
}
.faq-item:hover{border-color:var(--line-2)}
.faq-item[open]{
  border-color:var(--accent);
  box-shadow:0 8px 26px rgba(var(--accent-rgb),.34);
}
.faq-item summary{
  list-style:none;cursor:pointer;
  padding:18px 34px 18px 0;position:relative;
  font-size:16px;font-weight:600;color:var(--ink);
  transition:color .15s ease;
}
.faq-item summary::-webkit-details-marker{display:none}
.faq-item summary:hover{color:var(--accent-deep)}
/* One glyph, rotated — a "+" turned 135deg reads as a close "x", and unlike swapping
   content:"+" for a minus it can actually be transitioned. */
.faq-item summary::after{
  content:"+";
  position:absolute;right:4px;top:50%;
  transform:translateY(-50%) rotate(0deg);
  font-size:22px;font-weight:400;color:var(--muted);line-height:1;
  transition:transform .3s cubic-bezier(.4,0,.2,1), color .2s ease;
}
.faq-item[open] summary::after{
  transform:translateY(-50%) rotate(135deg);
  color:var(--accent-deep);
}
.faq-item p{margin:0;padding:0 0 20px;font-size:15px;color:var(--muted);max-width:68ch}
/* The answer fades up whenever the item opens. This works everywhere, including the
   browsers that cannot animate the disclosure height itself. */
.faq-item[open] > p{animation:faqIn .34s ease both}
@keyframes faqIn{
  from{opacity:0;transform:translateY(-6px)}
  to{opacity:1;transform:none}
}
/* Progressive enhancement: where ::details-content exists (Chromium 131+), the panel also
   animates its HEIGHT open and closed. Needs interpolate-size on :root for the auto keyword
   to be interpolable. Everywhere else this block is simply skipped and the fade above stands. */
@supports selector(::details-content){
  .faq-item::details-content{
    block-size:0;
    overflow:hidden;
    transition:block-size .34s cubic-bezier(.4,0,.2,1), content-visibility .34s allow-discrete;
  }
  .faq-item[open]::details-content{block-size:auto}
}

/* ============================== FORM ============================== */

/* DARK, and the THIRD dark section after the hero and the beat — to the client's mock, which
   puts this one on a deep blue wash rather than on the page tone. It earns it: this is the
   section the whole page points at, and a dark band under the white cards of #plans makes the
   form card the brightest object on the screen when you reach it.
   It also fixes the rhythm rather than breaking it — white · DARK · grey · white — so the
   hairline the FAQ used to need is gone with it.

   The glow is our accent, not the mock's navy-and-magenta: the whole point of the palette pass
   was that the page stopped mixing hues, and a magenta corner would put a fourth one back. Two
   soft radials on near-black, the big one behind the copy column where the mock has it. */
.form-section{
  position:relative;isolation:isolate;overflow:hidden;
  background:var(--bg-dark);
  color:rgba(var(--ink-on-dark-rgb),.86);
}
.form-section::before{
  content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  /* The wash is --accent-deep (#2f4a73), not --accent-on-dark. The pale on-dark accent is a
     TEXT colour: spread thin over near-black it turns blue-GREY, which is what the first two
     attempts looked like. The deep navy is already a page colour - the «popular» badge and the
     tariff per-month figures use it - so the section reads as blue without a new hue entering
     the palette. The pale one comes back on top, small, as the highlight core. */
  background:
    radial-gradient(58% 62% at 26% 26%, rgba(var(--accent-on-dark-rgb),.18), transparent 70%),
    radial-gradient(96% 100% at 24% 28%, rgba(var(--accent-deep-rgb),.92), transparent 68%),
    radial-gradient(70% 70% at 0% 100%, rgba(var(--accent-deep-rgb),.55), transparent 64%),
    radial-gradient(82% 62% at 98% 0%, rgba(var(--accent-deep-rgb),.48), transparent 62%),
    linear-gradient(170deg, rgba(var(--accent-deep-rgb),.38), rgba(var(--accent-deep-rgb),.12) 66%, transparent);
}

/* THE PHOTOGRAPH, desktop only.
   An advocate's desk at night - folder and pen in the lower-left, the legal shelf dissolving
   behind - generated to brief, defocused throughout (which is why 1920px of it is 30KB).

   It loads from 980px up and nowhere else, on purpose. Below that the section stacks to
   390x1383 - portrait - and the white card covers 350x936 of it, so a 2:1 landscape photo
   would crop to a meaningless vertical sliver behind a card nobody can see past. Phones keep
   the plain gradient and download nothing.

   `left center`, not `center`: at 1280 the image is taller than the box, so `cover` scales by
   HEIGHT and crops the sides - centred, that cuts the folder off at the left edge, which is the
   one thing in the frame worth showing. Anchored left it survives at every width.

   The gradient above becomes the scrim rather than an extra layer: the near-black radial keeps
   the rail's corner readable, and the navy linear pulls the leather's warmth back towards the
   page's hue. */
@media (min-width:980px){
  .form-section{--form-shot:url("/images/form-bg-8996aaf4de440264af261fce4962a8ef.webp")}
  .form-section::before{
    background:
      radial-gradient(86% 94% at 18% 20%, rgba(var(--bg-dark-rgb),.95),
                      rgba(var(--bg-dark-rgb),.42) 56%, transparent 76%),
      linear-gradient(150deg, rgba(var(--accent-deep-rgb),.50),
                      rgba(var(--accent-deep-rgb),.24) 58%, rgba(var(--bg-dark-rgb),.60)),
      var(--form-shot) left center / cover no-repeat;
  }
}

/* The rail flips to the dark surface; the card does NOT - it stays the white panel.
   Note this section deliberately does NOT re-point --accent-deep the way .hero and .beat do.
   The white card lives inside it, and --accent-deep is what paints the chosen tariff card's
   border and name on that white ground; re-pointing the token would wash it out. Same trap as
   the «popular» badge on .plan-hl: scope the colours to the elements that are actually on the
   dark surface. */
.form-section h2{color:#fff}

/* ---------------------------------------------------------------------------------------
   SPLIT, to the client's mock: the pitch on the left, the card on the right. The card is
   the wider column - it is the thing being used, the rail is the thing being read - and the
   two are centred against each other rather than top-aligned, because the rail is shorter.
   Stacks below 980px: two columns of ~420px put the +48 pill under the number and wrapped
   every label in the card. --------------------------------------------------------------- */
.form-split{display:grid;gap:34px}
@media (min-width:980px){
  .form-split{
    grid-template-columns:minmax(0,.88fr) minmax(0,1.12fr);
    gap:clamp(40px,5vw,72px);
    /* start, not center: the card is much taller than the rail, and centring left the rail
       floating in the middle of the section with 250px of empty grey above it. Top-aligned,
       the two read as one block with the heading and the card title on the same line. */
    align-items:start;
  }
  .form-aside{padding-top:6px}
}

.form-aside h2{margin:0 0 14px}
/* --muted (#5f6673) is a LIGHT-surface colour: on this section's blue it measured 1.8:1.
   The rail sits on the dark ground, so it takes the on-dark ink. */
.form-aside .sub{margin:0 0 22px;color:rgba(var(--ink-on-dark-rgb),.82);font-size:17px;max-width:38ch}

/* The three chips are the #situations titles, so the two sections cannot drift apart. */
.form-chips{
  list-style:none;margin:0 0 24px;padding:0;
  display:flex;flex-wrap:wrap;gap:8px;
}
.form-chips li{
  display:flex;align-items:center;gap:8px;
  background:rgba(255,255,255,.08);border:1px solid var(--line-on-dark);
  border-radius:var(--radius-pill);padding:7px 14px;
  font-size:13.5px;font-weight:600;color:rgba(var(--ink-on-dark-rgb),.92);
}
.form-chips li::before{
  content:"";width:6px;height:6px;border-radius:50%;
  background:var(--accent-on-dark);flex:none;
}

/* Renders only once LANDING_TG / LANDING_WA are set. */
.form-direct{display:flex;align-items:center;flex-wrap:wrap;gap:10px;margin-bottom:24px}
.form-direct > span{font-size:14px;color:rgba(var(--ink-on-dark-rgb),.6)}
.form-direct .btn-m{
  display:inline-flex;align-items:center;gap:8px;
  background:rgba(255,255,255,.08);border:1px solid var(--line-on-dark);
  border-radius:var(--radius-pill);padding:9px 16px;
  color:#fff;font-size:14px;font-weight:600;text-decoration:none;
  transition:border-color .15s, transform .15s;
}
.form-direct .btn-m:hover{border-color:rgba(255,255,255,.5);transform:translateY(-1px)}

.form-where{display:flex;align-items:flex-start;gap:10px;margin:0}
.form-where svg{width:19px;height:19px;flex:none;color:var(--accent-on-dark);margin-top:1px}
.form-where b{display:block;font-size:14.5px;font-weight:600;color:#fff}
/* .75, not .6: measured against the BRIGHTEST pixel of the gradient behind it - (52,76,110)
   - .6 came out at 3.97:1 and this is 5.1. The DOM contrast sweep cannot see this, because
   the paint comes from a ::before gradient and the walker finds the section's flat
   background instead; gradients have to be checked against pixels. */
.form-where small{display:block;margin-top:1px;font-size:13px;color:rgba(var(--ink-on-dark-rgb),.75)}

/* ---- the card ---- */
.form-card{min-width:0}
#leadForm{
  background:var(--bg-2);border:1px solid var(--line);border-radius:var(--radius);
  padding:28px;
  /* Deeper than the old one: a 5%-ink shadow is invisible on a dark ground, and the card
     needs to sit ON the section rather than be pasted into it. */
  box-shadow:0 28px 60px -20px rgba(0,0,0,.55);
}
.form-card-h{margin:0 0 6px;font-size:22px;font-weight:800;letter-spacing:-.02em}
/* The card's own promise line, from the mock. The rail's .sub no longer says the same thing:
   two near-identical sentences 60px apart on desktop read as a bug, so the rail keeps the
   product line and the card keeps the "what happens next" one. */
.form-card-sub{margin:0 0 20px;font-size:14.5px;color:var(--muted);line-height:1.5}

/* Name + phone share a row - the one idea worth taking from the mock. It collapses at 620px,
   not at the usual 760 breakpoint, because what runs out first is not the viewport but the
   HALF of the card: under ~300px a half cannot hold the country pill and the number side by
   side. Tariff and email used to pair here too; the tariff picker is full-width now, so email
   sits on its own row. */
.field-row{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:18px}
.field-row > .field{margin-bottom:0;min-width:0}
@media (max-width:620px){
  .field-row{grid-template-columns:1fr;gap:0;margin-bottom:0}
  .field-row > .field{margin-bottom:18px}
}

.field{margin-bottom:18px}
label.l{display:block;margin-bottom:7px;font-size:14px;font-weight:600;color:var(--ink)}
.req{color:var(--bad)}
.opt{font-weight:400;font-size:12px;color:var(--muted)}

.ctrl{
  width:100%;
  /* White fields with one quiet border. They used to be a grey fill inside a white card,
     which read as pre-filled or read-only. */
  background:var(--bg-2);
  border:1px solid var(--line-2);
  border-radius:var(--radius-sm);
  padding:12px 14px;
  color:var(--ink);
  /* 16px is a HARD floor, not a preference: iOS Safari zooms the whole page when a focused
     input is smaller than that, and never zooms back out. This was 15px. */
  font-family:inherit;font-size:16px;
  transition:border-color .15s, background .15s, box-shadow .15s;
}
.ctrl::placeholder{color:var(--placeholder)}
/* A DARK focus ring, not an accent one: the fields are white now, and the pale periwinkle
   halo on white was barely a state change. This is the same near-black as the submit button. */
.ctrl:focus{
  outline:none;
  background:var(--bg-2);
  border-color:var(--ink);
  box-shadow:0 0 0 3px rgba(var(--ink-rgb),.14);
}
.ctrl.er{border-color:var(--bad)}

/* --- radio chips: three EQUAL segments across the card, as in the mock ---
   Not pills sized to their own labels. With two-column rows above and below, a left-aligned
   pill row left the right third of the card empty and the card read as ragged. The selected
   one is a FILLED near-black pill - the same --cta the submit button uses, so "chosen" and
   "the action" speak with one colour. `contactMethod` has three options in every language,
   and three across fits down to 360px. */
.radios{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px}
.chip{cursor:pointer;display:block}
.chip input{position:absolute;opacity:0;width:0;height:0}
.chip span{
  display:flex;align-items:center;justify-content:center;
  min-height:42px;text-align:center;
  border:1px solid var(--line-2);border-radius:var(--radius-pill);
  background:var(--bg-2);color:var(--ink-2);
  padding:8px 10px;font-size:14px;
  transition:border-color .15s, background .15s, color .15s;
}
.chip:hover span{border-color:var(--accent-deep);color:var(--ink)}
/* The chosen contact method is a FILLED near-black pill - the same --cta the submit button
   uses, so "selected" and "the action" speak with one colour. */
.chip input:checked + span{
  background:var(--cta);border-color:var(--cta);color:var(--cta-ink);font-weight:600;
}
.chip input:focus-visible + span{box-shadow:0 0 0 3px rgba(var(--ink-rgb),.2)}

/* --- the tariff picker: three cards, to the client's mock (this was a <select>) ---
   Deliberately NOT the same visual as the contact-method chips directly above it. Those fill
   with --cta when chosen; two filled near-black blocks stacked would make the middle of the
   card the heaviest thing in the section and give equal weight to a throwaway choice and the
   expensive one. The tariff takes the ACCENT instead - tinted fill, --accent-deep border and
   name - which is the same grammar #plans uses to mark the chosen route. */
.plan-pick{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px}
.plan-opt{cursor:pointer;display:block;min-width:0}
.plan-opt input{position:absolute;opacity:0;width:0;height:0}
.plan-opt > span{
  display:flex;flex-direction:column;gap:3px;height:100%;
  border:1px solid var(--line-2);border-radius:var(--radius-sm);
  background:var(--bg-2);padding:12px 13px;
  transition:border-color .15s, background .15s, box-shadow .15s;
}
.plan-opt b{font-size:14.5px;font-weight:700;color:var(--ink);line-height:1.25;min-width:0}
.plan-opt small{font-size:12.5px;color:var(--muted);line-height:1.3}
.plan-opt:hover > span{border-color:var(--accent-deep)}
.plan-opt input:checked + span{
  background:rgba(var(--accent-rgb),.34);
  border-color:var(--accent-deep);
  /* an INSET ring, not a 2px border: a thicker border resizes the box, and the two cards
     beside it would jog by a pixel every time the choice changes */
  box-shadow:inset 0 0 0 1px var(--accent-deep);
}
.plan-opt input:checked + span b{color:var(--accent-deep)}
.plan-opt input:checked + span small{color:var(--ink-2)}
.plan-opt input:focus-visible + span{box-shadow:0 0 0 3px rgba(var(--ink-rgb),.2)}
/* both, or focusing the chosen card would drop its ring */
.plan-opt input:checked:focus-visible + span{
  box-shadow:inset 0 0 0 1px var(--accent-deep), 0 0 0 3px rgba(var(--ink-rgb),.2);
}
/* What runs out here is never the viewport - it is the CARD's inner width, and the two do not
   move together. Measured inner width per column, ru/uk/pl:

     >=1280  171px   split, but .wrap is capped at 1180 so the card stops narrowing
     980-1279 136-144px   split, card column at its NARROWEST - the tight band
     561-979  154-257px   stacked, the card is the full .wrap
     <=560    one per row

   So the squeeze is in the MIDDLE of the range, not at the bottom of it. At 980 Polish
   «OCHRONA PLUS» wrapped to two lines in a 108px cell and made the whole Polish card 19px
   taller than the Russian one. Trim the type and the padding rather than stack: 104px of name
   in 114px of cell. */
@media (min-width:980px) and (max-width:1279px){
  .plan-opt > span{padding:11px 10px}
  .plan-opt b{font-size:13.5px}
}

/* Below 560 three across cannot hold the longest name at any readable size. One per row
   instead, name on the left and price on the right - and 46px tall, which is a finger. */
@media (max-width:560px){
  .plan-pick{grid-template-columns:1fr;gap:7px}
  .plan-opt > span{
    flex-direction:row;align-items:center;justify-content:space-between;
    gap:10px;min-height:46px;padding:10px 14px;
  }
  .plan-opt small{flex:none;text-align:right}
}
/* 320px: name + price on one line needs 196px and the cell gives 208 only once the type and
   the padding come down. Without this «ЗАЩИТА PLUS» wrapped and left the middle card 12px
   taller than the two around it. Scoped to <=400 like the hero's floors, so 360-412 keep the
   bigger type they already fit. */
@media (max-width:400px){
  .plan-opt > span{gap:8px;padding:10px 12px}
  /* the NAME only: the price is already the shortest string in the row, and dropping it to
     12px would put it on the page's floor for no gain */
  .plan-opt b{font-size:13.5px}
}

/* --- consent, implicit ---
   No checkbox: the mock makes pressing the button the consent and says so underneath. It is
   the quietest text in the card on purpose, but it still has to be read - 13px --muted is
   5.8:1 on white, which clears AA. */
.consent-note{margin:14px 0 0;font-size:13px;color:var(--muted);line-height:1.55}
.consent-note b{color:var(--ink-2);font-weight:600}

/* honeypot — off-screen, never focusable */
/* Honeypot. Clipped in place rather than parked off-canvas for the same reason as .skip:
   left:-9999px leaves it in the document's overflow. It stays reachable to a bot that reads
   the DOM, which is the point, while tabindex/aria-hidden keep it away from people. */
.hp{
  position:absolute;width:1px;height:1px;
  overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);
  white-space:nowrap;border:0;padding:0;opacity:0;
}

.err{display:block;margin-top:6px;font-size:13px;color:var(--bad)}
.submit-error{
  background:rgba(179,38,30,.07);border:1px solid rgba(179,38,30,.3);
  border-radius:var(--radius-sm);padding:13px 15px;margin-bottom:16px;
  font-size:14px;color:var(--bad);
}

.submit{
  width:100%;cursor:pointer;
  display:flex;align-items:center;justify-content:center;gap:10px;
  background:var(--cta);color:var(--cta-ink);
  border:none;border-radius:var(--radius-pill);
  padding:15px 24px;font-family:inherit;font-size:16px;font-weight:600;
  transition:opacity .15s, transform .15s;
}
.submit .arr{font-size:18px;line-height:1;transition:transform .15s}
.submit:hover:not(:disabled){opacity:.88;transform:translateY(-1px)}
.submit:hover:not(:disabled) .arr{transform:translateX(3px)}
.submit:disabled{opacity:.55;cursor:default;transform:none}

/* ============================== intl-tel-input — LIGHT skin ==============================
   Two jobs here, and the FIRST one is structural, not cosmetic:

   1. LAYOUT. The library absolutely-positions its flag container over the input and then
      compensates with an inline padding-left (see the _updateInputPadding override in
      index.html). We want the country pill as a real sibling BESIDE the input instead, so
      `.iti` becomes a flex row and the container is forced back to position:static. Drop the
      position/flex rules and the dial code lands on top of the placeholder.
   2. COLOUR. Aligns the pill and the dropdown with the form controls above. */
.iti{
  width:100%;
  display:flex;
  align-items:stretch;
  gap:8px;
  position:relative;
}
.iti__tel-input{flex:1 1 auto;min-width:0;width:auto}
/* the pill lives outside the input now, so the library's reserved space is dead */
.iti--separate-dial-code .iti__tel-input.ctrl,
.iti--separate-dial-code .iti__tel-input{padding-left:14px !important}

.iti__country-container,
.iti__flag-container{
  position:static;
  flex:0 0 auto;
  height:auto;
}
.iti__selected-flag,
.iti--separate-dial-code .iti__selected-flag,
.iti__country-container{
  display:flex;
  align-items:center;
  gap:5px;
  /* White, like the field beside it. It was a tinted pill, which now that the inputs are
     white read as a separate, greyed-out control rather than part of the phone field. */
  background-color:var(--bg-2);
  border:1px solid var(--line-2);
  border-radius:var(--radius-sm);
  padding:0 11px;
  min-width:86px;
  transition:border-color .15s ease, background-color .15s ease;
}
.iti__selected-flag:hover,
.iti--separate-dial-code .iti__selected-flag:hover,
.iti__selected-flag:focus,
.iti__country-container:hover{background-color:var(--bg-3);border-color:var(--accent-deep)}
.iti__selected-dial-code{color:var(--ink);font-size:14px;font-weight:500}
.iti__arrow{border-top-color:var(--muted)}
.iti__arrow--up{border-bottom-color:var(--muted)}

/* Dropdown panel */
.iti__country-list,
.iti__dropdown-content{
  background:var(--bg-2);
  color:var(--ink-2);
  border:1px solid var(--line);
  border-radius:var(--radius-sm);
  box-shadow:0 14px 38px rgba(var(--ink-rgb),.16);
  max-height:260px;
  padding:6px;
  margin-top:4px;
  font-size:13.5px;
  scrollbar-width:thin;
  scrollbar-color:var(--line-2) transparent;
}
.iti__dropdown-content .iti__country-list{
  border:0;box-shadow:none;margin:0;padding:0;background:transparent;
}

/* SIZE AND ANCHOR THE DROPDOWN.
   The library gives .iti__dropdown-content `position:absolute` and no width at all, so it
   shrink-wraps inside its containing block - which is .iti, and .iti is now HALF a form row
   (256px at 1280px). Country names wrapped onto two lines, the dial codes were pushed against
   them and the list grew a horizontal scrollbar. Nothing to do with the library; the field
   simply got narrower when name and phone were paired.
     right:0, not left   - it is the RIGHT half of the row, so the panel has to grow leftwards,
                           into the card, instead of out past its edge.
     width:max-content   - as wide as the longest row actually needs.
     min-width:100%      - but never narrower than the field itself.
     max-width           - capped, and never wider than the viewport. At 320px the cap wins and
                           the panel spans to the left edge of the screen without crossing it. */
.iti__dropdown-content{
  left:auto;right:0;
  /* max(100%, ...) is the point: `min-width:100%` alone just re-ties the panel to the field,
     and `width:max-content` never exceeds it, so at 980px - where the split is on and the
     field is at its narrowest 204px - the panel stayed 204px and long names truncated.
     This gives it a real floor of 300px, still never wider than the field when the field is
     wider, and never wider than the viewport. */
  width:max-content;
  min-width:max(100%, min(300px, calc(100vw - 40px)));
  max-width:min(340px, calc(100vw - 40px));
}
/* overflow-x:hidden kills the horizontal scrollbar the wrapped rows were causing; the library
   sets overflow-y:scroll on the list, which stays. */
.iti__country-list{overflow-x:hidden}

/* Search field at top of dropdown */
.iti__search-input{
  display:block;
  box-sizing:border-box;
  width:calc(100% - 8px);
  margin:2px 4px 6px;
  padding:9px 12px;
  background:var(--bg);
  color:var(--ink);
  border:1px solid var(--line-2);
  border-radius:8px;
  font-size:13.5px;
  font-family:inherit;
  outline:none;
  transition:border-color .15s ease, box-shadow .15s ease;
}
.iti__search-input:focus{
  border-color:var(--accent-deep);
  box-shadow:0 0 0 3px rgba(var(--accent-rgb),.45);
}
.iti__search-input::placeholder{color:var(--placeholder)}

/* Country rows */
.iti__country{
  display:flex;
  align-items:center;
  gap:10px;
  padding:7px 10px;
  border-radius:6px;
  line-height:1.3;
  cursor:pointer;
}
.iti__flag-box{flex:0 0 auto}
.iti__flag{transform:scale(.9);transform-origin:left center}
/* One line, always. The library ships a `white-space:normal` rule for the list, which is what
   let «Åland Islands» wrap; an ellipsis is the right failure mode for a name that still will
   not fit, not a two-line row in a list of 244. */
.iti__country-name{
  color:var(--ink-2);font-size:13.5px;font-weight:500;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0;
}
.iti__dial-code{color:var(--muted);font-size:12.5px;margin-left:auto;flex:none}

/* Hover vs keyboard-highlight vs currently-selected */
.iti__country:hover{background:var(--bg)}
.iti__country.iti__highlight{background:var(--bg-3)}
.iti__country.iti__active{background:rgba(var(--accent-rgb),.35)}
.iti__country.iti__active .iti__dial-code{color:var(--accent-deep)}

/* Divider between preferred and the rest */
.iti__divider{
  margin:4px 6px;
  border:0;
  border-bottom:1px solid var(--line);
}

/* Scrollbar (webkit) */
.iti__country-list::-webkit-scrollbar,
.iti__dropdown-content::-webkit-scrollbar{width:8px}
.iti__country-list::-webkit-scrollbar-thumb,
.iti__dropdown-content::-webkit-scrollbar-thumb{background:var(--line-2);border-radius:4px}
.iti__country-list::-webkit-scrollbar-track,
.iti__dropdown-content::-webkit-scrollbar-track{background:transparent}

/* Carry our error styling through the wrapper */
.iti .ctrl.er{border-color:var(--bad)}

/* ============================== FOOTER ============================== */

/* Footer structure from the Dobry Piec (kotly) site — brand / links / contact columns, a
   coverage strip and a bottom bar — rebuilt on this landing's light palette. Theirs is navy
   with white text; the tokens below keep it on --bg-2 so the page stays light end to end. */
.site-footer{
  background:var(--bg-2);   /* WHITE, under the grey FAQ - no rule needed */
  padding:clamp(48px,6vw,72px) 0 28px;
  font-size:15px;color:var(--muted);
}
.foot-grid{
  display:grid;grid-template-columns:1fr;gap:34px;
}
.foot-brand .logo{display:inline-flex;align-items:center;gap:9px;text-decoration:none;margin-bottom:12px}
.site-footer .logo .brand-mark{height:34px;width:34px;flex:none;filter:none}
.ft-tag{
  margin:0 0 14px;
  font-size:12px;font-weight:700;letter-spacing:.16em;text-transform:uppercase;
  color:var(--accent-deep);
}
.ft-about{margin:0;max-width:40ch;font-size:15px;color:var(--muted)}

/* h3, not h4: the page goes h1 (hero) -> h2 (section headings) -> h3, and the footer
   columns were jumping straight to h4, which is a skipped level for a screen reader. */
.foot-col h3{
  margin:0 0 16px;
  font-size:12px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;
  color:var(--ink);
}
.foot-col ul{list-style:none;margin:0;padding:0;display:grid;gap:11px}
.foot-col a{color:var(--muted);text-decoration:none;transition:color .2s ease}
.foot-col a:hover{color:var(--ink)}

.foot-contact li{display:flex;gap:10px;align-items:flex-start}
.foot-contact svg{
  width:17px;height:17px;flex:none;margin-top:3px;
  color:var(--accent-deep);
  transition:transform .25s cubic-bezier(.4,0,.2,1);
}
.foot-contact li:hover svg{transform:scale(1.15) rotate(-8deg)}
/* It has its own clock now, so it lays out like its siblings instead of faking the indent. */
.foot-hours{font-size:14px}

.foot-bottom{
  margin-top:36px;padding-top:22px;border-top:1px solid var(--line);
  display:flex;flex-wrap:wrap;gap:14px;justify-content:space-between;align-items:center;
  font-size:13.5px;
}
.foot-bottom .fb-links{display:flex;gap:22px;flex-wrap:wrap;align-items:center}

/* ============================== REVEAL ============================== */

.reveal{opacity:0;transform:translateY(16px);transition:opacity .55s ease, transform .55s ease}
.reveal.in{opacity:1;transform:none}
.d1{transition-delay:.07s}
.d2{transition-delay:.14s}
.d3{transition-delay:.21s}
.d4{transition-delay:.28s}
.d5{transition-delay:.35s}
.d6{transition-delay:.42s}

/* ============================== RESPONSIVE ============================== */

@media (min-width:600px){
  .foot-grid{grid-template-columns:1.5fr 1fr 1.2fr;gap:40px}
  /* minmax(0,...) everywhere, never a bare `fr`. A bare `1fr` is `minmax(auto,1fr)`: the column
     is allowed to grow past its share to fit its MIN-CONTENT, and a grid that grows takes the
     page with it. These two fit comfortably; the zero floor is what guarantees they always will. */
  .np-grid{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}
}

/* TABLET, 761-879: the hero is still ONE column here, so the stats strip runs the full 728px
   across four columns of ~170px - too narrow for «до 3 лет · срок действия» on one line in ru
   and uk, where it wrapped and made the strip 29px taller than the Polish one. The hero is a
   fixed-height flex column, so a taller strip shrinks the row above it and the whole copy block
   moved up: the hero jumped on a language switch, at 768 only. The label goes under the value,
   as it does on phones, which is stable at this width and shorter than the wrapped version. */
@media (min-width:761px) and (max-width:879px){
  .hero-stats li{flex-direction:column;align-items:flex-start;gap:2px}
}

/* The situation cards go three-across from 760, not from 600. At 600 a card is 176px wide:
   the copy wrapped to nine two-word lines and the round arrow was pushed 12px past the right
   edge of the PAGE in Polish. At 768 a card is 236px and the same three read cleanly, so the
   threshold is the phone breakpoint. Below it they stack, as they do on a phone. */
@media (min-width:760px){
  .sit-grid{grid-template-columns:repeat(3,minmax(0,1fr))}
}

@media (min-width:880px){
  /* The tariff cards go three-across HERE, not at 600. A card's min-content is about 264px -
     nine feature rows, several carrying a `white-space:nowrap` tag like «для всех участников» -
     and a third of a 768px tablet is 236. They used to be three-across anyway, so the columns
     grew to fit and the whole PAGE picked up 94px of horizontal scroll. Below this they stack,
     which is what they already did on a phone.
     880 is measured, not chosen: (880 - 40 wrap - 32 gaps) / 3 = 269px a card. */
  .plan-grid{grid-template-columns:repeat(3,minmax(0,1fr))}
  /* And if a translation ever makes a row wider than its card anyway, the tag drops to its own
     line instead of pushing the card out. */
  .plan-feats li{flex-wrap:wrap}
  .beat-meta{grid-template-columns:auto 1fr auto;align-items:start;gap:48px}
  .beat-action{text-align:right;justify-self:end}
  section{padding:96px 0}
  .hero{padding-top:calc(var(--head-h) + clamp(24px,6vh,72px))}
  /* minmax(0,...), not a bare fr: a bare `1.08fr` is `minmax(auto,1.08fr)`, so the column is
     allowed to grow past its share to fit its MIN-CONTENT - and the min-content here is the
     longest unbreakable word in the headline. On a 1080-tall screen the type is at its cap and
     the Polish pill word is wider than the share, so the copy column took 614px against 585 in
     ru/uk and the advocate card lost 67px. A zero floor keeps the two columns proportional in
     every language; the headline cap below is what keeps the word inside its column. */
  /* column-gap only: the shorthand would reset the row-gap that separates the copy row
     from the stats strip, which lives in this grid now. */
  .hero-grid{grid-template-columns:minmax(0,1.08fr) minmax(0,.92fr);align-items:center;
    column-gap:56px}
  /* Three columns with the nav in the middle one, so it is centred on the PAGE rather than
     wherever the logo and the language picker happen to leave it. 1fr on both sides keeps it
     centred even though those two are different widths. */
  .site-header .wrap{display:grid;grid-template-columns:1fr auto 1fr;gap:20px}
  .site-header .logo{justify-self:start}
  .main-nav{display:flex;justify-self:center}
  .head-right{justify-self:end;margin-left:0}
  #leadForm{padding:36px}
}

/* The CTA pair is the one row whose WRAPPING depends on the language, and in a vertically
   centred column that moves everything above it too: at 1100px Russian broke to two rows and
   Polish stayed on one, which shifted the whole hero by 33px when the picker was used.

   The copy column is about (min(1180,vw) - 96) * 0.54 wide and the longest pair needs roughly
   542px, so the two only fit side by side from about 1280px up. Below that they stack, in every
   language, which makes the height deterministic instead of content-dependent. */
@media (min-width:880px) and (max-width:1279px){
  .hero .sub{min-height:8em}   /* five lines here, not four: Polish needs the extra one */
  .hero-actions{flex-direction:column;align-items:stretch}
  .cta-primary{min-width:0}
  .cta-ghost{width:100%}
}

/* ============================== TELEGRAM FLOAT ==============================
   Bottom-right Telegram button plus a one-time bubble. Rendered only when LANDING_TG is set.
   z-index 40: above every section, under the header (50) and the skip link (100). */
.tg-float{
  position:fixed;z-index:40;
  right:max(16px, env(safe-area-inset-right));
  bottom:max(16px, env(safe-area-inset-bottom));
}
/* HIDDEN BY DEFAULT: the script shows it once the hero is scrolled past and hides it again
   over the form. It used to start visible and be hidden by the script, which ran at the end of
   the body - so every visitor saw the button fade OUT over the hero on load. Same pattern as
   .reveal: default hidden, and a <noscript> style in the head turns it on when there is no
   script to do it. visibility rides the transition so a hidden float is out of the tab order. */
.tg-float{
  opacity:0;visibility:hidden;transform:translateY(12px);pointer-events:none;
  transition:opacity .25s ease, transform .25s ease, visibility 0s linear .25s;
}
.tg-float.on{
  opacity:1;visibility:visible;transform:none;pointer-events:auto;
  transition:opacity .25s ease, transform .25s ease, visibility 0s;
}

.tg-fab{
  display:flex;align-items:center;justify-content:center;
  width:56px;height:56px;border-radius:50%;
  background:var(--tg);
  box-shadow:0 12px 28px -10px rgba(var(--ink-rgb),.55);
  transition:transform .15s ease, box-shadow .15s ease;
}
.tg-fab:hover{transform:translateY(-2px);box-shadow:0 16px 32px -10px rgba(var(--ink-rgb),.6)}
.tg-fab:focus-visible{outline:3px solid var(--ink);outline-offset:3px}
/* the plane's visual centre sits right of its box centre, hence the nudge */
.tg-fab svg{width:26px;height:26px;fill:#fff;margin-left:-3px}

/* --- the bubble --- */
.tg-pop{
  position:absolute;right:0;bottom:70px;
  width:min(272px, calc(100vw - 32px));
  background:var(--bg-2);border:1px solid var(--line);border-radius:var(--radius);
  box-shadow:0 20px 44px -18px rgba(var(--ink-rgb),.45);
  opacity:0;transform:translateY(8px);
  transition:opacity .25s ease, transform .25s ease;
}
.tg-pop[hidden]{display:none}   /* the author display would otherwise beat [hidden] */
.tg-pop.show{opacity:1;transform:none}
/* the tail, pointing at the button */
.tg-pop::after{
  content:"";position:absolute;right:22px;bottom:-7px;
  width:12px;height:12px;background:var(--bg-2);
  border-right:1px solid var(--line);border-bottom:1px solid var(--line);
  transform:rotate(45deg);
}
.tg-pop-body{display:block;padding:15px 46px 15px 17px;text-decoration:none;border-radius:inherit}
.tg-pop-body b{display:block;margin-bottom:3px;font-size:15px;font-weight:700;color:var(--ink)}
.tg-pop-body span{display:block;font-size:13.5px;line-height:1.45;color:var(--muted)}
.tg-pop-body:hover b{color:var(--accent-deep)}
.tg-pop-body:focus-visible{outline:3px solid var(--ink);outline-offset:2px}
/* 40px: a close button is the one control on this widget a thumb has to find on its own */
.tg-pop-x{
  position:absolute;top:3px;right:3px;
  width:40px;height:40px;border:0;border-radius:50%;
  background:none;cursor:pointer;
  font-family:inherit;font-size:22px;line-height:1;color:var(--muted);
  transition:background .15s, color .15s;
}
.tg-pop-x:hover{background:var(--bg-3);color:var(--ink)}
.tg-pop-x:focus-visible{outline:3px solid var(--ink);outline-offset:-3px}

@media (prefers-reduced-motion:reduce){
  .tg-float, .tg-float.on, .tg-pop, .tg-fab{transition:none}
}
@media print{ .tg-float{display:none} }

/* ============================== PHONES ==============================
   Placed AFTER the min-width blocks so it overrides them. Two themes here: touch targets and
   vertical economy. 44px is the practical floor for a finger; several controls were sized for
   a cursor and came in around 31px. */
@media (max-width:760px){
  /* ZOOM ARTEFACTS. Reported from a phone: after a pinch-zoom the header bar paints its
     background across only part of its width, and the hero can come back blank while elements
     below it are fine.

     Not a layout bug - documentElement.scrollWidth equals clientWidth at 360 and 412, so there
     is no overflow for the fixed bar to fail to cover. It is compositing: a position:fixed
     element carrying BOTH backdrop-filter and will-change:transform gets its own layer, and
     Android re-rasterises layers at the new scale during a pinch. When that goes wrong the
     layer comes back partly or wholly unpainted, which is exactly the two symptoms.

     will-change was added to stop a scroll flicker, and the blur is worth little on a phone
     where the bar is 40px of a small screen. Both go here; the bar becomes a solid --bg strip,
     which is the ordinary mobile pattern and cannot desynchronise from anything. The same
     treatment for the other two blurred surfaces, which sit over photographs. */
  /* The bar is TRANSPARENT at the top of the page now, because the hero behind it is dark -
     a solid light strip there would cut the hero off. So the solid fallback moves onto the
     scrolled state, which is the only one that ever carried a blur. */
  .site-header{-webkit-backdrop-filter:none;backdrop-filter:none;will-change:auto}
  .site-header.scrolled:not(.over-dark){
    background:var(--bg-2);
    -webkit-backdrop-filter:none;backdrop-filter:none;
  }
  .site-header.scrolled.over-dark{
    background:var(--bg-dark);
    -webkit-backdrop-filter:none;backdrop-filter:none;
  }
  .advocate{-webkit-backdrop-filter:none;backdrop-filter:none;background:rgba(255,255,255,.1)}
  .sit-go{background:rgba(255,255,255,.24);-webkit-backdrop-filter:none;backdrop-filter:none}
}

@media (max-width:760px){
  section{padding:56px 0}
  /* PHONE RHYTHM. Every vertical metric in the hero is tuned for a desktop viewport by a
     clamp() whose vh term resolves generously on a tall phone - 20px here, 27px there, 33px of
     grid padding - and together they ran the section ~90px past the fold on an iPhone. None of
     these is a design change; each is the same spacing asked for in phone units. */
  .hero{padding-top:calc(var(--head-h) + 14px)}
  .hero-grid{row-gap:18px;padding-bottom:18px}
  /* Copy, stats, then the quote card. The strip was the last thing in the section and landed
     half-cut at the bottom edge of a 730px-tall phone screen - visible enough to look broken,
     not visible enough to read. The advocate quote is the supporting line, so it is the one
     that goes below the fold. */
  .hero-copy{order:1}
  .hero-stats{order:2}
  .advocate{order:3}
  .hero h1{margin-bottom:12px}
  .hero .sub{margin-bottom:18px}
  .hero-actions{gap:10px}
  /* Both CTAs the full width of the column. The ghost one shrank to its label, so the pair
     read as two different buttons stacked rather than one choice offered twice. */
  .cta-primary{padding:10px 10px 10px 22px}
  .cta-ghost{width:100%;padding:13px 22px}
  .advocate{padding:16px 18px}
  .advocate-head{margin-bottom:10px}
  /* The strip is four values in a 2x2; its own padding and row gap were the last 23px. */
  .hero-stats{padding:12px 0 16px;gap:12px 16px}
  /* 2x2, not 4 across: at 412px four columns are ~85px each and every value breaks mid-phrase
     («до 3 / лет»). The label goes under the value for the same reason. */
  .hero-stats{grid-template-columns:repeat(2,minmax(0,1fr));gap:18px 16px}
  .hero-stats li{flex-direction:column;align-items:flex-start;gap:2px}
  .hero-stats b{font-size:19px}
  .hero .sub{font-size:16px}
  .sec-sub{font-size:16px;margin-bottom:26px}

  /* --- touch targets --- */
  .lang-btn{padding:11px 14px;font-size:14px}
  .lang-menu a{padding:13px 14px}
  /* min-height, not padding: the span is inline-block, so its height follows the inherited
     line-height and padding alone landed it at 41px. 44px is the floor for a finger. */
  .chip span{min-height:44px;padding:0 10px;font-size:15px}
  .faq-item summary{padding:17px 34px 17px 0}
  /* 10px, not 3: a footer link was a 30px-tall target. 10 + the 24px line box = 44. */
  .foot-col a{display:inline-block;padding:10px 0}
  /* The logo is a LINK, and its mark is 38px, so the hit area was 38x38. The mark stays the
     size it is; the anchor grows around it. */
  .site-header .logo,
  .site-footer .logo{min-width:44px;min-height:44px;justify-content:center}

  /* Full-width stacked CTAs: two pills side by side on a 360px screen leaves each of them
     too narrow to read, and the second one wraps its label. */
  /* Full-width pill, link underneath. The 320px floor would overflow a 360px screen. */
  .hero-actions{gap:14px;align-items:stretch}
  .cta-primary{min-width:0;width:100%}

  #leadForm{padding:20px}
  .plan{padding:24px 20px}
  .foot-grid{gap:28px}
  .foot-bottom{justify-content:flex-start;gap:10px}
}

/* Phones: the matrix STAYS a table and scrolls sideways, with the feature column pinned.
   It used to explode into one block per feature, which repeated each tariff name twelve times
   and made you read DOWN a list instead of ACROSS a comparison, which is the one thing a
   comparison table is for. Pinning the first column and letting the tariff columns scroll is
   how Apple, Stripe and most pricing pages solve this.
   The third column being cut off at the screen edge IS the scroll affordance: nothing else is
   needed, and a fade would have to lie once you reach the end. */

@media (max-width:760px){
  /* Stacked, so a 400px card would be most of a phone screen each. */
  .sit-card{min-height:250px;padding:22px;border-radius:20px}
  .sit-foot{padding-top:20px}
}

@media (max-width:560px){
  /* FAQ rows are ragged on a phone: measured at a true 412px viewport (NOT Chrome headless,
     which silently clamps its window to ~504px and hides this) the cards come out 55px or 82px
     depending on whether the question wraps to a second line, and at 320px the longest ones
     reach three lines.

     Two parts to the fix. First give the text more room so three-line rows stop happening:
     15px type, 16px side padding instead of 20, and 30px reserved for the "+" instead of 34.
     Then pin a uniform height — min-height is the two-line height including padding, and the
     summary becomes a centred flex row so a one-line question sits in the middle of it rather
     than at the top. Rows that still need three lines grow past it instead of being clipped. */
  .faq-item{padding:0 16px}
  .faq-item summary{
    display:flex;align-items:center;
    padding:14px 30px 14px 0;
    min-height:76px;
    font-size:15px;
  }
  .faq-item summary::after{right:2px}
}

@media (max-width:560px){
  /* The 4-line floor holds at 412px but not at 360, where Ukrainian needs six lines and
     Russian and Polish five, so the CTA drifted between languages again. Smaller type pulls
     the worst case back to five lines and the floor then pins all three to the same height.
     Measured, not guessed: see the sweep in the session notes. */
  /* Three blocks, so three lines in every language: the base 3.12em floor is enough and
     the old 5.3em would reserve two blank ones. */
  /* Bigger, not smaller. The headline is the one thing on a phone hero that should be loud,
     and at 7.4vw it was 29px on a 390px screen - smaller than the paragraph felt. The height
     this adds is paid for several times over by the metrics above. */
  /* FILL the column. At 8.4vw the longest line used about two thirds of the width and the
     headline read as small type with a lot of air around it. 10vw is set by the widest pill
     word at the narrowest phone: Polish «bezpieczeństwa» is 287px at 8.4vw in a 372px column,
     so 10vw brings it to ~342px and leaves 30px. Above 440px the 44px cap takes over.
     Re-measure `.hero h1 > span.mark` against `.hero-copy` if the headline copy changes. */
  .hero h1{font-size:clamp(30px,10vw,44px)}
  /* FIVE lines, not six, and the quote drops back to the base three. Measured at 430, 412
     and 400: every language needs exactly five here and exactly three in the quote, so the
     old six-and-four floors were reserving 48px of blank on every phone. */
  .hero .sub{min-height:8em}
  .advocate-quote{min-height:4.65em}
}

@media (max-width:400px){
  /* Polish runs one line longer than Russian and Ukrainian down here, so the paragraph needs a
     five-line floor rather than the four that holds from 401px up. The cost is one blank line
     for the shorter languages; the alternative is the button sitting 26px lower in Polish,
     which is exactly the jump this is meant to stop.

     Verified aligned to the pixel across ru/uk/pl at 360, 390, 412, 560 and 1280. It is NOT
     aligned at 320, where Russian needs a seventh headline line and the others six: raising
     the floor again just moves every language down together and leaves the same 19px gap. A
     320px viewport is rare enough that reserving two blank lines on every phone to chase it is
     the worse trade. */
  /* Six, not seven. At 380 Russian takes five lines where uk and pl take six, and at 360 all
     three take six - so six is the floor that holds, and the seventh line was dead. The quote
     goes back UP to four here: at 360 Ukrainian needs four where ru and pl need three. */
  .hero .sub{min-height:9.6em}
  .advocate-quote{min-height:6.2em}
  #leadForm{padding:20px}
  .plan{padding:24px 20px}
  .radios{gap:6px}
  .chip span{padding:0 6px;font-size:13.5px}
}

/* SHORT windows. A laptop at 1366x640 running Polish - the longest of the three - still spilled
   past the fold once every margin was already height-tracked, because the copy itself was the
   thing that did not fit. This trims the type rather than the spacing.
   min-width:761px because it is a LAPTOP rule: on a 360x640 phone `clamp(30px,7vh,52px)` comes
   out at 45px, which is bigger than the desktop headline and four times the phone rule above.
   Phones get their sizes from the max-width blocks, which already track width. */
@media (max-height:700px) and (min-width:761px){
  .hero h1{font-size:clamp(30px,7vh,52px)}
  .hero .sub{font-size:15.5px;line-height:1.5}
  .hero-stats b{font-size:19px}
  .advocate{padding:16px 18px}
}

@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  .reveal{opacity:1;transform:none;transition:none}
  /* the looping ones must STOP, not run 1000x faster */
  .beat-word-track{animation:none !important}
  *{animation-duration:.01ms !important;transition-duration:.01ms !important}
}
