/* ============================================================================
   koeln-schloss24.de — THE SHARED DESIGN LANGUAGE.
   Every page links this file UNEDITED; cohesion lives here, uniqueness lives in
   the per-page composition of the primitives below.

   Feel: stahl-kupfer (style-library/stahl-kupfer) — machined, sober, transparent;
   ruled objects rather than floating cards. Re-themed from that style's gunmetal
   steel-blue to KÖLN'S VIOLET #6B21A8 (network palette for this domain), with the
   copper CTA family kept because design-tokens.md §3.4 requires the CTA to be a
   WARM accent contrasting the primary, contrast-verified as TEXT and not only as
   a fill.

   Every colour pair below was COMPUTED, not eyeballed (tools/contrast-check.py).
   The four surfaces carry a faint violet cast so the neutrals belong to the
   primary instead of sitting beside it.
   ========================================================================== */
:root{
  /* --- surfaces (faint violet cast: "brushed metal in Köln violet") --- */
  --bg:#faf8fd; --surface:#ffffff; --surface-alt:#f2edf8; --steel:#e8e0f2;
  --line:#dbd2e6;          /* decorative hairline only */
  --line-strong:#7f7191;   /* 3.50:1 on --steel, 4.49:1 on --surface — use when a
                              border is the ONLY signal. The stahl-kupfer value
                              re-hued lands at 2.86:1 on this violet steel and was
                              darkened until it cleared 3:1 on ALL FOUR light grounds. */
  --dark:#171122; --dark-2:#221a31; --dark-line:#372a4a; --dark-muted:#bdb0cf;

  /* --- ink --- */
  --text:#1d1826;          /* 17.34:1 on --surface */
  --muted:#544a63;         /*  8.28:1 on --surface — "muted" is chroma, never contrast */
  --head:#161020;

  /* --- brand --- */
  --primary:#6B21A8;       /* Köln violet · 8.72:1 on --surface, 6.80:1 on --steel */
  --primary-hover:#571888;
  --primary-subtle:#f0e6fa;
  --on-primary:#ffffff;    /* 8.72:1 */

  /* --- the ONE reserved accent: the phone CTA --- */
  --cta:#b8541c;           /* copper · white on it 4.86:1 — a FILL token */
  --cta-hover:#9c4415;     /* white on it 6.46:1 */
  --cta-light:#efb283;     /* copper for TEXT ON DARK. stahl-kupfer's #e8a06a is
                              4.02:1 on THIS primary (it was 4.89:1 on the steel-blue
                              one) — under AA. Lightened until it clears 4.5 on
                              --primary (4.72) and --dark (9.97). */
  --cta-ink:#a04716;       /* copper for TEXT on any LIGHT band. --cta itself is
                              4.86:1 on white but only 4.36 on --surface-alt and
                              3.98 on --steel, so it is a FILL, not a text colour.
                              --cta-ink clears 4.5 on all five light grounds (worst
                              --steel 4.81). */
  --on-cta:#ffffff;

  --dark-3:#2c2240;        /* raised surface ON a dark band */
  --dark-4:#362a4d;        /* hover surface / ghost graphic on dark */
  --dark-line-2:#54426f;   /* hover border on dark */
  --on-dark:#ded4ea;       /* body copy on any dark or primary fill (6.11:1 on --primary) */
  --tint-2:#e2d6f2;        /* pressed/hover tint on light */
  --cta-tint:#fdf4ef;      /* ground of the info notice + accent hover tint */
  --focus:#180f26;         /* always paired with a white inner ring */
  --danger:#b3261e; --danger-tint:#fdf1f0;
  --success:#1c6b3f;

  /* --- personality --- */
  --r-xs:2px; --r-sm:4px; --r:8px; --r-lg:14px; --pill:999px;
  --notch:14px;                                   /* the key-bow corner cut */
  --sh-sm:0 1px 2px rgba(23,17,34,.06), 0 2px 6px rgba(23,17,34,.05);
  --sh:0 6px 18px rgba(23,17,34,.09);
  --sh-lg:0 18px 44px rgba(23,17,34,.15);
  --sh-dark:0 18px 44px rgba(0,0,0,.34);

  --c:1320px; --gut:24px;
  --ease:cubic-bezier(.22,.61,.36,1);
  --dur:.22s; --dur-slow:.58s;
  --tap:44px;
  --f:'Segoe UI',system-ui,-apple-system,'Helvetica Neue',Arial,sans-serif;
  --f-num:ui-monospace,'SF Mono','Cascadia Mono','Segoe UI Mono',Menlo,Consolas,monospace;
}

/* ---------------------------------------------------------------- base ---- */
*,*::before,*::after{box-sizing:border-box}
*{margin:0}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
body{
  font-family:var(--f);
  font-size:18px;              /* A10 floor — never drop to 16px */
  line-height:1.7;
  color:var(--text);
  background:var(--bg);
  overflow-x:hidden;
  -webkit-font-smoothing:antialiased;
  text-underline-offset:.18em;
}
img{max-width:100%;height:auto;display:block}
svg{display:block}
a{color:var(--primary);text-decoration-thickness:1px}
/* THE BUG THIS FIXES: a bare `a:hover` is (0,1,1) and beats `.btn{color:var(--btn-fg)}`
   (0,1,0), so on hover every button label turned copper — and on .btn--cta that is
   copper text on a darker-copper wipe, i.e. the label disappears. A link that IS a
   component owns its own colour; only prose links take the copper hover.
   (Same specificity trap as `.section--dark a` further down — attribute/state selectors
   quietly outrank plain class rules.) */
a:not(.btn):not(.callbtn):not(.calltab):not(.chip):not(.brand):not(.ftel):not(.telbig):hover{
  color:var(--cta-ink)}
/* hyphens:auto on a DISPLAY heading produces mid-word breaks that read as a defect
   ("Schließzylin-" / "der" at 48px). Headings get hyphens:manual with overflow-wrap
   as the safety net for a compound too long for its column; body copy — where German
   hyphenation genuinely helps the ragged edge — keeps hyphens:auto. */
h1,h2,h3,h4{color:var(--head);line-height:1.14;letter-spacing:-.018em;font-weight:800;
  overflow-wrap:break-word;hyphens:manual}
p{max-width:68ch;hyphens:auto}
ul,ol{margin:0;padding:0}
strong{color:var(--head);font-weight:700}
::selection{background:var(--cta);color:#fff}

/* one focus treatment that survives EVERY band: white inner ring + dark outer */
:where(a,button,summary,[tabindex]):focus-visible{
  outline:none;
  box-shadow:0 0 0 3px var(--surface),0 0 0 6px var(--focus);
  border-radius:var(--r-sm);
}
.section--dark :where(a,button,summary):focus-visible{
  box-shadow:0 0 0 3px var(--dark),0 0 0 6px var(--cta-light);
}

/* ------------------------------------------------------------ structure --- */
.wrap{max-width:var(--c);margin-inline:auto;padding-inline:var(--gut)}
/* The narrow and wide measures move WITH --c, or the deliberate measure change
   between a normal band and the FAQ band stops reading as a decision. */
.wrap--narrow{max-width:920px}
.wrap--wide{max-width:1440px}
.section{padding:clamp(58px,7.2vw,104px) 0;position:relative}
.section--tight{padding:clamp(40px,4.6vw,64px) 0}
.section--alt{background:var(--surface-alt)}
.section--surface{background:var(--surface)}
.section--dark{background:var(--dark);color:var(--dark-muted)}
.section--dark h1,.section--dark h2,.section--dark h3,.section--dark h4{color:#fff}
/* ROOT-CAUSE FIX: a bare `.section--dark a` is (0,1,1) and silently beat every
   button's own (0,1,0) colour, so .btn/.callbtn inside a dark band rendered their
   label in --cta-light — copper-on-copper at ~1.4:1 on the CTA fill. A link that is
   a BUTTON carries its own colour; only prose links take the dark-band link colour. */
.section--dark a:not(.btn):not(.callbtn):not(.calltab):not(.chip):not(.brand):not(.ftel){
  color:var(--cta-light)}
.section--dark .lead{color:var(--on-dark)}

/* the SIGNATURE band: brushed steel. A material texture (german-design.md §4.3),
   not a decorative gradient — fine vertical hairlines at 2.5% over a flat tint. */
.section--steel{
  background:
    repeating-linear-gradient(90deg,
      rgba(107,33,168,.030) 0 1px, rgba(255,255,255,0) 1px 6px),
    repeating-linear-gradient(90deg,
      rgba(255,255,255,.42) 0 1px, rgba(255,255,255,0) 1px 14px),
    var(--steel);
}
.section--dark.section--steel{
  background:
    repeating-linear-gradient(90deg,
      rgba(255,255,255,.035) 0 1px, rgba(255,255,255,0) 1px 4px),
    var(--dark);
}

/* --------------------------------------------------------- typography ----- */
.display{
  font-size:clamp(34px,5.6vw,62px);font-weight:800;line-height:1.05;
  letter-spacing:-.026em;color:var(--head);
}
.display .l2{display:block;color:var(--primary)}
.section--dark .display,.hero--dark .display{color:#fff}
.section--dark .display .l2,.hero--dark .display .l2{color:var(--cta-light)}
.display--long{font-size:clamp(30px,4.4vw,48px)}

.stitle{font-size:clamp(27px,3.3vw,42px);font-weight:800;letter-spacing:-.022em}
.h3{font-size:clamp(19px,1.5vw,22px);font-weight:700;letter-spacing:-.012em;line-height:1.28}
.lead{font-size:clamp(18px,1.35vw,20.5px);line-height:1.66;color:var(--muted)}
.small{font-size:16.5px;line-height:1.6}
.vh{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}

/* section head — the eyebrow + title + optional lead, three rhythms */
.shead{margin-bottom:clamp(30px,3.4vw,50px);max-width:760px}
.shead--center{margin-inline:auto;text-align:center}
.shead--split{display:grid;gap:22px clamp(28px,4vw,64px);align-items:end;max-width:none;
  grid-template-columns:minmax(0,1fr)}
@media(min-width:900px){.shead--split{grid-template-columns:minmax(0,1.05fr) minmax(0,.95fr)}}
.shead .stitle+.lead{margin-top:15px}

/* eyebrow — variant A: copper key-bit mark + label */
.eyebrow{display:inline-flex;align-items:center;gap:10px;font-size:13px;font-weight:800;
  letter-spacing:.15em;text-transform:uppercase;color:var(--cta-ink);margin-bottom:15px}
.section--dark .eyebrow{color:var(--cta-light)}
/* the key-bitting mark — 4 teeth at 30x12. Measured: a 7-tooth profile at 26x9 renders
   as an illegible smear, so the tooth count is capped at what survives at this size. */
.eyebrow::before{content:"";width:30px;height:12px;flex:none;background:currentColor;
  clip-path:polygon(0 100%,0 42%,20% 42%,20% 8%,40% 8%,40% 58%,60% 58%,60% 22%,80% 22%,80% 70%,100% 70%,100% 100%)}
/* eyebrow — variant B: boxed, for use where a rule would be too quiet */
.eyebrow--box{border:1.5px solid var(--line-strong);color:var(--primary);
  padding:7px 14px;letter-spacing:.13em;font-size:12px}
.eyebrow--box::before{display:none}
.section--dark .eyebrow--box{border-color:var(--dark-line);color:var(--cta-light)}
/* eyebrow — variant C: the pin-tumbler rule. Pins HANG from a shear line rather than
   standing on a baseline — bottom-anchored bars read as signal-strength bars, which is
   the wrong object entirely. Top-anchored under a rule reads as a lock cross-section. */
.pinrule{display:flex;align-items:flex-start;gap:5px;height:24px;margin-bottom:16px;
  padding-top:4px;border-top:2px solid var(--cta);width:45px}
.pinrule i{width:4px;background:var(--cta);display:block;border-radius:0 0 2px 2px}
.pinrule i:nth-child(1){height:13px}.pinrule i:nth-child(2){height:7px}
.pinrule i:nth-child(3){height:17px}.pinrule i:nth-child(4){height:10px}
.pinrule i:nth-child(5){height:15px}
.section--dark .pinrule{border-top-color:var(--cta-light)}
.section--dark .pinrule i{background:var(--cta-light)}

/* ------------------------------------------------------------- buttons ---- */
.btn{
  --btn-bg:var(--primary); --btn-fg:var(--on-primary); --btn-bg-h:var(--primary-hover);
  position:relative;display:inline-flex;align-items:center;justify-content:center;gap:11px;
  min-height:var(--tap);padding:14px 26px;border:0;border-radius:var(--r-sm);
  background:var(--btn-bg);color:var(--btn-fg);
  font:700 17px/1.2 var(--f);letter-spacing:.005em;text-decoration:none;cursor:pointer;
  transition:background var(--dur) var(--ease),transform var(--dur) var(--ease),
             box-shadow var(--dur) var(--ease);
  overflow:hidden;isolation:isolate;
}
/* The wipe MUST be z-index:-1, not 0. CSS paint order puts a positioned descendant at
   z-index:0 ABOVE the element's own inline content — so a button whose label is a bare
   text node (most of them) had its text painted over by the wipe on hover. `.btn>*`
   cannot rescue it: a text node is not an element and can never be lifted.
   At -1, and with `isolation:isolate` on .btn keeping it inside this stacking context,
   the wipe paints above the button's background and below the label, wrapped or not. */
.btn>*{position:relative;z-index:1}
.btn::before{content:"";position:absolute;inset:0;z-index:-1;background:var(--btn-bg-h);
  transform:scaleX(0);transform-origin:left;transition:transform .3s var(--ease)}
.btn:hover::before{transform:scaleX(1)}
.btn:hover{box-shadow:var(--sh)}
.btn:active{transform:translateY(1px)}
.btn--cta{--btn-bg:var(--cta);--btn-fg:var(--on-cta);--btn-bg-h:var(--cta-hover)}
.btn--ghost{--btn-bg:transparent;--btn-fg:var(--primary);--btn-bg-h:var(--primary);
  box-shadow:inset 0 0 0 1.5px var(--line-strong)}
.btn--ghost:hover{color:#fff}
.section--dark .btn--ghost{--btn-fg:#fff;--btn-bg-h:#fff;box-shadow:inset 0 0 0 1.5px var(--dark-line)}
.section--dark .btn--ghost:hover{color:var(--dark)}
.btn--lg{padding:18px 32px;font-size:18.5px}
.btn--block{display:flex;width:100%}
.btn svg{width:20px;height:20px;flex:none}

/* the call button: label above the number, icon disc at the left.
   Lifted from the Dexon hero treatment, re-coloured to copper. */
.callbtn{
  display:inline-flex;align-items:center;gap:14px;min-height:var(--tap);
  padding:11px 26px 11px 11px;border-radius:var(--pill);
  background:var(--cta);color:#fff;text-decoration:none;
  transition:background var(--dur) var(--ease),transform var(--dur) var(--ease),box-shadow var(--dur) var(--ease);
}
.callbtn:hover{background:var(--cta-hover);color:#fff;transform:translateY(-2px);box-shadow:var(--sh-lg)}
.callbtn .disc{width:46px;height:46px;flex:none;border-radius:50%;background:rgba(255,255,255,.19);
  display:grid;place-items:center}
.callbtn .disc svg{width:21px;height:21px;stroke:#fff}
/* opacity:.86 white over copper blends to #f5e7df = 4.02:1 — under AA for 12px text.
   Full white is 4.86:1. Never dim text on the accent fill to "soften" it. */
.callbtn .cap{display:block;font-size:12px;font-weight:700;letter-spacing:.14em;
  text-transform:uppercase;line-height:1}
.callbtn .num{display:block;font-size:21px;font-weight:800;letter-spacing:-.01em;margin-top:3px;
  font-variant-numeric:tabular-nums}
/* Specificity note: `.section--dark a` is (0,1,1) and would otherwise win over a
   plain `.callbtn--dark` (0,1,0), painting this white-ground button in --cta-light
   at ~1.9:1. Doubling the class to (0,2,0) is what keeps it readable on a dark band. */
.callbtn.callbtn--dark{background:var(--surface);color:var(--primary)}
.callbtn.callbtn--dark:hover{background:var(--surface);color:var(--primary)}
.callbtn--dark .disc{background:var(--cta)}
.callbtn--dark .cap{color:var(--muted);opacity:1}

/* ------------------------------------------------------- icon badges ------ */
.ibadge{width:54px;height:54px;flex:none;border-radius:var(--r);display:grid;place-items:center;
  background:var(--primary-subtle);color:var(--primary);
  transition:background var(--dur) var(--ease),color var(--dur) var(--ease),transform var(--dur) var(--ease)}
.ibadge svg{width:26px;height:26px;stroke-width:1.7}
.ibadge--cta{background:var(--cta);color:#fff}
.ibadge--dark{background:var(--primary);color:#fff}
.ibadge--outline{background:transparent;box-shadow:inset 0 0 0 1.5px var(--line-strong)}
.ibadge--round{border-radius:50%}
.ibadge--lg{width:70px;height:70px}.ibadge--lg svg{width:32px;height:32px}
.ibadge--sm{width:40px;height:40px;border-radius:var(--r-sm)}.ibadge--sm svg{width:20px;height:20px}
.section--dark .ibadge{background:var(--dark-3);color:var(--cta-light)}

/* --------------------------------------------------------------- cards ---- */
.card{background:var(--surface);border:1px solid var(--line);border-radius:var(--r);
  padding:clamp(22px,2.2vw,30px);position:relative;
  transition:border-color var(--dur) var(--ease),box-shadow var(--dur) var(--ease),
             transform var(--dur) var(--ease)}
.card:hover{border-color:var(--line-strong);box-shadow:var(--sh);transform:translateY(-3px)}
.card h3,.card .h3{margin-bottom:9px}
.card p{color:var(--muted);font-size:17px}
.section--dark .card{background:var(--dark-2);border-color:var(--dark-line);color:var(--dark-muted)}
.section--dark .card:hover{border-color:var(--dark-line-2)}
.section--dark .card p{color:var(--dark-muted)}

/* the key-bow NOTCH — the style's structural signature: one cut top-right corner.
   NOTE: clip-path also clips border AND box-shadow, so a notched box can never carry
   either. Two forms exist, and both are honest about that:
     .card--notch  — a FILLED notched card (no edge). Only legible on a band that
                     contrasts its fill, so it ships on tint/steel/dark bands.
     .notch/.notch__in — a two-element notched card WITH a hairline edge: the outer
                     box is the line colour, the inner is inset 1px and re-clipped.
   Elevation on a clipped box must use filter:drop-shadow(), which is applied after
   clipping and therefore traces the notch; box-shadow would be cut away. */
.card--notch{
  clip-path:polygon(0 0,calc(100% - var(--notch)) 0,100% var(--notch),100% 100%,0 100%);
  border:0;background:var(--primary-subtle);box-shadow:none;
  transition:background var(--dur) var(--ease),transform var(--dur) var(--ease),filter var(--dur) var(--ease)}
.card--notch:hover{background:var(--tint-2);filter:drop-shadow(0 10px 20px rgba(23,17,34,.15))}
.section--dark .card--notch{background:var(--dark-2)}
.section--dark .card--notch:hover{background:var(--dark-4);filter:none}

.notch{--notch-line:var(--line);
  clip-path:polygon(0 0,calc(100% - var(--notch)) 0,100% var(--notch),100% 100%,0 100%);
  background:var(--notch-line);padding:1px;
  transition:background var(--dur) var(--ease),filter var(--dur) var(--ease)}
.notch:hover{--notch-line:var(--line-strong);filter:drop-shadow(0 10px 20px rgba(23,17,34,.14))}
.notch__in{
  clip-path:polygon(0 0,calc(100% - var(--notch)) 0,100% calc(var(--notch) - 1px),100% 100%,0 100%);
  background:var(--surface);padding:clamp(22px,2.2vw,30px);height:100%}
.section--dark .notch{--notch-line:var(--dark-line)}
.section--dark .notch:hover{--notch-line:var(--dark-line-2);filter:none}
.section--dark .notch__in{background:var(--dark-2)}

/* the COPPER INLAY — a 3px leading edge marking the emphasis card in a set */
.card--inlay{border-top:3px solid var(--cta)}
.card--lead{background:var(--primary);border-color:var(--primary);color:var(--on-dark)}
.card--lead h3,.card--lead .h3{color:#fff}
.card--lead p{color:var(--on-dark)}

/* -------------------------------------------------------------- grids ----- */
.grid{display:grid;gap:clamp(16px,1.7vw,24px)}
.g2{grid-template-columns:minmax(0,1fr)}
.g3{grid-template-columns:minmax(0,1fr)}
.g4{grid-template-columns:minmax(0,1fr)}
@media(min-width:640px){.g2{grid-template-columns:repeat(2,minmax(0,1fr))}.g3{grid-template-columns:repeat(2,minmax(0,1fr))}.g4{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(min-width:980px){.g3{grid-template-columns:repeat(3,minmax(0,1fr))}.g4{grid-template-columns:repeat(4,minmax(0,1fr))}}
.split{display:grid;gap:clamp(28px,4vw,60px);align-items:center;grid-template-columns:1fr}
@media(min-width:900px){
  .split{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}
  .split--wide-l{grid-template-columns:minmax(0,1.22fr) minmax(0,.78fr)}
  .split--wide-r{grid-template-columns:minmax(0,.78fr) minmax(0,1.22fr)}
  .split--flip>*:first-child{order:2}
}

/* --------------------------------------------------------------- chips ---- */
.chips{display:flex;flex-wrap:wrap;gap:9px;padding:0;list-style:none}
.chip{display:inline-flex;align-items:center;gap:8px;padding:9px 15px;border-radius:var(--pill);
  background:var(--surface);border:1px solid var(--line);font-size:16px;font-weight:600;color:var(--text);
  transition:border-color var(--dur) var(--ease),background var(--dur) var(--ease)}
.chip:hover{border-color:var(--cta);background:var(--cta-tint)}
.chip--solid{background:var(--primary-subtle);border-color:transparent;color:var(--primary)}
.section--dark .chip{background:var(--dark-3);border-color:var(--dark-line);color:var(--on-dark)}

/* ------------------------------------------------------- image slots ------ */
.imgph{position:relative;display:block;width:100%;background:var(--steel);border-radius:var(--r);
  overflow:hidden;color:var(--muted)}
.imgph img{width:100%;height:100%;object-fit:cover}
.imgph--notch{clip-path:polygon(0 0,calc(100% - 22px) 0,100% 22px,100% 100%,0 100%);border-radius:0}
.ratio-16x9{aspect-ratio:16/9}.ratio-4x3{aspect-ratio:4/3}.ratio-1x1{aspect-ratio:1/1}
.ratio-3x4{aspect-ratio:3/4}.ratio-3x2{aspect-ratio:3/2}

/* ------------------------------------------------------------- motion ----- */
/* TRANSFORM-ONLY, and this is a correctness decision, not a taste one.
   `.reveal{opacity:0}` with a JS-only `.in` leaves every below-fold element at
   zero opacity in any renderer that does not scroll — which is every headless
   audit. axe then computes the foreground alpha as 0 and reports serious
   colour-contrast violations on perfectly legible text, and a reader with
   scripting off sees a blank page. The rise alone carries the reveal; the text
   is opaque from the first paint. */
.reveal{transform:translateY(18px);
  transition:transform var(--dur-slow) var(--ease)}
.reveal.in{transform:none}
.reveal.d1{transition-delay:.08s}.reveal.d2{transition-delay:.16s}
.reveal.d3{transition-delay:.24s}.reveal.d4{transition-delay:.32s}
/* one-shot clip reveal for images — fires from the same observer */
img.wipe,.imgph.wipe{clip-path:inset(0 0 100% 0);transition:clip-path .8s var(--ease)}
.wipe.in{clip-path:inset(0 0 0 0)}

@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation:none!important;transition:none!important}
  .reveal{opacity:1;transform:none}
  .wipe{clip-path:none}
}

/* ======================================================================== */
/*  SHARED CHROME — identical on every page (navbar, call bar, to-top,      */
/*  footer). Built once here so the four pages cannot drift.                */
/* ======================================================================== */

/* --- topbar: the number is ALWAYS visible, never behind the hamburger --- */
.topbar{background:var(--dark);color:var(--dark-muted);font-size:15.5px}
.topbar .wrap{display:flex;align-items:center;justify-content:space-between;gap:16px;
  min-height:var(--tap);flex-wrap:wrap}
.topbar a{color:#fff;text-decoration:none;display:inline-flex;align-items:center;gap:9px;
  min-height:var(--tap);font-weight:600}
.topbar a:hover{color:var(--cta-light)}
.topbar svg{width:17px;height:17px;stroke:var(--cta-light);flex:none}
.topbar .tb-note{display:none}
@media(min-width:760px){.topbar .tb-note{display:inline-flex;align-items:center;gap:9px}}

/* --- header --- */
header{position:sticky;top:0;z-index:120;background:var(--surface);
  border-bottom:1px solid var(--line);transition:box-shadow var(--dur) var(--ease)}
header.stuck{box-shadow:0 6px 20px rgba(23,17,34,.10)}
.navrow{display:flex;align-items:center;gap:18px;min-height:74px}
.brand{display:inline-flex;align-items:center;gap:11px;text-decoration:none;margin-right:auto}
.brand .bmark{width:40px;height:40px;flex:none;border-radius:var(--r-sm);background:var(--primary);
  display:grid;place-items:center}
.brand .bmark svg{width:23px;height:23px;stroke:var(--cta-light)}
.brand b{font-size:20px;font-weight:800;color:var(--head);letter-spacing:-.02em;line-height:1.1}
@media(max-width:400px){
  /* the lockup alone was 229px, overflowing a 320px viewport once the burger
     and gutters were counted. */
  .brand b{font-size:16.5px}.brand span{font-size:11px}
  .brand .bmark{width:34px;height:34px}.brand .bmark svg{width:19px;height:19px}
  .navrow{gap:10px}
}
.brand span{display:block;font-size:12.5px;font-weight:600;letter-spacing:.1em;
  text-transform:uppercase;color:var(--muted)}
.nav{display:none;gap:4px;list-style:none}
.nav a{display:inline-flex;align-items:center;min-height:var(--tap);padding:0 11px;
  font-size:16.2px;font-weight:600;color:var(--text);text-decoration:none;border-radius:var(--r-sm);
  white-space:nowrap;
  transition:color var(--dur) var(--ease),background var(--dur) var(--ease)}
.nav a:hover,.nav a[aria-current="page"]{color:var(--primary);background:var(--primary-subtle)}
.navcall{display:none}
.navcall span{white-space:nowrap}
/* raised from 1040: with four items plus the brand and the call button, the bar
   only genuinely fits from ~1120px. Below that the burger is the honest answer. */
@media(min-width:1120px){.nav{display:flex}.navcall{display:inline-flex}
  .brand b{white-space:nowrap}}
/* flex:none is load-bearing — as a flex item in .navrow the burger shrank to 38px
   wide at tablet widths, i.e. under the 44px floor for the ONE control that opens
   the menu. Width alone does not protect a flex item. */
.burger{display:inline-grid;place-items:center;flex:none;
  width:var(--tap);height:var(--tap);min-width:var(--tap);
  border:1px solid var(--line);border-radius:var(--r-sm);background:var(--surface);cursor:pointer}
.burger svg{width:24px;height:24px;stroke:var(--head)}
@media(min-width:1120px){.burger{display:none}}
.mobmenu{display:none;border-top:1px solid var(--line);background:var(--surface)}
.mobmenu.open{display:block}
.mobmenu ul{list-style:none;padding:10px 0 18px}
.mobmenu a{display:flex;align-items:center;min-height:52px;font-size:17.5px;font-weight:600;
  color:var(--text);text-decoration:none;border-bottom:1px solid var(--line)}
.mobmenu a:hover{color:var(--cta-ink)}

/* --- sticky mobile call bar (C2: class matches (call|tel|phone|anruf) + position:fixed) --- */
.callbar{position:fixed;left:0;right:0;bottom:0;z-index:150;display:none;
  background:var(--surface);border-top:1px solid var(--line);
  box-shadow:0 -6px 22px rgba(23,17,34,.17);padding:9px 14px calc(9px + env(safe-area-inset-bottom))}
.callbar a{display:flex;align-items:center;justify-content:center;gap:11px;min-height:52px;
  border-radius:var(--r-sm);background:var(--cta);color:#fff;text-decoration:none;
  font-size:18.5px;font-weight:800;letter-spacing:.01em}
.callbar a svg{width:22px;height:22px;stroke:#fff;flex:none}
@media(max-width:1119px){.callbar{display:block}body{padding-bottom:84px}}

/* --- scroll to top --- */
.totop{position:fixed;right:16px;bottom:96px;z-index:140;width:48px;height:48px;
  display:grid;place-items:center;border:1px solid var(--line);border-radius:50%;
  background:var(--surface);color:var(--primary);cursor:pointer;
  opacity:0;visibility:hidden;transform:translateY(9px);
  transition:opacity var(--dur) var(--ease),transform var(--dur) var(--ease),
             visibility var(--dur) var(--ease),box-shadow var(--dur) var(--ease)}
.totop.show{opacity:1;visibility:visible;transform:none}
.totop:hover{box-shadow:var(--sh);border-color:var(--line-strong)}
.totop svg{width:22px;height:22px;stroke:currentColor}
@media(min-width:1120px){.totop{bottom:24px}}

/* --- footer --- */
footer{background:var(--dark);color:var(--dark-muted);padding-top:clamp(48px,5.4vw,76px)}
footer h3{color:#fff;font-size:17px;letter-spacing:.09em;text-transform:uppercase;margin-bottom:17px}
.fgrid{display:grid;gap:34px clamp(24px,3vw,48px);grid-template-columns:1fr}
@media(min-width:700px){.fgrid{grid-template-columns:repeat(2,1fr)}}
@media(min-width:1020px){.fgrid{grid-template-columns:1.4fr 1fr 1fr 1.1fr}}
footer ul{list-style:none}
/* 44px floor on footer links too: A11 only WARNS on non-call controls, but this
   audience is older and often one-handed on a phone, so the floor is worth the height. */
footer li{margin-bottom:0}
footer a{color:var(--dark-muted);text-decoration:none;
  display:inline-flex;align-items:center;min-height:var(--tap)}
footer a:hover{color:var(--cta-light);text-decoration:underline}
footer .ftel{display:inline-flex;align-items:center;gap:11px;min-height:var(--tap);
  color:#fff;font-size:21px;font-weight:800;font-variant-numeric:tabular-nums}
footer .ftel svg{width:21px;height:21px;stroke:var(--cta-light);flex:none}
.fbase{margin-top:clamp(34px,4vw,52px);border-top:1px solid var(--dark-line);
  padding:22px 0 26px;display:flex;flex-wrap:wrap;gap:10px 22px;
  align-items:center;justify-content:space-between;font-size:15.5px}
.fbase ul{display:flex;flex-wrap:wrap;gap:2px 20px}
.fbase li{margin:0}
.fbase a{min-height:var(--tap)}

/* skip link — visible only on focus, above the sticky header */
.skip{position:absolute;left:-9999px;top:0;z-index:400;background:var(--cta);color:#fff;
  padding:13px 20px;font-weight:700;text-decoration:none;border-radius:0 0 var(--r-sm) 0}
.skip:focus{left:0;color:#fff}

/* footer lockup reuses .brand with dark-band colours */
.brand--foot b{color:#fff}
.brand--foot span span{color:var(--dark-muted)}
.brand--foot .bmark{background:var(--dark-2);border:1px solid var(--dark-line)}

/* ======================================================================== */
/*  Two late primitives, both from the hotlock/dexon reads.                 */
/* ======================================================================== */

/* THE KEYPAD GRID — the layout lines ARE the design. One `gap:1px` over a line-
   coloured ground, cells painted in the surface colour, so the rules are drawn by
   the gap rather than by per-cell borders (the source hand-tuned border-width per
   cell at every breakpoint; this needs no arithmetic and reflows for free).
   Reads unmistakably as security hardware — the closest thing this style has to a
   trade-specific structure. Also the mechanism behind the segmented assurance slab:
   three cells at gap:2px read as ONE slab, not three cards. */
.keypad{display:grid;gap:1px;background:var(--line);border:1px solid var(--line)}
.keypad>*{background:var(--surface);padding:clamp(20px,2.2vw,30px);margin:0}
.keypad--tight{gap:2px;background:var(--line-strong);border:0}
.keypad--cta{gap:2px;background:var(--cta-hover);border:0}
.keypad--cta>*{background:var(--cta);color:#fff}
.keypad--cta>* :where(h2,h3,h4,.h3,strong){color:#fff}
.section--dark .keypad{background:var(--dark-line);border-color:var(--dark-line)}
.section--dark .keypad>*{background:var(--dark-2)}
@media(min-width:640px){.keypad--2{grid-template-columns:repeat(2,1fr)}
  .keypad--3{grid-template-columns:repeat(2,1fr)}.keypad--4{grid-template-columns:repeat(2,1fr)}}
@media(min-width:980px){.keypad--3{grid-template-columns:repeat(3,1fr)}
  .keypad--4{grid-template-columns:repeat(4,1fr)}.keypad--6{grid-template-columns:repeat(6,1fr)}}

/* PHONE NUMBER AS DISPLAY TYPE — no button chrome at all. On a page where the call
   IS the only conversion channel, a huge tappable number outranks another square
   button, and it still clears the 44px target by a wide margin. */
.telbig{display:inline-flex;align-items:center;gap:14px;text-decoration:none;
  font-size:clamp(30px,4.4vw,54px);font-weight:800;line-height:1.06;
  letter-spacing:-.025em;font-variant-numeric:tabular-nums;color:var(--head);
  transition:color var(--dur) var(--ease)}
.telbig:hover{color:var(--cta-ink)}
.telbig svg{width:.72em;height:.72em;flex:none;stroke:var(--cta);stroke-width:1.8}
.section--dark .telbig{color:#fff}
.section--dark .telbig:hover{color:var(--cta-light)}
.section--dark .telbig svg{stroke:var(--cta-light)}

/* THE CALL TAB — a copper block that reads as die-cut out of the image above it:
   one rounded corner, zero top radius, and a negative pull so it bites into the
   photo's bottom edge. From the `blocks` kit, where it is a generic tab; the recon
   flagged it as "the best-shaped button in the corpus and it wants a phone number",
   so here it only ever carries the number. Unlike .btn it has NO hover wipe —
   design-tokens.md §5 forbids animating the CTA; the hover is colour only. */
.calltab{
  display:inline-flex;align-items:center;gap:13px;position:relative;z-index:2;
  margin-top:-34px;padding:20px 30px 20px 26px;
  border-radius:0 var(--r-lg) 0 0;
  background:var(--cta);color:#fff;text-decoration:none;
  font-size:clamp(19px,1.7vw,24px);font-weight:800;letter-spacing:-.01em;
  font-variant-numeric:tabular-nums;min-height:var(--tap);
  transition:background var(--dur) var(--ease)}
.calltab:hover{background:var(--cta-hover);color:#fff}
.calltab svg{width:1.05em;height:1.05em;flex:none;stroke:currentColor;stroke-width:1.9}
.calltab .cap{display:block;font-size:12px;font-weight:700;letter-spacing:.14em;
  text-transform:uppercase;line-height:1;margin-bottom:4px}

/* TAP-TARGET FLOOR for every click-to-call, whatever a page happens to call it.
   A11 measures the rendered box, so a number styled as pure display type still has
   to clear 44px. min-height only bites on a flex/block box, hence the display switch;
   verified that no tel: link on any page sits inline inside a <p>, so this is safe. */
/* :not(.navcall) is load-bearing: this rule is (0,1,1) and would otherwise beat
   `.navcall{display:none}` (0,1,0) below 1040px, resurrecting the desktop call
   button and pushing the burger off-screen on every phone <=390px. */
a[href^="tel:"]:not(.navcall){display:inline-flex;align-items:center;min-height:var(--tap)}
/* ============================================================================
   stahl-kupfer — SHARED LANGUAGE, PART 2.
   Section + layout primitives and the widget set, all drawn from the recon
   catalogue (`_recon-catalogue.md`). Neutral, composable bricks — never finished
   templates. Every value is a token; nothing here introduces a new theme value.
   ========================================================================== */

/* ------------------------------------------------------------------------- */
/*  A · THE SEAM HELPERS — the overlap grammar, made hard to get wrong.       */
/*  Rule 1 of the style is "every other band has exactly one element crossing  */
/*  its boundary". Two traps make it easy to botch by hand: the crossing       */
/*  element must be the FIRST or LAST child of its band (pulling up a mid-     */
/*  section element just collides with the heading above it), and it needs a   */
/*  z-index or the next band paints over it. These encode both.               */
/* ------------------------------------------------------------------------- */
.seam-up{position:relative;z-index:2;margin-top:calc(-1 * var(--seam,54px))}
.seam-down{position:relative;z-index:2;margin-bottom:calc(-1 * var(--seam,54px))}
.seam-sm{--seam:32px} .seam-lg{--seam:82px}
/* A .seam-down is only half the mechanism and on its own it does NOTHING: the pull is
   smaller than the band's own bottom padding, so the element never reaches the seam.
   It takes THREE classes, and all three are required:
     .section--hang   on the band the element hangs OUT of  (drops its bottom padding)
     .seam-down       on that band's LAST child
     .section--catch  on the following band                 (makes room for the overhang)
   The .seam-up counterpart needs only .seam-up on the next band's FIRST child, plus
   enough bottom padding on the band above for the element to sit in. */
.section--hang{padding-bottom:0}
.section--catch{padding-top:calc(clamp(58px,7.2vw,104px) + var(--seam,54px))}
@media(max-width:699px){
  /* below 700px the bands are too short for a crossing element to read as
     deliberate — it just looks like a mistake. Collapse them. */
  .seam-up,.seam-down{margin-top:0;margin-bottom:0}
  .section--catch{padding-top:clamp(58px,7.2vw,104px)}
}

/* ------------------------------------------------------------------------- */
/*  B · SECTION + LAYOUT PRIMITIVES                                           */
/* ------------------------------------------------------------------------- */

/* B1 · DIPTYCH — zero-gutter two-column band, each half carrying its OWN fill,
   meeting at the exact centreline with no divider. Off-centre text comes from
   asymmetric percentage padding, so it stays optically centred at every width
   with no media query for position. (hotlock: three visually different bands
   from one grid rule.) */
.diptych{display:grid;grid-template-columns:minmax(0,1fr)}
.diptych__half{padding:clamp(38px,5vw,72px) var(--gut)}
@media(min-width:900px){
  .diptych{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}
  .diptych__half{padding:clamp(52px,6vw,92px) 8% clamp(52px,6vw,92px) 14%}
  .diptych__half+.diptych__half{padding:clamp(52px,6vw,92px) 14% clamp(52px,6vw,92px) 8%}
}
.diptych__half--dark{background:var(--dark);color:var(--dark-muted)}
.diptych__half--dark :where(h2,h3,h4){color:#fff}
.diptych__half--steel{background:var(--steel)}
.diptych__half--primary{background:var(--primary);color:var(--on-dark)}
.diptych__half--primary :where(h2,h3,h4){color:#fff}
/* steel ground so a slow or failed image reads as an empty slot, not a black void */
.diptych__half--media{padding:0;position:relative;min-height:320px;background:var(--steel)}
.diptych__half--media img,.diptych__half--media .imgph{
  position:absolute;inset:0;width:100%;height:100%;object-fit:cover;border-radius:0}

/* B2 · LEDGER — one hairline frame around rows whose narrow cell is a label tab
   and whose wide cell carries the content. A ruled register reads as a record;
   a card grid reads as marketing. Right for Öffnungszeiten, coverage, liability
   splits, credential lists. (dexon: 20% white label cell / 80% filled cell.) */
.ledger{border:1px solid var(--line);background:var(--surface)}
.ledger__row{display:grid;grid-template-columns:minmax(0,1fr);border-top:1px solid var(--line)}
.ledger__row:first-child{border-top:0}
.ledger__k{padding:16px clamp(16px,2vw,24px);font-weight:700;color:var(--head);
  background:var(--surface-alt);font-size:16.5px;display:flex;align-items:center}
.ledger__v{padding:16px clamp(16px,2vw,24px);color:var(--muted);font-size:16.8px;line-height:1.55}
@media(min-width:700px){
  .ledger__row{grid-template-columns:minmax(180px,.26fr) 1fr}
  .ledger__k{border-right:1px solid var(--line)}
}
.ledger--dark{border-color:var(--dark-line);background:var(--dark-2)}
.ledger--dark .ledger__row{border-top-color:var(--dark-line)}
.ledger--dark .ledger__k{background:var(--dark-3);color:#fff;border-right-color:var(--dark-line)}
.ledger--dark .ledger__v{color:var(--dark-muted)}

/* B3 · SIDE RAIL — a sticky column against a single-file stack. The spine of a
   long service page: the number stays reachable through explanatory copy.
   Single-viewport sticky only — never a multi-viewport scroll sequence. */
.rail{display:grid;gap:clamp(28px,4vw,54px);grid-template-columns:1fr;align-items:start}
@media(min-width:1000px){
  .rail{grid-template-columns:minmax(0,.4fr) minmax(0,1fr)}
  .rail__side{position:sticky;top:108px}
  .rail--right .rail__side{order:2}
}
.rail__main{display:grid;gap:clamp(30px,3.6vw,52px)}

/* B4 · OFFSET GRID — hand-placed masonry rhythm with zero JS and no library.
   Every nth item drops, so the grid reads composed rather than tabulated.
   (ekvator built this with presentational spacer divs; nth-child is cleaner.) */
.offgrid{display:grid;gap:clamp(16px,1.8vw,26px);grid-template-columns:minmax(0,1fr);align-items:start}
@media(min-width:640px){
  .offgrid{grid-template-columns:repeat(2,minmax(0,1fr))}
  .offgrid>*:nth-child(2n){margin-top:clamp(20px,3vw,44px)}
}
@media(min-width:980px){
  .offgrid--3{grid-template-columns:repeat(3,minmax(0,1fr))}
  .offgrid--3>*:nth-child(2n){margin-top:0}
  .offgrid--3>*:nth-child(3n-1){margin-top:clamp(24px,3.4vw,52px)}
}

/* B5 · PEEK RAIL — user-driven horizontal scroll with the next card bleeding off
   the edge as the affordance. scroll-snap, NOT an auto-carousel: nothing moves
   until the reader moves it, and every card is keyboard-reachable. */
.peek{display:flex;gap:clamp(14px,1.6vw,22px);overflow-x:auto;scroll-snap-type:x mandatory;
  padding-bottom:14px;scrollbar-width:thin}
.peek>*{flex:0 0 clamp(250px,74vw,330px);scroll-snap-align:start}
@media(min-width:760px){.peek>*{flex-basis:330px}}
.peek::-webkit-scrollbar{height:8px}
.peek::-webkit-scrollbar-thumb{background:var(--line-strong);border-radius:var(--pill)}
.peek::-webkit-scrollbar-track{background:var(--surface-alt)}

/* B6 · MOSAIC — one tall image beside two stacked halves. An asymmetric 1+2
   composition out of a plain two-column grid. */
.mosaic{display:grid;gap:14px;grid-template-columns:minmax(0,1fr)}
@media(min-width:700px){.mosaic{grid-template-columns:minmax(0,1.25fr) minmax(0,1fr)}}
.mosaic__col{display:grid;gap:14px;grid-template-rows:1fr 1fr}
.mosaic .imgph{height:100%}
.mosaic--flip>*:first-child{order:2}

/* B7 · COMPARE — a static two-up with a shared centre rule. This is the LEGAL
   form of a before/after: the source templates build that with <input
   type="range">, which the validator hard-fails. Nothing here is interactive. */
.compare{display:grid;grid-template-columns:minmax(0,1fr);border:1px solid var(--line);
  background:var(--surface)}
.compare__side{padding:clamp(22px,2.6vw,34px)}
.compare__side+.compare__side{border-top:1px solid var(--line)}
@media(min-width:760px){
  .compare{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}
  .compare__side+.compare__side{border-top:0;border-left:1px solid var(--line)}
}
.compare__tag{display:inline-flex;align-items:center;gap:9px;margin-bottom:13px;
  font-size:12.5px;font-weight:800;letter-spacing:.13em;text-transform:uppercase}
.compare__side--a .compare__tag{color:var(--success)}
.compare__side--b .compare__tag{color:var(--danger)}

/* B8 · TIMELINE — vertical connected steps. Order matters, so a stepper, not a
   grid. The connector is a pseudo-element so no extra markup carries it. */
.timeline{list-style:none;display:grid;gap:clamp(20px,2.4vw,32px);counter-reset:tl}
.timeline>li{position:relative;padding-left:64px;counter-increment:tl}
.timeline>li::before{content:counter(tl,decimal-leading-zero);position:absolute;left:0;top:0;
  width:44px;height:44px;border-radius:50%;display:grid;place-items:center;
  background:var(--surface);color:var(--primary);box-shadow:inset 0 0 0 1.5px var(--line-strong);
  font:800 14px/1 var(--f-num);letter-spacing:.02em}
.timeline>li::after{content:"";position:absolute;left:21.5px;top:52px;bottom:calc(-1 * clamp(20px,2.4vw,32px));
  width:1px;background:var(--line)}
.timeline>li:last-child::after{display:none}
.section--dark .timeline>li::before{background:var(--dark-2);color:var(--cta-light);
  box-shadow:inset 0 0 0 1.5px var(--dark-line)}
.section--dark .timeline>li::after{background:var(--dark-line)}

/* B9 · STEPPER — the horizontal counterpart, for a sibling page that must not
   repeat the timeline's shape. */
.stepper{list-style:none;display:grid;gap:clamp(18px,2vw,26px);grid-template-columns:minmax(0,1fr);
  counter-reset:st}
@media(min-width:820px){.stepper{grid-template-columns:repeat(4,minmax(0,1fr))}}
.stepper>li{counter-increment:st;position:relative;padding-top:56px}
.stepper>li::before{content:counter(st,decimal-leading-zero);position:absolute;left:0;top:0;
  width:42px;height:42px;border-radius:var(--r-sm);display:grid;place-items:center;
  background:var(--primary);color:#fff;font:800 14px/1 var(--f-num)}
.stepper>li::after{content:"";position:absolute;left:52px;top:20px;right:0;height:1px;
  background:var(--line)}
.stepper>li:last-child::after{display:none}
@media(max-width:819px){.stepper>li::after{display:none}}

/* B10 · NOTICE — a real callout, never a paragraph. --danger is the safety
   register (gas, electrical, 110/112); --info carries the copper. */
.notice{border:1px solid var(--danger);border-left-width:5px;background:var(--danger-tint);
  padding:clamp(22px,2.6vw,34px);border-radius:var(--r-sm)}
.notice__head{display:flex;align-items:center;gap:13px;margin-bottom:12px}
.notice__ic{width:40px;height:40px;flex:none;border-radius:50%;display:grid;place-items:center;
  background:var(--danger);color:#fff}
.notice__ic svg{width:22px;height:22px;stroke:currentColor}
.notice h2,.notice h3,.notice .h3{color:var(--danger)}
.notice--info{border-color:var(--cta);background:var(--cta-tint)}
.notice--info .notice__ic{background:var(--cta)}
.notice--info :where(h2,h3,.h3){color:var(--cta-ink)}

/* B11 · STAT RAIL — static figures only. The sources animate these with
   odometers; counters are on the banlist and an invented figure breaks iron
   rule 4, so a figure appears here only if the partner can defend it. */
.stats{display:grid;gap:1px;background:var(--line);border:1px solid var(--line);
  grid-template-columns:repeat(2,minmax(0,1fr))}
@media(min-width:820px){.stats{grid-template-columns:repeat(4,minmax(0,1fr))}}
.stats>div{background:var(--surface);padding:clamp(20px,2.4vw,30px)}
.stats b{display:block;font-size:clamp(28px,3.4vw,40px);font-weight:800;color:var(--primary);
  letter-spacing:-.025em;font-variant-numeric:tabular-nums;line-height:1.05}
.stats span{display:block;margin-top:7px;font-size:16px;color:var(--muted);line-height:1.4}
.section--dark .stats{background:var(--dark-line);border-color:var(--dark-line)}
.section--dark .stats>div{background:var(--dark-2)}
.section--dark .stats b{color:var(--cta-light)}
.section--dark .stats span{color:var(--dark-muted)}

/* B12 · INDEX ROWS — the hover-flood service index. Three independent sources
   converged on this shape, and it is the answer to "never a bare <ul>": a list
   that is also a gallery. Four coordinated changes, all pure CSS. */
.rows{list-style:none;border-top:1px solid var(--line)}
.rows>li{position:relative;isolation:isolate;border-bottom:1px solid var(--line);
  transition:border-color var(--dur) var(--ease)}
.rows__flood{position:absolute;inset:auto 0 0 0;height:0;z-index:-1;background:var(--primary);
  transition:height .34s var(--ease)}
.rows>li:hover .rows__flood,.rows>li:focus-within .rows__flood{height:100%}
.rows__link{display:grid;gap:6px 20px;align-items:center;padding:clamp(20px,2.4vw,30px) 0;
  text-decoration:none;color:inherit;min-height:var(--tap)}
.rows__link::after{content:"";position:absolute;inset:0;z-index:1}
.rows>li:hover :where(.rows__t,.rows__d),.rows>li:focus-within :where(.rows__t,.rows__d){color:#fff}
.rows__t{font-size:clamp(19px,1.6vw,23px);font-weight:700;color:var(--head);
  transition:color var(--dur) var(--ease)}
.rows__d{font-size:16.8px;color:var(--muted);line-height:1.55;max-width:62ch;
  transition:color var(--dur) var(--ease)}
.rows__n{font:800 13px/1 var(--f-num);color:var(--muted);letter-spacing:.08em}
.rows__thumb{position:absolute;right:clamp(16px,2.4vw,36px);top:50%;translate:0 -50%;
  width:180px;aspect-ratio:16/11;overflow:hidden;border-radius:var(--r-sm);
  opacity:0;scale:.86;transition:opacity .3s var(--ease),scale .3s var(--ease);
  pointer-events:none;display:none}
@media(min-width:1040px){
  .rows__thumb{display:block}
  .rows__link{padding-right:230px}
  .rows>li:hover .rows__thumb,.rows>li:focus-within .rows__thumb{opacity:1;scale:1}
}

/* B13 · BAND STRIP — a full-bleed accent rule between sections, carrying the
   service vocabulary. The source MARQUEES this; continuous motion is banned, so
   it is static and reads as a hard divider. */
.strip{background:var(--cta);padding:22px 0}
.strip ul{list-style:none;display:flex;flex-wrap:wrap;justify-content:center;
  align-items:center;gap:12px clamp(16px,2vw,26px)}
.strip li{color:#fff;font-size:clamp(15px,1.5vw,19px);font-weight:800;letter-spacing:.06em;
  text-transform:uppercase;display:inline-flex;align-items:center;gap:12px clamp(16px,2vw,26px)}
.strip li:not(:last-child)::after{content:"";width:26px;height:11px;flex:none;background:#fff;
  opacity:.62;
  clip-path:polygon(0 100%,0 42%,20% 42%,20% 8%,40% 8%,40% 58%,60% 58%,60% 22%,80% 22%,80% 70%,100% 70%,100% 100%)}
.strip--dark{background:var(--dark)}
.strip--steel{background:var(--steel)}
.strip--steel li{color:var(--head)}
.strip--steel li:not(:last-child)::after{background:var(--cta);opacity:1}

/* ------------------------------------------------------------------------- */
/*  C · WIDGETS                                                              */
/* ------------------------------------------------------------------------- */

/* C1 · numeral pill — the step marker. Reads better than a bare digit or a
   filled circle, and it is the right shape for a numbered flow. */
.numpill{display:inline-flex;align-items:center;justify-content:center;min-width:44px;
  min-height:30px;padding:5px 14px;border-radius:var(--pill);border:1px solid var(--line);
  background:var(--surface-alt);color:var(--primary);font:800 13.5px/1 var(--f-num);
  letter-spacing:.04em}
.numpill--cta{background:var(--cta);border-color:var(--cta);color:#fff}
.section--dark .numpill{background:var(--dark-2);border-color:var(--dark-line);color:var(--cta-light)}

/* C2 · seal — a circular CREDENTIAL mark, sized to straddle a band seam.
   Deliberately NOT a rating badge: the sources put "4.5 (1,200 reviews)" in this
   slot, and a rating may only appear if it is real, attributable and evidenced. */
.seal{width:clamp(120px,12vw,148px);height:clamp(120px,12vw,148px);border-radius:50%;
  background:var(--cta);color:#fff;display:grid;place-content:center;justify-items:center;
  gap:3px;text-align:center;padding:12px;border:6px solid var(--surface)}
.seal svg{width:25px;height:25px;stroke:currentColor}
.seal b{font-size:12.5px;font-weight:800;line-height:1.15}
/* opacity:.92 white over copper blends to #f9f1ed = 4.35:1 — under AA for 11px text, and
   axe flags every seal on the page. Same trap the .callbtn .cap comment names: never dim
   text on the accent fill to "soften" it. Full white is 4.86:1. */
.seal i{font-style:normal;font-size:11px;font-weight:700;letter-spacing:.12em;
  text-transform:uppercase}
.seal--on-dark{border-color:var(--dark)}
.seal--primary{background:var(--primary)}

/* C3 · caption chip welded to an image corner — one widget, two content types
   (a Stadtteil on a job photo, a date on an article), which is where a gallery
   and a blog grid start reading as one family. */
.capchip{position:absolute;left:0;bottom:0;z-index:2;background:var(--surface);color:var(--head);
  padding:9px 15px;font-size:14px;font-weight:800;letter-spacing:.05em;text-transform:uppercase;
  border-radius:0 var(--r-sm) 0 0;max-width:calc(100% - 22px)}
.capchip--cta{background:var(--cta);color:#fff}
.capchip--tr{left:auto;right:0;bottom:auto;top:0;border-radius:0 0 0 var(--r-sm)}

/* C4 · avatar cluster ending in a quote mark — the only social-proof widget in
   the whole corpus that carries zero numbers and zero stars, which is why it is
   the one that ports into a German trade site untouched. */
.avatars{display:flex;align-items:center;flex-wrap:wrap}
.avatars img,.avatars .avatars__q{width:56px;height:56px;border-radius:50%;object-fit:cover;
  border:3px solid var(--surface);flex:none}
.avatars>*+*{margin-left:-15px}
.avatars__q{background:var(--cta);color:#fff;display:grid;place-items:center}
.avatars__q svg{width:22px;height:22px}
.section--dark .avatars img,.section--dark .avatars .avatars__q{border-color:var(--dark)}

/* C5 · quote card — a speech card with a tail. No stars, no counts, no rating. */
.quote{position:relative;background:var(--surface);border:1px solid var(--line);
  border-radius:var(--r);padding:clamp(22px,2.4vw,30px)}
.quote p{font-size:17.2px;line-height:1.62;color:var(--text)}
.quote__by{margin-top:16px;padding-top:14px;border-top:1px solid var(--line);
  font-size:14px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;color:var(--cta-ink)}
.section--dark .quote{background:var(--dark-2);border-color:var(--dark-line)}
.section--dark .quote p{color:var(--on-dark)}
.section--dark .quote__by{color:var(--cta-light);border-top-color:var(--dark-line)}

/* C6 · flanked hairline — centred text with two rules growing to fill the row.
   Three declarations, and nothing like the usual border-top. */
.hrule{display:flex;align-items:center;gap:18px;font-size:14px;font-weight:800;
  letter-spacing:.14em;text-transform:uppercase;color:var(--muted)}
.hrule::before,.hrule::after{content:"";flex:1;height:1px;background:var(--line)}
/* the LABEL needs the dark-band colour too, not only the two rules — --muted on --dark
   is 2.49:1. Every widget below that paints text in --muted needs the same partner rule. */
.section--dark .hrule{color:var(--dark-muted)}
.section--dark .hrule::before,.section--dark .hrule::after{background:var(--dark-line)}

/* C7 · colophon chip — a bordered circle holding one letter, beside a name.
   Pure editorial garnish; the right home for a Meister/Innung mark in a hero. */
.colophon{display:inline-flex;align-items:center;gap:10px;font-size:12.5px;font-weight:700;
  letter-spacing:.05em;color:var(--muted)}
.colophon i{font-style:normal;width:22px;height:22px;flex:none;border-radius:50%;
  border:1.6px solid var(--line-strong);display:grid;place-items:center;
  font:800 11px/1 var(--f-num);color:var(--primary)}
.section--dark .colophon{color:var(--dark-muted)}
.section--dark .colophon i{border-color:var(--dark-line);color:var(--cta-light)}

/* C8 · double-framed card — an outer tinted frame at 10px padding with an inner
   hairline. Two rules, and every card stops looking flat. */
.framed{background:var(--surface-alt);border-radius:var(--r-lg);padding:10px}
.framed__in{background:var(--surface);border:1px solid var(--line);border-radius:var(--r);
  padding:clamp(20px,2.2vw,28px);height:100%}
.section--dark .framed{background:var(--dark-3)}
.section--dark .framed__in{background:var(--dark-2);border-color:var(--dark-line)}

/* C9 · expanding hover pill — an arrow square at rest that grows into a labelled
   button. max-width (not width) so there is no layout shift. */
.hpill{display:inline-flex;align-items:center;gap:0;min-height:var(--tap);
  border-radius:var(--pill);background:var(--primary);color:#fff;text-decoration:none;
  padding:6px;overflow:hidden}
.hpill__ic{width:32px;height:32px;flex:none;display:grid;place-items:center}
.hpill__ic svg{width:18px;height:18px;stroke:currentColor}
.hpill__t{max-width:0;opacity:0;white-space:nowrap;overflow:hidden;font-weight:700;font-size:16px;
  transition:max-width .34s var(--ease),opacity .28s var(--ease),padding .34s var(--ease);padding:0}
.hpill:hover,.hpill:focus-visible{color:#fff;background:var(--cta)}
.hpill:hover .hpill__t,.hpill:focus-visible .hpill__t{max-width:16rem;opacity:1;padding:0 12px 0 4px}

/* C10 · eyebrow variant D — a bordered chip with a solid accent disc flush in
   its left cap. Gives a section a coloured anchor without a coloured band. */
.eyebrow--cap{border:1.5px solid var(--line);border-radius:var(--pill);
  padding:4px 16px 4px 4px;color:var(--primary);letter-spacing:.11em;gap:11px}
.eyebrow--cap::before{width:28px;height:28px;border-radius:50%;background:var(--cta);
  clip-path:none}
.section--dark .eyebrow--cap{border-color:var(--dark-line);color:#fff}

/* C11 · crushed numeral — one deliberate break in the type system. A token-driven
   design with no exceptions reads machine-made; exactly one exception reads
   art-directed. Use it ONCE per page, never twice.
   THE NUMERAL IS DECORATION, AND THE MARKUP HAS TO SAY SO. At --line it carries
   1.41:1 (--dark-4 on --dark: 1.33:1) and could never clear AA as text — 3:1 is the
   floor even for display sizes. So the digits are passed in `data-n` and painted by the
   pseudo-element, the same move .timeline already makes for its step counters: a graphic
   in numeral form, not text a reader must decipher. Meaning belongs in the heading
   beside it. Written as <span class="bignum" data-n="01" aria-hidden="true"></span>. */
.bignum{font-size:clamp(56px,8vw,104px);font-weight:800;line-height:.72;letter-spacing:-.04em;
  color:var(--line);font-variant-numeric:tabular-nums;display:block}
.bignum::before{content:attr(data-n)}
.bignum--cta{color:var(--cta)}
.section--dark .bignum{color:var(--dark-4)}

/* C12 · hours rows — opening times as a real record, not a paragraph. */
.hours{list-style:none;display:grid;gap:0}
.hours li{display:flex;justify-content:space-between;gap:18px;padding:12px 0;
  border-bottom:1px solid var(--line);font-size:16.8px}
.hours li:last-child{border-bottom:0}
.hours b{color:var(--head);font-weight:700}
.hours span{color:var(--muted);text-align:right}
.section--dark .hours li{border-bottom-color:var(--dark-line)}
.section--dark .hours b{color:#fff}
.section--dark .hours span{color:var(--dark-muted)}

/* C13 · breadcrumbs */
.crumbs{list-style:none;display:flex;flex-wrap:wrap;align-items:center;gap:2px 4px;font-size:15.5px}
.crumbs li{display:inline-flex;align-items:center;gap:4px;color:var(--muted)}
.crumbs li+li::before{content:"";width:6px;height:6px;flex:none;border-right:1.5px solid var(--line-strong);
  border-top:1.5px solid var(--line-strong);rotate:45deg;margin-right:4px}
.crumbs a{display:inline-flex;align-items:center;min-height:var(--tap);min-width:var(--tap);
  color:var(--muted);text-decoration:none}
.crumbs a:hover{color:var(--cta-ink);text-decoration:underline}
.crumbs [aria-current="page"]{color:var(--head);font-weight:700}

/* C14 · in-page index — the sticky rail's table of contents. */
.toc{list-style:none;display:grid;gap:2px;border-left:2px solid var(--line)}
.toc a{display:flex;align-items:center;min-height:var(--tap);padding:6px 0 6px 16px;
  margin-left:-2px;border-left:2px solid transparent;color:var(--muted);text-decoration:none;
  font-size:16.5px;transition:color var(--dur) var(--ease),border-color var(--dur) var(--ease)}
.toc a:hover,.toc a[aria-current="true"]{color:var(--primary);border-left-color:var(--cta);
  font-weight:700}

/* C15 · tab switcher — buttons with the real roles. The sources build this from
   radio inputs; any <input> is a hard validator fail, and site.js already wires
   [data-switcher] with roving focus. */
.tabs{display:grid;gap:clamp(24px,3vw,44px);grid-template-columns:minmax(0,1fr);align-items:start}
@media(min-width:900px){.tabs{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}}
.tabs__list{display:grid;gap:0;list-style:none}
/* The source dims the inactive tab with opacity:.45. That cannot be rescued: --muted at
   .45 over white is 2.07:1, and even at .9 it is still 4.63:1 on --steel — an opacity
   veil scales the CONTRAST down along with the colour, so no value both dims visibly and
   clears AA on every band this style ships. The inactive state is therefore carried by
   colour and border, the way the rest of the style carries state. */
.tabs__btn{display:block;width:100%;text-align:left;background:none;border:0;cursor:pointer;
  padding:18px 0;border-bottom:1px solid var(--line);color:inherit;font:inherit;
  min-height:var(--tap);transition:color var(--dur) var(--ease),border-color var(--dur) var(--ease)}
.tabs__btn:hover{border-bottom-color:var(--line-strong)}
.tabs__btn[aria-selected="true"]{border-bottom-color:var(--cta);border-bottom-width:2px}
.tabs__btn b{display:block;font-size:clamp(18px,1.5vw,21px);font-weight:700;color:var(--muted);
  margin-bottom:5px;transition:color var(--dur) var(--ease)}
.tabs__btn:hover b,.tabs__btn[aria-selected="true"] b{color:var(--head)}
.tabs__btn span{display:block;font-size:16.4px;color:var(--muted);line-height:1.55}
.section--dark .tabs__btn b,.section--dark .tabs__btn span{color:var(--dark-muted)}
.section--dark .tabs__btn:hover b,.section--dark .tabs__btn[aria-selected="true"] b{color:#fff}
.tabs__panel[hidden]{display:none}

/* C16 · FAQ accordion — native <details>, so it works with JS off; site.js only
   adds the one-open-at-a-time behaviour. */
.faq{display:grid;gap:12px}
.faq details{border:1px solid var(--line-strong);border-radius:var(--r-sm);
  background:var(--surface);overflow:hidden}
.faq summary{display:flex;align-items:center;gap:14px;justify-content:space-between;
  padding:18px clamp(16px,2vw,24px);min-height:var(--tap);cursor:pointer;list-style:none;
  font-size:clamp(17px,1.4vw,19.5px);font-weight:700;color:var(--head)}
.faq summary::-webkit-details-marker{display:none}
.faq summary::after{content:"";width:12px;height:12px;flex:none;
  border-right:2px solid var(--cta);border-bottom:2px solid var(--cta);rotate:45deg;
  translate:0 -3px;transition:rotate var(--dur) var(--ease)}
.faq details[open] summary::after{rotate:-135deg;translate:0 3px}
.faq details[open]{border-color:var(--cta)}
.faq__a{padding:0 clamp(16px,2vw,24px) 20px;color:var(--muted);font-size:17px;line-height:1.62}
.section--dark .faq details{background:var(--dark-2);border-color:var(--dark-line)}
.section--dark .faq summary{color:#fff}
.section--dark .faq summary::after{border-color:var(--cta-light)}

/* C17 · check / icon list — the default treatment for factors, symptoms and
   benefits. Never a <ul> with the bullets deleted. */
.iclist{list-style:none;display:grid;gap:clamp(14px,1.7vw,22px)}
.iclist--2{grid-template-columns:minmax(0,1fr)}
@media(min-width:700px){.iclist--2{grid-template-columns:repeat(2,minmax(0,1fr))}}
.iclist li{display:grid;grid-template-columns:auto 1fr;gap:14px;align-items:start}
.iclist__ic{width:34px;height:34px;flex:none;border-radius:50%;display:grid;place-items:center;
  background:var(--primary-subtle);color:var(--primary)}
.iclist__ic svg{width:18px;height:18px;stroke:currentColor;stroke-width:2.2}
.iclist--cta .iclist__ic{background:var(--cta);color:#fff}
.iclist b{display:block;color:var(--head);font-weight:700;font-size:17.5px;margin-bottom:3px}
.iclist p{font-size:16.6px;color:var(--muted);line-height:1.55}
.section--dark .iclist__ic{background:var(--dark-3);color:var(--cta-light)}
.section--dark .iclist b{color:#fff}
.section--dark .iclist p{color:var(--dark-muted)}

/* C18 · media frame — an image with the notch, a seam badge slot and a caption
   chip, so a photo is a composed object rather than a rectangle. */
.frame{position:relative}
.frame__seal{position:absolute;left:50%;bottom:0;translate:-50% 50%;z-index:3}
.frame__seal--r{left:auto;right:clamp(16px,4vw,54px);translate:0 50%}

/* ==========================================================================
   D · THIS SITE'S OWN LAYER — the hero family, the WordPress seams, and the
   defect classes an audit found AFTER a green validator. Everything here is a
   correctness floor or a shared primitive; no page copy, no new theme value
   beyond the :root set above.
   ========================================================================== */

/* --------------------------------------------------------------------------
   D0 · WordPress structural seams.
   WP wraps every rendered template part in its own element, so <main> is opened
   and closed AROUND the part blocks (see the render_block filter in
   functions.php) and must not carry a layout of its own.
   -------------------------------------------------------------------------- */
main#main{display:block}
.wp-block-template-part{display:contents}

/* German compounds set the page's minimum width when they cannot break.
   `hyphens` on headings alone is not enough: a compound in BODY copy
   (Barrierefreiheitsstaerkungsgesetz) pushes the document past a 320px viewport. */
body{overflow-wrap:break-word}
p,li,td,th,figcaption,summary,dd,dt{hyphens:auto}

/* Prose links must be underlined (axe: link-in-text-block). Components own their
   own affordance and are excluded by name, exactly as the hover rule above is. */
p a,li a:not(.chip):not(.btn):not(.callbtn):not(.rows__link):not(.hpill),
.faq__a a,.lead a,dd a{text-decoration:underline;text-underline-offset:.18em}

/* A chip carries no underline, so its container must be identifiable
   non-textually: --line is 1.19:1 against --surface and distinguishes nothing.
   Every district chip here is a real link, so it takes the 3:1-gated border —
   computed, not asserted. */
.chip{border-color:var(--line-strong);border-width:1.5px;min-height:var(--tap)}
.chip--solid{border-color:var(--primary-subtle)}
.section--dark .chip{border-color:var(--dark-line-2)}

/* Breadcrumb links are measured as tap targets because .crumbs is a <nav>.
   min-height alone leaves a short label (Start = 36px) under the floor. */
.crumbs a{min-width:var(--tap);justify-content:center;padding-inline:6px}

/* --------------------------------------------------------------------------
   D1 · BAND-INK CONTAINMENT for a DARK PANEL sitting in a LIGHT band.
   The style's signature move is "drop a dark card into a light band, and make
   that dark card the phone card". Such a panel is dark by its OWN background,
   NOT by sitting inside .section--dark — so every `.section--dark X` rule above
   silently does not apply and its descendants render dark-on-dark. `.on-dark`
   is that missing partner. Adding a new light-surfaced primitive means adding
   it here too.
   -------------------------------------------------------------------------- */
.on-dark{background:var(--dark);color:var(--dark-muted)}
.on-dark :where(h1,h2,h3,h4,.h3,.stitle,.display,strong,b){color:#fff}
.on-dark .lead,.on-dark p{color:var(--on-dark)}
.on-dark .eyebrow{color:var(--cta-light)}
.on-dark .pinrule{border-top-color:var(--cta-light)}
.on-dark .pinrule i{background:var(--cta-light)}
.on-dark .telbig{color:#fff}
.on-dark .telbig:hover{color:var(--cta-light)}
.on-dark .telbig svg{stroke:var(--cta-light)}
.on-dark .ibadge{background:var(--dark-3);color:var(--cta-light)}
.on-dark .iclist__ic{background:var(--dark-3);color:var(--cta-light)}
.on-dark .iclist b{color:#fff}
.on-dark .iclist p{color:var(--dark-muted)}
.on-dark .numpill{background:var(--dark-2);border-color:var(--dark-line);color:var(--cta-light)}
.on-dark .chip{background:var(--dark-3);border-color:var(--dark-line-2);color:var(--on-dark)}
.on-dark .hrule{color:var(--dark-muted)}
.on-dark .hrule::before,.on-dark .hrule::after{background:var(--dark-line)}
.on-dark .colophon{color:var(--dark-muted)}
.on-dark .colophon i{border-color:var(--dark-line);color:var(--cta-light)}
.on-dark .timeline>li::before{background:var(--dark-2);color:var(--cta-light);
  box-shadow:inset 0 0 0 1.5px var(--dark-line)}
.on-dark .timeline>li::after{background:var(--dark-line)}
/* A LINK inside a coloured slab that says `color:inherit` inherits the BAND's
   colour, not the slab's. Name the colour. */
.on-dark a:not(.btn):not(.callbtn):not(.calltab):not(.chip):not(.telbig){color:var(--cta-light)}
.on-dark :where(a,button,summary):focus-visible{
  box-shadow:0 0 0 3px var(--dark),0 0 0 6px var(--cta-light)}

/* --------------------------------------------------------------------------
   D2 · SEAM MECHANICS — the two ways an overlap silently renders as zero.
   (a) The receiving band's own top padding swallows the 54px pull, so the child
       lands below the seam and crosses nothing.
   (b) With padding-top:0 the child's negative margin then COLLAPSES THROUGH the
       parent: the whole band moves up, its background boundary travels with the
       element, and again nothing crosses. `display:flow-root` establishes a BFC
       and stops the collapse (measured on a prior build: -18px to +64px).
   Encoded with :has() so forgetting the explicit class cannot kill the overlap.
   -------------------------------------------------------------------------- */
.section:has(> .wrap > .seam-up:first-child),
.section:has(> .seam-up:first-child){padding-top:0;display:flow-root}
.section--hang{display:flow-root}
.section--catch{display:flow-root}
@media(max-width:699px){
  .section:has(> .wrap > .seam-up:first-child),
  .section:has(> .seam-up:first-child){padding-top:clamp(58px,7.2vw,104px)}
}

/* --------------------------------------------------------------------------
   D3 · THE HERO FAMILY. The reference keeps its heroes page-local; a 37-page
   site needs them shared, so the VARIANTS live here and each page picks one.
   Variety is the point: a Notdienst page and a Ratgeber page must not open the
   same way (layout-variety.md).
   -------------------------------------------------------------------------- */
.hero{position:relative;padding:clamp(46px,6vw,86px) 0 clamp(46px,5.4vw,78px);
  background:var(--surface);display:flow-root}
.hero .display{margin-bottom:18px}
.hero .lead{max-width:60ch}
.hero__actions{display:flex;flex-wrap:wrap;gap:14px;margin-top:26px;align-items:center}
.hero__meta{display:flex;flex-wrap:wrap;gap:10px 22px;margin-top:22px;
  font-size:16px;color:var(--muted)}
.hero__meta span{display:inline-flex;align-items:center;gap:9px}
.hero__meta svg{width:18px;height:18px;stroke:var(--cta-ink);flex:none}
.hero .crumbs{margin-bottom:20px}

/* V1 · local-context: copy left, a real photo right, brushed-steel ground. Site default. */
.hero--context{background:
  repeating-linear-gradient(90deg,rgba(107,33,168,.030) 0 1px,rgba(255,255,255,0) 1px 6px),
  repeating-linear-gradient(90deg,rgba(255,255,255,.42) 0 1px,rgba(255,255,255,0) 1px 14px),
  var(--steel)}
.hero__grid{display:grid;gap:clamp(28px,4vw,58px);align-items:center;
  grid-template-columns:minmax(0,1fr)}
@media(min-width:960px){.hero--context .hero__grid{grid-template-columns:minmax(0,1.06fr) minmax(0,.94fr)}}

/* V2 · solid panel: one calm column, no photo. Editorial and legal-calm pages. */
.hero--panel{background:var(--surface-alt)}
.hero--panel .wrap{max-width:980px}

/* V3 · emergency bar: darkest band, number above the fold, tightest padding. */
.hero--emergency{background:var(--dark);color:var(--dark-muted);
  padding:clamp(34px,4.4vw,62px) 0 clamp(34px,4vw,58px)}

/* V4 · split: copy beside a self-contained block (phone block, checklist, seal). */
@media(min-width:940px){.hero--split .hero__grid{grid-template-columns:minmax(0,1.15fr) minmax(0,.85fr)}}

/* V5 · diptych: two halves, each its own fill, meeting on the centreline. */
.hero--diptych{padding:0;background:var(--surface)}

/* V6 · dark situation band: calm-serious, for the problem pages. */
.hero--situation{background:var(--dark);color:var(--dark-muted);
  padding:clamp(42px,5.2vw,74px) 0}

/* the dark-hero ink set, shared by V3 and V6 */
.hero--emergency .display,.hero--situation .display{color:#fff}
.hero--emergency .display .l2,.hero--situation .display .l2{color:var(--cta-light)}
.hero--emergency .lead,.hero--situation .lead{color:var(--on-dark)}
.hero--emergency .crumbs li,.hero--emergency .crumbs a,
.hero--situation .crumbs li,.hero--situation .crumbs a{color:var(--dark-muted)}
.hero--emergency .crumbs [aria-current="page"],
.hero--situation .crumbs [aria-current="page"]{color:#fff}
.hero--emergency .crumbs li+li::before,
.hero--situation .crumbs li+li::before{border-color:var(--dark-line-2)}
.hero--emergency .hero__meta,.hero--situation .hero__meta{color:var(--dark-muted)}
.hero--emergency .hero__meta svg,.hero--situation .hero__meta svg{stroke:var(--cta-light)}
.hero--emergency .eyebrow,.hero--situation .eyebrow{color:var(--cta-light)}
.hero--emergency a:not(.btn):not(.callbtn):not(.calltab):not(.chip):not(.telbig),
.hero--situation a:not(.btn):not(.callbtn):not(.calltab):not(.chip):not(.telbig){color:var(--cta-light)}
.hero--emergency :where(a,button,summary):focus-visible,
.hero--situation :where(a,button,summary):focus-visible{
  box-shadow:0 0 0 3px var(--dark),0 0 0 6px var(--cta-light)}

/* V7 · compact: a low hero designed to sit directly above a card row. */
.hero--compact{padding-bottom:clamp(30px,3.4vw,48px)}

/* the hero photo slot */
.hero__media{position:relative;min-width:0}
.hero__media .imgph{box-shadow:var(--sh-lg)}

/* --------------------------------------------------------------------------
   D4 · THE PHONE BLOCK — this site's one conversion object, in four weights.
   -------------------------------------------------------------------------- */
.phone-block{border-radius:var(--r-lg);padding:clamp(26px,3.2vw,44px);
  display:grid;gap:22px;align-items:center;grid-template-columns:minmax(0,1fr)}
@media(min-width:860px){.phone-block--wide{grid-template-columns:minmax(0,1.15fr) minmax(0,.85fr)}}
.phone-block>*{min-width:0}
.phone-block__note{font-size:16.5px;line-height:1.55;margin-top:12px}
.phone-block--light{background:var(--surface);border:1px solid var(--line-strong)}
.phone-block--tint{background:var(--primary-subtle)}
.phone-block--cta{background:var(--cta);color:#fff}
.phone-block--cta :where(h2,h3,.h3,.stitle){color:#fff}
.phone-block--cta p,.phone-block--cta .lead,.phone-block--cta .eyebrow{color:#fff}
.phone-block--cta .telbig{color:#fff}
.phone-block--cta .telbig:hover{color:#fff}
.phone-block--cta .telbig svg{stroke:#fff}
.phone-block--cta :where(a,button):focus-visible{
  box-shadow:0 0 0 3px var(--cta),0 0 0 6px #fff}

/* --------------------------------------------------------------------------
   D5 · TWO FOCUS RINGS THAT VANISH IN PLACE.
   (a) A position:fixed control floats over EVERY band, so no single ring colour
       works — an amber ring over an amber band measured 1.00:1. A dual ring
       (light outline + dark shadow) keeps one layer contrasting whatever it
       floats over.
   (b) A ring must be bound to the surface that PAINTS the fill, not to the band
       class — see .on-dark and .phone-block--cta above.
   -------------------------------------------------------------------------- */
.totop:focus-visible,.callbar a:focus-visible{
  outline:3px solid var(--surface);outline-offset:0;
  box-shadow:0 0 0 6px var(--focus);border-radius:var(--r-sm)}

/* --------------------------------------------------------------------------
   D6 · NAV SUBMENU. LINK-PLAN gives the header a Leistungen submenu; the
   reference bar has none. Hover AND focus-within so it is keyboard-reachable,
   and it collapses into the drawer below the burger breakpoint.
   -------------------------------------------------------------------------- */
.nav li{position:relative;list-style:none}
.nav__sub{display:none;position:absolute;left:0;top:100%;min-width:290px;z-index:130;
  background:var(--surface);border:1px solid var(--line-strong);border-radius:var(--r-sm);
  box-shadow:var(--sh-lg);padding:6px;list-style:none}
.nav li:hover>.nav__sub,.nav li:focus-within>.nav__sub{display:block}
.nav__sub a{display:flex;width:100%;min-height:var(--tap);padding:6px 12px;font-size:16px;
  border-radius:var(--r-sm);white-space:normal}
.nav__par>a::after{content:"";width:7px;height:7px;flex:none;margin-left:7px;
  border-right:1.6px solid var(--line-strong);border-bottom:1.6px solid var(--line-strong);
  rotate:45deg;translate:0 -2px}
.mobmenu .mm-sub a{padding-left:18px;font-size:16.4px;min-height:48px;color:var(--muted)}
.mobmenu .mm-head{display:block;padding:16px 0 6px;font-size:12.5px;font-weight:800;
  letter-spacing:.14em;text-transform:uppercase;color:var(--cta-ink);border:0;min-height:0}

/* --------------------------------------------------------------------------
   D7 · Header overflow at 360px. A flex item's default min-width:auto stops the
   brand shrinking and pushes the layout past the viewport, taking the burger
   off-screen — invisible to axe and to the Site Standard, both of which ignore
   layout. Only a viewport sweep catches it.
   -------------------------------------------------------------------------- */
.brand{min-width:0;overflow:hidden}
.brand b{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:block}
.burger{flex:0 0 auto}
.navcall{flex:0 0 auto}

/* --------------------------------------------------------------------------
   D8 · A full-bleed band still needs an inline gutter, and a `.wrap` combined
   with a class that sets SHORTHAND padding loses that gutter silently (equal
   specificity, later declaration wins). Classes that may share an element with
   .wrap use padding-block only.
   -------------------------------------------------------------------------- */
.strip{padding-block:22px;padding-inline:0}
.strip ul{padding-inline:var(--gut)}

/* --------------------------------------------------------------------------
   D9 · Grid tracks. `1fr` and `auto` take a MIN-CONTENT minimum, so one German
   compound sets the document's minimum width and the whole page scrolls
   sideways at 320px. (And never put a display:none child in a grid whose tracks
   are counted — it is removed from layout entirely and the grid collapses.)
   -------------------------------------------------------------------------- */
.grid>*,.split>*,.rail>*,.mosaic>*,.compare>*,.offgrid>*,.veedel>*{min-width:0}
.imgph{min-width:0}

/* --------------------------------------------------------------------------
   D10 · Reveal must never blank text. `.reveal{opacity:0}` with a JS-only `.in`
   leaves most of a page invisible with scripting off, and axe — which never
   scrolls — reads below-fold elements as 0-contrast.
   -------------------------------------------------------------------------- */
.no-js .reveal,.no-js .wipe{transform:none;clip-path:none}

/* --------------------------------------------------------------------------
   D11 · A scrollable region must be focusable or axe fails
   `scrollable-region-focusable` (serious).
   -------------------------------------------------------------------------- */
.peek:focus-visible,.tablewrap:focus-visible{
  box-shadow:0 0 0 3px var(--surface),0 0 0 6px var(--focus)}
.tablewrap{overflow-x:auto}

/* --------------------------------------------------------------------------
   D12 · Shared objects this site composes with that the reference leaves
   page-local: the segmented slab, the Veedel cluster, the glossary register,
   the A-Z rail, a measure-limited prose block and the refusal register.
   -------------------------------------------------------------------------- */
.slab{display:grid;gap:2px;background:var(--line-strong);border:0;
  grid-template-columns:minmax(0,1fr)}
@media(min-width:760px){
  .slab--3{grid-template-columns:repeat(3,minmax(0,1fr))}
  .slab--2{grid-template-columns:repeat(2,minmax(0,1fr))}
  .slab--4{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(min-width:1040px){.slab--4{grid-template-columns:repeat(4,minmax(0,1fr))}}
.slab>*{background:var(--surface);padding:clamp(20px,2.3vw,30px);margin:0;min-width:0}
.slab--cta{background:var(--cta-hover)}
.slab--cta>*{background:var(--cta);color:#fff}
.slab--cta>* :where(h3,.h3,strong,b){color:#fff}
.slab--dark{background:var(--dark-line)}
.slab--dark>*{background:var(--dark-2);color:var(--dark-muted)}
.slab--dark>* :where(h3,.h3,strong,b){color:#fff}
.slab__k{display:block;font:800 12.5px/1 var(--f-num);letter-spacing:.13em;
  text-transform:uppercase;color:var(--cta-ink);margin-bottom:11px}
.slab--cta .slab__k{color:#fff}
.slab--dark .slab__k{color:var(--cta-light)}
.section--dark .slab{background:var(--dark-line)}
.section--dark .slab>*{background:var(--dark-2);color:var(--dark-muted)}
.section--dark .slab>* :where(h3,.h3,strong,b){color:#fff}
.section--dark .slab__k{color:var(--cta-light)}

.veedel{display:grid;gap:clamp(22px,2.6vw,36px);grid-template-columns:minmax(0,1fr)}
@media(min-width:820px){.veedel{grid-template-columns:repeat(2,minmax(0,1fr))}}
.veedel__head{display:flex;align-items:center;gap:12px;margin-bottom:15px;
  font-size:13px;font-weight:800;letter-spacing:.14em;text-transform:uppercase;
  color:var(--cta-ink)}
.veedel__head::before{content:"";width:26px;height:2px;flex:none;background:var(--cta)}
.section--dark .veedel__head,.on-dark .veedel__head{color:var(--cta-light)}
.section--dark .veedel__head::before,.on-dark .veedel__head::before{background:var(--cta-light)}

.gloss{display:grid;gap:0;border-top:1px solid var(--line)}
.gloss>div{display:grid;gap:6px 26px;padding:clamp(16px,1.8vw,24px) 0;
  border-bottom:1px solid var(--line);grid-template-columns:minmax(0,1fr)}
@media(min-width:760px){.gloss>div{grid-template-columns:minmax(190px,.3fr) minmax(0,1fr)}}
.gloss dt{font-weight:800;color:var(--head);font-size:18px;scroll-margin-top:130px;min-width:0}
.gloss dd{color:var(--muted);font-size:16.8px;line-height:1.6;margin:0;min-width:0}
.section--dark .gloss{border-top-color:var(--dark-line)}
.section--dark .gloss>div{border-bottom-color:var(--dark-line)}
.section--dark .gloss dt{color:#fff}
.section--dark .gloss dd{color:var(--dark-muted)}

.azrail{display:flex;flex-wrap:wrap;gap:6px;list-style:none}
.azrail a{display:grid;place-items:center;min-width:var(--tap);min-height:var(--tap);
  border:1.5px solid var(--line-strong);border-radius:var(--r-sm);
  font:800 15px/1 var(--f-num);color:var(--primary);text-decoration:none}
.azrail a:hover{background:var(--primary);color:#fff;border-color:var(--primary)}

.prose{max-width:74ch}
.prose p+p{margin-top:16px}

.refuse{list-style:none;display:grid;gap:0;border-top:1px solid var(--line)}
.refuse li{display:grid;grid-template-columns:auto minmax(0,1fr);gap:14px;
  padding:16px 0;border-bottom:1px solid var(--line);align-items:start}
.refuse__ic{width:30px;height:30px;flex:none;border-radius:50%;display:grid;place-items:center;
  background:var(--surface-alt);color:var(--muted)}
.refuse__ic svg{width:16px;height:16px;stroke:currentColor;stroke-width:2.4}
.refuse b{display:block;color:var(--head);font-weight:700;font-size:17.4px;margin-bottom:2px}
.refuse p{color:var(--muted);font-size:16.4px;line-height:1.55}
.section--dark .refuse,.section--dark .refuse li{border-color:var(--dark-line)}
.section--dark .refuse__ic{background:var(--dark-3);color:var(--dark-muted)}
.section--dark .refuse b{color:#fff}
.section--dark .refuse p{color:var(--dark-muted)}

/* utility spacing used by the section helpers — no new theme values */
.mt-s{margin-top:14px}.mt-m{margin-top:26px}.mt-l{margin-top:clamp(28px,3.4vw,48px)}
.tc{text-align:center}
.stack{display:grid;gap:clamp(22px,2.6vw,36px)}
.stack>*{min-width:0}

/* --------------------------------------------------------------------------
   D13 · CHROME, BOUND TO CLASSES RATHER THAN TAGS.
   WordPress renders a template part inside its OWN <header class=
   "wp-block-template-part"> wrapper. A bare `header{position:sticky}` therefore
   targets that wrapper — which carries display:contents and cannot be sticky —
   while the real bar goes unstyled. The chrome binds to .site-head / .site-footer
   instead, and the tag rules above are neutralised for the wrapper only.
   -------------------------------------------------------------------------- */
.site-head{display:block}
.site-bar{position:sticky;top:0;z-index:120;background:var(--surface);
  border-bottom:1px solid var(--line);transition:box-shadow var(--dur) var(--ease)}
.site-head.stuck .site-bar{box-shadow:0 6px 20px rgba(23,17,34,.10)}

.site-footer{background:var(--dark);color:var(--dark-muted);
  padding-top:clamp(48px,5.4vw,76px)}
.site-footer h3{color:#fff;font-size:17px;letter-spacing:.09em;text-transform:uppercase;
  margin-bottom:17px}
.site-footer ul{list-style:none;padding:0;margin:0}
.site-footer a{color:var(--dark-muted);text-decoration:none;
  display:inline-flex;align-items:center;min-height:var(--tap)}
.site-footer a:hover{color:var(--cta-light);text-decoration:underline}
.site-footer p{color:var(--dark-muted);max-width:46ch}
.site-footer .ftel{display:inline-flex;align-items:center;gap:11px;min-height:var(--tap);
  color:#fff;font-size:21px;font-weight:800;font-variant-numeric:tabular-nums;
  margin-top:14px;text-decoration:none}
.site-footer .ftel:hover{color:var(--cta-light);text-decoration:none}
.site-footer .ftel svg{width:21px;height:21px;stroke:var(--cta-light);flex:none}
.site-footer .brand--foot b{color:#fff}
.site-footer .brand--foot span span{color:var(--dark-muted)}
.site-footer .brand--foot .bmark{background:var(--dark-2);border:1px solid var(--dark-line)}
.site-footer .brand--foot .bmark svg{stroke:var(--cta-light)}
.site-footer .fbase{margin-top:clamp(30px,3.4vw,44px);border-top:1px solid var(--dark-line);
  padding:22px 0 26px;display:flex;flex-wrap:wrap;gap:6px 22px;
  align-items:center;justify-content:space-between;font-size:15.5px}
.site-footer .fbase ul{display:flex;flex-wrap:wrap;gap:2px 20px}

/* the full Einsatzgebiet row — all eleven Bezirke, both Rheinseiten */
.farea{margin-top:clamp(34px,4vw,52px);padding-top:clamp(28px,3.2vw,40px);
  border-top:1px solid var(--dark-line)}
.fchips{display:flex;flex-wrap:wrap;gap:8px}
.fchips a{padding:7px 14px;border:1.5px solid var(--dark-line-2);border-radius:var(--pill);
  font-size:15.6px;font-weight:600;color:var(--on-dark);text-decoration:none;min-height:var(--tap)}
.fchips a:hover{border-color:var(--cta-light);color:var(--cta-light);text-decoration:none}
.farea .veedel__head{color:var(--cta-light)}
.farea .veedel__head::before{background:var(--cta-light)}

/* the sticky call bar sits OUTSIDE <footer>, but name its colours anyway so no
   descendant rule can ever repaint the label on the copper fill */
.callbar a,.callbar a:hover{color:#fff;text-decoration:none}
.callbar a svg{stroke:#fff}

/* --------------------------------------------------------------------------
   D14 · Two tap-target floors the reference does not need but a 37-page site
   does. The brand is the only route home from a phone; the in-body forward
   links are how a reader reaches the money pages. Both are real controls.
   Also: the brand lockup's two lines need REAL whitespace between them —
   without it textContent reads "koeln-schloss24Schlüsseldienst Köln" as one
   token to a screen reader and to any extractor. A visual line break is not a
   word break.
   -------------------------------------------------------------------------- */
.brand{min-height:var(--tap)}
/* min-width:0 has to travel the WHOLE block chain: the flex item shrinks, but a
   nested block child keeps its own min-content width and simply overflows the
   clipped parent, so the ellipsis on <b> never fires and the name is cut mid-word
   with no visual cue that anything is missing. */
.brand__lock{display:block;min-width:0}
.brand__lock>span{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

.tlink{display:inline-flex;align-items:center;gap:8px;min-height:var(--tap);
  font-weight:700;color:var(--primary);text-decoration:underline;
  text-underline-offset:.18em;text-decoration-thickness:1px}
.tlink:hover{color:var(--cta-ink)}
.tlink__ic{width:17px;height:17px;flex:none;transition:transform var(--dur) var(--ease)}
.tlink:hover .tlink__ic{transform:translateX(3px)}
.section--dark .tlink,.on-dark .tlink{color:var(--cta-light)}
.phone-block--cta .tlink{color:#fff}

/* --------------------------------------------------------------------------
   D15 · The desktop bar has to actually FIT, measured — not assumed.
   The container is capped at 1180px, so above that width the row is a fixed
   1132px no matter how wide the screen is. Brand lockup 234 + nav 616 + call
   capsule 252 + three 18px gaps = 1156: it overflowed by 24px at EVERY desktop
   width, and the only visible symptom was the brand name silently losing its
   last characters to an ellipsis. Six items at 3px less padding each frees 36px.
   -------------------------------------------------------------------------- */
.navrow{gap:16px}
.nav a{padding:0 8px}
.navcall{padding:9px 20px 9px 9px}
.navcall .disc{width:42px;height:42px}
.navcall .num{font-size:20px}

/* Even tightened, the row needs 1095px and the container only gives 1072px
   between 1120 and 1199. The burger is the honest answer below 1200 — so the
   whole breakpoint family moves together. Moving only ONE of these is how a
   phone ends up with both the desktop call button and the burger, or with
   neither. */
@media(max-width:1199px){
  .nav{display:none}
  .navcall{display:none}
  .burger{display:inline-grid}
  .callbar{display:block}
  body{padding-bottom:84px}
  .totop{bottom:96px}
}
@media(min-width:1200px){
  .nav{display:flex}
  .navcall{display:inline-flex}
  .burger{display:none}
  .callbar{display:none}
  body{padding-bottom:0}
  .totop{bottom:24px}
}

/* --------------------------------------------------------------------------
   D16 · INK CONTAINMENT FOR COLOURED PANELS — the same class of bug as D1,
   found again on a different surface.
   `.diptych__half--primary` paints the violet itself; it is not a
   `.section--dark` and it is not `.on-dark`, so NONE of the dark-band ink rules
   reach it. The reference only re-declares h2/h3/h4 there, which leaves the
   whole hero set behind: measured on the Sülz diptych hero, `.display .l2`
   rendered --primary on --primary at **1.00:1**, the breadcrumbs 1.05:1 and the
   lead 1.05:1. axe catches none of it unless it happens to sample those nodes,
   and the Site Standard does not look at layout or colour at all.
   The lesson generalises: bind the ink to the surface that PAINTS the fill.
   -------------------------------------------------------------------------- */
.diptych__half--primary,
.diptych__half--dark{color:var(--on-dark)}
.diptych__half--primary :where(h1,h2,h3,h4,.h3,.stitle,.display,strong,b),
.diptych__half--dark :where(h1,h2,h3,h4,.h3,.stitle,.display,strong,b){color:#fff}
.diptych__half--primary .display .l2,
.diptych__half--dark .display .l2{color:var(--cta-light)}
.diptych__half--primary :where(p,.lead),
.diptych__half--dark :where(p,.lead){color:var(--on-dark)}
.diptych__half--primary .eyebrow,
.diptych__half--dark .eyebrow{color:var(--cta-light)}
.diptych__half--primary .crumbs li,
.diptych__half--primary .crumbs a,
.diptych__half--dark .crumbs li,
.diptych__half--dark .crumbs a{color:var(--on-dark)}
.diptych__half--primary .crumbs [aria-current="page"],
.diptych__half--dark .crumbs [aria-current="page"]{color:#fff}
.diptych__half--primary .crumbs li+li::before,
.diptych__half--dark .crumbs li+li::before{border-color:var(--dark-line-2)}
.diptych__half--primary .hero__meta,
.diptych__half--dark .hero__meta{color:var(--on-dark)}
.diptych__half--primary .hero__meta svg,
.diptych__half--dark .hero__meta svg{stroke:var(--cta-light)}
.diptych__half--primary a:not(.btn):not(.callbtn):not(.calltab):not(.chip):not(.telbig),
.diptych__half--dark a:not(.btn):not(.callbtn):not(.calltab):not(.chip):not(.telbig){color:var(--cta-light)}
.diptych__half--primary .iclist__ic,
.diptych__half--dark .iclist__ic{background:rgba(255,255,255,.16);color:#fff}
.diptych__half--primary :where(a,button,summary):focus-visible{
  box-shadow:0 0 0 3px var(--primary),0 0 0 6px #fff}
.diptych__half--dark :where(a,button,summary):focus-visible{
  box-shadow:0 0 0 3px var(--dark),0 0 0 6px var(--cta-light)}

/* Same root cause on the copper phone panel: a PROSE link inside it inherited
   --primary (1.80:1 on copper). `.tlink` was named; a bare inline <a> was not. */
.phone-block--cta a{color:#fff;text-decoration-color:rgba(255,255,255,.7)}
.phone-block--cta .iclist__ic{background:rgba(255,255,255,.2);color:#fff}

/* --------------------------------------------------------------------------
   D17 · THE DARK-SURFACE SET, named once.
   Three separate defects in this build had the same root cause: a primitive
   whose ink is only re-declared for `.section--dark`, dropped onto a surface
   that is dark or saturated for a DIFFERENT reason. `.hero--emergency` and
   `.hero--situation` paint --dark themselves; `.diptych__half--primary` paints
   the violet; `.on-dark` and `.phone-block--cta` paint their own fills. None of
   them is a `.section--dark`, so none of them got those rules.

   Rather than chase the next one, every dark-ish surface is listed here, and
   ADDING A NEW ONE MEANS ADDING IT TO THIS LIST. The outlined button is the
   worst offender because its label colour IS its only colour: on the violet
   panel it measured 1.00:1 — text the exact colour of its own background.
   -------------------------------------------------------------------------- */
.section--dark .btn--ghost,
.on-dark .btn--ghost,
.hero--emergency .btn--ghost,
.hero--situation .btn--ghost,
.diptych__half--dark .btn--ghost,
.diptych__half--primary .btn--ghost{
  --btn-fg:#fff; --btn-bg-h:#fff;
  box-shadow:inset 0 0 0 1.5px rgba(255,255,255,.42)}
.section--dark .btn--ghost:hover,
.on-dark .btn--ghost:hover,
.hero--emergency .btn--ghost:hover,
.hero--situation .btn--ghost:hover,
.diptych__half--dark .btn--ghost:hover,
.diptych__half--primary .btn--ghost:hover{color:var(--dark)}
.phone-block--cta .btn--ghost{
  --btn-fg:#fff; --btn-bg-h:#fff; box-shadow:inset 0 0 0 1.5px rgba(255,255,255,.55)}
.phone-block--cta .btn--ghost:hover{color:var(--cta-hover)}

/* the same set, for every other primitive that paints its own ink */
.hero--emergency .chip,
.hero--situation .chip{background:var(--dark-3);border-color:var(--dark-line-2);color:var(--on-dark)}
.hero--emergency .iclist__ic,
.hero--situation .iclist__ic{background:var(--dark-3);color:var(--cta-light)}
.hero--emergency .iclist b,
.hero--situation .iclist b{color:#fff}
.hero--emergency .iclist p,
.hero--situation .iclist p{color:var(--dark-muted)}
.hero--emergency .numpill,
.hero--situation .numpill{background:var(--dark-2);border-color:var(--dark-line);color:var(--cta-light)}
.hero--emergency .card,
.hero--situation .card{background:var(--dark-2);border-color:var(--dark-line);color:var(--dark-muted)}
.hero--emergency .card :where(h3,.h3),
.hero--situation .card :where(h3,.h3){color:#fff}
.hero--emergency .tlink,
.hero--situation .tlink,
.diptych__half--dark .tlink,
.diptych__half--primary .tlink{color:var(--cta-light)}

/* ==========================================================================
   E · BUTTON GEOMETRY — squarer, wider, shorter, with a real edge.
   The call capsule was a 999px lozenge 67–73px tall: soft, and far taller than
   it needed to be for a 44px target. It now reads as a machined control —
   a 6px radius, a defined 1px edge, more horizontal padding and less vertical.
   Nothing drops below the 44px tap floor; that floor is why the height is
   trimmed TO it rather than past it.
   ========================================================================== */

/* --- the outlined/filled button family --------------------------------- */
.btn{
  padding:11px 30px;                    /* was 14px 26px — wider, shorter */
  border-radius:var(--r-sm);
  letter-spacing:.008em;
  box-shadow:inset 0 0 0 1px rgba(0,0,0,.16);   /* the edge, on the fill */
}
.btn:hover{box-shadow:inset 0 0 0 1px rgba(0,0,0,.16),var(--sh)}
.btn--lg{padding:14px 38px;font-size:18px}
.btn--ghost{box-shadow:inset 0 0 0 1.5px var(--line-strong)}
.btn--ghost:hover{box-shadow:inset 0 0 0 1.5px var(--line-strong),var(--sh)}
.section--dark .btn--ghost:hover,
.on-dark .btn--ghost:hover,
.hero--emergency .btn--ghost:hover,
.hero--situation .btn--ghost:hover,
.diptych__half--dark .btn--ghost:hover,
.diptych__half--primary .btn--ghost:hover{box-shadow:inset 0 0 0 1.5px rgba(255,255,255,.42),var(--sh)}

/* --- the call capsule, de-pilled --------------------------------------- */
.callbtn{
  border-radius:var(--r);               /* 8px, not 999px */
  padding:7px 26px 7px 7px;
  gap:13px;
  box-shadow:inset 0 0 0 1px rgba(0,0,0,.18);
}
.callbtn:hover{
  transform:none;                       /* a lozenge could float; a panel should not */
  box-shadow:inset 0 0 0 1px rgba(0,0,0,.18),var(--sh);
}
.callbtn .disc{
  width:36px;height:36px;
  border-radius:var(--r-sm);            /* square is structural — the glyph stays round-ish */
}
.callbtn .disc svg{width:19px;height:19px}
.callbtn .cap{font-size:11px;letter-spacing:.15em}
.callbtn .num{font-size:19.5px;margin-top:2px}
.callbtn.callbtn--dark{box-shadow:inset 0 0 0 1px var(--line-strong)}
.callbtn.callbtn--dark:hover{box-shadow:inset 0 0 0 1px var(--line-strong),var(--sh)}

/* the header instance is the tightest of the three */
.navcall{padding:6px 22px 6px 6px}
.navcall .disc{width:34px;height:34px}
.navcall .num{font-size:18.5px}

/* --- the sticky mobile bar keeps its generous target on purpose -------- */
.callbar a{min-height:50px;border-radius:var(--r);
  box-shadow:inset 0 0 0 1px rgba(0,0,0,.18);letter-spacing:.01em}

/* --- the die-cut tab follows the same radius language ------------------ */
.calltab{border-radius:0 var(--r) 0 0;padding:15px 30px 15px 24px}

/* --- CHIPS: a place name may not break mid-name -------------------------
   Prefixing the district chips with "Köln-" pushed the longest labels past
   their box, and a wrapped chip grew to 102px tall — more than twice the
   others. A chip is one token; it stays on one line and the row wraps instead. */
.chip{white-space:nowrap;padding:8px 16px;min-height:var(--tap)}
.fchips a{white-space:nowrap}

/* The number inherited body line-height (1.7), so a 19.5px figure occupied 33px
   and set the capsule's height on its own. The two lines are a lockup, not
   running text. */
.callbtn .num{line-height:1.12}
.callbtn .cap{line-height:1}

/* The wider horizontal padding is right on desktop and costs label room on a
   phone: "Jetzt anrufen · 0176 4287 6015" needs ~316px and a 390px viewport
   leaves 342px inside the gutter, so 38px of padding each side pushed it onto a
   second line and the button grew to ~130px tall. Below 480px it goes full-width
   with a tighter inset instead — one line, one clear target. */
@media(max-width:479px){
  .btn--lg{width:100%;padding:13px 16px;font-size:17px}
  .hero__actions .btn--ghost{width:100%;padding:11px 16px}
  .callbtn{padding-right:18px}
}

/* SPECIFICITY, not taste: the sitewide tap-target floor is written as
   `a[href^="tel:"]:not(.navcall)` — (0,2,1), because :not() contributes its
   argument's specificity — so it silently outranked `.callbar a` (0,1,1) and the
   sticky bar rendered as a 268px-wide, 44px-tall inline-flex instead of the
   full-width 50px block it was given. Matching the attribute selector is what
   makes the declaration land. */
.callbar a[href^="tel:"]{display:flex;width:100%;min-height:50px}

/* ==========================================================================
   F · POST BODY — the only place on this site where the markup is not written
   by the build. A post comes out of the block editor as core blocks, so its
   headings, lists, quotes, tables and images need type rules of their own.
   Measure stays inside .wrap--narrow; everything here is a token.
   ========================================================================== */
.postbody{font-size:18px;line-height:1.75}
.postbody > * + *{margin-top:20px}
.postbody h2{font-size:clamp(23px,2.4vw,30px);font-weight:800;margin-top:clamp(34px,3.4vw,48px)}
.postbody h3{font-size:clamp(19px,1.6vw,22px);font-weight:700;margin-top:clamp(26px,2.6vw,36px)}
.postbody h4{font-size:18.5px;font-weight:700;margin-top:24px}
.postbody p{max-width:none}
.postbody a{color:var(--primary);text-decoration:underline;text-underline-offset:.18em}
.postbody a:hover{color:var(--cta-ink)}
.postbody ul,.postbody ol{padding-left:1.35em;display:grid;gap:9px}
.postbody li{padding-left:4px}
.postbody ul{list-style:disc}
.postbody ol{list-style:decimal}
.postbody li::marker{color:var(--cta-ink)}
.postbody blockquote{border-left:3px solid var(--cta);padding:4px 0 4px 20px;margin-left:0;
  color:var(--muted);font-size:19px}
.postbody blockquote p{margin-top:0}
.postbody img,.postbody figure img{border-radius:var(--r);height:auto}
.postbody figure{margin:0}
.postbody figcaption{margin-top:9px;font-size:15.5px;color:var(--muted)}
.postbody hr{border:0;border-top:1px solid var(--line);margin-block:clamp(28px,3vw,40px)}
.postbody code{background:var(--surface-alt);padding:2px 6px;border-radius:var(--r-xs);font-size:.92em}
.postbody pre{background:var(--surface-alt);border:1px solid var(--line);border-radius:var(--r-sm);
  padding:18px;overflow-x:auto}
.postbody table{width:100%;border-collapse:collapse}
.postbody :where(th,td){border:1px solid var(--line);padding:10px 13px;text-align:left}
.postbody th{background:var(--surface-alt);font-weight:700}
.postbody .wp-block-table{overflow-x:auto}

/* pagination on the archive */
.postnav .nav-links{display:flex;flex-wrap:wrap;gap:9px;align-items:center}
.postnav a,.postnav .current{display:inline-flex;align-items:center;justify-content:center;
  min-width:var(--tap);min-height:var(--tap);padding:0 14px;border-radius:var(--r-sm);
  border:1.5px solid var(--line-strong);text-decoration:none;font-weight:700;color:var(--primary)}
.postnav .current{background:var(--primary);border-color:var(--primary);color:#fff}
.postnav a:hover{background:var(--primary-subtle)}
.postnav .screen-reader-text{position:absolute;width:1px;height:1px;overflow:hidden;
  clip:rect(0 0 0 0);white-space:nowrap}

/* The archive card's title IS the link to the post, so it is a control and takes
   the 44px floor like every other one. A 26px heading link is the kind of target
   that only fails for people who need it to pass. */
.postcard__t a{display:inline-flex;align-items:center;min-height:var(--tap);
  color:var(--head);text-decoration:none}
.postcard__t a:hover{color:var(--cta-ink);text-decoration:underline;text-underline-offset:.18em}

/* "Blog" is the shortest label on the site and the first footer link narrow
   enough to fall under the 44px target — every other one was wide enough to hide
   the problem. Rather than padding short labels into odd wide boxes, a link in a
   footer COLUMN fills its row: the target grows to the column width, and a
   left-aligned list looks exactly the same. The base row stays inline, because
   Impressum / Datenschutz / Barrierefreiheit sit side by side there. */
.site-footer .fgrid ul li a{display:flex;width:100%}
