:root{
  --ink:#1D1D1F; --ink-2:#5B5B60; --ink-3:#6E6E73;
  --bg:#FFFFFF; --bg-alt:#F5F5F7;
  --blue:#0066CC; --blue-fill:#0071E3; --blue-hover:#0077ED;
  --loss:#C7442E;
  --line:#D2D2D7; --line-soft:#E8E8ED;
  --shadow:0 4px 20px rgba(0,0,0,.06);
  --shadow-lift:0 12px 36px rgba(0,0,0,.10);
  --r:18px;
}
*{box-sizing:border-box}
[hidden]{display:none !important}
html{scroll-behavior:smooth}
body{margin:0;background:var(--bg);color:var(--ink);
  font-family:Inter,-apple-system,"SF Pro Text","Helvetica Neue",Arial,sans-serif;
  font-size:17px;line-height:1.47;letter-spacing:-.012em;-webkit-font-smoothing:antialiased}
/* A word longer than its line has nowhere to go and simply overflows: the
   Russian "конфиденциальности" rendered 397px wide in a 346px column and was
   clipped on a phone. Let long words hyphenate, and break them if they still
   will not fit. */
h1,h2,h3,h4{margin:0;font-weight:600;text-wrap:balance;letter-spacing:-.022em;
  overflow-wrap:break-word;hyphens:auto}
p,li,dd,dt,td,th{overflow-wrap:break-word}
p{margin:0}
img{max-width:100%;display:block}
a{color:var(--blue);text-decoration:none}
a:hover{text-decoration:underline}
a:focus-visible{outline:2px solid var(--blue);outline-offset:3px;border-radius:8px}
button:focus-visible,summary:focus-visible,[tabindex]:focus-visible{
  outline:2px solid var(--blue);outline-offset:3px;border-radius:10px}
input:focus-visible,textarea:focus-visible,select:focus-visible{
  outline:2px solid var(--blue);outline-offset:2px}
.skip{position:absolute;left:-9999px}
.skip:focus{left:8px;top:8px;z-index:60;background:#fff;padding:10px 16px;border-radius:10px;box-shadow:var(--shadow)}

/* nav */
/* Transparent over the hero image, solid once you scroll past it. */
/* anchors must not land underneath the fixed bar */
[id]{scroll-margin-top:66px}

/* layout */
section{padding:clamp(60px,8vw,104px) 22px}
section.alt{background:var(--bg-alt)}
.in{max-width:1080px;margin:0 auto}
.narrow{max-width:730px;margin:0 auto}
/* 730px is a reading measure, and the hero headline is not reading matter: at
   the larger size it wrapped inside its own <br> and stranded "to." on a line
   of its own. The hero gets room for the break it was written with; the lead
   keeps the narrow measure so it stays readable. */
.hero .in.narrow{max-width:1080px}
.hero .lead{max-width:840px;margin-left:auto;margin-right:auto}
.center{text-align:center}
.stack-sm{display:flex;flex-direction:column;gap:.9rem}
.stack-md{display:flex;flex-direction:column;gap:1.6rem}
.stack-lg{display:flex;flex-direction:column;gap:clamp(2.4rem,4vw,3.6rem)}

.eyebrow{font-size:18px;font-weight:600;color:var(--blue);letter-spacing:-.01em}
.eyebrow.light{color:#fff;opacity:.9;text-shadow:0 1px 14px rgba(0,0,0,.4)}
/* Headline scale. The old caps (68/48) held the type well below the size the
   layout has room for at 1280px and up, which reads as a brochure rather than
   as a statement. Larger sizes want tighter tracking, hence the extra -.004em. */
/* text-wrap:pretty, not the balance inherited from the h1 rule: balance evens
   the line lengths and was happy to leave "to." alone on the last line of a
   phone. pretty is the one that refuses a short last line. Browsers without it
   drop the declaration and fall back to balance, which is the old behaviour. */
.h-hero{font-size:clamp(38px,5.9vw,82px);line-height:1.03;font-weight:700;letter-spacing:-.038em;
  text-wrap:pretty;hyphens:manual;overflow-wrap:anywhere}
/* one authored line per span; site.js shrinks the type until each fits */
.h-hero .hl{display:block}
.h-sec{font-size:clamp(30px,4.4vw,56px);line-height:1.06;font-weight:700;letter-spacing:-.033em}
.h-sub{font-size:clamp(21px,2.4vw,29px);line-height:1.18;font-weight:600;letter-spacing:-.022em}
.lead{font-size:clamp(18px,1.9vw,22px);line-height:1.42;color:var(--ink-2);letter-spacing:-.016em}
.lead.light{color:rgba(255,255,255,.94);text-shadow:0 1px 18px rgba(0,0,0,.4)}
.body-lg{font-size:18.5px;line-height:1.55;color:var(--ink-2)}
.small{font-size:14px;color:var(--ink-2)}

/* hero with photo */
/* One floor height for every inner hero, so the band is identical in all
   languages and on every page. Content is centred inside it. */
.hero{position:relative;isolation:isolate;overflow:hidden;color:#fff;
  min-height:640px;padding:104px 22px 76px;
  display:flex;align-items:center;justify-content:center}
/* the home hero fills the screen */
.hero.tall{min-height:100svh;padding:132px 22px 104px}
@supports not (height:100svh){.hero.tall{min-height:100vh}}
.hero .bg{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:0}
/* Two stacked scrims at .72/.62 buried the photograph — the canal read as grey
   weather rather than as Amsterdam. The headline is now 82px at weight 700 with
   its own shadow, so it carries itself over a much lighter ground. Kept darkest
   directly behind the text and lifted at the edges, where only the picture is.
   Any further lift and pixelcontrast.mjs starts failing on the lead. */
.hero .scrim{position:absolute;inset:0;z-index:1;
  background:
    radial-gradient(118% 88% at 50% 52%, rgba(0,0,0,.44) 0%, rgba(0,0,0,.30) 62%, rgba(0,0,0,.46) 100%),
    linear-gradient(180deg, rgba(8,10,12,.56) 0%, rgba(8,10,12,.34) 44%, rgba(8,10,12,.62) 100%)}
.hero .bg{filter:saturate(1.02) contrast(1.03) brightness(var(--hero-bright,1))}
.hero .h-hero{text-shadow:0 1px 30px rgba(0,0,0,.28)}

/* buttons */
.pill{display:inline-block;background:var(--blue-fill);color:#fff;font-size:16.5px;
  padding:12px 24px;border-radius:980px;transition:background .2s ease,transform .2s ease}
.pill:hover{background:var(--blue-hover);text-decoration:none;color:#fff}
.pill.ghost{background:rgba(255,255,255,.14);color:#fff;border:1px solid rgba(255,255,255,.4);backdrop-filter:blur(6px)}
.pill.ghost:hover{background:rgba(255,255,255,.24);color:#fff}
section:not(.hero) .pill.ghost{background:transparent;color:var(--blue);border:1px solid var(--line);backdrop-filter:none}
section:not(.hero) .pill.ghost:hover{background:var(--bg-alt);color:var(--blue)}
.btns{display:flex;flex-wrap:wrap;gap:12px;justify-content:center}

/* The three commitments under the hero buttons. Quiet — they are there to be
   read after the headline, not to compete with it — but each separated by a
   rule so they read as three facts rather than one sentence. On a phone they
   stack, and the separators have to go with the row. */
.proof{list-style:none;margin:26px 0 0;padding:0;
  display:flex;flex-wrap:wrap;justify-content:center;align-items:center;
  gap:10px 26px;font-size:14.5px;font-weight:500;
  color:rgba(255,255,255,.82);text-shadow:0 1px 14px rgba(0,0,0,.45)}
.proof li{position:relative;display:flex;align-items:center;gap:26px}
.proof li::after{content:"";width:1px;height:13px;background:rgba(255,255,255,.34)}
.proof li:last-child::after{display:none}
@media(max-width:620px){
  .proof{flex-direction:column;gap:9px}
  .proof li{gap:0}
  .proof li::after{display:none}
}

/* cards */
.grid{display:grid;gap:20px;grid-template-columns:1fr}
@media(min-width:640px){.g2{grid-template-columns:repeat(2,1fr)}.g3{grid-template-columns:repeat(2,1fr)}}
@media(min-width:940px){.g3{grid-template-columns:repeat(3,1fr)}}

.card{background:var(--bg);border-radius:var(--r);padding:28px 26px;display:flex;flex-direction:column;gap:.6rem;
  box-shadow:var(--shadow);transition:transform .35s cubic-bezier(.2,.7,.3,1),box-shadow .35s ease;overflow:hidden}
section:not(.alt) .card{background:var(--bg-alt);box-shadow:none}
.card:hover{transform:translateY(-3px);box-shadow:var(--shadow-lift)}
.card h3{font-size:19.5px;line-height:1.24;letter-spacing:-.018em}
.card p{font-size:15px;line-height:1.52;color:var(--ink-2);letter-spacing:-.008em}
/* margin-top:auto, not a fixed gap: the paragraphs above differ in length, so a
   fixed gap left the three closing lines and their rules at three different
   heights across a row. Auto pins each to the foot of its own card, and the
   cards are already equal height, so the row reads as one row. */
.card .then{color:var(--ink);font-weight:500;border-top:1px solid var(--line-soft);
  padding-top:.75rem;margin-top:auto}
.card.img{padding:0}
.card.img .pad{padding:24px 26px 28px;display:flex;flex-direction:column;gap:.55rem}
.shot{aspect-ratio:16/10;overflow:hidden;background:var(--line-soft)}
.shot img{width:100%;height:100%;object-fit:cover;transition:transform .6s cubic-bezier(.2,.7,.3,1)}
.card.img:hover .shot img,.proj:hover .shot img{transform:scale(1.04)}

/* The figure is the argument on these cards, so it has to outrank the section
   heading above it. At the old 48px it sat under the new 56px headings and read
   as a subtitle. The estimator's own total is deliberately left alone: that
   panel has to fit one screen at 1366x768 and has 22px of headroom. */
.force .n{font-size:clamp(40px,5vw,64px);line-height:1;font-weight:700;letter-spacing:-.042em;font-variant-numeric:tabular-nums}
.force h3{margin-top:.2rem}
.force .src{font-size:11px;color:var(--ink-3);margin-top:auto;padding-top:.7rem}

/* projects */
.proj{background:var(--bg);border-radius:var(--r);overflow:hidden;box-shadow:var(--shadow);display:flex;flex-direction:column;
  transition:transform .35s cubic-bezier(.2,.7,.3,1),box-shadow .35s ease}
.proj:hover{transform:translateY(-3px);box-shadow:var(--shadow-lift)}
.proj .pad{padding:24px 26px 28px;display:flex;flex-direction:column;gap:.6rem;flex:1}
.proj .kind{font-size:11.5px;font-weight:600;color:var(--blue);letter-spacing:.04em;text-transform:uppercase}
.proj h2,.proj h3{font-size:19.5px;letter-spacing:-.018em;font-weight:600}
.proj p{font-size:15px;line-height:1.52;color:var(--ink-2)}
/* The spec block is the reason the card exists — four hard facts, the same
   four on every card, so a reader can compare them down a column rather than
   read five paragraphs. Right-aligned values give it the shape of a spec
   sheet instead of a list. */
/* Two traps here, both only visible in Russian on a 320px phone.
   `1fr` is `minmax(auto,1fr)` and will not shrink below its content's
   min-content width, and `white-space:nowrap` on the label let
   "Ориентировочная стоимость" claim 188px of the 271px available — so the
   value had 83px, could not fit, and hung 15px off the side of the screen.
   The label wraps, and the value track is allowed to shrink. */
.proj dl{margin:0;display:grid;grid-template-columns:auto minmax(0,1fr);gap:.4rem 1rem;font-size:13.5px;
  border-top:1px solid var(--line-soft);padding-top:.85rem;margin-top:auto}
.proj dt{color:var(--ink-3)}
.proj dd{margin:0;font-weight:600;text-align:right;min-width:0}
/* Below this width the two columns stop working: "Ориентировочная стоимость"
   takes most of the row and leaves the figure a column so narrow it breaks one
   character per line. Label above, value below — the numbers stay whole, which
   is the entire point of the block. */
@media(max-width:560px){
  .proj dl{grid-template-columns:1fr;gap:0}
  .proj dt{margin-top:.6rem}
  .proj dt:first-of-type{margin-top:0}
  .proj dd{text-align:left}
}
/* the cost is the figure the eye goes to, so it gets the weight of one */
.proj dl div{display:contents}
.proj .kind.fin{margin-left:.5rem;color:var(--ink-3)}
.proj .kind.fin::before{content:"· "}
.projlink{margin-top:.9rem;font-size:13.5px;font-weight:600;color:var(--blue);
  display:inline-flex;align-items:center;gap:.3rem}
.projlink::after{content:"›";font-weight:400;transition:transform .2s ease;display:inline-block}
.proj:hover .projlink::after{transform:translateX(3px)}

/* steps */
.steps{display:grid;gap:20px;grid-template-columns:1fr}
@media(min-width:640px){.steps{grid-template-columns:repeat(2,1fr)}}
@media(min-width:1000px){.steps{grid-template-columns:repeat(4,1fr)}}
.step{background:var(--bg);border-radius:var(--r);padding:26px 24px;display:flex;flex-direction:column;gap:.55rem;box-shadow:var(--shadow)}
section:not(.alt) .step{background:var(--bg-alt);box-shadow:none}
.step .num{font-size:13px;font-weight:600;color:var(--blue)}
.step h3{font-size:18.5px;letter-spacing:-.017em}
.step p{font-size:14.5px;line-height:1.5;color:var(--ink-2)}

/* split image + text */
.split{display:grid;gap:clamp(24px,3.5vw,52px);align-items:center;grid-template-columns:1fr}
@media(min-width:880px){.split{grid-template-columns:1fr 1fr}.split.flip .shot{order:2}}
.split .shot{aspect-ratio:4/3;border-radius:var(--r);box-shadow:var(--shadow)}
.split .txt{display:flex;flex-direction:column;gap:.75rem}
.split .txt p{color:var(--ink-2);font-size:16.5px;line-height:1.55}

/* chart */
.anchor{background:var(--bg);border-radius:24px;padding:clamp(26px,4vw,50px);box-shadow:var(--shadow);
  display:grid;gap:clamp(26px,4vw,50px);align-items:center;grid-template-columns:1fr}
@media(min-width:920px){.anchor{grid-template-columns:1.05fr 1fr}}
.chart{display:flex;flex-direction:column;gap:22px}
.rng .top{display:flex;justify-content:space-between;align-items:baseline;gap:1rem;margin-bottom:9px}
.rng .lab{font-size:15px;font-weight:600;letter-spacing:-.012em}
.rng .amt{font-size:15px;font-weight:700;font-variant-numeric:tabular-nums}
.rng .amt.loss{color:var(--loss)}
.rng .amt.fee{color:var(--blue)}
.rng .track{position:relative;height:14px;background:var(--line-soft);border-radius:980px}
.rng .span{position:absolute;top:0;height:100%;border-radius:980px}
.rng .span.loss{background:var(--loss)}
.rng .span.fee{background:var(--blue-fill)}
.rng .note{font-size:13px;color:var(--ink-2);margin-top:8px;line-height:1.45}
.axis{display:flex;justify-content:space-between;font-size:11px;color:var(--ink-3);
  border-top:1px solid var(--line-soft);padding-top:7px;font-variant-numeric:tabular-nums}
.anchor .cap{display:flex;flex-direction:column;gap:1rem}
.anchor .cap .src{font-size:12px;color:var(--ink-3)}

/* table */
/* The fee table is 620px wide and will not fit a phone, so it scrolls
   sideways. Two things follow from that. The reader has to be able to SEE that
   there is more table — otherwise the "Priced as" column simply does not exist
   for them — and a keyboard user has to be able to reach it, which site.js
   handles by making an overflowing .scroll focusable.

   The cue is the Verou scroll-shadow: a shadow pinned to the right edge of the
   box, and over it a band of page colour that scrolls WITH the content. When
   there is nothing more to see the band has arrived at the edge and hides the
   shadow, so the hint appears and disappears on its own with no JS at all. */
.scroll{overflow-x:auto;border-radius:var(--r);background:var(--bg);box-shadow:var(--shadow);
  background-image:linear-gradient(to left,var(--bg) 34%,rgba(255,255,255,0)),
                   radial-gradient(farthest-side at 100% 50%,rgba(0,0,0,.17),rgba(0,0,0,0));
  background-repeat:no-repeat;
  background-position:right center,right center;
  background-size:38px 100%,17px 100%;
  background-attachment:local,scroll}
section.alt .scroll{background-color:var(--bg)}
.scroll:focus-visible{outline:2px solid var(--blue);outline-offset:3px}
table{border-collapse:collapse;width:100%;min-width:620px}
th,td{text-align:left;padding:18px 25px;vertical-align:top;font-size:15px;line-height:1.45}
thead th{font-size:11.5px;font-weight:600;color:var(--ink-3);letter-spacing:.04em;text-transform:uppercase}
tbody tr{border-top:1px solid var(--line-soft)}
td b{font-weight:600;color:var(--ink)}
td:nth-child(2){color:var(--ink-2)}
td.fee{white-space:nowrap;font-weight:600}

/* footer */
footer{background:var(--bg-alt);padding:56px 22px 40px;font-size:13.5px;line-height:1.55;color:var(--ink-2)}
footer .in{display:flex;flex-direction:column;gap:2.4rem}
/* The brand column carries a sentence; the others carry short links. Equal
   columns left the sentence wrapping awkwardly beside three near-empty ones,
   so the brand gets the room it needs and the link columns line up together. */
footer .fgrid{display:grid;gap:2.2rem 2.4rem;grid-template-columns:1fr;align-items:start}
@media(min-width:640px){footer .fgrid{grid-template-columns:repeat(2,1fr)}}
@media(min-width:900px){footer .fgrid{grid-template-columns:1.8fr repeat(3,1fr)}}
footer .fbrand{max-width:34ch}
footer .fbrand p{margin-top:.55rem}
footer .flangs{color:var(--ink-3);font-size:12.5px}
footer .flangs a{color:var(--ink-2)}
footer .flangs a:hover{color:var(--ink)}
footer .flangs a.on{color:var(--ink);font-weight:600}
footer .flangs a.on:hover{text-decoration:none;cursor:default}
footer .fcol h2{white-space:nowrap}
@media(min-width:640px){footer .fgrid{grid-template-columns:repeat(2,1fr)}}
@media(min-width:940px){footer .fgrid{grid-template-columns:1.5fr 1fr 1fr 1fr}}
footer h2{font-size:13px;font-weight:600;color:var(--ink);margin-bottom:.6rem}
footer ul{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:.42rem}
footer a{color:var(--ink-2)}
footer a:hover{color:var(--ink)}
footer .flogo{display:inline-flex;align-items:center;gap:9px;margin-bottom:.6rem;color:var(--ink)}
footer .flogo:hover{text-decoration:none}
footer .flogo img{width:30px;height:30px;object-fit:contain;filter:brightness(0);opacity:.88}
footer .flogo b{color:var(--ink);font-size:15px}
footer .rule{height:1px;background:var(--line)}

/* Small print reads left-aligned across the full measure. Right-aligning five
   lines gives every one of them a different starting point, which is exactly
   the thing that makes a block of text hard to scan. */
footer .fine{color:var(--ink-3);font-size:12px;line-height:1.65;max-width:none;text-align:left}
footer .fcopy{color:var(--ink-3);font-size:12.5px;margin-top:-1.2rem}

/* reveal */
/* Scroll reveals removed on purpose. Content that animates in can get stuck at
   opacity 0 and reads as ghosted mid-transition. Visible is better than clever. */
.rv{opacity:1;transform:none}
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  .card,.proj,.pill,.shot img{transition:none}
}

/* comparison table */
table.vs thead th{font-size:12px}
table.vs thead th:first-child{color:var(--ink-3)}
table.vs thead th:last-child{color:var(--blue)}
table.vs td{font-size:15px;width:50%}
table.vs td.them{color:var(--ink-3)}
table.vs td.us{color:var(--ink);font-weight:500}
table.vs td.us{border-left:1px solid var(--line-soft)}

/* ── statement band (breaks up the card rhythm) ───── */
/* Statement bands share one floor height too, so the rhythm of full-width
   image sections is identical in every language and on every page. */
.band{position:relative;isolation:isolate;overflow:hidden;color:#fff;
  min-height:480px;padding:96px 22px;text-align:center;
  display:flex;flex-direction:column;align-items:center;justify-content:center}
.band .bg{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:0;filter:saturate(.9)}
.band .scrim{position:absolute;inset:0;z-index:1;
  background:linear-gradient(180deg,rgba(8,10,12,.74) 0%,rgba(8,10,12,.6) 50%,rgba(8,10,12,.78) 100%)}
.band .quote{font-size:clamp(26px,3.9vw,56px);line-height:1.08;font-weight:600;letter-spacing:-.032em;
  max-width:20ch;margin:0 auto;text-wrap:balance;text-shadow:0 1px 24px rgba(0,0,0,.35)}
.band .sub{margin:1.1rem auto 0;max-width:56ch;font-size:17.5px;line-height:1.5;color:rgba(255,255,255,.86)}

/* ── feature: one big image beside a short list ───── */
.feature{display:grid;gap:clamp(24px,3.5vw,54px);align-items:center;grid-template-columns:1fr}
@media(min-width:940px){.feature{grid-template-columns:1.1fr 1fr}}
.feature .shot{aspect-ratio:5/4;border-radius:24px;box-shadow:var(--shadow)}
.feature ol{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:1.35rem;counter-reset:f}
.feature li{display:grid;grid-template-columns:auto 1fr;gap:1rem;align-items:start}
.feature li::before{counter-increment:f;content:counter(f,decimal-leading-zero);
  font-size:12px;font-weight:600;color:var(--blue);padding-top:.28rem;font-variant-numeric:tabular-nums}
.feature li h3{font-size:18px;letter-spacing:-.016em;margin-bottom:.2rem}
.feature li p{font-size:15px;line-height:1.52;color:var(--ink-2)}

/* ── quiet stat row ───────────────────────────────── */
.statrow{display:grid;gap:1px;background:var(--line-soft);border-radius:var(--r);overflow:hidden;grid-template-columns:1fr}
@media(min-width:700px){.statrow{grid-template-columns:repeat(3,1fr)}}
.statrow>div{background:var(--bg);padding:30px 26px;display:flex;flex-direction:column;gap:.3rem}
.statrow .n{font-size:clamp(32px,3.6vw,42px);line-height:1;font-weight:700;letter-spacing:-.038em;font-variant-numeric:tabular-nums}
.statrow .t{font-size:15px;font-weight:600;margin-top:.3rem}
.statrow .d{font-size:14px;line-height:1.48;color:var(--ink-2)}

/* contact detail blocks */
.detail{display:grid;gap:20px;grid-template-columns:1fr}
@media(min-width:700px){.detail{grid-template-columns:repeat(3,1fr)}}
.detail>div{background:var(--bg-alt);border-radius:var(--r);padding:28px 26px;display:flex;flex-direction:column;gap:.5rem}
.detail h3{font-size:18px}
.detail p{font-size:15px;color:var(--ink-2);line-height:1.5}
.detail a{font-weight:600;font-size:16px}

/* ── estimator ─────────────────────────────────────── */
.est{display:grid;gap:0;grid-template-columns:1fr;border-radius:24px;overflow:hidden;
  box-shadow:0 18px 60px rgba(0,0,0,.10),0 2px 8px rgba(0,0,0,.04);background:var(--bg)}
@media(min-width:820px){.est{grid-template-columns:1.16fr 1fr}}
.est .controls{padding:clamp(20px,2.3vw,30px);display:flex;flex-direction:column;gap:.95rem;background:var(--bg)}
.est .field{display:flex;flex-direction:column;gap:.42rem}
.est .flabel{font-size:11.5px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-3)}
.est .opts{display:flex;flex-wrap:wrap;gap:6px}
/* Ten scope buttons flow-wrapped into four rows in English and five in Dutch and
   Russian, and since the card takes the height of its taller column that alone
   pushed it off the screen in two languages out of three. A fixed two-column
   grid gives the same five rows in every language, whatever the labels say. */
/* Two columns only where they are wide enough to hold the longest label. Below
   this the same grid squeezed "Планировка и конструктив" into 183px and cut it
   short, so there the buttons flow and wrap as normal. */
@media(min-width:1000px){
  .est .opts.pkg{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px}
  .est .opts.pkg button[data-opt]{text-align:left;padding-left:14px;padding-right:14px;
    overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
}
.est button[data-opt]{font:inherit;font-size:14px;padding:7px 12px;border-radius:980px;cursor:pointer;
  border:1px solid var(--line);background:var(--bg);color:var(--ink-2);transition:all .16s ease}
.est button[data-opt]:hover{border-color:var(--ink-3);color:var(--ink)}
.est button[data-opt].on{background:var(--ink);border-color:var(--ink);color:#fff;font-weight:500}
.est .opts.pkg button[data-opt].on::before{content:"✓ ";font-weight:600}
.est .arearow{display:flex;justify-content:space-between;align-items:baseline}
.est #est-area-val{font-size:16px;font-weight:600;font-variant-numeric:tabular-nums}
/* The visible track stays thin, but the input itself is a full-height touch target. */
.est input[type=range]{-webkit-appearance:none;appearance:none;width:100%;height:34px;
  background:transparent;outline:none;margin:0;cursor:pointer;display:block}
/* Filled to the thumb, grey beyond it. --fill is set by estimator.js on every
   render, so it follows a drag and a restored permalink alike. */
.est input[type=range]::-webkit-slider-runnable-track{height:4px;border-radius:980px;
  background:linear-gradient(to right,var(--blue-fill) 0 var(--fill,20.8%),var(--line) var(--fill,20.8%) 100%)}
.est input[type=range]::-moz-range-track{height:4px;border-radius:980px;
  background:linear-gradient(to right,var(--blue-fill) 0 var(--fill,20.8%),var(--line) var(--fill,20.8%) 100%)}
.est input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;width:24px;height:24px;border-radius:50%;
  background:#fff;border:1px solid var(--line);box-shadow:0 2px 8px rgba(0,0,0,.18);margin-top:-10px}
.est input[type=range]::-moz-range-thumb{width:24px;height:24px;border-radius:50%;background:#fff;
  border:1px solid var(--line);box-shadow:0 2px 8px rgba(0,0,0,.18)}
.est input[type=range]:focus-visible{outline:2px solid var(--blue);outline-offset:4px;border-radius:980px}

.est .result{padding:clamp(22px,2.6vw,34px);background:#111316;color:#fff;display:flex;flex-direction:column;gap:1.1rem}
.est .rlabel{font-size:11.5px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:rgba(255,255,255,.55)}
.est .big{font-size:clamp(34px,4.4vw,52px);line-height:1.02;font-weight:700;letter-spacing:-.04em;
  font-variant-numeric:tabular-nums;white-space:nowrap;margin-top:.2rem}
.est #est-empty{font-size:14.5px;color:rgba(255,255,255,.6);line-height:1.5}

/* cost breakdown bars */
/* Stacked on a phone the panel is not beside anything, but it still must not
   grow as the scope changes or every section below it jumps down mid-tap. Same
   idea as the desktop rule: a height fixed for a given screen, scrolling inside
   once there are more rows than fit. */
.est .bd{--bl-h:29.84px;--bl-gap:.7rem;
  display:flex;flex-direction:column;gap:var(--bl-gap);margin-top:.2rem;
  height:clamp(110px, 30vh, calc(10 * var(--bl-h) + 9 * var(--bl-gap)));
  overflow-y:auto;overscroll-behavior:contain;
  scrollbar-width:thin;scrollbar-color:rgba(255,255,255,.28) transparent}
.est .bd::-webkit-scrollbar{width:6px}
.est .bd::-webkit-scrollbar-thumb{background:rgba(255,255,255,.28);border-radius:980px}
.est .bl{display:flex;flex-direction:column;gap:5px;flex:none;min-height:var(--bl-h)}
.est .bt{display:flex;justify-content:space-between;gap:1rem;font-size:13.5px}
.est .bt span:first-child{color:rgba(255,255,255,.72);min-width:0}

/* A `1fr` grid track is really `minmax(auto,1fr)`, so it refuses to shrink below
   its content's min-content width. Without this the panel silently rendered
   wider than its own box and clipped the figures on a phone. */
.est>.controls,.est>.result{min-width:0}

/* Desktop only. The breakdown is the one part of this panel whose length follows
   what the visitor picked; left free it grew 205px between the lightest and the
   heaviest scope and shoved every section below it down the page mid-click. Here
   there is room to reserve all ten packages up front so the box never resizes.
   Below this width the two columns stack, the panel is no longer beside
   anything, and reserving 400px would be dead space — so labels wrap instead of
   being cut short, which matters more on a phone than a fixed height does. */
@media(min-width:820px){
  /* A FIXED height, not a minimum: fixed means the panel never resizes as the
     scope changes, so nothing below it moves. Tying that height to the viewport
     means the whole card still fits on one screen — reserving all ten rows made
     it 954px against 819px of usable height on a 900px window, which is how it
     stopped fitting. 640px is everything in the card that is not the breakdown,
     plus the header and a margin. Past ten rows it caps and scrolls inside. */
  .est .bd{height:clamp(110px, calc(100vh - 664px), calc(10 * var(--bl-h) + 9 * var(--bl-gap)))}
}
@media(min-width:1000px){
  .est .bt span:first-child{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
}
.est .bt span:last-child{font-weight:600;font-variant-numeric:tabular-nums;white-space:nowrap}
.est .bb{height:5px;border-radius:980px;background:rgba(255,255,255,.13);overflow:hidden}
.est .bb i{display:block;height:100%;border-radius:980px;background:rgba(255,255,255,.82);
  transition:width .45s cubic-bezier(.2,.7,.3,1)}

.est .rows{display:flex;flex-direction:column;gap:0;margin-top:.35rem}
.est .row{display:flex;justify-content:space-between;gap:1rem;padding:10px 0;
  border-top:1px solid rgba(255,255,255,.12);font-size:13.5px}
.est .row span:first-child{color:rgba(255,255,255,.6)}
.est .row span:last-child{font-weight:600;font-variant-numeric:tabular-nums;text-align:right;white-space:nowrap}
.est .row.good span:last-child{color:#6FCF97}
/* On a narrow screen the label and the figure share one line, so a longer
   figure squeezes the label into an extra line and the row grows — the row's
   height ends up depending on the number printed beside it. Stack them, and
   every row keeps the same height whatever the value says. */
@media(max-width:430px){
  .est .row{flex-direction:column;align-items:flex-start;gap:1px}
  .est .row span:last-child{text-align:left}
}
.est .note{font-size:11.5px;line-height:1.5;color:rgba(255,255,255,.45);margin-top:.2rem}
.est .rcta{margin-top:.35rem}
.est .rcta .pill{background:#fff;color:#111316;font-weight:500}
.est .rcta .pill:hover{background:#EDEDED;color:#111316}

/* build-period risk notes: a strip beneath the card, not a column inside it */
.riskstrip{margin-top:20px;background:var(--bg);border-radius:var(--r);
  padding:24px clamp(22px,3vw,34px);box-shadow:var(--shadow);
  display:flex;flex-direction:column;gap:1rem}
.riskstrip .rhead{font-size:11.5px;font-weight:600;letter-spacing:.06em;
  text-transform:uppercase;color:var(--ink-3)}
.riskgrid{display:grid;gap:18px 30px;grid-template-columns:1fr}
/* display:grid outranks the UA [hidden] rule, so state it explicitly */
.riskgrid[hidden]{display:none}
@media(min-width:700px){.riskgrid{grid-template-columns:repeat(2,1fr)}}
@media(min-width:1000px){.riskgrid{grid-template-columns:repeat(3,1fr)}}
.risk{display:flex;flex-direction:column;gap:3px;padding-left:15px;position:relative}
.risk::before{content:"";position:absolute;left:0;top:6px;width:6px;height:6px;border-radius:50%}
.risk.high::before{background:#C7442E}
.risk.med::before{background:#E8963C}
.risk.info::before{background:var(--ink-3)}
.risk.good::before{background:#00A651}
.risk b{font-size:14.5px;font-weight:600;letter-spacing:-.01em}
.risk p{font-size:13.5px;line-height:1.5;color:var(--ink-2)}

@media(max-width:860px){
  .est button[data-opt]{padding:12px 16px;font-size:14.5px}
  .est .opts{gap:8px}
}

/* ── sticky conversion bar ─────────────────────────── */
.sticky{position:fixed;left:0;right:0;bottom:0;z-index:35;
  background:rgba(255,255,255,.86);backdrop-filter:saturate(180%) blur(20px);
  -webkit-backdrop-filter:saturate(180%) blur(20px);border-top:1px solid var(--line-soft);
  transform:translateY(110%);transition:transform .38s cubic-bezier(.2,.7,.3,1);
  box-shadow:0 -4px 24px rgba(0,0,0,.06)}
.sticky.show{transform:none}
.sticky .in{max-width:1080px;margin:0 auto;padding:11px 22px;display:flex;align-items:center;
  justify-content:space-between;gap:1rem}
.sticky p{font-size:14.5px;font-weight:500;letter-spacing:-.012em}
.sticky p span{display:block;font-size:12.5px;font-weight:400;color:var(--ink-2)}
.sticky .pill{padding:10px 20px;font-size:15px;white-space:nowrap}
@media(max-width:560px){.sticky p span{display:none}.sticky .in{padding:9px 16px}}
@media (prefers-reduced-motion:reduce){.sticky{transition:none}}

/* ── language switcher ─────────────────────────────── */
/* No JS: reveal the menu on focus/hover so language is always reachable */
.langlist{font-weight:600;font-size:16px;color:var(--ink)}

/* the X takes priority over every colour state */

/* ── header state: transparent over the hero, solid after ──────────
   Kept at the end of the file so it reliably wins the cascade. */
/* Over the hero everything is white; the logo is a dark mark, so invert it. */
/* the CTA pill keeps its own colour in both states */

/* ── mobile navigation: one authoritative block, last in the file ──────
   The stylesheet is layered, so every mobile nav rule lives here to keep
   the cascade predictable rather than scattered across earlier blocks. */

/* ══════════════════════════════════════════════════════════════════════
   NAVIGATION — written once, in one place, in cascade order.
   States: default (transparent over the hero) · .solid (scrolled) · .open (mobile sheet)
   ══════════════════════════════════════════════════════════════════════ */

/* ── structure ─────────────────────────────────────────────────────── */
.nav{position:fixed;top:0;left:0;right:0;z-index:40;
  background:transparent;border-bottom:1px solid transparent;
  transition:background .3s ease,border-color .3s ease}
.nav .in{max-width:1080px;margin:0 auto;padding:0 22px;min-height:56px;
  display:flex;align-items:center;gap:1.5rem}
.nav .brand{display:flex;align-items:center;gap:9px;font-size:15px;font-weight:600;
  letter-spacing:-.01em;text-decoration:none}
.nav .brand:hover{text-decoration:none}
.nav .brand img{width:26px;height:26px;object-fit:contain;transition:filter .3s ease}
.nav #navmenu{display:flex;gap:1.5rem;list-style:none;margin:0 0 0 auto;padding:0;align-items:center}
.nav #navmenu li{margin:0}
.nav #navmenu a{font-size:12.5px;text-decoration:none}
.nav #navmenu li.keep{display:none}          /* the desktop CTA lives in .navright */
.navright{display:flex;align-items:center;gap:10px}
.nav .cta{background:var(--blue-fill);color:#fff;padding:8px 16px;border-radius:980px;
  font-size:12.5px;white-space:nowrap;text-decoration:none;display:inline-block}
.nav .cta:hover{background:var(--blue-hover);color:#fff;text-decoration:none}

/* ── language switcher ─────────────────────────────────────────────── */
.lang{position:relative}
.langbtn{display:flex;align-items:center;gap:5px;font:inherit;font-size:12.5px;font-weight:400;
  letter-spacing:0;background:transparent;border:1px solid transparent;border-radius:980px;
  padding:6px 9px;cursor:pointer;line-height:1;transition:background .18s ease,color .18s ease}
.langbtn svg{flex:none;width:13px;height:13px;opacity:.75}
.langbtn:hover svg{opacity:1}
.langmenu{position:absolute;right:0;top:calc(100% + 10px);min-width:172px;list-style:none;
  margin:0;padding:6px;background:rgba(255,255,255,.96);
  backdrop-filter:saturate(180%) blur(20px);-webkit-backdrop-filter:saturate(180%) blur(20px);
  border:1px solid var(--line-soft);border-radius:14px;box-shadow:0 12px 40px rgba(0,0,0,.16);
  opacity:0;visibility:hidden;transform:translateY(-6px);
  transition:opacity .2s ease,transform .2s ease,visibility .2s;z-index:50}
.lang.open .langmenu{opacity:1;visibility:visible;transform:none}
html:not(.js) .lang:hover .langmenu,html:not(.js) .lang:focus-within .langmenu{
  opacity:1;visibility:visible;transform:none}
.langmenu li{margin:0}
.langmenu a{display:block;padding:10px 12px;border-radius:9px;font-size:14px;
  color:var(--ink-2);text-decoration:none}
.langmenu a:hover{background:var(--bg-alt);color:var(--ink);text-decoration:none}
.langmenu a.on{color:var(--ink);font-weight:600}
.langmenu a.on::after{content:" ✓";color:var(--blue)}
.langlist{font-weight:600;font-size:16px;color:var(--ink)}

/* ── burger ────────────────────────────────────────────────────────── */
.burger{display:none;align-items:center;justify-content:center;width:40px;height:40px;
  border:0;background:transparent;cursor:pointer;border-radius:10px;margin:0;padding:0}
.burger i{display:block;width:20px;height:2px;border-radius:2px;position:relative;
  transition:background .2s}
.burger i::before,.burger i::after{content:"";position:absolute;left:0;width:20px;height:2px;
  border-radius:2px;transition:transform .28s cubic-bezier(.2,.7,.3,1)}
.burger i::before{top:-7px}
.burger i::after{top:7px}

/* ── colour by state ───────────────────────────────────────────────── */
/* Default: over the hero, everything white; the logo is dark so invert it.
   Scoped with :not() so these never compete with the solid/open rules below. */
.nav:not(.solid):not(.open) .brand{color:#fff}
.nav:not(.solid):not(.open) .brand img{filter:brightness(0) invert(1);opacity:.92}
.nav:not(.solid):not(.open) #navmenu a:not(.cta){color:rgba(255,255,255,.86)}
.nav:not(.solid):not(.open) #navmenu a:not(.cta):hover,
.nav:not(.solid):not(.open) #navmenu a.on{color:#fff}
.nav:not(.solid):not(.open) .langbtn{color:rgba(255,255,255,.88)}
.nav:not(.solid):not(.open) .langbtn:hover{background:rgba(255,255,255,.18);color:#fff}
.nav:not(.solid):not(.open) .burger i,
.nav:not(.solid):not(.open) .burger i::before,
.nav:not(.solid):not(.open) .burger i::after{background:#fff}

/* scrolled, or mobile sheet open: solid white with dark ink */
.nav.solid,.nav.open{background:rgba(255,255,255,.94);
  backdrop-filter:saturate(180%) blur(20px);-webkit-backdrop-filter:saturate(180%) blur(20px);
  border-bottom-color:var(--line-soft)}
.nav.solid .brand,.nav.open .brand{color:var(--ink)}
.nav.solid .brand img,.nav.open .brand img{filter:brightness(0);opacity:.88}
.nav.solid #navmenu a:not(.cta),.nav.open #navmenu a:not(.cta){color:var(--ink-2)}
.nav.solid #navmenu a:not(.cta):hover,.nav.solid #navmenu a.on,
.nav.open #navmenu a:not(.cta):hover,.nav.open #navmenu a.on{color:var(--ink)}
.nav.solid .langbtn,.nav.open .langbtn{color:var(--ink)}
.nav.solid .langbtn:hover,.nav.open .langbtn:hover{background:var(--bg-alt);color:var(--ink)}
.nav.solid .burger i,.nav.solid .burger i::before,.nav.solid .burger i::after,
.nav.open .burger i::before,.nav.open .burger i::after{background:var(--ink)}
/* the CTA pill keeps its own colour in every state */
.nav .cta,.nav.solid .cta,.nav.open .cta{background:var(--blue-fill);color:#fff}

/* the CTA label is white in every state, stated after the link colours */
.nav a.cta,.nav a.cta:hover{color:#fff}

/* the open burger is an X: stated last so no colour rule repaints the middle bar */
.nav.open .burger i{background:transparent}
.nav.open .burger i::before{transform:translateY(7px) rotate(45deg);background:var(--ink)}
.nav.open .burger i::after{transform:translateY(-7px) rotate(-45deg);background:var(--ink)}

/* ── mobile ────────────────────────────────────────────────────────── */
@media(max-width:860px){
  .nav .in{flex-wrap:wrap;padding-top:8px;padding-bottom:8px}
  .burger{display:flex}
  .navright .deskcta{display:none}
  .nav.open{background:rgba(255,255,255,.98);box-shadow:0 14px 34px rgba(0,0,0,.10)}

  /* A display toggle rather than an animated max-height. The slide was pretty and
     cost hours to fight; this is unambiguous and cannot be outranked by a transition. */
  .nav #navmenu{display:none;order:3;flex-basis:100%;flex-direction:column;
    align-items:stretch;gap:0;margin:0;padding:0;max-height:none;overflow:visible}
  .nav.open #navmenu{display:flex}
  html:not(.js) .nav #navmenu{display:flex}   /* no JS: always reachable */

  .nav #navmenu li{display:block;border-top:1px solid var(--line-soft)}
  .nav #navmenu li:first-child{margin-top:8px}
  .nav #navmenu li.keep{display:block}
  .nav #navmenu a{display:block;padding:15px 2px;font-size:16px}
  .nav #navmenu .cta{display:inline-block;margin:12px 0 16px;padding:12px 22px;
    font-size:15px;text-align:center}
}

/* anchors must not land underneath the fixed bar */
[id]{scroll-margin-top:70px}

/* ══════════════════════════════════════════════════════════════════════
   LANGUAGE GATE — a small glass panel floating over the blurred page, not a
   white slab. Hidden here and revealed by JS, so crawlers and no-JS visitors
   always get the page itself.
   ══════════════════════════════════════════════════════════════════════ */
.langgate{position:fixed;inset:0;width:100%;max-width:none;margin:0;z-index:120;display:flex;align-items:center;justify-content:center;
  padding:24px;background:rgba(12,14,16,.30);
  backdrop-filter:blur(26px) saturate(150%);-webkit-backdrop-filter:blur(26px) saturate(150%);
  opacity:0;transition:opacity .5s ease}
.langgate[hidden]{display:none}
.langgate.shown{opacity:1}
.langgate.out{opacity:0;pointer-events:none}

.gwrap{width:100%;max-width:326px;padding:30px 22px 20px;
  display:flex;flex-direction:column;align-items:center;text-align:center;
  background:rgba(255,255,255,.58);
  backdrop-filter:blur(40px) saturate(190%);-webkit-backdrop-filter:blur(40px) saturate(190%);
  border:1px solid rgba(255,255,255,.6);border-radius:28px;
  box-shadow:0 30px 70px rgba(0,0,0,.34),0 2px 8px rgba(0,0,0,.12),
             inset 0 1px 0 rgba(255,255,255,.75);
  transform:translateY(10px) scale(.985);
  transition:transform .55s cubic-bezier(.2,.7,.3,1)}
.langgate.shown .gwrap{transform:none}

.glogo{width:34px;height:34px;object-fit:contain;margin-bottom:16px;
  filter:brightness(0);opacity:.8}
/* Sized so the longest greeting still fits on one line in the narrowest panel:
   "Здравствуйте" is 239px at 36px, and a 320px phone leaves only 226px. */
.greet{position:relative;width:100%;font-size:clamp(30px,9vw,36px);
  line-height:1.15;height:1.15em;margin-bottom:6px}
/* The three greetings are stacked in one box, so a symmetrical half-second
   crossfade leaves two of them legible on top of each other for a third of
   every cycle — "Goedendag" printed through "Здравствуйте". The outgoing word
   therefore leaves quickly and the incoming one waits until it has gone: 220ms
   out, then in from 260ms. The two are never readable at the same time. */
.greet .gw{position:absolute;left:0;right:0;top:0;font-size:inherit;font-weight:600;
  letter-spacing:-.03em;line-height:inherit;color:var(--ink);
  opacity:0;transform:translateY(8px);
  transition:opacity .22s ease,transform .22s cubic-bezier(.2,.7,.3,1)}
.greet .gw.on{opacity:1;transform:none;
  transition:opacity .34s ease .26s,transform .42s cubic-bezier(.2,.7,.3,1) .26s}
.gsub{font-size:13.5px;color:var(--ink-2);margin-bottom:20px}

.gopts{width:100%;display:flex;flex-direction:column}
.gopt{display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:13px 12px;font-size:15.5px;font-weight:500;color:var(--ink);
  text-decoration:none;border-radius:12px;transition:background .16s ease}
.gopt + .gopt{box-shadow:inset 0 1px 0 rgba(0,0,0,.07)}
.gopt:hover{background:rgba(255,255,255,.72);text-decoration:none;color:var(--ink);box-shadow:none}
.gopt:hover + .gopt{box-shadow:none}
.gopt svg{color:var(--ink-3);flex:none;width:15px;height:15px}
.gopt:hover svg{color:var(--blue)}

@media (prefers-reduced-motion:reduce){
  /* .greet .gw.on carries its own staggered transition and out-specifies a
     bare .greet .gw, so it has to be named here or the greeting keeps
     animating for a reader who asked it not to. */
  .langgate,.gwrap,.greet .gw,.greet .gw.on{transition:none}
}

/* ── image sections: positive stacking only ────────────────────────────
   A negative z-index can escape its section and paint behind the rest of
   the page. Image 0, scrim 1, content 2 — nothing can leak upward. */
.hero,.band{position:relative;isolation:isolate;overflow:hidden}
.hero > .in,.band > .in{position:relative;z-index:2}

/* ══════════════════════════════════════════════════════════════════════
   ENQUIRY FORM — the conversion point. Apple-plain: one column of quiet
   fields, errors that appear under the field they belong to, and a state
   for every outcome including "the server did not answer".
   ══════════════════════════════════════════════════════════════════════ */
.cform{background:var(--bg);border-radius:var(--r);box-shadow:var(--shadow);
  padding:clamp(24px,3.4vw,40px);display:flex;flex-direction:column;gap:18px}
.frow{display:grid;gap:18px;grid-template-columns:1fr}
@media(min-width:720px){.frow{grid-template-columns:1fr 1fr}}
.ff{display:flex;flex-direction:column;gap:7px;min-width:0}
.ff label{font-size:13.5px;font-weight:600;color:var(--ink);
  display:flex;align-items:baseline;justify-content:space-between;gap:10px}
.ff label .req{font-size:11.5px;font-weight:500;color:var(--ink-3);letter-spacing:.01em}
.ff input:not([type=checkbox]):not([type=radio]),.ff textarea,.ff select{
  width:100%;font:inherit;font-size:16px;color:var(--ink);background:var(--bg-alt);
  border:1px solid transparent;border-radius:12px;padding:13px 14px;
  transition:border-color .16s ease,background .16s ease;appearance:none}
.ff textarea{resize:vertical;min-height:132px;line-height:1.5}
.ff input::placeholder,.ff textarea::placeholder{color:var(--ink-3)}
.ff input:not([type=checkbox]):hover,.ff textarea:hover,.ff select:hover{background:#EFEFF2}
.ff input:not([type=checkbox]):focus,.ff textarea:focus,.ff select:focus{
  background:var(--bg);border-color:var(--blue);outline:none}
.ff input:not([type=checkbox])[aria-invalid=true],.ff textarea[aria-invalid=true]{
  border-color:var(--loss);background:#FDF4F2}
.ff .fer{font-size:13px;color:var(--loss);font-weight:500}
.selwrap{position:relative}
.selwrap::after{content:"";position:absolute;right:16px;top:50%;width:8px;height:8px;
  border-right:1.8px solid var(--ink-3);border-bottom:1.8px solid var(--ink-3);
  transform:translateY(-70%) rotate(45deg);pointer-events:none}
/* appearance:none makes the browser render the chosen option itself, and it
   hard-cuts the text mid-letter under the chevron rather than ellipsising it.
   The labels are written to fit, but a longer one in any language must degrade
   to "…" instead of a word sliced in half. */
.ff select{padding-right:38px;cursor:pointer;text-overflow:ellipsis}

.hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}

.consent{gap:10px}
.chk{display:flex;align-items:flex-start;gap:11px;font-size:14.5px;font-weight:400;
  line-height:1.5;color:var(--ink-2);cursor:pointer}
.chk input[type=checkbox]{flex:none;appearance:auto;-webkit-appearance:checkbox;
  width:20px;height:20px;min-width:20px;padding:0;margin:1px 0 0;border-radius:0;
  background:none;border:0;accent-color:var(--blue-fill);cursor:pointer}
.consent[data-invalid=true] .chk span{color:var(--loss)}
.chk span{flex:1}

.fsend{display:flex;flex-wrap:wrap;align-items:center;gap:14px 18px;margin-top:2px}
.fsend .pill{border:none;cursor:pointer;font-family:inherit}
.fsend .pill[disabled]{opacity:.55;cursor:progress}
.fnote{font-size:14px;color:var(--ink-2);line-height:1.5;flex:1;min-width:220px}
.fnote.warn{color:var(--ink)}
.fnote .mailfb{font-weight:600;white-space:nowrap}
/* the copy button has to read as the same kind of thing as the mail link
   beside it, not as a second submit button */
.fnote button.ascopy{font:inherit;font-weight:600;color:var(--blue);
  background:none;border:none;padding:0;cursor:pointer;text-decoration:none}
.fnote button.ascopy:hover{text-decoration:underline}
.fnote .fcopied{font-weight:600;color:var(--ink)}

.estchip{display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  background:var(--bg-alt);border-radius:12px;padding:12px 14px;font-size:14px;color:var(--ink-2)}
.estchip .dot{flex:none;width:8px;height:8px;border-radius:50%;background:var(--blue-fill)}
.estchip button{margin-left:auto;font:inherit;font-size:13.5px;font-weight:600;color:var(--blue);
  background:none;border:none;cursor:pointer;padding:2px 4px}
.estchip button:hover{text-decoration:underline}

.fdone{background:var(--bg);border-radius:var(--r);box-shadow:var(--shadow);
  padding:clamp(30px,4vw,52px);display:flex;flex-direction:column;align-items:center;
  text-align:center;gap:1rem}
.fdone .tick{width:56px;height:56px;border-radius:50%;background:#E6F6EC;color:#17864A;display:flex;align-items:center;justify-content:center}
.fdone .pill{border:none;cursor:pointer;font-family:inherit;margin-top:.4rem}

/* ── estimator: share / print sit beside the primary action ───────────── */
.est .rcta{display:flex;flex-wrap:wrap;gap:10px;align-items:center}
.est .rcta .pill.sm{font-size:14px;padding:10px 18px;border:1px solid rgba(255,255,255,.32);
  background:transparent;color:rgba(255,255,255,.92);cursor:pointer;font-family:inherit}
.est .rcta .pill.sm:hover{background:rgba(255,255,255,.12);color:#fff}
.est .rcta .pill.sm.ok{border-color:#6FCF97;color:#6FCF97}

/* ── legal pages: long-form reading, one column, generous rhythm ──────── */
.legal{display:flex;flex-direction:column;gap:2.2rem}
.legal .updated{font-size:12.5px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;
  color:var(--ink-3)}
.legal .intro{color:var(--ink)}
.legal .pv{padding:0;display:flex;flex-direction:column;gap:.85rem}
.legal .pv p{color:var(--ink-2);line-height:1.62}
.legal .pv b{color:var(--ink);font-weight:600}

/* ── 404: every page in every language, one click away ────────────────── */
.e4grid{display:grid;gap:20px;grid-template-columns:1fr}
@media(min-width:700px){.e4grid{grid-template-columns:repeat(3,1fr)}}
.e4col{background:var(--bg-alt);border-radius:var(--r);padding:26px 24px}
.e4col h2{font-size:16px;margin-bottom:.7rem}
.e4col ul{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:.45rem}
.e4col a{font-size:15.5px;color:var(--ink-2)}
.e4col a:hover{color:var(--blue)}

/* The estimate as a standalone document: masthead and footer that exist only
   on paper, so a printed estimate identifies itself without the website
   wrapped around it. */
.printdoc,.printfoot{display:none}

/* ══════════════════════════════════════════════════════════════════════
   PRINT — an estimate someone prints should read like a document, not a
   screenshot of a website. Chrome, navigation and photography come off;
   the numbers and the risk notes stay.
   ══════════════════════════════════════════════════════════════════════ */
@media print{
  @page{margin:16mm}
  html{scroll-behavior:auto}
  body{background:#fff;color:#000;font-size:11pt}
  .nav,.sticky,.langgate,.skip,.burger,.band,.hero .btns,
  .est .rcta,footer .fgrid>div:nth-child(2),.e4grid{display:none !important}
  .hero{min-height:auto;padding:0 0 12mm}
  .hero .bg,.hero .scrim,.shot,.feature .shot,.split .shot,.card.img .shot{display:none !important}
  .hero .h-hero{font-size:22pt;color:#000;text-shadow:none}
  .hero .eyebrow.light,.hero .lead.light{color:#333;text-shadow:none}
  section{padding:0 0 8mm;break-inside:avoid}
  section.alt{background:#fff}
  /* The result panel is a dark slab on screen. Printing it as-is wastes a
     cartridge and leaves dark type on a dark ground, so invert the whole
     estimator — panel, children and all — rather than just its outer box. */
  .est,.est .controls,.est .result{background:#fff !important;color:#000 !important;
    box-shadow:none;border:0}
  .est{border:1px solid #999}
  .est .result{border-top:1px solid #999}
  .est .big,.est .row span,.est .rlabel,.est .bt span,.est .note,
  .est .flabel,.est .rows span,.est .row.good span:last-child{color:#000 !important}
  .est .note,.est .rlabel{color:#444 !important}
  .est .row{border-top:1px solid #ccc}
  .est .bb{background:#e4e4e4}
  .est .bb i{background:#555}
  .est button[data-opt].on{background:#fff !important;color:#000 !important;border:1px solid #000}
  .est .opts button:not(.on){display:none}
  .est .opts button.on{border:1px solid #000;color:#000;background:#fff}
  .riskstrip,.card,.proj,.cform{box-shadow:none;border:1px solid #ccc;break-inside:avoid}
  a{color:#000;text-decoration:none}
  a[href^="http"]::after{content:" (" attr(href) ")";font-size:8pt;color:#555}
  .fdone,.legal .pv{break-inside:avoid}

  /* ── "Print or save as PDF" inside the estimator ────────────────────
     That button is part of the estimate, so it must produce the estimate —
     not six and a half pages of the website with the figures somewhere in
     the middle. The script sets .print-est on <html> for the duration of the
     print, so an ordinary Ctrl/Cmd-P still prints the whole page. */
  html.print-est body > *:not(main){display:none !important}
  html.print-est main > section:not(#estimate){display:none !important}
  html.print-est #estimate{padding:0 !important;background:#fff !important}
  html.print-est #estimate > .in{max-width:none;gap:10mm}
  /* the section's own marketing heading is replaced by the document masthead */
  html.print-est #estimate > .in > .narrow{display:none !important}
  html.print-est .printdoc{display:flex;align-items:flex-end;justify-content:space-between;
    gap:12mm;padding-bottom:3mm;margin-bottom:2mm;border-bottom:1.5px solid #111}
  html.print-est .printdoc .pd-brand{display:flex;align-items:center;gap:7px;font-size:15pt}
  /* The mark is light artwork (mean 164/255); on white paper it all but
     disappears. Print it as a solid silhouette instead. */
  html.print-est .printdoc .pd-brand img{width:22px;height:22px;object-fit:contain;
    filter:brightness(0)}
  html.print-est .printdoc .pd-meta{display:flex;flex-direction:column;align-items:flex-end;
    gap:2px;font-size:9.5pt;text-align:right}
  html.print-est .printdoc .pd-meta b{font-size:11pt}
  html.print-est .printfoot{display:block;font-size:8pt;line-height:1.5;color:#444;
    border-top:1px solid #bbb;padding-top:2.5mm;margin-top:2mm}
  /* reserved rows are for on-screen stability; on paper they are dead space */
  html.print-est .est .bd{min-height:0 !important}
  /* a slider track is a control, not information — the value is already shown */
  html.print-est .est input[type=range]{display:none !important}
  html.print-est .est .arearow{margin-bottom:0}
  html.print-est .est{break-inside:avoid}
}

/* Touch targets: the globe and the burger are the two controls a thumb has to
   find in the header. 27px and 40px are comfortable with a mouse and mean on a
   phone, so give them the full 44px on any coarse pointer without disturbing
   the desktop header's proportions. */
@media (pointer:coarse), (max-width:860px){
  .langbtn{min-height:44px;padding-left:12px;padding-right:12px}
  .burger{width:44px;height:44px}
  .langmenu a{padding-top:13px;padding-bottom:13px}
  .gopt{min-height:48px}
}

