/* ==========================================================================
   Rapid Construct — landing page
   Tokens follow docs/RC-WEBSITE-MASTER-PLAN.md section 4, with two overrides
   approved by the owner: --brand and --ink are sampled from the logo file and
   match the approved mockup, so they win over the (pre-logo) plan values.
   ========================================================================== */

:root {
  /* Heading family. The Inter/Unbounded A/B is resolved: Inter stays, and
     Unbounded is no longer loaded. Kept as a variable so the family is still a
     single-value change; switching to a new family also means adding it to the
     font link in the template. */
  --font-heading: 'Inter';
  --font-body: 'Inter';
  --font-fallback: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif;

  --brand: #F65308;
  --brand-dark: #B23C08;
  --ink: #1A1A1A;
  --ink-muted: #5A5A5A;

  /* Phase 2 amendment: sections use only #FFFFFF and #141414. --bg-grey
     survives solely as the image-placeholder fill, never as a section. */
  --bg-light: #FFFFFF;
  --bg-grey: #F2F2F2;
  --bg-dark: #141414;

  /* Motion. Every value here is disabled, not reduced, under
     prefers-reduced-motion at the bottom of this file. */
  --reveal-dur: 320ms;
  --hover-dur: 200ms;
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);

  --line: #E2E2E2;

  --container: 1200px;
  --gutter: 24px;
  --section-pad: 96px;
  --band-pad: 56px;
  --gap: 24px;

  --radius-control: 6px;
  --radius-card: 10px;
  --shadow-card: 0 1px 3px rgba(0, 0, 0, 0.08);
  --control-h: 48px;
}

/* --- base ----------------------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  padding-top: 96px;   /* constant spacer for the fixed band, never animated */
  background: var(--bg-light);
  color: var(--ink);
  font-family: var(--font-body), var(--font-fallback);
  font-size: 17px;
  font-weight: 400;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; }
a { color: inherit; text-decoration: none; }
a:hover { color: var(--brand-dark); }
::selection { background: var(--brand); color: var(--bg-light); }
:focus-visible {
  outline: 3px solid var(--brand-dark);
  outline-offset: 2px;
  border-radius: 2px;
}
/* On the two dark sections the dark ring would disappear. */
.section--dark :focus-visible,
.footer :focus-visible { outline-color: var(--bg-light); }
/* Filled brand controls: ring sits outside the fill so it stays legible. */
.btn--primary:focus-visible,
.floating__call:focus-visible { outline-color: var(--ink); outline-offset: 3px; }

h1, h2, h3 { font-family: var(--font-heading), var(--font-fallback); margin: 0; line-height: 1.15; }
h1 { font-size: 56px; font-weight: 800; text-transform: uppercase; letter-spacing: -0.02em; }
h2 { font-size: 40px; font-weight: 800; text-transform: uppercase; letter-spacing: -0.01em; }
h3 { font-size: 22px; font-weight: 700; }
p { margin: 0; }

.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--bg-light); color: var(--ink);
  padding: 12px 16px; border: 1px solid var(--line); border-radius: var(--radius-control);
}
.skip-link:focus { left: 16px; top: 16px; }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* --- layout primitives ---------------------------------------------------- */

.container { max-width: var(--container); margin: 0 auto; padding: 0 var(--gutter); }
.section { padding: var(--section-pad) 0; }
.section--light { background: var(--bg-light); }
.section--grey  { background: var(--bg-light); }
/* White-on-white boundaries need a rule so sections still read as blocks.
   Still a hard edge: 1px line, no gradient, no fade. */
.section--divided { border-top: 1px solid var(--line); }
.section--dark  { background: var(--bg-dark); color: var(--bg-light); padding: var(--band-pad) 0; }

.eyebrow {
  font-size: 13px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.08em; color: var(--brand-dark); margin-bottom: 16px;
}
.section--dark .eyebrow { color: var(--brand); }
.lede { margin-top: 16px; max-width: 720px; }
.muted { color: var(--ink-muted); }

.grid { display: grid; gap: var(--gap); }
.grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.grid--5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }

/* --- buttons -------------------------------------------------------------- */

.btn {
  height: var(--control-h); padding: 0 28px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--radius-control); border: 1px solid transparent;
  font-family: inherit; font-size: 19px; font-weight: 700; line-height: 1;
  white-space: nowrap; cursor: pointer;
}
/* 19px bold clears the 18.66px WCAG large-text threshold, where AA asks 3:1
   rather than 4.5:1. White on --brand is 3.41:1, so the button passes without
   darkening the brand fill. Two pixels on a 48px control. */
.btn--primary { background: var(--brand); color: var(--bg-light); }
.btn--primary:hover { background: var(--brand-dark); color: var(--bg-light); }
.btn--outline { background: transparent; border-color: var(--ink); color: var(--ink); }
.btn--outline:hover { background: var(--ink); color: var(--bg-light); }
.btn--outline-light { background: transparent; border-color: var(--bg-light); color: var(--bg-light); }
.btn--outline-light:hover { background: var(--bg-light); color: var(--bg-dark); }

.link-arrow {
  margin-top: auto; align-self: flex-start;
  display: inline-flex; align-items: center; gap: 8px;
  /* --brand as small text is 3.41:1 on white, below AA. --brand-dark is 5.93:1.
     Brand orange is kept for fills and large numerals, which pass. */
  font-weight: 700; line-height: 1.15; color: var(--brand-dark);
}
.link-arrow:hover { color: var(--brand-dark); }
.link-arrow svg { display: block; flex: none; }

/* --- media slots ---------------------------------------------------------- */

.media { background: var(--bg-grey); overflow: hidden; }
.media img { display: block; width: 100%; height: 100%; object-fit: cover; }
.media--4x3 { aspect-ratio: 4 / 3; }
.media--3x2 { aspect-ratio: 3 / 2; }
.media--card { border-bottom: 1px solid var(--line); }
.media--framed { border: 1px solid var(--line); border-radius: var(--radius-card); }

.card {
  background: var(--bg-light);
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  overflow: hidden;
  display: flex; flex-direction: column;
}
.card__body { padding: 24px; display: flex; flex-direction: column; gap: 8px; flex: 1; }

/* --- service page: spec table, FAQ, related ---------------------------------- */
/* W9-08. No new colour: borders are --line, secondary text is --ink-muted, and
   the row heading sits on --bg-light like every other card. */

/* The table scrolls inside its own box. A long specification row must never be
   the reason the page body scrolls sideways. */
.table-wrap { overflow-x: auto; margin-top: 28px; -webkit-overflow-scrolling: touch; }

.spec {
  width: 100%; min-width: 480px;
  border-collapse: collapse;
  background: var(--bg-light);
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  overflow: hidden;
}
.spec th, .spec td { padding: 13px 20px; text-align: left; vertical-align: top; }
.spec tr + tr th, .spec tr + tr td { border-top: 1px solid var(--line); }
.spec th { font-weight: 700; width: 34%; white-space: nowrap; }
.spec td { color: var(--ink-muted); }

.faq { margin-top: 28px; display: flex; flex-direction: column; gap: 18px; }
.faq__item { border-top: 1px solid var(--line); padding-top: 18px; }
.faq__item:first-child { border-top: 0; padding-top: 0; }
.faq__q { margin: 0 0 8px; }
.faq__a { margin: 0; color: var(--ink-muted); max-width: 760px; }

.svc-related { margin-top: 28px; max-width: 760px; }
.svc-updated { margin-top: 16px; font-size: 14px; }

@media (max-width: 768px) {
  .spec th { white-space: normal; width: 40%; }
  .spec th, .spec td { padding: 12px 14px; }
}

/* --- header ---------------------------------------------------------------- */

/* Two layers. The BAND is a full-width solid #FFFFFF strip, fixed, opaque at
   every scroll position, so nothing ever shows through or overlaps. The PILL
   is a #141414 rounded bar sitting inside it. */
.header {
  position: fixed; top: 0; left: 0; right: 0; z-index: 100;
  height: 96px;
  background: var(--bg-light);
  border-bottom: 1px solid var(--line);
  display: flex; align-items: center;
}
.header__inner {
  max-width: var(--container); margin: 0 auto; width: 100%;
  padding: 0 var(--gutter);
}
.header__pill {
  background: var(--bg-dark);
  border-radius: 999px;
  height: 64px;
  padding: 0 12px 0 24px;
  display: flex; align-items: center; justify-content: space-between; gap: 24px;
}
.header__logo { display: flex; align-items: center; flex: none; }
/* W13-03. The mark is sized to the SAME 8px vertical clearance the CTA button
   already has inside the pill: 64 - 48 = 16, 8 top and 8 bottom. That makes the
   figure derived rather than chosen, and it holds at every pill height below.

   48px is the box, not the ink. logo-mono.png carries 76px of transparent
   margin at the top of its 568px canvas and 24px at the bottom, so the ink is
   82.4% of the box: 39.6px here. That is why the mark read small at 32px, where
   only 26.4px of it was ever visible, and it is why the box may match the CTA's
   48px without the mark out-shouting a solid filled button. */
.header__logo img { height: 48px; width: auto; display: block; }

.nav { display: flex; align-items: center; justify-content: center; gap: 28px; flex: 1 1 auto; min-width: 0; }
.nav a { font-size: 17px; line-height: 1; white-space: nowrap; color: var(--bg-light); }
.nav a:hover { color: var(--brand); }
.nav a[aria-current='page'] { color: var(--brand); font-weight: 700; }

.header__actions { display: flex; align-items: center; gap: 16px; flex: none; }
.header__phone {
  display: flex; align-items: center; gap: 8px;
  font-size: 17px; font-weight: 700; line-height: 1; white-space: nowrap;
  color: var(--bg-light);
}
.header__phone:hover { color: var(--brand); }
.header__phone svg { display: block; flex: none; }

.lang {
  display: flex; align-items: center; gap: 6px;
  border: 1px solid rgba(255, 255, 255, 0.4);
  border-radius: 999px; padding: 6px 10px;
}
.lang span, .lang a { font-size: 13px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; line-height: 1; }
.lang a { color: var(--bg-light); }
.lang a:hover { color: var(--brand); }
.lang[data-lang='ro'] .lang__ro,
.lang[data-lang='ru'] .lang__ru { color: var(--brand); pointer-events: none; cursor: default; }
.lang__sep { width: 1px; height: 12px; background: rgba(255, 255, 255, 0.4); }

.icon-btn {
  width: 44px; height: 44px; border-radius: 999px;
  display: none; align-items: center; justify-content: center;
  background: transparent; border: 0; color: var(--bg-light); cursor: pointer;
}
.icon-btn svg { display: block; }
.icon-btn svg[hidden] { display: none; }
.icon-btn--call { color: var(--brand); }
.icon-btn:hover { background: rgba(255, 255, 255, 0.12); }
.header__mobile { display: none; align-items: center; gap: 4px; flex: none; }

.mobile-panel { display: none; }
.mobile-panel[data-open='true'] { display: block; }
.mobile-panel {
  position: fixed; top: 96px; left: 0; right: 0; bottom: 0; z-index: 99;
  background: var(--bg-light); border-top: 1px solid var(--line);
  padding: 16px var(--gutter); overflow-y: auto;
}
.mobile-panel a.mobile-nav-link {
  display: block; font-size: 16px; line-height: 1;
  padding: 14px 0; border-bottom: 1px solid var(--line); white-space: nowrap;
}
.mobile-panel .btn { width: 100%; margin-top: 16px; }
.mobile-panel__foot { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-top: 16px; }
.mobile-panel__foot a { font-size: 16px; font-weight: 700; white-space: nowrap; }
.mobile-panel .lang { border-color: var(--line); }
.mobile-panel .lang a { color: var(--ink-muted); }
.mobile-panel .lang__sep { background: var(--line); }

/* --- promo bar (W12-02) ---------------------------------------------------- */

/* A static offer strip in normal flow, directly beneath the fixed header and
   above the hero. Ruling R-H in DECISIONS.md: CLAUDE.md section 1 forbids
   ANIMATION above the fold, and this does not animate. It is not sticky, has no
   transition, no transform and no keyframes, and it scrolls away with the page.

   Text is --ink on --brand: 5.10:1, which clears WCAG AA for normal text at any
   size. White on --brand is 3.41:1 and fails AA below the large-text threshold,
   which is why the bar is dark-on-orange and not the site's usual white-on-
   orange. Both ratios are measured and recorded in DECISIONS.md.

   Height is a hard cap, not a minimum, and the text is centred inside it and
   clipped rather than allowed to push the box open. That is what makes the
   contribution to CLS exactly zero: the strip occupies 44px from first paint,
   before the webfont resolves and whatever the string turns out to be. */
.promo {
  height: 44px;
  background: var(--brand);
  color: var(--ink);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 var(--gutter);
  overflow: hidden;
}
.promo__text {
  margin: 0;
  font-size: 15px;
  font-weight: 700;
  line-height: 1;
  /* One line, always. It may not wrap into a second and it may not grow the
     bar; on a viewport too narrow for the string it is clipped by the rule
     above, which is a visual loss and never a layout shift. */
  white-space: nowrap;
  text-overflow: ellipsis;
  overflow: hidden;
  max-width: 100%;
}

/* --- hero ----------------------------------------------------------------- */

/* W5-01: the eyebrow sat 96px below the band, which read as a hole. Scoped to
   the hero only; no negative margin, the hero never slides under the header. */
.hero { text-align: center; padding-top: 64px; }
.hero .eyebrow { margin-bottom: 24px; }
.hero h1 { max-width: 900px; margin: 0 auto 24px; text-wrap: pretty; }
.hero__sub { max-width: 640px; margin: 0 auto 40px; }

.stats {
  padding: 32px 0;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  margin-bottom: 40px;
}
.stat__n { font-family: var(--font-heading), var(--font-fallback); font-size: 44px; font-weight: 800; line-height: 1.15; color: var(--brand); }
.stat__label { color: var(--ink-muted); }

.price-box {
  border: 1px solid var(--line);
  border-top: 4px solid var(--brand);
  border-radius: var(--radius-control);
  padding: 24px 28px;
  margin: 0 auto 40px;
  max-width: 560px;
}
.price-box__title { font-size: 22px; font-weight: 700; line-height: 1.15; margin-bottom: 12px; }
.price-box__line { color: var(--ink-muted); }

.cta-row { display: flex; gap: 16px; flex-wrap: wrap; justify-content: center; }

/* --- services ------------------------------------------------------------- */

.service__title { margin-bottom: 0; }
.service__desc { color: var(--ink-muted); margin-bottom: 8px; }

/* --- process -------------------------------------------------------------- */

.step { display: flex; flex-direction: column; gap: 16px; }
.step__n { font-family: var(--font-heading), var(--font-fallback); font-size: 44px; font-weight: 800; line-height: 1.15; color: var(--brand); }
.step__title { margin-bottom: 8px; }
.step__line { color: var(--ink-muted); }

/* Process now sits on #141414. --ink-muted would be 1.5:1 there, so body text
   goes full white and the placeholder frame switches to a white border. */
.section--dark .step__title { color: var(--bg-light); }
.section--dark .step__line { color: var(--bg-light); }
.section--dark .media--framed { border-color: var(--bg-light); }
.section--dark h2 { color: var(--bg-light); }

/* --- portfolio ------------------------------------------------------------ */

.filters { display: flex; flex-wrap: wrap; gap: 8px; margin: 24px 0 40px; }
.filter {
  height: 40px; padding: 0 20px;
  border-radius: var(--radius-control); border: 1px solid var(--line);
  background: transparent; color: var(--ink);
  font-family: inherit; font-size: 17px; font-weight: 400; line-height: 1;
  white-space: nowrap; cursor: pointer;
}
.filter:hover { border-color: var(--brand); color: var(--brand-dark); }
.filter[aria-pressed='true'] { background: var(--bg-light); border-color: var(--brand); color: var(--brand-dark); font-weight: 700; }

.project__media { position: relative; }
.chip {
  position: absolute; top: 12px; left: 12px;
  /* 13px uppercase cannot reach the large-text threshold without wrecking the
     card, so the fill darkens instead: white on --brand-dark is 5.93:1. */
  background: var(--brand-dark); color: var(--bg-light);
  font-size: 13px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em;
  line-height: 1; padding: 7px 10px; border-radius: var(--radius-control);
}
.project[hidden] { display: none; }
.project__link { display: flex; flex-direction: column; height: 100%; color: inherit; }
.project__link:hover { color: inherit; }
.project__link:hover h3 { color: var(--brand-dark); }
.project__desc { color: var(--ink-muted); }

/* W9-04. The homepage portfolio is a teaser grid, the service page is where a
   project is read in full. The real descriptions run eleven to thirteen lines
   in a 366px card, which put the homepage 326px (RO) and 322px (RU) over the
   section 2 budgets. Clamped to four lines HERE ONLY: `#proiecte` on the
   service page is untouched and still prints every sentence.

   The text stays in the DOM, so nothing is hidden from a screen reader or from
   a crawler, and the whole card is already a link to the full entry. */
#portfolio-grid .project__desc,
#proiecte .project__desc {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
/* Four lines on the homepage teaser, six on the service page, where the project
   is the subject rather than a link to it. Both are visual only: the full
   summary stays in the DOM for a screen reader and a crawler, and it is also
   the `description` of that project's ImageObject in the page's JSON-LD. */
#portfolio-grid .project__desc { -webkit-line-clamp: 4; line-clamp: 4; }
#proiecte .project__desc { -webkit-line-clamp: 6; line-clamp: 6; }
/* Two optional project facts too long to sit in the chip row: main materials
   and the challenge. Each renders only when it has real content, so on a
   project with neither, nothing at all is emitted and the card is unchanged. */
.project__fact { font-size: 15px; color: var(--ink-muted); margin-top: 8px; }
.project__fact span { font-weight: 700; color: var(--ink); }
/* W12-01, W12-05. The closing tile of the portfolio grid. Same box as a project
   card and nothing else: the `card` class already supplies the background,
   border, radius and shadow, so this rule adds no colour value and no second
   box style.

   W12-05 made it span all three columns. As a single grid cell it was alone on
   a third row, and a row exists whether or not anything sits beside the tile:
   that cost 193px. Spanning the full width the row is only as tall as one line
   of content, and the same tile costs 101px. It also stops reading as a
   seventh card that failed to load.

   The numeral is the .stat__n treatment at a smaller size (34px / 800 /
   --brand). --brand on white is 3.41:1, which clears the WCAG 3:1 large-text
   threshold at this size and weight, the same justification the hero stats have
   carried since wave 1. */
.card--more {
  grid-column: 1 / -1;
  flex-direction: row;
  align-items: center;
  justify-content: center;
  gap: 16px;
  padding: 18px 24px;
}
.more__n {
  margin: 0;
  font-family: var(--font-heading), var(--font-fallback);
  font-size: 34px; font-weight: 800; line-height: 1.15;
  color: var(--brand);
}
.more__line { margin: 0; color: var(--ink-muted); }

.portfolio__foot { display: flex; justify-content: center; margin-top: 40px; }
.portfolio__empty { color: var(--ink-muted); margin-top: 8px; }

/* --- dark stats band ------------------------------------------------------ */

.band__stats { margin-bottom: 32px; }
.band .stat { text-align: center; }
.band .stat__n { font-size: 64px; }
.band .stat__label { color: var(--bg-light); }
.band__coverage { text-align: center; color: var(--line); }
.band__coverage strong { color: var(--bg-light); font-weight: 700; }

/* --- trust + reviews ------------------------------------------------------ */

.trust-grid { gap: 40px 24px; }
.trust-item { display: flex; flex-direction: column; gap: 12px; }
.trust-item svg { display: block; }
.trust-item__line { color: var(--ink-muted); }

.divider { height: 1px; background: var(--line); border: 0; margin: 64px 0; }

.review {
  background: var(--bg-light);
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  padding: 24px;
  display: flex; flex-direction: column; gap: 16px;
}
.review__quote { flex: 1; }
.review__name { font-weight: 700; }
.review__meta { color: var(--ink-muted); }

/* --- form ----------------------------------------------------------------- */

.form-layout { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); gap: var(--gap); align-items: start; }
.form-card { background: var(--bg-light); border: 1px solid var(--line); border-radius: var(--radius-card); box-shadow: var(--shadow-card); padding: 32px; }
.form-card--stack { display: flex; flex-direction: column; gap: 20px; }
.form-aside { display: flex; flex-direction: column; gap: var(--gap); }

.field { display: flex; flex-direction: column; gap: 8px; }
.field label { font-size: 13px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; color: var(--brand-dark); }
.field input, .field select, .field textarea {
  height: var(--control-h); padding: 0 16px;
  border: 1px solid var(--line); border-radius: var(--radius-control);
  background: var(--bg-light); color: var(--ink);
  font-family: inherit; font-size: 17px; line-height: 1.6;
}
.field textarea { height: auto; padding: 12px 16px; resize: vertical; }
.field__hint { font-size: 13px; color: var(--ink-muted); }
.field__error { font-size: 13px; font-weight: 700; color: var(--brand-dark); }
.field__error[hidden] { display: none; }
.field input[aria-invalid='true'], .field select[aria-invalid='true'] { border-color: var(--brand); }

.consent { display: flex; align-items: flex-start; gap: 12px; }
.consent input { width: 20px; height: 20px; margin: 2px 0 0; accent-color: var(--brand); flex: none; }
.consent label { font-size: 13px; line-height: 1.6; color: var(--ink-muted); }
.consent a { text-decoration: underline; }

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

.form-status { font-weight: 700; }
.form-status[hidden] { display: none; }

.aside__phone {
  display: block; font-family: var(--font-heading), var(--font-fallback);
  font-size: 40px; font-weight: 800; line-height: 1.15; letter-spacing: -0.01em;
  color: var(--brand); margin-bottom: 12px; white-space: nowrap;
}
.aside__phone:hover { color: var(--brand-dark); }

/* --- footer --------------------------------------------------------------- */

.footer { background: var(--bg-dark); color: var(--bg-light); padding-top: var(--section-pad); }
.footer__cta { display: flex; gap: 16px; flex-wrap: wrap; padding-bottom: 40px; border-bottom: 1px solid var(--bg-light); margin-bottom: 40px; }
.footer__cols { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--gap); padding-bottom: var(--section-pad); }
.footer__brand { display: flex; flex-direction: column; gap: 16px; }
/* W13-03. Enlarged by the same 1.5x factor as the header mark, so the two move
   together and the footer keeps its existing relationship to the header. */
.footer__brand img { height: 66px; width: auto; display: block; align-self: flex-start; }
.footer__desc { max-width: 340px; }
.footer__offer { font-weight: 700; color: var(--brand); max-width: 340px; }
.footer__heading { font-size: 13px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; color: var(--brand); margin-bottom: 16px; }
.footer__links { display: flex; flex-direction: column; gap: 10px; }
.footer__links a:hover { color: var(--brand); }
.footer__lists { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--gap); }
.footer__contact { display: flex; flex-direction: column; gap: 12px; }
.footer__contact dt { font-size: 13px; color: var(--line); }
.footer__contact dd { margin: 0; font-weight: 700; }
.footer__bar { border-top: 1px solid var(--bg-light); }
.footer__bar-inner { max-width: var(--container); margin: 0 auto; padding: 20px var(--gutter); display: flex; align-items: center; justify-content: space-between; gap: 24px; flex-wrap: wrap; font-size: 13px; color: var(--line); }
.footer__bar-inner a:hover { color: var(--brand); }
.footer__legal { display: flex; gap: 20px; flex-wrap: wrap; }

/* --- floating contact ----------------------------------------------------- */

.floating { position: fixed; right: 24px; bottom: 24px; z-index: 90; display: flex; flex-direction: column; gap: 12px; }
.floating a {
  width: 56px; height: 56px; border-radius: 28px;
  display: inline-flex; align-items: center; justify-content: center;
  box-shadow: var(--shadow-card);
}
.floating svg { display: block; }
/* Official WhatsApp brand green with the white mark, so it is never mistaken
   for SMS. #25D366 is WhatsApp's own colour and is not part of the site palette;
   it appears on this one control. */
.floating__wa { background: #25D366; border: 1px solid #1EBE5A; color: #FFFFFF; }
.floating__wa:hover { background: #1EBE5A; color: #FFFFFF; }
.floating__call { background: var(--brand); border: 1px solid var(--brand); color: var(--bg-light); }
.floating__call:hover { background: var(--brand-dark); border-color: var(--brand-dark); color: var(--bg-light); }

/* --- long-form pages (privacy) --------------------------------------------- */

.prose { max-width: 760px; }
.prose h1 { margin-bottom: 8px; }
.prose h2 {
  font-size: 22px; font-weight: 800; text-transform: none; letter-spacing: 0;
  margin: 48px 0 12px;
}
.prose p { margin-bottom: 16px; }
.prose__updated { color: var(--ink-muted); font-size: 13px; margin-bottom: 24px; }
.prose__lead { font-size: 19px; }
.prose__todo {
  border-left: 4px solid var(--brand);
  background: var(--bg-grey);
  padding: 12px 16px;
  color: var(--ink-muted);
  font-size: 13px;
  font-weight: 700;
}
.prose ul { margin: 0 0 16px; padding-left: 22px; }
.prose li { margin-bottom: 8px; }
.prose a { text-decoration: underline; }
.prose__dl { margin: 0 0 16px; display: flex; flex-direction: column; gap: 10px; }
.prose__dl > div { display: grid; grid-template-columns: 180px minmax(0, 1fr); gap: 12px; align-items: baseline; }
.prose__dl dt { color: var(--ink-muted); font-size: 13px; }
.prose__dl dd { margin: 0; font-weight: 700; }
.prose__back { margin-top: 48px; }

@media (max-width: 768px) {
  .prose__lead { font-size: 17px; }
  .prose h2 { font-size: 19px; margin-top: 32px; }
  .prose__dl > div { grid-template-columns: minmax(0, 1fr); gap: 2px; }
}

/* ==========================================================================
   PHASE 2 MOTION
   Every effect below is opacity/transform only, never touches scroll, and is
   switched off entirely by the prefers-reduced-motion block at the end.
   ========================================================================== */

/* --- 1. card hover -------------------------------------------------------- */
/* @media (hover: hover) so touch devices never get a stuck hover state. */
@media (hover: hover) {
  .card, .trust-item, .review {
    transition: transform var(--hover-dur) ease-out,
                box-shadow var(--hover-dur) ease-out,
                border-color var(--hover-dur) ease-out,
                background-color var(--hover-dur) ease-out;
  }
  .card:hover, .review:hover {
    transform: translateY(-4px);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
    border-color: var(--brand);
  }
  .trust-item {
    border: 1px solid transparent;
    border-radius: var(--radius-card);
    padding: 16px;
    margin: -16px;
  }
  .trust-item:hover {
    transform: translateY(-4px);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
    border-color: var(--brand);
    background: var(--bg-light);
  }
  /* Shadows do not read on #141414, so the dark sections lift with a wash. */
  .section--dark .step {
    border: 1px solid transparent;
    border-radius: var(--radius-card);
    padding: 16px;
    margin: -16px;
    transition: transform var(--hover-dur) ease-out,
                background-color var(--hover-dur) ease-out,
                border-color var(--hover-dur) ease-out;
  }
  .section--dark .step:hover {
    transform: translateY(-4px);
    background: rgba(255, 255, 255, 0.06);
    border-color: var(--brand);
  }
}

/* --- 2. scroll reveal ------------------------------------------------------ */
/* The hidden state is scoped to .js-motion, which an inline script sets on
   <html>. Without JS nothing is ever hidden. */
.js-motion [data-reveal] {
  opacity: 0;
  transform: translateY(16px);
}
.js-motion [data-reveal].is-revealed {
  opacity: 1;
  transform: none;
  transition: opacity var(--reveal-dur) ease-out, transform var(--reveal-dur) ease-out;
}
/* Stagger, capped at 6 so a nine-card grid completes in 360ms. */
.js-motion [data-reveal].is-revealed { transition-delay: 0ms; }
.js-motion [data-reveal][data-stagger="1"].is-revealed { transition-delay: 60ms; }
.js-motion [data-reveal][data-stagger="2"].is-revealed { transition-delay: 120ms; }
.js-motion [data-reveal][data-stagger="3"].is-revealed { transition-delay: 180ms; }
.js-motion [data-reveal][data-stagger="4"].is-revealed { transition-delay: 240ms; }
.js-motion [data-reveal][data-stagger="5"].is-revealed { transition-delay: 300ms; }
.js-motion [data-reveal][data-stagger="6"].is-revealed { transition-delay: 360ms; }

/* --- 3. sticky header refinement ------------------------------------------ */
/* Past 40px the BAND keeps its 96px height (so nothing below ever moves) and
   only the pill compresses, plus a shadow on the band. */
.header { transition: box-shadow var(--hover-dur) ease-out; }
.header__pill { transition: height var(--hover-dur) ease-out, padding var(--hover-dur) ease-out; }
.header__logo img { transition: height var(--hover-dur) ease-out; }
.header[data-scrolled="true"] { box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08); }
.header[data-scrolled="true"] .header__pill { height: 56px; }
/* 56 - 16 = 40, the same 8px clearance. */
.header[data-scrolled="true"] .header__logo img { height: 40px; }

/* --- 6. supplier marquee --------------------------------------------------- */
.marquee { overflow: hidden; padding: var(--band-pad) 0; background: var(--bg-dark); }
.marquee h2 { color: var(--bg-light); }
/* Reduced opacity, not reduced size: the body keeps its 17px. */
.marquee .lede { color: var(--bg-light); opacity: 0.75; }
.marquee__viewport {
  overflow: hidden;
  /* html sets scroll-behavior: smooth. Inherited here it animates the sideways
     scroll the browser performs to reveal a focused tile, which then races the
     reset in main.js and wins. This box is never an anchor target, so it has no
     use for smooth scrolling. */
  scroll-behavior: auto;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 80px, #000 calc(100% - 80px), transparent);
          mask-image: linear-gradient(90deg, transparent, #000 80px, #000 calc(100% - 80px), transparent);
}
.marquee__track {
  display: flex;
  width: max-content;
  /* NOT `gap`. Flex puts n-1 gaps between n tiles, so the second copy of the
     list starts 12px short of half the track width and the -50% keyframe lands
     12px off its seam, jumping by half a gap every cycle. Measured at 12px with
     8, 12 and 11 brands: it was always gap/2 and had been there since phase 1.
     A trailing margin on every tile gives n gaps, so half the width falls
     exactly on the first duplicate. Fixed W8-04. */
  /* The track travels half its own width per cycle. 11 brands rendered twice is
     22 tiles at 4,928px, so 66s holds ~37px/s, the speed phase 1 ran at with 16
     tiles in 40s. With the trailing-margin fix above the -50% seam is exact at
     any brand count, so adding or dropping a brand cannot reopen the jump. */
  animation: marquee-scroll 66s linear infinite;
}
/* Pause is a pure CSS state change on an animation. It registers no wheel,
   touch or scroll handler, so it cannot delay, capture or hijack scrolling.
   Keyboard focus does exactly what hover does. */
.marquee__viewport:hover .marquee__track,
.marquee__viewport:focus-within .marquee__track { animation-play-state: paused; }
@keyframes marquee-scroll {
  from { transform: translate3d(0, 0, 0); }
  /* The track holds the list twice; -50% lands exactly on the seam. */
  to   { transform: translate3d(-50%, 0, 0); }
}
/* White logo tile. Sized for a wordmark, 2.5:1, not for a text label. The
   height is deliberately unchanged from phase 1: the homepage has very little
   headroom against its budget, and a logo needs width, not height.
   AMENDED under R-R, W12-31: this comment carried a cap and a headroom figure
   that ruling R-J superseded (DECISIONS.md, W12-04). The budgets are per
   locale, derived, and held in R-J. No figure is restated here, per R-Q. */
.supplier {
  flex: none;
  width: 200px; height: 80px;
  margin-right: 24px;          /* the tile gap; see .marquee__track above */
  display: flex; align-items: center; justify-content: center;
  border-radius: var(--radius-card);
  background: var(--bg-light);
  padding: 14px 20px;
}
/* Default: greyscale and dimmed. One full-colour source file per brand and no
   second asset; the grey state is this filter, and hover or keyboard focus
   removes it. Scoped to the logo, never the tile: applied to the tile it also
   dimmed the text fallback below AA. */
.supplier__logo {
  filter: grayscale(100%); opacity: 0.6;
  transition: filter var(--hover-dur) ease-out, opacity var(--hover-dur) ease-out;
}
/* No CLS without an explicit box: the tile is a fixed 200x80 and the logo is
   clamped inside it, whatever the file's own dimensions turn out to be. */
.supplier__logo { max-width: 160px; max-height: 52px; width: auto; height: auto; }
/* Guarded: on a touch device :hover sticks after a tap. Focus is not guarded,
   it is exactly the keyboard equivalent and must always work. */
@media (hover: hover) {
  .supplier:hover .supplier__logo { filter: grayscale(0%); opacity: 1; }
}
.supplier:focus-visible .supplier__logo { filter: grayscale(0%); opacity: 1; }
.supplier:focus-visible { outline: 2px solid var(--brand); outline-offset: 3px; }
/* Text fallback until a logo file lands. Full-strength --ink on #FFFFFF,
   17.40:1. It is not dimmed with the logo: contrast is worth more than the
   visual consistency of a placeholder. */
.supplier__label {
  font-size: 15px; font-weight: 700; line-height: 1.2;
  color: var(--ink); text-align: center;
  word-break: break-word;
}

/* --- 6b. footer social links ------------------------------------------------ */
/* Monochrome, drawn in currentColor. Brand colours are deliberately not used:
   Instagram, Facebook and TikTok would add at least three values to a palette
   that is fixed at ten, and the footer's own language is white on #141414.
   Hover and focus move to --brand, which is already in the set. */
/* It lives in the footer bar, not in a column: the bar already runs 62px tall
   with 700px of unused width, so the row costs the page ZERO height. In the
   contact column it cost 70px, which the homepage had no room for.
   AMENDED under R-R, W12-31: the cap and the headroom figure this comment
   carried were superseded by ruling R-J (DECISIONS.md, W12-04). R-J makes the
   decision recorded here STRONGER, not weaker: the real headroom was a
   fraction of the figure written at the time, so the 70px row would have blown
   the budget outright rather than eaten part of it. Budgets are held in R-J
   and no figure is restated here, per R-Q. */
.footer__social { display: flex; gap: 4px; align-items: center; }
.footer__social a {
  /* 44x44 clears the WCAG 2.5.8 target minimum with room to spare. The bar's
     line box is ~22px inside 20px of padding, so a negative block margin lets
     the target overlap that padding rather than grow the bar: the hit area
     stays 44px and the bar height does not move. */
  width: 44px; height: 44px;
  margin: -11px 0;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--bg-light);
  border-radius: var(--radius-control);
  transition: color var(--hover-dur) ease-out, background-color var(--hover-dur) ease-out;
}
.footer__social a:hover { color: var(--brand); background: rgba(255, 255, 255, 0.06); }
.footer__social a:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.footer__social svg { display: block; }

/* --- 7. hero two-panel block ---------------------------------------------- */
.hero-panels {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--gap);
  align-items: stretch;
  margin-top: 32px;
  text-align: left;
}
.hero-claim {
  background: var(--bg-dark);
  color: var(--bg-light);
  border-radius: var(--radius-card);
  padding: 32px;
  display: flex; flex-direction: column;
}
.hero-claim h2 {
  font-size: 28px; color: var(--bg-light);
  text-transform: none; letter-spacing: 0; margin-bottom: 16px;
}
.hero-claim__line { color: var(--bg-light); margin-bottom: 8px; }

/* CTA sits inside the card, left aligned, in the space above the divider. */
.hero-claim__cta { align-self: flex-start; margin-top: 20px; }

.hero-claim__divider { height: 1px; background: rgba(255, 255, 255, 0.25); margin: 24px 0 16px; border: 0; margin-top: auto; }

/* Three separate rows, each with its own middot marker. */
.hero-claim__highlights { list-style: none; margin: 0; padding: 0; }
.hero-claim__highlights li {
  color: var(--brand); font-weight: 700; font-size: 16px; line-height: 1.5;
  padding-left: 16px; position: relative;
  /* one line each: never wrap into six rows */
  text-wrap: pretty;
}
.hero-claim__highlights li::before {
  content: '·'; position: absolute; left: 0; top: 0;
}
.hero-claim__highlights li + li { margin-top: 4px; }
.hero-panel-media { border-radius: var(--radius-card); border: 1px solid var(--line); overflow: hidden; }
/* contain, not cover. The illustration is 4:3 and the box is 4:3, so the two
   render identically today, but contain guarantees a future asset at a
   different ratio is letterboxed rather than silently cropped. */
.hero-panel-media img { object-fit: contain; }
/* W6-03: with a real photograph the box should be filled, not letterboxed.
   process-photos crops to exactly 4:3, so contain and cover agree, but the
   intent differs and cover is right for a photo. */
.hero-panel-media--photo img { object-fit: cover; }

/* --- 8. service illustration box ------------------------------------------ */
/* Fixed 4:3 box, illustration centred and contained. The <img> always resolves
   because placeholder SVGs ship until the real ones land. */
.media--illustration {
  aspect-ratio: 4 / 3;
  background: var(--bg-grey);
  border-bottom: 1px solid var(--line);
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
}
.media--illustration img {
  width: 100%; height: 100%;
  object-fit: contain;
  display: block;
}

/* --- 5. lead capture modal -------------------------------------------------- */
.modal[hidden] { display: none; }
.modal {
  position: fixed; inset: 0; z-index: 200;
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
  /* The single permitted translucency on the site: an overlay, not a section. */
  background: rgba(0, 0, 0, 0.6);
}
.modal__panel {
  background: var(--bg-light);
  border-radius: var(--radius-card);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
  padding: 32px;
  width: 100%; max-width: 440px;
  position: relative;
}
.modal__close {
  position: absolute; top: 8px; right: 8px;
  width: 44px; height: 44px;
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent; border: 0; color: var(--ink-muted); cursor: pointer;
  border-radius: var(--radius-control);
}
.modal__close:hover { background: var(--bg-grey); color: var(--ink); }
.modal h2 { font-size: 26px; margin-bottom: 12px; padding-right: 40px; }
.modal__sub { color: var(--ink-muted); margin-bottom: 20px; }
.modal .field { margin-bottom: 16px; }
/* The one gradient permitted on the site, on this button only. */
.modal__submit {
  width: 100%;
  background: linear-gradient(135deg, #F65308 0%, #B23C08 100%);
  color: var(--bg-light);
  border: 0;
}
.modal__submit:hover { background: linear-gradient(135deg, #B23C08 0%, #B23C08 100%); color: var(--bg-light); }
.modal__fine { font-size: 13px; color: var(--ink-muted); margin-top: 16px; }
.modal__fine a { text-decoration: underline; }
.modal__status { font-weight: 700; margin-top: 12px; }
.modal__status[hidden] { display: none; }

/* W12-21. The privacy page numbers its own sections.

   The ordinals used to be typed into the heading strings, which meant inserting
   a section at the top renumbered every heading below it: adding the operator
   identity, when the registry extract lands, would have been a rewrite of five
   strings in two locale files rather than an addition. A counter makes the new
   section purely additive. No new colour, no new box. */
.prose { counter-reset: prose-section; }
.prose h2 { counter-increment: prose-section; }
.prose h2::before { content: counter(prose-section) ". "; }

/* --- reviews: aggregate panel + cards ------------------------------------- */
.reviews-layout {
  display: grid;
  grid-template-columns: minmax(0, 320px) minmax(0, 1fr);
  gap: 40px var(--gap);
  align-items: start;
}
.rating {
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  padding: 32px;
  text-align: center;
}
.rating__score {
  font-family: var(--font-heading), var(--font-fallback);
  font-size: 64px; font-weight: 800; line-height: 1.15; color: var(--brand);
}
.rating__outof { color: var(--ink-muted); margin-bottom: 12px; }
.rating__count { font-weight: 700; margin-top: 12px; }

/* Five outline stars with a filled copy clipped to the real percentage.
   No gradient: the overlay is width-clipped. */
.stars { position: relative; display: inline-block; line-height: 0; }
.stars__base, .stars__fill { display: flex; gap: 4px; }
.stars__fill {
  position: absolute; inset: 0;
  overflow: hidden; white-space: nowrap;
}
.stars svg { display: block; flex: none; }

.rating__google[hidden] { display: none; }
.rating__google { margin-top: 16px; }

.review__head { display: flex; flex-direction: column; gap: 4px; margin-bottom: 4px; }
.review__name { font-weight: 700; }
.review__tags { display: flex; flex-wrap: wrap; gap: 6px; }
.review__tag {
  font-size: 13px; color: var(--ink-muted);
  border: 1px solid var(--line); border-radius: 999px; padding: 3px 10px;
}
.review__quote { flex: 1; }

@media (max-width: 1024px) {
  .reviews-layout { grid-template-columns: minmax(0, 1fr); }
}

/* --- service pages --------------------------------------------------------- */
.breadcrumb {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  font-size: 13px; color: var(--ink-muted); margin-bottom: 24px;
}
.breadcrumb a { text-decoration: underline; }
.breadcrumb a:hover { color: var(--brand-dark); }
.breadcrumb [aria-current='page'] { color: var(--ink); font-weight: 700; }

.svc-hero__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 420px);
  gap: 40px var(--gap);
  align-items: center;
}
.svc-hero__art {
  border-radius: var(--radius-card);
  overflow: hidden;
  background: var(--bg-dark);
}
.svc-hero__art img { width: 100%; height: 100%; object-fit: contain; display: block; }
/* An illustration is contained on the dark field; a photograph fills it. */
.svc-hero__art--photo img { object-fit: cover; }

/* The dark price strip is a band, not a full section. */
.section--compact { padding: var(--band-pad) 0; }

@media (max-width: 1024px) {
  .svc-hero__grid { grid-template-columns: minmax(0, 1fr); }
}

/* ==========================================================================
   Tablet — 1024px and below: 3-col grids become 2-col, 5-col process becomes 3
   ========================================================================== */

@media (max-width: 1024px) {
  :root { --section-pad: 72px; }
  .grid--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .grid--5 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  h1 { font-size: 44px; }
  .nav { gap: 20px; }
  .nav a { font-size: 16px; }
  .header__actions { gap: 12px; }
  .header__phone span { display: none; }
  .form-layout { grid-template-columns: minmax(0, 1fr); }
  .hero-panels { grid-template-columns: minmax(0, 1fr); }
  .footer__cols { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .footer__brand { grid-column: 1 / -1; }
}

/* ==========================================================================
   Mobile — 768px and below: single column throughout
   ========================================================================== */

@media (max-width: 768px) {
  :root {
    --gutter: 16px;
    --section-pad: 56px;
    --gap: 16px;
  }

  body { font-size: 16px; padding-top: 80px; }
  h1 { font-size: 32px; letter-spacing: -0.01em; }
  h2 { font-size: 26px; letter-spacing: 0; }
  h3 { font-size: 19px; }

  .nav, .header__actions { display: none; }
  .header__mobile { display: flex; }
  .icon-btn { display: inline-flex; }
  .header { height: 80px; }
  .header__pill { padding: 0 8px 0 16px; height: 56px; }
  .header[data-scrolled="true"] .header__pill { height: 52px; }
  /* Mobile had no rule of its own and inherited the desktop 32px into a 56px
     pill. Same 8px clearance as everywhere else: 56 - 16 and 52 - 16. */
  .header__logo img { height: 40px; }
  .header[data-scrolled="true"] .header__logo img { height: 36px; }
  .mobile-panel { top: 80px; }

  /* Hard cap, 36px. The type shrinks to fit the line rather than the bar
     growing or the text moving: 13px clipped the Russian string at 360px and
     both strings at 320px, and the card's instruction there is to reduce the
     font size, never to introduce motion. The floor of the clamp, 11px, is the
     size at which the longer string (Russian, 331px at 13px) fits the 288px
     available inside a 320px viewport. Measured widths are in DECISIONS.md.

     A viewport-relative size is still a static size: it is fixed for a given
     viewport and never animates, and the bar's height is capped independently
     of it, so nothing here can shift layout. */
  .promo { height: 36px; }
  .promo__text { font-size: clamp(11px, 3.4vw, 13px); }

  /* The grid is one column here, so the tile is full width already and the
     numeral and sentence would be cramped side by side. Stack them. */
  .card--more { flex-direction: column; text-align: center; gap: 4px; }

  .grid--3, .grid--5 { grid-template-columns: minmax(0, 1fr); }
  .grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  /* W5-03: desktop keeps the tightened 64px; mobile returns to the section
     rhythm of 56px, which was already inside the intended range. */
  .hero { padding-top: 56px; }
  .hero .eyebrow { margin-bottom: 16px; }
  .hero { text-align: left; }
  .hero h1 { margin: 0 0 16px; }
  .hero__sub { margin: 0 0 24px; }
  .stats { padding: 24px 0; margin-bottom: 24px; }
  .stat__n { font-size: 32px; }
  .price-box { padding: 16px 20px; margin-bottom: 24px; }
  .price-box__title { font-size: 19px; }
  .cta-row { flex-direction: column; }
  .cta-row .btn { width: 100%; }

  /* Single column: without a cap, a 4:3 slot at a 736px container is 552px
     tall and the services section balloons. No effect at the 390px reference
     width, where a 4:3 slot is already only 268px. */
  .media--4x3, .media--3x2 { max-height: 300px; }

  .hero-claim { padding: 24px; }
  .hero-claim h2 { font-size: 22px; }
  .hero-claim__cta { width: 100%; align-self: stretch; }
  .hero-claim__highlights li { font-size: 15px; }
  .modal__panel { padding: 24px; }
  .modal h2 { font-size: 22px; }
  .media--illustration { padding: 16px; }

  .card__body { padding: 16px; }
  .step__n { font-size: 32px; }
  .filters { margin: 16px 0 24px; }
  .filter { height: 44px; padding: 0 16px; font-size: 16px; }
  .portfolio__foot .btn { width: 100%; }

  .band .stat__n { font-size: 44px; }
  .trust-grid { gap: 32px 16px; }
  .divider { margin: 40px 0; }

  .form-card { padding: 16px; }
  .field input, .field select, .field textarea { font-size: 16px; }
  .aside__phone { font-size: 26px; }

  .footer__cta { flex-direction: column; }
  .footer__cta .btn { width: 100%; }
  .footer__cols { grid-template-columns: minmax(0, 1fr); gap: 32px; }
  .footer__lists { grid-template-columns: minmax(0, 1fr); gap: 32px; }
  .footer__bar-inner { flex-direction: column; gap: 8px; }

  .floating { right: 16px; bottom: 16px; }
}


/* ==========================================================================
   prefers-reduced-motion: every phase 2 effect OFF, not softened.
   Elements render in their final state.
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    transition-delay: 0ms !important;
    scroll-behavior: auto !important;
  }
  /* Reveals: final state immediately, regardless of observer. */
  .js-motion [data-reveal],
  .js-motion [data-reveal].is-revealed {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
  /* Hover: no travel. Colour feedback stays, it is not motion. */
  .card:hover, .review:hover, .trust-item:hover,
  .section--dark .step:hover { transform: none !important; }
  /* Marquee: stopped dead, static row. Nothing to pause, so hover and focus
     have nothing to do and cannot error; they only ever set a play state. */
  .marquee__track { animation: none !important; transform: none !important; }
  .marquee__viewport { overflow-x: auto; }
  /* Every logo full colour: the grey default is a motion-adjacent effect and
     there is no hover reveal left to restore it. */
  .supplier__logo { filter: none !important; opacity: 1 !important; transition: none !important; }
  /* The second copy exists only to make the loop seamless. With no loop it is
     twelve repeated tiles a reader has to scroll past. */
  .supplier[aria-hidden="true"] { display: none; }
  /* Header: no compression animation. */
  .header, .header__logo img { transition: none !important; }
  /* Modal: no entrance. */
  .modal, .modal__panel { transition: none !important; animation: none !important; }
}
