/* ============================================================
   ITH GROUP — V2 MAIN STYLESHEET  (faithful recovery)

   This file is a reconstruction of the lost V2 stylesheet, rebuilt
   from src/styles/tokens.css, the recovered templates, the surviving
   generated HTML and the documented design direction. It is NOT a
   redesign: every rule serves a class that the templates already use,
   with restrained, industrial B2B presentation on light surfaces.

   Both tokens.css and this file are copied into dist/assets/css/, so
   the token layer is pulled in here and only main.css is linked.
   ============================================================ */

@import "tokens.css";
@import "fonts.css";

/* ---- Reset / base ------------------------------------------------ */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

/* The header is sticky, so an in-page link would otherwise scroll its
   target underneath it — measured at -14px for #ct-form-title, taking the
   heading and the "required fields" hint out of view. Headings are the
   only anchor targets the site links to. */
:is(h1, h2, h3)[id] { scroll-margin-top: calc(var(--nav-h) + var(--space-5)); }

body {
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--body);
  background: var(--surface);
  font-weight: var(--fw-regular);
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
}

img, picture, svg { display: block; max-width: 100%; }
a { color: inherit; }
button { font: inherit; color: inherit; cursor: pointer; }
ul { list-style: none; padding: 0; }

h1, h2, h3, h4 {
  font-family: var(--font-display);
  color: var(--ink);
  line-height: var(--lh-snug);
  font-weight: var(--fw-bold);
  text-wrap: balance;
  word-break: normal;
  overflow-wrap: normal;
}

/* Body copy may wrap long compounds without splitting display headings. */
p, li, a, span, .t-body, .card__text { overflow-wrap: break-word; }

/* ---- Accessibility: skip link + focus --------------------------- */
.skip-link {
  position: fixed;
  top: var(--space-2);
  left: var(--space-2);
  z-index: var(--z-skip);
  padding: var(--space-2) var(--space-4);
  background: var(--ink);
  color: #fff;
  border-radius: var(--radius-sm);
  transform: translateY(-160%);
  transition: transform var(--dur-fast) var(--ease);
}
.skip-link:focus { transform: translateY(0); }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 2px;
}
:focus:not(:focus-visible) { outline: none; }

/* ---- Layout: containers + sections ------------------------------ */
.container {
  width: 100%;
  max-width: var(--container-standard);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
/* Every hero section in the templates already carries both .container
   and .hero on the same element, so this widens all of them with no
   markup change. Higher specificity than .container alone wins
   regardless of source order. */
.container.hero {
  max-width: var(--container-wide);
}
.container-text {
  width: 100%;
  max-width: min(var(--container-text), 68ch);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
/* Standalone wide container (the hero band already gets this via
   .container.hero; this exposes it as a reusable class for full-width
   editorial bands such as the process line). */
.container-wide {
  width: 100%;
  max-width: var(--container-wide);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.site-main { display: block; }

.section { padding-block: var(--section-y); }
/* Rhythm variants — shared foundation for later phases; not yet
   assigned to any specific section. */
.section--compact { padding-block: var(--section-y-compact); }
.section--major { padding-block: var(--section-y-major); }
.section--alt { background: var(--off); border-block: 1px solid var(--line); }
/* Consecutive tinted sections belong to one theme, so they read as a single
   band: the hairline between them would announce a boundary that is not
   there. The band's outer edges keep their rules. */
.section--alt + .section--alt { border-top: 0; }
.section-head { max-width: 62ch; }
.section-head--center { margin-inline: auto; text-align: center; }
/* One gap between a section's heading and its standfirst, everywhere.
   Paragraphs carry no margin of their own (the reset zeroes them), so this
   was previously set ad hoc on a single homepage paragraph and nowhere else. */
.section-head > p { margin-top: var(--space-4); }

/* ---- Typography helpers ----------------------------------------- */
.t-eyebrow {
  display: inline-block;
  max-width: 100%;
  font-family: var(--font-display);
  font-size: var(--fs-eyebrow);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--tracking-wider);
  text-transform: uppercase;
  color: var(--accent);
}
.t-h2 { font-size: var(--fs-h2-section); font-weight: var(--fw-bold); }
.t-h3 { font-size: var(--fs-h3); font-weight: var(--fw-bold); font-family: var(--font-body); }
.t-lead { font-size: var(--fs-lead); color: var(--muted); line-height: 1.55; }
.t-body { font-size: var(--fs-body); color: var(--body); }
.section-head .t-h2 { margin-top: var(--space-2); }

/* Display sizes are large enough that a single long compound can be wider
   than the line box on a phone — "Textilproduktfertigung" in the German
   hero overflowed the document by 125px at 390px. Break only when a word
   genuinely cannot fit, so ordinary wrapping is unchanged. */
.hero__title, .t-h2, .t-h3, .division-card__title,
.card__title, .resp-card__title,
.anchor__title, .site-triggers__title, .site-terms__title { overflow-wrap: break-word; }
/* German compounds are the only titles long enough to need a break inside a
   word, and break-word alone splits them mid-syllable with no hyphen. Ask
   the engine for hyphenation, limited to German card titles so HU, EN and
   IT wrapping is untouched. In the one Chromium build this was tested in,
   the declaration had no measurable effect; the cause and the behaviour of
   other engines, versions and platforms were not established. It is kept
   because it costs nothing where it does nothing. What actually produces
   the correct break is the conditional hyphen (U+00AD) each of the four
   affected titles carries at its compound seam in src/content/de/;
   break-word stays underneath both as the overflow fallback. */
.card__title:lang(de), .resp-card__title:lang(de) { hyphens: auto; }

/* The reset zeroes every margin, so a run of body paragraphs used to sit
   at 0px and read as one wrapped block — measured on every content page,
   102 pairs across 390px and 1440px. The templates already separate the
   first paragraph from its heading with .t-body.u-mt-4 (or, inside a
   .section-head, with `.section-head > p` above); this gives the ones
   that follow the same 1rem step, so the whole run keeps one rhythm.

   Deliberately limited to the two editorial content columns, as direct
   children: the enquiry form, the cards, the pillar label/value pairs
   and the legal prose all live elsewhere or already carry their own
   spacing, and none of them should move. A paragraph that asks for a
   different step with a u-mt-* utility keeps it — without the :not(),
   this rule's three classes would outweigh the utility's one and quietly
   shrink the 2rem breaks on Work With Us to 1rem.

   This replaces the `#home-proof-title ~ .t-body + .t-body` rule, which
   set the identical value on that homepage section alone; those
   paragraphs are direct children of .split__content and are covered
   here, at 1rem as before. */
.container-text > .t-body + .t-body:not([class*="u-mt-"]),
.split__content > .t-body + .t-body:not([class*="u-mt-"]) {
  margin-top: var(--space-4);
}

/* ---- Utilities --------------------------------------------------- */
.u-center { text-align: center; }
.u-measure { max-width: var(--container-text); margin-inline: auto; }
.u-mt-4 { margin-top: var(--space-4); }
.u-mt-6 { margin-top: var(--space-6); }
.u-mt-8 { margin-top: var(--space-8); }

/* ---- Buttons ----------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  max-width: 100%;
  overflow-wrap: anywhere;
  padding: .85em min(1.5em, 24px);
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  font-size: var(--fs-small);
  letter-spacing: .02em;
  text-decoration: none;
  border: 1px solid transparent;
  border-radius: var(--radius-pill);
  transition: background var(--dur-fast) var(--ease),
              color var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease),
              transform var(--dur-fast) var(--ease);
}
.btn > span:not(.btn__arrow) { min-width: 0; }
.btn--primary { background: var(--accent); color: #fff; }
.btn--primary:hover { background: var(--accent-dark); }
/* The secondary action sits below the primary, not beside it: muted label and
   a hairline-weight border instead of ink on a near-text-strength rule. Size,
   padding and hit area are untouched, so it stays as tappable and as
   keyboard-reachable as the primary; only the visual weight changes. */
.btn--outline {
  background: transparent;
  color: var(--muted);
  border-color: color-mix(in srgb, var(--muted) 32%, #fff);
}
.btn--outline:hover { border-color: var(--accent); color: var(--accent); }
.btn--block { display: flex; width: 100%; justify-content: center; }
.btn__arrow { transition: transform var(--dur-fast) var(--ease); }
.btn:hover .btn__arrow { transform: translateX(3px); }

/* Tertiary text link — for in-section links that shouldn't carry full
   button weight (e.g. "See How We Work", "Explore Capabilities").
   Foundation only: not yet applied in any template. */
.link-quiet {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  color: var(--accent);
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  font-size: var(--fs-small);
  text-decoration: underline;
  text-decoration-color: transparent;
  text-underline-offset: .25em;
  transition: text-decoration-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.link-quiet:hover { text-decoration-color: currentColor; color: var(--accent-dark); }

/* ---- Header ------------------------------------------------------ */
/* The translucent bar is painted by ::before rather than by the header
   itself. backdrop-filter (like filter) makes an element the containing
   block for its position:fixed descendants, which is how the mobile
   drawer ended up sized and placed against the 66px header box instead
   of the viewport. Moving the effect to a pseudo-element keeps the exact
   same appearance without that side effect. */
.site-header {
  position: sticky;
  top: 0;
  z-index: var(--z-nav);
  border-bottom: 1px solid var(--line);
}
.site-header::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: rgba(255, 255, 255, .9);
  backdrop-filter: saturate(140%) blur(8px);
}
.site-header__wrap {
  display: flex;
  align-items: center;
  gap: var(--space-5);
  min-height: var(--nav-h);
  max-width: var(--container-wide);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.site-logo {
  font-family: var(--font-display);
  font-weight: var(--fw-black);
  font-size: 1.35rem;
  line-height: 1.2;
  letter-spacing: .02em;
  color: var(--ink);
  text-decoration: none;
}
.site-logo em { font-style: normal; color: var(--accent); }

.site-nav { margin-inline-start: auto; }
/* Quote CTA shown inside the mobile/tablet drawer only; the desktop
   CTA lives in .site-header__right. Hidden on desktop by default. */
.site-nav__cta { display: none; }
.site-nav__list { display: flex; align-items: center; gap: var(--space-5); }
.site-nav__link {
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  font-size: .95rem;
  color: var(--muted);
  text-decoration: none;
  padding-block: var(--space-2);
  transition: color var(--dur-fast) var(--ease);
}
.site-nav__link:hover { color: var(--ink); }
.site-nav__link[aria-current="page"] { color: var(--accent); }

/* Nav dropdown (Divisions) — desktop absolute menu, mobile flows in the drawer */
.nav-dropdown { position: relative; }
.nav-dropdown summary { list-style: none; }
.nav-dropdown__trigger { display: inline-flex; align-items: center; gap: .5rem; }
.nav-dropdown__trigger::-webkit-details-marker { display: none; }
.nav-dropdown__menu { display: none; position: absolute; left: 0; top: calc(100% + 6px); min-width: 220px; padding: var(--space-2); background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow-lg); z-index: var(--z-overlay); }
.nav-dropdown[open] .nav-dropdown__menu { display: block; }
.nav-dropdown__menu li a { display: block; padding: var(--space-2) var(--space-3); color: var(--body); text-decoration: none; border-radius: var(--radius-sm); }
.nav-dropdown__menu li a:hover { background: var(--panel-2); color: var(--ink); }

.site-header__right { display: flex; align-items: center; gap: var(--space-4); }

.nav-toggle {
  display: none;
  min-width: 44px;
  min-height: 44px;
  flex-shrink: 0;
  margin-inline-start: auto;
  padding: var(--space-2);
  background: transparent;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  color: var(--ink);
}
.nav-toggle svg { width: 24px; height: 24px; }

/* Language switcher (native <details>) */
.lang-switch { position: relative; }
.lang-switch__trigger {
  display: inline-flex;
  min-height: 44px;
  align-items: center;
  gap: var(--space-1);
  list-style: none;
  padding: var(--space-2) var(--space-3);
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  font-size: .85rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  color: var(--ink);
}
.lang-switch__trigger::-webkit-details-marker { display: none; }
/* display:none is not the browser's own closed-<details> default here:
   Chromium hides non-summary content of a closed <details> by making it
   unrendered (content-visibility), which still leaves a laid-out box that
   getClientRects() reports as non-empty. nav.js's focus-trap and legal.js's
   focus-trap both use getClientRects() > 0 as "really focusable right now"
   (the same test that correctly reads .nav-dropdown__menu below, because
   that one already sets display:none/block explicitly). Without an
   explicit toggle here, the four language links stayed in that computed
   "rendered" set while closed, so the header's Tab-trap could compute them
   as its last focusable item and call .focus() on an element the browser
   refuses to actually focus — Shift+Tab from the header logo then hit
   preventDefault() with no working target and went nowhere (a real
   keyboard trap). The same permanently-laid-out box was also what a 200%
   browser zoom on /contact/ measured as horizontal overflow. Mirrors
   .nav-dropdown__menu exactly. */
.lang-switch__menu {
  display: none;
  position: absolute;
  right: 0;
  margin-top: var(--space-2);
  min-width: 180px;
  padding: var(--space-2);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  z-index: var(--z-overlay);
}
.lang-switch[open] .lang-switch__menu { display: block; }
.lang-switch__opt {
  display: flex;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  text-decoration: none;
  color: var(--body);
  font-size: .9rem;
}
.lang-switch__opt span { color: var(--muted); font-weight: var(--fw-semibold); }
.lang-switch__opt:hover { background: var(--panel-2); }
.lang-switch__opt[aria-current="true"] { color: var(--accent); }

/* ---- Hero -------------------------------------------------------- */
.hero { padding-block: clamp(2.5rem, 4vw, 4rem); }
.hero__inner { min-width: 0; max-width: none; text-align: left; }
/* A hero with no media column (Contact, Work With Us) would otherwise
   let the H1 and intro run the full width of the wide hero band.
   Constrain the text block so a media-less hero still reads as a
   composed unit; the two-column .hero--asym heros are unaffected. */
.hero:not(.hero--asym) .hero__inner { max-width: 46rem; }
.hero--center .hero__inner { margin-inline: auto; max-width: 46rem; text-align: center; }
.hero__title { font-size: var(--fs-h1); font-weight: var(--fw-black); margin-top: var(--space-3); }
.hero__sub { max-width: 65ch; font-size: var(--fs-lead); color: var(--muted); margin-top: var(--space-5); }
.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  margin-top: var(--space-6);
}
.hero--center .hero__actions { justify-content: center; }
.hero__actions--center { justify-content: center; }

/* Enquiry pages lead directly into the contact route. */
.hero--enquiry { padding-block: var(--section-y-compact); }
.enquiry-email { padding: var(--space-6); }
.enquiry-email__address {
  display: inline-block;
  font-size: var(--fs-lead);
  font-weight: var(--fw-medium);
  overflow-wrap: anywhere;
}

/* Asymmetric hero layout for editorial composition. align-items:start
   (not center) so the media block's top edge lines up with the
   headline instead of floating mid-column — the placeholder/photo
   rarely matches the text block's height exactly, and centering it
   left visible empty space above and below instead of one clean gap
   at the bottom. */
.hero--asym { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: clamp(var(--space-5), 4vw, var(--space-8)); align-items: start; }
.hero--asym > .hero__media { width: 100%; min-width: 0; }
.hero--division {
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.02fr);
  align-items: start;
  row-gap: var(--space-6);
  padding-block: clamp(2rem, 3vw, 3.5rem);
}
.hero--division .hero__title { margin-top: var(--space-2); }
.hero--division .hero__sub { margin-top: var(--space-4); }
.hero--division .hero__actions { margin-top: var(--space-5); }
.hero--division .trust-line { margin-top: var(--space-5); }
.hero--division > .hero__media { align-self: start; }
.hero--division > .hero__media > .media,
.hero--division > .hero__media > .media__picture { width: 100%; height: auto; aspect-ratio: 3 / 2 !important; }
.hero--division > .hero__media > .media__picture img { width: 100%; height: 100%; object-fit: cover; }
.hero__media { display: block; justify-self: end; }
.hero__media .media { width: 100%; height: auto; border-radius: 0; border: none; box-shadow: none; background: var(--panel-2); overflow: hidden; }
.hero__media .media[data-label]::after { font-size: var(--fs-caption); text-transform: uppercase; color: var(--muted); }
.media--hero { aspect-ratio: 16 / 10; overflow: hidden; }
.media--detail { aspect-ratio: 4 / 5; overflow: hidden; }
.media--landscape { aspect-ratio: 3 / 2; overflow: hidden; }
.media img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* ---- Trust line -------------------------------------------------- */
.trust-line {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3) var(--space-6);
  margin-top: var(--space-4);
  font-size: var(--fs-small);
  color: var(--muted);
}
.trust-line li { position: relative; padding-left: var(--space-4); min-width: 0; max-width: 100%; }
.trust-line li::before {
  content: "";
  position: absolute;
  left: 0; top: .62em;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--accent);
}

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

/* Lone product group (e.g. Hospitality g4) renders in its own grid--3;
   centre the single card so it reads as intentional, not orphaned.
   CSS-only — no change to division.html or the copy. */
.grid--3:has(> :only-child) {
  grid-template-columns: minmax(0, calc((var(--container-standard) - 2 * var(--space-5)) / 3));
  justify-content: center;
}

/* ---- Split section ---------------------------------------------- */
.split {
  display: grid;
  grid-template-columns: minmax(320px, 55%) 1fr;
  gap: var(--space-8);
  align-items: start;
}
.split__content { min-width: 0; }
/* justify-self must stay stretch: any other value sizes the grid item to
   its content, and .media (width:100% with only an aspect-ratio) then has
   nothing to resolve against and collapses to a few pixels — which is why
   every split section rendered an empty image column. */
.split__media { min-width: 0; }
/* Visual-only reversal (media left / content right) for editorial
   rhythm between consecutive split sections — DOM order (and so
   reading/tab order) is unchanged; only the rendered position moves.
   The track sizes swap with it so the text keeps the wider column
   instead of inheriting the one meant for the media. */
.split--reverse { grid-template-columns: 1fr minmax(320px, 55%); }
.split--reverse > .split__media { order: -1; }

/* ---- Cards ------------------------------------------------------- */
.card {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  overflow: hidden;
}
/* Keep room for enlarged labels instead of doubling the empty inset too. */
.card__body { padding: min(var(--space-6), 32px); }
.card__bar { display: inline-block; width: 42px; height: 3px; border-radius: 3px; background: var(--accent); margin-bottom: var(--space-4); }
.card__icon { width: 40px; height: 40px; color: var(--accent); margin-bottom: var(--space-4); }
/* Card titles name a thing — a division, a cooperation type, a product
   group — so they are headings and speak in the display face, like
   .division-card__title and .group-list__title already do. Weight and
   size are unchanged. .t-h3 keeps the body face deliberately: it is the
   generic sub-heading, not a card title, and is out of scope here. */
.card__title { font-family: var(--font-display); font-weight: var(--fw-bold); font-size: var(--fs-h3); }
.card__subtitle { font-size: var(--fs-small); color: var(--muted); margin-top: var(--space-1); }
.card__text { color: var(--muted); margin-top: var(--space-3); }
.card__media { aspect-ratio: 16 / 9; background: var(--panel-2); }
.card__link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-4);
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  font-size: var(--fs-small);
  color: var(--accent);
}

/* Divisions editorial grid */
.divisions-grid { grid-template-columns: repeat(2, 1fr); gap: var(--space-6); }
.division-card {
  display: block;
  text-decoration: none;
  color: inherit;
  border: 1px solid var(--line);
  border-top: 3px solid var(--accent);
  border-radius: var(--radius-card);
  overflow: hidden;
  background: var(--surface);
  transition: border-color var(--dur-fast) var(--ease);
}
/* 16:10 matches the aspect ratio the four home-card slots declare in
   src/data/images.json, so the wrapper and the slot agree whether the card
   shows a placeholder or a real photo. Change both together, or the
   inline ratio the manifest emits wins and the two disagree. Flatter
   than the former 3:2 so four cards fit one row at 1280px and above
   without the media taking over the card. */
.division-card__media { width: 100%; aspect-ratio: 16/10; background: var(--accent-soft); display: block; }
/* Each card already names its division in text, so colour never carries
   information on its own here. The tint only makes the four cards easier
   to tell apart at a glance while the photo slots are still empty; a real
   photo covers it completely. Alphas are .08–.10, so the placeholder
   label keeps its contrast. */
.division-card__media .media { background: var(--accent-soft); }
.division-card__media .media img { object-fit: cover; }
.division-card:hover { border-color: var(--accent); }
.division-card__body { padding: var(--space-5); }
/* The card carries a division name, so it speaks in the display face like
   every other heading on the page. At 1.1rem in the body face it sat below
   its own description and did not move between 390px and 1440px, while the
   section heading above it grew from 28.8px to 41.6px. Sized here for
   desktop; the phone step is in the 767px tier. */
.division-card__title {
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  font-size: 1.75rem;
  line-height: 1.1;
  color: var(--ink);
  margin-bottom: var(--space-1);
}
/* Title and subtitle read as one unit; the description starts a new one. */
.division-card__subtitle { font-size: .95rem; color: var(--muted); margin-bottom: var(--space-4); }
.division-card__text { color: var(--body); }

/* ============================================================
   RESPONSIVE FOUNDATION — three deliberate tiers, each with its
   own rules rather than one shrinking desktop:
     ≤1279  tablet landscape / small desktop
     ≤1023  tablet portrait
     ≤767   mobile
   Section-rhythm tokens are redefined at :root for each tier, so
   every current and future .section / .section--compact /
   .section--major becomes more compact automatically — no
   per-selector overrides needed.
   ============================================================ */
@media (max-width: 1279px) {
  :root {
    --section-y-compact: clamp(1.75rem, 3.5vw, 2.5rem);
    --section-y:         clamp(2.25rem, 4.5vw, 3.25rem);
    --section-y-major:   clamp(3rem, 5.5vw, 4.5rem);
  }
  .grid--4 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  /* These gaps are fixed (not fluid) in the base rules, so they never
     eased on their own between 1500px and 980px. Tighten them
     deliberately for this band instead of leaving 1024px to inherit
     desktop spacing unchanged. */
  .split { gap: var(--space-6); }
  .hero--asym { gap: var(--space-6); }
  /* 6-step process line wraps to 3x2; the straight connector can't
     span two rows, so it's dropped and the numbering carries the
     sequence. The 4-step variant still fits on one row here. */
  .process-line { grid-template-columns: repeat(3, minmax(0, 1fr)); row-gap: var(--space-6); }
  .process-line__step:not(:last-child)::after { display: none; }
  .process-line--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* ---- Process line (connected workflow) --------------------------- */
/* A sequence, not a grid of independent cards. The step count drives
   the columns through --steps, so the same component serves the 6-step
   homepage overview and the 4-step Contact / Work-With-Us sequences.
   The connector is drawn per step (badge centre to the next badge
   centre) rather than as one line behind the row, so it can never fall
   out of alignment with the badges and needs no hardcoded background
   colour to sit on. */
.process-line {
  --steps: 6;
  display: grid;
  grid-template-columns: repeat(var(--steps), minmax(0, 1fr));
  gap: var(--space-5);
}
.process-line--4 { --steps: 4; }
.process-line__step {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  text-align: center;
}
/* Connector: from this badge's centre across the gap to the next
   badge's centre. Hidden for the last step and whenever the line wraps
   to more than one row (see responsive tiers), where a straight
   horizontal rule would be wrong. */
.process-line__step:not(:last-child)::after {
  content: "";
  position: absolute;
  top: 21px;
  left: 50%;
  width: calc(100% + var(--space-5));
  height: 2px;
  background: var(--line);
  z-index: 0;
}
.process-line__num {
  position: relative;
  z-index: 1;
  display: inline-grid;
  place-items: center;
  width: 44px;
  height: 44px;
  flex: none;
  border-radius: 50%;
  background: var(--surface);
  border: 2px solid var(--accent);
  color: var(--accent);
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  font-size: 1.05rem;
}
.process-line__title { font-family: var(--font-body); font-weight: var(--fw-bold); font-size: 1.02rem; line-height: var(--lh-snug); color: var(--ink); margin-top: var(--space-1); overflow-wrap: break-word; }
/* At --fs-small (14.08px) these four steps read as captions, but they
   carry real content — material responsibility, sample approval, quality
   control. 1rem sits between --fs-small and --fs-body, which have no step
   in between; the slightly tighter line-height keeps the block compact in
   a 266px column (the section grows by ~33px at 1440). */
.process-line__text { font-size: 1rem; line-height: 1.6; color: var(--muted); }

.card--feature { box-shadow: var(--shadow-md); }
.card--interactive {
  text-decoration: none;
  transition: box-shadow var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.card--interactive:hover {
  box-shadow: 0 2px 8px -4px rgba(43,47,56,.05);
  border-color: color-mix(in srgb, var(--accent) 25%, var(--line));
}
.card--interactive:hover .btn__arrow { transform: translateX(3px); }

/* Responsive info card (holds a check-list) */
.resp-card { padding: var(--space-6); }
.resp-card__title { font-family: var(--font-display); font-weight: var(--fw-bold); font-size: var(--fs-h3); margin-bottom: var(--space-3); }

/* Form panel: the enquiry forms are a .card used directly (no
   .card__body), so they carry their own padding token instead of the
   former inline style="padding:2rem". */
.form-card { padding: var(--space-7); }

/* ---- Pillars ----------------------------------------------------- */
.pillar-list { display: grid; gap: var(--space-5); }
.pillar { position: relative; padding-left: var(--space-6); }
.pillar__dot { position: absolute; left: 0; top: .35em; width: 12px; height: 12px; border-radius: 50%; background: var(--accent); }
.pillar__name { font-family: var(--font-body); font-weight: var(--fw-bold); font-size: 1.1rem; color: var(--ink); }
.pillar__desc { color: var(--muted); margin-top: var(--space-1); }

/* ---- Highlights -------------------------------------------------- */
.highlight {
  padding: var(--space-4) var(--space-5);
  border-left: 3px solid var(--accent);
  background: var(--accent-soft);
  border-radius: var(--radius-sm);
  color: var(--body);
}
.highlight--muted {
  border-left-color: var(--muted);
  background: var(--panel-2);
  color: var(--muted);
}

/* ---- Check list -------------------------------------------------- */
.check-list { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-2) var(--space-5); }
/* Single-column variant for narrow contexts (inside cards and split
   columns) — replaces the inline grid-template-columns:1fr overrides
   that were repeated across the templates. */
.check-list--stack { grid-template-columns: 1fr; }
.check-list li { position: relative; padding-left: var(--space-5); color: var(--body); overflow-wrap: break-word; min-width: 0; }
.check-list li::before {
  content: "";
  position: absolute;
  left: 0; top: .55em;
  width: 12px; height: 7px;
  border-left: 2px solid var(--accent);
  border-bottom: 2px solid var(--accent);
  transform: rotate(-45deg);
}

/* ---- Process steps ---------------------------------------------- */
/* min-width:0 lets the text column shrink below its longest word; without
   it a flex item keeps min-width:auto and pushed the step heading past the
   viewport on narrow screens (German step titles at 360px). */
.step-head { display: flex; align-items: center; gap: var(--space-4); }
.step-head > :not(.step-num) { min-width: 0; }
.step-num {
  flex: none;
  display: inline-grid;
  place-items: center;
  width: 46px; height: 46px;
  border-radius: 50%;
  background: var(--accent);
  color: #fff;
  font-family: var(--font-display);
  font-weight: var(--fw-black);
  font-size: 1.15rem;
}

/* ---- Media placeholders / pictures ------------------------------ */
.media {
  position: relative;
  /* <picture> is inline by default and the placeholder is a <div>. Both
     carry .media, so the box has to be declared here rather than relying
     on the element — otherwise an approved slot lays out as a line box
     and the aspect-ratio never takes effect. */
  display: block;
  width: 100%;
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}
/* Honest placeholder label for pending imagery. */
.media[data-label]::after {
  content: attr(data-label);
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-size: var(--fs-small);
  color: var(--muted);
  letter-spacing: .02em;
}
/* .media img base rule already declared above (with display:block) —
   this duplicate (main.css, faithful-recovery pass) has been removed. */

/* ---- FAQ --------------------------------------------------------- */
.faq { display: grid; gap: var(--space-3); max-width: 820px; margin-inline: auto; }
.faq__item { border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); overflow: hidden; }
.faq__item h3 { margin: 0; }
.faq__trigger {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  width: 100%;
  padding: var(--space-4) var(--space-5);
  background: transparent;
  border: 0;
  text-align: left;
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  font-size: 1.05rem;
  color: var(--ink);
}
.faq__trigger > :first-child { min-width: 0; }
.faq__icon { flex: none; font-size: 1.3rem; color: var(--accent); transition: transform var(--dur-fast) var(--ease); }
.faq__trigger[aria-expanded="true"] .faq__icon { transform: rotate(45deg); }
.faq__panel-inner { padding: 0 var(--space-5) var(--space-5); color: var(--muted); }
/* Without JS the answers are open and readable; enhancement collapses them. */
.faq[data-enhanced] .faq__panel[hidden] { display: none; }

/* ---- Forms ------------------------------------------------------- */
.form-fieldset { border: 0; padding: 0; margin-top: var(--space-6); }
.form-fieldset:first-of-type { margin-top: 0; }

/* Optional-detail disclosure. Native <details>: keyboard-operable and
   fully functional without JavaScript, and the fields inside keep their
   values — and keep being submitted — while it is closed. */
.form-details { margin-top: var(--space-6); border-top: 1px solid var(--line); padding-top: var(--space-5); }
.form-details__summary {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  cursor: pointer;
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  font-size: var(--fs-small);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--accent);
  list-style: none;
}
.form-details__summary::-webkit-details-marker { display: none; }
.form-details__summary::before {
  content: "+";
  display: inline-grid;
  place-items: center;
  width: 1.5em; height: 1.5em;
  border: 1px solid currentColor;
  border-radius: 50%;
  font-size: .95em;
  line-height: 1;
}
.form-details[open] .form-details__summary::before { content: "\2013"; }
.form-details__summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.form-details__note { margin-top: var(--space-3); }
.form-fieldset__legend {
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  font-size: var(--fs-h3);
  color: var(--ink);
  padding: 0;
  margin-bottom: var(--space-4);
}
.form-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-5); }
/* Fields inside one row had no separation at all — they touched. A step
   below the row gap keeps them grouped without colliding. */
.form-row { grid-column: 1 / -1; display: grid; gap: var(--space-4); }
.field { display: grid; gap: var(--space-2); }
.field__label { font-weight: var(--fw-medium); font-size: var(--fs-small); color: var(--ink); }
.field__req { color: var(--accent); margin-left: 2px; }
.field__control {
  width: 100%;
  padding: .7em .9em;
  font: inherit;
  font-size: var(--fs-small);
  color: var(--body);
  background: var(--field);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  transition: border-color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
}
.field__control:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.field__control:disabled { opacity: .55; cursor: not-allowed; background: var(--panel-2); }
select.field__control { appearance: none; background-image: linear-gradient(45deg, transparent 50%, var(--muted) 50%), linear-gradient(135deg, var(--muted) 50%, transparent 50%); background-position: calc(100% - 20px) 1.15em, calc(100% - 14px) 1.15em; background-size: 6px 6px, 6px 6px; background-repeat: no-repeat; padding-right: 2.4em; }
textarea.field__control { min-height: 8rem; resize: vertical; }
.field__hint { font-size: var(--fs-caption); color: var(--muted); }
.field--check { grid-template-columns: auto 1fr; align-items: start; gap: var(--space-3); }
/* Consent box was 14x14px — below any reasonable touch target. The label
   stays the larger hit area and the browser's own focus ring is left
   intact. */
.field--check input { margin-top: .15em; width: 1.35em; height: 1.35em; accent-color: var(--accent); }
.form-note { font-size: var(--fs-caption); color: var(--muted); margin-top: var(--space-3); }
.form-status { margin-top: var(--space-4); padding: var(--space-4); border-radius: var(--radius-sm); font-size: var(--fs-small); }
.form-status[data-state="pending"] { background: var(--panel-2); color: var(--muted); }
.form-status[data-state="success"] { background: rgba(30, 92, 46, .1); color: #1e5c2e; }
.form-status[data-state="error"] { background: var(--accent-soft); color: var(--accent-dark); }
/* Honeypot: visually and from assistive tech, but present in the DOM. */
.form-trap { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* ---- Legal (static sections → enhanced overlays) ---------------- */
.legal-set { }
.legal { padding-block: var(--space-6); }
.legal__box { max-width: var(--container-text); margin-inline: auto; padding-inline: var(--gutter); }
.legal__title { font-size: var(--fs-h2); }
.legal__body { margin-top: var(--space-4); color: var(--body); }
.legal__body :is(h2, h3, h4) { margin-top: var(--space-5); }
.legal__body p, .legal__body ul { margin-top: var(--space-3); }
.legal__body ul { list-style: disc; padding-left: var(--space-5); }
.legal__body a { color: var(--accent); }
.legal__close { display: none; }

/* When enhanced, each panel becomes a centred modal over a backdrop. */
.legal-set[data-enhanced] .legal {
  position: fixed;
  inset: 0;
  z-index: var(--z-overlay);
  display: grid;
  place-items: center;
  padding: var(--gutter);
  background: rgba(26, 29, 35, .55);
}
.legal-set[data-enhanced] .legal[hidden] { display: none; }
.legal-set[data-enhanced] .legal__box {
  position: relative;
  max-height: min(86vh, 900px);
  overflow: auto;
  margin: 0;
  padding: var(--space-8);
  background: var(--surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xl);
}
.legal-set[data-enhanced] .legal__close {
  position: absolute;
  top: var(--space-4);
  right: var(--space-4);
  display: inline-grid;
  place-items: center;
  width: 40px; height: 40px;
  background: var(--panel-2);
  border: 0;
  border-radius: 50%;
  font-size: 1.1rem;
  color: var(--ink);
}
/* Scroll lock while an overlay is open (set by legal.js / nav.js). */
.has-legal-open, .has-nav-open { overflow: hidden; }

/* ---- Footer ------------------------------------------------------ */
.site-footer { background: var(--ink); color: #cfd4dc; padding-block: var(--space-8) var(--space-6); margin-top: var(--space-9); }
.site-footer a { color: #cfd4dc; text-decoration: none; }
.site-footer a:hover { color: #fff; }
.site-footer__top { display: grid; grid-template-columns: 1.2fr 2fr; gap: var(--space-8); }
.site-footer__brand .site-logo { color: #fff; }
.site-footer__brand .site-logo em { color: #fff; }
.site-footer__tagline { color: #9aa2ad; margin-top: var(--space-4); max-width: 34ch; font-size: var(--fs-small); }
.site-footer__cols { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-6); }
.site-footer__col h2 { font-size: var(--fs-small); text-transform: uppercase; letter-spacing: var(--tracking-wide); color: #fff; }
.site-footer__col ul { margin-top: var(--space-4); display: grid; gap: var(--space-2); }
.site-footer__col a { font-size: var(--fs-small); }
.site-footer__bottom {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--space-3);
  margin-top: var(--space-8);
  padding-top: var(--space-5);
  border-top: 1px solid rgba(255, 255, 255, .1);
  font-size: var(--fs-caption);
  color: #9aa2ad;
}
.site-footer__legal { margin-top: var(--space-3); font-size: var(--fs-caption); color: #9aa2ad; }
.site-footer__legal a { text-decoration: underline; }

/* ---- 404 language links ----------------------------------------- */
.nf-langs {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-3) var(--space-5);
  margin-top: var(--space-5);
}
.nf-langs a { color: var(--accent); text-decoration: none; font-family: var(--font-display); font-weight: var(--fw-semibold); }
.nf-langs a:hover { text-decoration: underline; }

/* ---- Division themes: swap the accent, components follow --------- */
.theme-sport       { --accent: var(--div-sport);       --accent-dark: var(--div-sport-dark);       --accent-soft: rgba(212, 43, 43, .08); }
.theme-marine      { --accent: var(--div-marine);      --accent-dark: var(--div-marine-dark);      --accent-soft: rgba(15, 45, 74, .08); }
.theme-hospitality { --accent: var(--div-hospitality); --accent-dark: var(--div-hospitality-dark); --accent-soft: rgba(140, 99, 24, .1); }
.theme-event       { --accent: var(--div-event);       --accent-dark: var(--div-event-dark);       --accent-soft: rgba(30, 92, 46, .08); }

/* ---- Reveal-on-scroll (enhancement only) ------------------------ */
/* Content is fully visible without JS; .has-reveal is only ever added
   by components.js, and never under prefers-reduced-motion. */
.has-reveal .reveal { opacity: 0; transform: translateY(14px); transition: opacity var(--dur) var(--ease-out), transform var(--dur) var(--ease-out); }
.has-reveal .reveal.is-visible { opacity: 1; transform: none; }

@media (max-width: 1023px) {
  /* Keep the fixed drawer below the header when users enlarge text. */
  :root { --nav-h: max(66px, 4.125rem); }
  .site-header__wrap { gap: min(var(--space-5), 3vw); padding-inline: max(5vw, 24px); }
  .nav-toggle { display: inline-flex; order: 3; margin-inline-start: 0; }

  /* Keep the utility cluster (language switcher) in the top bar so it
     stays reachable — previously the whole cluster was hidden here,
     which removed the language switcher entirely below 1024px on a
     four-language site. Only the desktop inline CTA is hidden; the
     quote CTA reappears as a full-width button inside the drawer. */
  .site-header__right { display: flex; order: 2; margin-inline-start: auto; }
  .site-header__cta { display: none; }
  .site-nav__cta { display: flex; margin-top: var(--space-5); }

  /* Primary navigation becomes a drawer, opened by the toggle.

     The closed drawer is taken out of the layout with display:none
     rather than parked off-screen with transform alone. A translated
     box is still laid out: it kept its own width in the document's
     scrollable overflow (the 320px of horizontal scroll that existed
     below 1024px on every page) and kept its links in the tab order
     and in the accessibility tree while the menu was closed.

     display is a discrete property, so the slide-in is preserved with
     allow-discrete + @starting-style where those are supported, and
     degrades to an instant open where they are not. */
  .site-nav {
    display: none;
    position: fixed;
    inset: var(--nav-h) 0 0 auto;
    width: min(320px, 82vw);
    margin: 0;
    padding: var(--space-6) var(--gutter);
    background: var(--surface);
    border-left: 1px solid var(--line);
    box-shadow: var(--shadow-xl);
    transform: translateX(100%);
    transition: transform var(--dur) var(--ease), display var(--dur) allow-discrete;
    overflow-y: auto;
    /* The page behind is scroll-locked while the drawer is open; keep
       drawer scrolling from chaining out to it on short screens. */
    overscroll-behavior: contain;
  }
  .site-nav.is-open { display: block; transform: translateX(0); }
  @starting-style {
    .site-nav.is-open { transform: translateX(100%); }
  }
  .site-nav__list { flex-direction: column; align-items: stretch; gap: var(--space-3); }
  .site-nav__link { display: flex; align-items: center; min-height: 44px; font-size: 1.1rem; overflow-wrap: anywhere; }
  /* A drawer disclosure must push subsequent links down, not cover them. */
  .nav-dropdown__menu { position: static; min-width: 0; margin-top: var(--space-2); box-shadow: none; }

  .grid--3, .grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .grid--3:has(> :only-child) { grid-template-columns: minmax(0, 1fr); }
  /* 4-step process line goes 2x2 at tablet portrait. */
  .process-line--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: var(--space-6); }
  .hero--asym { grid-template-columns: 1fr; gap: var(--space-6); }
  .hero--asym > .hero__inner { padding-inline: 0; }
  .hero--asym > .hero__media { justify-self: stretch; }
  /* Division hero collapses to one column here (moved from the old,
     arbitrary 1119px cutoff — the whole 1024–1279 tablet-landscape
     band now keeps the two-column layout deliberately; see above). */
  .hero--division {
    grid-template-columns: 1fr;
    row-gap: var(--space-5);
    padding-block: clamp(1.5rem, 4vw, 2.5rem);
  }
  .hero--division .hero__actions {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-3);
  }
  .hero--division .trust-line {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--space-2) var(--space-4);
  }
  .hero--division > .hero__media { justify-self: stretch; }
  .split { grid-template-columns: 1fr; gap: var(--space-6); }
  /* Once .split collapses to one column, always show text first
     regardless of the desktop-only editorial reversal above. */
  .split--reverse > .split__media { order: 0; justify-self: stretch; }
  .site-footer__top { grid-template-columns: 1fr; gap: var(--space-6); }
}

/* Below the drawer breakpoint the primary navigation is display:none and
   only nav.js can reveal it, by adding .is-open. With scripting off that
   never happens: the nav is unreachable from the header and the hamburger
   is a control that cannot do anything (measured in Chromium and in
   WebKitGTK, round 20 — 10 nav links present, 0 rendered, toggle rendered
   with aria-expanded="false"). The footer still carries all nine routes,
   so the site stayed navigable, but the header did not.

   The fix is the standard CSS-only one rather than a JS-set marker class:
   (scripting: none) is evaluated at parse time, so there is no flash of an
   expanded nav on the JS path, and neither nav.js nor the document shell
   has to change. Everything a scripted browser sees is untouched — this
   block simply never applies there.

   Residual, deliberately not covered here: scripting enabled but main.js
   failing to load. (scripting: enabled) still matches then, so the drawer
   stays script-dependent. Closing that too needs a marker the script sets,
   which is a separate decision (§15). */
@media (max-width: 1023px) and (scripting: none) {
  /* The expanded fallback must scroll away with the page. */
  .site-header { position: static; }
  .nav-toggle { display: none; }
  .site-nav {
    display: block;
    position: static;
    width: auto;
    inset: auto;
    padding: 0;
    background: none;
    border-left: 0;
    box-shadow: none;
    transform: none;
    overflow-y: visible;
    flex-basis: 100%;
    order: 3;
  }
  /* The header bar becomes two rows: the logo line, then the navigation. */
  .site-header__wrap { flex-wrap: wrap; row-gap: var(--space-4); padding-block: var(--space-4); }
  .site-nav__cta { margin-top: var(--space-4); }
}

@media (max-width: 767px) {
  :root {
    --section-y-compact: clamp(1.25rem, 5vw, 1.75rem);
    --section-y:         clamp(1.75rem, 7vw, 2.5rem);
    --section-y-major:   clamp(2.25rem, 8vw, 3rem);
  }
  .grid--2, .grid--3, .grid--4 { grid-template-columns: 1fr; }
  /* One step down from the desktop 1.75rem: still clearly the card's
     headline, still below the section heading it sits under. */
  .division-card__title { font-size: 1.375rem; }
  /* Standfirsts long enough to wrap four to seven times on a phone read
     badly centred — both edges ragged, nothing for the eye to return to.
     The paragraphs carrying this class are named one by one in the
     templates; the eyebrow and heading above them stay centred and still
     sit as a title over the block. Desktop keeps the centred setting,
     where the same copy runs two or three lines. */
  .u-mobile-left { text-align: left; }
  .divisions-grid { grid-template-columns: 1fr; }
  .form-grid { grid-template-columns: 1fr; }
  /* iOS Safari zooms the page when a field smaller than 16px takes focus;
     on a 20+ field form that means pinching back after every tap. */
  .field__control { font-size: 1rem; }
  /* 48px of card padding left the inputs 244px wide on a 390px screen. */
  .form-card { padding: var(--space-5); }
  .check-list { grid-template-columns: 1fr; }
  .hero__actions { flex-direction: column; align-items: stretch; }
  .hero--division .hero__actions { align-items: stretch; }
  .hero--division .trust-line { grid-template-columns: minmax(0, 1fr); }
  .hero--center .hero__actions { align-items: center; }
  .site-footer__cols { grid-template-columns: 1fr; gap: var(--space-5); }
  .site-footer__bottom { flex-direction: column; }
  .legal-set[data-enhanced] .legal__box { padding: var(--space-6); }

  /* Process line becomes a vertical connected timeline, reusing the
     same badge — badge spans two rows on the left, title/text stack
     beside it — with a vertical rule joining consecutive badges. */
  .process-line { display: flex; flex-direction: column; gap: var(--space-6); }
  .process-line__step {
    display: grid;
    grid-template-columns: 44px minmax(0, 1fr);
    column-gap: var(--space-4);
    row-gap: var(--space-1);
    align-items: start;
    text-align: left;
  }
  .process-line__num { grid-row: 1 / 3; }
  .process-line__step:not(:last-child)::after {
    content: "";
    position: absolute;
    left: 21px;
    top: 44px;
    bottom: calc(-1 * var(--space-6));
    width: 2px;
    background: var(--line);
  }
}

/* ============================================================
   HOMEPAGE COMPOSITION
   Everything below is scoped to [data-page="home"] (emitted by
   src/components/document.html on <main>) because .hero--asym,
   .hero__media, .process-line and .check-list are shared with
   About, How We Work, Contact, Work With Us and the division
   template. .division-card / .divisions-grid are homepage-only
   and are styled in place, above.
   ============================================================ */

/* Hero. The audit measured the desktop hero at 45–60% of the first
   screen, with the next section's heading and media slot already
   visible beside it — two competing openings on one screen. Rather
   than force a min-height (a clamp tuned for one viewport leaves dead
   space at another), the media column's ratio drives the height: a
   square crop at desktop widths fills the column it is given, so the
   hero grows because something occupies it, not because it was
   padded. The text block then centres against it. */
[data-page="home"] .hero--asym { align-items: center; }
/* Up from clamp(2.4rem, 4.4vw, 3.6rem): 58px at 1440 was small against
   a 1176px band. The 2.4rem floor is unchanged, so phones keep today's
   38px exactly. */
[data-page="home"] .hero__title { font-size: clamp(2.4rem, 4.8vw, 4.5rem); }
@media (min-width: 1024px) {
  /* The slot carries an inline aspect-ratio from src/data/images.json,
     so overriding it needs !important — the same mechanism
     .hero--division already uses. The manifest keeps 16/9, which is
     what phones and tablets render. */
  [data-page="home"] .hero--asym > .hero__media > .media { aspect-ratio: 1 / 1 !important; }
  [data-page="home"] .hero__sub { max-width: 34rem; }
}

/* Four divisions in one row on the widest tier. 1280px is the
   breakpoint the four home-card entries in src/data/images.json
   already declare in their `sizes` ("(max-width: 1280px) 50vw, 25vw"),
   and it is the existing responsive tier boundary, so the grid, the
   image sizes attribute and the stylesheet's own tiers all agree.
   Below it the grid stays 2×2. */
@media (min-width: 1280px) {
  .divisions-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-5); }
}

/* Process line: left-aligned on desktop, matching the vertical
   timeline the ≤767 tier already renders. Centred text in four narrow
   columns gave the reader no edge to scan down. */
@media (min-width: 768px) {
  [data-page="home"] .process-line__step { align-items: start; text-align: left; }
  [data-page="home"] .process-line__num { width: 52px; height: 52px; font-size: 1.3rem; }
  /* Connector now runs from the badge's right edge to the next badge,
     instead of from centre to centre. */
  [data-page="home"] .process-line__step:not(:last-child)::after {
    top: 25px;
    left: 52px;
    width: calc(100% - 52px + var(--space-5));
  }
}
/* The step titles name the four stages; they are headings and now read
   in the display face like every other heading on the page. Applied at
   every width, including the mobile timeline. */
[data-page="home"] .process-line__title {
  font-family: var(--font-display);
  font-size: 1.3rem;
  line-height: var(--lh-snug);
  margin-top: var(--space-2);
}

/* Enquiry close. Source order is the mobile order — invitation, what
   to send, the MOQ note, then the action — and the desktop grid only
   places those same four blocks into two columns. No new content. */
.home-close { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-6); }
.home-close__head > .t-lead { max-width: 68ch; }
@media (min-width: 900px) {
  .home-close {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-template-areas: "head list" "cta note";
    column-gap: clamp(var(--space-7), 5vw, var(--space-9));
    row-gap: var(--space-7);
    align-items: start;
  }
  .home-close__head { grid-area: head; }
  .home-close__list { grid-area: list; }
  .home-close__note { grid-area: note; }
  .home-close__cta  { grid-area: cta; align-self: start; }
}

/* ---- Grouped list ------------------------------------------------
   A long enumeration split into named groups. Not a card grid: the
   groups share the section's surface and are separated by a heading
   and a rule, so the grouping reads as structure rather than as
   decoration. Two columns from 768px, one column below, in source
   order. Used where a content file supplies the groups; every other
   page keeps its flat list. */
.group-list { display: grid; gap: var(--space-6); align-items: start; }
.group-list__title {
  overflow-wrap: anywhere;
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  font-size: 1.3rem;
  line-height: var(--lh-snug);
  color: var(--ink);
  padding-bottom: var(--space-2);
  border-bottom: 1px solid var(--line);
  margin-bottom: var(--space-4);
}
@media (min-width: 768px) {
  .group-list { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--space-7); row-gap: var(--space-7); }
}

/* ---- Enquiry preparation: first contact vs. detailed assessment --
   The short block is set apart by a rule and its own spacing, not by a
   card, a tint or a border box — the section already carries a tinted
   background and another panel inside it would read as decoration. */
.req-start__list { margin-top: var(--space-4); }
.req-start__label {
  font-family: var(--font-body);
  font-weight: var(--fw-bold);
  font-size: var(--fs-small);
  letter-spacing: .04em;
  text-transform: uppercase;
  /* --muted on --off still clears AA at this size; the hierarchy comes
     from the label, not from making the items themselves fainter. */
  color: var(--muted);
  margin-top: var(--space-5);
}
.req-details__intro { margin-top: var(--space-4); }
/* One level down from the A/B headings above them. */
.group-list__title--sub { font-size: 1.1rem; }

/* ---- Hospitality enquiry-preparation width -----------------------
   This one section carries four short lists and two explanatory
   paragraphs. On the narrow .container-text the two detail columns fall
   to 244px at 1440 — narrower than at 768px, because --gutter is 5vw.
   Give this section the standard container and keep every paragraph at
   a readable measure; box-sizing is border-box, so the usable width is
   the container max-width minus two gutters. */
[data-division="hospitality"] section[aria-labelledby="div-req-title"] > .container-text {
  max-width: var(--container-standard);
}
[data-division="hospitality"] section[aria-labelledby="div-req-title"] .section-head p,
[data-division="hospitality"] section[aria-labelledby="div-req-title"] .req-details p,
[data-division="hospitality"] section[aria-labelledby="div-req-title"] .req-start__list,
[data-division="hospitality"] section[aria-labelledby="div-req-title"] .highlight {
  max-width: 68ch;
}
/* Three named groups read best side by side once there is room for them;
   below that the existing two-column and single-column steps apply. */
@media (min-width: 1100px) {
  [data-division="hospitality"] section[aria-labelledby="div-req-title"] .group-list {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

/* ---- Hospitality section rhythm ---------------------------------
   Requirements, Materials and Site assessment are three consecutive
   .section--alt bands on this page, which the audit measured as
   4702px (desktop) / 5658px (mobile) of unbroken tint — the longest
   run on the page, exactly where the detail is densest. Giving the
   middle one the page surface turns it into two shorter bands with a
   visible boundary at each end. Scoped by data-division so Sport,
   Marine and Event keep their own rhythm, which does not have this
   problem. */
[data-division="hospitality"] section[aria-labelledby="div-mat-title"] {
  background: var(--surface);
  border-block: 1px solid var(--line);
}
/* .section--alt + .section--alt drops the shared rule between two tinted
   bands; here the bands are no longer adjacent, so both edges are drawn. */
[data-division="hospitality"] section[aria-labelledby="div-site-title"] { border-top: 1px solid var(--line); }

/* ================================================================
   EVENT PAGE COMPOSITION

   The Event page carried the most content of the four divisions and the
   least shape: six consecutive sections rendered the same tick list in
   the same 536px column, and Requirements + Materials + Site assessment
   formed a 4740px run of one tint. The round separates four content
   roles — the claim, the scope boundary, the product example and the
   data needed to prepare an enquiry — and gives each a structure of its
   own, so the page is read rather than scanned as a document.

   Three principles hold the block together:
     · section width and reading width are set independently; a wide
       band never widens a paragraph past its measure;
     · the three reworked sections get three different shapes, not three
       different backgrounds — head-beside-body, a panel pair, and a
       lead with a bordered terms block;
     · everything is scoped to [data-division="event"] or to a class that
       only Event's content gates into existence, so the other three
       division pages render byte-identically (verified).
   ================================================================ */

/* ---- 1 · Band rhythm --------------------------------------------
   Requirements, Materials and Site assessment are three .section--alt
   bands in a row. Giving the middle one the page surface splits the run
   into two shorter bands with a drawn boundary at each end — the same
   mechanism round 7 used on Hospitality, applied to Event's own
   sequence. .section--alt + .section--alt drops the shared rule between
   adjacent tinted bands, so the site section redraws its top edge. */
[data-division="event"] section[aria-labelledby="div-mat-title"] {
  background: var(--surface);
  border-block: 1px solid var(--line);
}
[data-division="event"] section[aria-labelledby="div-site-title"] { border-top: 1px solid var(--line); }

/* ---- 2 · Audience and project types ------------------------------
   The template's `.group-list u-mt-5` is a no-op — u-mt-5 has never been
   defined — so the two named audience groups butted straight up against
   the sentence introducing them. Restored as a real step, scoped here;
   Hospitality carries the same latent gap and is left for its own round.
   The thirteen project types are a reference list, not prose: they
   belong in a block the eye takes in at once rather than a column 13
   rows tall. Columns rather than a grid, because a grid aligns rows and
   a two-line entry then punches a hole in every other column; flowing
   the items down each column in turn also keeps the reading order. The
   head and the closing sentence stay at the reading measure. */
[data-division="event"] section[aria-labelledby="div-who-title"] .group-list {
  margin-top: var(--space-6);
}
[data-division="event"] section[aria-labelledby="div-projects-title"] > .container-text {
  max-width: var(--container-standard);
}
[data-division="event"] section[aria-labelledby="div-projects-title"] .section-head,
[data-division="event"] section[aria-labelledby="div-projects-title"] > .t-body {
  max-width: 68ch;
}
@media (min-width: 768px) {
  [data-division="event"] section[aria-labelledby="div-projects-title"] .check-list {
    display: block;
    columns: 2;
    column-gap: var(--space-7);
  }
  [data-division="event"] section[aria-labelledby="div-projects-title"] .check-list li {
    break-inside: avoid;
    margin-bottom: var(--space-2);
  }
}
@media (min-width: 1100px) {
  [data-division="event"] section[aria-labelledby="div-projects-title"] .check-list { columns: 3; }
}

/* ---- 3 · Requirements: head beside body --------------------------
   The section answers two questions — what to write first, and what the
   assessment draws on — and the second answer is much longer than the
   first. Standing the head off to the left lets the detail use the full
   band while the eyebrow, heading and intro stay legible at the top,
   and it removes the empty right-hand half the 536px column left at
   1440. Below 1024 the same source order simply stacks. */
[data-division="event"] section[aria-labelledby="div-req-title"] > .container-text {
  max-width: var(--container-wide);
}
[data-division="event"] section[aria-labelledby="div-req-title"] .section-head p,
[data-division="event"] section[aria-labelledby="div-req-title"] .req-start__lead,
[data-division="event"] section[aria-labelledby="div-req-title"] .req-details p,
[data-division="event"] section[aria-labelledby="div-req-title"] .highlight {
  max-width: 68ch;
}
@media (min-width: 1024px) {
  [data-division="event"] section[aria-labelledby="div-req-title"] > .container-text {
    display: grid;
    /* Auto-placed children fall into column 2 in source order. row-gap
       is 0 on purpose: the blocks already carry their own u-mt-* steps,
       and a grid gap would add a second, competing rhythm. */
    grid-template-columns: minmax(0, 21rem) minmax(0, 1fr);
    column-gap: var(--space-7);
    row-gap: 0;
    align-items: start;
  }
  [data-division="event"] section[aria-labelledby="div-req-title"] > .container-text > * {
    grid-column: 2;
  }
  /* The head spans further than the body will ever reach. Placing it in
     row 1 alone makes that row as tall as the head, which opened a
     200px hole above the second block; spanning it costs nothing
     because the surplus rows are empty and row-gap is 0. */
  [data-division="event"] section[aria-labelledby="div-req-title"] > .container-text > .section-head {
    grid-column: 1;
    grid-row: 1 / span 20;
  }
  /* Barlow Condensed at the section size breaks "rendezvényprojekt" and
     "Veranstaltungstermin" inside the word in a column this narrow. One
     step down fits the longest compound on all four languages and still
     reads as the section heading. */
  [data-division="event"] section[aria-labelledby="div-req-title"] .section-head .t-h2 {
    font-size: clamp(1.7rem, 2.4vw, 2.2rem);
  }
  /* First body block starts level with the heading, not below it. */
  [data-division="event"] section[aria-labelledby="div-req-title"] > .container-text > .req-start {
    margin-top: 0;
  }
}
/* The detail intro ends in a full paragraph; the three group headings
   need a step below it or they read as its continuation. */
[data-division="event"] section[aria-labelledby="div-req-title"] .group-list {
  margin-top: var(--space-6);
}
/* On a phone the three group headings carry more chrome than the ten
   short lines under them: a rule, its padding and a 1rem step each. The
   heading alone separates the groups at that width, and the blocks are
   already a stacked column, so the step between them can be smaller
   too. Type size and line height are untouched. */
@media (max-width: 639px) {
  [data-division="event"] section[aria-labelledby="div-req-title"] .group-list { gap: var(--space-5); }
  [data-division="event"] section[aria-labelledby="div-req-title"] .group-list__title {
    padding-bottom: 0;
    border-bottom: 0;
    margin-bottom: var(--space-3);
  }
  [data-division="event"] section[aria-labelledby="div-req-title"] .req-details { margin-top: var(--space-6); }
}
/* Three named groups fit side by side once the body column is wide
   enough; below that the shared two-column and one-column steps apply. */
@media (min-width: 1100px) {
  [data-division="event"] section[aria-labelledby="div-req-title"] .group-list {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

/* ---- 4 · The two starting anchors -------------------------------
   A first enquiry answers two questions, so it is set as two headed
   statements rather than a third tick list: ticks read as a checklist
   to complete, which is the impression this section exists to remove.
   The rule above each is a marker, not the distinction — the heading
   carries that, so the meaning survives without colour. */
.req-start__lead { margin-top: var(--space-3); }
/* The block heading is underlined and each anchor is topped by a rule;
   without a clear step between them the two read as one heavy band. */
.anchor-pair { display: grid; gap: var(--space-5); margin-top: var(--space-6); }
@media (min-width: 640px) {
  .anchor-pair { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-6); }
}
.anchor { border-top: 2px solid var(--accent); padding-top: var(--space-4); }
.anchor__title {
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  font-size: 1.15rem;
  line-height: var(--lh-snug);
  color: var(--ink);
}
.anchor__text { margin-top: var(--space-2); color: var(--muted); }

/* The three figures under "if already known" are things the visitor
   either has to hand or does not. They read as one short line of prose
   rather than three more ticked rows — and as prose, not as controls:
   bordered chips looked clickable, which is a promise nothing on the
   page keeps. The separator is generated, so it never reaches the
   accessibility tree or a copied selection as content. */
.known-row {
  display: flex;
  flex-wrap: wrap;
  margin-top: var(--space-2);
  color: var(--muted);
}
.known-row li + li::before {
  content: "·";
  margin: 0 var(--space-2);
}
.known-row li { min-width: 0; max-width: 100%; overflow-wrap: anywhere; }
.req-cta { margin-top: var(--space-6); }
/* Says when to send the enquiry, immediately above the button that
   sends it. */
.req-timing { margin-top: var(--space-5); color: var(--muted); }

/* ---- 5 · Materials: two named panels ----------------------------
   Material properties and components are two decisions, and they used
   to run down one column as twenty identical ticks with a single
   sentence between them. Each becomes a panel with its own heading, and
   on a wide enough band the two sit side by side, halving the section's
   height without hiding anything. */
[data-division="event"] section[aria-labelledby="div-mat-title"] > .container-text {
  max-width: var(--container-wide);
}
[data-division="event"] section[aria-labelledby="div-mat-title"] .section-head { max-width: 68ch; }
.mat-lead { color: var(--ink); max-width: 62ch; }
.mat-claim { margin-top: var(--space-5); max-width: 68ch; }
.mat-panels { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-6); margin-top: var(--space-7); }
@media (min-width: 900px) {
  .mat-panels { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-7); }
}
.mat-panel {
  min-width: 0;
  background: var(--off);
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  padding: var(--space-6);
}
.mat-panel__lead { color: var(--muted); margin-top: var(--space-1); }
/* On a phone the panel is nearly the full width, so its padding is pure
   chrome; the border and tint still tell the two material groups apart,
   which is what they are there for. */
@media (max-width: 639px) {
  .mat-panel { padding: var(--space-5); }
}
.mat-close { margin-top: var(--space-7); }
/* These paragraphs are not direct children of the content column, so the
   site-wide `.container-text > .t-body + .t-body` step does not reach
   them; they would run together exactly as the page did before. */
.mat-close > .t-body + .t-body, .site-terms > .t-body + .t-body {
  margin-top: var(--space-4);
}
.mat-close > .t-body, .mat-close > .highlight { max-width: 68ch; }

/* ---- 6 · Site assessment: lead, triggers, terms ------------------
   An optional service had grown into the longest block on the phone.
   One lead now answers "does this concern me?" and states the
   usually-not-needed case, once; three themed sentences replace eight
   near-identical triggers; and the terms group is a heading and a rule,
   not a panel. The panel had to go: it wrapped a highlight, and two
   nested boxes squeezed the boundary statement — the one thing here a
   reader must not miss — into a column two paddings deep. One emphasis,
   on that statement. The band stays narrower than the two above it,
   which closes the sequence rather than repeating it. */
[data-division="event"] section[aria-labelledby="div-site-title"] > .container-text {
  max-width: var(--container-standard);
}
[data-division="event"] section[aria-labelledby="div-site-title"] .section-head { max-width: 68ch; }
.site-lead { color: var(--ink); max-width: 62ch; }
.site-triggers__title,
.site-terms__title {
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  font-size: 1.15rem;
  line-height: var(--lh-snug);
  color: var(--ink);
  margin-bottom: var(--space-4);
}
.site-triggers__list { max-width: 74ch; }
.site-triggers__list li + li { margin-top: var(--space-3); }
.site-terms {
  margin-top: var(--space-7);
  padding-top: var(--space-6);
  border-top: 1px solid var(--line);
}
.site-terms .t-body, .site-terms .highlight { max-width: 68ch; }
.site-terms__boundary { margin-top: var(--space-4); }
.site-terms__link { margin-top: var(--space-5); }

/* ---- Reduced motion --------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  .has-reveal .reveal { opacity: 1; transform: none; }
}
