/* =====================================================================
   Vias Media v2 "Bauplan" — shared components
   buttons · header · menu sheet · rows · accordion · cursor · footer
   ===================================================================== */

/* =====================================================================
   Buttons — square, one height per row, plain state changes
   ===================================================================== */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.625rem;
  height: var(--ctl-h);
  padding-inline: 1.125rem;
  border: 1px solid var(--ink);
  border-radius: var(--radius);
  background: transparent;
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: 0.9375rem;
  font-weight: 550;
  letter-spacing: -0.005em;
  line-height: 1;
  white-space: nowrap;
  transition: background-color var(--dur-fast) ease, color var(--dur-fast) ease, border-color var(--dur-fast) ease;
}
.btn svg { width: 0.875rem; height: 0.875rem; flex: none; transition: transform var(--dur-base) var(--ease-out); }
.btn--lg { height: 3.25rem; padding-inline: 1.375rem; font-size: 1rem; }
.btn--accent { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.btn--solid { background: var(--ink); color: var(--ground); }
@media (hover: hover) {
  .btn:hover { background: var(--ink); border-color: var(--ink); color: var(--ground); }
  .btn--solid:hover { background: transparent; color: var(--ink); }
  .btn:hover .ico-arrow { transform: translateX(0.1875rem); }
}

/* the page's main action as a plain text link: small lower-case words and an
   arrow, in the second accent, no box and no underline. (Owner: "smaller and
   simpler", "smaller, in small letters", then "use #E8AE3A on the cta in the hero,
   the underline deleted".) Also used for "all projects" under the projects. */
.cta {
  position: relative;
  isolation: isolate;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  min-height: var(--ctl-h);      /* still a full-size touch target */
  padding-inline: 0.625rem;
  margin-inline: -0.625rem;      /* the words stay where they were; the fill gets room */
  color: var(--accent-2);
  font-size: 0.875rem;
  font-weight: 600;
  line-height: 1;
  text-transform: lowercase;
  white-space: nowrap;
}
/* hover: a gold fill sweeps in from the left behind the words, the words turn
   dark on it, the arrow runs on (owner, 2026-10-14: "more feedback on hover of
   the hero cta"). Only the layer's transform animates. */
.cta::before {
  content: "";
  position: absolute;
  inset: 0.375rem 0;
  z-index: -1;
  background: var(--accent-2);
  transform: scaleX(0);
  transform-origin: 0 50%;
  transition: transform 0.35s var(--ease-out);
}
.cta__ico { display: inline-flex; }
.cta__ico svg { width: 0.875rem; height: 0.875rem; transition: transform var(--dur-base) var(--ease-out); }
@media (hover: hover) {
  .cta:hover { color: var(--on-accent); transition: color 0s linear 0.08s; }
  .cta:hover::before { transform: scaleX(1); }
  .cta:hover .cta__ico svg { transform: translateX(0.375rem); }
}
.cta:focus-visible { outline-offset: 6px; }

/* =====================================================================
   Cranes — a small flock after an old print of whooping cranes (white
   bodies, dark primaries with hairlines between the feathers; on the dark
   ground the dark parts get an ink outline). Each crane crosses from left
   to right; main.js flies them (every flight different, see initFlock):
   the wings beat by scaling around the shoulder line, the far wing moves
   against the near one, as in the print. The flock's band (--band-a,
   --band-b: fractions of its height) is where the birds may fly.
   Decorative only (aria-hidden). Used in the homepage hero and in the
   "sent" dialog.
   ===================================================================== */
.flock {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  overflow: clip;
  pointer-events: none;
  color: var(--ink);
}
.crane {
  position: absolute;
  left: 0;
  top: var(--top, 50%);
  width: var(--w, 12rem);
  opacity: var(--o, 0.4);
  transform: translate3d(var(--rest, 50vw), 0, 0);       /* without the script: resting in the print's pose */
  transform-origin: 50% 50%;
}
/* the script flies them (main.js): it sets position, width and opacity per flight */
.flock.is-js .crane { top: 0; will-change: transform; }
.crane svg { display: block; width: 100%; height: auto; overflow: visible; }
.crane g { transform-box: view-box; }
.cr__wn,
.cr__wf { transform-origin: 0 100px; }
.cr__wf { transform: translate(22px, -4px) scale(0.8, -0.55); }
.cr-k { fill: currentColor; }
.cr-d { fill: var(--ground-2); stroke: currentColor; stroke-width: 1.3; stroke-linejoin: round; }
.cr-l { fill: none; stroke: currentColor; stroke-width: 1.1; stroke-linecap: round; }
.cr-leg { fill: none; stroke: currentColor; stroke-width: 2.6; stroke-linecap: round; }
.cr-x { fill: var(--ground); }
.cr-bl { fill: none; stroke: var(--ground); stroke-width: 1.1; opacity: 0.55; }

/* =====================================================================
   Header — one full-bleed bar on the page ground
   ===================================================================== */
.hdr {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: var(--z-header);
  height: var(--hdr-h);
  background: var(--ground);
  border-bottom: 1px solid transparent;
  transition: background-color var(--dur-base) ease, border-color var(--dur-base) ease, color var(--dur-base) ease;
}
.hdr.is-scrolled { border-bottom-color: var(--line-soft); }
.hdr__bar {
  height: 100%;
  display: flex;
  align-items: center;
  gap: var(--gutter);
}

.hdr__logo {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  height: var(--ctl-h);
  margin-right: auto;
  flex: none;
}
.hdr__logo img { width: auto; height: 1.5rem; }
/* the wordmark is the brand's own lettering: it stays in the grotesk, lower case */
.wordmark {
  font-family: var(--font-sans);
  font-stretch: 125%;
  font-weight: 650;
  font-size: 1.375rem;
  letter-spacing: -0.04em;
  line-height: 1;
}
.wordmark .dot { color: var(--accent); }

.hdr__nav {
  display: none;
  align-items: center;
  gap: 0.25rem;
}
/* bracketed plan labels as links */
.blink {
  display: inline-flex;
  align-items: center;
  height: var(--ctl-h);
  padding-inline: 0.75rem;
  font-family: var(--font-mono);
  font-stretch: 87.5%;
  font-size: var(--fs-mono);
  color: inherit;
}
.blink::before { content: "[\00a0"; content: "[\00a0" / ""; opacity: 0.62; }
.blink::after { content: "\00a0]"; content: "\00a0]" / ""; opacity: 0.62; }
/* where you are: a filled block, not just a heavier word */
.blink[aria-current] { background: var(--ink); color: var(--ground); font-weight: 600; }
.blink[aria-current]::before,
.blink[aria-current]::after { opacity: 1; }

/* word roll: the word is the front of a cube; on hover the cube turns a quarter
   and brings the same word up from below, all at once (owner, 2026-10-14: "the
   whole word should rotate at once, not each digit individually") */
.roll { display: inline-flex; }
.roll .ch {
  position: relative;
  display: inline-block;
  height: 1.4em;
  line-height: 1.4em;
  white-space: pre;
  transform-style: preserve-3d;
  transform-origin: 50% 50% -0.7em;
  transition: transform 0.55s var(--ease-io);
}
.roll .ch::after {
  content: attr(data-c);
  position: absolute;
  left: 0;
  top: 100%;
  height: 100%;
  transform-origin: 50% 0;
  transform: rotateX(-90deg);
}
@media (hover: hover) {
  a:hover > .roll .ch,
  button:hover > .roll .ch { transform: rotateX(90deg); }
  /* before JS has split the letters (or without JS): a plain underline */
  .blink:hover .roll:not(.is-split) { text-decoration: underline; text-underline-offset: 0.3em; }
}
@media (prefers-reduced-motion: reduce) {
  .roll .ch { transition: none; }
  a:hover > .roll .ch,
  button:hover > .roll .ch { transform: none; }
  .blink:hover .roll { text-decoration: underline; text-underline-offset: 0.3em; }
}

.hdr__tools {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.lang-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.25rem;
  height: var(--ctl-h);
  min-width: var(--ctl-h);
  padding-inline: 0.625rem;
  border: 1px solid var(--line);
  font-family: var(--font-mono);
  font-stretch: 87.5%;
  font-size: var(--fs-mono);
  transition: background-color var(--dur-fast) ease, border-color var(--dur-fast) ease;
}
.lang-toggle .lang-cur { font-weight: 700; }
.lang-toggle .lang-sep,
.lang-toggle .lang-alt { opacity: 0.62; }
@media (hover: hover) {
  .lang-toggle:hover { background: var(--line-soft); border-color: currentColor; }
}

/* burger: two bars that cross in place. Small on phones; the tap area stays 44px */
.burger {
  position: relative;
  width: 2.25rem;
  height: 2.25rem;
  border: 1px solid currentColor;
  order: 2;
  flex: none;
}
.burger::after { content: ""; position: absolute; inset: -0.25rem; }
.burger span {
  position: absolute;
  left: 0.5625rem;
  right: 0.5625rem;
  top: 50%;
  height: 1.5px;
  margin-top: -0.75px;
  background: currentColor;
  transition: transform var(--dur-base) var(--ease-out);
}
.burger span:nth-child(1) { transform: translateY(-0.1875rem); }
.burger span:nth-child(2) { transform: translateY(0.1875rem); }
.burger.is-open span:nth-child(1) { transform: rotate(45deg); }
.burger.is-open span:nth-child(2) { transform: rotate(-45deg); }
@media (min-width: 48rem) {
  .burger { width: 2.5rem; height: 2.5rem; }
  .burger span { left: 0.625rem; right: 0.625rem; }
}

/* phones: no bar and no button, only the logo and the burger over the page.
   A short scrim under them lets text that scrolls beneath fade out instead of
   running into the logo. The sheet menu brings the solid ground back. */
@media (max-width: 47.9375rem) {
  .hdr,
  .hdr.is-scrolled { background: transparent; border-bottom-color: transparent; }
  .hdr::before {
    content: "";
    position: absolute;
    inset: 0 0 -0.75rem 0;
    z-index: -1;
    pointer-events: none;
    background: linear-gradient(to bottom, rgba(20, 19, 18, 0.94), rgba(20, 19, 18, 0.74) 62%, rgba(20, 19, 18, 0));
  }
  .hdr__cta { display: none; }
  .menu-open .hdr { background: var(--ground); }
  .menu-open .hdr::before { display: none; }
}
@media (min-width: 62.5rem) {
  /* laptops: logo and the four links, nothing else (language lives in the
     footer and in the phone menu) */
  .hdr__nav { display: flex; margin-left: auto; margin-right: -0.75rem; }
  .hdr__tools { display: none; }
  .hdr__logo { margin-right: 0; }
}
.menu-open .hdr { border-bottom-color: var(--line-soft); }

/* =====================================================================
   Menu sheet (≤ 999px) — full screen under the bar, slides in from the right
   ===================================================================== */
.menu {
  position: fixed;
  inset: var(--hdr-h) 0 0 0;
  z-index: var(--z-menu);
  overflow: hidden;            /* clips the off-screen panel: no sideways scroll */
  visibility: hidden;
  transition: visibility 0s linear var(--dur-base);
}
.menu.is-open { visibility: visible; transition-delay: 0s; }
.menu__panel {
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: 1fr auto;
  background: var(--ground);
  transform: translateX(100%);
  transition: transform var(--dur-base) var(--ease-out);
  overflow-y: auto;
  overscroll-behavior: contain;
}
.menu.is-open .menu__panel { transform: none; }
.menu__list { align-self: start; }
.menu__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  min-height: 4.25rem;
  padding: 0.5rem var(--margin);
  border-bottom: 1px solid var(--line-soft);
  font-family: var(--font-display);
  font-size: 2.25rem;
  letter-spacing: 0.01em;
  line-height: 1;
  transition: background-color var(--dur-fast) ease, color var(--dur-fast) ease;
}
.menu__row svg { width: 1.125rem; height: 1.125rem; flex: none; transition: transform var(--dur-base) var(--ease-out); }
.menu__row[aria-current] { background: var(--line-soft); }
/* the row answers the finger (active) and the pointer (hover) the same way */
.menu__row:active { background: var(--ink); color: var(--ground); }
@media (hover: hover) {
  .menu__row:hover { background: var(--ink); color: var(--ground); }
  .menu__row:hover svg { transform: translateX(0.375rem); }
}
/* foot: the call tile (an icon in a square) on the left, the main action beside it */
.menu__foot {
  display: flex;
  flex-direction: row-reverse;
  gap: 0.5rem;
  padding: var(--margin);
  padding-bottom: calc(var(--margin) + env(safe-area-inset-bottom, 0px));
}
.menu__foot .btn { flex: 1; height: 3.25rem; padding-inline: 0.5rem; }
.menu__foot .menu__call { flex: none; width: 3.25rem; padding: 0; }
.menu__call svg { width: 1.25rem; height: 1.25rem; }
@media (min-width: 62.5rem) {
  .menu { display: none; }
}
@media (max-width: 22.5rem) {
  .menu__row { font-size: 2rem; min-height: 3.75rem; }
}

/* =====================================================================
   Rows — hairline lists instead of card grids
   ===================================================================== */
.rows { border-top: 1px solid var(--line); }
.row {
  display: grid;
  grid-template-columns: repeat(var(--cols), minmax(0, 1fr));
  column-gap: var(--gutter);
  row-gap: 0.5rem;
  align-items: baseline;
  padding-block: var(--row-pad);
  border-bottom: 1px solid var(--line);
}
.row__n {
  grid-column: 1 / -1;
  font-family: var(--font-mono);
  font-stretch: 87.5%;
  font-size: var(--fs-mono);
  color: var(--ink-3);
}
.row__n::before { content: "[\00a0"; content: "[\00a0" / ""; }
.row__n::after { content: "\00a0]"; content: "\00a0]" / ""; }
.row__t { grid-column: 1 / -1; }
.row__d { grid-column: 1 / -1; }
.row__d p { color: var(--ink-2); max-width: 34rem; text-wrap: pretty; }

/* a row that is a link inverts. The inversion is a layer that only changes
   opacity (compositor work); the text switches colour in one step, so nothing
   repaints frame by frame while the pointer travels down the list. */
a.row { position: relative; isolation: isolate; }
a.row::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--ink);
  opacity: 0;
  transition: opacity 0.16s ease;
}
.row__go {
  grid-column: -2 / -1;
  grid-row: 1;
  justify-self: end;
  align-self: center;
}
.row__go svg { width: 1.125rem; height: 1.125rem; transition: transform var(--dur-base) var(--ease-out); }
@media (hover: hover) {
  a.row:hover { color: var(--ground); }
  a.row:hover::before { opacity: 1; }
  a.row:hover .row__n,
  a.row:hover .row__d p { color: inherit; }
  a.row:hover .row__go svg { transform: translateX(0.25rem); }
}
a.row:focus-visible { outline-offset: -3px; }

/* =====================================================================
   Accordion (FAQ) — one open at a time, plus turns into minus
   ===================================================================== */
/* section layout: head beside the list on laptops (the head stays in view) */
.faq { row-gap: var(--head-gap); }
.faq__head { grid-column: 1 / -1; display: grid; gap: var(--block-gap); align-content: start; }
.faq__list { grid-column: 1 / -1; align-self: start; }
@media (min-width: 62.5rem) {
  .faq__head { grid-column: 1 / span 3; position: sticky; top: calc(var(--hdr-h) + 2rem); }
  .faq__list { grid-column: 4 / -1; }
}
.faq__list { border-top: 1px solid var(--line); }
.faq-item { border-bottom: 1px solid var(--line); }
.faq-item__q {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.25rem;
  padding-block: var(--row-pad);
  text-align: left;
}
.faq-item__q > span:first-child { min-width: 0; text-wrap: balance; overflow-wrap: break-word; -webkit-hyphens: auto; hyphens: auto; }
.faq-item__icon {
  position: relative;
  flex: none;
  width: 2rem;
  height: 2rem;
  border: 1px solid var(--line);
  transition: background-color var(--dur-fast) ease, border-color var(--dur-fast) ease, color var(--dur-fast) ease;
}
.faq-item__icon::before,
.faq-item__icon::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 0.75rem;
  height: 1.5px;
  margin: -0.75px 0 0 -0.375rem;
  background: currentColor;
  transition: transform var(--dur-base) var(--ease-out);
}
.faq-item__icon::after { transform: rotate(90deg); }
.faq-item.is-open .faq-item__icon { background: var(--ink); border-color: var(--ink); color: var(--ground); }
.faq-item.is-open .faq-item__icon::after { transform: rotate(0deg); }
@media (hover: hover) {
  .faq-item__q:hover .faq-item__icon { border-color: var(--ink); }
}
.faq-item__panel {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--dur-base) var(--ease-out);
}
.faq-item.is-open .faq-item__panel { grid-template-rows: 1fr; }
.faq-item__answer {
  min-height: 0;
  overflow: hidden;
  visibility: hidden;
  transition: visibility 0s linear var(--dur-base);
}
.faq-item.is-open .faq-item__answer { visibility: visible; transition-delay: 0s; }
.faq-item__answer p {
  padding-bottom: var(--row-pad);
  max-width: 38rem;
  color: var(--ink-2);
  text-wrap: pretty;
}
/* without JS every answer is simply open */
html:not(.js) .faq-item__panel { grid-template-rows: 1fr; }
html:not(.js) .faq-item__answer { visibility: visible; }
html:not(.js) .faq-item__icon { display: none; }

/* =====================================================================
   Cursor (fine pointers only): a drafting crosshair with a label.
   One moving element, no blend mode: the earlier full-screen difference
   layer cost a render pass on every frame.
   ===================================================================== */
.cur { display: none; }
@media (hover: hover) and (pointer: fine) {
  html.has-cur,
  html.has-cur * { cursor: none !important; }
  html.has-cur input,
  html.has-cur textarea { cursor: text !important; }
  html.has-cur .cur { display: block; }
  .cur {
    position: fixed;
    left: 0;
    top: 0;
    z-index: var(--z-cursor);
    pointer-events: none;
    color: var(--ink);
    opacity: 0;
    transition: opacity var(--dur-fast) ease, color var(--dur-fast) ease;
  }
  .cur.is-live { opacity: 1; }
  .cur__pos,
  .cur__tag { position: absolute; left: 0; top: 0; will-change: translate; }
  .cur__h { position: absolute; left: -100vw; top: 0; width: 200vw; height: 1px; background: currentColor; opacity: 0.13; }
  .cur__v { position: absolute; left: 0; top: -100vh; width: 1px; height: 200vh; background: currentColor; opacity: 0.13; }
  .cur__x {
    position: absolute;
    left: -0.6875rem;
    top: -0.6875rem;
    width: 1.375rem;
    height: 1.375rem;
    background:
      linear-gradient(currentColor, currentColor) 50% 50% / 100% 1.5px no-repeat,
      linear-gradient(currentColor, currentColor) 50% 50% / 1.5px 100% no-repeat;
    transition: scale var(--dur-base) var(--ease-out), rotate var(--dur-base) var(--ease-out), opacity var(--dur-fast) ease;
  }
  .cur.is-link .cur__x { rotate: 45deg; scale: 0.8; }
  .cur.is-down .cur__x { scale: 0.6; }
  /* over a labelled target the label is the cursor */
  .cur.has-tag .cur__x { opacity: 0; }
  .cur__tag {
    margin: -0.75rem 0 0 0.625rem;
    padding: 0.4375rem 0.5625rem;
    background: var(--accent);
    color: #161514;
    font-family: var(--font-mono);
    font-stretch: 87.5%;
    font-size: var(--fs-mono-s);
    font-weight: 600;
    line-height: 1;
    white-space: nowrap;
    opacity: 0;
    transition: opacity var(--dur-fast) ease;
  }
  .cur.has-tag .cur__tag { opacity: 1; }
}

/* =====================================================================
   Footer
   ===================================================================== */
.ftr {
  position: relative;        /* the section before it brings the space above */
  overflow: hidden;
  overflow: clip;
}
/* The last section of a page can stand still while the footer slides over it:
   .tail wraps that section and adds one screen of travel; the footer starts that
   screen early. main.js pins the section by its bottom edge (it is usually taller
   than the screen), so all of this waits for the script (.js, not .rv-fallback).
   The section is scrolled to its very end first and then holds for a quarter of
   a screen (the extra 25 in the travel) before the footer starts to cover it. */
.js:not(.rv-fallback) .tail { position: relative; z-index: 1; }
.js:not(.rv-fallback) .tail > .s { position: sticky; top: 0; }
.js:not(.rv-fallback) .tail::after { content: ""; display: block; height: calc(var(--vh, 1vh) * 125); }
.js:not(.rv-fallback) .ftr--over {
  z-index: 2;
  margin-top: calc(var(--vh, 1vh) * -100);
  padding-top: var(--section);
  background: var(--ground);
  border-top: 1px solid var(--line-soft);
}
@media (prefers-reduced-motion: reduce) {
  .js:not(.rv-fallback) .tail > .s { position: relative; top: auto !important; }
  .js:not(.rv-fallback) .tail::after { display: none; }
  .js:not(.rv-fallback) .ftr--over { margin-top: 0; padding-top: 0; border-top: 0; }
}
.ftr__cta { row-gap: var(--head-gap); }
.ftr__cta .s__label,
.ftr__cta .s__head,
.ftr__cta .s__body { grid-column: 1 / -1; margin-bottom: 0; }
/* the closing question on two lines of almost equal length, stacked and left
   aligned. They rise one after the other like every title; then the accent
   block sweeps in behind the second line from the left, and the words turn
   dark on it once it is complete. (Owner, 2026-10-14: the halves that came in
   from both sides were "really bad and unbalanced".) */
.ftr__big {
  font-size: clamp(2.75rem, 1.2rem + 7.4vw, 8.5rem);
  line-height: 0.86;
}
.js .ftr__big .mark {
  transition: background-size 0.8s var(--ease-io) 0.55s, color 0.25s ease 1.25s;
}
.js .ftr__big:not(.is-in) .mark {
  background-size: 0% 1.02em;
  color: var(--ink);
  transition: none;
}
@media (prefers-reduced-motion: reduce) {
  .js .ftr__big .mark { transition: none; }
}
.rv-fallback .ftr__big .mark { background-size: 100% 1.02em; color: var(--on-accent); }
.ftr__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.ftr__lines {
  margin-top: var(--head-gap);
  border-top: 1px solid var(--line);
}
.ftr__line {
  position: relative;
  isolation: isolate;
  display: flex;
  align-items: center;
  justify-content: center;
  padding-block: clamp(0.875rem, 0.6rem + 1.2vw, 1.5rem);
  border-bottom: 1px solid var(--line);
  font-family: var(--font-sans);
  font-stretch: 125%;
  font-weight: 450;
  font-size: clamp(1.0625rem, 0.3rem + 3.9vw, 3.75rem);   /* the e-mail fits one line at 320px */
  letter-spacing: -0.035em;
  line-height: 1.05;
}
.ftr__line::before { content: ""; position: absolute; inset: 0; z-index: -1; background: var(--ink); opacity: 0; transition: opacity 0.16s ease; }
.ftr__line > span::before { content: "[\00a0"; content: "[\00a0" / ""; font-weight: 300; }
.ftr__line > span::after { content: "\00a0]"; content: "\00a0]" / ""; font-weight: 300; }
@media (hover: hover) {
  .ftr__line:hover { color: var(--ground); }
  .ftr__line:hover::before { opacity: 1; }
}

.ftr__cols {
  margin-top: var(--head-gap);
  row-gap: var(--block-gap);
}
.ftr__col { grid-column: span 2; display: flex; flex-direction: column; align-items: flex-start; gap: 0.125rem; }
.ftr__col--nap { grid-column: 1 / -1; }
.ftr__col .tag { margin-bottom: 0.5rem; }
.ftr__col a,
.ftr__col span,
.ftr__col button {
  font-size: var(--fs-small);
  line-height: 1.3;
  color: var(--ink-2);
  padding-block: 0.3125rem;
}
.ftr__col a,
.ftr__col button { text-decoration: underline; text-decoration-color: transparent; text-underline-offset: 0.2em; transition: color var(--dur-fast) ease, text-decoration-color var(--dur-fast) ease; }
@media (hover: hover) {
  .ftr__col a:hover,
  .ftr__col button:hover { color: var(--ink); text-decoration-color: currentColor; }
}
@media (min-width: 48rem) {
  .ftr__col { grid-column: span 2; }
  .ftr__col--nap { grid-column: span 2; }
}

.ftr__word {
  margin-top: var(--head-gap);
  font-family: var(--font-sans);
  font-stretch: 125%;
  font-weight: 600;
  font-size: 41vw;
  letter-spacing: -0.06em;
  line-height: 0.74;
  white-space: nowrap;
  margin-left: -0.045em;
  margin-bottom: -0.03em;
  user-select: none;
  pointer-events: none;      /* its tall line box reaches over the links above it */
}
.ftr__word .dot { color: var(--accent); }
.ftr__legal {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: 0.5rem 1.5rem;
  padding-block: 1rem;
  padding-bottom: calc(1rem + env(safe-area-inset-bottom, 0px));
  background: var(--ink);
  color: var(--ground);
}
.ftr__legal .mono { font-size: var(--fs-mono-s); }
.ftr__legal nav { display: flex; flex-wrap: wrap; align-items: center; gap: 0.25rem 1.25rem; }
.ftr__legal a,
.ftr__legal button {
  font-family: var(--font-mono);
  font-stretch: 87.5%;
  font-size: var(--fs-mono-s);
  line-height: 1.45;
  padding-block: 0.375rem;
}
.ftr__legal a::before,
.ftr__legal button::before { content: "[\00a0"; content: "[\00a0" / ""; opacity: 0.6; }
.ftr__legal a::after,
.ftr__legal button::after { content: "\00a0]"; content: "\00a0]" / ""; opacity: 0.6; }
.ftr__legal :focus-visible { outline-color: var(--ground); }
/* the language switch, written like its neighbours */
.lang-toggle--plain {
  display: inline;
  height: auto;
  min-width: 0;
  padding-inline: 0;
  border: 0;
}
.lang-toggle--plain .lang-cur,
.lang-toggle--plain .lang-sep { margin-right: 0.25em; }
@media (hover: hover) {
  .ftr__legal a:hover,
  .ftr__legal button:hover { background: none; text-decoration: underline; text-underline-offset: 0.25em; }
}

/* =====================================================================
   Enquiry form — the three-step quiz, used on the contact page and in the
   enquiry modal (below). Fields are one height with the buttons, square,
   a hairline frame; the error line sits in the gap under its field and
   never moves anything.
   ===================================================================== */
.form {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  row-gap: 1.75rem;
  column-gap: 0.5rem;
  padding: clamp(1.125rem, 0.9rem + 1.2vw, 2rem);
  background: var(--ground-2);
}
/* fields: one height with the buttons, square, a hairline frame. The error
   line sits in the gap under its field and never moves anything. */
.field { position: relative; display: grid; gap: 0.5rem; }
.field__label {
  font-family: var(--font-mono);
  font-stretch: 87.5%;
  font-size: var(--fs-mono);
  color: var(--ink-2);
}
.field__opt { color: var(--ink-3); }
.field input,
.field textarea {
  width: 100%;
  height: 3.25rem;
  padding: 0 0.875rem;
  border: 1px solid var(--line);
  border-radius: 0;
  background: var(--ground);
  color: var(--ink);
  font: inherit;
  font-size: 1rem;
  line-height: 1.3;
  -webkit-appearance: none;
  appearance: none;
  transition: border-color var(--dur-fast) ease;
}
.field textarea { height: 8.5rem; padding-block: 0.875rem; resize: vertical; }
.field input:focus-visible,
.field textarea:focus-visible { outline: 2px solid var(--ink); outline-offset: 0; border-color: var(--ink); }
@media (hover: hover) {
  .field input:hover,
  .field textarea:hover { border-color: var(--ink-3); }
}
.field.is-invalid input { border-color: var(--accent-ink); }
/* a field that is right confirms itself: a gold tick inside it */
.field[data-check]::after {
  content: "";
  position: absolute;
  right: 1rem;
  bottom: 1.4rem;
  width: 0.75rem;
  height: 0.4375rem;
  border-left: 2px solid var(--accent-2);
  border-bottom: 2px solid var(--accent-2);
  transform: rotate(-45deg) scale(0.4);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-fast) ease, transform var(--dur-base) var(--ease-out);
}
.field.is-valid::after { opacity: 1; transform: rotate(-45deg) scale(1); }
.field[data-check] input { padding-right: 2.5rem; }
.field__error {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(100% + 0.25rem);
  overflow: hidden;
  font-size: 0.8125rem;
  line-height: 1.2;
  color: var(--accent-ink);
  white-space: nowrap;
  text-overflow: ellipsis;
  visibility: hidden;
}
.field.is-invalid .field__error { visibility: visible; }

/* The enquiry as a short quiz. Every step lies in the same grid cell, so the
   panel is as tall as its tallest step and never changes height; only the
   active one is visible. Without JavaScript the steps just follow each other. */
.quiz { grid-template-columns: minmax(0, 1fr); row-gap: 1.25rem; }
.quiz__bar { display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
.quiz__count { color: var(--ink-2); }
.quiz__meter { display: flex; gap: 0.25rem; width: min(50%, 11rem); }
.quiz__meter i { flex: 1; height: 0.25rem; background: var(--line); transition: background-color var(--dur-base) ease; }
.quiz__meter i.is-on { background: var(--ink); }
.quiz__meter i.is-done { background: var(--accent-2); }   /* a step behind you is done: the positive colour */
.quiz__step { display: grid; gap: 1.75rem; align-content: start; min-width: 0; }   /* the gap holds a field's error line */
.quiz__q { font-size: var(--fs-d2); line-height: 0.92; }
.quiz__q:focus { outline: none; }
.quiz__tiles { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.375rem; }
.tile {
  display: flex;
  align-items: flex-end;
  min-height: 4.5rem;
  padding: 0.75rem 0.875rem;
  border: 1px solid var(--line);
  background: var(--ground);
  font-weight: 550;
  line-height: 1.2;
  text-align: left;
  transition: border-color var(--dur-fast) ease, background-color var(--dur-fast) ease, color var(--dur-fast) ease;
}
/* the chosen answer: filled in the positive colour, with a tick */
.tile { position: relative; padding-right: 2.25rem; }
.tile::after {
  content: "";
  position: absolute;
  right: 0.75rem;
  top: 0.75rem;
  width: 0.875rem;
  height: 0.5rem;
  border-left: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(-45deg) scale(0.4);
  opacity: 0;
  transition: opacity var(--dur-fast) ease, transform var(--dur-base) var(--ease-out);
}
.tile[aria-checked="true"] { background: var(--accent-2); border-color: var(--accent-2); color: var(--on-accent); }
.tile[aria-checked="true"]::after { opacity: 1; transform: rotate(-45deg) scale(1); }
.tile:focus-visible { outline-offset: -2px; }
@media (hover: hover) {
  .tile:not([aria-checked="true"]):hover { border-color: var(--ink); }
}
.quiz__done { justify-items: start; }
.quiz__done p { color: var(--ink-2); }
/* one row at every width (a second row would change the panel's height between steps):
   "back" is an arrow in a square, the action takes what it needs */
.quiz__nav { display: flex; justify-content: space-between; gap: 0.5rem; min-height: 3.25rem; }
.quiz__back { flex: none; width: 3.25rem; padding: 0; }
.quiz__back svg { width: 1.125rem; height: 1.125rem; transform: scaleX(-1); }
.quiz__next,
.quiz__send { margin-left: auto; }
.form__note { font-size: 0.8125rem; line-height: 1.4; color: var(--ink-2); }
/* the reserved line under the steps: a confirmation for every action (gold, with a
   tick) or why sending failed. Both share one cell, so the form keeps its height */
.quiz__msg { display: grid; min-height: 2.6em; margin-top: -0.5rem; font-size: 0.875rem; line-height: 1.3; }
.quiz__msg > * { grid-area: 1 / 1; }
.quiz__fb { color: var(--accent-2); font-weight: 550; opacity: 0; transform: translate3d(0, 0.25rem, 0); }
.quiz__fb.is-on { opacity: 1; transform: none; transition: opacity 0.3s ease, transform 0.4s var(--ease-out); }
.quiz__fb.is-on::before { content: "\2713\00a0\00a0"; content: "\2713\00a0\00a0" / ""; }
.form__status { color: var(--accent-ink); }
.form__status:empty { display: none; }
/* what has been chosen so far, one quiet line under the progress bar */
.quiz__sum { min-height: 1.45em; margin-top: -0.5rem; color: var(--ink-2); overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.quiz__sum.is-on::before { content: "\2713\00a0"; content: "\2713\00a0" / ""; color: var(--accent-2); }
@media (min-width: 37.5rem) {
  .quiz__msg { min-height: 1.4em; }
}
.hp { position: absolute; left: -200vw; width: 1px; height: 1px; overflow: hidden; }
.quiz__busy,
.quiz__sent,
.is-sending .quiz__idle,
.is-sent .quiz__idle { display: none; }
.is-sending .quiz__busy,
.is-sent .quiz__sent { display: inline; }
/* sent: the button itself turns to the positive colour for the moment before the thank-you page */
.is-sent .quiz__send { background: var(--accent-2); border-color: var(--accent-2); color: var(--on-accent); }
.is-sent .quiz__send .ico-arrow { display: none; }
.is-sent .quiz__send::after { content: "\2713"; content: "\2713" / ""; font-weight: 700; }
html:not(.js) .quiz__bar,
html:not(.js) .quiz__sum,
html:not(.js) .quiz__back,
html:not(.js) .quiz__next,
html:not(.js) .quiz__done { display: none; }
.js .quiz__steps { display: grid; grid-template-columns: minmax(0, 1fr); }
.js .quiz__step {
  grid-area: 1 / 1;
  visibility: hidden;
  opacity: 0;
  transform: translate3d(1.25rem, 0, 0);
  transition: opacity var(--dur-base) ease, transform var(--dur-base) var(--ease-out), visibility 0s linear var(--dur-base);
}
.js .quiz__step.is-active { visibility: visible; opacity: 1; transform: none; transition-delay: 0s; }
/* which buttons a step shows (data-at is set on the form by main.js) */
.js .quiz[data-at="1"] .quiz__back,
.js .quiz:not([data-at="3"]) .quiz__send,
.js .quiz[data-at="3"] .quiz__next,
.js .quiz[data-at="done"] .quiz__nav,
.js .quiz[data-at="done"] .quiz__bar { display: none; }
.quiz__go,
.quiz[data-filled] .quiz__skip { display: none; }
.quiz[data-filled] .quiz__go { display: inline; }
@media (prefers-reduced-motion: reduce) {
  .js .quiz__step { transform: none; transition: none; }
}

.tile:not([aria-checked="true"]):active { background: var(--ink); border-color: var(--ink); color: var(--ground); }

/* =====================================================================
   Enquiry modal — a centred panel on laptops, a full-screen sheet on
   phones. One size for every step (the quiz never changes height). The
   page behind is pinned (main.js), the scrim closes it.
   ===================================================================== */
.mq {
  position: fixed;
  inset: 0;
  z-index: 70;
  display: grid;
  place-items: center;
  visibility: hidden;
  transition: visibility 0s linear 0.45s;
}
.mq.is-open { visibility: visible; transition-delay: 0s; }
/* closed, nothing of it may be hit: the active quiz step sets visibility: visible
   itself and would otherwise sit unseen in the middle of every page, catching the
   pointer (found 2026-10-14: "not a single effect fires and my cursor tries to select text") */
.mq:not(.is-open) { pointer-events: none; }
.mq:not(.is-open) .quiz__step { visibility: hidden; }
.mq__scrim { position: absolute; inset: 0; background: rgba(12, 11, 10, 0.78); opacity: 0; transition: opacity 0.35s ease; }
.mq.is-open .mq__scrim { opacity: 1; }
.mq__panel {
  position: relative;
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100%;
  overflow-y: auto;
  overscroll-behavior: contain;
  background: var(--ground-2);
  transform: translate3d(0, 2.5rem, 0);
  opacity: 0;
  transition: transform 0.5s var(--ease-out), opacity 0.3s ease;
}
.mq.is-open .mq__panel { transform: none; opacity: 1; }
.mq__head {
  position: sticky;
  top: 0;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.5rem 0.5rem 0.5rem clamp(1.125rem, 0.9rem + 1.2vw, 2rem);
  padding-top: calc(0.5rem + env(safe-area-inset-top, 0px));
  border-bottom: 1px solid var(--line-soft);
  background: var(--ground-2);
}
.mq__title { margin: 0; font-weight: 400; }
.mq__x { position: relative; flex: none; width: var(--ctl-h); height: var(--ctl-h); border: 1px solid var(--line); transition: background-color var(--dur-fast) ease, border-color var(--dur-fast) ease, color var(--dur-fast) ease; }
.mq__x::before,
.mq__x::after { content: ""; position: absolute; left: 50%; top: 50%; width: 1rem; height: 1.5px; margin: -0.75px 0 0 -0.5rem; background: currentColor; transform: rotate(45deg); }
.mq__x::after { transform: rotate(-45deg); }
@media (hover: hover) {
  .mq__x:hover { background: var(--ink); border-color: var(--ink); color: var(--ground); }
}
.mq__x:active { background: var(--ink); border-color: var(--ink); color: var(--ground); }
.mq__form { flex: 1; align-content: start; padding-bottom: calc(clamp(1.125rem, 0.9rem + 1.2vw, 2rem) + env(safe-area-inset-bottom, 0px)); }
@media (min-width: 48rem) {
  .mq { padding: var(--margin); }
  .mq__panel { width: min(100%, 40rem); height: auto; max-height: calc(100% - 2rem); border: 1px solid var(--line); }
  .mq__head { padding-top: 0.5rem; }
}
@media (prefers-reduced-motion: reduce) {
  .mq__panel,
  .mq__scrim { transition: none; }
}

/* =====================================================================
   Sent — the confirmation after an enquiry, always a dialog. The hero's
   cranes fly through its top band, a seal in the positive colour draws
   itself. Opened by main.js after a send; without JavaScript the form's
   redirect lands on #gesendet and :target shows it.
   ===================================================================== */
.sent {
  position: fixed;
  inset: 0;
  z-index: 72;
  display: grid;
  place-items: center;
  visibility: hidden;
  pointer-events: none;
  transition: visibility 0s linear 0.45s;
}
.sent.is-open,
.sent:target { visibility: visible; pointer-events: auto; transition-delay: 0s; }
.sent__scrim { position: absolute; inset: 0; background: rgba(12, 11, 10, 0.82); opacity: 0; transition: opacity 0.35s ease; }
.sent.is-open .sent__scrim,
.sent:target .sent__scrim { opacity: 1; }
.sent__panel {
  position: relative;
  width: 100%;
  height: 100%;
  overflow-x: hidden;
  overflow-y: auto;
  overscroll-behavior: contain;
  background: var(--ground-2);
  opacity: 0;
  transform: translate3d(0, 2.5rem, 0);
  transition: transform 0.55s var(--ease-out), opacity 0.3s ease;
}
.sent.is-open .sent__panel,
.sent:target .sent__panel { opacity: 1; transform: none; }
.sent__flock { bottom: auto; height: 10.5rem; --band-a: 0.1; --band-b: 0.58; }
.sent__flock .crane { --w: clamp(6.5rem, 26%, 10rem); --o: 0.55; --top: 26%; }
.sent__flock .crane--2 { --top: 12%; --rest: 46%; }
.sent__flock .crane--3 { --top: 44%; --rest: 20%; }
.sent__head {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  min-height: 9.5rem;
  padding: calc(0.5rem + env(safe-area-inset-top, 0px)) 0.5rem 0 clamp(1.125rem, 0.9rem + 1.2vw, 2rem);
}
.sent__head .mq__x { align-self: flex-start; }
.sent__seal { width: 3.5rem; height: 3.5rem; fill: none; stroke: var(--accent-2); stroke-width: 2.5; stroke-linecap: square; }
.sent__seal circle { stroke-dasharray: 189; transform: rotate(-90deg); transform-origin: 50% 50%; }
.sent__seal path { stroke-dasharray: 44; }
.sent.is-open .sent__seal circle,
.sent:target .sent__seal circle { animation: sent-draw 0.9s var(--ease-out) 0.25s both; }
.sent.is-open .sent__seal path,
.sent:target .sent__seal path { animation: sent-tick 0.5s var(--ease-out) 1s both; }
@keyframes sent-draw { from { stroke-dashoffset: 189; } }
@keyframes sent-tick { from { stroke-dashoffset: 44; } }
.sent__body {
  position: relative;
  z-index: 1;
  display: grid;
  gap: 1.25rem;
  justify-items: start;
  padding: 1.25rem clamp(1.125rem, 0.9rem + 1.2vw, 2rem) calc(clamp(1.125rem, 0.9rem + 1.2vw, 2rem) + env(safe-area-inset-bottom, 0px));
}
.sent__body > * { max-width: 100%; }
.sent__title { font-size: clamp(3rem, 2rem + 4vw, 5.5rem); line-height: 0.86; overflow-wrap: break-word; }
.sent__title:focus { outline: none; }
.sent__lead { font-size: 1.0625rem; line-height: 1.45; color: var(--ink-2); max-width: 30rem; text-wrap: pretty; }
.sent__lead .em { color: var(--ink); font-weight: 600; }
.sent__sum { color: var(--ink-2); }
.sent__sum::before { content: "\2713\00a0"; content: "\2713\00a0" / ""; color: var(--accent-2); }
.sent__next { display: grid; gap: 0.75rem; width: 100%; margin-top: 0.5rem; }
.sent__next .row { grid-template-columns: 3rem minmax(0, 1fr); row-gap: 0.25rem; padding-block: 0.875rem; }
.sent__next .row__n { grid-column: 1; grid-row: 1 / span 2; }
.sent__next .row__t { grid-column: 2; font-weight: 600; }
.sent__next .row__d { grid-column: 2; color: var(--ink-2); font-size: 0.9375rem; }
.sent__act { display: flex; flex-wrap: wrap; align-items: center; gap: 0.75rem 1.75rem; margin-top: 0.5rem; }
@media (min-width: 48rem) {
  .sent { padding: var(--margin); }
  .sent__panel { width: min(100%, 42rem); height: auto; max-height: calc(100% - 2rem); border: 1px solid var(--line); }
  .sent__head { padding-top: 0.5rem; }
}
@media (prefers-reduced-motion: reduce) {
  .sent__panel,
  .sent__scrim { transition: none; }
  .sent .sent__seal circle,
  .sent .sent__seal path { animation: none !important; }
}

/* =====================================================================
   Consent banner — adopt the plan's look, fix link contrast
   ===================================================================== */
#cc-banner { border-top-color: var(--ink); }
.cc-link { color: var(--accent-ink); }
.cc-link:hover { color: var(--ink); }
.cc-title,
.cc-modal__title { font-family: var(--font-sans); font-stretch: 125%; letter-spacing: -0.02em; }

/* =====================================================================
   Pressed states — what a finger gets instead of hover: the same change
   the pointer sees, for as long as the finger is down. (iOS applies
   :active only because main.js registers a touchstart listener.)
   ===================================================================== */
a,
button { -webkit-tap-highlight-color: transparent; }
.btn:active { background: var(--ink); border-color: var(--ink); color: var(--ground); }
.btn--solid:active { background: transparent; color: var(--ink); }
.cta:active { color: var(--on-accent); }
.cta:active::before { transform: scaleX(1); transition-duration: 0.12s; }
.cta:active .cta__ico svg { transform: translateX(0.375rem); }
.burger:active { background: var(--ink); color: var(--ground); }
.lang-toggle:active { background: var(--ink); border-color: var(--ink); color: var(--ground); }
a.row:active { color: var(--ground); }
a.row:active::before { opacity: 1; }
a.row:active .row__n,
a.row:active .row__d p { color: inherit; }
.faq-item__q:active { background: var(--ink); color: var(--ground); box-shadow: -0.75rem 0 0 var(--ink), 0.75rem 0 0 var(--ink); }
.faq-item__q:active .faq-item__icon { border-color: currentColor; }
.ftr__line:active { color: var(--ground); }
.ftr__line:active::before { opacity: 1; }
.ftr__col a:active,
.ftr__col button:active { color: var(--ink); text-decoration-color: currentColor; }
