@font-face{font-family:'Archivo';src:url('../fonts/archivo-var-latin.woff2?v=de2f1fe8') format('woff2');font-weight:100 900;font-stretch:62% 125%;font-display:optional/* NOT swap. Archivo at wdth 125 is ~34% wider than the Arial fallback, so a swap AFTER first paint re-sizes the hero grid track, re-wraps the lead and slides the right-aligned nav: CLS 0.0751 on ~1 cold load in 6 (measured 21.08.2026). optional keeps whichever face won the ~100ms race for that document's life, so the shift cannot happen. The font is preloaded and every repeat visit is cached. */}@font-face{font-family:'Martian Mono';src:url('../fonts/martianmono-var-latin.woff2?v=64092ca6') format('woff2');font-weight:400 700;font-display:swap}@font-face{font-family:'Archivo Fallback';src:local('Arial');size-adjust:99%;ascent-override:88%;descent-override:21%;line-gap-override:0%}@font-face{font-family:'Archivo Fallback Wide';src:local('Arial');size-adjust:104.4%;ascent-override:88%;descent-override:21%;line-gap-override:0%}@font-face{font-family:'Martian Fallback';src:local('Courier New');size-adjust:116.6%;ascent-override:100%;descent-override:20%;line-gap-override:0%}:root{--ink:#16130F;--ink-2:#1E1A14;--line:rgba(239,233,222,.14);--line-soft:rgba(239,233,222,.08);--bone:#EFE9DE;--bone-dim:rgba(239,233,222,.68);--brass:#D2A62C;--paper:#EFE9DE;--paper-ink:#16130F;--paper-dim:rgba(22,19,15,.66);--paper-line:rgba(22,19,15,.16);--error:#C8552E;--font-sans:'Archivo','Archivo Fallback',Arial,sans-serif;--font-disp:'Archivo','Archivo Fallback Wide',Arial,sans-serif;--font-mono:'Martian Mono','Martian Fallback','Courier New',monospace;--wide:'wdth' 125;--cond:'wdth' 68;--radius-pill:999px;--radius-input:0;--gutter:clamp(1.25rem,4vw,4rem);--section-y:clamp(4.5rem,11vw,9.5rem);--max:1280px}*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}html{scroll-behavior:smooth;-webkit-text-size-adjust:100%}body{background:var(--ink);color:var(--bone);font-family:var(--font-sans);font-size:1.06rem;line-height:1.65;-webkit-font-smoothing:antialiased;overflow-x:clip}img,svg,video{display:block;max-width:100%}a{color:inherit;text-decoration:none}button{font:inherit;color:inherit;background:none;border:0;cursor:pointer}ul,ol{list-style:none}[hidden]{display:none !important}::selection{background:var(--brass);color:var(--ink)}:focus-visible{outline:2px solid var(--brass);outline-offset:3px;border-radius:2px}.paper:focus-visible{outline-color:var(--paper-ink)}.skip-link{position:fixed;top:-100px;left:1rem;z-index:300;background:var(--brass);color:var(--ink);padding:.7rem 1.2rem;border-radius:var(--radius-pill);font-weight:650;transition:top .2s}.skip-link:focus{top:1rem}@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}*,*::before,*::after{transition-duration:.01ms !important;animation-duration:.01ms !important;animation-iteration-count:1 !important}}h1,h2,h3{line-height:1.02;letter-spacing:-0.015em;text-wrap:balance}.display{font-family:var(--font-disp);font-variation-settings:var(--wide);font-weight:810;font-size:clamp(2.9rem,8.5vw,6.6rem);line-height:.96;text-transform:none}h1,h2,h3,h4,h5,h6,.display{overflow-wrap:break-word}h2,.h2{font-family:var(--font-disp);font-variation-settings:var(--wide);font-weight:760;font-size:clamp(1.95rem,4.6vw,3.3rem)}h3,.h3{font-weight:660;font-size:1.32rem;line-height:1.25}.lead{font-size:clamp(1.12rem,1.6vw,1.3rem);line-height:1.55;color:var(--bone-dim);max-width:56ch}.dim{color:var(--bone-dim)}.paper .dim{color:var(--paper-dim)}.mono{font-family:var(--font-mono);font-size:.8rem;font-weight:430;letter-spacing:0;line-height:1.5}.mono-dim{color:var(--bone-dim)}.paper .mono-dim{color:var(--paper-dim)}.big-stat{font-variation-settings:var(--cond);font-weight:210;font-size:clamp(3.2rem,8vw,6rem);line-height:1;letter-spacing:-0.01em}.wrap{max-width:var(--max);margin:0 auto;padding-inline:var(--gutter)}.section{padding-block:var(--section-y);position:relative}.section + .section{border-top:1px solid var(--line-soft)}.cv{content-visibility:auto;contain-intrinsic-size:auto 900px}.sec-head{display:flex;align-items:flex-end;justify-content:space-between;gap:1.5rem;margin-bottom:clamp(2.2rem,5vw,4rem)}.sec-note{text-align:right;white-space:nowrap;padding-bottom:.5rem}@media (max-width:700px){.sec-head{flex-direction:column;align-items:flex-start}.sec-note{text-align:left;padding-bottom:0;white-space:normal}}.paper{background:var(--paper);color:var(--paper-ink)}.paper::selection{background:var(--paper-ink);color:var(--paper)}.btn{display:inline-flex;align-items:center;gap:.55rem;background:var(--brass);color:var(--ink);font-weight:680;font-size:1rem;padding:.95rem 1.9rem;border-radius:var(--radius-pill);transition:transform .18s ease,filter .18s ease}.btn:hover{transform:translateY(-1px);filter:brightness(1.07)}.btn:active{transform:translateY(0)}.btn:focus-visible{outline-color:var(--bone)}.paper .btn:focus-visible{outline-color:var(--paper-ink)}.btn-ghost{display:inline-flex;align-items:center;gap:.55rem;border:1px solid var(--line);color:var(--bone);font-weight:560;font-size:1rem;padding:.95rem 1.9rem;border-radius:var(--radius-pill);transition:border-color .18s ease,transform .18s ease}.btn-ghost:hover{border-color:var(--bone);transform:translateY(-1px)}.paper .btn-ghost{border-color:var(--paper-line);color:var(--paper-ink)}.paper .btn-ghost:hover{border-color:var(--paper-ink)}.link-arrow{display:inline-flex;align-items:center;gap:.4rem;font-weight:600;text-decoration:underline;text-underline-offset:5px;text-decoration-thickness:1px;text-decoration-color:var(--line);transition:color .15s ease,text-decoration-color .15s ease}.link-arrow:hover{color:var(--brass);text-decoration-color:var(--brass)}.paper .link-arrow:hover{color:var(--paper-ink);text-decoration-color:var(--paper-ink)}.brand-logo{position:fixed;top:0;left:0;z-index:120;padding:.9rem var(--gutter);transition:opacity .25s ease}.brand-logo.faded{opacity:0;pointer-events:none}.nav-logo{display:flex;align-items:center;gap:.65rem}.nav-logo-parrot{height:30px;width:auto}.nav-logo-textblock{display:flex;flex-direction:column;line-height:1.1}.nav-logo-name{font-variation-settings:var(--wide);font-weight:740;font-size:.92rem;letter-spacing:.01em;text-transform:uppercase}.nav-logo-sub{font-family:var(--font-mono);font-size:.58rem;color:var(--bone-dim);margin-top:.2rem}.site-nav{position:fixed;top:0;left:0;right:0;z-index:110;display:flex;align-items:center;justify-content:flex-end;gap:1.6rem;padding:.9rem var(--gutter);border-bottom:1px solid transparent;transition:background-color .25s ease,border-color .25s ease}.site-nav.scrolled{background:var(--ink);border-bottom-color:var(--line-soft)}.nav-links{display:flex;gap:1.4rem}.nav-links a{font-size:.95rem;font-weight:520;color:var(--bone-dim);padding:.3rem 0;border-bottom:2px solid transparent;transition:color .15s ease,border-color .15s ease}.nav-links a:hover{color:var(--bone)}.nav-links a.active{color:var(--bone);border-bottom-color:var(--brass)}.nav-right{display:flex;align-items:center;gap:1rem}.lang-switcher{display:flex;gap:.15rem;font-family:var(--font-mono);font-size:.74rem}.lang-btn{padding:.35rem .5rem;color:var(--bone-dim);border-radius:var(--radius-pill);min-width:34px;min-height:30px}.lang-btn.active{color:var(--ink);background:var(--bone);font-weight:700}.lang-btn:not(.active):hover{color:var(--bone)}.nav-cta{background:var(--brass);color:var(--ink);font-weight:660;font-size:.92rem;padding:.6rem 1.25rem;border-radius:var(--radius-pill);transition:transform .18s ease,filter .18s ease}.nav-cta:hover{transform:translateY(-1px);filter:brightness(1.07)}.site-footer{border-top:1px solid var(--line);padding:clamp(3rem,7vw,5.5rem) var(--gutter) 2rem;max-width:var(--max);margin:0 auto}.footer-grid{display:grid;grid-template-columns:1.4fr 1fr;gap:clamp(2rem,5vw,4.5rem);padding-bottom:3rem}@media (max-width:820px){.footer-grid{grid-template-columns:1fr}}.footer-logo{display:flex;align-items:center;gap:.65rem;margin-bottom:1.1rem}.footer-logo-parrot{height:34px;width:auto}.footer-logo-textblock{display:flex;flex-direction:column;line-height:1.1}.footer-logo-name{font-variation-settings:var(--wide);font-weight:740;font-size:.95rem;text-transform:uppercase}.footer-logo-sub{font-family:var(--font-mono);font-size:.6rem;color:var(--bone-dim);margin-top:.2rem}.footer-brand p{color:var(--bone-dim);font-size:.95rem;max-width:34ch}.footer-col .footer-h{font-family:var(--font-mono);font-weight:430;font-size:.74rem;color:var(--bone-dim);margin-bottom:1rem}.footer-col a{display:block;padding:.28rem 0;font-size:.97rem;color:var(--bone);width:fit-content}.footer-col a:hover{color:var(--brass)}.footer-col p{color:var(--bone-dim);font-size:.85rem;margin-top:.6rem}.footer-bottom{border-top:1px solid var(--line-soft);padding-top:1.4rem;display:flex;flex-wrap:wrap;gap:.8rem 2rem;align-items:center;justify-content:space-between;font-family:var(--font-mono);font-size:.72rem;color:var(--bone-dim)}.footer-legal{display:flex;gap:.8rem}.footer-legal a:hover{color:var(--bone)}.footer-gh{display:inline-flex;align-items:center}.sticky-cta{position:fixed;left:0;right:0;bottom:0;z-index:90;display:none;background:var(--ink);border-top:1px solid var(--line);padding:.65rem var(--gutter);padding-bottom:calc(.65rem + env(safe-area-inset-bottom,0));gap:.6rem}@media (max-width:768px){.sticky-cta{display:flex}body.has-sticky-cta{padding-bottom:72px}}.sticky-cta-primary{flex:1;text-align:center;background:var(--brass);color:var(--ink);font-weight:680;font-size:.98rem;padding:.8rem 1rem;border-radius:var(--radius-pill)}.sticky-cta-second{display:inline-flex;align-items:center;gap:.45rem;border:1px solid var(--line);padding:.8rem 1.05rem;border-radius:var(--radius-pill);font-weight:560;font-size:.92rem}label{display:block;font-family:var(--font-mono);font-size:.74rem;color:var(--bone-dim);margin-bottom:.45rem}input[type="text"],input[type="email"],input[type="tel"],input[type="number"],select,textarea{width:100%;background:var(--ink-2);border:1px solid var(--line);border-radius:var(--radius-input);color:var(--bone);font:inherit;font-size:16px;padding:.8rem 1rem;transition:border-color .15s ease}input:focus,select:focus,textarea:focus{outline:none;border-color:var(--brass)}input:focus-visible,select:focus-visible,textarea:focus-visible{outline:2px solid var(--brass);outline-offset:2px/* The rule above kills the outline for BOTH pointer and keyboard focus, so a keyboard user only ever got a 1px border colour change — below the 3:1 non-text contrast floor and invisible on a dark field. This puts the site-wide focus ring back for keyboard focus only. Offset 2px, not the global 3px: these are boxed fields and 3px collided with the neighbouring field's border in the two-column rows. */}input[type="range"]:focus-visible,input[type="checkbox"]:focus-visible{outline:2px solid var(--brass);outline-offset:4px;border-radius:2px}.paper input[type="range"]:focus-visible,.paper input[type="checkbox"]:focus-visible{outline-color:var(--paper-ink)}textarea{min-height:120px;resize:vertical}.field{margin-bottom:1.3rem}.field-error{border-color:var(--error) !important}.error-msg{color:var(--error);font-size:.85rem;margin-top:.4rem}.hp-field{position:absolute !important;left:-9999px !important;width:1px;height:1px;overflow:hidden}.check-row{display:flex;align-items:flex-start;gap:.7rem}.check-row input[type="checkbox"]{width:18px;height:18px;margin-top:.25rem;accent-color:var(--brass);flex-shrink:0}.check-row label,.check-row span{font-family:var(--font-sans);font-size:.9rem;color:var(--bone-dim);margin:0}.check-row a{text-decoration:underline;text-underline-offset:3px}/* Section footnotes sit in a full-width .wrap, so nothing else caps their measure.
   70ch matches .bleed-note; Martian Mono runs wide, so an uncapped line here
   reached 129 characters. */
#demos > .wrap > p.mono-dim,.price-foot > p.mono-dim{max-width:70ch}
.faq-item{border-top:1px solid var(--line)}.faq-item:last-child{border-bottom:1px solid var(--line)}.faq-q{width:100%;display:flex;align-items:center;justify-content:space-between;gap:1.5rem;text-align:left;padding:1.35rem 0;font-weight:620;font-size:1.08rem}.faq-q .faq-x{flex-shrink:0;width:20px;height:20px;position:relative;transition:transform .3s ease}.faq-q .faq-x::before,.faq-q .faq-x::after{content:'';position:absolute;background:var(--bone-dim);top:50%;left:0;width:100%;height:1.5px;transform:translateY(-50%)}.faq-q .faq-x::after{transform:translateY(-50%) rotate(90deg);transition:transform .3s ease}.faq-q[aria-expanded="true"] .faq-x::after{transform:translateY(-50%) rotate(0deg)}.faq-h{margin:0;font:inherit}.faq-a{display:grid;grid-template-rows:0fr;transition:grid-template-rows .35s ease}.faq-item.open .faq-a{grid-template-rows:1fr}.faq-a-inner{overflow:hidden}.faq-a-inner p{padding-bottom:1.35rem;color:var(--bone-dim);max-width:68ch}.paper .faq-q .faq-x::before,.paper .faq-q .faq-x::after{background:var(--paper-dim)}.paper .faq-a-inner p{color:var(--paper-dim)}.paper .faq-item,.paper .faq-item:last-child{border-color:var(--paper-line)}.demo-strip{display:grid;grid-template-columns:1.35fr 1fr;gap:clamp(1.5rem,4vw,3.5rem);align-items:center;padding-block:clamp(2rem,5vw,3.5rem);border-top:1px solid var(--line-soft)}.demo-strip:first-of-type{border-top:0}.demo-strip.flip{grid-template-columns:1fr 1.35fr}.demo-strip.flip .demo-media{order:2}@media (max-width:820px){.demo-strip,.demo-strip.flip{grid-template-columns:1fr}.demo-strip.flip .demo-media{order:0}}.demo-media{position:relative;aspect-ratio:16 / 10;overflow:hidden;background:var(--ink-2)}.demo-media img{width:100%;height:100%;object-fit:cover;transition:transform .5s ease}.demo-strip:hover .demo-media img{transform:scale(1.03)}.demo-media::before,.demo-media::after{content:'';position:absolute;width:20px;height:20px;border-color:var(--brass);opacity:.5;pointer-events:none;transition:opacity .25s ease}.demo-media::before{top:12px;left:12px;border-top:1.5px solid;border-left:1.5px solid}.demo-media::after{bottom:12px;right:12px;border-bottom:1.5px solid;border-right:1.5px solid}.demo-strip:hover .demo-media::before,.demo-strip:hover .demo-media::after,.demo-media:focus-visible::before,.demo-media:focus-visible::after{opacity:1}.gate-head{display:flex;align-items:baseline;gap:1rem;margin-bottom:1rem;flex-wrap:wrap}.gate-num{font-variation-settings:var(--cond);font-weight:230;font-size:clamp(1.5rem,2.4vw,1.9rem);color:var(--bone-dim);line-height:1}.gate-num-total{font-size:.58em;opacity:.8/* was .55 = 3.1:1 on --ink. Visible text needs 4.5:1 even inside an aria-hidden ornament: contrast is a low-vision concern, not a screen-reader one. */}.gate-tags{display:flex;flex-wrap:wrap;gap:.5rem}.gate-tag{display:inline-flex;align-items:center;border:1px solid var(--line);border-radius:var(--radius-pill);padding:.3rem .8rem;font-family:var(--font-mono);font-size:.66rem;letter-spacing:.02em;color:var(--bone-dim)}.paper .gate-tag{border-color:var(--paper-line);color:var(--paper-dim)}.demo-info h3{font-variation-settings:var(--wide);font-weight:730;font-size:clamp(1.5rem,2.6vw,2.1rem);margin-bottom:.7rem}.demo-info p{color:var(--bone-dim);max-width:46ch;margin-bottom:1.2rem}.demo-links{display:flex;flex-wrap:wrap;gap:.5rem 1.4rem}.hairline-top{border-top:1px solid var(--line)}.center{text-align:center}.nowrap{white-space:nowrap}[aria-hidden="true"]{user-select:none}.will-reveal{will-change:transform}@media print{[data-reveal]{visibility:visible !important;opacity:1 !important;clip-path:none !important;transform:none !important}}.bleed-intro{max-width:60ch;color:var(--bone-dim);font-size:1.1rem;margin-bottom:2.4rem}.bleed-tabs{display:flex;flex-wrap:wrap;gap:.6rem;margin-bottom:clamp(1.8rem,4vw,2.6rem)}.bleed-tab{border:1px solid var(--line);color:var(--bone-dim);padding:.6rem 1.15rem;border-radius:var(--radius-pill);font-size:.95rem;font-weight:560;transition:color .15s ease,border-color .15s ease}.bleed-tab:hover{color:var(--bone);border-color:var(--bone)}.bleed-tab.active{background:var(--bone);color:var(--ink);border-color:var(--bone);font-weight:690}.bleed-panel[hidden]{display:none}.bleed-grid{display:grid;grid-template-columns:1.35fr 1fr;gap:clamp(2rem,5vw,4rem);align-items:start}@media (max-width:820px){.bleed-grid{grid-template-columns:1fr}}.bleed-slider{padding:1.15rem 0;border-top:1px solid var(--line-soft)}.bleed-slider:first-child{border-top:0;padding-top:0}.bleed-slider label{display:flex;justify-content:space-between;align-items:baseline;gap:1rem;font-family:var(--font-sans);font-size:.98rem;color:var(--bone);margin-bottom:.8rem}.bleed-val{font-family:var(--font-mono);font-size:.95rem;font-weight:700;white-space:nowrap}.bleed input[type="range"]{-webkit-appearance:none;appearance:none;width:100%;height:2px;background:var(--line);border-radius:0}.bleed input[type="range"]::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:20px;height:20px;border-radius:50%;background:var(--brass);border:0;cursor:pointer}.bleed input[type="range"]::-moz-range-thumb{width:20px;height:20px;border-radius:50%;background:var(--brass);border:0;cursor:pointer}.bleed input[type="range"]::-moz-range-track{height:2px;background:var(--line)}.bleed-result{border:1px solid var(--line);padding:clamp(1.4rem,3vw,2rem)}.bleed-num{font-variation-settings:var(--cond);font-weight:230;font-size:clamp(2.6rem,5vw,4.1rem);line-height:1;margin:.55rem 0 .5rem;white-space:nowrap}.bleed-num .bleed-unit{font-size:.85rem;font-weight:430;color:var(--bone-dim)}.bleed-cta{display:flex;flex-wrap:wrap;gap:.9rem 1.4rem;align-items:center;margin-top:clamp(2rem,4vw,2.8rem)}.bleed-note{margin-top:1.3rem;max-width:70ch}@media (max-width:1000px) and (min-width:821px){.footer-grid{grid-template-columns:1fr 1fr}}

/* ===== IHRE FARBEN — six palettes, switched by html[data-farbe] ===== */
/* Written UNMINIFIED on purpose — the rest of this file is hand-minified, this
   block is the exception, because it is the one part of the stylesheet a human is
   meant to open: adding a trade = copy one palette block + one chip line + one line
   in js/farben.js. Built 2026-09-02.

   WHY it exists. A visitor from a Gasthof, a Friseursalon or a Maschinenbau firm
   flips the whole studio site into the pigments of their own trade. The colour is
   an argument ("he can do MY thing"), not decoration — and it closes a measured
   flank: 0 of the 4 Tirol competitors we measured map anything to a trade.

   THE FOUR RULES
   1. The default has NO [data-farbe]. It is the werkstatt palette in :root at the
      top of this file and is never redefined here, so an untouched visit renders
      byte-for-byte what it rendered yesterday.
   2. Every palette overrides the COMPLETE colour token set. Half a palette leaks
      the default ink into a light ground — the one failure mode that looks broken.
   3. Contrast is computed, not eyeballed. Per palette: body text >= 4.5:1 on the
      ground, accent >= 3:1 on the ground, CTA text (--ink on --brass) >= 4.5:1,
      dim text >= 4.5:1 (alpha composited first), error text >= 4.5:1.
   4. Nothing is stored on the device. The choice lives in ?farbe= and nowhere else
      — no localStorage, no cookie. The site has no consent banner because of it. */

/* Gasthof — walnut Stube at night, candlelight on the cloth, honey brass.
   The ground is deliberately a RED-brown, not a darker version of the default
   olive-black: the first draft (#1E1610) was so close to werkstatt that the two
   swatches were indistinguishable in the rail, which defeats the whole point. */
:root[data-farbe="gasthof"] {
  --ink: #2A1B12;
  --ink-2: #362317;
  --line: rgba(244,232,206,.15);
  --line-soft: rgba(244,232,206,.09);
  --bone: #F4E8CE;
  --bone-dim: rgba(244,232,206,.70);
  --brass: #E3A73C;
  --paper: #F4E8CE;
  --paper-ink: #2A1B12;
  --paper-dim: rgba(42,27,18,.68);
  --paper-line: rgba(42,27,18,.17);
  --error: #DC6A42;
}

/* Friseur — aubergine, blush, rose gold. Warm skin tones, no pink UI candy. */
:root[data-farbe="friseur"] {
  --ink: #241A26;
  --ink-2: #302432;
  --line: rgba(242,220,224,.15);
  --line-soft: rgba(242,220,224,.09);
  --bone: #F2DCE0;
  --bone-dim: rgba(242,220,224,.70);
  --brass: #D79A8C;
  --paper: #F2DCE0;
  --paper-ink: #241A26;
  --paper-dim: rgba(36,26,38,.68);
  --paper-line: rgba(36,26,38,.17);
  --error: #D96A58;
}

/* Handwerk — cold rolled steel, zinc, and the orange of a real Warnweste. */
:root[data-farbe="handwerk"] {
  --ink: #191C1E;
  --ink-2: #24282B;
  --line: rgba(227,230,232,.15);
  --line-soft: rgba(227,230,232,.09);
  --bone: #E3E6E8;
  --bone-dim: rgba(227,230,232,.70);
  --brass: #F07A26;
  --paper: #E3E6E8;
  --paper-ink: #191C1E;
  --paper-dim: rgba(25,28,30,.68);
  --paper-line: rgba(25,28,30,.17);
  --error: #E2624A;
}

/* Maschinenbau — night navy and the washed blue of a blueprint line. */
:root[data-farbe="maschinenbau"] {
  --ink: #0F1926;
  --ink-2: #182534;
  --line: rgba(231,238,245,.15);
  --line-soft: rgba(231,238,245,.09);
  --bone: #E7EEF5;
  --bone-dim: rgba(231,238,245,.70);
  --brass: #6FA6CE;
  --paper: #E7EEF5;
  --paper-ink: #0F1926;
  --paper-dim: rgba(15,25,38,.68);
  --paper-line: rgba(15,25,38,.17);
  --error: #DB6A4C;
}

/* Café — the one LIGHT palette: milk, espresso, terracotta.
   The whole model inverts here. --ink is the light ground and --bone the dark
   text, so the .paper sections (which are the inverse of the page by definition)
   become a dark espresso band inside a milk page instead of the other way round.
   The alpha tokens flip with it: dark ink over a light ground, same hairline
   weight. Do not "fix" this by keeping --paper light — the two would merge and
   #preise would lose its seam. */
:root[data-farbe="cafe"] {
  --ink: #F7F1E6;
  --ink-2: #EFE7D8;
  --line: rgba(43,30,21,.17);
  --line-soft: rgba(43,30,21,.10);
  --bone: #2B1E15;
  --bone-dim: rgba(43,30,21,.74);
  --brass: #A8492A;
  --paper: #2B1E15;
  --paper-ink: #F7F1E6;
  --paper-dim: rgba(247,241,230,.72);
  --paper-line: rgba(247,241,230,.17);
  --error: #95301A;
}

/* ── Three colours the tokens cannot reach ──
   Hard-coded fills that were correct only for the default palette. Scoped to
   [data-farbe] so the untouched default keeps exactly the CSS it has today. */

/* The WhatsApp glyphs are knock-outs: the handset is painted in the BUTTON's
   colour, not in a colour of its own. It was authored as the literal default
   value (#16130F, the glyph of the checkout's sticky bar in components.v2.js),
   so under any other palette a near-black handset sat on a coloured button. */
:root[data-farbe] .sticky-cta-second svg path + path { fill: var(--ink); }
/* The three "browser dots" in the hero mini-browser sit on that frame's own dark
   chrome, not on the page, so they must stay light even when the page is light. */
:root[data-farbe="cafe"] .hb-dot { background: #F5EBDD; }

/* The ground washes over when a palette is PICKED; type and accents snap. Only two
   selectors, so this can never become a whole-document transition — and it is gated
   on [data-farbe-wash], which js/farben.js sets on the first switch and never on
   load: without the gate, arriving at ?farbe=gasthof played a 350ms fade from the
   default ground, i.e. a visible flash of the wrong palette. */
:root[data-farbe-wash] body,
:root[data-farbe-wash] .paper { transition: background-color .35s ease, color .35s ease; }

/* ── The rail ──
   Desktop: a fixed strip on the right edge, vertically centred so it never lands
   on the hero CTA.
   It carries its own --ink ground on purpose: constant contrast for the swatch
   hairlines no matter which section scrolls behind it. */
.farben {
  position: fixed;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  z-index: 88;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .7rem;
  padding: .85rem .55rem;
  background: var(--ink);
  border: 1px solid var(--line);
  border-right: 0;
}
.farben-label {
  writing-mode: vertical-rl;
  font-family: var(--font-mono);
  font-size: .62rem;
  letter-spacing: .06em;
  color: var(--bone-dim);
  text-transform: uppercase;
}
/* .5rem: the site-wide :focus-visible outline is 2px at a 3px offset, so two
   neighbouring chips need 10px between them or the rings touch. */
.farben-group { display: flex; flex-direction: column; gap: .55rem; }
/* Square chips, not dots: they read as pigment samples and they show two colours
   each — the ground the visitor would get, and the accent that sits on it. */
.farben-sw {
  width: 26px;
  height: 26px;
  border: 1px solid var(--line);
  background: linear-gradient(var(--chip-ground) 0 64%, var(--chip-accent) 64% 100%);
  transition: transform .18s ease, box-shadow .18s ease;
}
.farben-sw:hover { transform: translateX(-2px); }
/* Checked ring, drawn OUTSIDE the chip so it never eats into the colour sample.
   :focus-visible keeps the site-wide brass outline; the two never collide. */
.farben-sw[aria-checked="true"] { box-shadow: 0 0 0 2px var(--ink), 0 0 0 3px var(--bone); }
.farben-toggle { display: none; }

.farben-sw[data-farbe="werkstatt"]    { --chip-ground: #16130F; --chip-accent: #D2A62C; }
.farben-sw[data-farbe="gasthof"]      { --chip-ground: #2A1B12; --chip-accent: #E3A73C; }
.farben-sw[data-farbe="friseur"]      { --chip-ground: #241A26; --chip-accent: #D79A8C; }
.farben-sw[data-farbe="handwerk"]     { --chip-ground: #191C1E; --chip-accent: #F07A26; }
.farben-sw[data-farbe="maschinenbau"] { --chip-ground: #0F1926; --chip-accent: #6FA6CE; }
.farben-sw[data-farbe="cafe"]         { --chip-ground: #F7F1E6; --chip-accent: #A8492A; }

/* Phone: a rail on the edge would sit on the text, so it collapses to one pill in
   the bottom right — parked ABOVE the sticky CTA bar (72px, z-index 90) the same
   way body.has-sticky-cta reserves room for it. js/farben.js builds the rail only
   after that bar exists, so the pill is never repositioned after paint (CLS 0). */
@media (max-width: 768px) {
  .farben {
    top: auto;
    bottom: calc(1.1rem + env(safe-area-inset-bottom, 0));
    right: clamp(1rem, 4vw, 2rem);
    transform: none;
    align-items: flex-end;
    gap: .55rem;
    padding: 0;
    background: none;
    border: 0;
  }
  body.has-sticky-cta .farben { bottom: calc(72px + .9rem + env(safe-area-inset-bottom, 0)); }
  .farben-label { display: none; }
  .farben-toggle {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    background: var(--ink);
    color: var(--bone);
    border: 1px solid var(--line);
    border-radius: var(--radius-pill);
    font-family: var(--font-mono);
    font-size: .68rem;
    letter-spacing: .04em;
    padding: .6rem .95rem;
    min-height: 40px;
  }
  .farben-chip { width: 12px; height: 12px; background: var(--brass); flex-shrink: 0; }
  .farben-group {
    flex-direction: row;
    gap: .4rem;
    padding: .5rem;
    background: var(--ink);
    border: 1px solid var(--line);
  }
  .farben:not(.open) .farben-group { display: none; }
  .farben-sw { width: 32px; height: 32px; }
  .farben-sw:hover { transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  :root[data-farbe-wash] body,
  :root[data-farbe-wash] .paper,
  .farben-sw { transition: none; }
  .farben-sw:hover { transform: none; }
}

/* ============================================================================
   A/2 — THE STICKY BAR MUST NOT EAT THE LAST SCREEN (ported from B/16, 2026-09-15)
   The base rule reserves a flat `body.has-sticky-cta{padding-bottom:72px}` for a
   bar that actually measures 73.66px at 360-768px, and the bar adds
   env(safe-area-inset-bottom) to its own padding while the reserve did not — so
   on a notched phone ~36px of the footer sat under the bar.
   76px, not 73.66: the bar's buttons are text-sized and Archivo is
   font-display:optional, so a cold load rendering in the Arial fallback is a
   fraction taller. The 320px rule is not speculative — at 320 the two buttons
   wrap to a second row and the bar measures 99.13px.
   ========================================================================== */
@media (max-width: 768px) {
  body.has-sticky-cta { padding-bottom: calc(76px + env(safe-area-inset-bottom, 0px)); }
}
@media (max-width: 359px) {
  body.has-sticky-cta { padding-bottom: calc(102px + env(safe-area-inset-bottom, 0px)); }
}

/* ============================================================================
   A/3 — .nowrap utility (2026-09-15)
   One legal citation must never break across lines: at <=360px the price
   footnote wrapped after "§ 6 Abs. 1 Z 27" and left "UStG" alone on the next
   line, which reads as a truncated citation. Used in services.html and
   konfigurator.html; kept generic because a paragraph reference is the only
   thing that ever needs it.
   ========================================================================== */
.nowrap { white-space: nowrap; }

/* ============================================================================
   A/4 — THE LANGUAGE DROPDOWN (2026-09-16)
   The nav no longer carries two DE/EN buttons; js/i18n.js renders one
   .wdm-lang listbox into each [data-lang-host] slot. Four languages as a row of
   codes would eat the nav — BRIEF-i18n-2026-09-16, anti-goal 2.
   The component ships neutral defaults and reads four custom properties; these
   are the studio's skin. Everything below is written in TOKENS, not hexes, so
   the same block is correct in werk.css and werk-b.css even though B inverts
   --ink and --bone.
   min-width on the host is the anti-CLS reserve: the control is injected after
   first paint, so the nav has to hold its box before it arrives.
   Since 2026-10-08 (A/5) the host is in the header at every width: the overlay
   menu that used to carry it on phones is gone.
   ========================================================================== */
.lang-host { display: flex; justify-content: flex-end; min-width: 47px; min-height: 30px; }

.wdm-lang {
  --wdm-lang-bg: transparent;
  --wdm-lang-fg: var(--bone-dim);
  --wdm-lang-border: var(--bone-dim);
  --wdm-lang-font: var(--font-mono);
  font-size: .74rem;
}
.wdm-lang__list { background: var(--ink); }
.wdm-lang__btn:hover { color: var(--brass); border-color: var(--brass); }
.wdm-lang__list li[aria-selected="true"] { color: var(--brass); }
.wdm-lang__list li:hover,
.wdm-lang__list li:focus { background: var(--brass); color: var(--ink); }


/* ---------------------------------------------------------------------------
   Footer-Sitemap: alle Hauptseiten
   WHY it is styled here and authored in every page's HTML rather than built by
   js/components.v2.js like the rest of the footer: nav and footer are injected,
   so the raw source used to contain no internal links at all and a crawler that
   does not run JavaScript saw no link graph at all (2026-08-08: nine money pages
   were reachable only through sitemap.xml). components.v2.js moves the authored
   node into the footer, so it renders exactly once.

   The block carries its OWN colour tokens instead of the page's: two of the 24
   pages that hold it (/3d-fit-check/ and the Anna-Schley case study) do not load
   this stylesheet and have light palettes of their own, and the same markup has
   to read the same on all of them.
   --------------------------------------------------------------------------- */
.footer-sitemap {
  --fs-ink: #16130F;
  --fs-bone: #EFE9DE;
  --fs-dim: rgba(239, 233, 222, .68);
  --fs-line: rgba(239, 233, 222, .14);
  --fs-brass: #D2A62C;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(148px, 1fr));
  gap: 1.5rem 2rem;
  margin-bottom: 2rem;
  /* No side padding here, unlike the standalone copy of these rules: .site-footer
     already carries the page gutter, and an extra inset would push the columns
     out of line with the brand text above them. */
  padding: 1.7rem 0 1.5rem;
  border-top: 1px solid var(--fs-line);
  background: var(--fs-ink);
  color: var(--fs-bone);
  font-family: 'Archivo', 'Archivo Fallback', Arial, sans-serif;
  font-size: 1rem;
  line-height: 1.5;
}
.footer-sitemap .fs-h {
  margin: 0 0 .65rem;
  font-family: 'Martian Mono', 'Martian Fallback', 'Courier New', monospace;
  font-weight: 430;
  font-size: .72rem;
  color: var(--fs-dim);
}
.footer-sitemap a {
  display: block;
  padding: .22rem 0;
  max-width: 100%;
  font-size: .93rem;
  color: var(--fs-bone);
  text-decoration: none;
  overflow-wrap: break-word;
  transition: color .15s ease;
}
.footer-sitemap a:hover { color: var(--fs-brass); }
/* Two columns rather than five at phone width: auto-fit would give one very tall
   list, and 148px tracks would overflow a 390px viewport once the gutter is off. */
@media (max-width: 560px) {
  .footer-sitemap { grid-template-columns: 1fr 1fr; gap: 1.2rem 1rem; padding: 1.4rem 0 1.2rem; }
}
/* The legal row may wrap: the French labels need 367px on one line, 31px more than a 360px phone has. */
.footer-legal { flex-wrap: wrap; }


/* ============================================================================
   A/5 — KOPF: THE TRIMMED HEADER (ported from werk.css B/19, 2026-10-08)
   /werkstadt/ loads this file instead of werk.css, so the header rules have to
   live here too: js/components.v2.js builds logo, two links, the language
   dropdown and the WhatsApp pill, and nothing else. The hamburger,
   the overlay .mobile-menu and the nav-fit rules for nine labels were deleted
   from this file with it. Every width gets the same header and no overlay.
   ========================================================================== */
/* 44px tall without looking like a button: the tap target is the padding. */
.nav-links a { padding: .7rem 0; }
/* The language button is drawn 30px tall; its tap area is 44px, grown with an
   invisible pseudo-element so the pill itself keeps its size. */
.site-nav .wdm-lang__btn { position: relative; }
.site-nav .wdm-lang__btn::after { content: ""; position: absolute; inset: -7px 0; }
/* The logo is its own fixed box (it fades on scroll, the bar does not). Same
   height as the bar and centred in it, or the taller links sit lower than it. */
.brand-logo { display: flex; align-items: center; height: 4.75rem; padding-block: 0; }
.site-nav { height: 4.75rem; padding-block: 0; }
@media (max-width: 768px) {
  /* On phones the pill lives in the sticky bar at the bottom of the screen. */
  .site-nav .nav-cta { display: none; }
}
@media (max-width: 480px) {
  /* What has to fit in 312px: the mark, the name, two links and the dropdown. */
  .brand-logo .nav-logo-sub { display: none; }
  .brand-logo .nav-logo-name { font-size: .72rem; line-height: 1.15; width: min-content; }
  .site-nav { gap: .7rem; }
  .nav-links { gap: .7rem; }
  .nav-links a { font-size: .88rem; white-space: nowrap; }
}


/* ============================================================================
   A/6 — THE ROLLOUT: ONE WHATSAPP BUTTON, AND THE CLOSE BLOCK (2026-10-08)
   For every page js/components.v2.js serves; the recipe is docs/rollout-spec.md.
   Same block as css/werk.css B/22; /werkstadt/ loads this sheet instead.
   ========================================================================== */
/* While a WhatsApp button of the page itself is on screen, the header pill and
   the sticky bar step back (components.v2.js watchOwnWa sets body.wa-own).
   visibility, not display: the nav keeps its box and nothing moves. */
body.wa-own .site-nav .nav-cta,
body.wa-own .sticky-cta { visibility: hidden; }
/* The hidden pill would leave a hole at the right end of the header, so the
   links and the language button slide into it. A transform, not a layout
   change: it costs no layout shift when the pill comes back on scroll. */
.site-nav .nav-links,
.site-nav .lang-host { transition: transform .25s ease; }
@media (min-width: 769px) {
  body.wa-own .site-nav .nav-links,
  body.wa-own .site-nav .lang-host { transform: translateX(var(--wa-pill, 0px)); }
}

/* The sticky bar's first button is the WhatsApp one now, and its label is the
   long one. It has to stay on one row beside "Briefing" on a 360px phone. */
.sticky-cta-primary { white-space: nowrap; }
.sticky-cta-second { text-align: center; }
@media (max-width: 420px) {
  .sticky-cta-primary { font-size: .9rem; padding-inline: .55rem; }
  .sticky-cta-second { padding-inline: .85rem; }
}

/* -- START: the close block. One sentence, one button, on the forest ground -- */
/* The only full-colour block on the page. It is the CTA colour turned into a
   wall, so the last screen cannot be mistaken for another content section.
   In this dark sheet the same tokens give ink on brass, the pair every .btn
   here already uses. */
.start { background: var(--brass); color: var(--ink); }
.section + .section.start { border-top: 0; }
.start h2 { max-width: 16ch; margin-bottom: 1.6rem; }
.start .lead { color: var(--ink); margin-bottom: 2.2rem; }
/* Inverted button: the forest .btn would vanish on a forest ground. */
.start-btn { background: var(--ink); color: var(--bone); }
.start-btn:focus-visible { outline-color: var(--ink); }
.start-wege { display: flex; flex-wrap: wrap; align-items: center; gap: .4rem 1.4rem; }
/* werk.css underlines .link-arrow in a tint of the ink; on forest the line and
   the hover colour have to be the paper. */
.start .link-arrow { padding: .7rem 0; text-decoration-color: currentColor; }
.start .link-arrow:hover { color: var(--ink); }
.start-mail { margin-top: 1.4rem; font-size: .78rem; }
.start-mail a { text-decoration: underline; text-underline-offset: 3px; }
/* werk.css draws focus rings in --brass, which IS this section's ground. */
.start a:focus-visible { outline-color: var(--ink); }
.start ::selection { background: var(--ink); color: var(--bone); }


/* ============================================================================
   A/7 — THE MENU BUTTON (2026-10-13)
   Same block as css/werk.css B/24; /werkstadt/ loads this sheet instead.
   js/components.v2.js initMenu() builds one button and one small sheet.
   ========================================================================== */
.nav-menu-wrap { position: relative; display: flex; }
.nav-menu-btn {
  width: 44px; height: 44px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 5px;
  border: 1px solid var(--line); border-radius: var(--radius-pill);
  transition: border-color .15s ease;
}
.nav-menu-btn:hover { border-color: var(--bone); }
.nav-menu-btn span { display: block; width: 18px; height: 2px; background: var(--bone); transition: transform .2s ease, opacity .15s ease; }
.nav-menu-btn[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-menu-btn[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav-menu-btn[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }
.nav-menu {
  position: absolute; top: calc(100% + 1rem); right: 0; z-index: 130;
  width: min(18rem, calc(100vw - 2 * var(--gutter)));
  max-height: calc(100vh - 6.5rem); overflow-y: auto;
  display: flex; flex-direction: column;
  background: var(--ink); border: 1px solid var(--line);
  padding: .6rem 1.2rem 1.2rem;
  box-shadow: 0 18px 40px -24px rgba(0,0,0,.6);
}
.nav-menu[hidden] { display: none; }
.nav-menu a {
  font-variation-settings: var(--wide); font-weight: 680; font-size: 1.02rem;
  color: var(--bone); padding: .62rem 0; border-bottom: 1px solid var(--line-soft);
}
.nav-menu a:hover { color: var(--brass); }
.nav-menu a.active { color: var(--brass); }
.nav-menu a.nav-menu-cta {
  font-variation-settings: normal; align-self: flex-start; margin-top: 1rem; border-bottom: 0;
  background: var(--brass); color: var(--ink); font-weight: 660; font-size: .95rem;
  padding: .7rem 1.3rem; border-radius: var(--radius-pill);
}
.nav-menu a.nav-menu-cta:hover { color: var(--ink); filter: brightness(1.07); }
.nav-menu a.nav-menu-cta:focus-visible { outline-color: var(--bone); }
@media (prefers-reduced-motion: no-preference) {
  .nav-menu:not([hidden]) { animation: nav-menu-in .18s ease-out; }
}
@keyframes nav-menu-in { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }
@media (max-width: 480px) {
  .site-nav .nav-links { display: none; }
}
