/* Vidamarina v9 — design system and page styles. Tokens and rules are documented in DESIGN.md. */

/* Display: Unbounded (SIL OFL 1.1), the user's choice: v3–v8 and again from v10 (Tektur in v9 was rejected).
   Text: Host Grotesk (SIL OFL 1.1).
   Neither family has a Reserved Font Name, so the subsets keep their names. The ?v= matches the preload links. */
@font-face {
  font-family: "Unbounded";
  src: url("assets/fonts/unbounded.woff?v=27") format("woff");
  font-weight: 500 800;
  font-display: swap;
}

@font-face {
  font-family: "Host Grotesk";
  src: url("assets/fonts/host-grotesk.woff?v=27") format("woff");
  font-weight: 380 720;
  font-display: swap;
}

:root {
  /* Uniform navy: night yard, dark sections, footer */
  --navy-950: #0b1424;
  --navy-900: #111e35;
  --navy-800: #1c2c4a;
  --navy-700: #2c3f63;
  /* Reading ground and surfaces */
  --steel-50: #f1f3f6;
  --steel-100: #e6eaf0;
  --steel-200: #d3d9e2;
  /* Boundary of form controls: at least 3:1 against the white panel and the field fill */
  --steel-500: #7d889a;
  --white: #ffffff;
  /* Text */
  --ink: #0e1726;
  --ink-2: #45536a;
  --on-dark: #ffffff;
  --on-dark-2: #b3bfd1;
  /* Hi-vis yoke: the only action colour */
  --yellow: #f5c400;
  --yellow-2: #ffd43b;
  /* Logo blue #0865FF: the company's own colour (DESIGN.md, "Version 7").
     brand = fills, outlines, icons; ink = blue text on light (>= 5:1 on steel-100);
     on-dark = blue text and icons on navy (>= 6.4:1); deep = fills behind white text (8.9:1). */
  --brand: #0865ff;
  --brand-ink: #0758e0;
  --brand-on-dark: #6aa1ff;
  --brand-deep: #0b3fb0;
  --blue: var(--brand);

  --font-display: "Unbounded", "Host Grotesk", "Segoe UI", system-ui, sans-serif;
  --font-text: "Host Grotesk", "Segoe UI", system-ui, -apple-system, sans-serif;

  --radius-photo: 12px;
  --radius-panel: 16px;
  --radius-control: 6px;

  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --dur-fast: 160ms;
  --dur-base: 280ms;

  --wrap: 1320px;
  --gutter: clamp(16px, 4vw, 56px);
  --header-h: 72px;   /* v15: 80 → 72 (user 2026-10-05: «высоту меню плашки немного меньше») */
  --yoke-h: 96px;
  --section-y: clamp(88px, 11vw, 160px);
  --edge: max(var(--gutter), calc((100vw - var(--wrap)) / 2));

  --shadow-lift: 0 1px 2px rgb(17 30 53 / 0.06), 0 22px 44px -22px rgb(17 30 53 / 0.4);
  --focus: var(--blue);
  color-scheme: light;
}

@media (max-width: 859px) {
  :root { --header-h: 64px; }
}

/* ---------- Base ---------- */

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

html {
  -webkit-tap-highlight-color: transparent;   /* shared rule 2026-10-05: no system flash on tap; presses have their own :active */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-padding-top: calc(var(--header-h) + 20px);
  scrollbar-color: var(--navy-700) var(--steel-100);
}

/* Smooth in-page jumps only once the page has loaded, so arriving at a #section lands instantly. */
html.motion-on.is-loaded { scroll-behavior: smooth; }

/* The stable gutter keeps the layout from shifting. */
html { scrollbar-gutter: stable; }

body {
  margin: 0;
  background: var(--steel-50);
  color: var(--ink);
  font-family: var(--font-text);
  font-size: 1.0625rem;
  font-weight: 420;
  line-height: 1.6;
  font-kerning: normal;
}

::selection { background: var(--brand); color: var(--white); }

img { display: block; max-width: 100%; height: auto; }

a { color: inherit; text-underline-offset: 0.22em; text-decoration-thickness: 1px; }

h1, h2, h3 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 650;
  line-height: 1.1;
  letter-spacing: -0.02em;
  text-wrap: balance;
}

p { margin: 0; text-wrap: pretty; }

button { font: inherit; }

:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 3px;
  border-radius: 4px;
}

.on-dark { --focus: var(--brand-on-dark); --glint: var(--brand-on-dark); --glint-core: var(--brand); }

[hidden] { display: none !important; }

.wrap {
  width: 100%;
  max-width: calc(var(--wrap) + 2 * var(--gutter));
  margin-inline: auto;
  padding-inline: var(--gutter);
}

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

.icon {
  width: 1.25em;
  height: 1.25em;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.75;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.skip {
  position: fixed;
  top: 12px;
  left: 12px;
  z-index: 100;
  padding: 12px 18px;
  border-radius: var(--radius-control);
  background: var(--navy-950);
  color: var(--on-dark);
  font-weight: 600;
  text-decoration: none;
  transform: translateY(-160%);
}

.skip:focus-visible { transform: none; outline-color: var(--brand-on-dark); }

/* ---------- Buttons ---------- */

.btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.6em;
  min-height: 54px;
  padding: 12px 26px;
  border: 0;
  border-radius: var(--radius-control);
  font: 620 1rem/1.2 var(--font-text);
  text-decoration: none;
  cursor: pointer;
  overflow: hidden;
  isolation: isolate;
  transition: background-color var(--dur-fast) ease, color var(--dur-fast) ease, box-shadow var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out);
}

.btn .icon { transition: transform var(--dur-base) var(--ease-out); }

.btn-primary { background: var(--yellow); color: var(--navy-950); }

/* Retroreflective sheen: the light catching hi-vis tape, once per hover. */
.btn-primary::after {
  content: "";
  position: absolute;
  inset: -2px auto -2px 0;
  z-index: -1;
  width: 45%;
  background: linear-gradient(100deg, transparent 0%, rgb(255 255 255 / 0.62) 50%, transparent 100%);
  transform: translateX(-130%) skewX(-16deg);
  pointer-events: none;
}

.btn-ghost { background: transparent; color: var(--on-dark); box-shadow: inset 0 0 0 1.5px rgb(255 255 255 / 0.45); }

.btn-quiet { min-height: 46px; padding: 10px 18px; background: var(--steel-50); color: var(--ink); box-shadow: inset 0 0 0 1px var(--steel-500); }

@media (hover: hover) and (pointer: fine) {
  .btn-primary:hover { background: var(--yellow-2); box-shadow: 0 16px 32px -16px rgb(245 196 0 / 0.8); }
  .btn-ghost:hover { background: rgb(255 255 255 / 0.08); box-shadow: inset 0 0 0 1.5px var(--on-dark); }
  .btn-quiet:hover { background: var(--white); box-shadow: inset 0 0 0 1.5px var(--navy-700); }
  .motion-on .btn:hover { transform: translateY(-2px); }
  .motion-on .btn-primary:hover::after { transform: translateX(300%) skewX(-16deg); transition: transform 760ms var(--ease-out); }
  .motion-on .btn-primary:hover .icon { transform: translateX(4px); }
}

.btn:active { transform: translateY(1px); }

/* ---------- Header ---------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--white);
}

/* never a 1 px line (rule 22.10); once the bar sticks a soft 18 px shade falls on the page under it (rule 28.10).
   z-index -1 keeps it under the open menu sheet */
.site-header::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 100%;
  z-index: -1;
  height: 18px;
  background: linear-gradient(rgb(17 30 53 / 0.12), rgb(17 30 53 / 0));
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-base) ease;
}
.site-header.is-scrolled::after { opacity: 1; }

/* v11: the row is centred (user 2026-10-04: "menu, languages, phone up, the logo down"). With the stacked logo, a shared
   baseline with its wordmark pushed every control to the bottom edge. The menu, the pill's number and LT/EN still
   stand on one line: 40 px plates and 44 px links with the same 15 px type and 22–24 px lines, centred together. */
.header-row {
  display: flex;
  align-items: center;
  gap: clamp(16px, 3vw, 40px);
  height: var(--header-h);
}

.brand { display: block; flex: none; border-radius: 4px; }
/* v15: 160 → 140 px, wordmark caps 13 px (user 2026-10-05: «лого немного меньше»); 118 px and 11 px caps on phones */
.brand img { width: 140px; height: auto; transform-origin: left center; transition: transform var(--dur-base) var(--ease-out), scale var(--dur-base) var(--ease-out); }
/* the stuck bar carries a smaller logo (rule 28.10: «при стике меню должен уменьшаться»): 50 → 43 px */
.is-scrolled .brand img { scale: 0.86; }

.nav { margin-left: auto; }

.nav-list { display: flex; gap: 20px; margin: 0; padding: 0; list-style: none; }

.nav-list a {
  position: relative;
  display: block;
  padding: 11px 6px;
  border-radius: var(--radius-control);
  color: var(--ink);
  font-size: 0.9375rem;
  line-height: 22px;   /* the plates' line: menu, pill number and LT/EN letters stand on one line */
  font-weight: 600;
  text-decoration: none;
  transition: background-color var(--dur-fast) ease;
}

.nav-list a::after {
  content: "";
  position: absolute;
  left: 6px;
  right: 6px;
  bottom: 4px;
  height: 3px;
  border-radius: 2px;
  background: var(--brand);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur-base) var(--ease-out);
}

.nav-list a[aria-current="true"]::after { transform: scaleX(1); }

.nav-toggle {
  display: none;
  align-items: baseline;
  justify-content: center;
  width: 40px;
  padding: 9px 0;
  font: inherit;
  font-size: 0.9375rem;
  line-height: 22px;
  border: 0;
  border-radius: var(--radius-control);
  background: var(--steel-50);
  color: var(--ink);
  cursor: pointer;
}

.nav-toggle::before { content: "\200b"; }
.nav-toggle .icon { align-self: center; width: 22px; height: 22px; }
/* the two lines come together into a cross while the menu is open, and part again when it closes */
.nav-toggle .icon-menu path { transform-box: fill-box; transform-origin: center; transition: transform 500ms var(--ease-in-out); }
.nav-toggle[aria-expanded="true"] .icon-menu path:first-child { transform: translateY(4px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .icon-menu path:last-child { transform: translateY(-4px) rotate(-45deg); }

/* The main phone, always one tap away (user rule: one main number as a large call element). */
.header-phone {
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  padding: 9px 16px 9px 13px;
  border-radius: 999px;
  background: var(--brand);
  color: var(--white);
  font-size: 0.9375rem;
  font-weight: 650;
  line-height: 22px;
  white-space: nowrap;
  text-decoration: none;
  transition: background-color var(--dur-fast) ease;
}
.header-phone .icon { align-self: center; width: 18px; height: 18px; }
@media (hover: hover) and (pointer: fine) { .header-phone:hover { background: var(--brand-deep); } }
@media (max-width: 1199px) {
  .header-phone { width: 40px; padding: 9px 0; gap: 0; justify-content: center; }
  .header-phone::before { content: "\200b"; }
  .header-phone span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
}

/* contact button (rule 28.10: «должен быть телефон, кнопка контактов»): the phone pill's outline twin; on hover the
   brand blue runs into it from the left like a weld pass; only where the bar has room for the full row */
.header-cta {
  position: relative;
  display: none;
  padding: 7px 18px;
  border: 2px solid var(--brand);
  border-radius: 999px;
  color: var(--brand);
  font-size: 0.9375rem;
  font-weight: 650;
  line-height: 22px;
  white-space: nowrap;
  text-decoration: none;
  overflow: hidden;
  transition: color var(--dur-fast) ease;
}
.header-cta::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--brand);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur-base) var(--ease-out);
}
.header-cta { isolation: isolate; }
@media (hover: hover) and (pointer: fine) {
  .header-cta:hover { color: var(--white); }
  .header-cta:hover::before { transform: scaleX(1); }
}
@media (min-width: 1200px) { .header-cta { display: inline-block; } }

.nav-extra { display: none; }
.lang { display: flex; gap: 6px; padding: 3px; border-radius: 8px; background: var(--steel-50); }

.lang a {
  display: grid;
  place-items: center;
  min-width: 40px;
  height: 34px;
  padding: 0 8px;
  border-radius: 5px;
  color: var(--ink-2);
  font-size: 0.9375rem;   /* the pill's type: the plates line up exactly */
  line-height: 22px;
  font-weight: 650;
  text-decoration: none;
  transition: background-color var(--dur-fast) ease, color var(--dur-fast) ease;
}

.lang a[aria-current="page"] { background: var(--white); color: var(--ink); box-shadow: 0 1px 2px rgb(17 30 53 / 0.14); }

@media (hover: hover) and (pointer: fine) {
  .motion-on .brand:hover img { transform: translateX(3px); }
  .nav-list a:hover { background: var(--steel-50); }
  .nav-list a:hover::after { transform: scaleX(0.45); }
  .nav-list a[aria-current="true"]:hover::after { transform: scaleX(1); }
  .lang a:not([aria-current]):hover { color: var(--ink); background: var(--white); }
  .nav-toggle:hover { background: var(--steel-100); }
}

/* Reading progress: a weld run along the lower edge of the header. */
.progress { position: absolute; left: 0; right: 0; bottom: -3px; height: 3px; pointer-events: none; }
.progress span { display: block; height: 100%; background: var(--brand); transform: scaleX(var(--progress, 0)); transform-origin: left; }

/* v24 «Шапка без каши»: up to 600 px only the logo (left) and the menu button (right, 16 px from the edge) stay in the
   header; the call button and LT/EN are the last rows of the open menu */
@media (max-width: 600px) {
  /* v27 (rule 28.10: «на телефоне тоже языки и телефон в шапке»): logo, LT|EN, call icon and the menu button stay in the bar; the open sheet repeats them large */
  /* one left column (shared rule «открытое меню без каши»): items, then LT/EN, then the call button; 24 px between groups */
  .js .nav-list .nav-extra, .no-js .nav-list .nav-extra { display: grid; justify-items: start; gap: 24px; padding: 18px 0 8px 4px; }
  .nav-extra .nav-call { justify-self: stretch; }
  .nav-extra .lang, .nav-extra .nav-call { order: 0; }
  .nav-extra .lang { width: max-content; }
  .nav-call {
    display: flex; align-items: center; justify-content: center; gap: 12px; min-height: 56px; padding: 0 20px;
    border-radius: 999px; background: var(--brand); color: var(--white); font-size: 1.1875rem; font-weight: 650;
    line-height: 1.2; white-space: nowrap; text-decoration: none; transition: background-color var(--dur-fast) ease;
  }
  .nav-call .icon { width: 22px; height: 22px; }
  .nav-call:active { background: var(--brand-deep); }
  .js .nav-list a.nav-call, .no-js .nav-list a.nav-call { display: flex; align-items: center; justify-content: center; gap: 12px; min-height: 56px; padding: 0 20px; border-radius: 999px; background: var(--brand); color: var(--white); font-size: 1.1875rem; line-height: 1.2; }
  .js .nav-list a.nav-call:active { background: var(--brand-deep); }
  .js .nav-list a.nav-call::after { display: none; }
  .js .nav-list .lang a { padding: 0 8px; border-radius: 5px; font-size: 0.9375rem; }
  .js .nav-list .lang a::after, .no-js .nav-list .lang a::after { display: none; }
}

@media (max-width: 859px) {
  .brand img { width: 118px; }
  .header-row { gap: 10px; }
  /* v17 (user 2026-10-05: «Иконка меню всегда справа!!»): the menu button is the last thing in the row, flush with its
     right edge, the call button right beside it, LT/EN before them. The logo alone pushes the group right. */
  .brand { margin-right: auto; }
  .nav { margin-left: 0; }
  .lang { order: 1; }
  .header-phone { order: 2; }
  .nav-toggle { display: inline-flex; order: 3; }
  .js .nav-list {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    display: none;
    flex-direction: column;
    gap: 0;
    padding: 8px var(--gutter) 20px;
    background: var(--white);
    box-shadow: 0 18px 30px -22px rgb(17 30 53 / 0.5);
  }
  .js .nav-list.is-open { display: flex; }
  .js .nav-list a { padding: 14px 4px; font-size: 1.0625rem; border-radius: 0; }
  .js .nav-list a::after { left: 4px; right: auto; width: 32px; bottom: 6px; }
  .no-js .nav { order: 4; flex-basis: 100%; }
  .no-js .header-row { flex-wrap: wrap; height: auto; padding-block: 10px; }
  .no-js .nav-toggle { display: none; }
  .no-js .nav-list { flex-wrap: wrap; }
}

/* ---------- Hero ----------
   v8: the night yard fills the first screen edge to edge and the copy stands on its navy side. On load the
   photo settles from a closer view: the site's scale grammar (DESIGN.md, "Version 8"). */

.hero { background: var(--navy-950); color: var(--on-dark); }

.hero-stage {
  --copy-w: clamp(430px, 46vw, 760px);
  --copy-end: calc(var(--edge) + var(--copy-w));
  position: relative;
  display: grid;
  align-items: center;
  min-height: clamp(560px, calc(100svh - var(--header-h) - var(--yoke-h)), 920px);
  isolation: isolate;
}

.hero-photo { position: absolute; inset: 0; z-index: -1; margin: 0; overflow: hidden; background: var(--navy-900); }

/* Navy only behind the copy: the top, the bottom and the far edge of the photo stay clean. */
.hero-photo::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, rgb(11 20 36 / 0.94) 0, rgb(11 20 36 / 0.86) calc(var(--copy-end) - 16%), rgb(11 20 36 / 0.6) var(--copy-end), rgb(11 20 36 / 0.14) calc(var(--copy-end) + 20%), rgb(11 20 36 / 0) calc(var(--copy-end) + 36%));
  pointer-events: none;
}

.hero-media { position: absolute; inset: 0; display: block; }
.hero-media picture, .hero-media img { width: 100%; height: 100%; }
.hero-media img { object-fit: cover; object-position: 60% 50%; }

.motion-on .hero-media { inset: -10% 0; transform: translate3d(var(--tx, 0px), var(--py, 0px), 0) scale(1.05); will-change: transform; }

.hero-copy { position: relative; padding-block: clamp(56px, 6vw, 112px); }

.hero h1 {
  /* The widest line (measured at build time as --h1-em) fills the copy column. */
  font-size: min(5.75rem, calc(var(--copy-w) / var(--h1-em)));
  font-weight: 700;
  line-height: 1.12;   /* Unbounded: ų and p under one line never touch i and l on the next (layout gate, v10) */
  letter-spacing: -0.02em;
}

.hero h1 .line { display: block; white-space: nowrap; }
.hero h1 .line > span { display: inline-block; }

.hero-lead {
  max-width: min(32em, var(--copy-w));
  margin-top: clamp(22px, 2.4vw, 34px);
  color: #c4cedd;
  font-size: clamp(1.0625rem, 0.95rem + 0.4vw, 1.3125rem);
  line-height: 1.55;
}

.hero-actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: clamp(28px, 3vw, 44px); }

.hero-tag {
  position: absolute;
  right: var(--edge);
  bottom: clamp(18px, 2.4vw, 32px);
  z-index: 1;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  max-width: calc(100% - 32px);
  padding: 8px 14px 8px 11px;
  border-radius: 999px;
  background: rgb(11 20 36 / 0.74);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  color: var(--on-dark);
  font-size: 0.875rem;
  font-weight: 600;
  line-height: 1.3;
}

.hero-tag .icon { width: 17px; height: 17px; color: var(--brand-on-dark); }

/* The yoke: the uniform's hi-vis band, carrying the two workplaces. */
.yoke { position: relative; background: var(--yellow); color: var(--navy-950); isolation: isolate; overflow: hidden; }

.yoke::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: var(--navy-950);
  transform: scaleX(0);
  transform-origin: right center;
  pointer-events: none;
}

.yoke::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 0;
  z-index: 2;
  width: 14px;
  height: 14px;
  margin: -7px 0 0 -7px;
  border-radius: 50%;
  background: var(--white);
  box-shadow: 0 0 0 5px rgb(255 212 59 / 0.55), 0 0 28px 12px rgb(255 190 0 / 0.7);
  opacity: 0;
  pointer-events: none;
}

/* Speed flare: the band is retroreflective tape; fast scrolling sweeps a light across it (app.js sets
   --flare 0–1 and --gx). The row sits above the flare. */
.yoke-glint {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: linear-gradient(100deg, rgb(255 255 255 / 0) 0%, rgb(255 255 255 / 0.95) 48%, rgb(255 251 220 / 0.9) 52%, rgb(255 255 255 / 0) 100%) no-repeat;
  background-size: 38% 100%;
  background-position: var(--gx, -60%) 0;
  opacity: var(--flare, 0);
}
.yoke-row {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) minmax(0, 1fr);
  align-items: center;
  gap: 4px clamp(24px, 4vw, 64px);
  min-height: var(--yoke-h);
  padding-block: 12px;
}

.yoke-label { font-size: 0.9375rem; font-weight: 650; }

.yoke-link {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  column-gap: 16px;
  padding: 6px 0;
  border-radius: 4px;
  text-decoration: none;
}

.yoke-link strong { font-family: var(--font-display); font-size: clamp(0.95rem, 0.8rem + 0.45vw, 1.2rem); font-weight: 650; line-height: 1.2; letter-spacing: -0.01em; }
.yoke-link span { grid-column: 1; font-size: 0.9375rem; font-weight: 520; color: var(--navy-800); }
.yoke-link .icon { grid-column: 2; grid-row: 1 / span 2; width: 26px; height: 26px; transition: transform var(--dur-base) var(--ease-out); }
.yoke-link:focus-visible { outline-color: var(--navy-950); }

@media (hover: hover) and (pointer: fine) {
  .yoke-link:hover strong { text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 0.18em; }
  .motion-on .yoke-link:hover .icon { transform: translateY(5px); }
}

@media (max-width: 899px) {
  .hero-stage { --copy-w: calc(100vw - 2 * var(--gutter)); display: flex; flex-direction: column; align-items: stretch; min-height: 0; }
  .hero-copy { order: 1; padding-block: 44px 36px; }
  .hero-photo { position: relative; inset: auto; z-index: 0; order: 2; aspect-ratio: 4 / 3; }
  .hero-photo::after { background: linear-gradient(180deg, var(--navy-950) 0%, rgb(11 20 36 / 0) 24%); }
  .hero h1 { font-size: min(3.4rem, calc(var(--copy-w) / var(--h1-em))); }
  .hero-tag { left: var(--gutter); right: auto; }
  .yoke-row { grid-template-columns: minmax(0, 1fr); padding-block: 18px 12px; }
}

@media (max-width: 459px) {
  .hero-actions .btn { flex: 1 1 100%; }
}

/* ---------- Section rhythm ---------- */

.section { padding-block: var(--section-y); }

.section-title { font-size: clamp(2.1rem, 1.2rem + 2.6vw, 3.6rem); }

.section-title .w { display: inline-block; overflow: hidden; vertical-align: top; padding: 0.02em 0 0.14em; margin: -0.02em 0 -0.14em; }
.section-title .w > span { display: inline-block; }

.lead { font-size: clamp(1.1875rem, 1.05rem + 0.45vw, 1.4375rem); line-height: 1.5; color: var(--ink-2); }

/* ---------- Film (v9) ----------
   One continuous camera pull-back from a fresh weld seam on a liner's side shell to the whole liner. It is baked
   offline (tools/render_film.cjs, DESIGN.md "Version 9") and drawn frame by frame on a canvas as the page scrolls;
   the stage is pinned under the header and the section is tall enough to give every frame about 20 px of scroll.
   Without JavaScript the first frame stands as a picture in a one-screen section. */

.film { position: relative; background: linear-gradient(var(--film-top, #24406b), var(--film-bottom, #7d7f80)); }
.js .film { height: 400svh; }   /* v15: 340 → 400, the closing frame is held for about a screen of scroll */

.film-stage { position: relative; height: calc(100svh - var(--header-h)); min-height: 420px; overflow: hidden; }
.js .film-stage { position: sticky; top: var(--header-h); }

.film-poster, .film-poster img, .film-canvas { position: absolute; inset: 0; display: block; width: 100%; height: 100%; }
.film-poster img { object-fit: cover; object-position: 50% 50%; }
.film-canvas { opacity: 0; transition: opacity 500ms ease; }
.film.is-live .film-canvas { opacity: 1; }

/* The sentence frames the ship. "Kiekviena siūlė" stays at the top from the seam on (v11, user 2026-10-04: no
   disappearing, larger, no plate); "– laivo dalis." rises at the bottom, under the keel, once the ship stands whole
   (v15, user 2026-10-05: «laivo dalis пусть будет ниже уже под кораблем»). A soft shade at the top keeps the white type
   readable over steel, paint and sky; a second one rises from the dock floor with the second line. No shadow under
   the letters (v13). */
.film-stage::after { content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none; background: linear-gradient(180deg, rgb(6 10 18 / 0.64) 0%, rgb(6 10 18 / 0.36) 30%, rgb(6 10 18 / 0.1) 50%, rgb(6 10 18 / 0) 64%); }
.film-stage::before { content: ""; position: absolute; left: 0; right: 0; bottom: 0; z-index: 1; height: 46%; pointer-events: none; background: linear-gradient(0deg, rgb(6 10 18 / 0.66) 0%, rgb(6 10 18 / 0.4) 34%, rgb(6 10 18 / 0.12) 68%, rgb(6 10 18 / 0) 100%); opacity: 0; transition: opacity 900ms ease; }
.film[data-phase="ab"] .film-stage::before, .no-js .film-stage::before { opacity: 1; }
.film-copy { position: absolute; z-index: 2; top: clamp(24px, 7vh, 88px); bottom: clamp(28px, 7vh, 80px); left: 0; right: 0; pointer-events: none; }
.film-title {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  height: 100%;
  max-width: 12em;
  color: var(--white);
  font-size: clamp(2.4rem, 0.9rem + 5.6vw, 7.6rem);
  font-weight: 700;
  line-height: 1.1;   /* Unbounded's p and g clear the next line (layout gate, v10) */
  letter-spacing: -0.02em;
}
.film-line { display: block; overflow: hidden; padding: 0.02em 0 0.14em; margin: -0.02em 0 -0.14em; }
.film-line > span { display: inline-block; }
.film-line--b { color: var(--brand-on-dark); }
.motion-on .film-title { transition: opacity 500ms ease, transform 700ms var(--ease-out); }
.motion-on .film-line > span { transition: transform 900ms var(--ease-out); }
.js .film:not([data-phase="a"]):not([data-phase="ab"]) .film-title { opacity: 0; transform: translateY(-12px); }
.js .film[data-phase="a"] .film-line--b > span { transform: translateY(108%); }
.film[data-phase="ab"] .film-line--b > span { transition-delay: 160ms; }

@media (max-aspect-ratio: 1/1) {
  .js .film { height: 350svh; }
}

/* ---------- Services ---------- */

.services { background: var(--steel-50); }

/* v11: no empty column (user 2026-10-04: "пустовато"). The heading row works like the process one: the title on the
   left, the lead and the company line on the right. Below it, the five services run the full width as a ledger:
   a large title in the left column, the sentence in the right one, hairlines between the rows. */
.services-grid { display: grid; gap: clamp(40px, 5vw, 72px); }

.services-head {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  column-gap: clamp(40px, 7vw, 120px);
  align-items: end;
}
.services-head .section-title { grid-row: 1 / span 2; align-self: start; }
.services-head .lead { grid-column: 2; color: var(--ink); max-width: 26em; }
.company-line { grid-column: 2; margin-top: 14px; max-width: 34em; color: var(--ink-2); }

.service-list { display: grid; margin: 0; padding: 0; list-style: none; border-top: 1px solid var(--steel-200); }

.service {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  column-gap: clamp(40px, 7vw, 120px);
  align-items: baseline;
  padding: clamp(22px, 2.4vw, 34px) 0;
  border-bottom: 1px solid var(--steel-200);
}

/* a weld-blue rule rises along the row; it also fades, so a leaving rule never lingers as a dash */
.service::before {
  content: "";
  position: absolute;
  left: calc(-1 * clamp(12px, 1.4vw, 22px));
  top: clamp(22px, 2.4vw, 34px);
  bottom: clamp(22px, 2.4vw, 34px);
  width: 3px;
  border-radius: 2px;
  background: var(--brand);
  opacity: 0;
  transform: scaleY(0);
  transform-origin: 50% 100%;
  transition: transform 420ms var(--ease-out), opacity 180ms linear;
}

.service h3 { font-size: clamp(1.75rem, 1.05rem + 2.1vw, 3.25rem); transition: color var(--dur-fast) ease, transform var(--dur-base) var(--ease-out); }
.service p { max-width: 32em; color: var(--ink-2); font-size: clamp(1.0625rem, 1rem + 0.3vw, 1.25rem); }

@media (hover: hover) and (pointer: fine) {
  .service { cursor: default; }
  .service:hover::before { opacity: 1; transform: none; }
  .service:hover h3 { color: var(--brand-ink); }
  .motion-on .service:hover h3 { transform: translateX(6px); }
}

/* v17: one photoreal object per service at the end of its row (user 2026-10-05: the v15 photo slots were «сосиски», and
   they repeated the gallery's photos). On hover the object is set down beside the sentence: it comes from a closer
   view, settles and leans a little with the hand. Touch screens set each object down once as its row arrives. */
/* the object fits inside the lowest row (its padding plus one title line), so it never crosses a hairline */
.service { --obj: calc(2 * clamp(22px, 2.4vw, 34px) + 1.1 * clamp(1.75rem, 1.05rem + 2.1vw, 3.25rem) - 12px); }
.service p { max-width: min(32em, calc(100% - var(--obj) - clamp(24px, 3vw, 48px))); }
.service-obj {
  position: absolute;
  top: 50%;
  right: 0;
  z-index: 1;
  width: var(--obj);
  height: var(--obj);
  margin-top: calc(var(--obj) / -2);
  pointer-events: none;
}
.service-obj img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  opacity: 0;
  transform: translateY(10px) scale(1.12);
  rotate: calc(var(--hx, 0) * 5deg);
  transition: opacity 200ms ease, transform 0s linear 200ms, rotate 700ms var(--ease-out);
}
.service.is-open .service-obj img { opacity: 1; transform: none; transition: opacity 420ms ease, transform 900ms var(--ease-out), rotate 700ms var(--ease-out); }
@media (hover: hover) and (pointer: fine) {
  .service:hover .service-obj img { opacity: 1; transform: none; transition: opacity 420ms ease, transform 900ms var(--ease-out), rotate 700ms var(--ease-out); }
}
@media (hover: none), (pointer: coarse) {
  .no-js .service-obj img { opacity: 1; transform: none; }
}

@media (max-width: 899px) {
  .services-head, .service { grid-template-columns: minmax(0, 1fr); }
  .services-head .section-title { grid-row: auto; }
  .services-head .lead, .company-line { grid-column: 1; }
  .services-head .lead { margin-top: 22px; }
  .service { row-gap: 8px; }
  /* the object stands beside the sentence, under the title */
  .service { --obj: 92px; grid-template-columns: minmax(0, 1fr) var(--obj); column-gap: 16px; }
  .service h3 { grid-column: 1 / -1; }
  .service p { grid-column: 1; max-width: 32em; }
  .service-obj { position: static; grid-column: 2; grid-row: 2; align-self: center; margin: 0; }
}

/* ---------- Works ---------- */

.works { background: var(--white); }

.works-head {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  gap: 24px clamp(40px, 7vw, 120px);
  align-items: end;
  margin-bottom: clamp(40px, 5vw, 72px);
}

.works-head .lead { max-width: 26em; }

/* Route map (v8): the Baltic as a chart in the company's blue, land in the uniform navy (Natural Earth, public
   domain). The sea is one flat colour, with no shading at the edges. The port cards carry the two workplaces. */
.works-map { --focus: var(--white); position: relative; margin: 0 0 clamp(72px, 9vw, 136px); }

.map-canvas { position: relative; border-radius: 24px; background: var(--brand); overflow: hidden; isolation: isolate; }

.map-art { position: relative; aspect-ratio: 1552 / 850; }
.map-land, .map-overlay { position: absolute; inset: 0; display: block; width: 100%; height: 100%; }

.map-grid { fill: none; stroke: rgb(255 255 255 / 0.14); stroke-width: 1; }
.map-sea { fill: rgb(255 255 255 / 0.6); font: 600 24px/1 var(--font-display); letter-spacing: 0.42em; text-anchor: middle; text-transform: uppercase; }
.map-country { fill: rgb(255 255 255 / 0.5); font: 600 14px/1 var(--font-text); letter-spacing: 0.3em; text-anchor: middle; text-transform: uppercase; }

.route-glow { fill: none; stroke: rgb(255 255 255 / 0.32); stroke-width: 16; stroke-linecap: round; filter: blur(7px); }
.chart-route { fill: none; stroke: var(--white); stroke-width: 3.5; stroke-linecap: round; stroke-dasharray: 0.008 0.011; }

.port-dot { fill: var(--white); }
.port-ring { fill: none; stroke: var(--white); stroke-width: 2; opacity: 0.5; transform-box: fill-box; transform-origin: center; transition: transform 500ms var(--ease-out), opacity 300ms ease; }
.works-map[data-hl="turku"] .port--turku .port-ring,
.works-map[data-hl="klaipeda"] .port--klaipeda .port-ring { opacity: 1; transform: scale(1.8); }

.route-km {
  position: absolute;
  left: var(--px);
  top: var(--py);
  display: inline-flex;
  align-items: baseline;
  gap: 0.25em;
  padding: 7px 14px;
  border-radius: 999px;
  background: var(--white);
  color: var(--navy-950);
  font: 650 0.9375rem/1.1 var(--font-display);
  letter-spacing: -0.01em;
  white-space: nowrap;
  box-shadow: 0 12px 26px -14px rgb(11 20 36 / 0.6);
  transform: translate(calc(-100% - 22px), -50%);
}


.port-card {
  position: absolute;
  left: var(--px);
  top: var(--py);
  z-index: 1;
  display: grid;
  grid-template-columns: 58px auto;
  align-items: center;
  gap: 14px;
  padding: 8px 20px 8px 8px;
  border-radius: 16px;
  background: var(--white);
  color: var(--ink);
  text-decoration: none;
  box-shadow: 0 1px 2px rgb(11 20 36 / 0.12), 0 22px 40px -22px rgb(11 20 36 / 0.75);
  transform: translate(30px, -50%);
  transition: transform var(--dur-base) var(--ease-out), box-shadow var(--dur-base) ease;
}

/* a short leader from the beacon to its card */
.port-card::before { content: ""; position: absolute; right: 100%; top: 50%; width: 22px; height: 2px; margin-top: -1px; background: var(--white); }
.port-card img { width: 58px; height: 58px; border-radius: 10px; object-fit: cover; }
.port-card-text { display: grid; gap: 3px; }
.port-card strong { font: 650 1.0625rem/1.15 var(--font-display); letter-spacing: -0.01em; }
.port-card-text span { color: var(--ink-2); font-size: 0.875rem; line-height: 1.3; white-space: nowrap; }
.port-card:focus-visible { outline-offset: 4px; }

@media (hover: hover) and (pointer: fine) {
  .port-card:hover { box-shadow: 0 1px 2px rgb(11 20 36 / 0.12), 0 30px 50px -24px rgb(11 20 36 / 0.85); }
  .motion-on .port-card:hover { transform: translate(30px, calc(-50% - 4px)); }
  .port-card:hover strong { text-decoration: underline; text-decoration-color: var(--brand); text-decoration-thickness: 2px; text-underline-offset: 0.2em; }
}

@media (max-width: 899px) {
  .map-country { font-size: 22px; }
  .map-sea { font-size: 28px; letter-spacing: 0.36em; }
}

/* Phones: the map stays a picture; the two port cards follow it. */
@media (max-width: 759px) {
  .map-canvas { display: grid; gap: 8px; padding-bottom: 12px; border-radius: var(--radius-panel); }
  .port-card { position: relative; inset: auto; grid-template-columns: 52px minmax(0, 1fr); margin-inline: 12px; padding: 6px 14px 6px 6px; transform: none; }
  .port-card::before { display: none; }
  .port-card img { width: 52px; height: 52px; }
  .port-card-text span { white-space: normal; }
  .motion-on .port-card:hover { transform: translateY(-2px); }
  .route-km { padding: 5px 10px; font-size: 0.8125rem; transform: translate(calc(-100% - 14px), -50%); }
  .map-country { display: none; }
  .map-sea { font-size: 34px; letter-spacing: 0.3em; }
}

.site + .site { margin-top: clamp(72px, 9vw, 136px); }

.site { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); grid-auto-flow: dense; gap: clamp(16px, 2vw, 28px); scroll-margin-top: calc(var(--header-h) + 24px); }
.gallery { display: contents; }
.site-card { grid-column: 1; grid-row: 1; }
.shot--lead { grid-column: 2 / span 2; grid-row: 1 / span 2; }
.site--klaipeda .site-card { grid-column: 3; grid-row: 1; }
.site--klaipeda .shot--lead { grid-column: 1 / span 2; }
.shot--lead .shot-frame, .shot--lead .shot-media, .shot--lead picture { height: 100%; }
.shot--lead img { height: 100%; aspect-ratio: auto; }
/* v13: the photo under the text column ends level with the lead photo (user 2026-10-05: «блок нужно опустить») */
@media (min-width: 900px) { .shot--lead + .shot { align-self: end; } }

.shot { margin: 0; }

/* The photo itself is the control: a quiet round "plus" cursor instead of badges and corners. */
.shot-frame {
  position: relative;
  display: block;
  border-radius: var(--radius-photo);
  background: var(--steel-100);
  overflow: hidden;
  cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='44' height='44' viewBox='0 0 44 44'%3E%3Ccircle cx='22' cy='22' r='19' fill='%23fff' fill-opacity='.94'/%3E%3Ccircle cx='22' cy='22' r='19' fill='none' stroke='%230b1424' stroke-opacity='.18'/%3E%3Cpath d='M22 15v14M15 22h14' stroke='%230865ff' stroke-width='2.2' stroke-linecap='round'/%3E%3C/svg%3E") 22 22, zoom-in;
  isolation: isolate;
}

.shot-media { display: block; transition: scale 900ms var(--ease-out); }
.motion-on .shot-media { transform: translate3d(0, var(--py, 0px), 0) scale(1.1); will-change: transform; }
.shot img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; }
.shot--wide { grid-column: span 2; }
.shot--wide img { aspect-ratio: 2.76; }

.shot-frame:focus-visible { outline-offset: 4px; }
/* v25 (user 2026-10-18: «не нужно их открывать на большой экран… в этой полосе, пусть она станет чуть побольше»): no
   full-screen viewer. A tap enlarges the photo in place: on wide screens it opens to the full width of its block, on
   phones the whole strip grows a little (82 → 92 % wide, 4:3 → 5:4). A second tap puts it back. */
button.shot-frame { width: 100%; padding: 0; border: 0; font: inherit; color: inherit; text-align: left; }
.shot.is-big .shot-frame { cursor: zoom-out; }
@media (min-width: 560px) {
  .site .shot.is-big { grid-column: 1 / -1; grid-row: auto; align-self: start; }
  .site .shot.is-big .shot-frame, .site .shot.is-big .shot-media, .site .shot.is-big picture { height: auto; }
  .site .shot.is-big img { height: auto; aspect-ratio: 16 / 9; }
}

@media (hover: hover) and (pointer: fine) {
  .motion-on .shot-frame:hover .shot-media { scale: 1.06; }
}

.site-card {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 4px 0 0;
  border-top: 2px solid var(--ink);
  color: var(--ink);
}

.site-card h3 { font-size: clamp(1.25rem, 1rem + 0.8vw, 1.75rem); }
.site-place { display: inline-flex; align-items: center; gap: 8px; color: var(--brand-ink); font-weight: 620; }
.site-place a { color: inherit; text-decoration-color: rgb(7 88 224 / 0.45); }
.site-place .icon { width: 18px; height: 18px; }
.site-card h3 { padding-top: 18px; }
.site-card p:last-child { max-width: 22em; color: var(--ink-2); }

@media (hover: hover) and (pointer: fine) {
  .site-place a:hover { text-decoration-color: currentColor; text-decoration-thickness: 2px; }
}

@media (max-width: 999px) {
  .works-head { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 899px) {
  .site { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .site-card, .site--klaipeda .site-card { grid-column: 1 / -1; grid-row: auto; min-height: 0; }
  .shot--lead, .site--klaipeda .shot--lead { grid-column: 1 / -1; grid-row: auto; }
  .shot--lead img { aspect-ratio: 3 / 2; height: auto; }
  .shot--wide img { aspect-ratio: 8 / 3; }
  /* Four workshop photos fill two rows evenly when the wide one takes a single cell. */
  .site--klaipeda .shot--wide { grid-column: auto; }
  .site--klaipeda .shot--wide img { aspect-ratio: 4 / 3; }
}

.strip-controls { display: none; }

/* v11 (user 2026-10-04: the stock square arrows looked "standard and ugly"): one navy pill like the language
   switch, two round fields with long drawing-office arrows and a hairline between them; a press fills the field with
   the logo blue, and the end of the strip dims its arrow. */
.strip-btn {
  position: relative;
  display: grid;
  place-items: center;
  width: 56px;
  height: 44px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--white);
  cursor: pointer;
  transition: background-color var(--dur-fast) ease, color var(--dur-fast) ease;
}
.strip-btn + .strip-btn::before { content: ""; position: absolute; left: -3px; top: 12px; bottom: 12px; width: 1px; background: rgb(255 255 255 / 0.18); }
.strip-btn .icon { width: 26px; height: 26px; stroke-width: 1.5; }
.strip-btn:disabled { color: rgb(255 255 255 / 0.3); cursor: default; }
.strip-btn:not(:disabled):active { background: var(--brand); }
@media (hover: hover) and (pointer: fine) { .strip-btn:not(:disabled):hover { background: var(--brand); } }

@media (max-width: 559px) {
  .site { display: block; }
  .strip-controls { display: flex; gap: 6px; width: max-content; margin: 18px 0 0 auto; padding: 4px; border-radius: 999px; background: var(--navy-950); }
  .gallery {
    display: flex;
    gap: 12px;
    margin: 12px calc(-1 * var(--gutter)) 0;
    padding: 0 var(--gutter) 8px;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scroll-padding-inline: var(--gutter);
    scrollbar-width: none;
  }
  .gallery::-webkit-scrollbar { display: none; }
  .gallery .shot { flex: 0 0 82%; scroll-snap-align: start; }
  /* v18 (user 2026-10-07: «фотки не влезли в контейнеры, видны серые границы»): the row stretched every frame to its
     tallest photo, so a 3:2 lead showed the frame's grey under it. Every frame in a phone strip is now the same 4:3
     box of the same width, and the photo covers it; a tap enlarges the strip (v25). */
  .gallery { align-items: flex-start; }
  .gallery .shot-frame { aspect-ratio: 4 / 3; height: auto; }
  .gallery .shot-media, .gallery .shot picture { height: 100%; }
  .site .gallery .shot img { height: 100%; aspect-ratio: auto; object-fit: cover; }
  .gallery.is-big .shot { flex-basis: 92%; }
  .gallery.is-big .shot-frame { aspect-ratio: 5 / 4; }
  .gallery:focus-visible { outline-offset: -3px; }
}

/* ---------- Process ----------
   v8: three cards stack as the page scrolls (the first stays pinned, the next slides over it and the one
   underneath steps back). Each photo settles from a closer view as its card arrives. The photos are generated
   still lifes, see PRODUCT.md. Pinning needs room: on short or narrow screens the cards simply follow each other. */

.process { background: var(--steel-100); }

.process-head { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: 24px clamp(40px, 7vw, 120px); align-items: end; }
.process-head .lead { max-width: 26em; }
/* v11: up to 1199 px the title gets the full width, so "How we work" never breaks after "How" (layout gate lone-word) */
@media (max-width: 1199px) { .process-head { grid-template-columns: minmax(0, 1fr); } }

.steps { display: grid; gap: clamp(28px, 5vh, 56px); margin: clamp(48px, 6vw, 88px) 0 0; padding: 0; list-style: none; }

.step {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  min-height: clamp(380px, calc(100svh - var(--header-h) - 200px), 560px);
  border-radius: 28px;
  background: var(--white);
  box-shadow: 0 1px 2px rgb(17 30 53 / 0.06), 0 34px 64px -40px rgb(17 30 53 / 0.55);
  overflow: hidden;
  transform-origin: 50% 0;
}

.step::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  border-radius: inherit;
  background: var(--navy-950);
  opacity: calc(var(--k, 0) * 0.14);
  pointer-events: none;
}

.step-body { display: grid; grid-template-columns: auto minmax(0, 1fr); align-content: start; column-gap: 18px; padding: clamp(26px, 2.6vw, 38px) clamp(28px, 3.6vw, 56px) clamp(28px, 3.6vw, 56px); }

.step-n { padding-top: 0.32em; color: var(--brand); font: 650 1.25rem/1 var(--font-display); letter-spacing: 0; font-variant-numeric: tabular-nums; }

.step h3 { font-size: clamp(1.625rem, 1.2rem + 1.3vw, 2.5rem); }
.step p { margin-top: 18px; max-width: 26em; color: var(--ink-2); font-size: clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem); }

.step-media { position: relative; margin: 0; overflow: hidden; background: var(--steel-200); }
.step-media picture, .step-media img { position: absolute; inset: 0; width: 100%; height: 100%; }
.step-media img { object-fit: cover; }
.motion-on .step-media img {
  /* v27 (user 2026-10-28: «размытая картинка»): no blur at all — the photo stays sharp and only dollies back as its card arrives */
  scale: calc(1.16 - var(--e, 1) * 0.16);
  will-change: scale;
}
/* v13: the layer camera draws the photo on a canvas (src/app.js); the photo stays for readers and fallbacks */

@media (min-width: 900px) and (min-height: 620px) {
  .step { position: sticky; top: calc(var(--header-h) + 24px + var(--i) * 88px); }
  .motion-on .step { transform: scale(calc(1 - var(--k, 0) * 0.04)); }
}

@media (max-width: 899px) {
  .process-head { grid-template-columns: minmax(0, 1fr); }
  .step { grid-template-columns: minmax(0, 1fr); min-height: 0; border-radius: 22px; }
  .step-media { order: -1; aspect-ratio: 3 / 2; }
  .step-body { gap: 18px; }
  .step-n { font-size: 1.125rem; }
}

/* Parallax backgrounds sit in their own clipping frame, so the section itself never clips content or focus rings. */
.bg-frame { position: absolute; inset: 0; z-index: -2; overflow: hidden; pointer-events: none; }

/* ---------- Contact ---------- */

.contact { position: relative; background: var(--navy-950); color: var(--on-dark); isolation: isolate; }

.contact-media { position: absolute; inset: 0; }
.contact-media picture, .contact-media img { width: 100%; height: 100%; }
.contact-media img { object-fit: cover; object-position: 50% 45%; }
.motion-on .contact-media { inset: -14% 0; transform: translate3d(0, var(--py, 0px), 0); will-change: transform; }

.contact::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  /* v21 photo redo: the finale has its own blue-hour quay photo with calm sky for the text, so the veil is light
     (a heavy veil "to save the text" hid the photo — docs/VISUAL_GENERATION.md §6a) */
  /* v23 (user 2026-10-17, "здесь все сливается"): the form column lay on the light hull. The veil is dense under the
     form (right 58 %) and light beside the contacts, so the photo still shows on the left */
  background: linear-gradient(90deg, rgb(11 20 36 / 0.66) 0%, rgb(11 20 36 / 0.7) 34%, rgb(11 20 36 / 0.88) 44%, rgb(11 20 36 / 0.9) 100%);
}
@media (max-width: 899px) {
  .contact::before { background: rgb(11 20 36 / 0.82); }
}

.contact-grid { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: 56px clamp(40px, 6vw, 104px); align-items: start; }
.contact-info { position: sticky; top: calc(var(--header-h) + 48px); }

.contact-lines { display: grid; gap: 6px; margin-top: clamp(28px, 3vw, 40px); }

.contact-line {
  display: inline-flex;
  align-items: center;
  gap: 14px;
  width: fit-content;
  max-width: 100%;
  padding: 6px 0;
  border-radius: 4px;
  color: var(--on-dark);
  font: 700 clamp(1.4rem, 1.05rem + 1.1vw, 2.125rem)/1.15 var(--font-text);
  letter-spacing: -0.015em;
  text-decoration: none;
  overflow-wrap: anywhere;
}

.contact-line .icon { width: 0.9em; height: 0.9em; color: var(--brand-on-dark); stroke-width: 2; transition: transform var(--dur-base) var(--ease-out); }

.addresses { display: grid; gap: 20px; margin: clamp(36px, 4vw, 56px) 0 0; }
.addresses dt { color: var(--on-dark-2); font-size: 0.9375rem; font-weight: 600; }
.addresses dd { margin: 6px 0 0; }
.addresses a { color: var(--on-dark); font-weight: 560; text-decoration-color: rgb(106 161 255 / 0.6); }
.addresses a .icon { display: inline; width: 0.95em; height: 0.95em; margin-left: 4px; vertical-align: -0.1em; color: var(--brand-on-dark); transition: transform var(--dur-base) var(--ease-out); }
/* Careers joined the contact finale in v8: one more address, set apart by a hairline. */
.addresses #karjera { padding-top: 20px; border-top: 1px solid rgb(255 255 255 / 0.14); }

@media (hover: hover) and (pointer: fine) {
  .contact-line:hover { text-decoration: underline; text-decoration-color: var(--brand-on-dark); text-decoration-thickness: 2px; text-underline-offset: 0.16em; }
  .motion-on .contact-line:hover .icon { transform: rotate(-12deg) scale(1.12); }
  .addresses a:hover { text-decoration-color: var(--brand-on-dark); text-decoration-thickness: 2px; }
  .motion-on .addresses a:hover .icon { transform: translate(2px, -2px); }
}

@media (max-width: 999px) {
  .contact-grid { grid-template-columns: minmax(0, 1fr); }
  .contact-info { position: static; }
}

/* Inquiry composer */

/* v21: the composer lies on the finale scene itself — underline fields on dark, no white card (a white form card on the
   dark finale reads cheap, and it hid the new quay photo) */
.composer { --focus: var(--brand-on-dark); padding: 0; color: var(--on-dark); }
.composer h3 { font-size: clamp(1.3rem, 1.05rem + 0.7vw, 1.75rem); }
.composer-note { margin-top: 10px; color: rgb(255 255 255 / 0.92); }

.field-group { min-width: 0; margin: 20px 0 0; padding: 0; border: 0; }
.field-group legend, .field-label { display: block; margin-bottom: 8px; padding: 0; color: var(--on-dark); font-size: 0.9375rem; font-weight: 650; }

.choices { display: flex; flex-wrap: wrap; gap: 8px; }
.choice { position: relative; display: inline-flex; }
.choice input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }

.choice span {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 40px;
  padding: 8px 14px;
  border-radius: var(--radius-control);   /* v26: rounded like every other control (user 2026-10-22) */
  background: rgb(11 20 36 / 0.35);
  box-shadow: inset 0 0 0 1px rgb(255 255 255 / 0.55);
  color: var(--on-dark);
  font-size: 0.9375rem;
  font-weight: 560;
  line-height: 1.25;
  transition: background-color var(--dur-fast) ease, box-shadow var(--dur-fast) ease, color var(--dur-fast) ease, transform var(--dur-fast) ease;
}

.choice .icon { display: none; width: 16px; height: 16px; stroke-width: 2.4; }
.choice input:checked + span { background: var(--white); box-shadow: inset 0 0 0 1px var(--white); color: var(--navy-950); }
.choice input:checked + span .icon { display: block; color: var(--blue); }
.choice input:focus-visible + span { outline: 3px solid var(--brand-on-dark); outline-offset: 2px; }
.motion-on .choice input:active + span { transform: scale(0.97); }

@media (hover: hover) and (pointer: fine) {
  .choice input:not(:checked):hover + span { background: rgb(255 255 255 / 0.12); box-shadow: inset 0 0 0 1.5px var(--white); }
}

.field-row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 20px; }
.field { margin-top: 18px; }

.field input,
.field textarea {
  display: block;
  width: 100%;
  min-height: 46px;
  padding: 10px 0;
  border: 0;
  border-bottom: 1.5px solid rgb(255 255 255 / 0.85);
  border-radius: 0;
  background: transparent;
  color: var(--on-dark);
  font: inherit;
  font-size: 1rem;
  transition: border-color var(--dur-fast) ease, box-shadow var(--dur-fast) ease, background-color var(--dur-fast) ease;
}

.field textarea { min-height: 92px; resize: vertical; line-height: 1.5; }
.field-hint { margin: -4px 0 10px; color: rgb(255 255 255 / 0.92); font-size: 0.9375rem; line-height: 1.45; }
.field input:focus-visible,
.field textarea:focus-visible { outline: none; border-color: var(--brand-on-dark); background: rgb(255 255 255 / 0.06); box-shadow: 0 2px 0 0 var(--brand-on-dark); }
.field input::placeholder, .field textarea::placeholder { color: rgb(255 255 255 / 0.7); }

@media (hover: hover) and (pointer: fine) {
  .field input:hover, .field textarea:hover { border-color: var(--white); }
}

.field [aria-invalid="true"] { border-color: #ff8a80; box-shadow: 0 2px 0 0 #ff8a80; }
.field-group[aria-invalid="true"] .choice span { box-shadow: inset 0 0 0 1.5px #ff8a80; }
.field-error { display: none; margin-top: 8px; padding-left: 10px; border-left: 3px solid #ff8a80; color: var(--on-dark); font-size: 0.9375rem; font-weight: 560; }
.field-error.is-visible { display: block; }
.optional { color: rgb(255 255 255 / 0.92); font-weight: 480; }

.composer-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 20px; margin-top: 24px; }
.composer-status { flex-basis: 100%; min-height: 0; color: rgb(255 255 255 / 0.92); font-size: 0.9375rem; }
.composer-status.is-ok { color: #8fe3a8; font-weight: 560; }

@media (max-width: 599px) {
  .field-row { grid-template-columns: minmax(0, 1fr); }
  .composer-actions .btn-primary { flex: 1 1 100%; }
}

/* ---------- Footer ----------
   v8: one composition on the centre line. Logo, sections and language share a row; the legal name, codes and
   credit sit centred under the sections, divided by thin rules. No second band.
   v11: the row is centred like the header and the logo is 140 px (user 2026-10-04: smaller than the header's).
   Below 1024 px the sections take their own row, so the logo never shrinks. */

.site-footer { background: var(--navy-950); color: var(--on-dark-2); font-size: 0.9375rem; }
.site-footer a { color: var(--on-dark); text-decoration-color: rgb(106 161 255 / 0.55); }

.footer-inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: center;
  gap: 22px clamp(24px, 3vw, 48px);
  padding-block: clamp(44px, 5vw, 72px) clamp(36px, 4vw, 56px);
}

.footer-center { display: contents; }

.footer-logo { grid-column: 1; grid-row: 1; justify-self: start; display: block; border-radius: 4px; }
.footer-logo img { display: block; width: 140px; max-width: none; height: auto; }

.footer-nav { grid-column: 2; grid-row: 1; }
.footer-nav ul { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px clamp(18px, 2.4vw, 36px); margin: 0; padding: 0; list-style: none; }
.footer-nav a { display: inline-flex; align-items: center; gap: 6px; padding: 6px 0; font-weight: 600; text-decoration: none; }
.footer-nav .icon { width: 15px; height: 15px; color: var(--brand-on-dark); transition: transform var(--dur-base) var(--ease-out); }

/* The language switch repeats the header's segmented control; the current language is a brand-blue pill. */
.footer-lang { grid-column: 3; grid-row: 1; display: flex; justify-self: end; gap: 2px; padding: 3px; border-radius: 8px; background: var(--navy-900); }
.footer-lang a { display: grid; place-items: center; min-width: 44px; height: 34px; padding: 0 8px; border-radius: 5px; color: var(--on-dark-2); font-size: 0.875rem; font-weight: 650; text-decoration: none; transition: background-color var(--dur-fast) ease, color var(--dur-fast) ease; }
.footer-lang a[aria-current="page"] { background: var(--brand); color: var(--white); }

/* app.js marks the first item of every wrapped line, so no rule ever starts a line. */
.footer-legal { grid-column: 1 / -1; grid-row: 2; display: flex; flex-wrap: wrap; justify-content: center; row-gap: 4px; margin: 0; font-size: 0.875rem; line-height: 1.5; text-align: center; }
.footer-legal > span { padding: 0 16px; white-space: nowrap; }
.footer-legal > span + span { border-left: 1px solid rgb(255 255 255 / 0.22); }
.footer-legal > span.is-line-start { border-left-color: transparent; }
.footer-legal > span:first-child { color: var(--on-dark); font-weight: 650; }
.footer-legal a { font-weight: 600; }

@media (hover: hover) and (pointer: fine) {
  .site-footer a:hover { text-decoration-color: var(--brand-on-dark); text-decoration-thickness: 2px; }
  .footer-nav a:hover { text-decoration: underline; text-underline-offset: 0.3em; }
  .motion-on .footer-nav a:hover .icon { transform: translate(2px, -2px); }
  .footer-lang a:not([aria-current]):hover { color: var(--on-dark); background: var(--navy-800); }
  .motion-on .footer-logo:hover img { transform: translateX(3px); }
  .footer-logo img { transition: transform var(--dur-base) var(--ease-out); }
}

@media (max-width: 1023px) {
  .footer-inner { grid-template-columns: minmax(0, 1fr) auto; }
  .footer-lang { grid-column: 2; }
  .footer-nav { grid-column: 1 / -1; grid-row: 2; }
  .footer-legal { grid-row: 3; }
}

@media (max-width: 459px) {
  .footer-nav ul { gap: 2px 22px; }
  .footer-legal > span { padding: 0 12px; white-space: normal; }
}
}

/* ---------- Motion ----------
   html.motion-on is always set before first paint (user decision 2026-10-01: no switch, prefers-reduced-motion does not disable it).
   Without JavaScript the class is absent and the page keeps opacity fades and colour changes only. */

@keyframes line-up { from { transform: translateY(108%); } to { transform: none; } }
@keyframes line-in { from { opacity: 0; transform: translateY(0.3em); } to { opacity: 1; transform: none; } }
@keyframes fade-up { from { opacity: 0; transform: translateY(34px); } to { opacity: 1; transform: none; } }
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes hero-zoom { from { scale: 1.3; } to { scale: 1; } }
@keyframes map-zoom { from { scale: 1.14; } to { scale: 1; } }
@keyframes card-in { from { opacity: 0; translate: 0 16px; } to { opacity: 1; translate: 0 0; } }
@keyframes clip-up { from { clip-path: inset(100% 0 0 0 round var(--radius-photo)); } to { clip-path: inset(0 0 0 0 round var(--radius-photo)); } }
@keyframes settle { from { scale: 1.28; } to { scale: 1; } }
@keyframes yoke-weld { from { transform: scaleX(1); } to { transform: scaleX(0); } }
@keyframes yoke-arc { 0% { left: 0; opacity: 1; } 88% { opacity: 1; } 100% { left: 100%; opacity: 0; } }
@keyframes ping { 0% { opacity: 0.9; transform: scale(0.5); } 100% { opacity: 0; transform: scale(2.6); } }
@keyframes rise { from { opacity: 0; transform: translateY(24px) scale(0.98); } to { opacity: 1; transform: none; } }

/* Hero entrance (CSS only, so it never waits for app.js) */
.motion-on .hero h1 .line > span { animation: line-in 900ms var(--ease-out) calc(80ms + var(--li) * 90ms) backwards; }
.motion-on .hero-lead { animation: fade-up 800ms var(--ease-out) 360ms backwards; }
.motion-on .hero-actions { animation: fade-up 800ms var(--ease-out) 460ms backwards; }
.motion-on .hero-photo { animation: fade-in 900ms ease backwards; }
.motion-on .hero-media img { animation: hero-zoom 2200ms var(--ease-out) backwards; }
.motion-on .hero-tag { animation: fade-up 700ms var(--ease-out) 1250ms backwards; }
.motion-on .yoke::before { animation: yoke-weld 1000ms var(--ease-out) 820ms backwards; }
.motion-on .yoke::after { animation: yoke-arc 1000ms var(--ease-out) 820ms backwards; }
.motion-on .yoke-row { animation: fade-in 600ms ease 1320ms backwards; }

/* Scroll reveals, armed by app.js (html.reveal-armed): without the script everything is simply visible.
   Animations use backwards fill, so hover transitions work normally once an element has arrived. */
.reveal-armed [data-reveal]:not(.is-in) { opacity: 0; }
.reveal-armed [data-reveal].is-in:not(.is-done) { animation: fade-in 700ms ease calc(var(--i, 0) * 90ms) backwards; }

.motion-on.reveal-armed [data-reveal="up"].is-in:not(.is-done) { animation: fade-up 950ms var(--ease-out) calc(var(--i, 0) * 100ms) backwards; }

.motion-on.reveal-armed [data-reveal="words"]:not(.is-in) { opacity: 1; }
.motion-on.reveal-armed [data-reveal="words"]:not(.is-in) .w > span { transform: translateY(108%); }
.motion-on.reveal-armed [data-reveal="words"].is-in { animation: none; }
.motion-on.reveal-armed [data-reveal="words"].is-in:not(.is-done) .w > span { animation: line-up 950ms var(--ease-out) calc(var(--wi, 0) * 85ms) backwards; }

.motion-on.reveal-armed [data-reveal="photo"]:not(.is-in) { opacity: 1; }
.motion-on.reveal-armed [data-reveal="photo"]:not(.is-in) .shot-frame { clip-path: inset(100% 0 0 0 round var(--radius-photo)); }
.motion-on.reveal-armed [data-reveal="photo"].is-in { animation: none; }
.motion-on.reveal-armed [data-reveal="photo"].is-in:not(.is-done) .shot-frame { animation: clip-up 1150ms var(--ease-out) calc(var(--i, 0) * 110ms) backwards; }
.motion-on.reveal-armed [data-reveal="photo"].is-in:not(.is-done) .shot-media { animation: settle 1600ms var(--ease-out) calc(var(--i, 0) * 110ms) backwards; }

.motion-on.reveal-armed [data-reveal="chart"].is-in:not(.is-done) { animation: rise 1000ms var(--ease-out) backwards; }
/* the map arrives from a closer view, like the hero; cards and the distance follow once it has settled */
.motion-on.reveal-armed [data-reveal="chart"].is-in:not(.is-done) .map-art { animation: map-zoom 2000ms var(--ease-out) backwards; }
.motion-on.reveal-armed [data-reveal="chart"]:not(.is-in) .port-card,
.motion-on.reveal-armed [data-reveal="chart"]:not(.is-in) .route-km { opacity: 0; }
.motion-on.reveal-armed [data-reveal="chart"].is-in:not(.is-done) .route-km { animation: card-in 700ms var(--ease-out) 500ms backwards; }
.motion-on.reveal-armed [data-reveal="chart"].is-in:not(.is-done) .port-card--klaipeda { animation: card-in 800ms var(--ease-out) 1300ms backwards; }
.motion-on.reveal-armed [data-reveal="chart"].is-in:not(.is-done) .port-card--turku { animation: card-in 800ms var(--ease-out) 2500ms backwards; }

/* The intro plays in under 2.2 s and runs three times faster as soon as the visitor scrolls (app.js). */

/* ---------- Print ---------- */

/* Presses (shared rule 2026-10-05: «при нажатии на иконку меню появляется синий селектор на секунду»). The system tap
   flash is off (html); a press shows the control's own hover fill or colour in place, on touch screens too. */
.btn-primary:active { background: var(--yellow-2); }
.btn-ghost:active { background: rgb(255 255 255 / 0.08); box-shadow: inset 0 0 0 1.5px var(--on-dark); }
.btn-quiet:active { background: var(--white); box-shadow: inset 0 0 0 1.5px var(--navy-700); }
.header-phone:active { background: var(--brand-deep); }
.nav-toggle:active { background: var(--steel-100); }
.nav-list a:active { background: var(--steel-50); }
.lang a:not([aria-current]):active { color: var(--ink); background: var(--white); }
.footer-lang a:not([aria-current]):active { color: var(--on-dark); background: var(--navy-800); }
.yoke-link:active strong, .footer-nav a:active { text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 0.18em; }
.port-card:active strong { text-decoration: underline; text-decoration-color: var(--brand); text-decoration-thickness: 2px; text-underline-offset: 0.2em; }
.contact-line:active { text-decoration: underline; text-decoration-color: var(--brand-on-dark); text-decoration-thickness: 2px; text-underline-offset: 0.16em; }
.site-place a:active, .addresses a:active, .site-footer a:active { text-decoration-color: currentColor; text-decoration-thickness: 2px; }
.choice input:not(:checked):active + span { background: rgb(255 255 255 / 0.12); box-shadow: inset 0 0 0 1.5px var(--white); }

@media print {
  .site-header, .skip, .composer, .film-canvas, .strip-controls { display: none; }
  .film { height: auto; }
  .hero, .site-footer, .site-card, .contact { background: none; color: #000; }
  .contact-media, .contact::before, .hero-photo::after { display: none; }
}

/* Headings catch a passing light: a glint in the company's blue runs through the letters once they have risen,
   and again when the page is scrolled fast (v8: blue as in the logo; yellow stays on the hi-vis band and the
   main buttons). The gradient exists only while it plays. */
@keyframes glint { from { background-position: 100% 0; } to { background-position: 0 0; } }
.motion-on [data-reveal="words"].glint .w > span,
.motion-on .hero h1.glint .line > span {
  background-image: linear-gradient(100deg, currentColor 0 34%, var(--glint, var(--brand)) 42%, var(--glint-core, #5c9dff) 49%, var(--glint, var(--brand)) 56%, currentColor 64% 100%);
  background-size: 300% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  animation: glint 1700ms var(--ease-in-out) calc(var(--wi, var(--li, 0)) * 80ms) both;
}
.motion-on.reveal-armed [data-reveal="words"].is-in.glint:not(.is-done) .w > span {
  animation: line-up 950ms var(--ease-out) calc(var(--wi, 0) * 85ms) backwards, glint 1700ms var(--ease-in-out) calc(820ms + var(--wi, 0) * 80ms) both;
}
.motion-on .hero h1.glint .line > span {
  animation: line-in 900ms var(--ease-out) calc(80ms + var(--li) * 90ms) backwards, glint 1800ms var(--ease-in-out) calc(1300ms + var(--li) * 110ms) both;
}


