/* =========================================================================
   site.css  --  Best Time Hair & Beauty Salon, Baden.
   Neuaufbau vom 2026-07-26, komplett von Grund auf. Die Vorfassungen
   (styles.css, theme.css, v2.css) liegen im Order unter
   backups/frontend-v1-2026-07-26 und werden nicht mehr geladen.

   Gestaltungsidee: «Creamy Editorial».
   Die Grundflaeche ist kein Weiss, sondern ein warmes Cremepapier. Darauf
   liegen tiefe, warme Schrift, Messinglinien und grosse, ruhige Bilder.
   Alles Trennende ist weich: grosse Radien, weiche warme Schatten, keine
   harten Kanten. Der einzige tiefe Ton der Seite ist das Nachtblau des
   Ladenschilds an der Stadtturmstrasse, es traegt Fusszeile und Akzentband.

   Herkunft der Farben: sie sind aus dem Bildmaterial genommen, nicht
   geraten. Das Schild ist nachtblau mit goldener Schrift (salon-12), der
   Innenraum ist weiss mit warmem Holzboden und goldenen Barbierstuehlen
   (hero-01), an den Waenden steht Marmor.

   Schrift: ausschliesslich Standardschriften des Betriebssystems, kein
   Webfont, kein Download. Georgia traegt die Ueberschriften (warm, mit
   echtem Kursiv, auf jedem System vorhanden und dem Schwung des Logos
   nahe), die System-Sans traegt alles andere.

   Aufbau dieser Datei
     01 Marken (Farbe, Schrift, Mass, Bewegung)
     02 Grundlagen und Reset
     03 Typografie
     04 Raster und Sektionsrhythmus
     05 Kopfzeile und Navigation
     06 Knoepfe und Links
     07 Buehne
     08 Bausteine (Karte, Bildrahmen, Band, Liste, Tafel)
     09 Preise
     10 Formulare
     11 Fusszeile
     12 Bewegung und Hilfsklassen
     13 Aktionsfenster
   ========================================================================= */

/* ============================================================ 01 Marken == */
:root {
  /* ---- Papier. Vier Stufen Creme, von hell nach warm. Der Wechsel
          zwischen ihnen gibt der Seite ihren Rhythmus, ohne dass eine
          einzige Trennlinie noetig waere. */
  --paper:       #f6f1e8;   /* Grundflaeche */
  --paper-lift:  #fbf8f2;   /* Karten, Tabellenzeilen */
  --linen:       #efe8db;   /* abgesetztes Band */
  --sand:        #e2d7c4;   /* Linien, Rahmen */
  --sand-deep:   #d3c4aa;   /* Linien auf Leinen */

  /* ---- Schrift. Warmes Tiefschwarz statt reinem Schwarz: auf Creme
          wirkt #000 blaeulich und hart. */
  --ink:      #1e1a15;      /* auf --paper 15.4:1 */
  --ink-soft: #5a5148;      /* auf --paper  6.9:1 */
  --ink-faint:#6f665b;      /* auf --paper 5.0:1, auf --linen 4.6:1 */

  /* ---- Messing. Zwei Werte, weil ein einziger nicht beides kann.
          --brass ist die Linien- und Flaechenfarbe, --brass-ink die
          Textfarbe: erst ab diesem dunkleren Wert traegt Gold auf Creme
          auch kleine Schrift (5.2:1 statt 3.6:1). */
  --brass:     #a98844;
  --brass-ink: #7c6122;     /* auf --paper 5.2:1 */
  --brass-lit: #c9a962;     /* nur auf --night */

  /* ---- Nachtblau. Der Ton des Ladenschilds. Genau zwei Auftritte auf
          der Seite: das Akzentband und die Fusszeile. */
  --night:      #191a20;
  --night-lift: #23242c;
  --on-night:      #f6f1e8; /* 15.4:1 */
  --on-night-soft: #b9b0a2; /*  8.1:1 */

  --white: #ffffff;

  /* ---- Mass. Radien sind gross und weich, das ist der Kern des
          «cremig». Nichts auf dieser Seite hat eine scharfe Ecke. */
  --r-sm: 6px;
  --r-md: 14px;
  --r-lg: 22px;
  --r-xl: 32px;
  --r-pill: 999px;

  /* Warme Schatten. Ein grauer Schatten auf Creme sieht schmutzig aus,
     deshalb steckt in jedem Wert ein Braunanteil. */
  --shadow-sm: 0 1px 2px rgba(72, 55, 30, .05), 0 6px 16px -10px rgba(72, 55, 30, .22);
  --shadow-md: 0 2px 6px rgba(72, 55, 30, .06), 0 22px 44px -28px rgba(72, 55, 30, .38);
  --shadow-lg: 0 4px 12px rgba(72, 55, 30, .07), 0 44px 80px -44px rgba(72, 55, 30, .45);

  /* ---- Schriftfamilien. Beide sind auf dem Geraet vorhanden, es wird
          nichts nachgeladen. */
  --font-display: Georgia, 'Iowan Old Style', 'Palatino Linotype', Palatino,
                  'Times New Roman', serif;
  --font-text: system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue',
               Arial, sans-serif;

  /* ---- Groessenleiter, fliessend zwischen 360px und 1440px. */
  --t-2xs:  clamp(.6875rem, .66rem + .10vw, .75rem);
  --t-xs:   clamp(.75rem,  .72rem + .12vw, .8125rem);
  --t-sm:   clamp(.875rem, .85rem + .12vw, .9375rem);
  --t-base: clamp(1rem,    .96rem + .18vw, 1.0625rem);
  --t-lead: clamp(1.0625rem, .99rem + .34vw, 1.28rem);
  --t-h3:   clamp(1.1875rem, 1.09rem + .42vw, 1.5rem);
  --t-h2:   clamp(1.75rem, 1.36rem + 1.66vw, 2.9rem);
  /* Der Hoechstwert war 4.6rem und damit zu gross fuer eine halbe Spalte:
     die Titelzeile brach dort in vier Zeilen um. 3.85rem passt in eine
     600px-Spalte auf eine Zeile. */
  --t-h1:   clamp(2.2rem, 1.5rem + 2.8vw, 3.85rem);
  --t-mega: clamp(3rem,   1.6rem + 5.9vw, 7rem);
  /* Unterhalb der Breite gaengiger Handys wird --t-h1 noch einmal
     kleiner. Grund: die laengste Ueberschrift der Seite ist ein Wort,
     «Datenschutzerklaerung», und sie misst im sonst kleinsten Grad
     (2.2rem) 326px. Bei 320px Fensterbreite ist der Satzspiegel aber nur
     280px breit, die Zeile lief also ueber den Rand und das letzte
     Zeichen war abgeschnitten. Bei 1.8125rem misst sie 266px und passt.

     Auf hyphens: auto ist kein Verlass: das Trennwoerterbuch laedt
     Chrome erst bei Bedarf nach, und wo es fehlt, schneidet der Browser
     mitten im Wort («Datenschutzerklaer / ung»). Eine kleinere Zeile ist
     die ehrlichere Loesung.

     Der negative Achsenabschnitt sieht falsch aus, ist es aber nicht: er
     legt die Gerade so, dass sie bei 320px auf 29px und bei 384px genau
     auf den bisherigen 35.2px landet. Dadurch gibt es an der Grenze
     keinen Sprung, und ab 384px aendert sich gar nichts. */
  --t-h1-narrow: clamp(1.8125rem, -.125rem + 9.69vw, 2.2rem);

  /* ---- Raum */
  --shell-max:  1240px;
  --shell:      min(var(--shell-max), 100% - 2.5rem);
  --shell-tight: min(880px, 100% - 2.5rem);
  /* Der seitliche Rand des Satzspiegels als eigener Wert. Gebraucht von
     allem, was aus dem Satzspiegel ausbricht und danach wieder auf seine
     Kante zurueck muss.

     Warum nicht einfach 50% wie beim Rand: in scroll-padding beziehen sich
     Prozente auf die BREITE DES SCROLLBEREICHS, nicht auf den umgebenden
     Block. Beim Bildband ist das die volle Fensterbreite, 50% davon sind
     50vw, und die Rechnung ergibt null. Gemessen am 2026-07-26: das erste
     Bild stand 20px statt 100px von links. */
  --gutter:     max(1.25rem, calc(50vw - var(--shell-max) / 2));
  /* War 8.5rem. Zwischen zwei Sektionen stehen zwei davon, also 17rem
     Leerraum, und die Seite las sich als Kette von Inseln. */
  --sp-section: clamp(3.25rem, 2.4rem + 3.4vw, 6rem);
  --sp-block:   clamp(2rem, 1.4rem + 2.4vw, 3.5rem);

  /* Zwei Werte fuer die Kopfzeile, und das ist kein Versehen.
       --header-min  ist fest und bestimmt, wie hoch die Kopfzeile ist.
       --header-h    meldet js/site.js als GEMESSENE Hoehe zurueck; daraus
                     baut html das scroll-padding und die mobile
                     Navigation ihren Startpunkt.
     Sie duerfen nie dieselbe Variable sein. Genau das war sie am
     2026-07-26 kurz: die gemessene Hoehe floss in die min-height zurueck,
     der 1px-Rand kam jedes Mal dazu, und die Kopfzeile wuchs bei jedem
     Messvorgang um eine Zeile weiter. */
  --header-min: 72px;
  --header-h:   72px;

  /* ---- Bewegung */
  --ease: cubic-bezier(.22, .61, .36, 1);
  --ease-out: cubic-bezier(.16, 1, .3, 1);
}

/* ================================================== 02 Grundlagen == */
*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* Ankersprung darf die Ueberschrift nicht hinter die klebende Kopfzeile
     schieben. Den echten Wert meldet js/site.js als --header-h. */
  scroll-padding-top: calc(var(--header-h) + 1.5rem);
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-text);
  font-size: var(--t-base);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

/* Papierkorn. Ein feines Rauschen ueber der ganzen Seite, 3.5% deckend.
   Ohne das wirkt eine grosse Cremeflaeche flach und digital; damit
   bekommt sie eine Oberflaeche. Liegt fest im Viewport, damit es beim
   Scrollen nicht mitwandert, und faengt keine Klicks ab. */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  opacity: .035;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.82' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
}

img, picture, video, svg { display: block; max-width: 100%; }
img { height: auto; }

a { color: inherit; text-decoration: none; }

button, input, select, textarea { font: inherit; color: inherit; }

hr {
  border: 0;
  border-top: 1px solid var(--sand);
  margin: var(--sp-block) 0;
}

::selection { background: var(--brass); color: var(--white); }

:focus-visible {
  outline: 2px solid var(--brass-ink);
  outline-offset: 3px;
  border-radius: var(--r-sm);
}

.skip-link {
  position: absolute;
  left: 1rem;
  top: -4rem;
  z-index: 200;
  padding: .7rem 1.2rem;
  background: var(--ink);
  color: var(--paper);
  border-radius: var(--r-pill);
  font-size: var(--t-sm);
  transition: top .2s var(--ease);
}
.skip-link:focus { top: 1rem; }

/* =================================================== 03 Typografie == */

/* Die Ueberschriften laufen in Georgia. Bei grossen Graden braucht sie
   engere Laufweite, sonst zerfaellt die Zeile; bei kleinen Graden nicht. */
h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 400;
  line-height: 1.08;
  letter-spacing: -.015em;
  margin: 0;
  text-wrap: balance;
}

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

/* --- Eine ruhige Zeile ueber der Titelzeile.

   Der erste Entwurf hatte hier eine gesperrte Versalienmarke mit einer
   Messinglinie davor, und zwar ueber JEDER Sektion. Der Kunde hat das am
   2026-07-26 als Schablone erkannt, zu Recht: ein Zeichen, das ueberall
   steht, sagt nirgends etwas. Es ist ersatzlos gestrichen.

   Was bleibt, ist diese eine Zeile, und sie steht genau einmal auf der
   ganzen Website, ueber der Titelzeile der Startseite. Keine Versalien,
   keine Sperrung, kein Strich. Nur eine kleine Zeile in Messingfarbe. */
.eyebrow {
  margin: 0 0 1rem;
  font-size: var(--t-sm);
  color: var(--brass-ink);
  line-height: 1.4;
}

/* Als Zeile INNERHALB des h1 der Buehne. Sie erbt sonst Georgia und die
   Titelgroesse und wuerde die Ueberschrift sprengen; hier bekommt sie ihre
   eigene Schrift zurueck. Sichtbar ist das Ergebnis dasselbe wie vorher,
   als sie noch ein eigener Absatz war. */
.hero__title .eyebrow {
  display: block;
  font-family: var(--font-text);
  font-weight: 400;
  letter-spacing: 0;
  color: var(--brass-lit);
  margin-bottom: .9rem;
}

/* --- Ueberschriftengrade

   Letztes Netz gegen zu lange Komposita. Greift nur, wenn ein Wort in
   keine Zeile passt, und aendert an allen anderen Stellen nichts. */
h1, h2, h3, .display, .title, .subtitle { overflow-wrap: break-word; }

.display {
  font-size: var(--t-h1);
  line-height: 1.02;
  letter-spacing: -.028em;
}
@media (max-width: 24rem) {
  .display { font-size: var(--t-h1-narrow); }
}
.display--mega { font-size: var(--t-mega); }

.title {
  font-size: var(--t-h2);
  line-height: 1.1;
  letter-spacing: -.02em;
}

.subtitle {
  font-size: var(--t-h3);
  line-height: 1.25;
  letter-spacing: -.01em;
}

/* Das kursive Wort in einer Ueberschrift. Georgia hat ein echtes,
   geschnittenes Kursiv mit Schwung, kein schraeggestelltes Roman. Es
   nimmt den Schwung der Logoschrift auf und ist der einzige Ort, an dem
   die Seite ornamental wird. */
.swash {
  font-style: italic;
  letter-spacing: -.005em;
}
.swash--brass { color: var(--brass-ink); }

.lead {
  font-size: var(--t-lead);
  line-height: 1.55;
  color: var(--ink-soft);
  max-width: 46ch;
  text-wrap: pretty;
}
.lead--wide { max-width: 62ch; }

.prose { max-width: 64ch; }
.prose p + p { margin-top: 1em; }
.prose p { color: var(--ink-soft); text-wrap: pretty; }

.note {
  font-size: var(--t-sm);
  color: var(--ink-faint);
}

/* Zahlen tabellarisch stellen, damit Preise und Zeiten untereinander
   stehen statt zu tanzen. */
.num { font-variant-numeric: tabular-nums; letter-spacing: 0; }

/* Zitat. Keine Anfuehrungsgrafik, sondern eine Messinglinie links und
   Georgia kursiv. */
.pull {
  margin: 1.75rem 0 0;
  padding-left: 1.35rem;
  border-left: 2px solid var(--brass);
  font-family: var(--font-display);
  font-style: italic;
  font-size: var(--t-h3);
  line-height: 1.4;
  color: var(--ink);
}

.sr {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ============================================ 04 Raster und Rhythmus == */

.shell { width: var(--shell); margin-inline: auto; }
.shell-tight { width: var(--shell-tight); margin-inline: auto; }

/* Jede Sektion bringt ihren eigenen Abstand mit. Drei Stufen, damit
   nicht alles gleich weit auseinander steht. */
.section { padding-block: var(--sp-section); position: relative; }
.section--tight { padding-block: calc(var(--sp-section) * .58); }
.section--flush-top { padding-top: 0; }

/* Abgesetztes Band in Leinen. Die Rundung oben und unten laesst die
   Flaeche auf dem Cremepapier liegen, statt es zu durchschneiden. */
.section--linen {
  background: var(--linen);
  border-radius: var(--r-xl);
  width: var(--shell);
  margin-inline: auto;
}

/* Der eine tiefe Auftritt der Seite. */
.section--night {
  background: var(--night);
  color: var(--on-night);
  border-radius: var(--r-xl);
  width: var(--shell);
  margin-inline: auto;
}
.section--night .kicker { color: var(--brass-lit); }
.section--night .kicker::before { background: var(--brass-lit); }
.section--night .lead,
.section--night .prose p { color: var(--on-night-soft); }

/* Sektionskopf: Kicker, Ueberschrift, Vorspann, optional ein Link
   rechts. Auf schmalen Displays stapelt er, ab 62rem stehen Text links
   und Link rechts auf einer Grundlinie. */
.head { margin-bottom: var(--sp-block); }
.head__top {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1.5rem 2.5rem;
}
.head__lead { margin-top: 1.1rem; }

/* Allgemeines Spaltenraster. Die Zahl im Namen ist die Spaltenzahl ab
   62rem, darunter ist alles einspaltig. */
.cols { display: grid; gap: clamp(1.5rem, 1rem + 2vw, 2.75rem); }
@media (min-width: 48rem) {
  .cols--2 { grid-template-columns: repeat(2, 1fr); }
  .cols--3 { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 62rem) {
  .cols--3 { grid-template-columns: repeat(3, 1fr); }
  .cols--4 { grid-template-columns: repeat(4, 1fr); }
}

/* Bild und Text nebeneinander, im Verhaeltnis 7:5. Mit --flip steht das
   Bild rechts. Der Wechsel gibt langen Seiten ihren Takt. */
.split {
  display: grid;
  gap: clamp(1.75rem, 1rem + 3.5vw, 4rem);
  align-items: center;
}
@media (min-width: 56rem) {
  .split { grid-template-columns: 7fr 5fr; }
  .split--even { grid-template-columns: 1fr 1fr; }
  .split--flip > :first-child { order: 2; }
}

/* ======================================= 05 Kopfzeile und Navigation == */

.header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: rgba(246, 241, 232, .82);
  backdrop-filter: saturate(140%) blur(14px);
  -webkit-backdrop-filter: saturate(140%) blur(14px);
  border-bottom: 1px solid transparent;
  transition: border-color .3s var(--ease), background .3s var(--ease);
}
.header.is-scrolled {
  border-bottom-color: var(--sand);
  background: rgba(246, 241, 232, .94);
}

.header__inner {
  width: var(--shell);
  margin-inline: auto;
  min-height: var(--header-min);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

/* Logo-Badge plus Wortmarke. Das B-Monogramm steht auf seinem dunklen
   Grund, daneben der Name in Georgia mit gesperrtem Untertitel. Texte
   bleiben auf einer Baseline, das Badge haengt sich mittig dazwischen.

   2026-08-26: Wortmarke in Gold statt Tiefschwarz/Oliv, Wunsch vom User
   nach der neuen Schaufensterbeschriftung (dort steht «BEST TIME
   COIFFEUR» in sattem Gold). Zweiter Durchgang gleichentags: das erste
   Gold basierte auf dem Messing der Seite (--brass) und wirkte weiter
   olivstichig. Jetzt klassisches Metallic Gold #d4af37 als Mittelton,
   dazu Highlight und Schatten fuer den Metall-Eindruck. Der Verlauf
   laeuft von hell nach tief, damit die Schrift auf Creme nicht zu Brei
   wird; der Fallback ohne background-clip ist der tiefe Goldton. */
.brand { display: inline-flex; align-items: baseline; gap: .55rem; padding: .5rem 0; }
.brand__mark { align-self: center; flex: none; margin-right: .15rem; }
.brand__mark img {
  display: block;
  width: clamp(2.35rem, 2.1rem + .8vw, 2.75rem);
  height: auto;
  border-radius: 24%;
  box-shadow: 0 1px 4px rgba(20, 18, 14, .25);
}
.brand__name {
  font-family: var(--font-display);
  font-size: clamp(1.25rem, 1.1rem + .5vw, 1.5rem);
  letter-spacing: -.02em;
  line-height: 1;
  color: #9c7a1e;
}
@supports ((background-clip: text) or (-webkit-background-clip: text)) {
  .brand__name {
    background: linear-gradient(172deg, #e9c55e 0%, #d4af37 45%, #9c7a1e 100%);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
  }
}
.brand__sub {
  display: none;
  font-size: var(--t-2xs);
  letter-spacing: .2em;
  text-transform: uppercase;
  color: #b08c26;
  white-space: nowrap;
}
@media (min-width: 34rem) { .brand__sub { display: inline; } }

.nav { display: flex; align-items: center; gap: clamp(1rem, 2.2vw, 2rem); }

.nav__list {
  display: flex;
  align-items: center;
  gap: clamp(.9rem, 1.6vw, 1.75rem);
  list-style: none;
  margin: 0;
  padding: 0;
}

/* Der aktive Punkt bekommt keinen Balken, sondern eine Messinglinie
   unter der Schrift. Beim Hovern waechst dieselbe Linie ein. */
.nav__link {
  position: relative;
  display: inline-block;
  padding: .35rem 0;
  font-size: var(--t-sm);
  color: var(--ink-soft);
  transition: color .2s var(--ease);
}
.nav__link::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 1px;
  background: var(--brass);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .3s var(--ease);
}
.nav__link:hover { color: var(--ink); }
.nav__link:hover::after { transform: scaleX(1); }
.nav__link[aria-current='page'] { color: var(--ink); }
.nav__link[aria-current='page']::after { transform: scaleX(1); }

.nav__side { display: flex; align-items: center; gap: clamp(.6rem, 1.4vw, 1.1rem); }

.nav__lang {
  font-size: var(--t-xs);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ink-soft);
  padding: .4rem .2rem;
  transition: color .2s var(--ease);
}
.nav__lang:hover { color: var(--brass-ink); }

.nav__phone {
  display: none;
  align-items: center;
  gap: .5rem;
  font-size: var(--t-sm);
  color: var(--ink-soft);
  transition: color .2s var(--ease);
}
.nav__phone:hover { color: var(--ink); }
.nav__phone svg { width: 1rem; height: 1rem; }
@media (min-width: 78rem) { .nav__phone { display: inline-flex; } }

/* Menuknopf. Zwei Striche, die sich zum Kreuz drehen. */
.burger {
  display: inline-flex;
  flex-direction: column;
  justify-content: center;
  gap: 6px;
  width: 44px; height: 44px;
  padding: 0 10px;
  background: none;
  border: 0;
  border-radius: var(--r-sm);
  cursor: pointer;
}
.burger span {
  display: block;
  height: 1.5px;
  background: var(--ink);
  border-radius: 2px;
  transition: transform .3s var(--ease), opacity .2s var(--ease);
}
.burger[aria-expanded='true'] span:first-child { transform: translateY(3.75px) rotate(45deg); }
.burger[aria-expanded='true'] span:last-child  { transform: translateY(-3.75px) rotate(-45deg); }

@media (min-width: 62rem) {
  .burger { display: none; }
}

/* Unter 62rem faehrt die Navigation als Blatt unter der Kopfzeile aus. */
@media (max-width: 61.999rem) {
  .nav {
    position: fixed;
    inset: var(--header-h) 0 auto 0;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: 1.25rem 1.25rem 2rem;
    background: var(--paper);
    border-bottom: 1px solid var(--sand);
    box-shadow: var(--shadow-md);
    max-height: calc(100dvh - var(--header-h));
    overflow-y: auto;
    transform: translateY(-102%);
    visibility: hidden;
    transition: transform .38s var(--ease-out), visibility .38s;
  }
  .nav.is-open { transform: translateY(0); visibility: visible; }

  .nav__list { flex-direction: column; align-items: stretch; gap: 0; }
  .nav__list li + li { border-top: 1px solid var(--sand); }
  .nav__link {
    padding: .95rem .25rem;
    font-family: var(--font-display);
    font-size: 1.35rem;
    color: var(--ink);
  }
  .nav__link::after { display: none; }
  .nav__link[aria-current='page'] { color: var(--brass-ink); }

  .nav__side {
    margin-top: 1.5rem;
    flex-direction: column;
    align-items: stretch;
    gap: .75rem;
  }
  .nav__phone { display: inline-flex; justify-content: center; }
  .nav__lang { text-align: center; }
}

/* --- Knopf «nach oben», fest unten rechts. Nur auf schmalen Displays:
       am Desktop ist der Weg nach oben eine Radumdrehung, auf dem Handy
       sind es bei diesen langen Seiten viele Wischer. Dieselbe Grenze wie
       beim Menue, damit die Seite genau einen Begriff von «schmal» hat.

       Nachtblau statt Creme: der Knopf liegt ueber wechselnden Flaechen
       (Papier, Leinen, Bild, Fusszeile) und muss auf allen vieren stehen.
       Das ist der einzige Ort ausserhalb von Band und Fusszeile, an dem
       das Nachtblau auftritt, und er ist klein genug dafuer. */
.totop {
  position: fixed;
  z-index: 90;
  right: max(1rem, env(safe-area-inset-right));
  bottom: max(1rem, env(safe-area-inset-bottom));
  display: grid;
  place-items: center;
  /* 46px. Ueber der Mindestgroesse von 44px fuer eine Fingerflaeche. */
  width: 2.875rem;
  height: 2.875rem;
  padding: 0;
  border: 1px solid rgba(246, 241, 232, .18);
  border-radius: var(--r-pill);
  background: var(--night);
  color: var(--on-night);
  box-shadow: var(--shadow-md);
  cursor: pointer;
  /* Ruhezustand. js/site.js setzt is-in, sobald weit genug gescrollt
     wurde. visibility nimmt ihn solange aus der Tabreihenfolge und aus
     dem Vorlesebaum; ohne Script bleibt er unsichtbar, und die Seite
     verliert dadurch nichts. */
  opacity: 0;
  visibility: hidden;
  transform: translateY(.75rem);
  transition: opacity .3s var(--ease), transform .3s var(--ease), visibility .3s;
}
.totop svg { width: 1.15rem; height: 1.15rem; }
.totop.is-in { opacity: 1; visibility: visible; transform: none; }
.totop:active { transform: translateY(1px); }

/* Bei offenem Menue waere er nur ein Fleck auf dem Menueblatt. */
body:has(.nav.is-open) .totop { opacity: 0; visibility: hidden; }

@media (min-width: 62rem) {
  .totop { display: none; }
}

/* ======================================== 06 Knoepfe und Textlinks == */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .6rem;
  padding: .85rem 1.6rem;
  border: 1px solid transparent;
  border-radius: var(--r-pill);
  font-size: var(--t-sm);
  font-weight: 500;
  letter-spacing: .01em;
  cursor: pointer;
  text-align: center;
  transition: background .25s var(--ease), color .25s var(--ease),
              border-color .25s var(--ease), transform .25s var(--ease),
              box-shadow .25s var(--ease);
}
.btn:active { transform: translateY(1px); }

/* Hauptaufruf: tiefe Tinte, kein Gold. Gold als Flaeche wirkt auf Creme
   schnell billig; als Linie und als kleine Schrift traegt es besser.
   Beim Hovern wandert die Flaeche ins Messing. */
.btn--solid {
  background: var(--ink);
  color: var(--paper);
  box-shadow: var(--shadow-sm);
}
.btn--solid:hover { background: var(--brass-ink); box-shadow: var(--shadow-md); }

.btn--line {
  background: transparent;
  color: var(--ink);
  border-color: var(--sand-deep);
}
.btn--line:hover { border-color: var(--ink); background: var(--paper-lift); }

.btn--ghost { background: transparent; color: var(--ink); }
.btn--ghost:hover { color: var(--brass-ink); }

/* Auf Nachtblau kehren sich die Werte um. */
.section--night .btn--solid,
.footer .btn--solid { background: var(--paper); color: var(--ink); }
.section--night .btn--solid:hover,
.footer .btn--solid:hover { background: var(--brass-lit); }
.section--night .btn--line,
.footer .btn--line { color: var(--on-night); border-color: rgba(246, 241, 232, .3); }
.section--night .btn--line:hover,
.footer .btn--line:hover { border-color: var(--on-night); background: rgba(246, 241, 232, .07); }

.actions {
  display: flex;
  flex-wrap: wrap;
  gap: .75rem;
  margin-top: var(--sp-block);
}
.actions--tight { margin-top: 1.5rem; }
.actions--center { justify-content: center; }

/* Textlink mit Pfeil. Der Pfeil rueckt beim Hovern nach, die Linie
   darunter laeuft von links ein. */
.arrowlink {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  padding-bottom: 3px;
  font-size: var(--t-sm);
  font-weight: 500;
  color: var(--brass-ink);
}
.arrowlink::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 1px;
  background: currentColor;
  opacity: 0;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .35s var(--ease), opacity .25s var(--ease);
}
.arrowlink:hover::after { opacity: .8; transform: scaleX(1); }
.arrowlink svg { width: .95rem; height: .95rem; transition: transform .3s var(--ease); }
.arrowlink:hover svg { transform: translateX(3px); }
.section--night .arrowlink { color: var(--brass-lit); }

/* =============================================================== 07 Buehne */

/* Aufbau nach dem Vorbild von sites/ENi (Wunsch des Kunden vom
   2026-07-26). ENi hat dasselbe Grundproblem: zwei gleichwertige
   Standbeine, die beide in der ersten Sekunde sichtbar sein muessen.
   Dort Reinigung und Garten, hier Coiffeur und Beauty.

   Uebernommen ist die Anlage: randabfallender Film, abgedunkelt, darauf
   mittig die Schrift und darunter zwei gleich grosse Einstiege.

   Zwei Dinge sind ausdruecklich anders:

   1  Der Hero ist der einzige dunkle Ort der Website, alles danach ist
      Cremepapier. Das ist kein Bruch, sondern der Weg von der Strasse in
      den Laden: das Schild an der Stadtturmstrasse ist nachtblau mit
      Goldschrift, drinnen ist alles weiss und hell.
   2  Die Abdunklung ist warm (Nachtblau mit Braunanteil), nicht das kuehle
      Schieferblau von ENi. Auf Creme wuerde ein kuehler Hero kalt wirken.

   Der Film selbst wird von scripts/build-hero-clip.mjs geschnitten und
   zeigt abwechselnd Coiffeur und Beauty. Dieselbe Aussage wie die zwei
   Einstiege darunter, nur in Bewegung. */
.hero {
  position: relative;
  isolation: isolate;
  display: flex;
  align-items: flex-end;
  min-height: min(92vh, 52rem);
  padding-block: clamp(4rem, 3rem + 6vw, 8rem) clamp(3.5rem, 2rem + 6vw, 7rem);
  background: var(--night);
  color: var(--on-night);
  overflow: hidden;
}

/* Ebenen der Buehne: 0 Film, 1 Schleier, 2 Schrift. Alle Werte positiv.

   Vorher lagen Film und Schleier auf -2 und -1, also hinter dem Inhalt.
   In Chrome sah das richtig aus. Auf iOS blieb die Flaeche schwarz: WebKit
   zeichnet ein hardwarebeschleunigtes <video> mit negativem z-index in
   einem eigenen Stapelkontext nicht zuverlaessig, und zwar samt seinem
   poster. Am 2026-07-26 auf einem iPhone genau so gesehen, waehrend jeder
   Test in Chrome gruen war.

   Merksatz: negativer z-index ist fuer Hintergrundvideo kein Werkzeug. */
.hero__video {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Die Abdunklung. Oben etwas staerker, damit die Kopfzeile traegt, in der
   Mitte am dichtesten, wo die Schrift steht. */
.hero__veil {
  position: absolute;
  inset: 0;
  z-index: 1;
  background:
    linear-gradient(to bottom,
      rgba(20, 18, 15, .72) 0%,
      rgba(20, 18, 15, .58) 30%,
      rgba(20, 18, 15, .62) 62%,
      rgba(20, 18, 15, .82) 100%);
}

.hero__content { position: relative; z-index: 2; }
.hero__title { margin-bottom: 1.25rem; color: var(--on-night); }
.hero__title span { display: block; }
.hero__title .swash { color: var(--brass-lit); }
/* Die Zeile unter dem Titel. Bewusst kurz: sie ist eine Losung, kein
   Absatz. Der ausfuehrliche Text steht im Band darunter und in der
   Sektion «Hair und Beauty, unter einem Dach». */
.hero__lead {
  max-width: 34ch;
  color: rgba(246, 241, 232, .88);
  font-size: var(--t-lead);
}
.hero .eyebrow { color: var(--brass-lit); }

/* --- Die beiden Einstiege.

       Sie waren zuerst zwei grosse Tafeln mit Icon, Titel, Untertitel und
       Pfeil. Zusammen mit Kicker, Titel, Vorspann und der Faktenzeile
       standen damit fuenf Bloecke uebereinander in der Buehne. Rueckmeldung
       vom 2026-07-26: der erste Eindruck ist der wichtigste, und darin
       gehoeren nur der Name, ein Satz und ein paar Knoepfe.

       Was bleibt, ist die Aufteilung selbst: die beiden Knoepfe heissen
       Coiffeur und Beauty und nicht Kontakt und Galerie. Dass Best Time
       auch Kosmetik macht, ist die eine Sache, die hier oben stehen muss.

       Beide gleich gebaut, keiner gefuellt: keiner der zwei Bereiche ist
       der Nebeneingang. Der gefuellte Knopf fuer die Terminbuchung steht
       in der Kopfzeile und ist beim Scrollen immer da. */
.hero .actions { margin-top: clamp(1.75rem, 1.2rem + 1.6vw, 2.5rem); }

@media (min-width: 60rem) { .hero { align-items: center; } }

.hero .btn--line {
  color: var(--on-night);
  border-color: rgba(246, 241, 232, .42);
  background: rgba(20, 18, 15, .28);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  padding-inline: clamp(1.6rem, 1rem + 2vw, 2.5rem);
}
.hero .btn--line:hover {
  background: var(--paper);
  border-color: var(--paper);
  color: var(--ink);
}

/* Das schmale Band direkt unter der Buehne: Zeiten, Adresse, Angebot.
   Es stand zuerst IN der Buehne und war dort der fuenfte Textblock. Hier
   unten auf Creme steht es dort, wo man es sucht, ohne den ersten Eindruck
   zu verstopfen. */
.ribbon { border-bottom: 1px solid var(--sand); background: var(--paper-lift); }
.ribbon__grid {
  display: grid;
  gap: 1.25rem 2.5rem;
  padding-block: clamp(1.25rem, 1rem + 1.2vw, 1.9rem);
}
@media (min-width: 44rem) { .ribbon__grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

.factlet__label {
  display: block;
  font-size: var(--t-xs);
  color: var(--ink-faint);
  margin-bottom: .3rem;
}
.factlet__value { font-size: var(--t-sm); line-height: 1.55; color: var(--ink); }
.factlet__value strong { font-weight: 600; }

/* Seitenkopf der Unterseiten. Gleiche Handschrift wie die Buehne, nur
   ohne Bild und flacher. */
.pagehead {
  padding-top: clamp(2.5rem, 1.5rem + 4vw, 5rem);
  padding-bottom: clamp(2rem, 1.4rem + 2.6vw, 3.5rem);
  border-bottom: 1px solid var(--sand);
}
.pagehead__title { margin-bottom: 1.25rem; }

/* ========================================================= 08 Bausteine == */

/* --- Bildrahmen. Jedes Bild der Seite laeuft hier durch: weiche Ecken,
       ein Hauch Rahmen, und beim Hovern zieht das Motiv langsam an. */
.frame {
  position: relative;
  overflow: hidden;
  border-radius: var(--r-lg);
  background: var(--linen);
  box-shadow: var(--shadow-md);
}
/* picture braucht die volle Hoehe, sonst legt sich das img in ein Kaestchen
   eigener Hoehe und der Rahmen bleibt unten leer. */
.frame picture { height: 100%; }
.frame img { width: 100%; height: 100%; object-fit: cover; }
.frame--sm { border-radius: var(--r-md); box-shadow: var(--shadow-sm); }
.frame--tall { aspect-ratio: 4 / 5; }
.frame--wide { aspect-ratio: 3 / 2; }
.frame--square { aspect-ratio: 1 / 1; }

a.frame img, .frame--zoom img {
  transition: transform .9s var(--ease-out);
}
a.frame:hover img, .frame--zoom:hover img { transform: scale(1.045); }

/* Bildunterschrift. Steht unter dem Rahmen, klein und gesperrt. */
figure { margin: 0; }
figcaption {
  margin-top: .75rem;
  font-size: var(--t-xs);
  letter-spacing: .04em;
  color: var(--ink-faint);
}

/* --- Karte. Der Grundbaustein fuer alles Aufzaehlende. */
.card {
  display: flex;
  flex-direction: column;
  background: var(--paper-lift);
  border: 1px solid var(--sand);
  border-radius: var(--r-lg);
  padding: clamp(1.35rem, 1rem + 1.2vw, 2rem);
  transition: transform .35s var(--ease), box-shadow .35s var(--ease),
              border-color .35s var(--ease);
}
a.card:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-md);
  border-color: var(--sand-deep);
}
.card__icon {
  width: 2.6rem; height: 2.6rem;
  display: grid;
  place-items: center;
  margin-bottom: 1.1rem;
  border-radius: var(--r-pill);
  background: var(--linen);
  color: var(--brass-ink);
}
.card__icon svg { width: 1.3rem; height: 1.3rem; }
.card__title { font-size: var(--t-h3); margin-bottom: .6rem; }
.card__text { color: var(--ink-soft); font-size: var(--t-sm); margin: 0; }
.card__foot { margin-top: auto; padding-top: 1.25rem; }

/* Karte mit Bild oben. Das Bild sitzt buendig in der Rundung.
   display:block ist noetig, weil die Huelle im Markup ein <span> ist (ein
   <div> waere in einem <a> nicht erlaubt): auf einem Inline-Element
   greift aspect-ratio nicht, und die Karte bliebe leer. */
.card--media { padding: 0; overflow: hidden; }
.card--media .card__media { display: block; aspect-ratio: 3 / 2; overflow: hidden; background: var(--linen); }
.card--media .card__media picture { height: 100%; }
.card--media .card__media img { width: 100%; height: 100%; object-fit: cover; transition: transform .9s var(--ease-out); }
a.card--media:hover .card__media img { transform: scale(1.045); }
.card--media .card__body {
  display: flex;
  flex-direction: column;
  flex: 1;
  padding: clamp(1.25rem, 1rem + 1vw, 1.75rem);
}

/* --- Eintrag. Die ausfuehrliche Form einer Leistung auf der Seite
       Dienstleistungen: Bild oder Zeichen, Text, rechts Preis und Aufruf.
       Getrennt durch Haarlinien statt durch Kaesten, damit zehn Eintraege
       untereinander nicht wie zehn Werbebanner wirken. */
.stack > * + * { margin-top: 0; }
.stack > * { border-top: 1px solid var(--sand); }
.stack > :first-child { border-top: 0; }

.entry {
  display: grid;
  gap: 1.25rem 2rem;
  padding-block: clamp(1.75rem, 1.2rem + 2vw, 3rem);
  /* Der Ankersprung von der Startseite soll oberhalb des Eintrags landen. */
  scroll-margin-top: calc(var(--header-h) + 2rem);
}
@media (min-width: 56rem) {
  .entry { grid-template-columns: clamp(9rem, 16vw, 13rem) 1fr auto; align-items: start; }
}
.entry__media { border-radius: var(--r-md); }
.entry__mark {
  display: grid;
  place-items: center;
  aspect-ratio: 1 / 1;
  width: clamp(4.5rem, 12vw, 100%);
  border: 1px solid var(--sand);
  border-radius: var(--r-md);
  background: var(--paper-lift);
  color: var(--brass);
}
.entry__mark svg { width: 38%; height: 38%; max-width: 3rem; }
.section--linen .entry__mark { background: var(--paper); border-color: var(--sand-deep); }
.entry__text { color: var(--ink-soft); margin: .5rem 0 0; max-width: 58ch; }
.entry__side { display: grid; gap: .8rem; justify-items: start; }
@media (min-width: 56rem) {
  .entry__side { justify-items: end; text-align: right; min-width: 10rem; }
}
.entry__price { font-family: var(--font-display); font-size: var(--t-h3); margin: 0; }
.entry__price span {
  display: block;
  font-family: var(--font-text);
  font-size: var(--t-xs);
  color: var(--ink-faint);
  margin-bottom: .15rem;
}

/* Aufzaehlung mit Haken. Kein Listenpunkt, sondern das Icon aus dem
   eigenen Satz, damit auf der ganzen Seite dieselben Formen stehen. */
.ticks { list-style: none; margin: 1.1rem 0 0; padding: 0; display: grid; gap: .55rem; }
.ticks li { display: flex; gap: .65rem; align-items: flex-start; font-size: var(--t-sm); color: var(--ink-soft); }
.ticks svg { width: 1rem; height: 1rem; flex: 0 0 auto; margin-top: .35rem; color: var(--brass-ink); }

/* --- Register. Die Leistungsliste als Zeilen statt als Kachelfeld:
       zehn gleich grosse Kacheln sind eine Wand, zehn Zeilen sind ein
       Inhaltsverzeichnis. Die Messinglinie links waechst beim Hovern. */
.rows { border-top: 1px solid var(--sand); }

.row {
  position: relative;
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: .35rem 1.5rem;
  padding: clamp(1.1rem, .9rem + .8vw, 1.65rem) 0;
  border-bottom: 1px solid var(--sand);
  transition: padding-left .35s var(--ease);
}
.row::before {
  content: '';
  position: absolute;
  left: 0; top: 50%;
  width: 0; height: 1px;
  background: var(--brass);
  transform: translateY(-50%);
  transition: width .35s var(--ease);
}
.row:hover { padding-left: 2.5rem; }
.row:hover::before { width: 1.75rem; }

.row__title {
  grid-column: 1;
  font-family: var(--font-display);
  font-size: var(--t-h3);
  line-height: 1.2;
  letter-spacing: -.015em;
}
.row__text {
  grid-column: 1;
  font-size: var(--t-sm);
  color: var(--ink-soft);
  max-width: 58ch;
  margin: 0;
}
.row__meta {
  grid-column: 2;
  grid-row: 1 / span 2;
  display: flex;
  align-items: center;
  gap: 1.25rem;
}
.row__price {
  font-size: var(--t-sm);
  color: var(--ink-soft);
  white-space: nowrap;
}
.row__go {
  flex: 0 0 auto;
  width: 2.4rem; height: 2.4rem;
  display: grid;
  place-items: center;
  border: 1px solid var(--sand-deep);
  border-radius: var(--r-pill);
  color: var(--brass-ink);
  transition: background .3s var(--ease), color .3s var(--ease),
              border-color .3s var(--ease), transform .3s var(--ease);
}
.row__go svg { width: 1rem; height: 1rem; }
.row:hover .row__go {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--paper);
  transform: translateX(3px);
}

/* Zeile mit Vorschaubild. Nur die Leistungen, fuer die es wirklich eine
   Aufnahme gibt, bekommen eins; die anderen bleiben ohne. Der ungleiche
   Rhythmus kommt damit aus den Daten und nicht aus Handarbeit. */
.row--media { grid-template-columns: auto 1fr auto; }
.row--media .row__thumb {
  grid-column: 1;
  grid-row: 1 / span 2;
  width: clamp(3.5rem, 8vw, 5.5rem);
  aspect-ratio: 1 / 1;
  border-radius: var(--r-md);
  overflow: hidden;
  background: var(--linen);
}
.row--media .row__thumb picture { height: 100%; }
.row--media .row__thumb img { width: 100%; height: 100%; object-fit: cover; }
.row--media .row__title,
.row--media .row__text { grid-column: 2; }
.row--media .row__meta { grid-column: 3; }

@media (max-width: 40rem) {
  .row__meta { grid-column: 2; grid-row: 1; }
  .row__price { display: none; }
  .row--media .row__meta { grid-column: 3; grid-row: 1 / span 2; }
}

/* --- Bildkachel. Das Gegenstueck zur service-card von ENi: ein grosses
       Bild, darauf ein Verlauf und unten der Text. Zwei Unterschiede zur
       Vorlage: der Verlauf ist warm statt schieferblau, und der Rahmen
       innen ist eine Messinglinie, kein weisser Schimmer.

       Die Hoehe ist bewusst gross. Eine flache Kachel liest sich als
       Knopf, eine hohe als Bild, und hier ist das Bild die Aussage. */
.tile {
  position: relative;
  display: block;
  min-height: clamp(20rem, 46vh, 30rem);
  border-radius: var(--r-lg);
  overflow: hidden;
  /* Nachtblau, nicht Leinen: die Beschriftung ist cremefarben und stuende
     sonst unsichtbar da, wenn das Foto nicht laedt. */
  background: var(--night);
  box-shadow: var(--shadow-md);
  transition: transform .35s var(--ease), box-shadow .35s var(--ease);
}
.tile:hover { transform: translateY(-4px); box-shadow: var(--shadow-lg); }

.tile__media { position: absolute; inset: 0; }
.tile__media picture, .tile__media img { width: 100%; height: 100%; object-fit: cover; }
.tile__media img { transition: transform 1s var(--ease-out); }
.tile:hover .tile__media img { transform: scale(1.06); }

.tile__veil {
  position: absolute;
  inset: 0;
  /* Der Verlauf muss bis auf Hoehe der Ueberschrift tragen, nicht nur bis
     zur Unterkante: bei «Herren Coiffeur» lag die Zeile sonst auf einer
     hellen Wand und war kaum zu lesen. */
  background: linear-gradient(to top,
    rgba(20, 18, 15, .90) 0%,
    rgba(20, 18, 15, .80) 26%,
    rgba(20, 18, 15, .46) 52%,
    rgba(20, 18, 15, .12) 78%,
    rgba(20, 18, 15, .04) 100%);
}
/* Der eingesetzte Messingrahmen, erscheint beim Hovern. */
.tile::after {
  content: '';
  position: absolute;
  inset: 12px;
  border: 1px solid rgba(201, 169, 98, .55);
  border-radius: calc(var(--r-lg) - 8px);
  opacity: 0;
  transform: scale(.99);
  transition: opacity .35s var(--ease), transform .35s var(--ease);
  pointer-events: none;
}
.tile:hover::after { opacity: 1; transform: scale(1); }

.tile__body {
  position: absolute;
  inset: auto 0 0 0;
  padding: clamp(1.25rem, 1rem + 1.2vw, 1.9rem);
  color: var(--on-night);
}
.tile__title { font-family: var(--font-display); font-size: var(--t-h3); line-height: 1.2; letter-spacing: -.015em; display: block; }
.tile__text { display: block; margin-top: .4rem; font-size: var(--t-sm); color: rgba(246, 241, 232, .82); }
.tile__more {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  margin-top: .9rem;
  font-size: var(--t-sm);
  color: var(--brass-lit);
}
.tile__more svg { width: 1rem; height: 1rem; transition: transform .3s var(--ease); }
.tile:hover .tile__more svg { transform: translateX(4px); }

/* --- Merkmalsliste als Zeile statt als Spalte.

       Die Leistungen standen zuerst als senkrechte Haekchenliste unter dem
       Text. Bei sechs Beauty-Leistungen sind das sechs Zeilen, und die
       Sektion wurde damit hoeher als der Bildschirm. Als umbrechende
       Reihe brauchen dieselben sechs Eintraege zwei Zeilen. */
.chips { display: flex; flex-wrap: wrap; gap: .45rem; margin: 1.1rem 0 0; padding: 0; list-style: none; }
.chips li {
  font-size: var(--t-xs);
  line-height: 1.4;
  padding: .35rem .8rem;
  border: 1px solid var(--sand-deep);
  border-radius: var(--r-pill);
  background: var(--paper);
  color: var(--ink-soft);
}
.section--linen .chips li { background: var(--paper-lift); }

/* --- Bildpaar. Ein hohes Bild, davor unten versetzt ein kleines. Diese
       eine Ueberschneidung bricht das Raster und ist der Grund, warum die
       Seite nicht wie ein Baukasten aussieht. Unter 44rem stehen beide
       Bilder einfach untereinander, dort waere die Ueberlappung eng. */
.duo { position: relative; }
.duo__main { border-radius: var(--r-lg); overflow: hidden; }
.duo__sub { margin-top: 1rem; }
@media (min-width: 44rem) {
  .duo { padding-bottom: clamp(2.5rem, 6vw, 5rem); padding-right: clamp(2rem, 6vw, 4.5rem); }
  .duo__sub {
    position: absolute;
    right: 0;
    bottom: 0;
    width: clamp(9rem, 34%, 15rem);
    margin-top: 0;
    border: 6px solid var(--paper);
    border-radius: calc(var(--r-md) + 6px);
    box-shadow: var(--shadow-lg);
    overflow: hidden;
  }
  .duo__sub img { border-radius: calc(var(--r-md) - 4px); }
}
/* Auf Leinen muss der Rand der Farbe des Bandes folgen, sonst schwebt ein
   cremefarbener Rahmen auf beigem Grund. */
.section--linen .duo__sub { border-color: var(--linen); }

/* --- Bildband. Waagerechte Schiene mit Schnappen, auf dem Handy die
       natuerliche Geste, am Desktop ein ruhiger Streifen.

   .railwrap ist nur der Bezugspunkt fuer die beiden Knoepfe. Es bekommt
   ausdruecklich KEINE Breite, kein Raster und kein overflow: der Streifen
   rechnet seinen Ausbruch mit 50% seines umgebenden Blocks, und das muss
   weiterhin der Satzspiegel sein. */
.railwrap { position: relative; }

.rail {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: min(78vw, 26rem);
  gap: clamp(1rem, .6rem + 1.4vw, 1.75rem);
  overflow-x: auto;
  /* Senkrecht darf hier gar nichts laufen. overflow-x allein genuegt
     dafuer nicht: sobald eine Achse scrollt, macht der Browser aus dem
     visible der anderen Achse ein auto. Der Streifen hatte deshalb neben
     der waagerechten auch eine senkrechte Leiste und liess sich um ein
     paar Pixel hoch und runter schieben. Der Schatten der Rahmen sitzt
     unter dem Bild, mitten im Streifen, ihn schneidet das nicht an. */
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  padding-bottom: 1rem;
  /* Der Streifen laeuft ueber den Satzspiegel hinaus, sonst wirkt er
     abgeschnitten. Er MUSS dafuer in .shell stehen: beide Werte rechnen mit
     50% des Satzspiegels, und ausserhalb davon ist das die Fensterbreite,
     der Ausbruch wird null und das erste Bild klebt am Fensterrand. */
  margin-inline: calc(50% - 50vw);
  padding-inline: var(--gutter);
  /* Ohne diese Zeile schnappt das erste Bild an die Aussenkante des
     Streifens statt an die Satzkante, und der Streifen steht beim Laden um
     den Betrag des padding verschoben da. scroll-padding rueckt den
     Schnapppunkt mit. */
  scroll-padding-inline: var(--gutter);
  /* Der Streifen darf am Ende nicht in die Seite weiterziehen. Ohne diese
     Zeile laeuft das Wischen ueber die letzte Kachel hinaus an das
     Fenster weiter: auf dem Handy und am Trackpad loest das die
     Zurueck-Geste des Browsers aus, man wischt durch die Bilder und
     landet auf der vorherigen Seite. */
  overscroll-behavior-x: contain;
  /* Hier stand kurz touch-action: pan-y. Das war falsch herum gedacht:
     touch-action sagt, welche Gesten der BROWSER auf diesem Element noch
     behandeln darf, und pan-y haette ihm ausgerechnet das waagerechte
     Wischen verboten, also die einzige Bedienung, die der Streifen auf
     dem Handy hat. Die Achsen trennt der Browser von sich aus richtig.
     Der Standardwert auto bleibt. */
  /* Keine sichtbare Leiste. Sie war das, was den Streifen nach Scrollen
     aussehen liess statt nach Bildband. Bedient wird waagerecht: am
     Desktop ueber die beiden Knoepfe, auf dem Handy mit dem Finger. */
  scrollbar-width: none;
}
.rail > * { scroll-snap-align: start; }
.rail::-webkit-scrollbar { display: none; }

/* Und das war die eigentliche Ursache der zweiten Leiste: der Rahmen ist
   hier ein <a> direkt in einer <figure>, also ein Inline-Kasten. Auf einen
   Inline-Kasten wirkt weder aspect-ratio noch overflow: hidden. Das Bild
   wuchs damit ueber seine Spalte hinaus, und die Zeilenhoehe des Streifens
   wurde ohne die Bildunterschrift gerechnet: die letzten 17 Pixel der
   Unterschrift hingen unten heraus, und genau die konnte man senkrecht
   wegscrollen. Als Block stimmt beides wieder, das Seitenverhaeltnis 3:2
   greift und die Zeile ist so hoch wie Bild plus Unterschrift.
   (Dieselbe Konstellation steht auch auf /galerie. Dort gemessen: kein
   Ueberstand, keine Ueberdeckung - nur greift das Seitenverhaeltnis der
   Rahmen auch dort nicht. Nicht angefasst, das ist eine eigene
   Entscheidung.) */
.rail .frame { display: block; }

/* Knoepfe am Streifen. Auf dem Handy gibt es sie nicht: dort ist das
   Wischen die bessere Bedienung, und ein Finger braucht keine Leiste.
   Ab der Schwelle unten uebernehmen sie allein, der Streifen laesst sich
   dort nicht mehr von Hand schieben. So gibt es auf jedem Geraet genau
   eine Bedienung statt zweier nebeneinander.

   Die Schwelle liegt bei 40rem und nicht mehr bei 62rem: seit die
   Bildlaufleiste weg ist, waere ein Mausbenutzer in einem 700 Pixel
   breiten Fenster sonst ohne jede Bedienung dagestanden, weder Leiste
   noch Knopf. 40rem ist die Breite, ab der neben der ersten Kachel
   ueberhaupt Platz fuer einen Knopf ist. */
.railnav { display: none; }

@media (min-width: 40rem) {
  /* Ab hier bewegt nur noch der Knopf. hidden nimmt dem Benutzer das
     Ziehen und das Rollen weg, das Script scrollt weiterhin: ein
     Scroll-Container bleibt das Element, es zeigt bloss keine Leiste
     und reagiert nicht mehr auf Maus und Trackpad. Der Tastatur-Fokus
     holt sich seine Kachel weiterhin selbst ins Bild.

     Nur mit .js am <html>: faellt das Script aus, bleiben auch die
     Knoepfe abgeschaltet und unsichtbar, und dann waere ein Streifen
     ohne jede Bedienung uebrig, von dem man nur die ersten Bilder saehe. */
  .js .rail { overflow-x: hidden; }

  .railnav {
    position: absolute;
    z-index: 2;
    display: grid;
    place-items: center;
    width: 3rem;
    height: 3rem;
    padding: 0;
    /* Die Bilder sind 3:2, darunter steht noch die Bildunterschrift. Die
       Mitte des Bildes liegt deshalb nicht auf der halben Hoehe des
       Streifens, sondern bei einem Drittel der Spaltenbreite
       (Hoehe = Breite / 1.5, davon die Haelfte = Breite / 3). Derselbe
       Ausdruck wie in grid-auto-columns, damit beide zusammen wandern. */
    top: calc(min(78vw, 26rem) / 3);
    transform: translateY(-50%);
    border: 1px solid var(--sand-deep);
    border-radius: var(--r-pill);
    background: var(--paper-lift);
    color: var(--ink);
    box-shadow: var(--shadow-md);
    cursor: pointer;
    transition: opacity .25s var(--ease), background .25s var(--ease),
                border-color .25s var(--ease), visibility .25s;
  }
  .railnav:hover { background: var(--white); border-color: var(--ink); }
  .railnav svg { width: 1.25rem; height: 1.25rem; }
  /* Innerhalb der Satzkante, nicht darueber hinaus: in schmalen Fenstern
     ist der Rand nur 20px breit, ein nach aussen gerueckter Knopf wuerde
     dort am Fensterrand abgeschnitten. */
  .railnav--prev { left: .75rem; }
  .railnav--prev svg { transform: rotate(180deg); }
  .railnav--next { right: .75rem; }
  /* Am Anfang und am Ende verschwindet der Knopf, statt tot dazustehen.
     visibility nimmt ihn zugleich aus der Tabreihenfolge. */
  .railnav[disabled] { opacity: 0; visibility: hidden; }
}

/* --- Zahlentafel. Ein grosser Betrag neben dem Text. Der einzige Ort,
       an dem eine Ziffer gross wird. */
.plate {
  display: grid;
  gap: clamp(1.5rem, 1rem + 2.5vw, 3.5rem);
  align-items: center;
  padding: clamp(2rem, 1.4rem + 3vw, 4rem);
}
@media (min-width: 56rem) { .plate { grid-template-columns: auto 1fr; } }
.plate__num {
  font-family: var(--font-display);
  font-size: clamp(4.5rem, 2.5rem + 9vw, 11rem);
  line-height: .82;
  letter-spacing: -.05em;
  color: var(--brass-lit);
  margin: 0;
}
.plate__num span { font-size: .38em; vertical-align: super; letter-spacing: 0; }

/* --- Oeffnungszeiten als Register. */
.hours { list-style: none; margin: 0; padding: 0; }
.hours li {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1.5rem;
  padding: .7rem 0;
  border-bottom: 1px solid var(--sand);
  font-size: var(--t-sm);
}
.hours li:first-child { border-top: 1px solid var(--sand); }
.section--night .hours li,
.section--night .hours li:first-child { border-color: rgba(246, 241, 232, .16); }
.hours__day { color: var(--ink-soft); }
.section--night .hours__day { color: var(--on-night-soft); }
.hours__time { font-variant-numeric: tabular-nums; }
.hours li.is-today .hours__day,
.hours li.is-today .hours__time { color: var(--brass-ink); font-weight: 600; }
.section--night .hours li.is-today .hours__day,
.section--night .hours li.is-today .hours__time { color: var(--brass-lit); }
.hours__today {
  margin-left: .6rem;
  font-size: var(--t-2xs);
  letter-spacing: .14em;
  text-transform: uppercase;
  font-weight: 600;
}

/* --- Randspalte. Steht auf der Buchungsseite neben dem Formular und
       traegt Zeiten und Telefonnummer. Auf Creme abgesetzt, damit sie als
       Beiwerk lesbar bleibt und nicht mit dem Formular konkurriert. */
.aside {
  background: var(--paper-lift);
  border: 1px solid var(--sand);
  border-radius: var(--r-lg);
  padding: clamp(1.35rem, 1rem + 1.4vw, 2rem);
  align-self: start;
}
@media (min-width: 56rem) {
  .aside { position: sticky; top: calc(var(--header-h) + 1.5rem); }
}

/* --- Kurzuebersicht des gebuchten Termins. */
.summary { display: grid; gap: .1rem; margin: 0; }
.summary > div {
  display: flex;
  flex-wrap: wrap;
  gap: .35rem 1.5rem;
  justify-content: space-between;
  padding: .8rem 0;
  border-bottom: 1px solid var(--sand);
}
.summary dt { color: var(--ink-soft); font-size: var(--t-sm); }
.summary dd { margin: 0; font-weight: 600; }

/* --- Kontaktzeilen mit Icon. */
.contactlist { list-style: none; margin: 0; padding: 0; display: grid; gap: 1.1rem; }
.contactlist li { display: flex; gap: .9rem; align-items: flex-start; }
.contactlist svg { width: 1.15rem; height: 1.15rem; flex: 0 0 auto; margin-top: .2rem; color: var(--brass-ink); }
.section--night .contactlist svg { color: var(--brass-lit); }
.contactlist a:hover { color: var(--brass-ink); }
.section--night .contactlist a:hover { color: var(--brass-lit); }
/* Grosse Fassung auf der Kontaktseite: dort ist die Liste der Inhalt und
   nicht eine Fussnote. */
.contactlist--lg { gap: 1.6rem; font-size: var(--t-lead); }
.contactlist--lg svg { width: 1.4rem; height: 1.4rem; margin-top: .35rem; }
.contactlist--lg .arrowlink { font-size: var(--t-sm); margin-top: .5rem; }

/* --- Bildmauerwerk der Galerie. Zwei bis drei Spalten, die Hoehe wechselt
       mit dem Seitenverhaeltnis des Rahmens. Kein masonry: das ist noch
       nicht ueberall da, und eine Spaltenaufteilung mit gleichen Zeilen
       reicht voellig. */
.mosaic {
  display: grid;
  gap: clamp(1rem, .6rem + 1.6vw, 2rem);
  align-items: start;
}
@media (min-width: 40rem) { .mosaic { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 62rem) { .mosaic { grid-template-columns: repeat(3, 1fr); } }

/* --- Karte (Landkarte) */
.map {
  border: 1px solid var(--sand);
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--linen);
  box-shadow: var(--shadow-sm);
}
.map iframe { display: block; width: 100%; height: clamp(18rem, 40vh, 26rem); border: 0; }

/* --- Meldung nach dem Absenden eines Formulars. */
.notice {
  display: flex;
  gap: .9rem;
  padding: 1.1rem 1.35rem;
  border-radius: var(--r-md);
  border: 1px solid var(--sand-deep);
  background: var(--paper-lift);
  font-size: var(--t-sm);
  margin-bottom: var(--sp-block);
}
.notice svg { width: 1.2rem; height: 1.2rem; flex: 0 0 auto; margin-top: .18rem; }
.notice--ok { border-color: #9aa87d; background: #f2f4e9; color: #38431f; }
.notice--ok svg { color: #55663a; }
.notice--bad { border-color: #cba49a; background: #faeeea; color: #6d2c1c; }
.notice--bad svg { color: #8f3b26; }

/* ============================================================ 09 Preise == */

.pricegroup + .pricegroup { margin-top: var(--sp-block); }

.pricegroup__head {
  display: flex;
  align-items: baseline;
  gap: 1rem;
  margin-bottom: 1rem;
}
.pricegroup__head h3 { font-size: var(--t-h3); }
.pricegroup__head::after {
  content: '';
  flex: 1 1 auto;
  height: 1px;
  background: var(--sand);
}

.pricetable { width: 100%; border-collapse: collapse; font-size: var(--t-sm); }
.pricetable caption { text-align: left; }
.pricetable th {
  text-align: left;
  font-weight: 600;
  font-size: var(--t-2xs);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--ink-faint);
  padding: 0 0 .6rem;
  border-bottom: 1px solid var(--sand);
}
.pricetable td { padding: .8rem 0; border-bottom: 1px solid var(--sand); vertical-align: baseline; }
.pricetable tr:last-child td { border-bottom: 0; }
.pricetable .col-dur,
.pricetable .col-price { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
.pricetable .col-dur { color: var(--ink-faint); width: 6.5rem; }
.pricetable .col-price { width: 7.5rem; }
.pricetable .col-price strong { font-weight: 600; }
.pricetable .is-request { color: var(--ink-faint); font-style: italic; }
@media (max-width: 34rem) {
  .pricetable .col-dur, .pricetable th.col-dur { display: none; }
}

/* ========================================================= 10 Formulare == */

.form { display: grid; gap: 1.25rem; }
@media (min-width: 44rem) {
  .form--2 { grid-template-columns: 1fr 1fr; }
  .form .full { grid-column: 1 / -1; }
}

.field { display: grid; gap: .45rem; }
.field label {
  font-size: var(--t-sm);
  font-weight: 600;
  color: var(--ink);
}
.field label .opt { font-weight: 400; color: var(--ink-faint); }
/* Pflichtfeld-Stern und die Legende darueber (Chef-Vorgabe 2026-10-03). */
.req { color: var(--gold, var(--ink)); font-weight: 600; }
.form__required-note {
  margin: 0 0 .25rem;
  font-size: var(--t-sm);
  color: var(--ink-faint);
}

.field input,
.field select,
.field textarea {
  width: 100%;
  padding: .8rem 1rem;
  background: var(--paper-lift);
  border: 1px solid var(--sand-deep);
  border-radius: var(--r-md);
  font-size: var(--t-base);
  transition: border-color .2s var(--ease), box-shadow .2s var(--ease), background .2s var(--ease);
}
.field textarea { min-height: 9rem; resize: vertical; }
.field input:focus,
.field select:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--brass-ink);
  background: var(--white);
  box-shadow: 0 0 0 3px rgba(124, 97, 34, .14);
}
.field select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%237c6122' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 1rem center;
  background-size: 1.1rem;
  padding-right: 2.75rem;
}
.field__hint { font-size: var(--t-xs); color: var(--ink-faint); }

/* Honigtopf: fuer Menschen unsichtbar, Bots fuellen ihn aus. */
.honey { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* Cloudflares Turnstile-Widget ist fest 300px breit. Auf einem 320px-Schirm
   ist der Satzspiegel aber nur 280px, und weil das Widget in einem Raster
   steht, zieht es die ganze Spalte auf 300px: die Seite ragt 20px hinaus und
   laesst sich seitlich schieben. Aufgefallen ist das erst am 2026-08-10, weil
   das Widget bis dahin ohne Keys gar nicht gerendert wurde. Auf der echten
   Domain mit echten Keys traefe es genauso zu.

   Zwei Zeilen: die Rasterzelle darf schmaler werden als ihr Inhalt (ein
   Rasterelement kann das sonst nicht), und das Widget bekommt seinen eigenen
   Scrollbereich, statt die Seite zu sprengen. Auf allen Breiten ab 360px
   aendert sich nichts, dort passen die 300px ohnehin. */
.form .full,
.field { min-width: 0; }
.cf-turnstile { max-width: 100%; overflow-x: auto; }

/* Zeitfenster der Buchung als Knopfraster. */
.slots { display: flex; flex-wrap: wrap; gap: .5rem; }
.slot {
  padding: .55rem 1rem;
  border: 1px solid var(--sand-deep);
  border-radius: var(--r-pill);
  background: var(--paper-lift);
  font-size: var(--t-sm);
  font-variant-numeric: tabular-nums;
  cursor: pointer;
  transition: background .2s var(--ease), color .2s var(--ease), border-color .2s var(--ease);
}
.slot:hover { border-color: var(--ink); }
/* Die gewaehlte Zeit erkennt man an aria-pressed, nicht an einer eigenen
   Klasse: public/js/booking.js setzt genau dieses Attribut, und damit
   stimmen Aussehen und Barrierefreiheit zwingend ueberein. */
.slot[aria-pressed='true'] { background: var(--ink); border-color: var(--ink); color: var(--paper); }
.slot-status { font-size: var(--t-sm); color: var(--ink-soft); margin: 0 0 .75rem; }
/* Die Statuszeile ist eine Live-Region und wird nicht mehr versteckt, sondern
   geleert (public/js/booking.js). Ohne diese Regel bliebe der Abstand stehen. */
.slot-status:empty { margin: 0; }

/* ---------------------------------------------------------------------------
   Leistungen als Kaestchen (seit 2026-08-10, ein Termin traegt bis zu vier).

   42 Positionen in neun Preisgruppen sind als flache Liste unbrauchbar,
   deshalb zwei Ebenen: je Angebotswelt ein aufklappbarer Block (details),
   darin die Preisgruppen wie auf der Preisseite. Der Zaehler rechts im
   Kopf zeigt an, was in einem zugeklappten Block angehakt ist.
   --------------------------------------------------------------------------- */
.service-picker { border: 0; margin: 0; padding: 0; min-width: 0; }
.service-picker > legend {
  padding: 0;
  margin-bottom: .35rem;
  font-size: var(--t-sm);
  font-weight: 600;
  color: var(--ink);
}
.service-picker > .field__hint { display: block; margin-bottom: .75rem; }

.service-world {
  border: 1px solid var(--sand-deep);
  border-radius: var(--r-md);
  background: var(--paper-lift);
}
.service-world + .service-world { margin-top: .6rem; }

.service-world__head {
  display: flex;
  align-items: center;
  gap: .6rem;
  padding: .9rem 1rem;
  font-weight: 600;
  color: var(--ink);
  cursor: pointer;
  /* Beide Zeilen zusammen entfernen das Standarddreieck: die erste in
     Firefox und Chrome, die zweite in Safari. */
  list-style: none;
}
.service-world__head::-webkit-details-marker { display: none; }
/* Eigenes Dreieck. Mit dem Standardmarker faellt sonst auch der einzige
   Hinweis weg, dass sich hier etwas auf- und zuklappen laesst. */
.service-world__head::before {
  content: '';
  flex: none;
  width: .48rem;
  height: .48rem;
  border-right: 2px solid var(--brass-ink);
  border-bottom: 2px solid var(--brass-ink);
  transform: rotate(-45deg);
  transition: transform .2s var(--ease);
}
.service-world[open] > .service-world__head::before { transform: rotate(45deg); }

.service-world__count {
  margin-left: auto;
  font-size: var(--t-xs);
  font-weight: 700;
  color: var(--brass-ink);
  white-space: nowrap;
}
.service-world__count:empty { display: none; }

.service-group { padding: 0 .6rem .5rem; }
.service-group + .service-group { border-top: 1px solid var(--sand); padding-top: .4rem; }
.service-group__title {
  margin: .55rem 0 .2rem;
  padding: 0 .4rem;
  font-family: var(--font-text);
  font-size: var(--t-xs);
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

/* min-height 48px: die Zeile muss auf dem Handy sicher zu treffen sein,
   auch bei einer kurzen Bezeichnung ohne Umbruch. */
.service-option {
  display: flex;
  align-items: center;
  gap: .7rem;
  min-height: 48px;
  padding: .45rem .55rem;
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  cursor: pointer;
  transition: background .2s var(--ease), border-color .2s var(--ease);
}
.service-option:hover { border-color: var(--sand-deep); }
.service-option input {
  flex: none;
  width: 1.15rem;
  height: 1.15rem;
  accent-color: var(--brass-ink);
  cursor: inherit;
}
/* Der angehakte Zustand haengt NICHT allein an der Farbe (WCAG 1.4.1):
   der Haken im Kaestchen und der kraeftigere Rahmen sind die zwei weiteren
   Kanaele, die auch ohne Farbwahrnehmung tragen. */
.service-option:has(input:checked) {
  border-color: var(--brass-ink);
  background: var(--linen);
}
.service-option:has(input:disabled) { opacity: .45; cursor: default; }
/* Der Ring gehoert um die ganze Zeile, nicht nur um das kleine Kaestchen:
   sonst ist bei Tastaturbedienung kaum zu sehen, wo man steht. */
.service-option:has(input:focus-visible) {
  outline: 2px solid var(--brass-ink);
  outline-offset: 2px;
}

/* Drei feste Spalten: Bezeichnung, Dauer, Preis. Dauer und Preis fix breit,
   damit die Betraege ueber alle Zeilen buendig untereinander stehen, der
   Preis rechtsbuendig wie in der Preisliste. Vorher flossen beide hinter der
   Bezeichnung her und standen in jeder Zeile woanders. */
.service-option__text {
  display: grid;
  grid-template-columns: 1fr 5.5rem 7.5rem;
  column-gap: .6rem;
  align-items: baseline;
  flex: 1;
  font-size: var(--t-sm);
  line-height: 1.35;
}
.service-option__name { color: var(--ink); }
.service-option__meta { color: var(--ink-faint); white-space: nowrap; }
.service-option__price { color: var(--ink-soft); white-space: nowrap; text-align: right; }
.service-option__price .is-request { color: var(--ink-faint); font-style: italic; }

/* Aktionspreis in der Zeile: regulaerer Betrag durchgestrichen, davor der
   Aktionsbetrag in Messing. Der Tag steht klein daneben, sonst behauptete
   die Zeile einen Preis, der nur einmal in der Woche gilt. */
.service-option__price s { color: var(--ink-faint); margin-right: .35rem; }
.service-option__price .is-promo { color: var(--brass-ink); }
.service-option__when {
  margin-left: .35rem;
  font-size: var(--t-2xs);
  color: var(--brass-ink);
  white-space: nowrap;
}
/* Schmale Screens: die zwei festen Spalten verschlanken, sonst bleibt der
   Bezeichnung kaum Platz. Buendig bleiben sie trotzdem. */
@media (max-width: 34rem) {
  .service-option__text { grid-template-columns: 1fr 4.6rem 6.6rem; }
}

/* Summe und Grenze. Beide sind Live-Regionen und werden geleert, nie
   versteckt (public/js/booking.js), deshalb hier dasselbe :empty wie bei
   .slot-status: sonst bliebe im Leerzustand ein Abstand stehen. */
.service-total {
  margin: .9rem 0 0;
  font-size: var(--t-sm);
  font-weight: 600;
  color: var(--ink);
}
.service-total:empty { margin: 0; }
.service-limit {
  margin: .4rem 0 0;
  font-size: var(--t-sm);
  color: var(--brass-ink);
}
.service-limit:empty { margin: 0; }

/* Ein Schritt im Buchungsformular. fieldset und legend, damit die drei
   Bloecke auch fuer einen Screenreader Bloecke sind und nicht eine lange
   Kette von Feldern. Der Browser-Standardrahmen muss dafuer weg. */
.fieldset { border: 0; margin: 0; padding: 0; }
.fieldset + .fieldset { margin-top: var(--sp-block); }
/* Nur DIREKTE Kinder. Ohne das ">" greift die Regel auch auf das zweite
   Feld innerhalb von .grid-2, und dann steht dort «Telefon» eine Zeile
   tiefer als «E-Mail», obwohl beide nebeneinander stehen sollen. */
.fieldset > .field + .field,
.fieldset > .field + .grid-2,
.fieldset > .grid-2 + .field { margin-top: 1.25rem; }

.grid-2 { display: grid; gap: 1.25rem; }
@media (min-width: 44rem) { .grid-2 { grid-template-columns: 1fr 1fr; } }

/* Schrittzaehler im Buchungsformular. */
.step { display: flex; align-items: center; gap: .8rem; margin-bottom: 1.25rem; padding: 0; }
.step__num {
  width: 1.9rem; height: 1.9rem;
  display: grid; place-items: center;
  border-radius: var(--r-pill);
  background: var(--linen);
  color: var(--brass-ink);
  font-size: var(--t-xs);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.step__title { font-family: var(--font-display); font-size: var(--t-h3); letter-spacing: -.015em; }

/* ========================================================= 11 Fusszeile == */

.footer {
  margin-top: var(--sp-section);
  background: var(--night);
  color: var(--on-night);
  border-radius: var(--r-xl) var(--r-xl) 0 0;
  padding-top: clamp(3rem, 2rem + 4vw, 5.5rem);
  position: relative;
  z-index: 2;
}
.footer a { color: inherit; }
.footer__grid {
  display: grid;
  gap: clamp(2rem, 1.4rem + 2.5vw, 3.5rem);
  padding-bottom: clamp(2.5rem, 2rem + 2vw, 3.5rem);
}
@media (min-width: 48rem) { .footer__grid { grid-template-columns: 1.4fr 1fr 1fr; } }
@media (min-width: 68rem) { .footer__grid { grid-template-columns: 1.6fr 1fr 1fr 1.1fr; } }

/* Freigestelltes Gold-Monogramm ueber der Wortmarke. Der leichte
   Negativ-Einzug gleicht den Stern-Glanz aus, der links aus dem B
   herausragt, damit das B optisch mit dem Text fluchtet. */
.footer__logo { display: block; margin: 0 0 1.2rem -.5rem; }
.footer__logo img { display: block; width: clamp(5.5rem, 5rem + 2vw, 7rem); height: auto; }

.footer__brand { font-family: var(--font-display); font-size: 1.75rem; letter-spacing: -.02em; line-height: 1; }
.footer__sub {
  display: block;
  margin-top: .6rem;
  font-family: var(--font-text);
  font-size: var(--t-xs);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--brass-lit);
}
.footer__text { margin-top: 1.25rem; color: var(--on-night-soft); font-size: var(--t-sm); max-width: 34ch; }

.footer__title {
  font-family: var(--font-text);
  font-size: var(--t-xs);
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--brass-lit);
  margin-bottom: 1.1rem;
}
.footer__list { list-style: none; margin: 0; padding: 0; display: grid; gap: .6rem; font-size: var(--t-sm); }
.footer__list a { color: var(--on-night-soft); transition: color .2s var(--ease); }
.footer__list a:hover { color: var(--on-night); }

.footer__bar {
  border-top: 1px solid rgba(246, 241, 232, .14);
  padding: 1.5rem 0 2rem;
  display: flex;
  flex-wrap: wrap;
  gap: .75rem 1.75rem;
  align-items: center;
  justify-content: space-between;
  font-size: var(--t-xs);
  color: var(--on-night-soft);
}
.footer__bar nav { display: flex; flex-wrap: wrap; gap: 1.25rem; }
.footer__bar a:hover { color: var(--on-night); }

/* Signatur der Agentur, ganz unten und bewusst leise. */
.credits {
  margin: 0;
  padding-bottom: 2rem;
  text-align: center;
  font-size: var(--t-xs);
  line-height: 1.7;
  color: var(--on-night-soft);
}
/* Eine Zeile, zentriert. Bricht auf schmalen Displays am Trennpunkt um,
   nicht mitten im Satz. */
.credits a {
  display: inline-flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: baseline;
  gap: .15rem .55rem;
  color: var(--on-night-soft);
  text-decoration: none;
  transition: color .2s var(--ease);
}
.credits__sep { color: var(--brass-lit); opacity: .7; }
.credits a:hover { color: var(--brass-lit); }
.credits svg {
  width: 1em; height: 1em;
  display: inline-block;
  vertical-align: -.14em;
  color: var(--brass-lit);
}

/* Signatur der Agentur, ganz unten und bewusst leise. */
.credits {
  margin: 0;
  padding-bottom: 2rem;
  text-align: center;
  font-size: var(--t-xs);
  line-height: 1.7;
  color: var(--on-night-soft);
}
/* Eine Zeile, zentriert. Bricht auf schmalen Displays am Trennpunkt um,
   nicht mitten im Satz. */
.credits a {
  display: inline-flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: baseline;
  gap: .15rem .55rem;
  color: var(--on-night-soft);
  text-decoration: none;
  transition: color .2s var(--ease);
}
.credits__sep { color: var(--brass-lit); opacity: .7; }
.credits a:hover { color: var(--brass-lit); }
.credits svg {
  width: 1em; height: 1em;
  display: inline-block;
  vertical-align: -.14em;
  color: var(--brass-lit);
}

.social { display: flex; gap: .6rem; margin-top: 1.25rem; }
.social a {
  width: 2.5rem; height: 2.5rem;
  display: grid; place-items: center;
  border: 1px solid rgba(246, 241, 232, .22);
  border-radius: var(--r-pill);
  color: var(--on-night-soft);
  transition: background .25s var(--ease), color .25s var(--ease), border-color .25s var(--ease);
}
.social a:hover { background: var(--brass-lit); border-color: var(--brass-lit); color: var(--night); }
.social svg { width: 1.15rem; height: 1.15rem; }

/* ============================================ 12 Bewegung und Hilfen == */

/* Einblenden beim Scrollen. Der Startzustand wird erst gesetzt, wenn
   js/site.js den Beobachter wirklich aufgebaut hat (Klasse reveal-ready
   am <html>). Faellt das Script aus, bleibt alles sichtbar. */
.reveal-ready .reveal {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity .8s var(--ease-out), transform .8s var(--ease-out);
}
.reveal-ready .reveal.is-in { opacity: 1; transform: none; }

/* Gestaffelter Auftritt der Buehne, einmalig beim Laden. */
@keyframes rise {
  from { opacity: 0; transform: translateY(20px); }
  to   { opacity: 1; transform: none; }
}
.js .hero__content > * { animation: rise .9s var(--ease-out) both; }
.js .hero__content > :nth-child(1) { animation-delay: .10s; }
.js .hero__content > :nth-child(2) { animation-delay: .20s; }
.js .hero__content > :nth-child(3) { animation-delay: .30s; }
.js .hero__content > :nth-child(4) { animation-delay: .42s; }
.js .hero__content > :nth-child(5) { animation-delay: .54s; }

.u-center { text-align: center; }
.u-mt { margin-top: var(--sp-block); }
.u-mt-sm { margin-top: 1.25rem; }
.u-nowrap { white-space: nowrap; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
  .reveal-ready .reveal { opacity: 1; transform: none; }
}

/* ======================================== 13 Aktionsfenster == */

/* Der Hinweis auf die laufende Aktion. Markup: views/partials/promo.ejs,
   Inhalt und Schalter: data/site.js, geoeffnet wird er allein von
   js/site.js.

   Gestaltet wie eine Karte dieser Website und nicht wie ein fremdes
   Werbebanner: Cremepapier, grosse Radien, warmer Schatten. Laut ist
   daran genau eine Sache, der Betrag in Messing.

   Nicht gesetzt wird eine Scrollsperre auf dem body. Sie waere hier
   teurer als ihr Nutzen: sobald die Scrollleiste verschwindet, rutscht
   die ganze Seite um deren Breite zur Seite, und dieser Ruck ist beim
   Oeffnen UND beim Schliessen zu sehen. Der Hintergrund darf also
   mitscrollen. Bedienbar bleibt er ohnehin nicht, das verhindert
   showModal(). */

.promo {
  width: min(26rem, 92vw);
  max-height: 88vh;
  max-height: 88svh;
  padding: 0;
  border: 0;
  border-radius: var(--r-lg);
  background: var(--paper-lift);
  color: var(--ink);
  box-shadow: var(--shadow-lg);
  /* Damit das Bild oben die Rundung des Fensters mitnimmt. */
  overflow: hidden;
}

/* Nur im offenen Zustand. Stuende display hier ohne die Bedingung, waere
   das Fenster dauernd sichtbar: dass ein geschlossenes <dialog> nicht
   erscheint, ist selbst eine display-Regel des Browsers. */
.promo[open] { display: flex; flex-direction: column; }

.promo::backdrop { background: rgba(25, 26, 32, .58); }

/* --- Bild. Aus dem 3:2 des Originals wird ein flacherer Ausschnitt: auf
       einem Handy soll das Fenster nicht die halbe Bildschirmhoehe fuer
       ein Foto ausgeben. Der Ausschnitt sitzt weit oben, weil unten nur
       die Lehne des Barbierstuhls steht und oben der Kopf des Coiffeurs
       sonst angeschnitten wird. */
.promo__media { margin: 0; flex: none; }
.promo__media img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  object-position: 50% 12%;
}

/* Bei flachen Fenstern faellt das Bild ganz weg. Auf einem quer
   gehaltenen Handy waere das Fenster sonst fast nur Foto, und die
   Knoepfe stuenden unterhalb des Bildschirms. Der Rumpf bekommt dann
   oben Luft, sonst laege das Kreuz auf der ersten Zeile. */
@media (max-height: 40rem) {
  .promo__media { display: none; }
  .promo__body { padding-top: 3.4rem; }
}

/* --- Schliessen. Der Knopf liegt auf dem Bild und braucht deshalb eine
       eigene Flaeche, sonst waere das Kreuz je nach Motiv nicht zu
       sehen. Das <dialog> ist beim Browser fixed positioniert und damit
       schon der Bezugsrahmen. */
.promo__x {
  position: absolute;
  top: .75rem;
  right: .75rem;
  width: 2.5rem;
  height: 2.5rem;
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  border-radius: var(--r-pill);
  background: var(--paper);
  color: var(--ink);
  box-shadow: var(--shadow-sm);
  cursor: pointer;
  transition: background .25s var(--ease), color .25s var(--ease);
}
.promo__x:hover { background: var(--ink); color: var(--paper); }
.promo__x svg { width: 1.1rem; height: 1.1rem; }

/* --- Text. Der Rumpf scrollt, nicht das Fenster: so bleibt das Bild
       oben stehen, wenn der Platz einmal nicht reicht. */
.promo__body {
  padding: clamp(1.25rem, 1rem + 1.4vw, 1.85rem);
  overflow-y: auto;
}
.promo .eyebrow { margin-bottom: .3rem; }
.promo__title {
  margin: 0;
  font-size: var(--t-h3);
  line-height: 1.18;
}

/* --- Der Betrag. Die neue Zahl gross in Messing, die alte klein und
       durchgestrichen daneben. Der ganze Absatz ist fuer Screenreader
       ausgeblendet: vorgelesen ergaebe er «20 CHF 25». Der Satz darunter
       sagt dasselbe in ganzen Worten. */
.promo__price {
  display: flex;
  align-items: baseline;
  gap: .55rem;
  margin: .85rem 0 0;
  font-family: var(--font-display);
  line-height: 1;
}
.promo__now {
  font-size: clamp(2.9rem, 2.2rem + 2.6vw, 3.6rem);
  letter-spacing: -.04em;
  color: var(--brass-ink);
}
.promo__unit {
  font-family: var(--font-text);
  font-size: var(--t-xs);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--brass-ink);
}
.promo__was {
  font-size: var(--t-h3);
  color: var(--ink-faint);
  text-decoration-thickness: 1px;
}

.promo__text { margin: .9rem 0 0; }
.promo__note {
  margin: .45rem 0 0;
  font-size: var(--t-sm);
  color: var(--ink-soft);
}

.promo__actions {
  display: flex;
  flex-wrap: wrap;
  gap: .6rem;
  margin-top: 1.35rem;
}
/* Beide Knoepfe teilen sich die Zeile und rutschen erst untereinander,
   wenn sie nebeneinander schmaler als 9rem wuerden. */
.promo__actions .btn { flex: 1 1 9rem; }

/* --- Derselbe Hinweis auf der Buchungsseite, sobald die beworbene
       Leistung angehakt ist. Keine zweite Gestaltung, nur eine Notiz mit
       Messinglinie: sie soll den Blick nicht vom Formular wegziehen,
       sondern die Zahl darunter erklaeren. */
.promo-hint {
  margin: 1rem 0 0;
  padding: .85rem 1rem;
  border-left: 3px solid var(--brass);
  border-radius: 0 var(--r-md) var(--r-md) 0;
  background: var(--linen);
  font-size: var(--t-sm);
  line-height: 1.5;
}
.promo-hint strong { display: block; color: var(--brass-ink); }

/* --- Auftritt. Kurz und ruhig, das Fenster steigt eine Handbreit auf. */
@keyframes promo-rise {
  from { opacity: 0; transform: translateY(14px) scale(.985); }
  to   { opacity: 1; transform: none; }
}
@keyframes promo-veil {
  from { opacity: 0; }
  to   { opacity: 1; }
}
.promo[open] { animation: promo-rise .42s var(--ease-out) both; }
.promo[open]::backdrop { animation: promo-veil .42s var(--ease-out) both; }

/* Die Sammelregel in Abschnitt 12 erreicht ::backdrop nicht, der
   Universalselektor deckt nur ::before und ::after ab. Deshalb hier
   noch einmal eigens. */
@media (prefers-reduced-motion: reduce) {
  .promo[open],
  .promo[open]::backdrop { animation: none; }
}

/* ======================================== 14 Hinweis zu Cookies == */
/* Ticket 4 (2026-10-10). Nur ein Hinweis, keine Wahl: die Seiten laden
   nichts, wofuer es eine Einwilligung braucht. Ein schmaler Streifen im
   Nachtblau des Ladenschilds, mittig ueber dem Seitenrand, Messing nur im
   Link. Erscheint erst nach 5,5 s und einer halben Bildschirmhoehe Scroll
   (js/cookie-hinweis.js), also nie ueber den beiden Knoepfen der Buehne.
   Solange er steht, rueckt «nach oben» darueber und die Fusszeile endet
   ueber ihm, die Signatur bleibt frei.
   Kontraste: on-night/night 15.4, brass-lit/night 7.8, ink/paper 15.4. */
.cookie {
  position: fixed;
  z-index: 95;
  left: 0;
  right: 0;
  bottom: max(1rem, env(safe-area-inset-bottom));
  width: min(46rem, 100% - 1.5rem);
  margin-inline: auto;
  display: grid;
  gap: .75rem 1.75rem;
  padding: 1rem 1rem 1rem 1.5rem;
  border: 1px solid rgba(246, 241, 232, .14);
  border-radius: var(--r-lg);
  background: var(--night);
  color: var(--on-night);
  box-shadow: var(--shadow-lg);
  font-family: var(--font-text);
  font-size: var(--t-sm);
  line-height: 1.5;
  animation: cookie-rise .45s var(--ease-out) both;
}
.cookie[hidden] { display: none; }
.cookie__text { margin: 0; }
.cookie__row { display: flex; align-items: center; justify-content: space-between; gap: 1.25rem; }
.cookie__row a {
  color: var(--brass-lit);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: .2em;
}
.cookie__row a:hover { color: var(--on-night); }
.cookie__ok { background: var(--paper); color: var(--ink); padding: .7rem 1.4rem; }
.cookie__ok:hover { background: var(--brass-lit); }
.cookie :focus-visible { outline-color: var(--brass-lit); }
@keyframes cookie-rise {
  from { opacity: 0; translate: 0 .75rem; }
}
@media (min-width: 48rem) {
  .cookie { grid-template-columns: 1fr auto; align-items: center; }
}
.hat-cookie { scroll-padding-bottom: calc(var(--cookie-h, 0px) + 2rem); }
.hat-cookie .totop { bottom: calc(max(1rem, env(safe-area-inset-bottom)) + var(--cookie-h, 0px) + .75rem); }
.hat-cookie .credits { padding-bottom: calc(5rem + var(--cookie-h, 0px)); }
/* Schmal liegt «nach oben» am Seitenende auf der Signatur, auch ohne Hinweis
   (gesehen 2026-10-10 bei 390). 5rem halten den Knopf darunter frei. */
@media (max-width: 61.99rem) {
  .credits { padding-bottom: 5rem; }
}
@media print { .cookie { display: none; } }
