/* ===========================================================================
   TeskaLabs / LogMan.io — site stylesheet

   Type, spacing and components were read off the reference build at
   teskalabs.mysuitu.com (computed styles, Sept 2026), so the proportions are
   the brand's rather than a generic set:

     body copy   16px/24px        h1 72/68 w600 white centred
     h2 42/48 w600 accent, -.02em h3 20/26 w600 accent (card)
     buttons: pill r20, 15px w600, 2px border, 44px tall, padding 0 28px
     cards: r10, 30-40px padding
     container 1140px, section padding 60px, dark bands 100px, footer 120px

   THE GROUND IS LIGHT (Sept 2026). The page is near-white paper, the way the
   TeskaLabs apparel is: deep navy display type, one bright accent kept for
   MARKS AND GRAPHICS, and the low-poly ridge rising out of the bottom of the
   hero. A card is white ON the paper — lighter than the ground, not darker.

     --page --surface --surface-2 --sunken --hero-ground --band-ground
     --line --line-strong --line-soft --ink --ink-strong

   Palette tokens live in static/css/theme-<site>.css, loaded before this file,
   so both sites share every rule below and differ by a handful of values:
     teskalabs  accent #1e85f2, accent-ink #0d5db5, page #f4f7fb
     logman     identical to teskalabs (Sept 2026) — the sites are not
                distinguished by colour; only --art and the logo differ
   --accent is 2-3.5:1 on the paper, so it may NOT carry text: everything that
   is READ — headings, eyebrows, labels, links, button fills — takes
   --accent-ink. Never write a literal colour here; a new site must be a theme
   file, not a fork of this one.
   =========================================================================== */

:root {
  --white:       #ffffff;   /* text ON an accent fill, not a surface colour */

  /* NOTE: --page / --surface / --surface-2 / --sunken / --hero-ground /
     --band-ground / --line / --line-strong / --line-soft / --ink /
     --ink-strong are set by the theme file and deliberately NOT repeated here.
     This stylesheet loads AFTER the theme, so a "fallback" copy at this
     specificity would silently win and both sites would wear one palette. */

  /* Verdana is the company font. It is a system font (macOS, Windows, iOS),
     not self-hosted; Geneva/Tahoma are the closest built-in stand-ins and
     other platforms fall through to their default sans-serif. Verdana ships
     only regular (400) and bold (700): 500 renders as regular, 600 as bold. */
  --font: Verdana, Geneva, Tahoma, sans-serif;
  /* Headings are Montserrat Medium — the face of the TeskaLabs logo and of the
     previous teskalabs.com — in place of the bold Verdana they had. It is the
     one web font on the site and it is self-hosted (static/fonts/, see the
     @font-face below), so there is still no request to anyone else's server.
     Only the 500 weight ships: to change --heading-weight, add that weight's
     file and an @font-face for it first, or the browser will fake it. */
  --font-display: "Montserrat", Verdana, Geneva, Tahoma, sans-serif;
  --heading-weight: 500;
  --container: 1140px;

  /* Responsive scale ------------------------------------------------------
     Breakpoints (see the RESPONSIVE section at the foot of this file):
       1180px  the nav becomes a drawer
       1080px  desktop grids collapse to tablet-landscape
        880px  zigzag rows stack
        700px  tablet portrait
        560px  phone
        380px  small phone
     Gutters and vertical rhythm are fluid between those, so the breakpoints
     only ever change layout, never size: 16px gutters on a 360px phone up to
     20px past 900px, and the 60/100px section rhythm compresses to 36/56px. */
  --pad-x: clamp(16px, 0.85rem + 1.4vw, 32px);
  --section-y: clamp(44px, 1.7rem + 4.4vw, 76px);
  --band-y: clamp(56px, 2rem + 6vw, 100px);
  --header-h: 72px;          /* kept in sync with .site-header__inner */
  --radius-card: 10px;
  --radius-pill: 20px;
  --radius-panel: 20px;

  /* How big the ridge art is drawn. At full width one file's width matches the
     viewport's, which on a phone leaves a 100px-tall ridge — too small to read
     as a mountain — so narrow screens zoom in and crop the sides instead. */
  --art-size: 100% auto;

  /* Depth. On paper a card is lifted by a soft shadow tinted with the page's
     own ink — never neutral grey, which goes muddy — plus the hairline that
     cuts it out. --edge is what the dark ground needed (a lit top edge) and
     is deliberately a no-op here; the rules that use it are unchanged. */
  --shade: 8, 33, 63;
  --edge: 0 0 transparent;
  --lift: 0 1px 2px rgba(var(--shade), .05), 0 10px 24px -14px rgba(var(--shade), .17);
  --lift-hover: 0 2px 4px rgba(var(--shade), .07), 0 22px 44px -18px rgba(var(--shade), .25);
  --glow-accent: 0 0 0 1px color-mix(in srgb, var(--accent) 34%, transparent),
                 0 18px 44px -24px color-mix(in srgb, var(--accent) 60%, transparent);

  /* Four-step tint ladder, mixed from whatever accent the theme file set, so
     each site gets its own. Used by the edition cards and the matrix column
     heads to show progression before a word is read. The mix is toward
     --page, so on this light ground the ladder runs PALE -> SATURATED. */
  --tint-1: color-mix(in srgb, var(--accent) 30%, var(--page));
  --tint-2: color-mix(in srgb, var(--accent) 52%, var(--page));
  --tint-3: color-mix(in srgb, var(--accent) 76%, var(--page));
  --tint-4: var(--accent);

  color-scheme: light;       /* native controls, scrollbars and form widgets */
}

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

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
  background: var(--page);
  /* Belt and braces: nothing should overflow sideways, but if a long unbroken
     string ever does, the page must not become horizontally pannable.
     `clip` rather than `hidden` so it does not create a scroll container
     (which would break position: sticky inside the page). */
  overflow-x: clip;
}
/* Anchor targets sit below the fixed header rather than under it. */
:target { scroll-margin-top: calc(var(--header-h) + 16px); }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  color: var(--ink);
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;

  /* The node field: a 32px matrix of faint accent dots over the whole page —
     the flat version of the network in the apparel art. Barely visible on its
     own, but it is the difference between a blank fill and a surface, and it
     is what the white cards then sit ON. */
  background-color: var(--page);
  background-image: radial-gradient(color-mix(in srgb, var(--accent) 24%, transparent) 1px, transparent 1px);
  background-size: 32px 32px;
  background-position: -1px -1px;
}

/* Montserrat Medium, subset to Latin + Latin Extended-A (English, Czech,
   Polish) — 19 kB. SIL Open Font License 1.1; see static/fonts/README.md for
   the source and the command that made it. `swap` shows the heading in Verdana
   until the file arrives; base.html preloads it so that is rarely seen. */
@font-face {
  font-family: "Montserrat";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/static/fonts/montserrat-500.woff") format("woff");
}

h1, h2, h3, h4 { margin: 0 0 20px; font-family: var(--font-display); font-weight: var(--heading-weight); }

h1 {
  font-size: clamp(2.1rem, 1.1rem + 3.4vw, 4.5rem);   /* 72px at full width */
  /* 0.95 is right for a 72px display line; at phone sizes it collides, so the
     leading opens up as the type shrinks (tightened again at >=880px below). */
  line-height: 1.1;
  color: var(--ink-strong);
  text-wrap: balance;
}
h2 {
  font-size: clamp(1.85rem, 1.2rem + 1.9vw, 2.625rem); /* 42px */
  line-height: 1.14;
  letter-spacing: -0.02em;
  color: var(--accent-ink);
}
h3 { font-size: 1.25rem; line-height: 1.3; color: var(--accent-ink); }  /* 20px */

p { margin: 0 0 1rem; }
p:last-child { margin-bottom: 0; }

/* Inline links take the darkened accent: the signature hue is 2-3.5:1 on the
   paper, well short of the 4.5:1 body-copy contrast; --accent-ink clears it
   on both sites. */
a { color: var(--accent-ink); text-underline-offset: 2px; }
a:hover { text-decoration: none; }

::selection { background: color-mix(in srgb, var(--accent) 28%, transparent); color: var(--ink-strong); }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 4px; }

.wrap {
  width: 100%; max-width: var(--container); margin-inline: auto;
  /* env() keeps content clear of a notch / rounded corner in landscape. */
  padding-left: max(var(--pad-x), env(safe-area-inset-left));
  padding-right: max(var(--pad-x), env(safe-area-inset-right));
}
.wrap--narrow { max-width: 860px; }

.skip-link { position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--accent-ink); color: var(--white); padding: .6rem 1rem; }
.skip-link:focus { left: .5rem; top: .5rem; }

.notice { margin: 0; padding: calc(var(--header-h) + 12px) var(--pad-x) 12px; text-align: center;
  background: var(--sunken); color: var(--ink); font-size: .85rem;
  border-bottom: 1px solid var(--line); }

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

.site-header {
  position: fixed; inset: 0 0 auto 0; z-index: 100;
  /* Translucent rather than solid: the page moves underneath it, which is the
     single cheapest way to make a fixed bar feel like software. The solid
     colour is the fallback where backdrop-filter is unsupported. */
  background: color-mix(in srgb, var(--band-ground) 86%, transparent);
  border-bottom: 1px solid var(--line);
  box-shadow: 0 1px 22px -12px rgba(var(--shade), .35);
  transition: background .25s ease, border-color .25s ease, box-shadow .25s ease;
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .site-header { -webkit-backdrop-filter: blur(14px) saturate(140%); backdrop-filter: blur(14px) saturate(140%); }
}
/* JS adds .at-top while the page is scrolled to the top of a hero, so the bar
   dissolves into it. Without JS the header simply stays solid. */
.site-header.at-top { background: transparent; border-bottom-color: transparent; box-shadow: none; }

.site-header__inner { display: flex; align-items: center; gap: 20px; min-height: var(--header-h); flex-wrap: nowrap; }

.logo { display: inline-flex; align-items: center; gap: 10px; min-width: 0;
  min-height: 44px;                     /* a finger-sized target for "home" */
  text-decoration: none; color: var(--ink-strong); }
.logo__mark { width: 26px; height: 26px; flex: none; }
/* `object-fit: contain` is the safety net: if the bar ever runs out of room the
   logo scales down in proportion instead of being squashed sideways (height is
   fixed, so a narrower box used to distort it). */
.logo__full { display: block; height: 44px; width: auto; max-width: 100%;
  object-fit: contain; object-position: left center; }
.logo__text { font-size: 1.35rem; font-weight: 600; letter-spacing: -.01em; line-height: 1; }
.logo__text strong { font-weight: 700; }
.logo__sub { display: block; font-size: .5rem; font-weight: 600; letter-spacing: .18em;
  text-transform: uppercase; color: var(--accent-ink); margin-top: 3px; }

.site-nav { display: flex; align-items: center; gap: 16px; margin-left: auto; flex-wrap: nowrap; }
/* Gap and side padding are sized so the widest bar — the logo image plus the
   Czech or Polish labels — fits the 1140px container with the logo at full
   size. At 6px / 14px it was ~20px short and the logo was squeezed even on a
   wide screen. */
.site-nav__list { display: flex; align-items: center; gap: 4px; list-style: none; margin: 0; padding: 0; }
.site-nav__list a {
  position: relative;
  display: block; padding: 12px 11px; border-radius: var(--radius-pill);
  color: var(--ink-strong); text-decoration: none;
  font-size: .875rem; font-weight: 500; letter-spacing: .02em; text-transform: uppercase;
  white-space: nowrap; transition: background .15s, color .15s;
}
.site-nav__list a:hover { background: color-mix(in srgb, var(--accent) 11%, transparent);
  color: var(--accent-ink); }
.site-nav__list a[aria-current="page"] { color: var(--accent-ink); }
/* The current page carries a lit marker rather than only a colour change. */
.site-nav__list a[aria-current="page"]::after {
  content: ""; position: absolute; left: 50%; transform: translateX(-50%);
  bottom: 2px; width: 16px; height: 2px; border-radius: 2px; background: var(--accent);
}
.site-nav__end { display: flex; align-items: center; gap: 12px; }

/* The drawer's control. The checkbox is the real control — it must stay in the
   tab order and be reachable by assistive tech, so it is clipped rather than
   `display: none`; the label next to it draws the burger. Both are hidden
   outright above the nav breakpoint, where the full nav bar is shown. */
.navtoggle { position: absolute; width: 1px; height: 1px; opacity: 0;
  margin: 0; pointer-events: none; }
.navtoggle__btn, .navdrawer__scrim { display: none; }
/* The panel's own CTA. Scoped past `.btn`, which also sets display. */
.site-nav .site-nav__cta { display: none; }

.langswitch { position: relative; }
.langswitch > summary {
  list-style: none; cursor: pointer; color: var(--ink-strong);
  /* 40px tall so it is a finger target, not just a mouse target. */
  display: inline-flex; align-items: center; min-height: 40px;
  font-size: .8rem; font-weight: 600; letter-spacing: .08em;
  border: 1px solid var(--line-strong); border-radius: var(--radius-pill); padding: 7px 14px;
  transition: border-color .15s, color .15s;
}
.langswitch > summary::-webkit-details-marker { display: none; }
.langswitch > summary:hover { border-color: var(--accent); color: var(--accent-ink); }
.langswitch ul {
  position: absolute; right: 0; top: calc(100% + 8px); z-index: 120;
  margin: 0; padding: 6px; list-style: none; min-width: 150px;
  background: var(--surface); border: 1px solid var(--line); border-radius: 12px;
  box-shadow: var(--lift);
}
.langswitch li a { display: flex; align-items: center; min-height: 44px;
  padding: 8px 14px; border-radius: 8px;
  color: var(--ink-strong); text-decoration: none; font-size: .9rem; }
.langswitch li a:hover { background: var(--sunken); color: var(--accent-ink); }
.langswitch li a[aria-current="true"] { color: var(--accent-ink); font-weight: 600; }

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

.btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 44px; padding: 0 28px;
  border: 2px solid transparent; border-radius: var(--radius-pill);
  font: inherit; font-size: .9375rem; font-weight: 600; text-decoration: none;
  white-space: nowrap; text-align: center;
  cursor: pointer; transition: background .18s, border-color .18s, color .18s, box-shadow .18s, transform .18s;
}
/* The fill is --accent-ink, not --accent: white on the signature blue is
   3.0:1 and on the LogMan teal 2.3:1, so the bright hue can hold a mark but
   never a label. */
.btn--primary { background: var(--accent-ink); color: var(--white);
  box-shadow: 0 10px 24px -14px color-mix(in srgb, var(--accent-ink) 60%, transparent); }
.btn--primary:hover { background: var(--accent-dark);
  box-shadow: 0 14px 28px -12px color-mix(in srgb, var(--accent-ink) 70%, transparent); }
.btn--secondary { background: var(--surface); color: var(--accent-ink);
  border-color: color-mix(in srgb, var(--accent-ink) 40%, transparent); }
.btn--secondary:hover { background: color-mix(in srgb, var(--accent) 12%, var(--surface));
  border-color: var(--accent-ink); color: var(--accent-dark); }
.btn--sm { min-height: 40px; padding: 0 22px; font-size: .875rem; }
.btn:active { transform: translateY(1px); }

/* The hero and the CTA panel are paper too, so the ghost button needs no
   inversion there — only a firmer edge against a tinted ground. */
.hero .btn--secondary, .band--cta .btn--secondary {
  border-color: color-mix(in srgb, var(--accent-ink) 55%, transparent); }

.actions { display: flex; flex-wrap: wrap; gap: 16px; margin: 40px 0 0; }
.hero .actions, .band--cta .actions, .band--center .actions { justify-content: center; }

/* --------------------------------------------------------------- sections -- */

/* The eyebrow carries a short lit rule. It is the smallest possible piece of
   instrumentation and it appears above every section head on the site, so it
   is what stops a page reading as a stack of unrelated blocks. */
.eyebrow { display: flex; align-items: center; gap: 10px;
  margin: 0 0 14px; font-size: .8125rem; font-weight: 700;
  letter-spacing: .14em; text-transform: uppercase; color: var(--accent-ink); }
.eyebrow::before { content: ""; width: 26px; height: 2px; flex: none; border-radius: 2px;
  background: linear-gradient(90deg, transparent, var(--accent)); }
.band__head .eyebrow, .hero .eyebrow { justify-content: center; }
.band__head .eyebrow::after, .hero .eyebrow::after {
  content: ""; width: 26px; height: 2px; flex: none; border-radius: 2px;
  background: linear-gradient(270deg, transparent, var(--accent)); }

.lead { font-size: 1.0625rem; line-height: 1.6; max-width: 70ch; }

.band { position: relative; padding: var(--section-y) 0; }
.band--alt { background: color-mix(in srgb, var(--accent) 5%, var(--page)); }
/* Every section head is centred — eyebrow, heading and lead — so the page has
   one axis from the hero down to the form. (It used to depend on `align:
   center` in the YAML, which left some heads on the left and some in the
   middle on the same page.) What sits under a head keeps its own alignment:
   card and timeline headings stay left with their text. */
.band__head { max-width: 900px; margin-inline: auto; text-align: center; }
.band__head .lead { margin-inline: auto; }

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

.hero {
  position: relative; isolation: isolate;
  background: var(--hero-ground);
  /* Clears the fixed header at every width without a per-breakpoint override. */
  padding: calc(var(--header-h) + clamp(48px, 7.5vw, 116px)) 0 clamp(84px, 10vw, 132px);
  text-align: center;
  color: var(--ink);
  overflow: hidden;
  border-bottom: 1px solid var(--line);
}
/* Backdrop. Three layers, front to back: the apparel art (--art: the low-poly
   ridge, the node net and the rook, anchored to the bottom edge and scaled to
   the full width), a blue haze rising off that bottom edge, and the paper
   gradient under all of it. (There used to be a 64px measuring grid between
   the haze and the gradient; it was removed in Oct 2026 — the backdrops are
   plain blue washes now, here, in the CTA panel and in the form band.) The art
   is one cached file
   per site rather than inline markup on every page. Swap in a photograph by
   setting a background-image here — the layers still read over one. */
.hero__bg {
  position: absolute; inset: 0; z-index: -1;
  background:
    var(--art) bottom center / var(--art-size) no-repeat,
    radial-gradient(120% 80% at 50% 116%, var(--glow) 0%, var(--glow-mid) 45%, transparent 72%),
    linear-gradient(180deg, var(--grad-top) 0%, var(--grad-mid) 48%, var(--grad-bottom) 100%);
}
/* Two fades in one layer. The top of the net dissolves towards
   the TOP, so the art reads as ground the content stands on rather than
   wallpaper behind it; and the foot of the ridge is washed back out into the
   page colour at the BOTTOM, so the hero ends by dissolving into the paper
   instead of on a hard blue cut. */
.hero__bg::after {
  content: ""; position: absolute; inset: 0;
  background:
    linear-gradient(180deg, var(--grad-top) 0%, transparent 46%),
    linear-gradient(0deg, var(--page) 0%, color-mix(in srgb, var(--page) 55%, transparent) 32px, transparent 112px);
}
/* A hairline along the bottom edge — the section's own signature. */
.hero::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 1px;
  background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--accent) 55%, transparent) 30%,
              color-mix(in srgb, var(--accent) 55%, transparent) 70%, transparent);
}
.hero .wrap { position: relative; }
.hero h1 { margin-bottom: 28px; max-width: 16ch; margin-inline: auto; }
/* The 16ch column suits a slogan. A long heading stacked six lines deep in it,
   so the macro marks those `hero--long`: the full container width and one step
   down in size. */
.hero--long h1 { max-width: none; font-size: clamp(1.9rem, 1rem + 2.4vw, 3.25rem); line-height: 1.1; }
.hero .lead { font-size: clamp(1rem, .9rem + .5vw, 1.5rem); line-height: 1.3;
  color: var(--ink); max-width: 62ch; margin-inline: auto; }
.hero .eyebrow { color: var(--accent-ink); }
.hero__byline { margin: 24px 0 0; color: var(--accent-ink); font-size: 1rem; }
.hero__note { margin: 48px 0 0; color: var(--ink); font-size: 1rem; }

/* cards ------------------------------------------------------------------ */

.cards, .grid { display: grid; gap: 24px; margin-top: 40px; }
.cards { grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr)); }
.grid  { grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr)); }

/* The surface every panel on the site is made of: one step above the ground,
   a hairline to cut it out, a lit top edge, and a shadow underneath. */
.card, .stack__item, .steps__item, .stat, .faq__item, .tablewrap {
  background: var(--surface);
  border: 1px solid var(--line);
  box-shadow: var(--edge), var(--lift);
}

.card {
  border-radius: var(--radius-card); padding: 30px 30px 40px;
  /* A column so a card's last line (the "who it is for" note) can be pinned to
     the bottom and line up across a row of unequal cards. */
  display: flex; flex-direction: column;
  transition: border-color .2s, box-shadow .2s, transform .2s, background .2s;
}
@media (hover: hover) {
  .card:hover { border-color: color-mix(in srgb, var(--accent) 45%, var(--line));
    background: var(--surface-2); box-shadow: var(--edge), var(--lift-hover); transform: translateY(-2px); }
}
.card h3 { margin-bottom: 14px; }
.card__eyebrow { margin: 0 0 10px; font-size: .8125rem; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase; color: var(--ink); }
/* `margin-top: auto` pins the note to the bottom of the card, so the "who it
   is for" lines align across a row of cards with unequal copy. Do not give it
   a margin-top elsewhere — that is what the auto is for. */
.card__note { margin: auto 0 0; padding-top: 16px; border-top: 1px solid var(--line);
  font-size: .875rem; line-height: 1.5; color: var(--ink); }
.card p + .card__note { padding-top: 18px; }
/* A row of cards that steps up in tint: the editions ladder. The tint is the
   card's top edge and a wash bleeding down from it, so the ladder is visible
   from across the room. */
.cards--tinted .card { border-radius: 4px; padding: 26px 22px 28px;
  border-top: 3px solid var(--tint, var(--accent));
  background:
    linear-gradient(180deg, color-mix(in srgb, var(--tint, var(--accent)) 16%, transparent), transparent 120px),
    var(--surface); }
.cards--tinted .card:nth-child(1) { --tint: var(--tint-1); }
.cards--tinted .card:nth-child(2) { --tint: var(--tint-2); }
.cards--tinted .card:nth-child(3) { --tint: var(--tint-3); }
.cards--tinted .card:nth-child(4) { --tint: var(--tint-4); }
.card__action { margin: 24px 0 0; }
.card__action a {
  display: inline-flex; align-items: center; gap: 10px;
  color: var(--ink-strong); font-size: .95rem; font-weight: 600; text-decoration: none;
}
.card__action a:hover { color: var(--accent-ink); }
/* the circular arrow chip used all over the reference design */
.card__action a::after {
  content: ""; width: 22px; height: 22px; flex: none; border-radius: 50%;
  background: var(--accent) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 6l6 6-6 6'/%3E%3C/svg%3E") center/12px no-repeat;
  box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 60%, transparent);
  transition: transform .18s, box-shadow .18s;
}
.card__action a:hover::after { transform: translateX(3px);
  box-shadow: 0 0 0 5px color-mix(in srgb, var(--accent) 18%, transparent); }
.card__address { color: var(--ink); font-size: .95rem; }

/* two-column intro + card grid ("Why teams switch to us") */
.split { display: grid; gap: 32px; grid-template-columns: minmax(240px, 1fr) 2.1fr; align-items: start; margin-top: 40px; }
.split__intro h3 { font-size: 1.5rem; line-height: 1.2; }
.split__intro p { font-size: .95rem; }
.split__items { display: grid; gap: 24px; grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr)); }

/* plain feature stack */
.stack { display: grid; gap: 24px; margin-top: 40px;
  grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr)); }
.stack__item { border-radius: var(--radius-card); padding: 30px; }
/* A block that carries a button is a column, so the button sits on the bottom
   edge and the buttons line up across a row of unequal copy. */
.stack__item--action { display: flex; flex-direction: column; }
.stack__item--action .actions { margin: auto 0 0; padding-top: 24px; }

/* long-form legal text (privacy policy) ---------------------------------- */

/* Reading type, not display type: the section headings step down from the
   42px h2 the marketing bands use, and the measure is the narrow wrap. */
.legal h2 { font-size: 1.5rem; line-height: 1.25; letter-spacing: 0; margin: 48px 0 16px; }
.legal h2:first-child { margin-top: 0; }
.legal h3 { font-size: 1.0625rem; color: var(--ink-strong); margin: 32px 0 12px; }
.legal ul { margin: 0 0 1rem; padding-left: 1.25rem; }
.legal li { margin-bottom: .5rem; }
.legal li::marker { color: var(--accent); }
.legal a { overflow-wrap: anywhere; }

/* zigzag ----------------------------------------------------------------- */

.zigzag { display: grid; gap: 56px; margin-top: 48px; }
.zigzag__item { display: grid; gap: 32px; grid-template-columns: 1fr 1fr; align-items: center; }
.zigzag__item:nth-child(even) .zigzag__text { order: 2; }
/* The figure is a plain blue panel: a glow under the glyph and corner brackets
   framing it. It stands in for a product illustration — set a background-image
   here when there is one. */
.zigzag__figure {
  position: relative; isolation: isolate;
  border-radius: var(--radius-card); min-height: 240px; overflow: hidden;
  border: 1px solid var(--line);
  background:
    radial-gradient(70% 60% at 50% 60%, color-mix(in srgb, var(--accent) 13%, transparent), transparent 70%),
    linear-gradient(160deg, var(--surface), var(--sunken));
  box-shadow: var(--edge), var(--lift);
  display: grid; place-items: center;
}
/* Corner brackets: two gradients clipped to 22px squares in opposite corners. */
.zigzag__figure::before {
  content: ""; position: absolute; inset: 14px; pointer-events: none;
  background:
    linear-gradient(var(--accent), var(--accent)) left top / 22px 1px no-repeat,
    linear-gradient(var(--accent), var(--accent)) left top / 1px 22px no-repeat,
    linear-gradient(var(--accent), var(--accent)) right bottom / 22px 1px no-repeat,
    linear-gradient(var(--accent), var(--accent)) right bottom / 1px 22px no-repeat;
  opacity: .55;
}
.zigzag__glyph { position: relative; width: 92px; height: 92px; border-radius: 24px;
  background: linear-gradient(150deg, var(--accent-ink), var(--accent) 55%, var(--accent-dark));
  box-shadow: 0 16px 34px -14px color-mix(in srgb, var(--accent-ink) 55%, transparent),
              inset 0 1px 0 rgba(255,255,255,.45); }
/* Two rings pushing out from the glyph — a signal leaving a node. */
.zigzag__glyph::before, .zigzag__glyph::after {
  content: ""; position: absolute; inset: -22px; border-radius: 34px;
  border: 1px solid color-mix(in srgb, var(--accent) 42%, transparent);
}
.zigzag__glyph::after { inset: -44px; border-radius: 46px;
  border-color: color-mix(in srgb, var(--accent) 20%, transparent); }
.zigzag h3 { font-size: 1.75rem; line-height: 1.15; }

/* stats ------------------------------------------------------------------ */

.stats { display: grid; gap: 24px; margin: 40px 0 0;
  grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr)); }
.stat { position: relative; overflow: hidden; margin: 0;
  border-radius: var(--radius-card); padding: 34px 28px 30px; }
/* A lit bar across the top edge: these are readings, not paragraphs. */
.stat::before { content: ""; position: absolute; left: 0; right: 0; top: 0; height: 2px;
  background: linear-gradient(90deg, var(--accent), transparent 70%); }
.stat__value { font-size: clamp(1.6rem, 1.05rem + 1.5vw, 2.25rem);
  font-family: var(--font-display); font-weight: var(--heading-weight);
  color: var(--ink-strong); line-height: 1;
  /* Figures line up column to column, and a touch of tracking keeps a 6-digit
     number from reading as a wall. */
  font-variant-numeric: tabular-nums; letter-spacing: -.02em; }
.stat__label { margin: 14px 0 0; color: var(--accent-ink); font-weight: 600; }
.stat__note { display: block; margin-top: 8px; font-weight: 400; color: var(--ink); font-size: .9rem; }

/* timeline --------------------------------------------------------------- */

.timeline { list-style: none; margin: 40px 0 0; padding: 0 0 0 28px;
  border-left: 1px solid var(--line); }
.timeline__item { position: relative; padding-bottom: 36px; }
.timeline__item:last-child { padding-bottom: 0; }
.timeline__item::before { content: ""; position: absolute; left: -34px; top: 6px;
  width: 11px; height: 11px; border-radius: 50%; background: var(--accent);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 16%, transparent),
              0 0 0 5px var(--page); }
.timeline__year { margin: 0 0 6px; font-size: .875rem; font-weight: 700;
  letter-spacing: .06em; color: var(--accent-ink); font-variant-numeric: tabular-nums; }
.timeline h3 { color: var(--ink-strong); font-size: 1.25rem; margin-bottom: 10px; }

/* faq -------------------------------------------------------------------- */

.faq { margin-top: 40px; }
.faq__item { border-radius: var(--radius-card); margin-bottom: 12px;
  transition: border-color .2s, background .2s; }
.faq__item[open], .faq__item:hover { border-color: color-mix(in srgb, var(--accent) 40%, var(--line)); }
.faq__item summary { display: flex; justify-content: space-between; gap: 20px; align-items: center;
  cursor: pointer; list-style: none; padding: 22px 26px;
  font-size: 1.05rem; font-weight: 600; color: var(--accent-ink); }
.faq__item summary::-webkit-details-marker { display: none; }
.faq__item summary::after { content: ""; width: 22px; height: 22px; flex: none; border-radius: 50%;
  background: var(--accent) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E") center/12px no-repeat;
  transition: transform .2s; }
.faq__item[open] summary::after { transform: rotate(180deg); }
.faq__item p { padding: 0 26px 24px; margin: 0; }

/* steps (numbered pipeline) ---------------------------------------------- */

.steps { list-style: none; counter-reset: step; margin: 40px 0 0; padding: 0;
  display: grid; gap: 24px; grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr)); }
.steps__item { counter-increment: step; position: relative;
  border-radius: var(--radius-card); padding: 30px; }
/* The index is a chip, not a caption: a bordered square with the number in it,
   so a row of steps reads as stages in a pipeline. */
.steps__item::before {
  content: counter(step, decimal-leading-zero);
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; margin-bottom: 16px;
  border: 1px solid color-mix(in srgb, var(--accent) 45%, transparent); border-radius: 8px;
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  font-size: .8125rem; font-weight: 700; letter-spacing: .06em; color: var(--accent);
  font-variant-numeric: tabular-nums;
}
.steps__item h3 { color: var(--ink-strong); margin-bottom: 10px; }
.steps__item p { font-size: .95rem; margin-bottom: 0; }

/* `layout: ladder`: named steps rather than numbered ones, marked with a rule
   instead of a card — an upgrade path, not a procedure. */
.steps--ladder { grid-template-columns: repeat(auto-fit, minmax(min(270px, 100%), 1fr)); gap: 28px; }
.steps--ladder .steps__item { background: transparent; border: 0; box-shadow: none;
  border-radius: 0; padding: 2px 0 2px 18px;
  border-left: 2px solid var(--accent); }
.steps--ladder .steps__item::before { content: none; }
.steps__item .steps__label { margin: 0 0 8px; font-size: .8125rem; font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase; color: var(--accent-ink); }
.steps--ladder .steps__item h3 { font-size: 1.0625rem; margin-bottom: 8px; }

/* comparison table ------------------------------------------------------- */

/* `position: relative` matters: the yes/no cells carry absolutely positioned
   .visually-hidden labels, and without a positioned ancestor they escape the
   scroller and make the whole PAGE scroll sideways on a phone. */
.tablewrap { position: relative; margin-top: 40px; overflow-x: auto;
  border-radius: var(--radius-card); }
.ftable { width: 100%; border-collapse: collapse; min-width: 620px; text-align: left; }
.ftable th, .ftable td { padding: 14px 20px; border-bottom: 1px solid var(--line); }
.ftable thead th { font-size: .8rem; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: var(--accent-ink); white-space: nowrap;
  vertical-align: bottom; padding-bottom: 12px; }
.ftable tbody th { font-weight: 500; color: var(--ink-strong); font-size: .95rem;
  vertical-align: top; }
.ftable thead th:first-child { width: 34%; min-width: 200px; }
.ftable td { text-align: center; width: 1%; white-space: nowrap; vertical-align: top; }
.ftable tbody tr:last-child th, .ftable tbody tr:last-child td { border-bottom: 0; }

/* The second line under a capability: what it actually covers. Small, quiet,
   and the reason the matrix can be read without a glossary beside it. */
.ftable tbody th small { display: block; margin-top: 5px;
  font-size: .8125rem; font-weight: 400; line-height: 1.4; color: var(--ink); }

/* Column heads carry the tint ladder as a lit rule beneath the label. */
.ftable__bar { display: block; height: 3px; margin-top: 10px; border-radius: 2px;
  background: var(--tint, var(--accent)); }
.ftable thead th:nth-child(2) { --tint: var(--tint-1); }
.ftable thead th:nth-child(3) { --tint: var(--tint-2); }
.ftable thead th:nth-child(4) { --tint: var(--tint-3); }
.ftable thead th:nth-child(5) { --tint: var(--tint-4); }

/* Group bands break 24 rows into four readable blocks. A pale wash was not
   enough to read as a divider at a glance, so they are cut INTO the surface:
   one step below the paper, deep navy caps, and an accent rule on top. */
.ftable tbody th.ftable__group {
  padding: 12px 20px; font-size: .8125rem; font-weight: 700; letter-spacing: .14em;
  text-transform: uppercase; color: var(--ink-strong);
  background: var(--sunken);
  border: 0; border-top: 1px solid color-mix(in srgb, var(--accent) 55%, transparent);
}
.ftable__grouprow + tr th, .ftable__grouprow + tr td { border-top: 0; }

/* A value rather than a tick: "18 months", "unlimited", "500 000+ EPS". */
.ftable__val { display: inline-block; padding: 3px 10px; border-radius: 6px;
  font-size: .8125rem; font-weight: 500; line-height: 1.5; white-space: nowrap;
  color: var(--ink-strong);
  background: color-mix(in srgb, var(--accent) 13%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 34%, transparent); }
/* A ceiling, not a feature — the thing that decides between two editions. */
.ftable__val--limit { color: var(--signal); background: var(--signal-wash);
  border-color: color-mix(in srgb, var(--signal) 40%, transparent); font-weight: 600; }

@media (hover: hover) {
  .ftable tbody tr:hover th, .ftable tbody tr:hover td {
    background: color-mix(in srgb, var(--accent) 8%, var(--surface)); }
  .ftable tbody tr:hover th.ftable__group { background: var(--sunken); }
}

/* Qualifications that belong to the matrix, not to a section of their own. */
.tablenotes {
  list-style: none; margin: 24px 0 0; padding: 18px 0 0;
  border-top: 1px solid var(--line);
  display: grid; gap: 12px 40px;
  grid-template-columns: repeat(auto-fit, minmax(min(330px, 100%), 1fr));
  font-size: .875rem; line-height: 1.6; text-align: left;
}
.tablenotes strong { color: var(--ink-strong); }
.ftable .yes::before { content: ""; display: inline-block; width: 20px; height: 20px;
  border-radius: 50%; background: var(--accent)
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 13l4 4L19 7'/%3E%3C/svg%3E") center/12px no-repeat; }
.ftable .no::before { content: ""; display: inline-block; width: 20px; height: 20px;
  border-radius: 50%; border: 1px solid var(--line-strong); }

/* screen-reader-only text (the table's yes/no cells) */
.visually-hidden { position: absolute; width: 1px; height: 1px; margin: -1px;
  padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* lists / offices -------------------------------------------------------- */

.linklist { list-style: none; margin: 16px 0 0; padding: 0; }
.linklist li { margin-bottom: 8px; }
.linklist a { color: var(--ink-strong); text-decoration: none; font-size: .95rem; font-weight: 500; }
.linklist a:hover { color: var(--accent-ink); }

/* CTA panel -------------------------------------------------------------- */

.band--cta { padding: var(--section-y) 0; }
.band--cta .panel {
  position: relative; isolation: isolate; overflow: hidden;
  border-radius: var(--radius-panel);
  border: 1px solid color-mix(in srgb, var(--accent) 30%, var(--line));
  padding: 90px 40px clamp(120px, 14vw, 170px);
  text-align: center;
  background: var(--hero-ground);
  color: var(--ink);
  box-shadow: 0 26px 60px -40px rgba(var(--shade), .40);
}
/* The same art as the hero, so the page closes on the surface it opened on. */
.band--cta .panel::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background:
    linear-gradient(0deg, var(--hero-ground) 0%, transparent 88px),
    var(--art) bottom center / var(--art-size) no-repeat,
    radial-gradient(110% 130% at 50% 132%, var(--glow) 0%, var(--glow-mid) 45%, transparent 75%),
    linear-gradient(180deg, var(--grad-top), var(--grad-bottom));
}
.band--cta h2 { color: var(--ink-strong); max-width: 22ch; margin-inline: auto; }
.band--cta .lead { color: var(--ink); max-width: 70ch; margin-inline: auto; }

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

.band--form { position: relative; isolation: isolate;
  background: var(--sunken); color: var(--ink);
  padding: var(--band-y) 0; border-top: 1px solid var(--line); overflow: hidden; }
/* A blue haze rising off the bottom edge, like the hero's: the page opens and
   closes on the same surface, and the band stops reading as the footer's
   first half. */
.band--form::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background:
    radial-gradient(80% 90% at 50% 130%, color-mix(in srgb, var(--accent) 14%, transparent), transparent 70%);
}
/* The form's heading and intro are a section head too: centred like the rest. */
.band--form h2 { color: var(--ink-strong); text-align: center; }
.band--form .lead { color: var(--ink); text-align: center; margin-inline: auto; }
.form { margin-top: 32px; }
.form__row { display: grid; gap: 0 20px; grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr)); }
.field { margin: 0 0 20px; display: flex; flex-direction: column; gap: 8px; }
.field label { font-size: .8125rem; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: var(--accent-ink); }
/* Fields are laid ON the band rather than cut into it: white against the
   band's wash, hairline border, accent ring on focus. */
.field input, .field select, .field textarea {
  font: inherit; font-size: .95rem; color: var(--ink-strong);
  background: var(--surface); border: 1px solid var(--line-strong); border-radius: 10px;
  padding: 12px 16px;
  transition: border-color .15s, box-shadow .15s;
}
.field input::placeholder, .field textarea::placeholder { color: color-mix(in srgb, var(--ink) 70%, transparent); }
.field input:hover, .field select:hover, .field textarea:hover { border-color: color-mix(in srgb, var(--accent) 40%, var(--line)); }
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none; border-color: var(--accent-ink);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 28%, transparent); }
.field textarea { resize: vertical; }
.form__submit { margin: 8px 0 0; }
.form__privacy { margin-top: 16px; font-size: .85rem; color: var(--ink); }
.form--thanks { padding: 32px; border-radius: var(--radius-card);
  background: color-mix(in srgb, var(--accent) 9%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--accent-ink) 45%, transparent);
  box-shadow: var(--lift); }
.form--thanks h3 { color: var(--ink-strong); }
.form--thanks p { color: var(--ink); }

.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.btn__busy { display: none; }
button.htmx-request .btn__label { display: none; }
button.htmx-request .btn__busy { display: inline; }

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

.site-footer { background: var(--band-ground); color: var(--ink); padding: var(--band-y) 0 40px;
  border-top: 1px solid var(--line); }
.site-footer__grid { display: grid; gap: 40px; grid-template-columns: 1.2fr 1fr 1.1fr; align-items: start; }
.site-footer__heading { margin: 0 0 20px; font-size: 1.25rem; font-weight: var(--heading-weight); color: var(--accent-ink); }
.site-footer address { font-style: normal; font-size: .95rem; line-height: 1.9; color: var(--ink-strong); }
.site-footer address a { color: var(--ink-strong); text-decoration: none; }
.site-footer address a:hover { color: var(--accent-ink); }
.site-footer .linklist a { color: var(--ink-strong); }
.site-footer .linklist a:hover { color: var(--accent-ink); }
.site-footer .linklist li { position: relative; padding-left: 16px; }
.site-footer .linklist li::before { content: ""; position: absolute; left: 0; top: .62em;
  width: 5px; height: 5px; border-radius: 50%; background: var(--accent); }
/* the outlined "complete ecosystem" box from the reference footer */
.site-footer__panel { border: 1px solid var(--line); border-radius: var(--radius-panel);
  padding: 28px; text-align: center; background: color-mix(in srgb, var(--accent) 6%, var(--band-ground)); }
.site-footer__panel .site-footer__heading { margin-bottom: 20px; }
.site-footer__panel .btn { width: 100%; margin-bottom: 12px; white-space: nowrap; }
.site-footer__panel .btn:last-child { margin-bottom: 0; }

.site-footer__legal { display: flex; flex-wrap: wrap; gap: 8px 24px; align-items: center;
  margin-top: 60px; padding-top: 24px; border-top: 1px solid var(--line-strong);
  font-size: .85rem; color: var(--ink); }
.site-footer__legal p { margin: 0; }
.site-footer__langs { display: flex; gap: 16px; list-style: none; margin: 0 0 0 auto; padding: 0; }
.site-footer__langs a { color: var(--ink); text-decoration: none; }
.site-footer__langs a:hover { color: var(--accent-ink); }
.site-footer__langs a[aria-current="true"] { color: var(--ink-strong); font-weight: 600; }

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

   site.js marks the blocks of a page and adds .is-in as each scrolls into
   view. The class that hides them (`.js-reveal`, on <html>) is added BY the
   script and only when the visitor has not asked for reduced motion, so with
   JavaScript off — or motion turned down — nothing is ever hidden.

   Deliberately not applied to .tablewrap: a transformed ancestor would break
   the matrix's sticky column heads.
   ====================================================================== */

.js-reveal [data-reveal] { opacity: 0; transform: translateY(18px); }
.js-reveal [data-reveal].is-in {
  opacity: 1; transform: none;
  transition: opacity .55s ease, transform .55s cubic-bezier(.22,.7,.3,1);
}
/* Items in a row arrive a beat apart, left to right. */
.js-reveal [data-reveal].is-in:nth-child(2) { transition-delay: .07s; }
.js-reveal [data-reveal].is-in:nth-child(3) { transition-delay: .14s; }
.js-reveal [data-reveal].is-in:nth-child(4) { transition-delay: .21s; }

/* ======================================================================
   ROWS OF FOUR

   Four items are a SET, not a list: four of anything must read as one row,
   never as 3 + 1 or 2 + 2. The section macros add `row4` wherever a section
   has exactly four items, so this is a property of the content, not of one
   page. Fixed columns rather than auto-fit — auto-fit is what wraps.

   Below the width where four columns still fit, the row does not wrap: it
   becomes a single line that scrolls sideways, the same answer the comparison
   matrix gives. The negative margin lets it bleed to the screen edges, so a
   part-visible fourth item is the affordance that there is more.

   `row4--compact` is for short tiles (stats, steps); they hold their four
   columns further down the scale than cards carrying body copy.

   This block sits at the end of the base styles deliberately: `.stats` and
   `.steps` set their own auto-fit tracks at the same specificity, and the
   later rule has to be this one.
   ====================================================================== */

.row4 { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 18px; }
.row4 > * { min-width: 0; }

@media (max-width: 1080px) {
  .row4:not(.row4--compact) { display: flex; }
}
@media (max-width: 940px) {
  .row4--compact { display: flex; }
}

/* Shared by both variants. Harmless while the row is still a grid: the
   negative margin and the matching padding cancel out, and a grid that fits
   never shows a scrollbar. */
@media (max-width: 1080px) {
  .row4 {
    gap: 14px;
    margin-inline: calc(-1 * var(--pad-x));
    padding: 4px var(--pad-x) 8px;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x proximity;
    scroll-padding-inline: var(--pad-x);
  }
  .row4 > * { scroll-snap-align: start; }
  .row4:not(.row4--compact) > * { flex: 0 0 min(280px, 76%); }
  .row4--compact > * { flex: 0 0 min(240px, 70%); }
}

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

   Five breakpoints, each with a job:

     1180px  the nav bar no longer fits, so the links become a slide-in panel.
             This was 880px while the header carried a text wordmark; the
             official logo image is ~200px wide, and with it the full bar
             (logo + five links + language + CTA) needs ~1175px in Czech and
             Polish. Below that the logo was squeezed, then vanished.
     1080px  the two widest desktop layouts (split intro, 3-column footer)
             lose a column — laptops and landscape tablets.
      880px  alternating text/figure rows (zigzag) become one column.
      700px  tablet portrait: multi-column card grids that still fit are kept,
             the ones that would squeeze below ~260px are collapsed.
      560px  phone: everything is one column, buttons go full width, the
             header CTA moves into the panel and the comparison table
             becomes a scroller with a sticky feature column.

   Gutters, section rhythm and display type are fluid (clamp) rather than
   stepped, so these breakpoints only ever change LAYOUT, never size.
   ========================================================================== */

/* Tighter display leading is only right once h1 is big. */
@media (min-width: 881px) { h1 { line-height: 0.95; } }

/* --------------------------------------------------------------- 1080px -- */

@media (max-width: 1080px) {
  .split { grid-template-columns: 1fr; }
  .ftable th, .ftable td { padding: 12px 14px; }

  /* Below the desktop breakpoint the matrix no longer fits, so it scrolls
     inside its own box. Two things make that safe: the capability column is
     pinned, so a row never loses its label, and the classic pure-CSS scroll
     shadow marks which side has more table to reach — its two `local` layers
     ride with the content and mask the two `scroll` shadows. */
  .ftable tbody th:not(.ftable__group), .ftable thead th:first-child {
    position: sticky; left: 0; z-index: 1;
    background: var(--surface);
    box-shadow: 1px 0 0 var(--line);
  }
  .tablewrap {
    background-image:
      linear-gradient(to right,  var(--surface), color-mix(in srgb, var(--surface) 0%, transparent)),
      linear-gradient(to left,   var(--surface), color-mix(in srgb, var(--surface) 0%, transparent)),
      linear-gradient(to right,  rgba(var(--shade), .20), rgba(var(--shade), 0)),
      linear-gradient(to left,   rgba(var(--shade), .20), rgba(var(--shade), 0));
    background-position: 0 0, 100% 0, 0 0, 100% 0;
    background-repeat: no-repeat;
    background-size: 24px 100%, 24px 100%, 12px 100%, 12px 100%;
    background-attachment: local, local, scroll, scroll;
  }
  .site-footer__grid { grid-template-columns: 1fr 1fr; }
  /* The ecosystem box would be a lone third column; give it the full row. */
  .site-footer__panel { grid-column: 1 / -1; }
  .zigzag { gap: 44px; }
}

/* ------------------------------------ 1180px: the nav becomes a drawer -- */

/* Keep this number in step with the matchMedia query in static/js/site.js. */
@media (max-width: 1180px) {
  :root { --header-h: 64px; }

  /* No hero to dissolve into once the bar is this short — keep it solid so
     the burger always has contrast behind it. */
  .site-header, .site-header.at-top { background: var(--band-ground); border-bottom-color: var(--line); }
  /* The bar is solid here, so the blur shows nothing — and it must go: an
     element with backdrop-filter becomes the containing block for its
     position:fixed descendants. With it on, the drawer and its scrim were
     sized against the 64px header instead of the viewport, so the open panel
     collapsed to a ~36px strip under the bar. Applies wherever the drawer
     does, i.e. this whole block. */
  .site-header { -webkit-backdrop-filter: none; backdrop-filter: none; }
  .site-header__inner { position: relative; gap: 12px; flex-wrap: nowrap; }

  /* The invisible checkbox lies exactly over the burger it controls. */
  .navtoggle {
    position: absolute; z-index: 4; margin: 0;
    right: max(var(--pad-x), env(safe-area-inset-right));
    top: 50%; transform: translateY(-50%);
    width: 44px; height: 44px; opacity: 0; pointer-events: auto; cursor: pointer;
    -webkit-appearance: none; appearance: none;
  }
  .navtoggle__btn {
    display: block; position: relative; z-index: 3; order: 3; flex: none;
    width: 44px; height: 44px; border-radius: 10px;
    border: 1px solid var(--line-strong);
  }
  .navtoggle__bars, .navtoggle__bars::before, .navtoggle__bars::after {
    content: ""; position: absolute; left: 12px; width: 18px; height: 2px;
    border-radius: 2px; background: var(--ink-strong);
    transition: transform .2s ease, background-color .1s ease;
  }
  .navtoggle__bars { top: 20px; }
  .navtoggle__bars::before { top: -6px; left: 0; }
  .navtoggle__bars::after  { top:  6px; left: 0; }
  /* Burger folds into a cross while the panel is open. */
  .navtoggle:checked + .navtoggle__btn .navtoggle__bars { background: transparent; }
  .navtoggle:checked + .navtoggle__btn .navtoggle__bars::before { transform: translateY(6px) rotate(45deg); }
  .navtoggle:checked + .navtoggle__btn .navtoggle__bars::after  { transform: translateY(-6px) rotate(-45deg); }
  .navtoggle:focus-visible + .navtoggle__btn { outline: 2px solid var(--accent); outline-offset: 3px; }
  .navtoggle__btn:hover { border-color: var(--accent); }

  .navdrawer__scrim {
    display: block; position: fixed; inset: var(--header-h) 0 0 0; z-index: 1;
    background: rgba(var(--shade), .34);
    opacity: 0; visibility: hidden; transition: opacity .22s ease, visibility .22s ease;
  }
  .navtoggle:checked ~ .navdrawer__scrim { opacity: 1; visibility: visible; }

  /* The panel. `visibility` (not display) so it can animate and so its links
     stay out of the tab order while it is closed. */
  .site-nav {
    position: fixed; z-index: 2; margin: 0;
    top: var(--header-h); right: 0; bottom: 0;
    /* Always leave a strip of the page visible, so the panel reads as an
       overlay and there is somewhere to tap to dismiss it. */
    width: min(360px, calc(100% - 44px));
    flex-direction: column; align-items: stretch; justify-content: flex-start; gap: 0;
    padding: 8px max(var(--pad-x), env(safe-area-inset-right))
             calc(28px + env(safe-area-inset-bottom));
    background: var(--band-ground);
    border-left: 1px solid var(--line);
    box-shadow: -18px 0 44px -20px rgba(var(--shade), .45);
    overflow-y: auto; overscroll-behavior: contain;
    opacity: 0; visibility: hidden; transform: translateX(14px);
    transition: opacity .22s ease, transform .22s ease, visibility .22s ease;
  }
  .navtoggle:checked ~ .site-nav { opacity: 1; visibility: visible; transform: none; }

  .site-nav__list { flex-direction: column; align-items: stretch; gap: 0; }
  .site-nav__list li { display: block; }
  .site-nav__list a {
    display: flex; align-items: center; min-height: 52px;
    padding: 12px 4px; border-radius: 0;
    border-bottom: 1px solid var(--line);
    font-size: .9375rem; white-space: normal;
  }
  .site-nav__list a:hover { background: transparent; color: var(--accent-ink); }
  /* In the panel the current-page marker sits at the left, not underneath. */
  .site-nav__list a[aria-current="page"]::after { left: auto; right: 2px; bottom: auto;
    top: 50%; transform: translateY(-50%); width: 6px; height: 6px; border-radius: 50%; }

  /* Language + CTA stay in the bar at these widths; the burger follows them. */
  .site-nav__end { order: 2; margin-left: auto; flex: none; }
  .langswitch ul { right: 0; }
}

/* --------------------------------------------- 880px: zigzag rows stack -- */

@media (max-width: 880px) {
  /* Alternating text/figure rows become one column: text first every time. */
  .zigzag { gap: 36px; }
  .zigzag__item { grid-template-columns: 1fr; gap: 24px; }
  .zigzag__item:nth-child(even) .zigzag__text { order: 0; }
  .zigzag__figure { min-height: 190px; }
}

/* Panels shouldn't slide for people who asked for less motion. */
@media (max-width: 1180px) and (prefers-reduced-motion: reduce) {
  .site-nav { transform: none; transition: opacity .01s, visibility .01s; }
}

/* JS adds .nav-open to <html> so the page behind the panel can't scroll.
   Without JS the panel's own overscroll-behavior still contains most of it. */
.nav-open { overflow: hidden; }

/* --------------------------------------------- 700px: tablet portrait -- */

@media (max-width: 700px) {
  /* Zoom the ridge and crop its sides, so it is still a mountain on a phone. */
  :root { --art-size: 190% auto; }

  .zigzag__figure { min-height: 160px; }
  .zigzag__glyph { width: 72px; height: 72px; border-radius: 18px; }
  .zigzag__glyph::before { inset: -16px; border-radius: 26px; }
  .zigzag__glyph::after { inset: -32px; border-radius: 36px; }
  .zigzag h3 { font-size: 1.4rem; }

  .card, .stack__item, .steps__item, .stat { padding: 26px 22px 30px; }
  .split__intro h3 { font-size: 1.3rem; }
  .band--cta .panel { padding: 64px 28px; }
  .timeline { padding-left: 22px; }
  .timeline__item::before { left: -28px; }
  .faq__item summary { padding: 18px 20px; font-size: 1rem; }
  .faq__item p { padding: 0 20px 20px; }

  /* iOS zooms the whole page in when a focused field is under 16px. */
  .field input, .field select, .field textarea { font-size: 16px; }
  /* Stacked fields need a little more air between them than the 20px that
     separates them from their own label. */
  .field { margin-bottom: 24px; }
}

/* ------------------------------------------------------- 560px: phone -- */

@media (max-width: 560px) {
  :root { --art-size: 260% auto; }

  /* The bar can't hold a CTA next to the wordmark; the panel gets it instead,
     full width and first thing under the links. */
  .site-nav__end .btn { display: none; }
  .logo__full { height: 38px; }
  .site-nav .site-nav__cta { display: flex; margin-top: 20px; width: 100%; }

  .hero .lead { font-size: 1.0625rem; }
  .hero h1 { max-width: none; }
  .hero__byline, .hero__note { font-size: .9375rem; }
  .hero__note { margin-top: 32px; }
  .actions { gap: 12px; margin-top: 28px; }
  .actions .btn { width: 100%; white-space: normal; }

  .cards, .grid, .stack, .stats, .steps, .split__items { gap: 16px; }
  .card, .stack__item, .steps__item, .stat { padding: 24px 20px 26px; }
  .band--cta .panel { padding: 48px 22px; border-radius: 14px; }
  .band--cta h2, .band--cta .lead { max-width: none; }

  .form--thanks { padding: 24px 20px; }
  .site-footer__grid { grid-template-columns: 1fr; gap: 32px; }
  .site-footer__legal { margin-top: 40px; }
  .site-footer__langs { margin-left: 0; }
  .site-footer__panel { padding: 24px 20px; }

  .ftable { min-width: 520px; font-size: .9rem; }
  .ftable th, .ftable td { padding: 11px 12px; }
  .ftable thead th { font-size: .7rem; letter-spacing: .06em; }
  .ftable thead th:first-child { min-width: 150px; }
  .ftable tbody th { font-size: .875rem; }
  .ftable tbody th small { font-size: .75rem; }
  .ftable__val { font-size: .75rem; padding: 2px 8px; }
  .ftable tbody th.ftable__group { padding: 10px 12px; font-size: .75rem; letter-spacing: .1em; }
  .tablenotes { margin-top: 20px; gap: 10px; }
}

/* ------------------------------------------------ 380px: small phone -- */

@media (max-width: 380px) {
  .logo__text { font-size: 1.15rem; }
  .logo__full { height: 34px; }
  .btn { padding: 0 20px; }
  .card, .stack__item, .steps__item, .stat { padding: 22px 18px 24px; }
  .faq__item summary { padding: 16px; gap: 12px; }
  .faq__item p { padding: 0 16px 18px; }
}

@media (min-width: 1081px) {
  .tablewrap { overflow: visible; }
  .ftable { min-width: 0; }
  .ftable thead th {
    position: sticky; top: var(--header-h); z-index: 2;
    background: var(--surface);
    /* An inset shadow, not a border: borders on a sticky cell detach from it
       while it is pinned. */
    border-bottom: 0; box-shadow: inset 0 -1px 0 var(--line);
  }
  .ftable thead th:first-child { border-top-left-radius: var(--radius-card); }
  .ftable thead th:last-child { border-top-right-radius: var(--radius-card); }
}

/* A phone held sideways has almost no height: don't spend it all on hero
   padding before the headline appears. */
@media (max-width: 880px) and (max-height: 520px) and (orientation: landscape) {
  .hero { padding-top: calc(var(--header-h) + 28px); padding-bottom: 36px; }
}
