/* GENERATED by design-system/static/tools/theme-sync.mjs from design-system/web-austria/components.css.
   Do not edit here: change the design system and run the sync again. */
/* components.css — the base classes every page uses (hand-maintained).
   Reads tokens.css for everything a designer would change: colours, faces, type sizes, radii, shadows, motion, and
   the spacing between blocks and sections (--margin, --gutter, --section*, --gap-*, --pad-*). No hex and no font
   family here — the one exception is the roof mark's five tile colours (.roof), an illustration of the real
   Stephansdom roof, kept fixed on purpose (client, 2026-10-26). Inside a component, padding, gaps and small margins
   use only six fixed steps: .25 / .5 / .75 / 1 / 1.25 / 1.5rem (4–24 px). Component sizes (widths, heights, icon
   and portrait sizes, overlaps) may be fixed rem. When a component changes, change it here so every instance
   follows (CLAUDE.md). Structure from Cortea (../raw/rules.md Part 2); edges per §1.4, hover per §1.6, mobile per §1.11.

   Breakpoints (max-width, so each rule applies below the width):
     47.99rem  768 px   phone: one column, swipe rows, the header's compact bar
     63.99rem  1024 px  tablet: two columns, the hero photos' foot row, booking stacks
     79.99rem  1280 px  laptop: services rows taller, two testimonials per view, the FAQ stacks
   and only for one component each:
     84.99rem  1360 px  the roof mark gets smaller before it meets the H1's second line
     55.99rem  896 px   the header's links give way to the menu button
     24.99rem  400 px   the logo drops its name
     @container 70rem   hero photo row: the proof cards straddle the foot of both photos
     @container 14rem   project card: logo over one line of tags

   Load order on a page: tokens.css (imports fonts/fonts.css) → components.css → page CSS. */

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body { margin: 0; font-family: var(--font-text); font-weight: var(--text-weight); font-size: var(--text-size);
  line-height: var(--text-leading); background: var(--bg); color: var(--text); }
img { display: block; max-width: 100%; }
[hidden] { display: none !important; }   /* the attribute always wins over a component's display */
a { color: inherit; }
h1, h2, h3, p, ul, ol, figure, blockquote { margin: 0; }

/* Motion (client, 2026-11-05: "smoother, not too much"). Only where something used to jump: anchor links scroll,
   pages cross-fade (the header stays put), the services menu and the phone menu ease in, FAQ answers slide open,
   lazy pictures fade in once loaded (components.js marks them). No reveal on scroll. All of it with the two motion
   tokens, and none of it with reduced motion. */
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
  @view-transition { navigation: auto; }
  .site-header { view-transition-name: site-header; }
  .mega:not([hidden]), .nav.is-open { animation: menu-in var(--t-open) both; }
  .faq__item { interpolate-size: allow-keywords; }
  .faq__item::details-content { block-size: 0; overflow: clip;
    transition: block-size var(--t-open), content-visibility var(--t-open) allow-discrete; }
  .faq__item[open]::details-content { block-size: auto; }
  img[data-fade] { transition: opacity var(--t-open); }
  img[data-fade="pending"] { opacity: 0; }
}
@keyframes menu-in { from { opacity: 0; translate: 0 -.5rem; } }
ul, ol { padding: 0; list-style: none; }
:focus-visible { outline: var(--focus-width) solid var(--focus); outline-offset: var(--focus-offset); }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.skip { position: absolute; left: var(--margin); top: .5rem; z-index: 100; display: inline-flex; align-items: center; min-height: var(--control-h);
  padding: 0 1rem; background: var(--cta); color: var(--on-cta);
  border-radius: var(--radius-control); transform: translateY(-200%); }
.skip:focus { transform: none; }

/* Themes paint their own section (rules §1.3) */
.theme-light, .theme-dark, .theme-brand { background: var(--bg); color: var(--text); }
.bg-2 { background: var(--bg-2); }
.bg-3 { background: var(--bg-3); }

/* Grid */
.wrap { max-width: var(--page-max); margin-inline: auto; padding-inline: var(--margin); }
.section { padding-block: var(--section); }
.section--sm { padding-block: var(--section-sm); }
/* A section that continues the one above it (the reference's statement after the hero): no hairline, and the
   gap from the content above to this heading is two margins, the hero ending one margin under its images
   (measured on the reference: 72 / 66 / 57 / 34 px at 1440 / 1280 / 1024 / 375). Its own end keeps the full
   section spacing. */
.hero { padding-bottom: var(--margin); }
.section--continued { padding-top: var(--margin); }
.hairline { border-top: var(--hairline) solid var(--rule); }
.grid { display: grid; grid-template-columns: repeat(var(--columns), minmax(0, 1fr)); column-gap: var(--gutter); row-gap: var(--gap-row); }
.span-2 { grid-column: span 2; } .span-3 { grid-column: span 3; } .span-4 { grid-column: span 4; } .span-6 { grid-column: span 6; }
.span-8 { grid-column: span 8; } .span-12 { grid-column: 1 / -1; } .start-5 { grid-column: 5 / span 8; }

/* Type */
.h1 { font-family: var(--font-display); font-weight: var(--display-weight); font-size: var(--text-h1);
  line-height: var(--leading-h1); letter-spacing: var(--track-head); text-wrap: balance; }
.h2 { font-family: var(--font-display); font-weight: var(--display-weight); font-size: var(--text-h2);
  line-height: var(--leading-h2); letter-spacing: var(--track-head); text-wrap: balance; max-width: 38rem; }
.title { font-family: var(--font-text); font-weight: var(--title-weight); font-size: var(--text-title); line-height: var(--leading-title); }
.lead { font-size: var(--text-lead); line-height: var(--leading-lead); color: var(--text-2); max-width: 31rem; }
.muted { color: var(--text-2); }
.label { font-family: var(--font-label); font-weight: var(--label-weight); font-size: var(--text-small); line-height: var(--leading-small);
  letter-spacing: var(--label-tracking); text-transform: var(--label-transform); color: var(--text-2); }
.stack > * + * { margin-top: var(--gap-text); }

/* Buttons — opposite-pole pill (§1.5), hover one ladder step (§1.6), never under 44px */
.btn { display: inline-flex; align-items: center; justify-content: center; gap: .4em; min-height: var(--control-h);
  padding: 0 var(--control-pad-x); border-radius: var(--radius-control); border: var(--hairline) solid var(--cta);
  background: var(--cta); color: var(--on-cta); font: inherit; text-decoration: none; white-space: nowrap; cursor: pointer;
  transition: background-color var(--t-colour), border-color var(--t-colour), color var(--t-colour); }
.btn:hover { background: var(--cta-hover); border-color: var(--cta-hover); color: var(--on-cta-hover); }
.btn--outline { background: transparent; color: var(--text); border-color: var(--line); }
.btn--outline:hover { background: var(--cta-2-hover); border-color: var(--line); color: var(--text); }
.btn--icon { width: var(--control-h); padding: 0; }
.link-arrow { display: inline-flex; min-height: var(--control-h); align-items: center; text-decoration: none; }
.link-arrow:hover { text-decoration: underline; text-underline-offset: .25em; }

/* Announcement bar */
.announce { background: var(--bg-2); }
.announce .wrap { display: flex; justify-content: center; align-items: center; min-height: var(--control-h); }
.announce a { display: block; max-width: 100%; line-height: var(--control-h); text-decoration: none; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.announce a:hover { text-decoration: underline; }
/* Header. Sticky while scrolling up, slides away while scrolling down; "Termin sichern" (the pin)
   never leaves the screen. It takes the theme of the section behind it: components.js puts .theme-light,
   .theme-dark or .theme-brand on .site-header, and the bar, dropdown and phone menu read that theme's
   tokens. The header box itself is transparent and lets clicks through, so a hidden bar blocks nothing. */
.site-header { --header-h: 4rem; position: sticky; top: 0; z-index: 50; height: var(--header-h); pointer-events: none; }
.site-header.theme-light, .site-header.theme-dark, .site-header.theme-brand { background: transparent; }
.site-header__bar { position: absolute; inset: 0 0 auto; height: var(--header-h); background: var(--bg); color: var(--text);
  border-bottom: var(--hairline) solid var(--rule); pointer-events: auto;
  transition: transform var(--t-open), background-color var(--t-colour), color var(--t-colour), border-color var(--t-colour); }
.site-header.is-hidden .site-header__bar { transform: translateY(calc(-100% - 1px)); }
.site-header__bar .wrap { display: flex; align-items: center; gap: var(--gutter); height: 100%; }
.site-header__pin { position: absolute; inset: 0 0 auto; height: var(--header-h); }
.site-header__pin .wrap { display: flex; justify-content: flex-end; align-items: center; height: 100%; }
.site-header__pin .btn { pointer-events: auto; transition: margin var(--t-open), background-color var(--t-colour), border-color var(--t-colour), color var(--t-colour); }
/* keeps the pinned button's width free inside the bar, so the menu never runs under it */
.site-header__space { visibility: hidden; flex: none; }
.logo { display: inline-flex; align-items: center; gap: .5rem; min-height: var(--control-h); margin-right: auto; color: inherit; text-decoration: none; }
.logo i { display: block; width: 3.25rem; aspect-ratio: 299.41 / 170.79; background: currentColor;
  -webkit-mask: url(../images/logo-mark.svg) no-repeat center / contain; mask: url(../images/logo-mark.svg) no-repeat center / contain; }
.logo__name { font-family: var(--font-display); font-weight: var(--display-weight); font-size: var(--text-title); letter-spacing: var(--track-head); white-space: nowrap; }
.nav { display: flex; align-items: center; height: 100%; }
.nav__list { display: flex; align-items: center; height: 100%; }
.nav__item { position: static; height: 100%; }
.nav__link { display: inline-flex; align-items: center; gap: .25rem; height: 100%; min-height: var(--control-h); padding-inline: .75rem;
  background: none; border: 0; color: inherit; font: inherit; text-decoration: none; cursor: pointer; }
.nav__link > span { border-bottom: var(--hairline) solid transparent; transition: border-color var(--t-colour); }
.nav__link:hover > span, .nav__link[aria-current="page"] > span, .nav__link[aria-expanded="true"] > span { border-color: currentColor; }
.nav__link svg { width: .75rem; height: .75rem; transition: transform var(--t-open); }
.nav__link[aria-expanded="true"] svg { transform: rotate(180deg); }
.mega { position: absolute; top: var(--header-h); left: 0; right: 0; background: var(--bg); color: var(--text);
  border-bottom: var(--hairline) solid var(--rule); }
.mega[hidden] { display: none; }
/* Mega menu: the three service groups, each link with a line icon, then the Mesh APP (our own CRM) as a fourth
   column with a cut of its dashboard in the browser frame on field A. The first group, the core offer, sits on
   --bg-2 with its icons on --bg squares. */
.site-header__bar .mega__inner { display: grid; grid-template-columns: minmax(0, 1.2fr) repeat(2, minmax(0, 1fr)) minmax(0, 1.3fr);
  align-items: start; gap: var(--gap-block); height: auto; padding-block: 1.5rem; }
.mega__group .label, .mega__app .label { display: block; margin-bottom: .75rem; }
.mega__group a { display: flex; align-items: center; gap: .75rem; min-height: var(--control-h); text-decoration: none; }
.mega__group a:hover > span:last-child, .mega__app a:hover .mega__more { text-decoration: underline; text-underline-offset: .25em; }
.mega__icon { display: grid; place-items: center; flex: none; }
.mega__icon svg { width: 1.25rem; height: 1.25rem; fill: none; stroke: currentColor; stroke-width: 1.4; stroke-linecap: round; stroke-linejoin: round; }
.mega__group--lead { align-self: stretch; margin-block: -1.25rem; padding: 1.25rem; background: var(--bg-2); }   /* runs the menu's height; its label level with the others */
.mega__group--lead ul { display: grid; gap: .25rem; }
.mega__group--lead .mega__icon { width: 2.5rem; height: 2.5rem; background: var(--bg); border-radius: var(--radius-chip); }
@media (max-width: 79.99rem) {   /* laptop: a narrower gap so the first group's links stay on one line */
  .site-header__bar .mega__inner { grid-template-columns: minmax(0, 1.25fr) repeat(2, minmax(0, 1fr)) minmax(0, 1.1fr); gap: 1.5rem; }
}
.mega__app a { display: block; color: inherit; text-decoration: none; }
.mega__shot { position: relative; display: block; aspect-ratio: 16 / 10; overflow: hidden; background: var(--field-a-from); }
.mega__shot .browser { position: absolute; top: 1.25rem; left: 1.25rem; width: 150%; }
.mega__shot .browser > img { flex: none; height: auto; }
.mega__more { display: inline-flex; align-items: center; gap: .5rem; min-height: var(--control-h); margin-top: .5rem; }
.mega__more svg { width: .75rem; height: .75rem; }
.menu-btn { display: none; }

/* Hero */
.hero .stack > * + * { margin-top: var(--gap-lead); }   /* headline → intro, one step wider than in sections */
.hero__actions { display: flex; flex-direction: column; align-items: flex-start; gap: var(--gutter); margin-top: var(--gap-actions); }
/* The note under the buttons belongs to the button that points at it (aria-describedby): on devices that can
   hover it appears while that button is hovered or keyboard-focused. Its space stays reserved, so nothing
   moves. Touch screens cannot hover, so there it stays visible. */
@media (hover: hover) {
  .hero__note { opacity: 0; transition: opacity var(--t-colour); }
  .hero__actions:has([aria-describedby]:hover, [aria-describedby]:focus-visible) .hero__note { opacity: 1; }
}
.hero__media { display: grid; grid-template-columns: 2fr 1fr; gap: var(--gutter); margin-top: var(--gap-block); }
.hero__media img { width: 100%; height: 100%; object-fit: cover; border-radius: var(--radius-container); }
.hero__media .tall { aspect-ratio: 4 / 5; }
/* Browser frame: a website we built, shown as a page in a browser window — floating UI (--radius-ui-frame,
   --shadow-float), a bar with three dots and the site's domain, the screenshot below it from its top edge.
   Used by the hero showcase and the project cards. .browser--sm is the compact bar for small frames (cards).
   Inside a card whose tokens are renamed on hover (dark), the frame carries .theme-light so the window keeps
   its light chrome. */
.browser { display: flex; flex-direction: column; overflow: hidden; background: var(--bg); color: var(--text);
  border-radius: var(--radius-ui-frame); box-shadow: var(--shadow-float); }
.browser__bar { display: flex; align-items: center; gap: .25rem; flex: none; padding: .5rem .75rem; border-bottom: var(--hairline) solid var(--rule); }
.browser__bar i { width: .45rem; height: .45rem; border-radius: 50%; background: var(--rule); }
.browser__bar span { flex: 1; margin-left: .5rem; padding: .25rem .75rem; border-radius: var(--radius-control); background: var(--bg-2); color: var(--text-2);
  font-family: var(--font-label); font-size: var(--text-small); line-height: var(--leading-small); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.browser > img { flex: 1; min-height: 0; width: 100%; height: 100%; object-fit: cover; object-position: top; border-radius: 0; }
.browser--sm .browser__bar { gap: .25rem; padding: .25rem .5rem; }
.browser--sm .browser__bar i { width: .3rem; height: .3rem; }
.browser--sm .browser__bar span { margin-left: .25rem; padding: 0 .5rem; }
/* Showcase (the hero's wide tile): websites we built, in the browser frame on the Nebelblau field (field A),
   flat like every coloured field (see Feature tile). The frame sits inside the field with one equal gap on all four
   sides (6.5 % of the tile's width, 16–56 px). Four slides cross-fade, 4 s each with 1 s fades (16 s a
   round), in CSS; the frame's address bar carries the site's domain so the name changes with the picture.
   The first slide is visible from the first paint (its delay is negative), so it is the hero's LCP image.
   With reduced motion nothing moves: the first site stays. */
.showcase { position: relative; overflow: hidden; margin: 0; border-radius: var(--radius-container); container-type: inline-size;
  background: var(--field-a-from); }
.showcase__slide { position: absolute; inset: clamp(1rem, 6.5cqw, 3.5rem); opacity: 0; animation: showcase 16s linear infinite both; }
.showcase__slide:nth-child(1) { animation-delay: -1s; }
.showcase__slide:nth-child(2) { animation-delay: 3s; }
.showcase__slide:nth-child(3) { animation-delay: 7s; }
.showcase__slide:nth-child(4) { animation-delay: 11s; }
@keyframes showcase { 0% { opacity: 0; } 6.25% { opacity: 1; } 25% { opacity: 1; } 31.25% { opacity: 0; } 100% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
  .showcase__slide { animation: none; }
  .showcase__slide:first-child { opacity: 1; }
}
/* The mark (markup from tools/roof-mark.mjs): the Web Austria W, big on the right of the hero where the
   reference shows its hatched logo ring, drawn in the tiles of the Stephansdom roof. Like that ring it runs
   off the right edge of the screen (18 % of its width is cut) and dips behind the top of the photo row
   (22 % of its height), showing between and beside the photos; the photos paint over it. Its height is
   1.14 × the photo column (1 × below 1360 px); the logo's own ratio gives the width. At rest it is a sketch: a hairline every
   10 px (the reference's hatch) in ink at 16 % into the page, nothing else. The colour layer lies on top, shown only
   inside a soft circle that follows the pointer (components.js); a finger does the same, and on touch
   screens the circle crosses the mark once by itself when it scrolls into view, so the colours are seen once.
   The glaze colours are the real roof's (black, white, green, ochre, and the mortar between tiles) and
   belong to the picture, not to the palette: they are not tokens, no component may reuse them. Only the
   shield takes the palette's red. The lattice is the choir roof's, weighted light (glaze A in DESIGN.md):
   white diamonds between the green ones, black only in the centres.
   Decoration only (aria-hidden); it never sits behind text. */
.hero { overflow-x: clip; }   /* the mark runs past the screen edge; never a sideways scroll */
.hero__media { position: relative; container-type: inline-size; isolation: isolate; }
.roof { --col: calc((100cqw - var(--gutter)) / 3); --h: calc(var(--col) * 1.14); --w: calc(var(--h) * 299.41 / 170.79);
  --roof-black: #2a3034; --roof-white: #f0ece2; --roof-green: #3f6448; --roof-ochre: #cfa64f; --roof-seam: #8b8478;
  position: absolute; z-index: -1; right: calc(-1 * (var(--margin) + var(--w) * .18)); bottom: 100%;
  width: var(--w); height: var(--h); transform: translateY(22%); pointer-events: none; }
.roof .hatch { fill: color-mix(in oklab, var(--text) 16%, var(--bg)); }   /* a step past the 10 % rule, still a hairline */
.roof .k { fill: var(--roof-black); }
.roof .w { fill: var(--roof-white); }
.roof .g { fill: var(--roof-green); }
.roof .y { fill: var(--roof-ochre); }
.roof .r { fill: var(--brand); }
.roof .c { fill: var(--roof-black); }   /* the lattice's diamond centres */
.roof .d { fill: var(--roof-white); }   /* the diamonds between the lattice's diamonds: white (glaze A, the light choir lattice) */
.roof .seam, .roof .bg { fill: var(--roof-seam); }   /* the joints between tiles: a warm grey mortar, so the colours read full without going dark */
.roof__hit { pointer-events: fill; }   /* the only part that listens: the pointer over the mark's box */
/* The brush: a soft circle in the colour layer's mask. It follows the pointer with a short lag, appears
   quickly and takes its time to go, so the sketch returns gradually. */
.roof__brush { cx: var(--mx, 50%); cy: var(--my, 50%); r: 26%; opacity: 0;
  transition: opacity calc(3 * var(--t-open)), cx var(--t-colour) linear, cy var(--t-colour) linear; }
.roof.is-lit .roof__brush { opacity: 1; transition-duration: var(--t-colour), var(--t-colour), var(--t-colour); }
.roof.is-passing .roof__brush { animation: roof-pass 3.2s ease-in-out both; }
@keyframes roof-pass { from { cx: 0; cy: 50%; opacity: 1; } 85% { opacity: 1; } to { cx: 100%; cy: 50%; opacity: 0; } }
/* Narrower screens: the H1's second line reaches half the page, so the mark shrinks first (laptops), then
   moves into its own row above the photos (tablets), still running off the right edge; phones below. */
@media (max-width: 84.99rem) { .roof { --h: var(--col); } }   /* below 1360 the H1's second line comes close */
@media (max-width: 63.99rem) {
  .hero__media { margin-top: calc(var(--gap-block) + 33.4% + var(--gutter)); }   /* 75 % × 170.79 / 299.41 × .78 */
  .roof { --w: 75cqw; --h: calc(var(--w) * 170.79 / 299.41); right: calc(-1 * (var(--margin) + 8cqw)); }
}
.head-row { display: flex; justify-content: space-between; align-items: end; gap: var(--gutter); flex-wrap: wrap; margin-bottom: var(--gap-block); }

/* Services: three panels (Webagentur, Marketing, Design) on the light surface, square like every container,
   rows on hairlines one step darker than the panel. Each row is one link: title and arrow, and under the title
   the service's description. The description is always in the HTML (indexable, read by screen readers); on
   devices that hover, rows have a fixed height and the text slides in under the title on hover or keyboard
   focus, so nothing else on the page moves (no layout shift). Touch screens show it all the time. Under the
   panels, the full-service page and the city pages in one row. */
.services { --row: 5.25rem; --hair: color-mix(in oklab, var(--text) 10%, var(--bg-2));
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--gutter); }
.services__panel, .services__all { background: var(--bg-2); border-radius: var(--radius-container); padding: 0 var(--pad-tile); }
.services__head { padding-block: 1.25rem; font-size: var(--text-title); line-height: var(--leading-title); font-weight: var(--title-weight); }
.services ul { list-style: none; margin: 0 0 var(--pad-tile); padding: 0; }
.services li { border-top: var(--hairline) solid var(--hair); }
.service { position: relative; display: block; min-height: var(--control-h); padding-block: 1rem; padding-right: 1.5rem; color: inherit; text-decoration: none; }
.service::after { content: "→"; position: absolute; right: .25rem; top: calc(1rem + (var(--text-size) * var(--leading-title)) / 2); translate: 0 -50%;
  transition: translate var(--t-colour), top var(--t-open); }
.service__title { font-size: var(--text-size); line-height: var(--leading-title); font-weight: var(--title-weight); }
.service__text { margin-top: .25rem; font-size: var(--text-small); line-height: var(--leading-small); color: var(--text-2); }
.service:hover .service__title, .service:focus-visible .service__title { text-decoration: underline; text-underline-offset: .2em; }
.service:hover::after, .service:focus-visible::after { translate: .25rem -50%; }
@media (hover: hover) {
  .service { height: var(--row); padding-block: 0; overflow: hidden; }
  /* At rest the title sits in the middle of the row with the text below it, out of view; on hover both move up. */
  .service__body { display: block; transform: translateY(calc((var(--row) - var(--text-size) * var(--leading-title)) / 2));
    transition: transform var(--t-open); }
  .service__text { opacity: 0; transition: opacity var(--t-open); }
  .service::after { top: 50%; }
  .service:hover .service__body, .service:focus-visible .service__body { transform: translateY(.9rem); }
  .service:hover .service__text, .service:focus-visible .service__text { opacity: 1; }
  .service:hover::after, .service:focus-visible::after { top: calc(.9rem + (var(--text-size) * var(--leading-title)) / 2); }
}
.services__all { grid-column: 1 / -1; display: flex; flex-wrap: wrap; align-items: baseline; gap: .25rem 1.5rem; padding-block: 1.25rem; }
.services__all .service__title a { display: inline-flex; align-items: center; min-height: var(--control-h); color: inherit; text-underline-offset: .2em; }
.services__all .service__title a::after { content: " →"; }
.services__all p { color: var(--text-2); font-size: var(--text-small); line-height: var(--leading-small); }
.services__cities { margin-left: auto; }
.services__cities a { color: inherit; text-underline-offset: .2em; }
/* On a service page (Leistungen, new structure): under each head its one-line promise and its points, plain, without
   rows (client: fewer lines), then one row, the service page that goes deeper, with the homepage's description. */
.service__title, .service__text { display: block; }
.services__lede { margin-top: -.75rem; padding-bottom: 1rem; color: var(--text-2); }
.services .services__points { margin-bottom: 1.25rem; }
.services__points li { padding-block: .25rem; border-top: 0; font-size: var(--text-small); line-height: var(--leading-small); }
/* Narrower screens: the panels get thinner, descriptions take a third line, so the rows grow; below 1024 px the
   panels stack, one per row, and the rows go back to their normal height. */
@media (max-width: 79.99rem) { .services { --row: 6.25rem; } }
@media (max-width: 63.99rem) { .services { grid-template-columns: 1fr; --row: 5.25rem; } }

/* Intro: a section's heading in the left half, its text from the page centre (the reference's statement block,
   measured: heading 36 px / 400 / 1.15 held to 12.7 em, text 18 / 27 px in ink — not the grey of the hero lead —
   held to 532 px). Stacks on phones. */
.intro { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--gutter); align-items: start;
  margin-bottom: var(--gap-block); }
.intro > .h2 { max-width: 12.7em; }
.intro:last-child { margin-bottom: 0; }   /* the last block of its section: the section's own padding ends it */
.intro > p { max-width: 33.25rem; font-size: var(--text-lead); line-height: var(--leading-lead); color: var(--text); }
/* Section head without text: the heading on the left, a link or controls on the right, on the heading's last line
   (Projekte: "Alle Referenzen →"; Kundenstimmen: the slider's arrows). */
.section-head { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: end; gap: var(--gap-text) var(--gutter);
  margin-bottom: var(--gap-block); }

/* Cost calculator (#kalkulator1): the estimate on the left (sticky), the questions on the right from the page
   centre, one step at a time. Options are native radios and checkboxes inside their labels, so keyboard and
   screen readers work as with any form; the tile's edge is the 3 : 1 UI line, the chosen tile gets an ink edge
   and a filled mark (state never by colour alone). The price stays blurred until the e-mail code is confirmed
   (`.is-locked`): obfuscation for the lead step, not a disabled state, and hidden from screen readers too.
   Without JavaScript every step is shown at once. */
.calc { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--gutter); align-items: start; }
.calc__estimate { position: sticky; top: calc(var(--header-h, 4rem) + var(--gutter)); padding: var(--pad-card);
  background: var(--bg-2); border-radius: var(--radius-container); }
.calc__price { margin-top: .75rem; font-family: var(--font-display); font-weight: var(--display-weight); font-size: var(--text-h1);
  line-height: var(--leading-h1); letter-spacing: var(--track-head); }
.calc__amount { display: inline-block; transition: filter var(--t-open); }
.calc.is-locked .calc__amount { filter: blur(.6rem); user-select: none; }
.calc__lock { margin-top: .5rem; font-size: var(--text-small); line-height: var(--leading-small); color: var(--text); }
.calc:not(.is-locked) .calc__lock { display: none; }
.calc__caption { margin-top: .25rem; font-size: var(--text-small); line-height: var(--leading-small); color: var(--text-2); }
.calc__summary { margin: var(--gap-text) 0 0; }
.calc__summary div { display: flex; justify-content: space-between; gap: var(--gutter); padding-block: .75rem;
  border-top: var(--hairline) solid color-mix(in oklab, var(--text) 10%, var(--bg-2)); font-size: var(--text-small); line-height: var(--leading-small); }
.calc__summary dt { color: var(--text-2); }
.calc__summary dd { margin: 0; text-align: right; }
.calc__progress { margin-bottom: var(--gap-text); }
.calc__count { font-size: var(--text-small); line-height: var(--leading-small); color: var(--text-2); }
.calc__bar { display: block; height: 2px; margin-top: .5rem; background: var(--rule); }
.calc__bar i { display: block; height: 100%; width: var(--p, 16.6%); background: var(--text); transition: width var(--t-open); }
.calc__step { min-width: 0; margin: 0; padding: 0; border: 0; }
.calc__step + .calc__step { margin-top: var(--gap-block); }
.calc.is-ready .calc__step { display: none; }
.calc.is-ready .calc__step.is-current { display: block; margin-top: 0; }
.calc__title { padding: 0; font-size: var(--text-title); line-height: var(--leading-title); font-weight: var(--title-weight); }
.calc__title:focus { outline: none; }
.calc__hint { margin-top: .25rem; color: var(--text-2); }
.calc__options { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--gutter); margin-top: 1.5rem; }
.calc__option { display: flex; gap: .75rem; align-items: start; min-height: var(--control-h); padding: 1rem 1.25rem; background: var(--bg);
  border: var(--hairline) solid var(--line); border-radius: var(--radius-container); cursor: pointer;
  transition: background-color var(--t-colour), border-color var(--t-colour); }
.calc__option:hover { background: var(--bg-2); }
.calc__option:has(input:checked) { border-color: var(--text); box-shadow: inset 0 0 0 1px var(--text); }
.calc__option:has(input:focus-visible) { outline: var(--focus-width) solid var(--focus); outline-offset: var(--focus-offset); }
.calc__option input { appearance: none; flex: none; display: grid; place-items: center; width: 1.25rem; height: 1.25rem; margin: .1em 0 0;
  border: var(--hairline) solid var(--line); background: var(--bg); }
.calc__option input[type="radio"] { border-radius: 50%; }
.calc__option input:checked { border-color: var(--text); }
.calc__option input:focus-visible { outline: none; }
.calc__option input::after { content: ""; width: .625rem; height: .625rem; background: var(--text); transform: scale(0); transition: transform var(--t-colour); }
.calc__option input[type="radio"]::after { border-radius: 50%; }
.calc__option input:checked::after { transform: scale(1); }
.calc__text { display: grid; gap: .25rem; }
.calc__text b { font-weight: var(--title-weight); }
.calc__desc { font-size: var(--text-small); line-height: var(--leading-small); color: var(--text-2); }
.calc__extra { margin-left: auto; font-size: var(--text-small); line-height: var(--leading-small); color: var(--text-2); }
.calc__fields { display: grid; gap: 1.25rem; margin-top: 1.5rem; }
.calc__fields textarea { min-height: 5.5rem; resize: vertical; }
.calc__error { margin-top: 1rem; }
.calc__resend { padding: 0; border: 0; background: none; font: inherit; color: inherit; text-decoration: underline; text-underline-offset: .2em; cursor: pointer; }
.calc__proto { margin-top: 1rem; padding: .75rem 1rem; background: var(--bg-2); font-size: var(--text-small); line-height: var(--leading-small); }
.calc__done { margin-top: 1.25rem; font-weight: var(--title-weight); }
.calc__nav { display: flex; gap: .75rem; margin-top: var(--gap-block); }
.calc__nav [data-next] { margin-left: auto; }

/* Photo tile: no container; square 4:5 photo, then text */
.tile img { width: 100%; aspect-ratio: 4 / 5; object-fit: cover; border-radius: var(--radius-container); }
.tile .title { margin-top: 1.25rem; }
.tile p { margin-top: .5rem; color: var(--text-2); }

/* Feature tile (§1.12): a field card, text at the bottom left, a white UI fragment floating above. Tinted
   (--a/--b/--c) and neutral tiles alternate. Fields are flat, the light colour only (--field-x-from), like every
   coloured field in this project: the reference's gradient to a deep corner (--field-x-to) is not used
   (client, 2026-10-26). */
.ftile { position: relative; display: flex; flex-direction: column; aspect-ratio: 4 / 5; padding: var(--pad-tile);
  background: var(--field-neutral); border-radius: var(--radius-container); }
.ftile--a { background: var(--field-a-from); }
.ftile--b { background: var(--field-b-from); }
.ftile--c { background: var(--field-c-from); }
.ftile .ui-area { flex: 1; display: grid; place-items: center; padding-block: .5rem 1.5rem; }
.ftile .title + p { margin-top: .5rem; color: var(--text-2); max-width: 22rem; }
.ftile .link-arrow { margin-bottom: -.75rem; }
.ftile .link-arrow::after { content: ""; position: absolute; inset: 0; }
.ftile:hover .link-arrow { text-decoration: underline; text-underline-offset: .25em; }
.ui { width: min(100%, 17rem); background: var(--bg); color: var(--text); border-radius: var(--radius-ui-frame);
  box-shadow: var(--shadow-float); padding: .75rem; font-size: var(--text-small); line-height: 1.35; }
.ui .bar { height: .5rem; border-radius: var(--radius-control); background: var(--rule); }
.ui .bar + .bar { margin-top: .5rem; }
.ui .row { display: flex; align-items: center; gap: .5rem; padding: .5rem .25rem; }
.ui .row + .row { border-top: var(--hairline) solid var(--rule); }
.ui .sq { width: .875rem; height: .875rem; border: var(--hairline) solid var(--line); flex: none; }
.ui .chip { display: inline-block; padding: .25rem .5rem; border-radius: var(--radius-control); background: var(--cta); color: var(--on-cta); }
.ui .dots { display: flex; gap: .25rem; margin-bottom: .5rem; }
.ui .dots i { width: .45rem; height: .45rem; border-radius: 50%; background: var(--rule); }
.ui .url { flex: 1; height: .9rem; border-radius: var(--radius-control); background: var(--bg-2); margin-left: .5rem; }
.ui .plate { aspect-ratio: 16 / 9; background: var(--bg-2); margin: .5rem 0; }
.ui--phone { width: 7.5rem; padding: .5rem .5rem 1rem; border-radius: 1.1rem; }
.ui--phone .plate { aspect-ratio: 1; }
.pills { display: grid; gap: 1.25rem; justify-items: start; }
.pill-status { display: inline-flex; align-items: center; gap: .5rem; padding: .25rem .75rem .25rem .25rem; border-radius: var(--radius-control);
  background: var(--bg); box-shadow: var(--shadow-float); font-size: var(--text-small); }
.pill-status i { width: 1.4rem; height: 1.4rem; border-radius: 50%; background: var(--n-300); }
.pill-status + .pill-status { margin-left: 1.5rem; }

/* Quote band */
.quote { display: grid; grid-template-columns: auto minmax(0, 32rem); gap: var(--gap-block); justify-content: center; align-items: start; }
.quote img { width: 7.5rem; aspect-ratio: 1; object-fit: cover; border-radius: var(--radius-container); }
.quote blockquote { font-family: var(--font-display); font-weight: var(--display-weight); font-size: var(--text-h2);
  line-height: var(--leading-h2); letter-spacing: var(--track-head); }
.quote figcaption { margin-top: 1.5rem; }

/* Steps on a dark band: bg-2 tiles */
.step { background: var(--bg-2); padding: var(--pad-card); display: flex; flex-direction: column; gap: .75rem; min-height: 100%; }
.step .num { font-family: var(--font-display); font-size: var(--text-h2); line-height: 1; }
.step .note { margin-top: auto; padding-top: 1.5rem; border-top: var(--hairline) solid var(--rule); font-size: var(--text-small); color: var(--text-2); }
.steps + .btns { margin-top: var(--gap-block); }   /* a link under the steps (the costs page on a service page) */

/* Form — square fields with a 3:1 edge, label above, error = text + icon + edge (never colour alone) */
.form { display: grid; gap: 1.5rem; }
.field label { display: block; margin-bottom: .5rem; font-weight: var(--label-weight); }
.field input, .field textarea, .field select { width: 100%; min-height: var(--control-h); padding: .75rem 1rem; font: inherit;
  font-weight: var(--text-weight); color: var(--text); background: var(--bg); border: var(--hairline) solid var(--line);
  border-radius: var(--radius-container); }
.field input::placeholder, .field textarea::placeholder { color: var(--text-2); }
.field.is-invalid input, .field.is-invalid textarea { border-color: var(--error); box-shadow: inset 0 0 0 1px var(--error); }
.field .msg { display: flex; gap: .5rem; align-items: start; margin-top: .5rem; color: var(--error); }
.field .msg svg { flex: none; margin-top: .2em; }
.check { display: flex; gap: .75rem; align-items: start; min-height: var(--control-h); padding-block: .75rem; cursor: pointer; }
.check input { appearance: none; flex: none; width: 1.375rem; height: 1.375rem; min-height: 0; margin: .1em 0 0; padding: 0; border: var(--hairline) solid var(--line);   /* not a text field's 44 px (.field input) */
  background: var(--bg); border-radius: 0; display: grid; place-content: center; cursor: pointer; }
.check input::after { content: ""; width: .75rem; height: .75rem; background: var(--text);
  clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%); transform: scale(0); transition: transform var(--t-colour); }
.check input:checked::after { transform: scale(1); }

/* Footer, after the reference's (../raw/REFERENCE-Cortea.md, Footer; measured on cortea.ai at 1440): 80 px above
   (--section-sm), grey 16 px headings over ink links on 44 px rows, then a hairline and the legal line in the small size
   with about 38 px of room above and below its text. Columns on the 12-column grid, 4 / 2 / 6: the company (logo, name
   and address, e-mail and phone, the social links as icons in one row), Unternehmen, and the services in three columns
   whose group names are headings like "Unternehmen" (no "Leistungen" heading above them).
   Below 1024 px the company and Unternehmen share a row above Leistungen; on phones everything stacks and Leistungen
   keeps two columns. */
.footer { padding-top: var(--section-sm); }
.footer__grid { display: grid; grid-template-columns: repeat(var(--columns), minmax(0, 1fr)); gap: var(--gap-block) var(--gutter); }
.footer__brand { grid-column: span 4; }
.footer__company { grid-column: span 2; }
.footer__services { grid-column: span 6; }
.footer h3 { font-size: var(--text-size); font-weight: var(--text-weight); color: var(--text-2); }
.footer h3 + ul { margin-top: .25rem; }
.footer ul + h3 { margin-top: 1.25rem; }   /* a second group in the same column */
.footer li a { display: inline-flex; min-height: var(--control-h); align-items: center; text-decoration: none; }
.footer li a:hover, .footer address a:hover { text-decoration: underline; text-underline-offset: .2em; }
.footer .logo { margin-bottom: var(--gap-text); }
.footer address { font-style: normal; }
.footer address p { color: var(--text-2); }
.footer address p + p { margin-top: .75rem; }
.footer address a { display: inline-flex; min-height: var(--control-h); align-items: center; color: var(--text); text-decoration: none; }
/* Social links: icons only (each named for screen readers), in one row, 44 px round targets; the first icon's glyph
   lines up with the text above. */
.footer__social { display: flex; flex-wrap: wrap; gap: .25rem; margin-top: var(--gap-text); margin-left: calc((1.25rem - var(--control-h)) / 2); }
.footer .footer__social a { display: grid; place-items: center; width: var(--control-h); height: var(--control-h); border-radius: var(--radius-control);
  color: var(--text); transition: background-color var(--t-colour); }
.footer .footer__social a:hover { background: var(--cta-2-hover); }
.footer__social svg { width: 1.25rem; height: 1.25rem; fill: currentColor; }
.footer__groups { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0 var(--gutter); }
.footer .legal { display: flex; justify-content: space-between; flex-wrap: wrap; gap: 0 1rem; margin-top: var(--section-sm);
  padding-block: var(--pad-tile); border-top: var(--hairline) solid var(--rule); font-size: var(--text-small); color: var(--text-2); }
.footer .legal > span:first-child { display: inline-flex; align-items: center; min-height: var(--control-h); }
.footer .legal a, .footer .legal button { display: inline-flex; align-items: center; min-height: var(--control-h); color: inherit; background: none; border: 0;
  font: inherit; text-decoration: none; cursor: pointer; }
.footer .legal a:hover, .footer .legal button:hover { text-decoration: underline; }
.footer__links { display: flex; flex-wrap: wrap; gap: 0 1.25rem; }
@media (max-width: 63.99rem) {
  .footer__brand, .footer__company { grid-column: span 6; }
  .footer__services { grid-column: 1 / -1; }
}
@media (max-width: 47.99rem) {
  .footer__brand, .footer__company { grid-column: 1 / -1; }
  .footer__groups { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Header on phones and small tablets: logo · pinned CTA · Menü; the menu opens as a full panel in the
   header's theme. When the bar slides away the pinned CTA moves to the corner. */
@media (max-width: 55.99rem) {
  .menu-btn { display: inline-flex; width: 5.5rem; padding: 0; }
  .site-header__pin .btn { margin-right: calc(5.5rem + var(--gutter)); padding-inline: 1rem; }
  .site-header.is-hidden .site-header__pin .btn { margin-right: 0; }
  .site-header__space { padding-inline: 1rem; }
  .nav { position: fixed; top: var(--header-h); left: 0; right: 0; bottom: 0; height: auto; display: block; overflow-y: auto;
    padding: var(--gap-text) var(--margin) var(--section-sm); background: var(--bg); color: var(--text); }
  .nav:not(.is-open) { display: none; }
  .nav__list { display: block; height: auto; }
  .nav__item { height: auto; border-bottom: var(--hairline) solid var(--rule); }
  .nav__link { width: 100%; justify-content: space-between; height: auto; min-height: 3.5rem; padding-inline: 0; font-size: var(--text-title); }
  .mega { position: static; border: 0; background: none; }
  .mega .wrap { padding-inline: 0; }
  .site-header__bar .mega__inner { grid-template-columns: 1fr; gap: 1.25rem; padding-block: .25rem 1.25rem; }
  .mega__group--lead { margin-block: 0; padding: 0; background: none; }
  .mega__group--lead .mega__icon { width: auto; height: auto; background: none; }
  .mega__shot { display: none; }
  .mega__more { margin-top: 0; }
}
@media (max-width: 24.99rem) { .logo__name { display: none; } }

/* Proof cards: four numbers, each on its own small card, floating on the hero's tall photo the way the browser
   frame floats on the showcase field (--radius-ui-frame, --shadow-float). The three track-record numbers sit
   on the feature-tile fields' light colours (Nebelblau, Kalkstein, Altrosa); these cards were the first to drop
   the gradient, whose deep corner dominated a card this small. The price, the one offer among them, is the dark theme.
   The cards are opaque, so no text sits on the photo. */
.proof { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--gutter); margin: 0; padding: 0; list-style: none; }
.proof__item { display: flex; flex-direction: column; justify-content: flex-end; min-height: 7rem; padding: 1rem 1.25rem;
  background: var(--bg); color: var(--text); border-radius: var(--radius-ui-frame); box-shadow: var(--shadow-float); }
.proof__item--a { background: var(--field-a-from); }
.proof__item--b { background: var(--field-b-from); }
.proof__item--c { background: var(--field-c-from); }
/* Hover: each card lifts a little and its shadow deepens (the float shadow twice, no new value), only where
   a pointer can hover and motion is welcome. The cards are not links; the lift is a response, not a promise. */
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  .proof__item { transition: transform var(--t-open), box-shadow var(--t-open); }
  .proof__item:hover { transform: translateY(-.25rem); box-shadow: var(--shadow-float), var(--shadow-float); }
}
.proof b { display: block; font-family: var(--font-display); font-weight: var(--display-weight); font-size: var(--text-quote); line-height: 1.2; letter-spacing: var(--track-head); }
/* Labels get two lines on every card, so numbers line up across a row whether the label wraps or not.
   Breaks only where the markup allows (&shy;), never mid-syllable by guess. */
.proof span { display: block; margin-top: .25rem; min-height: calc(2em * var(--leading-small)); font-size: var(--text-small);
  line-height: var(--leading-small); color: var(--text-2); hyphens: manual; }
.hero__media .tall { grid-column: 2; grid-row: 1; }
.hero__media .proof { grid-column: 2; grid-row: 1; align-self: end; margin: var(--pad-tile); position: relative; z-index: 1; }
/* Narrower photo row: the tall photo's column gets too thin for the cards (they would cover the faces), so the
   cards straddle the foot of both photos instead, four in one row. Phones: see the mobile block. */
@container (max-width: 70rem) {
  .hero__media .proof { grid-column: 1 / -1; grid-row: 2; align-self: start; margin: -3rem var(--pad-tile) 0;
    grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* Projects (Projekte): one card per client site, after Phenomenon's "Proof, not portfolio" row but without
   figures. Each card: the client's logo with two hashtags, the site in a mockup (the desktop screen running off
   the card's right edge, the phone view — or one piece of the interface — floating over it), then under a hairline
   the project's name and one line. Square containers (§1.4) on the feature-tile fields' light colours, flat as on
   the proof cards; the screens are floating UI, so they get --radius-ui-frame and --shadow-float.
   The name's link stretches over the whole card. Hover / keyboard focus turns the card to the opposite pole
   (--cta / --on-cta, the button's pair) by renaming the theme tokens inside it, so everything that reads --text
   follows, the phone's edge included; a logo with dark parts swaps to its light version (assets/work/logos/*-light).
   Hashtags keep their own case (WordPress), so they are not set as uppercase labels. The composition is drawn in
   the media box's own width (cqw), so it holds at every card width. The dividers line up across a row: all cards
   in a row are equally wide, so they all switch the head to the narrow layout (logo over one line of tags) at the
   same width. */
.cases { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--gutter); }
.case { --hair: color-mix(in oklab, var(--text) 14%, transparent); container-type: inline-size;
  position: relative; display: flex; flex-direction: column; overflow: hidden; padding: var(--pad-tile) var(--pad-tile) calc(var(--pad-tile) + 1.5rem);
  background: var(--field-neutral); color: var(--text); border-radius: var(--radius-container);
  transition: background-color var(--t-colour), color var(--t-colour); }
.case--a { background: var(--field-a-from); }
.case--b { background: var(--field-b-from); }
.case--c { background: var(--field-c-from); }
.case__top { display: flex; justify-content: space-between; align-items: start; gap: .5rem 1rem; }
.case__brand { display: grid; align-items: center; height: 2rem; }   /* one slot height for every logo */
.case__brand img { grid-area: 1 / 1; width: auto; height: 1.75rem; transition: opacity var(--t-colour); }
.case__brand img + img { opacity: 0; }
/* Logos are sized by how they read, not by their box: a filled block or a bare wordmark looks larger than a mark
   with lettering at the same height; a stacked logo (name over a line of small text) needs the full slot. */
.case__brand--solid img { height: 1.5rem; }
.case__brand--wordmark img { height: 1.375rem; }
.case__brand--stacked img { height: 2rem; }
.case__tags { font-family: var(--font-label); font-weight: var(--label-weight); font-size: var(--text-small);
  line-height: var(--leading-small); color: var(--text-2); text-align: right; }
/* The screen keeps its header and headline in view: it starts near the card's left edge, where the sites set their
   headlines, and the phone overlaps its lower right, where they show pictures. */
.case__media { position: relative; container-type: inline-size; aspect-ratio: 1; margin: var(--pad-tile) calc(-1 * var(--pad-tile)) 0; }
.case__media > * { position: absolute; max-width: none; }
/* The desktop screen is a browser frame (.browser.browser--sm.theme-light); the screenshot keeps its own ratio. */
.case__screen { left: 6cqw; top: 6cqw; width: 102.4cqw; }
.case__screen > img { flex: none; height: auto; }
.case__phone, .case__panel { height: auto; border-radius: var(--radius-ui-frame); box-shadow: var(--shadow-float); }
.case__phone { left: 68cqw; top: 50cqw; width: 23cqw; border: calc(2 * var(--hairline)) solid var(--text); transition: border-color var(--t-colour); }
.case__panel { left: 6cqw; top: 56cqw; width: 62cqw; }
/* An app has no desktop screen: two full phone screens side by side, the second set lower. */
.case__media--app .case__phone { width: 36cqw; }
.case__media--app .case__phone:first-child { left: 10cqw; top: 6cqw; }
.case__media--app .case__phone + .case__phone { left: 52cqw; top: 16cqw; }
.case__body { padding-top: var(--pad-tile); border-top: var(--hairline) solid var(--hair); }
.case__name { font-family: var(--font-display); font-weight: var(--display-weight); font-size: var(--text-quote);
  line-height: 1.2; letter-spacing: var(--track-head); }
.case__name a { color: inherit; text-decoration: none; }
.case__name a::after { content: ""; position: absolute; inset: 0; z-index: 1; }
.case__name a:focus-visible { outline: none; }
.case__text { margin-top: .5rem; color: var(--text-2); }
.case::after { content: "→"; position: absolute; right: var(--pad-tile); bottom: var(--pad-tile); line-height: 1.5rem;
  transition: translate var(--t-colour); }
.case:has(.case__name a:focus-visible) { --text: var(--on-cta); --text-2: var(--on-cta); background: var(--cta);
  outline: var(--focus-width) solid var(--focus); outline-offset: var(--focus-offset); }
.case:has(.case__name a:focus-visible) .case__brand img:first-child:not(:only-child) { opacity: 0; }
.case:has(.case__name a:focus-visible) .case__brand img + img { opacity: 1; }
@media (hover: hover) {
  .case:hover { --text: var(--on-cta); --text-2: var(--on-cta); background: var(--cta); }
  .case:hover .case__brand img:first-child:not(:only-child) { opacity: 0; }
  .case:hover .case__brand img + img { opacity: 1; }
  .case:hover::after { translate: .25rem 0; }
}
@container (max-width: 14rem) {   /* the widest logo (121 px) + gap + the widest tag (80 px) no longer fit */
  .case__top { flex-direction: column; }
  .case__tags { display: flex; gap: .5rem; text-align: left; }
}
/* Four in a row down to 1024 px, two to 640 px, then one */
@media (max-width: 63.99rem) { .cases { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
/* Phones: a swipe row, see the shared rule after Ratgeber. */

/* A section after another of the same theme: a hairline between them (§1.4 hairline dividers), inside the margins,
   with the full section spacing on both sides of it. */
.section--ruled { padding-top: 0; }
.section--ruled > .wrap::before { content: ""; display: block; grid-column: 1 / -1;   /* a whole row when the wrap is a grid */
  border-top: var(--hairline) solid var(--rule); margin-bottom: var(--section); }
:is(.theme-dark, .theme-brand) + .section--ruled > .wrap::before { border-top-color: transparent; }   /* after a coloured band the colour
   change divides them: the space stays, the hairline goes */

/* Kundenstimmen (Voices): six real quotes as cards in a horizontal swipe row, after the reference's testimonial
   slider (../raw/REFERENCE-Cortea.md, Testimonial Card): --bg-2 cards, square, --pad-card; the quote in the heading
   face at quote size with typographic quote marks; at the foot a square portrait, name and role, and the project
   link where there is one. Three cards per view from 1280 px, two below, one on phones. The row runs to the
   window's edges: its padding lines the cards up with the page's content, so the neighbouring cards show in the
   margins on both sides — the sign that it slides. Native horizontal scrolling with snap points (touch, trackpad,
   arrow keys on the focused row), so it works without JavaScript; components.js adds the arrows (outline icon
   buttons, 44 px, top right like the reference's) and copies the set before and after so the row loops.
   The card width is drawn in the row's own width (cqw). Portraits 4rem: the sources are 70–96 px, too small for
   the reference's 121 px. */
.voices__nav { display: flex; gap: .5rem; }
.voices { position: relative; container-type: inline-size; overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x mandatory;
  scroll-padding-inline: max(var(--margin), (100% - var(--page-max)) / 2 + var(--margin)); scrollbar-width: none; }
.voices::-webkit-scrollbar { display: none; }
.voices:focus-visible { outline-offset: calc(-1 * var(--focus-width)); }
.voices__track { --per: 3; --edge: max(var(--margin), (100cqw - var(--page-max)) / 2 + var(--margin));
  display: flex; gap: var(--gutter); width: max-content; padding-inline: var(--edge); }
.voice { flex: none; width: calc((100cqw - 2 * var(--edge) - (var(--per) - 1) * var(--gutter)) / var(--per)); display: flex;
  padding: var(--pad-card); background: var(--bg-2); border-radius: var(--radius-container); scroll-snap-align: start; }
.voice figure { display: flex; flex-direction: column; gap: var(--gap-block); width: 100%; }
.voice blockquote { font-family: var(--font-display); font-weight: var(--display-weight); font-size: var(--text-quote);
  line-height: var(--leading-quote); letter-spacing: var(--track-head); }
.voice blockquote p::before { content: "„"; }
.voice blockquote p::after { content: "“"; }
.voice figcaption { display: flex; align-items: flex-end; gap: 1rem; margin-top: auto; }
.voice figcaption img { flex: none; width: 4rem; height: auto; aspect-ratio: 1; object-fit: cover; border-radius: var(--radius-container); }
.voice b { display: block; font-weight: var(--title-weight); }
.voice small { display: block; font-size: var(--text-size); line-height: var(--text-leading); color: var(--text-2); }
.voice figcaption a { display: flex; width: fit-content; min-height: var(--control-h); margin-bottom: calc((var(--control-h) - 1lh) / -2); }
@media (max-width: 79.99rem) { .voices__track { --per: 2; } }   /* three below 1280 px get too tall (740 px at 1024) */
@media (max-width: 47.99rem) {
  /* One card, a little narrower than the content, centred: a strip of each neighbour shows on both sides. */
  .voices__track { --per: 1.15; }
  .voice { scroll-snap-align: center; }
}

/* Numbered list: hairline rows with the number (01, 02 …) in the label size on the left, a title and a line of
   --text-2 under it, or the title alone (booking steps). */
.numbered { counter-reset: step; border-top: var(--hairline) solid var(--rule); }
.numbered li { display: grid; grid-template-columns: 3rem minmax(0, 1fr); gap: .25rem 1rem; padding-block: 1.25rem; border-bottom: var(--hairline) solid var(--rule); }
.numbered li { font-weight: var(--title-weight); }   /* the title, also when an editor dropped its <p> (WordPress) */
.numbered li::before { counter-increment: step; content: "0" counter(step); grid-row: span 2;   /* a title-only row: see below */
  font-size: var(--text-small); font-weight: var(--text-weight); color: var(--text-2); padding-top: .2em; }
.numbered p:first-of-type { font-weight: var(--title-weight); }
.numbered li:not(:has(> p + p))::before { grid-row: auto; }   /* title only: no empty second row */
.numbered li > p.muted { grid-column: 2; font-weight: var(--text-weight); }   /* the line under the title stays beside the number */
.numbered li:has(> p.muted)::before { grid-row: span 2; }

/* Tabs (§ Components, Tabs — the reference's underline tabs): the labels in a row on a hairline; the chosen one in
   --text at the title weight with a 2 px ink line under it (state by line and weight, not colour alone), the others
   in --text-2. 44 px and more. Behaviour in components.js ([data-tabs]): arrow keys, Home, End; the panels share one
   grid cell, so the block keeps the height of the longest. Without JavaScript the row stays hidden and every panel
   shows. */
.tabs { display: flex; flex-wrap: wrap; border-bottom: var(--hairline) solid var(--rule); }
.tabs__tab { min-height: var(--control-h); padding: 1.25rem 1.5rem; margin-bottom: calc(-1 * var(--hairline)); border: 0;
  border-bottom: calc(2 * var(--hairline)) solid transparent; background: none; color: var(--text-2); font: inherit; cursor: pointer;
  transition: color var(--t-colour), border-color var(--t-colour); }
.tabs__tab:hover { color: var(--text); }
.tabs__tab[aria-selected="true"] { color: var(--text); font-weight: var(--title-weight); border-bottom-color: var(--text); }
[data-tabs].is-tabbed :has(> [data-tab-panel]) { display: grid; }   /* the panels' parent: one cell for all */
[data-tabs].is-tabbed [data-tab-panel] { grid-area: 1 / 1; visibility: hidden; }
[data-tabs].is-tabbed [data-tab-panel].is-shown { visibility: visible; }

/* Process (So arbeiten wir, #prozess) on the dark band: six step tiles (the kit's .step: --bg-2, the number in the
   heading face, the note under a hairline at the foot), three in a row. */
.steps { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--gutter); }
@media (max-width: 63.99rem) { .steps { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
/* Phones: compact rows — the number beside the title, text and note instead of above them (the six tiles made 2,300 px). */
@media (max-width: 47.99rem) {
  .steps { grid-template-columns: 1fr; }
  .step { display: grid; grid-template-columns: 2.5rem minmax(0, 1fr); column-gap: .75rem; row-gap: .5rem; padding: var(--pad-tile); }
  .step .num { grid-row: span 3; font-size: var(--text-quote); line-height: 1.2; }
  .step .note { margin-top: .5rem; padding-top: .75rem; }
}

/* FAQ (§ Components, FAQ): after the reference's 4/8 split, widened to 5 : 7 with a section-sized gap between the
   two (client: the columns sat too close, and the two buttons should stand side by side) — heading, intro, three
   short points and the buttons on the left (sticky while the questions scroll past), the questions on the right as
   hairline rows. Below 1280 px the two stack, so the buttons always stand side by side.
   Native <details>/<summary>: every answer is in the HTML, opens without JavaScript and works with the keyboard;
   the browser's own marker is replaced by a drawn chevron on the right that turns up when the row is open (state by
   shape, and the answer itself shows). Question at the title size and weight, answer in --text-2 at body size. */
.faq { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); column-gap: var(--section-sm); align-items: start; }
.faq__head { position: sticky; top: var(--section-sm); }
.faq__head > p { margin-top: var(--gap-text); color: var(--text-2); }
.faq__points { margin-top: var(--gap-block); border-top: var(--hairline) solid var(--rule); }
.faq__points li { padding-block: 1rem; border-bottom: var(--hairline) solid var(--rule); }
.faq__points b { display: block; font-weight: var(--title-weight); }
.faq__points span { display: block; font-size: var(--text-small); line-height: var(--leading-small); color: var(--text-2); }
.faq__head .btns { margin-top: var(--gap-actions); }
.faq__list { border-top: var(--hairline) solid var(--rule); }
.faq__item { border-bottom: var(--hairline) solid var(--rule); }
.faq__item summary { position: relative; display: flex; align-items: center; min-height: var(--control-h); padding: 1.25rem 1.5rem 1.25rem 0;
  list-style: none; cursor: pointer; }
.faq__item summary::-webkit-details-marker { display: none; }
.faq__item summary::after { content: ""; position: absolute; right: .5rem; top: 50%; width: .5rem; height: .5rem;
  border-right: calc(1.5 * var(--hairline)) solid currentColor; border-bottom: calc(1.5 * var(--hairline)) solid currentColor;
  translate: 0 -75%; rotate: 45deg; transition: rotate var(--t-open), translate var(--t-open); }
.faq__item[open] summary::after { translate: 0 -25%; rotate: -135deg; }
.faq__item h3 { font-size: var(--text-title); line-height: var(--leading-title); font-weight: var(--title-weight); }
.faq__item summary:hover h3 { text-decoration: underline; text-underline-offset: .2em; }
.faq__item p { max-width: 42rem; padding: 0 1.5rem 1.5rem 0; color: var(--text-2); }
.faq__item p a { color: var(--text); text-underline-offset: .2em; }
@media (max-width: 79.99rem) {   /* below 1280 px the left column gets too narrow for both buttons: stack */
  .faq { grid-template-columns: 1fr; }
  .faq__head { position: static; margin-bottom: var(--gap-block); }
}

/* Ratgeber (Posts): the reference's blog card — no container, a 3:2 cover with square corners, the category and
   date in the label face in --text-2, the title at the title size; the title's link stretches over the card and
   is underlined on hover. In the HTML the title comes first (headings before their details); the cover and the
   date are moved above it visually. Three in a row, like the reference's /blog; a swipe row below 768 px. */
.posts { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--gap-row) var(--gutter); }
.post { position: relative; display: flex; flex-direction: column; }
.post img { order: -2; width: 100%; height: auto; aspect-ratio: 3 / 2; object-fit: cover; border-radius: var(--radius-container); }
.post__meta { order: -1; margin-top: 1rem; font-family: var(--font-label); font-size: var(--text-small); line-height: var(--leading-small); color: var(--text-2); }
.post__title { margin-top: .5rem; font-size: var(--text-title); line-height: var(--leading-title); font-weight: var(--title-weight); }
.post__title a { text-decoration: none; text-underline-offset: .2em; }
.post__title a::after { content: ""; position: absolute; inset: 0; }
.post:hover .post__title a { text-decoration: underline; }
.post__title a:focus-visible { outline: none; text-decoration: underline; }
.post:has(.post__title a:focus-visible) { outline: var(--focus-width) solid var(--focus); outline-offset: var(--focus-offset); }

/* Phones (below 768 px): Projekte and Ratgeber become swipe rows instead of stacks (four project cards made 2,700 px,
   three posts 1,250 px): each card a little narrower than the content so the next one shows; the row runs to the
   screen's edges, lines its first card up with the content and snaps card by card. */
@media (max-width: 47.99rem) {
  .cases, .posts { display: flex; gap: var(--gutter); overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x mandatory;
    margin-inline: calc(-1 * var(--margin)); padding-inline: var(--margin); scroll-padding-inline: var(--margin); scrollbar-width: none; }
  .cases::-webkit-scrollbar, .posts::-webkit-scrollbar { display: none; }
  .case, .post { flex: 0 0 85%; scroll-snap-align: start; }
}

/* Booking (Erstgespräch, #calendlysektion1) on the dark band, laid out like the live section: the text on the left
   (heading, lead and the three steps as numbered hairline rows, titles only), the Calendly
   booking on the right as a light floating panel (.theme-light, --radius-ui-frame, --shadow-float: a third party's UI
   on the page, like the browser frames): Telefonat / Video, then the calendar. Calendly loads only after a click; until
   then the panel holds the button and the privacy note in its middle. Sticky beside the longer text column. */
.book { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--gap-block); align-items: start; }
.book__text .lead { margin-top: var(--gap-text); }
.book__text .numbered { margin-top: var(--gap-block); }
.book__widget { position: sticky; top: var(--section-sm); display: flex; flex-direction: column; align-items: center; padding: var(--pad-tile);
  border-radius: var(--radius-ui-frame); box-shadow: var(--shadow-float); }
.book__gate { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: .75rem; width: 100%; min-height: 24rem;
  text-align: center; }
.book__gate p { max-width: 20rem; font-size: var(--text-small); line-height: var(--leading-small); }
.calendly-frame { width: 100%; }
@media (max-width: 63.99rem) {   /* the calendar needs the full width below 1024 px: text above, booking below */
  .book { grid-template-columns: 1fr; }
  .book__widget { position: static; }
}
.segmented { display: inline-flex; padding: 3px; margin-bottom: 1rem; border: var(--hairline) solid var(--line); border-radius: var(--radius-control); }
.segmented button { min-height: var(--control-h); padding-inline: 1rem;   /* 44 px targets; the group grows by its padding */ border: 0; border-radius: var(--radius-control);
  background: transparent; color: var(--text); font: inherit; cursor: pointer; transition: background-color var(--t-colour), color var(--t-colour); }
.segmented button[aria-pressed="true"] { background: var(--cta); color: var(--on-cta); }
.calendly-frame iframe { display: block; width: 100%; height: 44rem; border: 0; background: var(--bg); }

/* Closing CTA band (brand theme): text left, buttons right, centred on the text block. Bottom-aligned, the buttons sat
   in the bottom-right corner with the top right empty, so the band read heavier at the bottom although its padding is
   the same above and below (112 px at 1440); their labels also sat 10 px above the last line of text. */
.closing .wrap { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: var(--gap-block); }
.closing__text { margin-top: var(--gap-text); }
.closing__tagline { display: flex; align-items: center; gap: .5rem; margin-bottom: var(--gap-text); }
.closing__tagline i { display: block; width: 2.5rem; aspect-ratio: 299.41 / 170.79; background: currentColor;
  -webkit-mask: url(../images/logo-mark.svg) no-repeat center / contain; mask: url(../images/logo-mark.svg) no-repeat center / contain; }
.btns { display: flex; flex-wrap: wrap; gap: .75rem; }

/* ===== Sub-pages (2026-10-26): the parts the service, blog, reference and company pages add to the homepage's set.
   Built by tools/site/build.mjs from the live pages' content; every one reads tokens only, like the rest. ===== */

/* Breadcrumbs: Home / section / page, in the small size and --text-2; the current page in --text. Links are 44 px. */
.crumbs { margin-bottom: var(--gap-text); font-size: var(--text-small); line-height: var(--leading-small); color: var(--text-2); }
.crumbs ol { display: flex; flex-wrap: wrap; align-items: center; }
.crumbs li { display: inline-flex; align-items: center; min-height: var(--control-h); }
.crumbs li + li::before { content: "/"; margin-inline: .5rem; }
.crumbs a { display: inline-flex; align-items: center; min-height: var(--control-h); color: inherit; text-underline-offset: .2em; }
.crumbs [aria-current] { color: var(--text); }

/* Second heading face: a block's heading inside a section that already has its H2 (panels, sub-blocks, articles). */
.h3 { font-family: var(--font-display); font-weight: var(--display-weight); font-size: var(--text-quote); line-height: var(--leading-quote);
  letter-spacing: var(--track-head); text-wrap: balance; max-width: 30rem; }
.intro > .h3 { max-width: 16em; }
/* An H1 with a second line (the live pages' "Name – claim"): the claim one step smaller, in --text-2. */
.h1__sub { display: block; margin-top: .5rem; font-size: var(--text-h2); line-height: var(--leading-h2); color: var(--text-2); }

/* Page hero (service, company and cost pages): the homepage hero's parts on a 7 : 5 split — crumbs, H1, lead, the two
   actions and the page's three points on the left; on the right one team photo with the page's four figures on proof
   cards at its foot, like the homepage's tall photo. Below 1024 px the photo goes under the text, the cards straddle
   its foot in one row; on phones they sit inside it again, two by two. */
.page-hero { padding-top: var(--gap-text); }
.page-hero__grid { display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); column-gap: var(--gutter); align-items: start; }
.page-hero .lead { margin-top: var(--gap-lead); }
.page-hero__note { margin-top: .75rem; font-size: var(--text-small); line-height: var(--leading-small); color: var(--text-2); }
.page-hero__points { margin-top: var(--gap-block); max-width: 34rem; }
.page-hero__media { position: relative; display: grid; isolation: isolate; }
.page-hero__media .tall { grid-area: 1 / 1; width: 100%; height: auto; aspect-ratio: 4 / 5; object-fit: cover; border-radius: var(--radius-container); }
.page-hero__media .proof { grid-area: 1 / 1; align-self: end; margin: var(--pad-tile); position: relative; z-index: 1; }
.page-hero .chips { margin-top: var(--gap-text); }
@media (max-width: 63.99rem) {
  .page-hero__grid { grid-template-columns: 1fr; row-gap: var(--gap-block); }
  .page-hero__media .tall { aspect-ratio: 3 / 2; }
  .page-hero__media .proof { grid-area: 2 / 1; align-self: start; margin: -3rem var(--pad-tile) 0; grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
@media (max-width: 47.99rem) {   /* the photos are landscape: shown 3 : 2, the cards two by two under its foot (inside, they hid the faces) */
  .page-hero__media .proof { margin: -3rem var(--gutter) 0; grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Centred page hero (client, 2026-11-02, service pages): crumbs, H1, lead, the two actions and one trust line on the
   centre axis; the page's team photo wide under them (21 : 9, 16 : 9 on tablets, 3 : 2 on phones), then the client logos. */
.page-hero--center .crumbs ol { justify-content: center; }
.page-hero__head { display: grid; justify-items: center; max-width: 52rem; margin-inline: auto; text-align: center; }
.page-hero__head .lead { max-width: 38rem; }
.page-hero__head .hero__actions { align-items: center; }
.page-hero__head .trustline { justify-content: center; }
.page-hero__photo { width: 100%; height: auto; margin-top: var(--gap-block); aspect-ratio: 21 / 9; object-fit: cover;
  border-radius: var(--radius-container); }
@media (max-width: 63.99rem) { .page-hero__photo { aspect-ratio: 16 / 9; } }
@media (max-width: 47.99rem) { .page-hero__photo { aspect-ratio: 3 / 2; } }

/* Process demo (client, 2026-11-02; under the centred page hero on website pages): a website taking shape in the
   browser frame on the Nebelblau field (field A, like the showcase), the window running off the field's foot. One
   scene per step of the page's own process, picked by the figure's data-step (components.js):
   1 the kick-off — "Sie" and "Web Austria" joined by a running dashed line, the workshop notes popping in;
   2 UX/UI & content, in a design tool — the page zooms out onto a grey canvas as a frame ("Startseite – Desktop"),
     layers left, properties right; it arrives piece by piece (logo, menu, text, buttons, drawing, boxes), then a
     cursor selects the headline and types it (caret in the selection box) and drags the picture's corner to make it
     larger (its size under it, measured from the layout by components.js);
   3 development — a field of code (fragments of HTML, CSS and JavaScript written by components.js) over the whole
     page, running upwards and faded out towards its edges; it fades out, then the page fades in; then a quality-check
     panel ticks off its points;
   4 the launch — a new tab: the page goes blank and the live .at domain is typed into an address field in the middle
     (like a browser's new-tab page), Enter, the field fades and the site loads; the address bar shows the domain with
     the lock, left like the other steps' addresses; then the first enquiry.
   The mock page is an example client's (a made-up PV installer, see BUILD_DEMO in tools/site/build.mjs): its sun logo,
   its name and a drawn roof with panels, coloured by the field tokens. Under it the steps as buttons on a
   segmented line (done and current in the text colour, the current one also in the title weight); a click shows that
   scene and stops the automatic run (no Pause button, client; it also holds under the pointer and with keyboard focus).
   On phones only the current step keeps its name. Scene changes are transitions, the things that appear inside
   a scene are animations (they replay each time the scene comes back; --i orders them). Without JavaScript and with
   reduced motion it rests on step 4, without fades. Colours are tokens only. */
.build { margin: var(--gap-block) 0 0; }
.build:not(.is-running) * { transition: none !important; }   /* no fades on load: they start with components.js */
.build__stage { position: relative; overflow: hidden; border-radius: var(--radius-container); background: var(--field-a-from);
  container-type: inline-size; }
.build__window { position: relative; margin: clamp(1rem, 4.5cqw, 3rem) clamp(1rem, 9cqw, 8rem) 0;
  border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
/* The mock page is drawn at a fixed size, like a screenshot, and scaled as a whole to the window (--s, set by
   components.js with the size, data-canvas, from the window's width): wide 1200 × 675, mid 800 × 600 (tablets and
   narrow laptops), narrow 340 × 500 (phones). Its layout never reflows between those, so nothing can squeeze or run
   over; the container queries below pick the mid and narrow layouts. */
.build__view { position: relative; overflow: hidden; aspect-ratio: 1200 / 675; }
.build__page { position: absolute; top: 0; left: 0; width: 1200px; height: 675px; transform: scale(var(--s, .9)); transform-origin: 0 0;
  container: page / inline-size; }
.build[data-canvas="mid"] .build__view { aspect-ratio: 800 / 600; }
.build[data-canvas="mid"] .build__page { width: 800px; height: 600px; }
.build[data-canvas="narrow"] .build__view { aspect-ratio: 340 / 500; }
.build[data-canvas="narrow"] .build__page { width: 340px; height: 500px; }
.build__lock { display: inline-block; width: 0; margin-right: 0; vertical-align: -.1em; opacity: 0; fill: none; stroke: currentColor;
  stroke-width: 1.5; transition: width .4s ease, margin .4s ease, opacity .4s ease; }
/* The address's parts sit inside the bar's pill, so they take none of its own spacing or fill (.browser__bar span). */
.browser__bar :is(.build__url-dev, .build__url-design, .build__url-live) { flex: none; margin: 0; padding: 0; border-radius: 0; background: none; }
.build__url-live, .build__url-design, .build:is([data-step="2"], [data-step="4"]) .build__url-dev { display: none; }
.build[data-step="2"] .build__url-design { display: inline; }
.build[data-step="4"] .build__url-live { display: inline; animation: build-type .4s ease 2.1s both; }
.build[data-step="4"] .build__lock { width: .5rem; margin-right: .25rem; opacity: 1; transition-delay: 2.1s; }
.build__kickoff, .build__site { position: absolute; inset: 0; transition: opacity .6s ease, visibility .6s; }
@keyframes build-pop { from { opacity: 0; transform: translateY(.75rem); } }
@keyframes build-type { from { color: transparent; } }
@keyframes build-scroll { to { transform: translateY(-50%); } }
@keyframes build-in { from { opacity: 0; } }
@keyframes build-out { to { opacity: 0; } }
@keyframes build-tick { from { border-color: var(--line); background-color: transparent; color: transparent; } }
@keyframes build-dash { to { stroke-dashoffset: -9; } }
@keyframes build-on { from, to { opacity: 1; } }
@keyframes build-mark { from, to { background-color: var(--rule); color: var(--text); } }
@keyframes build-reveal { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0); } }
@keyframes build-caret { to { left: 100%; } }
@keyframes build-blink { 50% { opacity: 0; } }
@keyframes build-grow { from { transform: scale(.85); } }
@keyframes build-grow-box { from { width: calc(var(--iw) * .85); height: calc(var(--ih) * .85); } }
@keyframes build-cursor {
  0% { left: 72%; top: 88%; opacity: 0; }
  8% { opacity: 1; }
  25%, 48% { left: var(--hx); top: calc(var(--hy) + var(--hh) * .6); }
  65% { left: calc(var(--ix) + var(--iw) * .85); top: calc(var(--iy) + var(--ih) * .85); opacity: 1; }
  90%, 100% { left: calc(var(--ix) + var(--iw)); top: calc(var(--iy) + var(--ih)); opacity: 1; }
}
/* The order things appear in within a scene (--i, used by the animation delays) */
.build__notes li:nth-child(2), .build__qa li:nth-child(2) .build__box, .build__menu { --i: 1; }
.build__notes li:nth-child(3), .build__qa li:nth-child(3) .build__box, .build__nav .build__btn { --i: 2; }
.build__qa li:nth-child(4) .build__box, .build__h { --i: 3; }
.build__qa li:nth-child(5) .build__box, .build__lead { --i: 4; }
.build__qa li:nth-child(6) .build__box, .build__copy .build__btn { --i: 5; }
.build__img { --i: 6; }
.build__col:nth-child(1) { --i: 7; }
.build__col:nth-child(2) { --i: 8; }
.build__col:nth-child(3) { --i: 9; }

/* 1 · kick-off */
.build__kickoff { display: grid; place-content: center; justify-items: center; gap: 2rem; opacity: 0; visibility: hidden; }
.build__team { display: flex; align-items: center; gap: 1rem; }
.build__who { display: inline-flex; align-items: center; gap: .625rem; min-height: 3rem; padding: .5rem 1.25rem; border-radius: var(--radius-control);
  background: var(--bg-2); color: var(--text); font-family: var(--font-label); font-size: var(--text-label-lg); line-height: var(--leading-small); }
.build__mark { display: block; width: 2rem; aspect-ratio: 299.41 / 170.79; background: currentColor;
  -webkit-mask: url(../images/logo-mark.svg) no-repeat center / contain; mask: url(../images/logo-mark.svg) no-repeat center / contain; }
.build__link { width: clamp(3rem, 14cqw, 8rem); height: .5rem; overflow: visible; }
.build__link path { fill: none; stroke: var(--line); stroke-width: 1.5; stroke-dasharray: 4 5; vector-effect: non-scaling-stroke; }
.build__notes { display: flex; flex-wrap: wrap; justify-content: center; gap: .5rem; }
.build__notes li { padding: .75rem 1rem; border: var(--hairline) solid var(--rule); border-radius: var(--radius-chip); background: var(--bg);
  color: var(--text-2); font-size: var(--text-label-lg); line-height: var(--leading-small); }
.build[data-step="1"] .build__kickoff { opacity: 1; visibility: visible; }
.build[data-step="1"] .build__link path { animation: build-dash 1s linear infinite; }
.build[data-step="1"] .build__notes li { animation: build-pop .4s ease calc(.4s + var(--i, 0) * .35s) both; }

/* 2 · the designed page, arriving piece by piece */
.build__site { display: flex; flex-direction: column; gap: clamp(.75rem, 3cqw, 1.75rem); padding: clamp(.75rem, 2.5cqw, 1.75rem) clamp(1rem, 4cqw, 3rem); }
.build[data-step="1"] .build__site { opacity: 0; visibility: hidden; }
.build__nav { display: flex; align-items: center; gap: clamp(.75rem, 2.5cqw, 1.75rem); font-family: var(--font-label); font-size: var(--text-small); line-height: var(--leading-small); }
.build__brand { display: flex; align-items: center; gap: .5rem; margin-right: auto; }
.build__logo { width: 1.5rem; height: 1.5rem; border-radius: 50%; background: var(--field-b-to); }
.build__name { font-weight: var(--title-weight); }
.build__menu { display: flex; gap: clamp(.75rem, 2.5cqw, 1.75rem); color: var(--text-2); }
.build__btn { display: block; padding: .375rem .875rem; border-radius: var(--radius-control); background: var(--cta); color: var(--on-cta);
  font-family: var(--font-label); font-size: var(--text-small); line-height: var(--leading-small); white-space: nowrap; }
.build__hero { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: clamp(1rem, 4cqw, 3rem); flex: 1; min-height: 0; align-items: center; }
.build__copy { display: grid; justify-items: start; gap: .75rem; }
.build__h { font-family: var(--font-display); font-weight: var(--display-weight); font-size: clamp(1.125rem, 4.5cqw, 2.5rem); line-height: 1.15; color: var(--text); }
.build__lead { max-width: 24rem; color: var(--text-2); font-size: var(--text-small); line-height: var(--leading-small); }
.build__copy .build__btn { margin-top: .25rem; }
.build__img { align-self: center; aspect-ratio: 4 / 3; max-height: 100%; overflow: hidden; border-radius: var(--radius-chip); background: var(--bg-2); }   /* never taller than wide */
.build__img img { display: block; width: 100%; height: 100%; object-fit: cover; }
.build__cols { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(.5rem, 2cqw, 1.5rem); }
.build__col { display: flex; align-items: end; min-height: clamp(1.5rem, 6cqw, 4rem); padding: .5rem .75rem; border-radius: var(--radius-chip);
  background: var(--bg-2); color: var(--text); font-family: var(--font-label); font-size: var(--text-small); line-height: var(--leading-small); }
.build[data-step="2"] :is(.build__brand, .build__menu, .build__nav .build__btn, .build__lead, .build__copy .build__btn, .build__col) {
  animation: build-pop .45s ease calc(.4s + var(--i, 0) * .22s) both; }

/* 2 · the design tool: canvas, frame, panels, the cursor's two edits (timed to build-cursor: .6 s + 4.6 s) */
.build__page > * { --build-zoom: .74; }   /* leaves the side panels about 130 px at desktop width */
.build__page { transition: background-color .6s ease; }
.build[data-step="2"] .build__page { background: var(--bg-2); }
.build__site { background: var(--bg); transform-origin: 50% 50%; transition: opacity .6s ease, visibility .6s, transform .6s ease; }
.build:is([data-step="1"], [data-step="2"]) .build__site { transform: scale(var(--build-zoom)); }
.build__type { display: inline-block; }
.build[data-step="2"] .build__type { animation: build-reveal 1.2s steps(20) 1.85s both; }
.build[data-step="2"] .build__img { transform-origin: 0 0; animation: build-pop .45s ease 1.2s both, build-grow 1.15s ease 3.6s both; }
.build__frame-label, .build__panel, .build__sel, .build__cursor { position: absolute; z-index: 2; opacity: 0; visibility: hidden; transition: opacity .3s ease, visibility .3s; }
.build[data-step="2"] :is(.build__frame-label, .build__panel) { opacity: 1; visibility: visible; }
.build[data-step="2"] :is(.build__sel, .build__cursor) { visibility: visible; transition: none; }
.build__frame-label { top: calc((100% - 100% * var(--build-zoom)) / 2 - 1.375rem); left: calc((100% - 100% * var(--build-zoom)) / 2);
  color: var(--text-2); font-family: var(--font-label); font-size: var(--text-small); line-height: var(--leading-small); }
.build__panel { top: 0; bottom: 0; width: calc((100% - 100% * var(--build-zoom)) / 2 - .75rem); padding: .75rem .625rem; overflow: hidden;
  background: var(--bg); font-family: var(--font-label); font-size: var(--text-small); line-height: var(--leading-small); }
.build__panel--layers { left: 0; border-right: var(--hairline) solid var(--rule); }
.build__panel--props { right: 0; border-left: var(--hairline) solid var(--rule); }
.build__panel > p { margin-bottom: .5rem; color: var(--text); font-weight: var(--title-weight); }
.build__panel li { padding: .25rem .375rem; border-radius: var(--radius-chip); color: var(--text-2); white-space: nowrap; }
.build[data-step="2"] .build__layer-h { animation: build-mark 1.3s linear 1.75s; }
.build[data-step="2"] .build__layer-i { animation: build-mark .01s linear 3.1s forwards; }
.build__panel dl { display: grid; gap: .375rem; color: var(--text-2); }
.build__panel dl div { display: flex; align-items: center; justify-content: space-between; gap: .375rem; padding: .25rem .375rem; border-radius: var(--radius-chip); background: var(--bg-2); }
.build__panel dd { color: var(--text); }
.build__swatch { display: inline-block; width: 1rem; height: 1rem; vertical-align: -.2em; border-radius: var(--radius-chip); background: var(--field-b-to); }
.build__sel { border: 1.5px solid var(--text); pointer-events: none; }
.build__sel--text { left: var(--hx); top: var(--hy); width: var(--hw); height: var(--hh); }
.build__sel--text::after { content: ""; position: absolute; top: 12%; bottom: 12%; left: 0; width: 2px; background: var(--text); }
.build[data-step="2"] .build__sel--text { animation: build-on 1.35s linear 1.75s; }
.build[data-step="2"] .build__sel--text::after { animation: build-caret 1.2s steps(20) 1.85s both, build-blink .8s step-end 3.05s infinite; }
.build__sel--img { left: var(--ix); top: var(--iy); width: var(--iw); height: var(--ih); }
.build__sel--img i { position: absolute; width: .5rem; height: .5rem; border: 1.5px solid var(--text); background: var(--bg); }
.build__sel--img i:nth-child(1) { top: -.3rem; left: -.3rem; }
.build__sel--img i:nth-child(2) { top: -.3rem; right: -.3rem; }
.build__sel--img i:nth-child(3) { bottom: -.3rem; left: -.3rem; }
.build__sel--img i:nth-child(4) { bottom: -.3rem; right: -.3rem; }
.build__size { position: absolute; top: calc(100% + .5rem); left: 50%; translate: -50% 0; padding: .125rem .5rem; border-radius: var(--radius-chip);
  background: var(--text); color: var(--bg); font-family: var(--font-label); font-size: var(--text-small); line-height: var(--leading-small); white-space: nowrap; }
.build[data-step="2"] .build__sel--img { animation: build-on .01s linear 3.1s forwards, build-grow-box 1.15s ease 3.6s both; }
.build__cursor { left: 0; top: 0; width: 1.25rem; height: 1.25rem; z-index: 3; }
.build__cursor path { fill: var(--text); stroke: var(--bg); stroke-width: 1; stroke-linejoin: round; }
.build[data-step="2"] .build__cursor { animation: build-cursor 4.6s ease .6s both; }

/* 3 · development: one field of code over the whole page (client: as the first version, but code, not 0/1), running
   upwards and faded out towards its edges (a mask, which takes its opacity from currentColor, so no colour is written
   here); it fades out (.6 s), then the page fades in (.8 s; the code gone before the page comes). */
.build__bits { position: absolute; inset: 0; z-index: 1; overflow: hidden; background: var(--bg); color: var(--rule);
  font-family: var(--font-label); font-size: var(--text-small); line-height: 1.5; white-space: pre;
  opacity: 0; visibility: hidden; pointer-events: none; }
.build__code-field { position: absolute; inset: 0; overflow: hidden; padding: .5rem 1rem;
  -webkit-mask: linear-gradient(to right, transparent, currentColor 12%, currentColor 88%, transparent),
    linear-gradient(to bottom, transparent, currentColor 15%, currentColor 85%, transparent);
  -webkit-mask-composite: source-in;
  mask: linear-gradient(to right, transparent, currentColor 12%, currentColor 88%, transparent),
    linear-gradient(to bottom, transparent, currentColor 15%, currentColor 85%, transparent);
  mask-composite: intersect; }
.build__code-field i { font-style: normal; color: var(--line); }
.build[data-step="3"] .build__bits { opacity: 1; visibility: visible;
  animation: build-in .4s ease .1s both, build-out .6s ease 1.6s forwards; }   /* forwards: build-in holds until then */
.build[data-step="3"] .build__code-field > div { animation: build-scroll 12s linear infinite; }
.build[data-step="3"] .build__site { animation: build-in .8s ease 2.2s both; }

/* 3 · the quality check; 4 · the first enquiry */
.build__qa, .build__toast { position: absolute; right: clamp(1rem, 4cqw, 3rem); bottom: clamp(.75rem, 3cqw, 2rem); border: var(--hairline) solid var(--rule);
  background: var(--bg); color: var(--text); box-shadow: var(--shadow-float); font-family: var(--font-label); line-height: var(--leading-small);
  opacity: 0; visibility: hidden; transition: opacity .3s ease, visibility .3s; }
.build__qa { padding: 1rem 1.25rem; border-radius: var(--radius-ui-frame); font-size: var(--text-small); }
.build__qa-title { margin-bottom: .75rem; color: var(--text-2); }
.build__qa ul { display: grid; grid-template-columns: repeat(2, auto); gap: .625rem 1.5rem; }
.build__qa li { display: flex; align-items: center; gap: .5rem; white-space: nowrap; }
.build__box { display: grid; place-items: center; flex: none; width: 1.25rem; height: 1.25rem; border: 1px solid var(--cta); border-radius: 50%;
  background: var(--cta); color: var(--on-cta); }
.build__box svg { width: .875rem; height: .875rem; }
.build[data-step="3"] .build__qa { opacity: 1; visibility: visible; animation: build-pop .4s ease 3s both; }
.build[data-step="3"] .build__box { animation: build-tick .25s ease calc(3.4s + var(--i, 0) * .3s) both; }
.build__toast { display: inline-flex; align-items: center; gap: .75rem; padding: .625rem 1.25rem .625rem .625rem; border-radius: var(--radius-control);
  font-size: var(--text-label-lg); }
.build__tick { display: grid; place-items: center; flex: none; width: 2rem; height: 2rem; border-radius: 50%; background: var(--cta); color: var(--on-cta); }
.build__tick svg { width: 1.125rem; height: 1.125rem; }
.build__toast small { display: block; color: var(--text-2); font-size: var(--text-small); }
.build[data-step="4"] .build__toast { opacity: 1; visibility: visible; animation: build-pop .45s ease 3s both; }

/* 4 · the new tab: the site fades out, the domain is typed into the field in the middle (its width and letter count,
   --ow and --oc, measured by components.js), Enter, the field fades, the site fades back in (timed: .2 s + 2.1 s) */
@keyframes build-reload { 0% { opacity: 1; } 7%, 75% { opacity: 0; } 100% { opacity: 1; } }
@keyframes build-omni { 0% { opacity: 0; transform: translateY(.5rem); } 12%, 85% { opacity: 1; transform: none; } 100% { opacity: 0; transform: none; } }
@keyframes build-typew { from { width: 0; } to { width: var(--ow); } }
@keyframes build-press { 50% { background-color: var(--bg-2); color: var(--text); transform: scale(.9); } }
.build[data-step="4"] .build__site { animation: build-reload 2.9s ease both; }
.build__omni { position: absolute; z-index: 2; top: 50%; left: 50%; translate: -50% -50%; display: flex; align-items: center; gap: .625rem;
  width: min(80%, 28rem); padding: .5rem .5rem .5rem 1rem; border: var(--hairline) solid var(--rule); border-radius: var(--radius-control);
  background: var(--bg); color: var(--text); font-family: var(--font-label); font-size: var(--text-label-lg);
  line-height: var(--leading-small); opacity: 0; visibility: hidden; }
.build__omni-icon { flex: none; width: 1.125rem; height: 1.125rem; fill: none; stroke: var(--text-2); stroke-width: 1.5; stroke-linecap: round; }
.build__omni-text { display: inline-block; overflow: hidden; white-space: nowrap; }
.build__omni-caret { flex: none; width: 2px; height: 1.2em; margin-left: -.5rem; background: var(--text); }
.build__enter { display: grid; place-items: center; flex: none; width: 2rem; height: 2rem; margin-left: auto; border: var(--hairline) solid var(--rule);
  border-radius: 50%; color: var(--text-2); }   /* a circle in the field's round end, .5 rem from it all round, with the field's
  hairline; no shadow under the field, which made the gap below look larger */
.build__enter svg { width: 1rem; height: 1rem; fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
.build[data-step="4"] .build__omni { visibility: visible; animation: build-omni 2.1s ease .2s both; }
.build[data-step="4"] .build__omni-text { animation: build-typew 1.1s steps(var(--oc, 15)) .5s both; }
.build[data-step="4"] .build__omni-caret { animation: build-blink .8s step-end 1.6s infinite; }
.build[data-step="4"] .build__enter { animation: build-press .3s ease 1.75s both; }
.build :is(.build__qa, .build__tick) path { fill: none; stroke: currentColor; stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round; }

/* SEO demo (client, 2026-11-02; /seo-agentur-wien/, .build--seo): the same frame, the same sample site, four other scenes:
   1 the audit — a crawl line runs across the top of the page, then the audit panel lists what it found, one flag at a
     time, and sums it up;
   2 the strategy — the page gives way to the keyword map on the grey canvas: keywords with their search volume as a
     bar (filled in the accent, the one accent on that scene), the volume and the cluster, row by row;
   3 the fixes — the headline loses its old text and gets the one with the keyword typed in; then the check panel
     (the website demo's quality check) ticks the measures;
   4 Google — the page fades to a results page, the query is typed into the search field, three results come in,
     the sample site climbs from third to first (the rows swap places), its position pops in, then the enquiry.
   Which address the bar shows follows the scene; the lock is there whenever the sample site's address is. */
.build--seo .build__url-site, .build--seo .build__url-map, .build--seo .build__url-google { display: none; }
.build--seo:is([data-step="1"], [data-step="3"]) .build__url-site, .build--seo[data-step="2"] .build__url-map,
.build--seo[data-step="4"] .build__url-google { display: inline; }
.build--seo:is([data-step="1"], [data-step="3"], [data-step="4"]) .build__lock { width: .5rem; margin-right: .25rem; opacity: 1; transition-delay: 0s; }
/* The site: whole on 1 and 3, gone on 2 and 4 (no zoom, no reload, no code field here) */
.build--seo:is([data-step="1"], [data-step="2"]) .build__site { transform: none; }
.build--seo[data-step="1"] .build__site { opacity: 1; visibility: visible; }
.build--seo:is([data-step="2"], [data-step="4"]) .build__site { opacity: 0; visibility: hidden; }
.build--seo:is([data-step="2"], [data-step="3"], [data-step="4"]) :is(.build__site, .build__img, .build__brand, .build__menu, .build__nav .build__btn, .build__lead, .build__copy .build__btn, .build__col) { animation: none; }
/* The order the panels' rows appear in (--i), and the results' places before and after the climb (--from, --row) */
:is(.build--seo, .build--ads) :is(.build__audit, .build__kw, .build__results) li:nth-child(2) { --i: 1; }
:is(.build--seo, .build--ads) :is(.build__audit, .build__kw, .build__results) li:nth-child(3) { --i: 2; }
:is(.build--seo, .build--ads) :is(.build__audit, .build__kw) li:nth-child(4) { --i: 3; }
:is(.build--seo, .build--ads) :is(.build__audit, .build__kw) li:nth-child(5) { --i: 4; }
:is(.build--seo, .build--ads) :is(.build__audit, .build__kw) li:nth-child(6) { --i: 5; }
.build__results li:nth-child(1) { --from: 0; --row: 1; }
.build__results li:nth-child(2) { --from: 1; --row: 2; }
.build__results .build__result--own { --from: 2; --row: 0; }
/* 1 · the crawl line and the audit panel */
.build__crawl { position: absolute; z-index: 2; top: 0; left: 0; width: 0; height: 3px; background: var(--text); opacity: 0; }
@keyframes build-crawl { from { width: 0; opacity: 1; } 85% { opacity: 1; } to { width: 100%; opacity: 0; } }
.build--seo[data-step="1"] .build__crawl { animation: build-crawl 1.4s ease .2s both; }
.build__audit, .build__kw { position: absolute; z-index: 2; border: var(--hairline) solid var(--rule); border-radius: var(--radius-ui-frame); background: var(--bg);
  color: var(--text); box-shadow: var(--shadow-float); font-family: var(--font-label); font-size: var(--text-small); line-height: var(--leading-small);
  opacity: 0; visibility: hidden; transition: opacity .3s ease, visibility .3s; }
.build__audit { right: clamp(1rem, 4cqw, 3rem); bottom: clamp(.75rem, 3cqw, 2rem); padding: 1rem 1.25rem; }
.build__audit ul { display: grid; gap: .625rem; }
.build__audit li { display: flex; align-items: center; gap: .5rem; white-space: nowrap; }
.build__flag { display: grid; place-items: center; flex: none; width: 1.25rem; height: 1.25rem; border: 1px solid var(--line); border-radius: 50%; color: var(--text); }
.build__flag svg { width: .875rem; height: .875rem; fill: none; stroke: currentColor; stroke-width: 1.75; stroke-linecap: round; }
.build__audit-sum { margin-top: .75rem; padding-top: .75rem; border-top: var(--hairline) solid var(--rule); color: var(--text-2); }
.build--seo[data-step="1"] .build__audit { opacity: 1; visibility: visible; animation: build-pop .4s ease 1.3s both; }
.build--seo[data-step="1"] .build__audit li { animation: build-pop .35s ease calc(1.7s + var(--i, 0) * .32s) both; }
.build--seo[data-step="1"] .build__audit-sum { animation: build-pop .4s ease 3.5s both; }
/* 2 · the keyword map on the grey canvas */
.build__kw { left: 50%; top: 50%; translate: -50% -50%; width: min(88%, 38rem); padding: 1.25rem 1.5rem; }
.build__kw ul { display: grid; }
.build__kw li { display: grid; grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr) 3.5rem auto; gap: .75rem; align-items: center; padding: .5rem 0;
  border-top: var(--hairline) solid var(--rule); white-space: nowrap; }
.build__kw-k { overflow: hidden; text-overflow: ellipsis; color: var(--text); }
.build__kw-bar { position: relative; height: .5rem; border-radius: var(--radius-chip); background: var(--bg-2); overflow: hidden; }
.build__kw-bar::before { content: ""; position: absolute; inset: 0; width: var(--w, 50%); border-radius: inherit; background: var(--cta); }
.build__kw-v { text-align: right; color: var(--text); font-variant-numeric: tabular-nums; }
.build__kw-c { padding: .125rem .625rem; border: var(--hairline) solid var(--rule); border-radius: var(--radius-chip); color: var(--text-2); }
.build__kw-foot { margin-top: .75rem; padding-top: .75rem; border-top: var(--hairline) solid var(--rule); color: var(--text-2); }
@keyframes build-bar { from { width: 0; } }
.build--seo[data-step="2"] .build__kw { opacity: 1; visibility: visible; animation: build-pop .4s ease .3s both; }
.build--seo[data-step="2"] .build__kw li { animation: build-pop .35s ease calc(.7s + var(--i, 0) * .35s) both; }
.build--seo[data-step="2"] .build__kw-bar::before { animation: build-bar .8s ease calc(.9s + var(--i, 0) * .35s) both; }
.build--seo[data-step="2"] .build__kw-foot { animation: build-pop .4s ease 2.9s both; }
/* 3 · the headline's new text (the website demo's check panel follows, timed there: 3 s, ticks from 3.4 s) */
.build--seo .build__h { display: grid; }
.build--seo .build__h > span { grid-area: 1 / 1; }
.build--seo .build__h-old { opacity: 0; visibility: hidden; }
.build--seo[data-step="1"] .build__h-old { opacity: 1; visibility: visible; }
.build--seo[data-step="1"] .build__h-new { opacity: 0; visibility: hidden; }
.build--seo[data-step="3"] .build__h-old { visibility: visible; animation: build-out .3s ease .5s both; }
.build--seo[data-step="3"] .build__h-new { animation: build-reveal 1.2s steps(24) .9s both; }
/* 4 · Google: the search field, the results and the climb; the toast after it */
.build__serp { position: absolute; inset: 0; z-index: 2; display: grid; align-content: start; gap: clamp(.75rem, 3cqw, 1.5rem);
  padding: clamp(.75rem, 3cqw, 2rem) clamp(1rem, 8cqw, 8rem); background: var(--bg); opacity: 0; visibility: hidden; transition: opacity .4s ease, visibility .4s; }
.build__q { display: flex; align-items: center; gap: .625rem; max-width: 28rem; padding: .5rem 1rem; border: var(--hairline) solid var(--rule);
  border-radius: var(--radius-control); background: var(--bg); color: var(--text); font-family: var(--font-label); font-size: var(--text-label-lg); line-height: var(--leading-small); }
.build__q-text { display: inline-block; overflow: hidden; white-space: nowrap; }
.build__results { --rh: 5.75rem; position: relative; max-width: 40rem; height: calc(3 * var(--rh)); font-family: var(--font-label); font-size: var(--text-small); line-height: var(--leading-small); }
.build__results li { position: absolute; left: 0; right: 0; top: calc(var(--row, 0) * var(--rh)); display: grid; align-content: start; gap: .25rem; min-height: var(--rh); padding-top: .75rem; }
.build__r-site { display: flex; align-items: center; gap: .5rem; color: var(--text-2); }
.build__r-fav { width: 1rem; height: 1rem; border-radius: 50%; background: var(--rule); }
.build__result--own .build__r-fav { background: var(--field-b-to); }
.build__r-title { color: var(--text); font-size: var(--text-label-lg); font-weight: var(--title-weight); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.build__r-snip { color: var(--text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.build__pos { position: absolute; right: 0; top: .75rem; padding: .25rem .75rem; border-radius: var(--radius-chip); background: var(--text); color: var(--bg); white-space: nowrap; opacity: 0; }
@keyframes build-row { from { top: calc(var(--from, 0) * var(--rh)); } to { top: calc(var(--row, 0) * var(--rh)); } }
:is(.build--seo, .build--ads)[data-step="4"] .build__serp { opacity: 1; visibility: visible; transition-delay: .3s; }
:is(.build--seo, .build--ads)[data-step="4"] .build__q-text { animation: build-typew 1.1s steps(var(--oc, 15)) .6s both; }
:is(.build--seo, .build--ads)[data-step="4"] .build__omni-caret { animation: build-blink .8s step-end 1.7s infinite; }
.build--seo[data-step="4"] .build__results li { animation: build-pop .4s ease calc(2s + var(--i, 0) * .25s) both, build-row 1s ease 3.6s both; }
.build--seo[data-step="4"] .build__pos { opacity: 1; animation: build-pop .4s ease 4.8s both; }
.build--seo[data-step="4"] .build__toast { animation-delay: 5.4s; }
:is(.build--seo, .build--ads) .build__toast { z-index: 3; right: auto; left: clamp(1rem, 8cqw, 8rem); }
@container page (max-width: 52rem) {
  .build__results { --rh: 5.25rem; }
}
@container page (max-width: 30rem) {
  .build__audit { left: 1rem; right: 1rem; padding: .75rem 1rem; }
  .build__audit li { white-space: normal; }
  .build__kw { width: calc(100% - 2rem); padding: 1rem; }
  .build__kw li { grid-template-columns: minmax(0, 1fr) 3rem; }
  .build__kw-bar, .build__kw-c, .build__kw-foot { display: none; }
  .build__serp { padding: 1rem; }
  .build__results { --rh: 5.5rem; }
  .build__r-snip { display: none; }
  .build__pos { position: static; justify-self: start; margin-top: .25rem; }
  :is(.build--seo, .build--ads) .build__toast { left: 1rem; right: 1rem; }
}

/* Ads demo (client, 2026-11-04, "Full Ads demo"; /google-ads-agentur/, .build--ads): the same frame, four scenes in the
   Google Ads account of the sample client instead of on its website:
   1 the audit — the campaign table as the account is (rows one by one), the budget share on irrelevant search terms
     fills as a bar, then the audit panel (the SEO demo's) lists what it found and sums it up;
   2 the set-up — on the grey canvas the campaign tree grows, campaign to ad groups to keywords with their match type;
     beside it the responsive search ad is written in the editor, one headline after the other, the description comes,
     the ad strength fills, and the tracking toast arrives;
   3 the optimisation — the dashboard: the figures, the weekly conversions grow as bars (the accent) while the CPA line
     (ink) falls, the search terms list marks the irrelevant ones negative and strikes them, then the target CPA is set;
   4 the scaling — Google with the sponsored result on top (the SEO demo's results page; no climb, an ad is placed),
     the daily budget slider moves up while the foot says the CPA stays, then the enquiry.
   The bar shows the account's addresses, the lock on every scene. */
.build--ads :is(.build__url-acc, .build__url-edit, .build__url-dash, .build__url-google) { display: none; }
.build--ads[data-step="1"] .build__url-acc, .build--ads[data-step="2"] .build__url-edit, .build--ads[data-step="3"] .build__url-dash,
.build--ads[data-step="4"] .build__url-google { display: inline; }
.build--ads .build__lock { width: .5rem; margin-right: .25rem; opacity: 1; transition-delay: 0s; }
/* The scenes' screens: each fills the page and shows on its step; what is in them is lettered in the label face */
.build__acc, .build__plan, .build__dash { position: absolute; inset: 0; display: grid; align-content: start; gap: clamp(.75rem, 2.5cqw, 1.25rem);
  padding: clamp(.75rem, 3cqw, 1.75rem) clamp(1rem, 4cqw, 3rem); color: var(--text); font-family: var(--font-label); font-size: var(--text-small);
  line-height: var(--leading-small); opacity: 0; visibility: hidden; transition: opacity .4s ease, visibility .4s; }
.build--ads[data-step="1"] .build__acc, .build--ads[data-step="2"] .build__plan, .build--ads[data-step="3"] .build__dash { opacity: 1; visibility: visible; }
.build__acc-head { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; font-size: var(--text-label-lg); font-weight: var(--title-weight); }
.build__acc-period { color: var(--text-2); font-size: var(--text-small); font-weight: normal; white-space: nowrap; }
/* The order the rows, nodes and bars appear in (--i) */
.build--ads :is(.build__tbl li, .build__tree li, .build__terms li, .build__kpis li, .build__wk i):nth-child(2) { --i: 1; }
.build--ads :is(.build__tbl li, .build__tree li, .build__terms li, .build__kpis li, .build__wk i):nth-child(3) { --i: 2; }
.build--ads :is(.build__tbl li, .build__tree li, .build__terms li, .build__kpis li, .build__wk i):nth-child(4) { --i: 3; }
.build--ads :is(.build__tbl li, .build__tree li, .build__terms li, .build__wk i):nth-child(5) { --i: 4; }
.build--ads :is(.build__tbl li, .build__tree li, .build__terms li, .build__wk i):nth-child(6) { --i: 5; }
.build--ads :is(.build__tree li, .build__wk i):nth-child(7) { --i: 6; }
.build--ads :is(.build__tree li, .build__wk i):nth-child(8) { --i: 7; }
.build--ads .build__tree li:nth-child(9) { --i: 8; }
.build--ads .build__results li:nth-child(n) { --i: var(--row); }   /* the sponsored result (row 0) comes first */
/* 1 · the campaign table, the budget share, the audit panel */
.build__tbl li { display: grid; grid-template-columns: minmax(0, 1.6fr) 5rem 5.5rem 4rem 4.5rem; gap: .75rem; padding: .625rem 0;
  border-top: var(--hairline) solid var(--rule); white-space: nowrap; }
.build__tbl li > span:nth-child(n+3), .build__terms li > span:nth-child(n+2) { text-align: right; font-variant-numeric: tabular-nums; }
.build__tbl-head { color: var(--text-2); }
:is(.build__tbl, .build__terms) .build__tbl-head { padding-top: 0; border-top: 0; }
.build--ads[data-step="1"] .build__tbl li:not(.build__tbl-head) { animation: build-pop .35s ease calc(.3s + var(--i, 0) * .3s) both; }
.build__waste { display: grid; gap: .5rem; max-width: 32rem; color: var(--text); }
.build__meter { display: block; position: relative; height: .5rem; border-radius: var(--radius-chip); background: var(--bg-2); overflow: hidden; }
.build__meter i { position: absolute; inset: 0; width: var(--w, 50%); border-radius: inherit; background: var(--text); }
.build--ads[data-step="1"] .build__waste { animation: build-pop .4s ease 1.5s both; }
.build--ads[data-step="1"] .build__waste .build__meter i { animation: build-bar .9s ease 1.8s both; }
.build--ads[data-step="1"] .build__audit { opacity: 1; visibility: visible; animation: build-pop .4s ease 2.8s both; }
.build--ads[data-step="1"] .build__audit li { animation: build-pop .35s ease calc(3.2s + var(--i, 0) * .32s) both; }
.build--ads[data-step="1"] .build__audit-sum { animation: build-pop .4s ease 5s both; }
/* 2 · the campaign tree and the ad editor on the grey canvas */
.build__plan { grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr); align-content: stretch; gap: clamp(.75rem, 2.5cqw, 1.5rem); }
.build__tree, .build__editor { min-height: 0; padding: 1rem 1.25rem; border: var(--hairline) solid var(--rule); border-radius: var(--radius-ui-frame);
  background: var(--bg); box-shadow: var(--shadow-float); overflow: hidden; }
.build__tree ul { display: grid; gap: .375rem; }
.build__node { display: flex; align-items: center; gap: .625rem; padding: .375rem .625rem; border-radius: var(--radius-chip); white-space: nowrap; }
.build__node--0 { background: var(--text); color: var(--bg); }
.build__node--1 { margin-left: 1.25rem; background: var(--bg-2); }
.build__node--2 { margin-left: 2.5rem; }
.build__node-k { overflow: hidden; text-overflow: ellipsis; }
.build__node-m { margin-left: auto; color: var(--text-2); }
.build__node--0 .build__node-m { color: var(--bg); }
.build__node--2 .build__node-m { padding: .125rem .5rem; border: var(--hairline) solid var(--rule); border-radius: var(--radius-chip); }
.build__editor-l { margin: .5rem 0 .25rem; color: var(--text-2); }
.build__heads { display: grid; gap: .375rem; }
.build__field { display: block; min-height: 2rem; padding: .375rem .75rem; border: var(--hairline) solid var(--line); border-radius: var(--radius-chip);
  color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.build__field--desc { white-space: normal; }
.build__typed { display: inline-block; }
.build__strength { display: flex; align-items: center; gap: .75rem; margin-top: .875rem; color: var(--text-2); }
.build__strength .build__meter { flex: 1; }
.build__strength .build__meter i { background: var(--cta); }
.build__strength b { color: var(--text); font-weight: var(--title-weight); white-space: nowrap; opacity: 0; }
.build--ads[data-step="2"] .build__tree { animation: build-pop .4s ease .2s both; }
.build--ads[data-step="2"] .build__node { animation: build-pop .3s ease calc(.6s + var(--i, 0) * .22s) both; }
.build--ads[data-step="2"] .build__editor { animation: build-pop .4s ease .4s both; }
.build--ads[data-step="2"] .build__heads li:nth-child(1) .build__typed { animation: build-reveal 1s steps(28) 1s both; }
.build--ads[data-step="2"] .build__heads li:nth-child(2) .build__typed { animation: build-reveal .8s steps(22) 2.2s both; }
.build--ads[data-step="2"] .build__heads li:nth-child(3) .build__typed { animation: build-reveal .7s steps(18) 3.2s both; }
.build--ads[data-step="2"] .build__field--desc { animation: build-in .4s ease 4s both; }
.build--ads[data-step="2"] .build__strength .build__meter i { animation: build-bar .9s ease 4.4s both; }
.build--ads[data-step="2"] .build__strength b { opacity: 1; animation: build-in .3s ease 5.2s both; }
.build--ads .build__toast--2 { right: auto; left: clamp(1rem, 4cqw, 3rem); }
.build--ads[data-step="2"] .build__toast--2 { opacity: 1; visibility: visible; animation: build-pop .45s ease 5.6s both; }
/* 3 · the dashboard: figures, the chart, the search terms */
.build__dash { grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr); grid-template-rows: auto auto minmax(0, 1fr); align-content: stretch; }
.build__dash > .build__acc-head, .build__kpis { grid-column: 1 / -1; }
.build__kpis { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: .75rem; }
.build__kpis li { display: grid; gap: .125rem; padding: .625rem .875rem; border-radius: var(--radius-chip); background: var(--bg-2); color: var(--text-2); }
.build__kpis b { color: var(--text); font-family: var(--font-display); font-weight: var(--display-weight); font-size: clamp(1.125rem, 2.5cqw, 1.625rem); line-height: 1.1; }
.build__graph, .build__terms { display: grid; grid-template-rows: auto minmax(0, 1fr) auto; min-height: 0; }
.build__graph .build__qa-title { display: flex; justify-content: space-between; gap: 1rem; }
.build__legend { display: inline-flex; align-items: center; gap: .375rem; white-space: nowrap; }
.build__legend-bar { width: .625rem; height: .625rem; border-radius: 2px; background: var(--cta); }
.build__legend-line { width: .875rem; height: 2px; margin-left: .5rem; background: var(--text); }
.build__plot { position: relative; min-height: 6rem; border-bottom: var(--hairline) solid var(--rule); }
.build__wk { position: absolute; inset: 0; display: grid; grid-template-columns: repeat(8, minmax(0, 1fr)); gap: clamp(.375rem, 1.2cqw, .75rem); align-items: end; }
.build__wk i { display: block; height: var(--w, 20%); border-radius: 2px 2px 0 0; background: var(--cta); transform-origin: bottom; }
.build__line { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
/* The line's viewBox is the plot's own size in px (set by components.js from data-points, in percent), so the stroke and
   the dash (pathLength 1, drawn by build-draw) stay uniform */
.build__line polyline { fill: none; stroke: var(--text); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; stroke-dasharray: 1; stroke-dashoffset: 1; }
@keyframes build-rise { from { transform: scaleY(0); } }
@keyframes build-draw { to { stroke-dashoffset: 0; } }
.build__target { justify-self: start; margin-top: .625rem; padding: .25rem .75rem; border-radius: var(--radius-chip); background: var(--text); color: var(--bg);
  white-space: nowrap; opacity: 0; }
.build__terms li { display: grid; grid-template-columns: minmax(0, 1fr) 3rem 3rem auto; gap: .625rem; align-items: center; padding: .5rem 0;
  border-top: var(--hairline) solid var(--rule); white-space: nowrap; }
.build__term-k { overflow: hidden; text-overflow: ellipsis; text-decoration: line-through transparent; }
.build__neg { padding: .125rem .5rem; border: var(--hairline) solid var(--text); border-radius: var(--radius-chip); color: var(--text); opacity: 0; visibility: hidden; }
.build__term--neg[data-n="1"] { --n: 1; }
.build__term--neg[data-n="2"] { --n: 2; }
@keyframes build-strike { to { color: var(--text-2); text-decoration-color: var(--text-2); } }
.build--ads[data-step="3"] .build__kpis li { animation: build-pop .35s ease calc(.3s + var(--i, 0) * .15s) both; }
.build--ads[data-step="3"] :is(.build__graph, .build__terms) { animation: build-in .4s ease .6s both; }
.build--ads[data-step="3"] .build__wk i { animation: build-rise .6s ease calc(1s + var(--i, 0) * .12s) both; }
.build--ads[data-step="3"] .build__line polyline { animation: build-draw 1.8s ease 1.4s both; }
.build--ads[data-step="3"] .build__terms li:not(.build__tbl-head) { animation: build-pop .35s ease calc(.8s + var(--i, 0) * .22s) both; }
.build--ads[data-step="3"] .build__term--neg .build__neg { opacity: 1; visibility: visible; animation: build-pop .3s ease calc(3s + var(--n, 0) * .45s) both; }
.build--ads[data-step="3"] .build__term--neg .build__term-k { animation: build-strike .3s ease calc(3.2s + var(--n, 0) * .45s) forwards; }
.build--ads[data-step="3"] .build__target { opacity: 1; animation: build-pop .4s ease 5s both; }
/* 4 · Google with the sponsored result on top, the budget slider, the enquiry */
.build__ad { color: var(--text); font-weight: var(--title-weight); }
.build__ad::after { content: " ·"; color: var(--text-2); font-weight: normal; }
/* 2 · the ad's preview in the editor (the results page's result, in a field) */
.build__preview { display: grid; gap: .25rem; margin-top: .25rem; padding: .625rem .75rem; border-radius: var(--radius-chip); background: var(--bg-2); opacity: 0; }
.build--ads[data-step="2"] .build__preview { opacity: 1; animation: build-in .4s ease 4.2s both; }
.build--ads[data-step="4"] .build__results li { animation: build-pop .4s ease calc(2s + var(--i, 0) * .25s) both; }
.build__scale { position: absolute; z-index: 2; right: clamp(1rem, 4cqw, 3rem); bottom: clamp(.75rem, 3cqw, 2rem); width: min(60%, 20rem); padding: 1rem 1.25rem;
  border: var(--hairline) solid var(--rule); border-radius: var(--radius-ui-frame); background: var(--bg); color: var(--text); box-shadow: var(--shadow-float);
  font-family: var(--font-label); font-size: var(--text-small); line-height: var(--leading-small); opacity: 0; visibility: hidden; }
.build__slider { display: flex; align-items: center; gap: .875rem; margin-top: .25rem; }
.build__slider-track { position: relative; flex: 1; height: .375rem; border-radius: var(--radius-chip); background: var(--bg-2); }
.build__slider-fill { position: absolute; left: 0; top: 0; bottom: 0; width: 55%; border-radius: inherit; background: var(--cta); }
.build__slider-fill::after { content: ""; position: absolute; right: -.625rem; top: 50%; width: 1.25rem; height: 1.25rem; translate: 0 -50%; border: 2px solid var(--cta);
  border-radius: 50%; background: var(--bg); box-shadow: var(--shadow-float); }
@keyframes build-budget { from { width: 55%; } to { width: 80%; } }
.build__slider-v { display: grid; min-width: 2.5rem; text-align: right; font-size: var(--text-label-lg); font-weight: var(--title-weight); font-variant-numeric: tabular-nums; }
.build__slider-v > span { grid-area: 1 / 1; }
.build__v-new { opacity: 0; }
.build--ads[data-step="4"] .build__scale { opacity: 1; visibility: visible; animation: build-pop .4s ease 3.2s both; }
.build--ads[data-step="4"] .build__slider-fill { animation: build-budget 1.3s ease 3.8s both; }
.build--ads[data-step="4"] .build__v-old { animation: build-out .3s ease 4.4s forwards; }
.build--ads[data-step="4"] .build__v-new { opacity: 1; animation: build-in .3s ease 4.6s both; }
.build--ads[data-step="4"] .build__scale .build__audit-sum { animation: build-pop .4s ease 5.2s both; }
.build--ads[data-step="4"] .build__toast { animation-delay: 6s; }
@container page (max-width: 52rem) {
  .build__tbl li { grid-template-columns: minmax(0, 1.6fr) 4.5rem 5rem 3.5rem 4rem; }
  .build__kpis { gap: .5rem; }
}
@container page (max-width: 30rem) {
  .build__acc, .build__plan, .build__dash { padding: 1rem; gap: .75rem; }
  .build__tbl li { grid-template-columns: minmax(0, 1fr) 4rem 3.5rem; }
  .build__tbl li > span:is(:nth-child(2), :nth-child(4)) { display: none; }
  .build__plan { grid-template-columns: minmax(0, 1fr); }
  .build__tree { display: none; }
  .build__dash { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto minmax(0, 1fr) auto; }
  .build__kpis { display: none; }
  .build__terms li { grid-template-columns: minmax(0, 1fr) 3rem auto; }
  .build__terms li > span:nth-child(2) { display: none; }
  .build__scale { left: 1rem; right: 1rem; bottom: 5.25rem; width: auto; padding: .75rem 1rem; }   /* above the toast */
}

/* App demo (client, 2026-11-03; /app-entwicklung-wien/, .build--app): the same frame and sample client, the artboard
   is a phone (--pw × --ph per canvas) on the grey page. 1 the kick-off; 2 the design tool around the phone (headline
   retyped, picture resized — the selections are measured by components.js as on the website); 3 the code field, then
   the app with its check panel beside the phone; 4 the store search in the field, the store in the bar, a push
   notification in the phone with the first enquiry. The phone's frame is a box-shadow, so the measured offsets stay
   those of the screen. */
.build--app { --pw: 300px; --ph: 600px; }
.build[data-canvas="mid"].build--app { --pw: 270px; --ph: 540px; }
.build[data-canvas="narrow"].build--app { --pw: 210px; --ph: 460px; }
.build--app .build__site { display: grid; place-items: center; padding: 0; background: var(--bg-2); }
.build__phone { position: relative; display: flex; flex-direction: column; width: var(--pw); height: var(--ph); overflow: hidden;
  border-radius: 2.25rem; background: var(--bg); box-shadow: 0 0 0 .5rem var(--text), var(--shadow-float); }
.build__phone::before { content: ""; position: absolute; z-index: 2; top: .625rem; left: 50%; translate: -50% 0; width: 4.5rem; height: 1.25rem;
  border-radius: 1rem; background: var(--text); }
.build__status { display: flex; align-items: center; justify-content: space-between; padding: .875rem 1.5rem 0; color: var(--text);
  font-family: var(--font-label); font-size: var(--text-small); line-height: var(--leading-small); --i: 0; }
.build__glyphs { display: flex; align-items: end; gap: .125rem; }
.build__glyphs i { display: block; width: .2rem; border-radius: 1px; background: var(--text); }
.build__glyphs i:nth-child(1) { height: .35rem; }
.build__glyphs i:nth-child(2) { height: .5rem; }
.build__glyphs i:nth-child(3) { height: .65rem; }
.build__glyphs i:nth-child(4) { width: 1.25rem; height: .625rem; margin-left: .375rem; border-radius: 2px; }
.build__screen { flex: 1; display: flex; flex-direction: column; gap: .875rem; min-height: 0; padding: .875rem 1rem 0; overflow: hidden; }
.build--app .build__nav { gap: .5rem; }
.build__bell { flex: none; width: 1.25rem; height: 1.25rem; margin-left: auto; fill: none; stroke: var(--text); stroke-width: 1.25; stroke-linejoin: round; stroke-linecap: round; --i: 2; }
.build--app .build__hero { display: flex; flex: none; flex-direction: column; align-items: stretch; gap: .75rem; }
.build--app .build__img { order: -1; align-self: stretch; max-height: none; aspect-ratio: 16 / 10; }
.build--app .build__copy { gap: .5rem; }
.build--app .build__h { font-size: var(--text-lead); line-height: var(--leading-lead); }
.build--app .build__cols { grid-template-columns: minmax(0, 1fr); gap: .5rem; }
.build--app .build__col { min-height: 2.5rem; align-items: center; justify-content: space-between; padding: .5rem .75rem; }
.build--app .build__col::after { content: "\203A"; color: var(--text-2); }
.build__tabs { display: flex; justify-content: space-around; padding: .625rem .5rem 1.25rem; border-top: var(--hairline) solid var(--rule); color: var(--text-2);
  font-family: var(--font-label); font-size: var(--text-small); line-height: var(--leading-small); --i: 10; }
.build__tabs span { display: grid; justify-items: center; gap: .25rem; }
.build__tabs span::before { content: ""; width: 1.125rem; height: 1.125rem; border-radius: .3rem; background: var(--rule); }
.build__tabs span:first-child { color: var(--text); }
.build__tabs span:first-child::before { background: var(--text); }
.build--app[data-step="2"] :is(.build__status, .build__bell, .build__tabs) { animation: build-pop .45s ease calc(.4s + var(--i, 0) * .22s) both; }
.build--app .build__frame-label { left: 50%; translate: -50% 0; top: calc((100% - var(--ph) * var(--build-zoom)) / 2 - 1.5rem); white-space: nowrap; }
.build--app .build__qa { right: clamp(1rem, 3cqw, 2.5rem); top: 50%; bottom: auto; translate: 0 -50%; }
.build[data-canvas="mid"].build--app .build__qa ul { grid-template-columns: auto; }
.build[data-canvas="narrow"].build--app .build__qa { top: auto; bottom: 1rem; left: 1rem; right: 1rem; translate: none; }
.build--app .build__lock { display: none; }
.build--app .build__toast { display: flex; z-index: 3; top: 2.625rem; right: .625rem; bottom: auto; left: .625rem; padding: .625rem .875rem .625rem .625rem;
  border-radius: var(--radius-ui-frame); font-size: var(--text-small); }
.build--app .build__tick { width: 1.5rem; height: 1.5rem; }
.build--app .build__tick svg { width: .875rem; height: .875rem; }
/* the picture's size label above the selection — under it, it covered the headline; the narrow phone: a smaller island,
   a shorter screen (no lead, two rows), the banner's text wrapping */
.build--app .build__size { top: auto; bottom: calc(100% + .5rem); }
.build--app .build__toast > span:last-child { min-width: 0; white-space: normal; }
.build[data-canvas="narrow"].build--app .build__phone::before { width: 3rem; height: 1rem; top: .5rem; }
.build[data-canvas="narrow"].build--app .build__status { padding: .625rem 1rem 0; }
.build[data-canvas="narrow"].build--app .build__screen { gap: .625rem; padding: .625rem .75rem 0; }
.build[data-canvas="narrow"].build--app .build__chart-head span { display: none; }   /* the narrow card keeps the total and the bars */
.build[data-canvas="narrow"].build--app :is(.build__lead, .build__col:nth-child(3)) { display: none; }
.build[data-canvas="narrow"].build--app .build__cols { display: grid; }   /* the website's narrow page hides the row of tiles; the phone keeps two rows */
/* the activity card in the picture's place (measured and resized like the picture): the week's bars, the last two
   days still to come */
.build__chart { display: flex; flex-direction: column; justify-content: space-between; padding: .75rem .875rem; }
.build__chart-head, .build__chart-days { display: flex; justify-content: space-between; align-items: baseline; color: var(--text-2);
  font-family: var(--font-label); font-size: var(--text-small); line-height: var(--leading-small); }
.build__chart-head b { color: var(--text); font-weight: var(--title-weight); }
.build__bars { flex: 1; display: flex; align-items: end; gap: .375rem; min-height: 0; margin: .5rem 0 .25rem; }
.build__bars i { flex: 1; height: var(--b); border-radius: .2rem .2rem 0 0; background: var(--text); }
.build__bars i:nth-child(1) { --b: 45%; }
.build__bars i:nth-child(2) { --b: 70%; }
.build__bars i:nth-child(3) { --b: 30%; }
.build__bars i:nth-child(4) { --b: 85%; }
.build__bars i:nth-child(5) { --b: 55%; }
.build__bars i:nth-child(6) { --b: 20%; background: var(--rule); }
.build__bars i:nth-child(7) { --b: 10%; background: var(--rule); }
/* 3 and 4 without the browser (client, 2026-11-03): the bar keeps its place but is invisible, the window and the page
   lose their fill, the code runs over the stage, the phone stands on it */
.build--app .build__window { transition: background-color .6s ease, box-shadow .6s ease; }
.build--app:is([data-step="3"], [data-step="4"]) .build__window { background: transparent; box-shadow: none; }
.build--app:is([data-step="3"], [data-step="4"]) .browser__bar { visibility: hidden; }
.build--app:is([data-step="3"], [data-step="4"]) .build__site { background: transparent; }
/* 3 · the code runs on the phone's screen (client, 2026-11-03): the phone is there from the start, the code field sits
   under the status bar, fades out, then the screen and the tab bar fade in */
.build--app .build__bits { top: 2.5rem; padding: 0; }
.build--app .build__code-field { padding: .5rem .75rem; }
.build--app[data-step="3"] .build__site { animation: none; }
.build--app[data-step="3"] :is(.build__screen, .build__tabs) { animation: build-in .8s ease 2.2s both; }
.build[data-canvas="narrow"].build--app .build__bits { top: 2.25rem; }
/* 4 · the store in the phone: the listing, "Laden", the ring fills, "Öffnen", the store goes, the app is there, then
   the push notification (timed: .4 s, .8 s press, 1.1–3.1 s ring, 3.1 s open, 3.6 s press, 4 s out, 5 s push) */
.build--app[data-step="4"] .build__site { animation: none; }
.build__store { position: absolute; z-index: 2; top: 2.5rem; right: 0; bottom: 0; left: 0; display: flex; flex-direction: column; align-items: center; gap: .375rem;
  padding: 1.25rem 1.25rem 0; background: var(--bg); color: var(--text); text-align: center; opacity: 0; visibility: hidden;
  font-family: var(--font-label); font-size: var(--text-small); line-height: var(--leading-small); }
.build__app-icon { display: grid; place-items: center; width: 4rem; height: 4rem; margin-bottom: .375rem; border-radius: 1rem; background: var(--cta); color: var(--on-cta);
  font-family: var(--font-display); font-size: var(--text-lead); font-weight: var(--display-weight); }
.build__app-name { font-size: var(--text-label-lg); font-weight: var(--title-weight); }
.build__app-sub, .build__app-meta { color: var(--text-2); }
.build__get { position: relative; display: grid; place-items: center; min-width: 5.5rem; min-height: 2rem; margin-top: .625rem; padding: .375rem 1rem;
  border-radius: var(--radius-control); background: var(--cta); color: var(--on-cta); }
.build__get > * { grid-area: 1 / 1; opacity: 0; }
.build__get-ring { width: 1.25rem; height: 1.25rem; fill: none; stroke: var(--line); stroke-width: 2.5; transform: rotate(-90deg); }
.build__get-arc { stroke: var(--on-cta); stroke-dasharray: 56.6; stroke-dashoffset: 56.6; stroke-linecap: round; }
.build__shots { display: flex; gap: .5rem; flex: 1; width: 100%; min-height: 0; margin-top: 1rem; }
.build__shots i { flex: 1; border-radius: .75rem .75rem 0 0; background: var(--bg-2); }
@keyframes build-ring { to { stroke-dashoffset: 0; } }
.build--app[data-step="4"] .build__store { opacity: 1; visibility: visible; animation: build-in .4s ease both, build-out .5s ease 4s forwards; }   /* opacity 1: build-in ends at the element's own value */
.build--app[data-step="4"] .build__get-load { animation: build-on 1.1s linear; }
.build--app[data-step="4"] .build__get { animation: build-press .3s ease .8s, build-press .3s ease 3.6s; }
.build--app[data-step="4"] .build__get-ring { animation: build-on 2s linear 1.1s; }
.build--app[data-step="4"] .build__get-arc { animation: build-ring 1.9s ease-in-out 1.15s both; }
.build--app[data-step="4"] .build__get-open { animation: build-on 1s linear 3.1s; }
.build--app[data-step="4"] .build__toast { animation: build-pop .45s ease 5s both; }
.build[data-canvas="narrow"].build--app .build__store { top: 2.25rem; padding-top: .75rem; }
.build[data-canvas="narrow"].build--app .build__app-icon { width: 3rem; height: 3rem; }
.build[data-canvas="narrow"].build--app .build__toast { top: 2.25rem; padding: .5rem .625rem .5rem .5rem; gap: .5rem; }

/* A screenshot in the demo's frame (.build--shot, the CRM page): the window on the stage as in the demos, the picture
   cut at the window's foot, the window no taller than the demo's view. */
.build--shot .build__window { max-height: clamp(18rem, 46cqw, 40rem); }
.build__shot { display: block; width: 100%; height: auto; }
/* the step line under a screenshot (client, 2026-11-04): the demo's steps as plain labels, every line drawn */
.build__steps--static .build__step { display: block; min-height: var(--control-h); padding: .75rem 0 .25rem; border-top: 2px solid var(--text); color: var(--text);
  font-size: var(--text-small); line-height: var(--leading-small); }

/* UX demo (client, 2026-11-03; /ux-agentur-wien/, .build--ux): the website demo's design tool over three scenes.
   1 the research kick-off; 2 the page as wireframes — every part a grey shape, the picture a crossed box, no edits yet;
   3 the parts become real: the headline is typed, the picture arrives and is resized (the website's step-2 edits, moved
   here); 4 the client's approval as a comment pinned to the picture, the "freigegeben" toast — the bar still reads
   "Entwurf", the panels stay: it is still the design tool. No code scene, no check panel, no address field. */
.build--ux .build__url-live { display: none; }
.build--ux:is([data-step="3"], [data-step="4"]) .build__url-dev { display: none; }
.build--ux:is([data-step="3"], [data-step="4"]) .build__url-design { display: inline; }
.build--ux:is([data-step="2"], [data-step="3"], [data-step="4"]) .build__page { background: var(--bg-2); }
.build--ux:is([data-step="3"], [data-step="4"]) .build__site { transform: scale(var(--build-zoom)); animation: none; }
.build--ux:is([data-step="3"], [data-step="4"]) :is(.build__frame-label, .build__panel) { opacity: 1; visibility: visible; }
.build--ux .build__bits { display: none; }
/* 2 · wireframes: the texts as bars, the buttons grey, the picture a crossed box; the parts still pop in one by one */
.build--ux :is(.build__name, .build__menu span, .build__lead, .build__col, .build__btn, .build__type, .build__logo) { transition: color .5s ease, background-color .5s ease; }
.build--ux[data-step="2"] :is(.build__name, .build__menu span, .build__lead, .build__col) { color: transparent; background: var(--rule); border-radius: .25rem; }
.build--ux[data-step="2"] .build__col::after { content: none; }
.build--ux[data-step="2"] :is(.build__btn, .build__logo) { background: var(--rule); color: transparent; }
.build--ux[data-step="2"] .build__type { color: transparent; background: var(--line); border-radius: .25rem; animation: build-pop .45s ease calc(.4s + 3 * .22s) both; }
.build--ux .build__img { background:
    linear-gradient(to top right, transparent calc(50% - 1px), var(--rule) calc(50% - 1px), var(--rule) calc(50% + 1px), transparent calc(50% + 1px)),
    linear-gradient(to top left, transparent calc(50% - 1px), var(--rule) calc(50% - 1px), var(--rule) calc(50% + 1px), transparent calc(50% + 1px)),
    var(--bg-2); }
.build--ux .build__img img { transition: opacity .6s ease; }
.build--ux[data-step="2"] .build__img { animation: build-pop .45s ease calc(.4s + 6 * .22s) both; }
.build--ux[data-step="2"] .build__img img { opacity: 0; }
.build--ux[data-step="2"] :is(.build__sel, .build__cursor) { visibility: hidden; animation: none; }
.build--ux[data-step="2"] .build__sel--text::after { animation: none; }
.build--ux[data-step="2"] :is(.build__layer-h, .build__layer-i) { animation: none; }
/* 3 · the real parts: the headline typed into its frame, the picture faded in and resized (the website's edits) */
.build--ux[data-step="3"] .build__type { animation: build-reveal 1.2s steps(20) 1.85s forwards; transition: color .2s ease 1.85s, background-color .4s ease 1.7s; }
  /* forwards, not both: the clip's start state would hide the bar during the delay; the bar fades as the typing starts */
.build--ux[data-step="3"] .build__img img { animation: build-in .6s ease 3.2s both; }
.build--ux[data-step="3"] .build__img { transform-origin: 0 0; animation: build-grow 1.15s ease 3.6s both; }
.build--ux[data-step="3"] :is(.build__sel, .build__cursor) { visibility: visible; transition: none; }
.build--ux[data-step="3"] .build__layer-h { animation: build-mark 1.3s linear 1.75s; }
.build--ux[data-step="3"] .build__layer-i { animation: build-mark .01s linear 3.1s forwards; }
.build--ux[data-step="3"] .build__sel--text { animation: build-on 1.35s linear 1.75s; }
.build--ux[data-step="3"] .build__sel--text::after { animation: build-caret 1.2s steps(20) 1.85s both, build-blink .8s step-end 3.05s infinite; }
.build--ux[data-step="3"] .build__sel--img { animation: build-on .01s linear 3.1s forwards, build-grow-box 1.15s ease 3.6s both; }
.build--ux[data-step="3"] .build__cursor { animation: build-cursor 4.6s ease .6s both; }
/* 4 · the approval: a comment pinned to the picture (its place from the measured picture), then the toast */
.build__comment { position: absolute; z-index: 3; left: calc(var(--ix) + var(--iw) * .5); top: calc(var(--iy) + var(--ih) * .12); display: flex; align-items: flex-start; gap: .5rem;
  max-width: 15rem; opacity: 0; visibility: hidden; font-family: var(--font-label); font-size: var(--text-small); line-height: var(--leading-small); }
.build__comment-who { display: grid; place-items: center; flex: none; width: 2rem; height: 2rem; border-radius: 50% 50% 50% .25rem; background: var(--cta); color: var(--on-cta); }
.build__comment-text { padding: .625rem .875rem; border: var(--hairline) solid var(--rule); border-radius: var(--radius-ui-frame); background: var(--bg); color: var(--text); box-shadow: var(--shadow-float); }
.build__comment-text b { display: block; margin-bottom: .125rem; font-weight: var(--title-weight); }
.build--ux[data-step="4"] .build__comment { opacity: 1; visibility: visible; animation: build-pop .45s ease .8s both; }
.build--ux .build__toast { z-index: 3; right: calc((100% - 100% * var(--build-zoom)) / 2 + 1rem); }   /* inside the canvas, left of the panel */
.build--ux[data-step="4"] .build__toast { animation: build-pop .45s ease 2.6s both; }
@container page (max-width: 30rem) {
  .build__comment { left: 1rem; right: 1rem; top: auto; bottom: 6.25rem; max-width: none; }
  .build--ux .build__toast { right: 1rem; }
}

/* The steps: buttons on a segmented line */
/* The link to the costs page: on a mouse it is a pill that follows the pointer over the demo (client, 2026-11-02); on
   touch and narrow screens it is a plain link under the steps. The static link stays in the document for keyboard and
   screen readers and shows itself on focus; the follow pill is pointer-only (aria-hidden, no tab stop). */
.build__follow { position: absolute; left: 0; top: 0; z-index: 3; display: none; pointer-events: none; opacity: 0;
  transform: translate(calc(var(--fx, 0px) - 50%), calc(var(--fy, 0px) - 50%)); box-shadow: var(--shadow-float);
  transition: opacity var(--t-colour); }   /* the position is never eased by CSS: the script moves it each frame */
.build__more { display: none; flex: 0 0 100%; margin: 0; }   /* on touch and narrow screens the link is not shown (client, 2026-11-02) */
@keyframes build-follow-in { from { opacity: 0; scale: .9; } }
@media (hover: hover) and (pointer: fine) and (min-width: 56rem) {
  .build__follow { display: inline-flex; }
  .build__more { display: block; }   /* desktop: in the document for keyboard and screen readers, visible on focus only */
  .build__follow.is-on { opacity: 1; pointer-events: auto; animation: build-follow-in .18s ease; }
  .build__more:not(:focus-within) { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
}
@media (prefers-reduced-motion: reduce) {
  .build__follow { transition: none; }
}
.build__foot { display: flex; flex-wrap: wrap; align-items: start; gap: var(--gutter); margin-top: var(--gap-text); }
.build__steps { flex: 1; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--gutter); }
.build__steps button { display: block; width: 100%; min-height: var(--control-h); padding: .75rem 0 .25rem; border: 0; border-top: 2px solid var(--rule);
  background: none; color: var(--text-2); font: inherit; font-size: var(--text-small); line-height: var(--leading-small); text-align: left; cursor: pointer;
  transition: border-color .4s ease, color .4s ease; }
.build__steps button:hover { border-top-color: var(--line); color: var(--text); }
.build__steps button[aria-current], .build__steps li:has(~ li > [aria-current]) > button { border-top-color: var(--text); }
.build__steps button[aria-current] { color: var(--text); font-weight: var(--title-weight); }
.build__num { font-family: var(--font-label); }
/* Under each step, when the page has them (PROCESS, inHero): its one line, the current step's in the text colour. On
   phones only the current step's shows (the others stay for screen readers). */
.build__step-text { margin-top: .25rem; color: var(--text-2); font-size: var(--text-small); line-height: var(--leading-small);
  transition: color .4s ease; }
.build__steps li:has(> [aria-current]) .build__step-text { color: var(--text); }
/* The mid page (800 px) has no room for the design tool's side panels and frame label: they go and the frame zooms
   out less. The narrow page (340 px) stacks. */
@container page (max-width: 52rem) {
  .build__panel, .build__frame-label { display: none; }
  .build__page > * { --build-zoom: .86; }
}
@container page (max-width: 30rem) {
  .build__hero { grid-template-columns: 1fr; align-items: start; align-content: start; }
  .build__img { aspect-ratio: 16 / 10; }
  .build__menu, .build__cols, .build__panel, .build__frame-label { display: none; }
  .build__page > * { --build-zoom: .88; }
  .build__team { gap: .5rem; }
  .build__who, .build__notes li, .build__toast { font-size: var(--text-small); }
  .build__who { min-height: 2.5rem; padding: .25rem .75rem; }
  .build__mark { width: 1.5rem; }
  .build__link { width: 2rem; }
  .build__notes li { padding: .5rem .75rem; }
  .build__qa { left: 1rem; right: 1rem; padding: .75rem 1rem; }
  .build__qa ul { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .5rem .75rem; }
  .build__qa li { white-space: normal; }
  .build__toast { white-space: nowrap; }
  .build__tick { width: 1.5rem; height: 1.5rem; }
}
@media (max-width: 47.99rem) {
  .build__steps { display: flex; gap: .5rem; }
  .build__steps li { flex: 1; }
  .build__steps li:has(> [aria-current]) { flex: 4; }
  .build__steps button:not([aria-current]) .build__label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .build__steps li:not(:has(> [aria-current])) .build__step-text { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
}
@media (max-width: 47.99rem) {   /* phones, the static steps under a screenshot: one column, every text shown (after the demo's rules, which hide all but the current step's) */
  .build--shot .build__steps--static { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--gap-text); }
  .build--shot .build__steps--static li .build__step-text { position: static; width: auto; height: auto; overflow: visible; clip: auto; white-space: normal; }
}
@media (prefers-reduced-motion: reduce) { .build * { animation: none !important; } .build__bits { display: none; } }

/* Service hero (client's choice, 2026-10-27, variant D): text and the page's points on the left; on the right a team
   photo with the booking card at its foot — the one main action, with what the call costs (nothing, 30 minutes) and the
   rating beside it. The page's four figures follow in a row, then the client logos. Below 1024 px the photo comes
   right after the text (3 : 2) with the card overlapping its foot, before the points, so the booking stays near the top. */
.hero-book { display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); grid-template-rows: auto 1fr;
  grid-template-areas: "text media" "points media"; column-gap: var(--gutter); align-items: start; }   /* the points follow the text */
.hero-book__text { grid-area: text; }
.hero-book__points { grid-area: points; }
.hero-book__more { margin-top: 1rem; }
.hero-book__media { grid-area: media; display: grid; }
.hero-book__photo { grid-area: 1 / 1; width: 100%; height: auto; aspect-ratio: 4 / 5; object-fit: cover; border-radius: var(--radius-container); }
.hero-book__media .bookcard { grid-area: 1 / 1; align-self: end; margin: var(--pad-tile); position: relative; }
.page-hero .figures { margin-top: var(--gap-block); }
@media (max-width: 63.99rem) {
  .hero-book { grid-template-columns: 1fr; grid-template-rows: none; grid-template-areas: "text" "media" "points"; row-gap: var(--gap-block); }
  .hero-book__photo { aspect-ratio: 3 / 2; }
  .hero-book__media .bookcard { grid-area: 2 / 1; margin: -4rem var(--pad-tile) 0; }
}
@media (max-width: 47.99rem) { .hero-book__media .bookcard { margin-inline: var(--gutter); } }
/* Booking card: a light floating panel (like the booking widget): what the call is, one button, the rating. */
.bookcard { display: grid; gap: 1rem; padding: var(--pad-card); border-radius: var(--radius-ui-frame); box-shadow: var(--shadow-float); }
.bookcard .muted { margin-top: .25rem; font-size: var(--text-small); line-height: var(--leading-small); }
.bookcard .btn { width: 100%; white-space: normal; text-align: center; }
.bookcard .link-arrow { justify-self: center; }
.bookcard__rating { font-size: var(--text-small); line-height: var(--leading-small); color: var(--text-2); text-align: center; }

/* Wide hero (Über uns, variant C): the H1 on the left, text and actions on the right, both from the top (like .intro:
   one --gap-text under the crumbs, as on every page — aligned to the foot, the H1 started 84 px down); under them a
   wide team photo (no figures on it: client, 2026-10-27). */
.hero-wide { display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); gap: var(--gap-lead) var(--gutter); align-items: start; }   /* stacked: H1 → text like every hero */
.hero-wide .lead { margin-top: 0; }
.hero-wide__media { display: grid; margin-top: var(--gap-block); }
.hero-wide__photo { width: 100%; height: auto; aspect-ratio: 21 / 9; object-fit: cover; border-radius: var(--radius-container); }
@media (max-width: 63.99rem) { .hero-wide { grid-template-columns: 1fr; } .hero-wide__photo { aspect-ratio: 16 / 9; } }
@media (max-width: 47.99rem) { .hero-wide__photo { aspect-ratio: 3 / 2; } }

/* Trust line under the actions, and the client logos under a hero (real clients, each named in its alt text). */
.trustline { display: flex; flex-wrap: wrap; gap: .25rem 1rem; margin-top: 1rem; font-size: var(--text-small); line-height: var(--leading-small); color: var(--text-2); }
/* Rating: five stars in the text colour (graphics, 3:1 on every surface the text sits on) before "4,9 / 5 Google-Bewertungen". */
.rating { display: inline-flex; align-items: center; gap: .5rem; }
.stars { display: inline-flex; gap: .125rem; color: var(--text); }
.stars svg { width: 1em; height: 1em; fill: currentColor; }
.logos { display: flex; flex-wrap: wrap; align-items: center; gap: 1rem var(--gap-block); margin-top: var(--gap-block); padding-top: var(--gap-text);
  border-top: var(--hairline) solid var(--rule); }
.logos__label { font-size: var(--text-small); line-height: var(--leading-small); color: var(--text-2); }
.logos ul { display: flex; flex-wrap: wrap; align-items: center; gap: 1.25rem var(--gap-block); }
.logos img { width: auto; height: 1.5rem; }
@media (max-width: 47.99rem) { .logos ul { gap: 1rem 1.5rem; } }

/* Logo run (the short service hero, client 2026-11-02): under the actions, a window about three logos wide; the logos
   run to the left on their own (the list twice, each moving its own width, so the run loops), faded in at the right
   end and out at the left (a mask, opacity from currentColor). Holds under the pointer; with reduced motion it stands. */
.logo-run { display: grid; justify-items: center; width: 100%; margin-top: 1.25rem; }   /* close under the trust line (client) */
.logo-run__window { display: flex; width: min(100%, 26rem); overflow: hidden;
  -webkit-mask: linear-gradient(to right, transparent, currentColor 22%, currentColor 78%, transparent);
  mask: linear-gradient(to right, transparent, currentColor 22%, currentColor 78%, transparent); }
.logo-run__window ul { display: flex; flex: none; align-items: center; gap: 2.5rem; padding-right: 2.5rem; animation: logo-run 28s linear infinite; }
.logo-run__window img { width: auto; height: 1.5rem; }
.logo-run__window:hover ul { animation-play-state: paused; }
@keyframes logo-run { to { transform: translateX(-100%); } }
@media (prefers-reduced-motion: reduce) { .logo-run__window ul { animation: none; } }

/* Figures: a row of numbers with what they mean, on hairlines (no cards) — the live pages' "Realität" facts. */
.figures { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--gap-block) var(--gutter); }
.figures li { padding-top: 1.25rem; border-top: var(--hairline) solid var(--rule); }
.figures b { display: block; font-family: var(--font-display); font-weight: var(--display-weight); font-size: var(--text-h2);
  line-height: var(--leading-h2); letter-spacing: var(--track-head); }
.figures span { display: block; margin-top: .5rem; max-width: 18rem; color: var(--text-2); }
@media (max-width: 63.99rem) { .figures { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* Features: a grid of entries, each under a hairline, no container (rule: cards only where grouping needs them) —
   an optional small kicker, the title, its text, an optional list of points and a note at the foot. Three in a row;
   --2 for entries with long text, --4 for short ones. */
.features { --cols: 3; display: grid; grid-template-columns: repeat(var(--cols), minmax(0, 1fr)); gap: var(--gap-block) var(--gutter); }
.features--2 { --cols: 2; }
.features--4 { --cols: 4; }
.feature { display: flex; flex-direction: column; padding-top: 1.25rem; border-top: var(--hairline) solid var(--rule); }
.feature__kicker { margin-bottom: .5rem; font-family: var(--font-label); font-size: var(--text-small); line-height: var(--leading-small); color: var(--text-2); }
.feature__title { font-size: var(--text-title); line-height: var(--leading-title); font-weight: var(--title-weight); }
.feature__text { margin-top: .5rem; color: var(--text-2); }
.feature__text + .feature__text { margin-top: .75rem; }
.feature__text a { color: var(--text); text-underline-offset: .2em; }
.feature__list { margin-top: 1rem; font-size: var(--text-small); line-height: var(--leading-small); }
.feature__list li { padding-block: .5rem; border-top: var(--hairline) solid var(--rule); }
.feature__note { margin-top: auto; padding-top: 1rem; font-size: var(--text-small); line-height: var(--leading-small); color: var(--text-2); }
.feature__figure { margin-top: auto; padding-top: 1.25rem; font-family: var(--font-display); font-weight: var(--display-weight);
  font-size: var(--text-quote); line-height: var(--leading-quote); letter-spacing: var(--track-head); }
.feature__links { margin-top: .75rem; }
.feature__figure--top { margin-top: .5rem; padding-top: 0; }   /* a plan's price, right under its name */
.kicker { font-family: var(--font-label); font-size: var(--text-small); line-height: var(--leading-small); color: var(--text-2); }
@media (max-width: 63.99rem) { .features, .features--4 { --cols: 2; } }
@media (max-width: 47.99rem) { .features, .features--2, .features--4 { --cols: 1; } }

/* Rows: a plain list on hairlines; as links, each row is one 44 px target with an arrow on the right. */
.rows { border-top: var(--hairline) solid var(--rule); }
.rows li { border-bottom: var(--hairline) solid var(--rule); }
.rows li > span, .rows li > p { display: block; padding-block: 1rem; }
.rows a { display: flex; align-items: center; justify-content: space-between; gap: 1rem; min-height: var(--control-h); padding-block: 1rem;
  color: inherit; text-decoration: none; }
.rows a::after { content: "→"; flex: none; transition: translate var(--t-colour); }
.rows a:hover { text-decoration: underline; text-underline-offset: .2em; }
.rows a:hover::after { translate: .25rem 0; }
.rows small { display: block; color: var(--text-2); font-size: var(--text-small); line-height: var(--leading-small); }

/* Chips: a short run of keywords in the label face, separated by dots (not pills, not uppercase). */
.chips { display: flex; flex-wrap: wrap; gap: .25rem .5rem; font-family: var(--font-label); font-size: var(--text-small);
  line-height: var(--leading-small); color: var(--text-2); }
.chips li + li::before { content: "·"; margin-right: .5rem; }

/* Tools: the names of the tools and platforms a service works with, four to a row on hairlines. */
.tools { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); column-gap: var(--gutter); border-top: var(--hairline) solid var(--rule); }
.tools li { padding-block: .75rem; border-bottom: var(--hairline) solid var(--rule); }
@media (max-width: 47.99rem) { .tools { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* Flow: the blocks of a section one after another, a block's distance apart. */
.flow > * + * { margin-top: var(--gap-block); }
.flow > .intro { margin-bottom: 0; }
.flow > .flow__block + .flow__block { margin-top: var(--section-sm); }
.flow p a, .intro p a { text-underline-offset: .2em; }

/* Tabs that fit their panel: the chosen panel alone sets the height (for panels of very different length). */
[data-tabs].is-tabbed.tabs--fit :has(> [data-tab-panel]) { display: block; }
[data-tabs].is-tabbed.tabs--fit [data-tab-panel]:not(.is-shown) { display: none; }
[data-tabs] .tabs + * { margin-top: var(--gap-block); }
@media (max-width: 47.99rem) {   /* phones: the labels stay in one row and scroll sideways instead of wrapping */
  .tabs { flex-wrap: nowrap; overflow-x: auto; margin-inline: calc(-1 * var(--margin)); padding-inline: var(--margin); scrollbar-width: none; }
  .tabs::-webkit-scrollbar { display: none; }
  .tabs__tab { flex: none; padding-inline: 1rem; }
}
[data-tabs]:not(.is-tabbed) [data-tab-panel] + [data-tab-panel] { margin-top: var(--section-sm); }   /* without JavaScript: all panels, one after another */
/* A use case as a tab panel (the app page, 2026-11-03): the sentence on the left, its points as the ruled list on the
   right; one column on phones. */
.usecase { display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); gap: var(--gap-text) var(--gutter); align-items: start; }
.usecase .h3 + .lead { margin-top: var(--gap-text); }
/* With the tabs active the tab names the panel (aria-labelledby), so the panel's own heading is for screen readers
   only (client, 2026-11-04: not the title twice); without JavaScript every panel shows and keeps its heading. */
[data-tabs].is-tabbed .usecase .h3 { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
[data-tabs].is-tabbed .usecase .h3 + .lead { margin-top: 0; }
.usecase .feature__list { margin-top: 0; }
@media (max-width: 63.99rem) { .usecase { grid-template-columns: minmax(0, 1fr); } }
.intro > .stack { max-width: 33.25rem; }
.intro > .stack p { font-size: var(--text-lead); line-height: var(--leading-lead); }

/* Steps in four or five columns (a service's own process), back to two and one like the six. */
.steps--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.steps--5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
@media (max-width: 79.99rem) { .steps--5 { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 63.99rem) { .steps--4, .steps--5 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 47.99rem) { .steps--4, .steps--5 { grid-template-columns: 1fr; } }

/* A quote that closes a section (one line from the page's own copy, in the heading face). */
.pull { max-width: 40rem; font-family: var(--font-display); font-weight: var(--display-weight); font-size: var(--text-quote);
  line-height: var(--leading-quote); letter-spacing: var(--track-head); }
.pull figcaption { margin-top: .75rem; font-family: var(--font-text); font-size: var(--text-size); color: var(--text-2); letter-spacing: 0; }

/* Article (blog posts, legal pages): the text column at a reading measure; headings in the heading face with room
   above; lists, tables, callouts and the checklist as the live posts have them. Heading IDs (#sec-…) keep a gap under
   the sticky header when jumped to. */
.prose { max-width: 42rem; }
.prose > * + * { margin-top: 1.25rem; }
.prose h2 { margin-top: var(--gap-block); font-family: var(--font-display); font-weight: var(--display-weight); font-size: var(--text-quote);
  line-height: var(--leading-quote); letter-spacing: var(--track-head); text-wrap: balance; }
.prose h3 { margin-top: var(--gap-text); font-size: var(--text-title); line-height: var(--leading-title); font-weight: var(--title-weight); }
.prose h4 { font-weight: var(--title-weight); }
.prose :is(h2, h3) { scroll-margin-top: calc(var(--header-h, 4rem) + 1.5rem); }
.prose > :first-child { margin-top: 0; }
.prose ul, .prose ol { padding-left: 1.25rem; }
.prose ul { list-style: disc; }
.prose ol { list-style: decimal; }
.prose li + li { margin-top: .5rem; }
.prose li > * + * { margin-top: .5rem; }
.prose li h3 { margin-top: .25rem; }
.prose a { text-underline-offset: .2em; }
.prose strong { font-weight: var(--title-weight); }
.prose blockquote { padding-left: 1.25rem; border-left: calc(2 * var(--hairline)) solid var(--text); font-family: var(--font-display);
  font-size: var(--text-quote); line-height: var(--leading-quote); }
.prose figure img { width: 100%; height: auto; }
.table { overflow-x: auto; }
.table table { width: 100%; min-width: 32rem; border-collapse: collapse; font-size: var(--text-small); line-height: var(--leading-small); }
.table th, .table td { padding: .75rem 1rem .75rem 0; text-align: left; vertical-align: top; border-bottom: var(--hairline) solid var(--rule); }
.table th { font-weight: var(--title-weight); border-bottom-color: var(--line); }
/* A callout in an article (the live posts' "Praxis-Tipp", "Wichtig zu wissen"). Not .note: that is the step tiles' foot line. */
.callout { padding: var(--pad-tile); background: var(--bg-2); }
.callout > * + * { margin-top: .5rem; }
.callout__title { font-weight: var(--title-weight); }
.prose .checklist { padding-left: 0; list-style: none; border-top: var(--hairline) solid var(--rule); }
.prose .checklist li { position: relative; margin: 0; padding: .75rem 0 .75rem calc(1.125rem + .75rem);   /* box + gap */ border-bottom: var(--hairline) solid var(--rule); }
.prose .checklist li::before { content: ""; position: absolute; left: 0; top: 1rem; width: 1.125rem; height: 1.125rem; border: var(--hairline) solid var(--line); }
.prose .checklist strong { display: block; }
.prose .faq__list { margin-top: var(--gap-text); }
.prose .faq__item p { padding-right: 1.5rem; }

/* Article page: head (meta line, H1 at the H2 size — titles here are long —, author) beside the cover, then the contents
   on the left (sticky) beside the text, with the call to book under it. Below 1024 px the contents go above the text. */
.article__head { max-width: 52rem; }
.article__meta { font-family: var(--font-label); font-size: var(--text-small); line-height: var(--leading-small); color: var(--text-2); }
.article__title { margin-top: 1rem; font-size: var(--text-h2); line-height: var(--leading-h2); }
.article__title .h1__sub { margin-top: 0; font-size: inherit; line-height: inherit; }
.article__author { display: flex; align-items: center; gap: .75rem; margin-top: var(--gap-text); }
.article__author img { width: 3rem; height: 3rem; object-fit: cover; border-radius: var(--radius-container); }
.article__author small { display: block; color: var(--text-2); font-size: var(--text-small); line-height: var(--leading-small); }
/* The head beside the post's cover (a designed 3:2 picture with the topic on it — never cropped, or its text would be). */
.article__top { display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); gap: var(--gap-block) var(--gutter); align-items: end; }
.article__cover { width: 100%; height: auto; aspect-ratio: 3 / 2; object-fit: cover; border-radius: var(--radius-container); }
.article__grid { display: grid; grid-template-columns: minmax(0, 4fr) minmax(0, 8fr); gap: var(--gap-block) var(--gutter); margin-top: var(--gap-block); align-items: start; }
.article__aside { position: sticky; top: calc(var(--header-h, 4rem) + var(--gutter)); display: grid; gap: var(--gap-block); max-width: 22rem; }
.toc__title { margin-bottom: .5rem; font-weight: var(--title-weight); }
.toc ol { border-top: var(--hairline) solid var(--rule); }
.toc a { display: flex; align-items: center; min-height: var(--control-h); padding-block: .5rem; border-bottom: var(--hairline) solid var(--rule);
  color: var(--text-2); text-decoration: none; transition: color var(--t-colour); }
.toc a:hover { color: var(--text); text-decoration: underline; text-underline-offset: .2em; }
.cta-card { padding: var(--pad-tile); background: var(--bg-2); }
.cta-card .title + p { margin-top: .5rem; color: var(--text-2); }
.cta-card .btns { margin-top: 1.25rem; }
@media (max-width: 63.99rem) {
  .article__top, .article__grid { grid-template-columns: 1fr; }
  .article__aside { position: static; max-width: none; }
  .article__aside .cta-card { display: none; }
}

/* Reference page: the client's name, what was done and the facts beside it (a definition list on hairlines), then
   the project's cover; the branding pictures as a gallery. */
.ref-hero__grid { display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); gap: var(--gap-block) var(--gutter); align-items: end; }
.ref-hero .lead { margin-top: var(--gap-lead); max-width: 38rem; }
.ref-hero .btns { margin-top: var(--gap-actions); }
.facts { border-top: var(--hairline) solid var(--rule); }
.facts > div { display: grid; grid-template-columns: 8rem minmax(0, 1fr); gap: 1rem; padding-block: .75rem; border-bottom: var(--hairline) solid var(--rule); }
.facts dt { color: var(--text-2); }
.facts dd { margin: 0; }
.facts dd li + li { margin-top: .25rem; }
.facts dd > a { display: inline-flex; align-items: center; min-height: var(--control-h); margin-block: calc((var(--control-h) - 1lh) / -2); text-underline-offset: .2em; }   /* a 44 px target in a text row */
.ref-cover { margin-top: var(--gap-block); }
.ref-cover img { width: 100%; height: auto; border-radius: var(--radius-container); }
.gallery { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--gutter); }
.gallery img { width: 100%; height: auto; aspect-ratio: 4 / 3; object-fit: cover; border-radius: var(--radius-container); background: var(--bg-2); }
@media (max-width: 63.99rem) { .ref-hero__grid { grid-template-columns: 1fr; } }
@media (max-width: 47.99rem) { .gallery { grid-template-columns: repeat(2, minmax(0, 1fr)); } .facts > div { grid-template-columns: 6.5rem minmax(0, 1fr); } }

/* Post card with a line of text (reference and project cards use the blog card). */
.post__text { margin-top: .5rem; color: var(--text-2); }

/* References overview (/referenzen/, 2026-11-04). The filter is one quiet line of text buttons under a hairline: the
   label in --text-2, the chosen one in --text and underlined (state not by colour alone), the count after each.
   Then the featured projects in rows of a wide (two thirds) and a narrow (one third) tile — the client's name small,
   the project's sentence large, the picture above both on a --bg-2 field (browser shot and phone on wide tiles,
   phones on narrow ones, cropped at the bottom). Every other client is a ruled row: name, sentence, and an empty
   right column where, on devices that hover, the reference's picture appears while the row is hovered or focused.
   The project's type (.ref-type) sits on the picture's bottom-left corner on --bg and shows only on hover / keyboard
   focus (client: the type as a line under the text looked loose). It is always in the HTML (opacity, not display),
   so screen readers read it; on touch screens and phones it is shown as small text instead. */
.filterline { display: flex; flex-wrap: wrap; column-gap: 1.5rem; margin-bottom: var(--gap-block); border-top: var(--hairline) solid var(--rule); }
.filterline button { min-width: 2.75rem; min-height: 2.75rem; padding: 0; border: 0; background: none; cursor: pointer;
  font-family: var(--font-label); font-weight: var(--label-weight); font-size: var(--text-small); line-height: var(--leading-small);
  color: var(--text-2); text-underline-offset: .35em; text-decoration-thickness: calc(2 * var(--hairline)); transition: color var(--t-colour); }
.filterline button:hover, .filterline button[aria-pressed="true"] { color: var(--text); }
.filterline button[aria-pressed="true"] { text-decoration-line: underline; }
.filterline button span { color: var(--text-2); }
.filterline button:focus-visible { outline: var(--focus-width) solid var(--focus); outline-offset: var(--focus-offset); }

.ref-type { font-family: var(--font-label); font-weight: var(--label-weight); font-size: var(--text-small); line-height: var(--leading-small); }

.works { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--gap-row) var(--gutter); }
.work { position: relative; display: flex; flex-direction: column; }
.work--wide { grid-column: span 2; }
.work__media { order: -1; position: relative; overflow: hidden; height: clamp(18rem, 30vw, 30rem); margin-bottom: 1rem;
  background: var(--bg-2); border-radius: var(--radius-container); }
.work__media > * { position: absolute; max-width: none; }
.work__screen { left: 6%; top: 9%; width: 78%; box-shadow: var(--shadow-float); }
.work__screen > img { flex: none; height: auto; }
.work__phone { height: auto; border: calc(2 * var(--hairline)) solid var(--text); border-radius: var(--radius-ui-frame); box-shadow: var(--shadow-float); }
.work--wide .work__phone { right: 6%; top: 24%; width: 18%; }
/* Narrow tiles size the phones by the tile's height, so the whole phone and its frame always show (client, 2026-11-05). */
.work--narrow .work__phone { left: 50%; top: 8%; width: auto; height: 84%; transform: translateX(-50%); }
.work--narrow .work__phone:nth-child(1):not(:only-of-type) { left: 8%; top: 6%; height: 80%; transform: none; }
.work--narrow .work__phone:nth-child(2) { left: auto; right: 8%; top: 14%; height: 80%; transform: none; }
.work--narrow .work__screen { left: 8%; top: 9%; width: 160%; }   /* a website in a narrow tile: the shot runs off the right edge */
.work__media .ref-type { left: 0; bottom: 0; z-index: 1; padding: .5rem .75rem; background: var(--bg); color: var(--text); }
.work__name { font-family: var(--font-label); font-weight: var(--label-weight); font-size: var(--text-small); line-height: var(--leading-small); color: var(--text-2); }
.work__name a { color: inherit; text-decoration: none; text-underline-offset: .25em; }
.work__name a::after { content: ""; position: absolute; inset: 0; z-index: 2; }
.work__text { margin-top: .25rem; max-width: 30rem; font-size: var(--text-title); line-height: var(--leading-title); font-weight: var(--title-weight); }
.work:hover .work__text { text-decoration: underline; text-underline-offset: .2em; }
.work__name a:focus-visible { outline: none; }
.work:has(.work__name a:focus-visible) { outline: var(--focus-width) solid var(--focus); outline-offset: var(--focus-offset); }

.clients-block { margin-top: var(--section-sm); }
.clients-block > .h3 { margin-bottom: var(--gap-text); }
.clients { border-bottom: var(--hairline) solid var(--rule); }
.client { position: relative; display: grid; grid-template-columns: minmax(0, 4fr) minmax(0, 5fr) minmax(0, 3fr); column-gap: var(--gutter);
  align-items: baseline; padding-block: 1.25rem; border-top: var(--hairline) solid var(--rule); }
.client__name { font-size: var(--text-title); line-height: var(--leading-title); font-weight: var(--title-weight); }
.client__name a { color: inherit; text-decoration: none; text-underline-offset: .2em; }
.client__name a::after { content: ""; position: absolute; inset: 0; z-index: 2; }
.client:hover .client__name a { text-decoration: underline; }
.client__name a:focus-visible { outline: none; text-decoration: underline; }
.client:has(.client__name a:focus-visible) { outline: var(--focus-width) solid var(--focus); outline-offset: var(--focus-offset); }
.client__text { color: var(--text-2); }
.client__media { position: relative; }
.client__pic img { display: none; }
.client__pic .ref-type { color: var(--text-2); }
.works [hidden], .clients [hidden], #referenzen-liste [data-filter-section][hidden] { display: none; }

/* Pointer devices from 768 px: the type only on hover / focus (sliding up on the featured tiles), and the client
   rows' picture with its type, right-aligned in the empty column and centred on the row (it overlaps the rows above
   and below, never the row's own text; it takes no pointer events). */
@media (hover: hover) and (min-width: 48rem) {
  .work__media .ref-type { opacity: 0; transform: translateY(100%); transition: opacity var(--t-open), transform var(--t-open); }
  .work:hover .ref-type, .work:focus-within .ref-type { opacity: 1; transform: none; }
  .client__media { align-self: stretch; }
  .client__pic { position: absolute; right: 0; top: 50%; width: min(100%, 20rem); transform: translateY(-50%); pointer-events: none;
    opacity: 0; transition: opacity var(--t-open); }
  .client__pic img { display: block; width: 100%; height: auto; aspect-ratio: 3 / 2; object-fit: cover; border-radius: var(--radius-container); background: var(--bg-2); }
  .client__pic .ref-type { position: absolute; left: 0; bottom: 0; padding: .5rem .75rem; background: var(--bg); color: var(--text); }
  .client:hover .client__media, .client:focus-within .client__media { z-index: 3; }
  .client:hover .client__pic, .client:focus-within .client__pic { opacity: 1; }
}
@media (hover: hover) and (min-width: 48rem) and (prefers-reduced-motion: reduce) {
  .work__media .ref-type { transform: none; }
}
@media (max-width: 63.99rem) {
  .work__text { font-size: var(--text-size); line-height: var(--text-leading); }
}
@media (max-width: 47.99rem) {
  .works { grid-template-columns: 1fr; }
  .work--wide { grid-column: auto; }
  .work__media { height: 20rem; }
  .work--wide .work__media { height: 14rem; }   /* the shot runs off the right edge and the bottom, as on the homepage cards */
  .work--wide .work__screen { width: 100%; }
  .work--wide .work__phone { width: 26%; }
  .work__text { font-size: var(--text-title); line-height: var(--leading-title); }
  .client { grid-template-columns: 1fr; row-gap: .25rem; }
}

/* Contact page (redesign 2026-11-05): the hero is the page head with a person (.page-hero__person: the picture with a
   name under it) and the direct lines (.contact__direct: phone and e-mail at title size, each with its note). Below,
   "what happens next" on the left — sticky beside the form on wide screens (.contact--sticky) — and the form on the
   right: the easy fields first, the services as chips last. Choices are native checkboxes (.check), the chips
   included: the box still shows the state, the chip's edge darkens as a hint. */
.contact { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); column-gap: var(--section-sm); align-items: start; }
.contact__ways { margin-top: var(--gap-block); }
.contact form { margin-top: var(--gap-block); }
.contact .h2 + .lead, .founder .h2 + .lead { margin-top: var(--gap-text); }
.contact__ways a { align-items: flex-start; }
.contact__ways b { display: block; font-weight: var(--title-weight); }
.form fieldset { min-width: 0; margin: 0; padding: 0; border: 0; }
.form legend { margin-bottom: .5rem; padding: 0; font-weight: var(--label-weight); }
.form__choices { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--gutter); }
.form__row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1.5rem var(--gutter); }
.form textarea { min-height: 8rem; resize: vertical; }
.form__trap { position: absolute; left: -100vw; width: 1px; height: 1px; overflow: hidden; }
.form__done { padding: var(--pad-tile); background: var(--bg-2); font-weight: var(--title-weight); }
.form__proto { padding: .75rem 1rem; background: var(--bg-2); font-size: var(--text-small); line-height: var(--leading-small); }
@media (max-width: 63.99rem) { .contact { grid-template-columns: 1fr; row-gap: var(--gap-block); } }
@media (max-width: 47.99rem) { .form__row, .form__choices { grid-template-columns: 1fr; } }
.field label.check { display: flex; margin-bottom: 0; font-weight: var(--text-weight); }   /* the privacy box beside its text, not above it */
.form__choices--chips { display: flex; flex-wrap: wrap; gap: .5rem; }
.form__choices--chips .check { align-items: center; min-height: var(--control-h); padding: .5rem 1rem .5rem .75rem; gap: .5rem;
  border: var(--hairline) solid var(--line); border-radius: var(--radius-control); transition: border-color var(--t-colour); }
.form__choices--chips .check input { width: 1.125rem; height: 1.125rem; margin: 0; }
.form__choices--chips .check:hover, .form__choices--chips .check:has(input:checked) { border-color: var(--text); }
.contact__aside .numbered { margin-top: var(--gap-text); }
.contact__aside .contact__ways { margin-top: var(--gap-block); }
/* Thank-you page (WordPress /thank-you/, page-thank-you.php): the message and two actions left, the Kontakt page's
   next steps right, in the page hero's 7 / 5 grid. */
.thanks .btns { margin-top: var(--gap-actions); }
.thanks .numbered { margin-top: var(--gap-text); }
@media (min-width: 64rem) {
  .contact--sticky .contact__aside { position: sticky; top: calc(4rem + var(--gap-block)); }
}
.contact__direct { display: grid; gap: .5rem; margin-top: var(--gap-block); }
.contact__direct li { display: grid; }
.contact__direct a { justify-self: start; display: inline-flex; align-items: center; min-height: var(--control-h); font-family: var(--font-display); font-weight: var(--display-weight); font-size: var(--text-quote);
  line-height: var(--leading-quote); text-decoration: none; }
.contact__direct a:hover { text-decoration: underline; text-underline-offset: .15em; }
.contact__direct span { color: var(--text-2); font-size: var(--text-small); line-height: var(--leading-small); }
.page-hero__person { margin: 0; }
.page-hero__person .tall { aspect-ratio: 1; object-position: 70% 50%; }   /* square, so the name under it is in the first screen */
.page-hero__person figcaption { margin-top: .75rem; font-weight: var(--title-weight); }
.page-hero__person figcaption small { display: block; color: var(--text-2); font-weight: var(--text-weight); }

/* Website-Kosten (redesign 2026-11-06). The calculator as the page head (.page-hero.theme-dark: crumbs, H1 and the
   lead with its trust line in the two-column intro above the form). The examples as a price table (.prices): three
   columns between hairlines, no cards; the range at heading size in the display face, the scope under it, a link that
   picks that project in the calculator ([data-calc-pick], components.js). .side: an intro beside its list (5 : 7, the
   FAQ's split) — used for the factors and the running costs. .rows--figures: a price list, the figure on the right. */
.page-hero.theme-dark .intro .lead { margin-top: 0; }
.prices { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); border-top: var(--hairline) solid var(--rule); }
.price { display: flex; flex-direction: column; gap: .75rem; padding: var(--pad-tile) var(--gutter) var(--pad-tile) 0; }
.price + .price { padding-left: var(--gutter); border-left: var(--hairline) solid var(--rule); }
.price__title { font-size: var(--text-title); line-height: var(--leading-title); font-weight: var(--title-weight); }
.price__figure { font-family: var(--font-display); font-weight: var(--display-weight); font-size: var(--text-h2); line-height: 1.15; }
.price__text { color: var(--text-2); }
.price__more { margin-top: auto; padding-top: .5rem; }
.side { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); column-gap: var(--section-sm); align-items: start; }
.side > .intro { display: block; margin-bottom: 0; }
.side > .intro > p { margin-top: var(--gap-text); }
.rows--figures li { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; padding-block: 1rem; }
.rows--figures li > span { padding-block: 0; }
.rows__figure { flex: none; text-align: right; font-weight: var(--title-weight); }
.rows__note { margin-top: var(--gap-text); color: var(--text-2); }
@media (max-width: 63.99rem) {
  .side { grid-template-columns: 1fr; row-gap: var(--gap-block); }
  .prices { grid-template-columns: 1fr; }
  .price + .price { padding-left: 0; border-left: 0; border-top: var(--hairline) solid var(--rule); }
}
@media (max-width: 47.99rem) { .rows--figures li { flex-direction: column; gap: .25rem; } .rows__figure { text-align: left; } }

/* Founder (Über uns): the portrait beside the text, square, like every photo. */
.founder { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: var(--gap-block) var(--section-sm); align-items: start; }   /* text and picture side by side: --section-sm apart, like the FAQ and contact splits (the gutter left 12 px) */
.founder figure img { width: 100%; height: auto; aspect-ratio: 4 / 5; object-fit: cover; border-radius: var(--radius-container); }
.founder figcaption { margin-top: .75rem; }
.founder figcaption small { display: block; color: var(--text-2); }
.founder .rows { margin-top: var(--gap-block); }
.founder .pull { margin-top: var(--gap-block); }
@media (max-width: 63.99rem) { .founder { grid-template-columns: 1fr; } .founder figure { max-width: 24rem; } }

/* Team photos (Über uns): four photos from the office shoot in two rows of unequal halves (7 : 5, then 5 : 7), each
   row as tall as its wider photo at 4 : 3; two by two (square) on phones. */
.team-photos { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: var(--gutter); }
.team-photos img { width: 100%; height: 100%; object-fit: cover; border-radius: var(--radius-container); }
.team-photos img:nth-child(4n + 1) { grid-column: span 7; aspect-ratio: 4 / 3; }
.team-photos img:nth-child(4n + 2) { grid-column: span 5; }
.team-photos img:nth-child(4n + 3) { grid-column: span 5; }
.team-photos img:nth-child(4n + 4) { grid-column: span 7; aspect-ratio: 4 / 3; }
@media (max-width: 47.99rem) { .team-photos img:nth-child(n) { grid-column: span 6; aspect-ratio: 1; height: auto; } }   /* phones: two by two, square */

/* Media split: text on the left (5), a picture or a browser frame on the right (7), --section-sm apart; stacks below 1024 px. */
.media-split { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: var(--gap-block) var(--section-sm); align-items: center; }
.media-split .lead { margin-top: var(--gap-text); }
.media-split .btns { margin-top: var(--gap-actions); }
/* --flip: the picture on the left (7), the text on the right (5); in the HTML the text comes first, so stacked
   (below 1024 px) it still leads. __photo: a photo instead of a browser frame. __points: a short plain list (no hairlines, client). */
.media-split--flip { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); }
.media-split--flip > :first-child { order: 2; }
.media-split__photo { width: 100%; height: auto; border-radius: var(--radius-container); }
.media-split__points { margin-top: var(--gap-text); }
.media-split__points li { padding-block: .25rem; }
@media (max-width: 63.99rem) { .media-split, .media-split--flip { grid-template-columns: 1fr; } .media-split--flip > :first-child { order: 0; } }

/* Comparison: two columns side by side (Freelancer / Agentur). */
.compare { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--gap-block) var(--gutter); }
.compare .rows { margin-top: 1rem; }
@media (max-width: 47.99rem) { .compare { grid-template-columns: 1fr; } }

/* Mobile (§1.11): one column, text before image, the CTA stays in the sticky bar */
@media (max-width: 47.99rem) {
  .span-3, .span-4, .span-6, .span-8, .start-5 { grid-column: 1 / -1; }
  .hero__actions .btns { width: 100%; }
  .hero__actions .btns .btn { flex: 1 1 100%; }   /* stacked actions: equal full-width pills */
  /* No W on phones (client): it needed its own block of room above the photos; the photos follow the buttons. */
  .hero__media { grid-template-columns: 1fr; margin-top: var(--gap-block); }
  .roof { display: none; }
  .hero__media .wide { aspect-ratio: 3 / 2; }
  .services { grid-template-columns: 1fr; }
  .intro { grid-template-columns: 1fr; row-gap: var(--gap-text); }
  .calc { grid-template-columns: 1fr; row-gap: var(--gap-block); }
  .calc__estimate { position: static; }
  .calc__options { grid-template-columns: 1fr; }
  .services__cities { margin-left: 0; }
  .quote { grid-template-columns: 1fr; }
  /* The four cards float on the photo, inside it at the foot like on desktop (client). The photo is shown whole (2 : 3,
     the shot's own ratio), which leaves the faces clear above the cards. */
  .hero__media .tall { aspect-ratio: 2 / 3; }
  .hero__media .tall, .hero__media .proof { grid-column: 1; grid-row: 1; }
  .hero__media .proof { align-self: end; margin: var(--gutter); grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .proof span { min-height: calc(3em * var(--leading-small)); }   /* narrow cards: the longest label takes three lines */
  .book { grid-template-columns: 1fr; }
  .book__widget { position: static; }
  .span-2 { grid-column: 1 / -1; }
}
@media (prefers-reduced-motion: reduce) { *, *::before, *::after { transition: none !important; } }
