/* lina4.ai design system, Atelier (dark, minimal premium), approved direction 2.
   Built zoom-/reflow-resilient from the start (D-058): fluid type via clamp(), rem/ch/%
   sizing, navigation collapses to a menu button, no nowrap on long text. Derived from
   design-mockups/r2-atelier-dark-final.html. */

/* Design tokens (:root) moved to the single canonical source static/tokens.css (D13), inherited by
   both the website and the Lina app. base.html links tokens.css BEFORE this file, so every var()
   below resolves against it. Do not re-declare tokens here; change a token once in tokens.css. */

* { box-sizing: border-box; }
/* scrollbar-gutter:stable always reserves the scrollbar's space, so navigating from a short page
   (no scrollbar) to a tall one (scrollbar appears) no longer shifts centred content sideways
   - the "jump" after login on classic-scrollbar desktops. */
/* scroll-padding-top keeps in-page anchor targets (#handle, #reassure) clear of the sticky header
   instead of landing ~header-height too high (Audit C9 / design-ui anchor-offset rule). */
html { scroll-behavior: smooth; font-size: 100%; scrollbar-gutter: stable; scroll-padding-top: 5rem; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }
body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  font-size: var(--step-0);
  line-height: 1.62;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  /* never fake a missing weight/slant: synthetic bold/italic is an Anti-KI tell (§4.5). Real
     italic/weight files are loaded where emphasis is actually used (the Caveat signature). */
  font-synthesis: none;
}

/* subtle warm grain, the one real "workshop material" detail, kept faint/premium */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 9999;
  pointer-events: none;
  opacity: 0.045;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  mix-blend-mode: overlay;
}

.wrap { max-width: 67.5rem; margin: 0 auto; padding: 0 var(--gutter); }
h1, h2, h3 {
  margin: 0;
  font-weight: 800;
  letter-spacing: -0.03em;
  line-height: 1.04;
  text-wrap: balance;
}
p { text-wrap: pretty; }
a { color: inherit; text-decoration: none; }

/* One visible, on-brand focus ring everywhere a keyboard can land (replaces the browser default and
   the scattered per-component focus rules). Only shows for keyboard/AT users via :focus-visible. */
a:focus-visible,
.btn:focus-visible,
button:focus-visible,
label.menu-toggle:focus-visible,
summary:focus-visible,
.help-card:focus-visible {
  outline: 2px solid var(--ember);
  outline-offset: 2px;
  border-radius: 0.3rem;
}

/* nav */
/* Smart-sticky header: reachable on long pages without taking permanent space. It sticks to the
   top, and a tiny scroll script (base.html) hides it on scroll-down and brings it back on the
   first scroll-up, so the menu is always one swipe away yet never sits on the content. The frosted
   backdrop keeps it legible while gliding over hero photos and bands. */
.site-head {
  position: sticky; top: 0; z-index: 80;
  background: var(--bg);
  border-bottom: 1px solid var(--border);
  transition: transform 0.32s var(--ease);
}
.site-head.is-hidden { transform: translateY(-100%); }
/* reduced motion: keep the header permanently visible rather than sliding it away. */
@media (prefers-reduced-motion: reduce) {
  .site-head { transition: none; }
  .site-head.is-hidden { transform: none; }
}
.nav {
  min-height: 4.6rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.9rem 0;
  /* Never wrap: the logo stays alone on the first row and the links collapse to the menu button
     instead of tearing off into a second row (the signed-in nav used to break here on desktop). */
  flex-wrap: nowrap;
}
.logo {
  font-weight: 800;
  font-size: 1.2rem;
  letter-spacing: -0.02em;
  display: inline-flex;
  gap: 0.6rem;
  align-items: center;
}
/* Werkstatt-Lampe (SVG, partials/_lamp.html): a lit little pendant lamp, cord + warm shade +
   emitted ember light, not a status dot (design-guardian C). Ties to brand "das Licht ist an". */
.logo .lamp {
  position: relative;
  display: inline-flex;
  align-self: center;
  width: 0.92rem;
  height: 1.17rem;   /* keeps the 22:28 viewBox aspect so the lamp is not letterboxed */
  flex: none;
}
.logo .lamp .lampsvg { width: 100%; height: 100%; overflow: visible; }
/* colours mixed from tokens (--text / --ember), no raw hex past the token system */
.logo .lamp .lamp-cord { stroke: var(--faint); stroke-width: 1.1; stroke-linecap: round; }
.logo .lamp .lamp-shade { fill: color-mix(in srgb, var(--ember) 58%, var(--text)); }
.logo .lamp .lamp-rim { stroke: color-mix(in srgb, var(--text) 72%, var(--ember)); stroke-width: 0.9; stroke-linecap: round; }
.logo .lamp .lamp-beam { fill: var(--ember); opacity: 0.14; }
.logo .lamp .lamp-bulb { fill: color-mix(in srgb, var(--text) 68%, var(--ember)); }
.logo .lamp .lamp-glow { fill: var(--ember); opacity: 0.3; filter: blur(1.4px); }
/* Wordmark: "lina" leads; "4.ai" steps back to a quiet domain suffix (marketing D). The 4 keeps
   its ember accent (brand/README wordmark spec) but at a subordinate size, so it no longer reads
   as a version number. Lowercase stays (brand/README: bewusst Kleinschreibung). */
.logo b { font-weight: 800; }
.logo .mark { display: inline-flex; align-items: baseline; letter-spacing: -0.005em; }
.logo .four { color: var(--ember); font-weight: 600; font-size: 0.72em; margin-left: 0.03em; }
.logo .tld {
  color: var(--muted);
  font-weight: 500;
  font-size: 0.72em;
  margin-left: 0.02em;
  opacity: 0.9;
}
.navlinks {
  display: flex;
  /* 1.25rem, not 1.9: keeps the fuller signed-in row (four landing anchors + area/help/account +
     language) on one line inside the 1080px bar; still an airy nav gap. */
  gap: 1.25rem;
  align-items: center;
  font-size: var(--step--1);
  color: var(--muted);
}
.navlinks a:not(.btn):hover { color: var(--text); }

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  border-radius: 0.6rem;
  padding: 0.7rem 1.25rem;
  font-weight: 700;
  font-size: var(--step--1);
  cursor: pointer;
  font-family: inherit;
  border: 1px solid transparent;
  line-height: 1.2;
  min-height: 2.75rem;  /* comfortable >=44px touch target (WCAG 2.5.8) without changing the look */
  white-space: nowrap;
  transition: transform var(--t-slow) var(--ease), box-shadow var(--t-slow) var(--ease),
              filter var(--t-slow) var(--ease), border-color var(--t-slow) var(--ease),
              background-color var(--t-slow) var(--ease), color var(--t-slow) var(--ease);
}
/* Punkt 0 / marketing: the primary action carries a flat warm ember, not the SaaS gradient
   (the same tell struck on the headline). Keeps the warm-classic register on the most-clicked element. */
.btn.primary { background: var(--ember); color: var(--on-accent); box-shadow: 0 0.4rem 1.1rem -0.5rem color-mix(in srgb, var(--ember-deep) 50%, transparent); }
.btn.ghost { border-color: var(--border); color: var(--text); background: rgba(255, 244, 230, 0.02); }
/* Branded-secondary nav CTA: one filled ember primary per viewport (hero/form), nav stays outline. */
.btn.nav-cta { background: transparent; border-color: var(--ember-deep); color: var(--ember); box-shadow: none; }
.btn.nav-cta:hover { background: color-mix(in srgb, var(--ember-deep) 10%, transparent); border-color: var(--ember); color: var(--ember); }
.btn.sm { padding: 0.5rem 0.95rem; }
.btn.lg { padding: 0.85rem 1.5rem; font-size: var(--step-0); }
.btn:hover { transform: translateY(-2px); transition-duration: var(--t-fast); }
.btn:active { transform: translateY(0); transition-duration: 0.05s; }
.btn.primary:hover { filter: brightness(1.05); box-shadow: 0 0.7rem 1.5rem -0.5rem color-mix(in srgb, var(--ember-deep) 60%, transparent); }
.btn.ghost:hover { border-color: var(--ember-deep); background: color-mix(in srgb, var(--ember-deep) 8%, transparent); }
@media (prefers-reduced-motion: reduce) {
  .btn { transition: filter var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease), background-color var(--t-fast) var(--ease); }
  .btn:hover, .btn:active { transform: none; }
}

/* mobile menu toggle (controlled collapse, D-058): comfortable 44px touch target, visible box */
.menu-toggle {
  display: none;
  align-items: center;
  gap: 0.35rem;
  height: 2.3rem;  /* compact, balanced against the delicate wordmark; ~37px, larger under page zoom */
  padding: 0 0.6rem;
  /* icon + the word "Menü": a warm, labelled control instead of a bare icon (the template tell),
     but restrained so it does not overpower the small wordmark next to it. */
  background: color-mix(in srgb, var(--ember-deep) 5%, transparent);
  border: 1px solid var(--ember-deep);
  border-radius: var(--r-sm);
  color: var(--ember);
  cursor: pointer;
  font-family: inherit;
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0.01em;
  z-index: 71;  /* stays above the open overlay so it can morph to the close (X) control */
  transition: border-color var(--t-fast) var(--ease), background-color var(--t-fast) var(--ease);
}
.menu-toggle .mt-label { line-height: 1; }
.menu-toggle svg { width: 1rem; height: auto; }
/* once open, the icon is the X; drop the word so the top-right control reads purely as "close" */
#nav-toggle:checked ~ .menu-toggle .mt-label { display: none; }
#nav-toggle:checked ~ .menu-toggle { padding: 0; width: 2.3rem; justify-content: center; }
.menu-toggle:hover { border-color: var(--ember); background: color-mix(in srgb, var(--ember-deep) 20%, transparent); }
.menu-toggle svg { display: block; }
.menu-toggle .i-close { display: none; }
#nav-toggle:checked ~ .menu-toggle .i-burger { display: none; }
#nav-toggle:checked ~ .menu-toggle .i-close { display: block; }
#nav-toggle { display: none; }

/* Off-canvas drawer scrim: a dimming layer behind the panel; clicking it closes the menu (it is a
   <label for="nav-toggle">). Hidden until the menu opens; only active on phones (see media query). */
.nav-scrim {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 64;
  background: var(--scrim);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--t-med) var(--ease);
}

/* language switcher (Variante A): globe + locale + caret, JS-free native <details> popover */
.langmenu { position: relative; }
.langmenu > summary {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  cursor: pointer;
  color: var(--muted);
  font-size: var(--step--1);
  padding: 0.4rem 0.55rem;
  border: 1px solid var(--border2);
  border-radius: 0.55rem;
  list-style: none;
  user-select: none;
  white-space: nowrap;
}
.langmenu > summary::-webkit-details-marker { display: none; }
.langmenu > summary:hover { color: var(--text); border-color: var(--faint); }
.langmenu .globe { display: block; opacity: 0.85; }
.langmenu .lang-code { font-weight: 700; letter-spacing: 0.02em; }
.langmenu .caret { transition: transform var(--t-fast) var(--ease); opacity: 0.7; }
.langmenu[open] > summary { color: var(--text); border-color: var(--faint); }
.langmenu[open] .caret { transform: rotate(180deg); }
.langmenu-pop {
  position: absolute;
  top: calc(100% + 0.5rem);
  right: 0;
  z-index: 40;
  display: grid;
  grid-template-columns: repeat(2, minmax(8.5rem, 1fr));
  gap: 0.1rem 0.4rem;
  padding: 0.5rem;
  background: var(--surface2);
  border: 1px solid var(--border2);
  border-radius: 0.7rem;
  box-shadow: 0 18px 40px rgba(0, 0, 0, 0.45);
}
.langmenu-pop .langopt {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.45rem 0.55rem;
  border-radius: 0.45rem;
  color: var(--muted);
  font-size: var(--step--1);
  white-space: nowrap;
}
.langmenu-pop .langopt:hover { color: var(--text); background: var(--surface); }
.langmenu-pop .langopt.active { color: var(--ember); font-weight: 700; }
.langmenu-pop .langtick { width: 0.9rem; flex: none; color: var(--ember); text-align: center; }

/* hero */
.hero {
  position: relative;
  padding: clamp(4rem, 2rem + 9vw, 7.5rem) 0 clamp(3.5rem, 2rem + 6vw, 6rem);
  text-align: center;
  overflow: hidden;
}
.hero::before {
  content: "";
  position: absolute;
  top: -10rem;
  left: 50%;
  transform: translateX(-50%);
  width: min(56rem, 120%);
  height: 38rem;
  background: radial-gradient(closest-side, color-mix(in srgb, var(--ember-deep) 20%, transparent), transparent 68%);
  pointer-events: none;
}
/* lamp cord into the hero glow (subtle workshop light) */
.hero::after {
  content: "";
  position: absolute;
  top: 0;
  left: 50%;
  width: 1px;
  height: clamp(2rem, 6vw, 4.5rem);
  background: linear-gradient(var(--faint), transparent);
  pointer-events: none;
}
.kicker {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  color: var(--muted);
  font-size: var(--step--1);
  border: 1px solid var(--border2);
  border-radius: 2.5rem;
  padding: 0.45rem 1rem;
  margin-bottom: 1.8rem;
  background: rgba(255, 244, 230, 0.02);
}
.kicker .d {
  width: 0.4rem;
  height: 0.4rem;
  border-radius: 50%;
  background: var(--ember);
  box-shadow: 0 0 0.6rem var(--ember);
}
h1.title {
  position: relative;
  font-size: var(--step-hero);
  letter-spacing: -0.04em;
}
/* Punkt 0: no gradient headline text anywhere; solid warm ember (matches the .lp-hero accent). */
h1.title .accent {
  color: var(--ember);
}
.lead {
  position: relative;
  color: var(--muted);
  font-size: var(--step-1);
  max-width: 38ch;
  margin: 1.6rem auto 2rem;
}
.cta-row {
  position: relative;
  display: flex;
  gap: 0.8rem;
  justify-content: center;
  flex-wrap: wrap;
}
.note {
  position: relative;
  margin-top: 1.25rem;
  color: var(--faint);
  font-size: var(--step--1);
}

/* long-form document (legal notice, privacy policy) */
.doc { max-width: 68ch; margin: 0 auto; }
.doc h1 { font-size: var(--step-3); }
.doc h2 { font-size: var(--step-2); margin: 2.4rem 0 0.4rem; letter-spacing: -0.02em; }
.doc h3 { font-size: var(--step-1); margin: 1.8rem 0 0.3rem; letter-spacing: -0.02em; }
.doc p, .doc li { color: var(--muted); }
.doc p { margin: 0.8rem 0; }
.doc ul { margin: 0.8rem 0; padding-left: 1.2rem; }
.doc li { margin: 0.35rem 0; }
.doc strong { color: var(--text); font-weight: 600; }
.doc-meta { font-size: var(--step--1); color: var(--faint); }

/* sections */
section { padding: clamp(3.5rem, 2rem + 6vw, 6rem) 0; }
.lab {
  font-size: 0.8rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ember);
  font-weight: 600;
}
.prose { color: var(--muted); }
.prose p { margin: 1.1rem 0 0; }
.prose p:first-child { margin-top: 0; }
.hero .lead p { margin: 0; }
.cta .prose { max-width: 44ch; margin: 1.1rem auto 1.9rem; font-size: var(--step-1); }
.cta .prose p { margin: 0.6rem 0 0; }
.cta .prose p:first-child { margin-top: 0; }

.head { text-align: center; max-width: 38ch; margin: 0 auto clamp(2.5rem, 1rem + 4vw, 3.75rem); }
.head h2 { font-size: var(--step-3); margin-top: 0.9rem; }
.head p { color: var(--muted); margin-top: 1rem; font-size: var(--step-1); }

/* handled band */
.band {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: clamp(1.75rem, 1rem + 3vw, 3.4rem);
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(1.75rem, 1rem + 3vw, 3.4rem);
  align-items: center;
}
.band h2 { font-size: var(--step-2); margin: 0.9rem 0 1rem; }
.band p { color: var(--muted); margin: 0; }

/* closing cta */
.cta { position: relative; text-align: center; padding: clamp(4rem, 2rem + 7vw, 7rem) 0 3.75rem; overflow: hidden; }
.cta::before {
  content: "";
  position: absolute;
  bottom: -12rem;
  left: 50%;
  transform: translateX(-50%);
  width: min(51rem, 120%);
  height: 32rem;
  background: radial-gradient(closest-side, color-mix(in srgb, var(--ember-deep) 18%, transparent), transparent 68%);
}
.cta > * { position: relative; }
.cta h2 { font-size: clamp(2.1rem, 1.2rem + 4.4vw, 4rem); letter-spacing: -0.04em; }
.cta p { color: var(--muted); max-width: 44ch; margin: 1.1rem auto 1.9rem; font-size: var(--step-1); }

footer {
  border-top: 1px solid var(--border);
  padding: 2.6rem 0 4.4rem;
  color: var(--faint);
  font-size: var(--step--1);
  display: flex;
  justify-content: space-between;
  gap: 1.1rem;
  flex-wrap: wrap;
}
.foot-links { display: flex; flex-wrap: wrap; gap: 0.4rem 1.4rem; }
.foot-links a { color: var(--muted); padding: 0.35rem 0; transition: color var(--t-fast) var(--ease); }
.foot-links a:hover { color: var(--text); }

/* auth + onboarding (register, login, reset, status pages) */
.auth-shell {
  max-width: 30rem;
  margin: clamp(2.5rem, 1.5rem + 4vw, 4.5rem) auto;
  padding: 0 var(--gutter);
}
.auth-shell-wide { max-width: 42rem; }
.auth-shell-center { min-height: 68svh; display: flex; flex-direction: column; justify-content: center; }
/* Atmosphere: one warm workshop light behind the centered auth/onboarding card, so the
   sign-in is lit like the rest of the atelier instead of floating on flat black. CSS-only
   (no image), fixed to the viewport, sits behind all content, never intercepts clicks. */
.auth-shell::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(58rem 38rem at 50% -10%, color-mix(in srgb, var(--ember-deep) 11%, transparent), transparent 60%),
    radial-gradient(34rem 30rem at 50% 16%, color-mix(in srgb, var(--ember) 6%, transparent), transparent 72%);
}
.auth-card {
  position: relative;
  /* a faint warm rim along the top edge (as if the light above catches it), over the surface */
  background:
    linear-gradient(180deg, color-mix(in srgb, var(--ember) 5%, transparent), transparent 28%),
    var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: clamp(1.5rem, 1rem + 2.5vw, 2.6rem);
  box-shadow: 0 1.4rem 3.5rem rgba(0, 0, 0, 0.42);
}
.auth-card h1 { font-size: var(--step-2); letter-spacing: -0.03em; text-wrap: balance; }
.auth-sub { color: var(--muted); margin: 0.7rem 0 1rem; }
.auth-reassure { color: var(--text); opacity: 0.82; font-size: var(--step--1); margin: 0 0 1.6rem; padding-left: 0.9rem; border-left: 2px solid var(--ember); text-wrap: pretty; }

.field { display: flex; flex-direction: column; gap: 0.4rem; margin-bottom: 1.15rem; }
.field label { font-size: var(--step--1); color: var(--text); font-weight: 600; }
.field label .opt { color: var(--faint); font-weight: 400; }
.field input,
.field select,
.field textarea {
  width: 100%;
  background: var(--bg);
  border: 1px solid var(--field-border);
  border-radius: 0.6rem;
  padding: 0.7rem 0.85rem;
  color: var(--text);
  font-family: inherit;
  font-size: var(--step-0);
  line-height: 1.4;
}
.field textarea { resize: vertical; min-height: 3rem; }
.field input:focus,
.field select:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--ember-deep);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--ember-deep) 18%, transparent);
}
.field .hint { font-size: var(--step--1); color: var(--faint); }
/* Text-only button that reads like a quiet link (e.g. the build-wish click-escape). */
.link-btn {
  align-self: flex-start;
  background: none;
  border: none;
  padding: 0.15rem 0;
  margin-top: 0.15rem;
  color: var(--muted);
  font: inherit;
  font-size: var(--step--1);
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}
.link-btn:hover { color: var(--ember); }
.link-btn:focus-visible { outline: 2px solid var(--ember); outline-offset: 2px; }
.field .hint code,
.auth-card code { background: var(--bg); border: 1px solid var(--border); border-radius: 0.35rem; padding: 0.05rem 0.35rem; font-size: 0.9em; }

.row2 { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }
.checkbox-row { flex-direction: row; align-items: center; gap: 0.6rem; }
/* custom box instead of the tiny native white default: dark, brand-tinted when checked, larger touch
   target, consistent on every browser (replaces the bright system checkbox the audit flagged) */
.checkbox-row input {
  appearance: none; -webkit-appearance: none;
  width: 1.25rem; height: 1.25rem; flex: 0 0 auto; margin: 0;
  border: 1px solid var(--field-border); border-radius: 0.35rem;
  background: var(--bg); cursor: pointer; position: relative;
  transition: background-color var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease);
}
.checkbox-row input:checked { background: var(--ember); border-color: var(--ember); }
.checkbox-row input:checked::after {
  content: ""; position: absolute; left: 0.42rem; top: 0.2rem;
  width: 0.3rem; height: 0.6rem; border: solid var(--on-accent); border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}
.checkbox-row input:focus-visible { outline: 2px solid var(--ember); outline-offset: 2px; }
.checkbox-row label { font-weight: 400; color: var(--muted); margin: 0; }

/* Cloudflare Turnstile: flexible size is responsive, so it stays inside the card; keep it clear of
   the newsletter checkbox above and never let it spill past the card edge (e.g. at 125% zoom). */
.cf-turnstile { margin: 1.6rem 0 0; max-width: 100%; overflow: hidden; }
/* Turnstile renders a fixed ~300px-wide iframe. On very narrow viewports (small phones, or a
   phone at ~125% page zoom) the card is narrower than 300px and the widget was being CLIPPED on
   the right by overflow:hidden. Below the threshold: stop clipping, let it use the full card width
   by breaking out of the card padding, and scale the fixed-width widget down to fit. */
@media (max-width: 24em) {
  .cf-turnstile {
    overflow: visible;
    margin-left: calc(-1 * clamp(1.5rem, 1rem + 2.5vw, 2.6rem));
    margin-right: calc(-1 * clamp(1.5rem, 1rem + 2.5vw, 2.6rem));
    transform: scale(0.83);
    transform-origin: center top;
  }
}

/* Password show/hide toggle (partials/password_field.html): an eye button overlaid at the right
   edge of the input, swapping to an eye-off icon when the password is revealed. */
.pw-wrap { position: relative; display: block; }
.pw-wrap input { padding-right: 2.9rem; }
.pw-toggle {
  position: absolute; top: 0; right: 0; height: 100%; width: 2.8rem;
  display: inline-flex; align-items: center; justify-content: center;
  padding: 0; border: 0; background: none; color: var(--faint); cursor: pointer;
  border-radius: 0 0.6rem 0.6rem 0;
}
.pw-toggle:hover { color: var(--text); }
.pw-toggle:focus-visible { outline: 2px solid var(--ember-deep); outline-offset: -2px; }
.pw-toggle svg { width: 1.2rem; height: 1.2rem; display: block; }
.pw-toggle .i-eye-off { display: none; }
.pw-toggle.on { color: var(--ember); }
.pw-toggle.on .i-eye { display: none; }
.pw-toggle.on .i-eye-off { display: block; }

.btn.block { width: 100%; margin-top: 0.4rem; }

.form-error,
.form-notice {
  border-radius: 0.6rem;
  padding: 0.75rem 0.9rem;
  margin-bottom: 1.2rem;
  font-size: var(--step--1);
  line-height: 1.5;
}
.form-error { background: color-mix(in srgb, var(--ember-deep) 16%, transparent); border: 1px solid var(--border2); border-left: 3px solid var(--ember); color: var(--text); }
.form-notice { background: var(--surface2); border: 1px solid var(--border); color: var(--muted); }

.auth-foot { margin-top: 1.5rem; color: var(--muted); font-size: var(--step--1); line-height: 1.9; }
.auth-foot a { color: var(--ember); }
.inline-resend { margin-top: 0.4rem; }

/* honeypot: visually + AT hidden, still submitted (real users never fill it) */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* next-steps finish line */
.next-steps { list-style: none; counter-reset: step; padding: 0; margin: 1.6rem 0; }
.next-steps li {
  counter-increment: step;
  position: relative;
  padding: 0 0 1.5rem 3rem;
  border-left: 1px solid var(--border);
  margin-left: 0.6rem;
}
.next-steps li:last-child { border-left-color: transparent; padding-bottom: 0; }
.next-steps li::before {
  content: counter(step);
  position: absolute;
  left: -0.85rem;
  top: -0.15rem;
  width: 1.7rem;
  height: 1.7rem;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--surface2);
  border: 1px solid var(--border2);
  color: var(--ember);
  font-weight: 800;
  font-size: var(--step--1);
}
.next-steps h3 { font-size: var(--step-1); margin-bottom: 0.3rem; letter-spacing: -0.02em; }
.next-steps p { color: var(--muted); margin: 0.35rem 0; }
pre.cmd {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 0.6rem;
  padding: 0.7rem 0.9rem;
  color: var(--ember);
  font-size: var(--step-0);
  overflow-x: auto;
  margin: 0.5rem 0;
}
.ws-link {
  display: inline-block;
  background: var(--bg);
  border: 1px solid var(--ember-deep);
  border-radius: 0.6rem;
  padding: 0.7rem 0.9rem;
  color: var(--ember);
  font-weight: 700;
  font-size: var(--step-0);
  text-decoration: none;
  margin: 0.5rem 0;
  word-break: break-all;
}
.ws-link:hover { border-color: var(--ember); }
.next-help { border-top: 1px solid var(--border); margin-top: 0.5rem; padding-top: 1.4rem; }
.logout-form { margin-top: 1.6rem; }

/* ---- admin console -------------------------------------------------------------------- */
.admin-nav .admin-tag {
  font-size: 0.7rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ember);
  border: 1px solid var(--border2);
  border-radius: 0.4rem;
  padding: 0.1rem 0.4rem;
  font-weight: 700;
}
.navlinks a.active { color: var(--text); }
.navlinks .soon {
  color: var(--faint);
  font-size: var(--step--1);
  white-space: nowrap;
}
.admin-logout { margin: 0; }

.admin-wrap { padding-top: 2.2rem; padding-bottom: 4rem; }
.admin-wrap .back { margin: 0 0 1.2rem; }
.admin-wrap .back a { color: var(--muted); font-size: var(--step--1); }
.admin-wrap .back a:hover { color: var(--text); }
.admin-head { margin-bottom: 1.6rem; }
.admin-head h1 { font-size: var(--step-2); }
.admin-sub { color: var(--muted); margin: 0.6rem 0 0; display: flex; align-items: center; gap: 0.7rem; flex-wrap: wrap; }
/* Stub/simulation notices: lifted out of the description prose into their own quiet, consistently
   styled note (badge first), so they read as a status hint instead of debug text in the sentence. */
.stub-note {
  display: flex; align-items: center; gap: 0.55rem; flex-wrap: wrap;
  margin: 0.9rem 0 0; padding: 0.5rem 0.8rem;
  border-left: 2px solid var(--border2); border-radius: 0 0.4rem 0.4rem 0;
  background: var(--surface); color: var(--faint); font-size: var(--step--1);
}

/* status filter chips */
.chips { display: flex; flex-wrap: wrap; gap: 0.55rem; margin-bottom: 1.6rem; }
.chip {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  border: 1px solid var(--border);
  background: var(--surface);
  border-radius: 2rem;
  padding: 0.4rem 0.85rem;
  font-size: var(--step--1);
  color: var(--muted);
}
.chip:hover { color: var(--text); }
.chip.on { border-color: var(--ember-deep); color: var(--text); }
.chip b { color: var(--ember); font-weight: 700; }

/* tables */
.table-scroll { overflow-x: auto; border: 1px solid var(--border); border-radius: var(--r-lg); }
.admin-table { width: 100%; min-width: 44rem; border-collapse: collapse; font-size: var(--step--1); }
.admin-table th {
  text-align: left;
  color: var(--faint);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-size: 0.74rem;
  padding: 0.85rem 1rem;
  border-bottom: 1px solid var(--border);
  background: var(--surface);
}
.admin-table td { padding: 0.85rem 1rem; border-bottom: 1px solid var(--border); color: var(--text); }
.admin-table tbody tr:last-child td { border-bottom: none; }
.admin-table tbody tr { cursor: pointer; }
.admin-table tbody tr:hover { background: var(--surface); }
.admin-table.compact th, .admin-table.compact td { padding: 0.6rem 0.85rem; }
.admin-table.compact tbody tr { cursor: default; }
.admin-table.compact tbody tr:hover { background: transparent; }
/* Admin tables collapse to stacked cards on phones (no off-screen columns). */
@media (max-width: 40rem) {
  .table-scroll { overflow-x: visible; border: none; border-radius: 0; }
  .admin-table { min-width: 0; }
  .admin-table thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
  .admin-table, .admin-table tbody, .admin-table tr, .admin-table td { display: block; width: 100%; }
  .admin-table tr { border: 1px solid var(--border); border-radius: var(--r-lg); padding: 0.55rem 0; margin-bottom: 0.7rem; }
  .admin-table td { border: none; padding: 0.28rem 1rem; }
  .admin-table td[data-label]::before { content: attr(data-label) ": "; color: var(--faint); font-size: var(--step--1); }
  .admin-table td:first-child { font-weight: 600; font-size: var(--step-0); padding-bottom: 0.45rem; }
}

.mono { font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 0.92em; }
.muted { color: var(--muted); }
.empty { color: var(--faint); padding: 1.5rem 0; }

/* status badge */
.badge {
  display: inline-block;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  padding: 0.18rem 0.55rem;
  border-radius: 2rem;
  border: 1px solid var(--border2);
  color: var(--muted);
  white-space: nowrap;
  vertical-align: middle;  /* sit centred next to its label (e.g. "Account status: [active]") */
}
.badge.s-pending_verify { color: var(--faint); }
.badge.s-pending_approval { color: var(--ember); border-color: var(--ember-deep); }
.badge.s-approved { color: var(--info); border-color: color-mix(in srgb, var(--info) 33%, transparent); }
/* Setup done -> ready to provision: a distinct teal so "the user's turn is over, it's ours now"
   reads at a glance, apart from plain approved blue. */
.badge.s-setup_done { color: var(--teal); border-color: color-mix(in srgb, var(--teal) 33%, transparent); }
/* Provisioning in progress: amber, the same in-flight cue as awaiting-approval. */
.badge.s-provisioning { color: var(--ember); border-color: var(--ember-deep); }
.badge.s-active { color: var(--ok); border-color: color-mix(in srgb, var(--ok) 33%, transparent); }
.badge.s-provision_failed { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 33%, transparent); }
.badge.s-rejected { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 33%, transparent); }
/* Reversible admin pause (B3): a calm amber, not an error red (the account is fine, just paused). */
.badge.s-suspended { color: var(--ember); border-color: var(--ember-deep); }

/* Onboarding Claude access (B5): the three ways to power Claude, each a calmly divided block. */
/* This is a <section> inside the setup card, so it would inherit the global section{} block
   padding (clamp up to 6rem top+bottom) and open a big void; neutralise it to a normal margin. */
.claude-access { margin: 1.8rem 0; padding: 0; }
.claude-access .claude-h { font-size: 1.05rem; margin: 0 0 .6rem; }
.claude-opt { padding: 1rem 0; border-top: 1px solid var(--border2); }
.claude-opt:first-of-type { border-top: none; padding-top: .25rem; }
.claude-opt h3 { font-size: 1rem; margin: 0 0 .35rem; }
.claude-opt .opt { color: var(--faint); font-weight: 400; font-size: .85em; }

/* Onboarding Claude-access: the F&F allowance is the big recommended default; the own-token ways
   step back into a small expandable panel below (Entscheidung 4, 2026-06-30). */
.claude-primary {
  margin: 1.3rem 0;
  padding: 1.15rem 1.25rem;
  background: var(--surface2);
  border: 1px solid var(--ember-deep);
  border-radius: var(--r-md);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--ember-deep) 10%, transparent), 0 8px 24px rgba(0, 0, 0, 0.22);
}
.claude-primary-head { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem .6rem; margin-bottom: .25rem; }
.claude-primary-head h3 { font-size: 1.05rem; margin: 0; letter-spacing: -0.01em; }
.claude-badge {
  font-size: .68rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  color: var(--bg); background: var(--ember); border-radius: 999px; padding: .15rem .55rem;
}
.claude-primary .hint { margin: 0 0 .85rem; }
.claude-own { margin: .4rem 0 .25rem; }
.claude-own > summary {
  cursor: pointer; list-style: none; color: var(--muted); font-size: var(--step--1);
  display: flex; align-items: center; gap: .3rem; min-height: 2.75rem; /* >=44px touch target (WCAG 2.5.8) */
  padding: .35rem .1rem; border-top: 1px solid var(--border2); user-select: none;
}
.claude-own > summary::-webkit-details-marker { display: none; }
.claude-own > summary::before { content: "+"; color: var(--faint); font-weight: 700; }
.claude-own[open] > summary::before { content: "\2212"; }
.claude-own > summary:hover { color: var(--text); }
.claude-own-body { padding-top: .25rem; }
.build-hint { text-align: center; margin-top: .7rem; }

/* Onboarding "building your workshop" waiting page: a calm card with a warm, slowly breathing lamp
   glow (mirrors the site's ember mark), so the wait feels like something is being made for you. */
.building-card { text-align: center; }
.building-lamp { display: flex; justify-content: center; margin: .4rem 0 1.5rem; }
.building-ember {
  width: .85rem; height: .85rem; border-radius: 50%;
  background: var(--ember); box-shadow: 0 0 1.2rem .15rem var(--ember), 0 0 .3rem #fff7;
  animation: building-breathe 2.6s var(--ease) infinite;
}
@keyframes building-breathe {
  0%, 100% { opacity: .55; transform: scale(0.9); box-shadow: 0 0 .8rem .1rem var(--ember); }
  50% { opacity: 1; transform: scale(1.12); box-shadow: 0 0 1.6rem .3rem var(--ember), 0 0 .4rem #fff8; }
}
@media (prefers-reduced-motion: reduce) {
  .building-ember { animation: none; opacity: .9; }
}
/* Admin user page: Claude-access action buttons line up with comfortable spacing. */
.admin-card form.stack { margin-top: .9rem; }
/* "not configured here" markers (relay/cost/WIF/panel stub): neutral grey, NOT an error red. */
.badge.s-stub { color: var(--faint); border-color: var(--border2); }

/* cards + detail */
.admin-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: clamp(1.25rem, 0.9rem + 1.6vw, 1.9rem);
  margin-bottom: 1.4rem;
}
.admin-card h2 { font-size: var(--step-1); margin-bottom: 1rem; letter-spacing: -0.02em; }
.admin-card h2 .opt { color: var(--faint); font-weight: 400; font-size: 0.8em; }
.admin-card .hint { color: var(--faint); font-size: var(--step--1); margin: 0 0 1rem; }
.admin-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 1.4rem; }

.actions .action-row { display: flex; flex-wrap: wrap; gap: 0.7rem; }
.actions form { margin: 0; }
.actions .hint { margin: 1rem 0 0; }
.btn.danger { border: 1px solid color-mix(in srgb, var(--danger) 33%, transparent); color: var(--danger); background: transparent; }
.btn.danger:hover { background: color-mix(in srgb, var(--danger) 10%, transparent); }

.kv { display: grid; grid-template-columns: minmax(7rem, auto) 1fr; gap: 0.5rem 1rem; margin: 0; }
.kv dt { color: var(--faint); font-size: var(--step--1); }
.kv dd { margin: 0; color: var(--text); font-size: var(--step--1); word-break: break-word; }

/* --- Phase 7: provisioning + setup --- */
/* provisioning / relay statuses, same vocabulary as the lifecycle badges */
.badge.s-applied { color: var(--ok); border-color: color-mix(in srgb, var(--ok) 33%, transparent); }
.badge.s-active,
.badge.s-dry_run { color: var(--info); border-color: color-mix(in srgb, var(--info) 33%, transparent); }
.badge.s-pending { color: var(--faint); }
.badge.s-blocked,
.badge.s-failed,
.badge.s-error { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 33%, transparent); }

.form-notice.ok { border-color: color-mix(in srgb, var(--ok) 33%, transparent); color: var(--text); }
.form-notice.warn { border-color: var(--ember-deep); color: var(--text); }

/* stage-2 plausibility report */
.check-list { list-style: none; margin: 0 0 1.4rem; padding: 0; display: grid; gap: 0.5rem; }
.check-list li {
  display: grid;
  grid-template-columns: 1.4rem 6rem 1fr;
  gap: 0.5rem;
  align-items: baseline;
  font-size: var(--step--1);
}
.check-list .check-mark { font-weight: 700; text-align: center; }
.check-list li.ok .check-mark { color: var(--ok); }
.check-list li.bad .check-mark { color: var(--danger); }
.check-list .check-field { color: var(--faint); text-transform: capitalize; }
.check-list .check-msg { color: var(--text); text-wrap: pretty; }

/* truncated relay output cell in the admin tables */
.out-cell { max-width: 22rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Workspace card (Admin cockpit "Arbeitsplatz", D-211): disk meter + ampel + status rows. */
.ws-meter { margin: 0.4rem 0 0.2rem; }
.ws-meter-head { display: flex; justify-content: space-between; gap: 1rem; font-size: var(--step--1); }
.ws-meter-head .ws-pct { color: var(--faint); }
.ws-meter-bar {
  margin-top: 0.4rem;
  height: 0.5rem;
  border-radius: 0.3rem;
  background: var(--surface2);
  border: 1px solid var(--border);
  overflow: hidden;
}
.ws-meter-fill { height: 100%; border-radius: 0.3rem 0 0 0.3rem; background: var(--ok); }
.ws-meter.lvl-orange .ws-meter-fill { background: var(--ember); }
.ws-meter.lvl-red .ws-meter-fill { background: var(--danger); }
.ws-meter.lvl-orange .ws-pct { color: var(--ember); }
.ws-meter.lvl-red .ws-pct { color: var(--danger); }

/* small inline forms (refresh, sign-out link) */
.inline-form { margin: 0.6rem 0 0; }
.action-row.tight { gap: 0.4rem; }
.action-row.tight form { margin: 0; }
.inline-logout { display: inline; margin: 0; }
.linkish {
  background: none;
  border: none;
  padding: 0;
  color: var(--muted);
  cursor: pointer;
  font: inherit;
  text-decoration: underline;
}
.linkish:hover { color: var(--text); }

/* Breakpoint in em, not px (D-058): at text zoom the rem-based nav grows but a px breakpoint would
   not, so the desktop nav would crowd/wrap before the mobile menu takes over. em tracks the zoom.
   66em (~1056px): the nav folds to the menu button just before the fuller signed-in row (eight items:
   four landing anchors + area/help/account + language switcher) would run out of room in the 1080px
   bar. One breakpoint for both states, so signed-in and signed-out fold identically and there is no
   special-cased desktop menu button. Page-content tweaks stay at 760px below. */
@media (max-width: 66em) {
  .menu-toggle { display: inline-flex; }
  /* keyboard access (no JS): the toggle is a checkbox driving the drawer. Off the desktop it must be
     focusable+operable (Space), so visually hide it WITHOUT display:none (which drops it from the tab
     order). The focus ring is painted on the visible button via the sibling combinator. */
  #nav-toggle { display: block; position: absolute; width: 1px; height: 1px; opacity: 0; margin: 0; pointer-events: none; }
  #nav-toggle:focus-visible ~ .menu-toggle { outline: 2px solid var(--ember); outline-offset: 2px; }
  .nav-scrim { display: block; }
  /* drawer never adds a horizontal scrollbar while parked off-canvas to the right */
  body { overflow-x: hidden; }
  /* lock the page behind the open drawer (no JS); :has is well supported on current browsers */
  html:has(#nav-toggle:checked) { overflow: hidden; }

  /* Full-screen overlay, not a narrow drawer: the workshop opens its door into warm light.
     Ember glow over a deep, blurred backdrop; few, large links. This is where the brand shows
     up in the menu itself instead of an interchangeable side panel. */
  .navlinks {
    position: fixed;
    inset: 0;
    z-index: 70;
    height: 100%;
    height: 100dvh;
    width: 100%;
    flex-direction: column;
    align-items: stretch;
    justify-content: center;
    gap: 0.15rem;
    padding: 6rem 2rem 3rem;
    background:
      radial-gradient(80% 55% at 50% 30%, color-mix(in srgb, var(--ember-deep) 16%, transparent), transparent 70%),
      color-mix(in srgb, var(--bg) 90%, transparent);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    overflow-y: auto;
    font-size: var(--step-0);
    opacity: 0;
    visibility: hidden;  /* out of tab + screen-reader order until opened */
    transition: opacity var(--t-med) var(--ease), visibility var(--t-med) var(--ease);
  }
  /* Direct child selector (>) only: the big display type must NOT cascade into the language
     popover's links, which live deeper inside .langmenu and were inheriting this size. */
  .navlinks > a:not(.btn) {
    padding: 0.25rem 0.2rem;
    color: var(--text);
    /* present but restrained: each item stays on one line at phone width incl. 125% zoom */
    font-size: clamp(1.05rem, 0.9rem + 1vw, 1.3rem);
    line-height: 1.25;
    letter-spacing: -0.01em;
    /* staggered reveal: each link glows up from just below, one after another (set on open) */
    opacity: 0;
    transform: translateY(12px);
    transition: opacity 0.5s var(--ease), transform 0.5s var(--ease);
  }
  .navlinks .btn { justify-content: center; margin-top: 1.2rem; font-size: var(--step-0); }
  #nav-toggle:checked ~ .navlinks { opacity: 1; visibility: visible; }
  #nav-toggle:checked ~ .navlinks > a:not(.btn) { opacity: 1; transform: none; }
  #nav-toggle:checked ~ .navlinks > a:not(.btn):nth-child(1) { transition-delay: 0.05s; }
  #nav-toggle:checked ~ .navlinks > a:not(.btn):nth-child(2) { transition-delay: 0.10s; }
  #nav-toggle:checked ~ .navlinks > a:not(.btn):nth-child(3) { transition-delay: 0.15s; }
  #nav-toggle:checked ~ .navlinks > a:not(.btn):nth-child(4) { transition-delay: 0.20s; }
  #nav-toggle:checked ~ .navlinks > a:not(.btn):nth-child(5) { transition-delay: 0.25s; }
  #nav-toggle:checked ~ .navlinks > a:not(.btn):nth-child(6) { transition-delay: 0.30s; }
  #nav-toggle:checked ~ .nav-scrim { opacity: 1; pointer-events: auto; }
  /* When the header hides on scroll-down its transform becomes the containing block for the fixed
     drawer; the (always-closed-while-hidden) drawer would then overflow to the right, so drop it
     from layout entirely. Opening the menu removes is-hidden first (base.html), so it never clashes. */
  .site-head.is-hidden .navlinks { display: none; }
  /* In the folded drawer the language popover flows inline instead of floating, so it never clips.
     Give it the same top separation the CTA has, so the switcher does not stick to the button above. */
  .langmenu { width: 100%; margin-top: 1.1rem; }
  .langmenu > summary { width: 100%; justify-content: flex-start; }
  .langmenu-pop { position: static; box-shadow: none; margin-top: 0.35rem; }
  .navlinks .soon { display: none; }
}

@media (max-width: 760px) {
  .band { grid-template-columns: 1fr; }
  /* Stack key/value rows on narrow screens so action buttons get the full width instead of being
     squeezed into a sliver where each button label wraps one letter per line (iPhone fix). */
  .kv { grid-template-columns: 1fr; gap: 0.2rem 0; }
  .kv dt { padding-top: 0.7rem; }
  /* Footer: stack into clean columns with gap rhythm instead of ragged inline-anchor margins. */
  footer { flex-direction: column; gap: 1.4rem; }
  .foot-links { flex-direction: column; gap: 0.9rem; }
  .foot-links a { margin-left: 0; padding: 0.2rem 0; }
  .row2 { grid-template-columns: 1fr; gap: 0; }
  .admin-cols { grid-template-columns: 1fr; }
}
@media (prefers-reduced-motion: reduce) {
  .navlinks { transition: none; }
  /* no reveal motion: the links are simply present in their final state when the overlay opens */
  .navlinks > a:not(.btn),
  #nav-toggle:checked ~ .navlinks > a:not(.btn) {
    opacity: 1; transform: none; transition: none; transition-delay: 0s;
  }
}

/* --- cost cockpit ------------------------------------------------------------------------- */
.card-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 1rem; }
.card-head .chips { margin-bottom: 0; }
.kpi { margin-top: 1.2rem; display: flex; align-items: baseline; gap: 0.7rem; }
.kpi-label { color: var(--muted); font-size: var(--step--1); }
.kpi-val { font-size: var(--step-2); color: var(--text); }
h3.sub { margin: 1.6rem 0 0.6rem; font-size: var(--step-0); color: var(--muted); font-weight: 600; }
.bar-list, .proj-list { list-style: none; margin: 0.4rem 0 0; padding: 0; display: flex; flex-direction: column; gap: 0.55rem; }
.bar-list li, .proj-list li { display: flex; align-items: center; gap: 0.8rem; padding: 0.45rem 0; border-bottom: 1px solid var(--border); }
.bar-list li:last-child, .proj-list li:last-child { border-bottom: 0; }
.bar-label { color: var(--text); flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
.proj-list .muted { font-size: var(--step--1); }
.cost-amt { margin-left: auto; color: var(--ember); font-weight: 700; white-space: nowrap; }
.cost-form { display: flex; flex-direction: column; gap: 0.9rem; margin-top: 0.8rem; }
.cost-form-row { display: flex; flex-wrap: wrap; gap: 1rem; }
.cost-form label { display: flex; flex-direction: column; gap: 0.3rem; font-size: var(--step--1); color: var(--muted); flex: 1 1 9rem; }
.cost-form label.grow { flex: 3 1 16rem; }
.cost-form input, .cost-form select {
  background: var(--bg); color: var(--text); border: 1px solid var(--border2);
  border-radius: 0.5rem; padding: 0.5rem 0.6rem; font: inherit; min-height: 2.4rem;
}

/* --- cockpit health panels (lazy HTMX) ---------------------------------------------------- */
.panel-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 18rem), 1fr));
  gap: 1.2rem; margin-top: 0.8rem;
}
/* The slot is the grid cell (stretched to the row height); make it a grid so the panel inside
   fills that height. Otherwise a shorter panel leaves a void below it in the row. */
.panel-slot { display: grid; }
.panel {
  background: var(--bg); border: 1px solid var(--border); border-radius: 0.7rem;
  padding: 1rem 1.1rem; display: flex; flex-direction: column; gap: 0.55rem; min-width: 0;
}
.panel[data-state="loading"] { opacity: 0.6; }
.panel-head { display: flex; align-items: center; justify-content: space-between; gap: 0.6rem; }
.panel-head h3 { font-size: var(--step-0); margin: 0; letter-spacing: -0.01em; text-wrap: balance; }
.panel-summary { margin: 0; color: var(--text); font-size: var(--step--1); text-wrap: pretty; }
.panel-pre {
  margin: 0; background: var(--surface); border: 1px solid var(--border);
  border-radius: 0.5rem; padding: 0.6rem 0.7rem; font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 0.8rem; color: var(--muted); line-height: 1.5; overflow-x: auto; white-space: pre;
  max-height: 14rem; overflow-y: auto;
}
.panel-source { margin: 0; font-size: 0.75rem; }

/* Incidents panel (D-212/D-213): open-first list, each row click-to-expand. A safe one-click heal
   shows where the producer set one; proposal-state rows carry the two-button Vorschlags-Karte. */
.incident-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.5rem; max-height: 24rem; overflow-y: auto; }
.incident-row { padding-bottom: 0.4rem; border-bottom: 1px solid var(--border); }
.incident-row:last-child { border-bottom: none; padding-bottom: 0; }
.incident-row.is-done { opacity: 0.65; }
.incident-line { min-width: 0; font-size: 0.8rem; line-height: 1.45; color: var(--text); overflow-wrap: anywhere; }
.incident-heal { margin: 0; flex: 0 0 auto; }

/* Per-guardian filter chips (JS-enhanced; without JS all rows stay visible). */
.incident-filter { display: flex; flex-wrap: wrap; gap: 0.4rem; margin: 0.2rem 0 0.7rem; }
.incident-filter .chip {
  font: inherit; font-size: 0.72rem; line-height: 1; padding: 0.32rem 0.6rem; cursor: pointer;
  color: var(--muted); background: transparent; border: 1px solid var(--border2);
  border-radius: 999px;
}
.incident-filter .chip.is-active { color: var(--text); border-color: var(--accent, var(--border2)); }

/* Click-to-expand detail. The summary holds the compact line; the body the full record. */
.incident-detail { width: 100%; }
.incident-summary { cursor: pointer; list-style: none; display: flex; align-items: flex-start; gap: 0.5rem; }
.incident-summary::-webkit-details-marker { display: none; }
.incident-summary::before {
  content: "+"; flex: 0 0 auto; width: 1rem; color: var(--muted); font-family: ui-monospace, monospace;
}
.incident-detail[open] .incident-summary::before { content: "-"; }
.incident-body { margin: 0.6rem 0 0.2rem 1.5rem; display: flex; flex-direction: column; gap: 0.55rem; }
.incident-meta { margin: 0; display: flex; flex-wrap: wrap; gap: 0.15rem 1.2rem; }
.incident-meta > div { display: flex; gap: 0.45rem; font-size: 0.76rem; }
.incident-meta dt { margin: 0; color: var(--muted); }
.incident-meta dd { margin: 0; color: var(--text); overflow-wrap: anywhere; }
.incident-text { margin: 0; font-size: 0.82rem; line-height: 1.5; color: var(--text); text-wrap: pretty; }
.incident-log { margin: 0; font-size: 0.76rem; overflow-wrap: anywhere; }
.incident-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }
.incident-copy-src { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }

/* Vorschlags-Karte (D-213): a guardian's proposed resolution, applied only on an explicit click. */
.proposal-card { border: 1px solid var(--border2); border-radius: 0.5rem; padding: 0.6rem 0.7rem; display: flex; flex-direction: column; gap: 0.5rem; }
.proposal-hint { margin: 0; font-size: 0.76rem; text-wrap: pretty; }
.proposal-buttons { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.proposal-form { margin: 0; }

/* Watcher-ampel panel (self-healing Phase W, D-217): one green/red lamp per watcher, grouped by
   server with a freshness stamp. Colours reuse the badge palette (green ok, red trouble, grey
   unknown). The state word next to each lamp carries the meaning without relying on colour alone
   (accessibility: never colour-only). */
.ampel-hosts { display: flex; flex-direction: column; gap: 0.9rem; max-height: 26rem; overflow-y: auto; }
.ampel-host-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 0.3rem 0.8rem; }
.ampel-host-name { margin: 0; font-size: 0.86rem; letter-spacing: -0.01em; }
.ampel-fresh { font-size: 0.72rem; color: var(--muted); }
.ampel-fresh.is-stale { color: var(--danger); }
.ampel-counts { margin: 0.15rem 0 0.4rem; font-size: 0.74rem; }
.ampel-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.35rem; }
/* Grid so a long label never collapses to one-char-per-line next to the detail: lamp + state word
   sit in fixed leading columns, the label fills the rest, and the detail wraps onto its own row
   under the label (spanning the two text columns). */
.ampel-row {
  display: grid; grid-template-columns: auto auto 1fr; align-items: baseline;
  column-gap: 0.5rem; row-gap: 0.1rem; font-size: 0.78rem; line-height: 1.4;
}
.ampel-lamp {
  grid-row: 1; width: 0.62rem; height: 0.62rem; border-radius: 50%;
  align-self: center; background: var(--faint); box-shadow: 0 0 0 1px var(--border) inset;
}
.ampel-row.is-green .ampel-lamp { background: var(--ok); box-shadow: 0 0 0.4rem color-mix(in srgb, var(--ok) 53%, transparent); }
.ampel-row.is-red   .ampel-lamp { background: var(--danger); box-shadow: 0 0 0.4rem color-mix(in srgb, var(--danger) 60%, transparent); }
.ampel-row.is-unknown .ampel-lamp { background: var(--faint); }
.ampel-state-word { grid-row: 1; font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.03em; color: var(--muted); white-space: nowrap; }
.ampel-row.is-green .ampel-state-word { color: var(--ok); }
.ampel-row.is-red .ampel-state-word { color: var(--danger); }
.ampel-label { grid-row: 1; grid-column: 3; min-width: 0; color: var(--text); overflow-wrap: anywhere; }
.ampel-detail { grid-row: 2; grid-column: 2 / 4; font-size: 0.72rem; overflow-wrap: anywhere; }

/* Server-Gesundheit board (host_facts, D-217): one card per server with disk/RAM/updates/reboot from
   its fact sheet. Colour is never the only signal -- each metric shows its number next to a plain
   label, and an off value carries a warn/red tint (accessibility: never colour-only). */
.facts-hosts { display: flex; flex-direction: column; gap: 0.9rem; }
.facts-host { border: 1px solid var(--border); border-radius: 0.6rem; padding: 0.7rem 0.85rem; }
.facts-host.is-red { border-color: color-mix(in srgb, var(--danger) 60%, var(--border)); }
.facts-host.is-warn { border-color: color-mix(in srgb, var(--warn) 55%, var(--border)); }
.facts-host-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 0.3rem 0.8rem; }
.facts-host-name { margin: 0; font-size: 0.86rem; letter-spacing: -0.01em; }
.facts-fresh { font-size: 0.72rem; color: var(--muted); }
.facts-fresh.is-stale { color: var(--danger); }
.facts-metrics { list-style: none; margin: 0.5rem 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 0.4rem 1.4rem; }
.facts-metric { display: flex; align-items: baseline; gap: 0.4rem; font-size: 0.78rem; }
.facts-metric-label { color: var(--muted); }
.facts-metric-value { color: var(--text); font-variant-numeric: tabular-nums; }
.facts-metric.is-warn .facts-metric-value { color: var(--warn); }
.facts-metric.is-red .facts-metric-value { color: var(--danger); font-weight: 600; }
.facts-units { margin: 0.45rem 0 0; font-size: 0.72rem; }

/* =======================================================================================
   Landing / public marketing pages: bespoke, uniquely-named components + curated, people-free
   atelier scenes, so the functional app chrome (cockpit/auth) stays untouched.
   ======================================================================================= */

/* .lp-hero: shared base frame for the public page headers (landing hero + the page-intro on
   Meet Lina / Samples). */
.lp-hero { position: relative; overflow: hidden; padding: clamp(3rem, 2rem + 5vw, 5rem) 0; }
.lp-hero::before { content: ""; position: absolute; top: -8rem; right: -6rem; width: 40rem; height: 36rem; background: radial-gradient(closest-side, color-mix(in srgb, var(--ember-deep) 18%, transparent), transparent 68%); pointer-events: none; }
.lp-hero h1 { font-size: var(--step-hero-narrow); letter-spacing: -0.04em; }
/* Punkt 0: no gradient headline anywhere; solid warm ember on the accent word. */
.lp-hero h1 .accent { color: var(--ember); }
.lp-hero .lead { color: var(--muted); font-size: var(--step-1); max-width: 40ch; margin: 1.4rem 0 1.9rem; }

/* Landing hero: pottery-wheel photo, GATE-3b approved (D-257). Full-bleed scene, copy overlaid
   left over a warm scrim. This is the ONE landing hero -- there is no alternate/illustration variant. */
.lp-hero.hero-photo { padding: 0; min-height: clamp(30rem, 22rem + 26vw, 44rem); display: flex; align-items: center; }
.lp-hero.hero-photo::before { display: none; } /* no corner glow behind the full-bleed photo */
.lp-hero.hero-photo .hero-bg { position: absolute; inset: 0; z-index: 0; }
.lp-hero.hero-photo .hero-bg picture { display: block; width: 100%; height: 100%; }
.lp-hero.hero-photo .hero-bg img { width: 100%; height: 100%; object-fit: cover; object-position: 78% 46%; }
/* legibility scrim: near-opaque over the left copy column, dropping fast before the glass so the glow
   stays untouched; a gentle bottom and a faint far-right darkening keep every edge off pure bright. */
.lp-hero.hero-photo .hero-bg::after {
  content: ""; position: absolute; inset: 0;
  /* warm, eased, directional scrim (16 stops): near-opaque at the left text edge, fading to the
     clay/hands on the right with no visible line; a gentle bottom lift keeps the lower edge off pure
     bright. Scaled into 0-83% so the potter's hands on the right stay clear. */
  background: linear-gradient(95deg,
      hsla(25,30%,6%,0.97) 0%,  hsla(25,30%,6%,0.955) 7%, hsla(25,30%,6%,0.925) 13%,
      hsla(25,30%,6%,0.878) 19%, hsla(25,30%,6%,0.812) 24%, hsla(25,30%,6%,0.727) 29%,
      hsla(25,30%,6%,0.628) 34%, hsla(25,30%,6%,0.523) 39%, hsla(25,30%,6%,0.42) 44%,
      hsla(25,30%,6%,0.323) 49%, hsla(25,30%,6%,0.236) 54%, hsla(25,30%,6%,0.16) 59%,
      hsla(25,30%,6%,0.098) 64%, hsla(25,30%,6%,0.047) 70%, hsla(25,30%,6%,0.014) 76%,
      hsla(25,30%,6%,0) 83%),
    linear-gradient(0deg, color-mix(in srgb, var(--bg) 50%, transparent), transparent 42%);
}
/* copy pinned to the left gutter (not the centred wrap) so it sits wholly in the dark-left zone,
   clear of the glowing glass on the right. */
.lp-hero.hero-photo .wrap { position: relative; z-index: 2; max-width: none; width: 100%; padding-inline: clamp(1.5rem, 5vw, 6rem); }
.lp-hero.hero-photo .hero-copy { max-width: 30rem; }
.lp-hero.hero-photo .hero-copy .lead { max-width: 27rem; }
@media (max-width: 51em) {
  /* mobile: DECOUPLE image and copy. Overlaying the long lead on the bright, centred glass never
     reads clean (a veil strong enough to fix it dims the glass). Instead the glass shows full and
     undimmed as a bounded portrait visual that melts into --bg at its lower edge, and the copy sits
     below on the solid page at full contrast. */
  .lp-hero.hero-photo { display: block; min-height: 0; padding: 0; }
  /* image becomes a LOW, bounded landscape band (not a viewport-eating portrait): the headline,
     first lead line and the primary button must clear the fold even with the browser chrome and at
     125% zoom. Flat band -> no hard bottom crop of the bench/glass either. */
  .lp-hero.hero-photo .hero-bg { position: relative; inset: auto; width: 100%; height: clamp(11rem, 32vh, 16rem); }
  .lp-hero.hero-photo .hero-bg img { object-position: 50% 42%; }
  /* only a soft bottom fade into the page, so the image melts in instead of cutting hard */
  .lp-hero.hero-photo .hero-bg::after { background: linear-gradient(180deg, transparent 56%, var(--bg) 100%); }
  /* copy on the solid brand ground below the image (AA-safe), lifted under the fade as a calm panel */
  .lp-hero.hero-photo .wrap {
    position: static; z-index: auto; background: var(--bg);
    margin-top: -2.25rem; border-radius: 1.25rem 1.25rem 0 0;
    padding: 1.5rem clamp(1.25rem, 6vw, 2rem) clamp(2.25rem, 9vw, 3.25rem);
  }
  .lp-hero.hero-photo .hero-copy, .lp-hero.hero-photo .hero-copy .lead { max-width: none; }
}

/* ---- landing photo-hero content v9 (potter's wheel, approved 2026-07-04): a serif headline over
   the calm dark-left zone, then a short spoken conversation whose wish rotates through the real
   examples. Reuses .lp-hero.hero-photo so the body.lp ignite + lamp-flare signature still fires.
   Only the headline takes the Fraunces serif (warm, old-school workshop); the rest stays on the
   site body font, so no extra body webfont ships. ---- */
@font-face {
  font-family: "Fraunces";
  src: url("/static/fonts/fraunces-normal.woff2") format("woff2");
  font-weight: 100 900; font-style: normal; font-display: swap;
}
.lp-hero.hero-photo .hero-copy { max-width: 34rem; }
.lp-hero.hero-photo h1 {
  font-family: "Fraunces", Georgia, "Times New Roman", serif; font-weight: 480;
  font-optical-sizing: auto; font-size: var(--step-hero-narrow); line-height: 1.05;
  letter-spacing: -0.015em; text-wrap: balance; text-shadow: 0 2px 26px rgba(0,0,0,0.45);
}
/* Audit Punkt 0: kein Verlaufs-Headline mehr; aufrecht, warm in --ember (ueberschreibt
   den geerbten .accent-Gradient aus .lp-hero h1 .accent). */
.lp-hero.hero-photo h1 .accent {
  display: block; font-weight: 540;
  background: none; -webkit-background-clip: border-box; background-clip: border-box;
  color: var(--ember);
}
/* Klarzeile direkt unter der Headline: sagt in einer Zeile, was entsteht (Kategorie). Body-Register
   (Work Sans, --step-1), nicht das Display-Serif-Motto, damit sie kompakt bleibt und die Demo
   ueber der Falz haelt. Traegt bewusst keine Namens-Signatur (das Lampen-Zeichen bleibt im Logo). */
.lp-hero.hero-photo .hero-lead {
  margin: 1.25rem 0 0; max-width: 40ch; color: var(--text);
  font-size: var(--step-1); line-height: 1.5; text-wrap: pretty;
  text-shadow: 0 1px 16px rgba(0,0,0,0.5);
}
/* Beruhigung direkt unter dem primaeren CTA (dort sitzt das Zoegern): Mut + kein-Risiko. */
.lp-hero.hero-photo .fear {
  margin: 1.5rem 0 0; max-width: 34ch; color: var(--muted);
  font-size: var(--step-1); line-height: 1.5; text-wrap: pretty; text-shadow: 0 1px 16px rgba(0,0,0,0.5);
}
/* the short conversation: proves the companion; the "you" idea line rotates through the wishes */
.lp-hero.hero-photo .talk { margin: 1.7rem 0 0; display: flex; flex-direction: column; gap: 0.8rem; max-width: 31rem; }
.lp-hero.hero-photo .turn { display: grid; grid-template-columns: auto 1fr; gap: 0.7rem; align-items: start; }
.lp-hero.hero-photo .turn .who { margin-top: 0.5rem; width: 0.5rem; height: 0.5rem; border-radius: 50%; flex: none; }
.lp-hero.hero-photo .turn.you .who { background: transparent; border: 1.5px solid var(--faint); }
.lp-hero.hero-photo .turn.lina .who { background: var(--ember); box-shadow: 0 0 0.5rem color-mix(in srgb, var(--ember) 70%, transparent); }
.lp-hero.hero-photo .turn .line { font-size: var(--step-0); line-height: 1.5; text-wrap: pretty; text-shadow: 0 1px 14px rgba(0,0,0,0.55); }
.lp-hero.hero-photo .turn.you .line { color: var(--muted); min-height: 3em; }
.lp-hero.hero-photo .turn.lina .line { color: var(--text); }
.lp-hero.hero-photo .idea { transition: opacity 0.5s var(--ease); }
.lp-hero.hero-photo .idea.swap { opacity: 0; }
.lp-hero.hero-photo .cta-row { margin-top: 2rem; }
.vh { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0; }
@media (max-width: 51em) {
  .lp-hero.hero-photo h1, .lp-hero.hero-photo .fear, .lp-hero.hero-photo .turn .line { text-shadow: none; }
  .lp-hero.hero-photo .fear { margin-top: 1.35rem; }
  .lp-hero.hero-photo .talk { max-width: none; margin-top: 1.25rem; }
  .lp-hero.hero-photo .turn.you .line { min-height: 0; }
  .lp-hero.hero-photo .cta-row { margin-top: 1.5rem; }
}

/* centered page intro used by samples/vibe hero headers (was repeated inline styles) */
.page-intro { max-width: 46rem; margin-inline: auto; text-align: center; }
.page-intro .lead { margin-inline: auto; }
.page-intro .cta-row { justify-content: center; }
.section.flush-top { padding-top: 0; }

/* Typo-System (Punkt 0, warm-klassisch, D-257): the marketing/advertising display headings take
   the Fraunces antiqua, the functional app chrome (cockpit/auth/account/help) keeps the clean
   grotesk. Scoped to the FOUR public pages: landing (body.lp), Meet Lina + Samples (body.mkt) and
   "So laeuft's" (body.longread) -- all Werbeseiten per D-257. weight ~500 and near-zero tracking
   read warm and classic (serifs reject the tight -0.03/-0.04em grotesk tracking). Higher
   specificity than the per-section h2 rules, so it wins on family + tracking without touching each. */
body.lp h1, body.lp h2,
body.mkt h1, body.mkt h2,
body.longread h1, body.longread h2,
/* Font-continuity (design-guardian S2): the large editorial h3 that sit in the headline tier
   (step-1/step-2) take the Fraunces display too, so a big .hl-key/.sample-lead/.flow-step title
   never reads as grotesk next to a serif h2 on the same page (D-257). The small label-tier h3
   (.handled-list h3 at step-0) stay in the grotesk on purpose, as a lower register. */
body.lp .hl-key, body.lp .flow-step h3,
body.mkt .sample-lead h3 {
  font-family: var(--font-display);
  font-weight: 500;
  letter-spacing: -0.008em;
  font-optical-sizing: auto;
}

/* section heading block */
.section-head { text-align: center; max-width: 40ch; margin: 0 auto clamp(2.5rem, 1rem + 4vw, 3.5rem); }
.section-head h2 { font-size: var(--step-3); margin-top: 0.8rem; }
.section-head p { color: var(--muted); margin-top: 0.9rem; font-size: var(--step-1); }

/* flow diagram (the requested arrow process) */
/* Editorial numbered process, not the old icon-in-glow-disc cards (KI-tell B1). Each step is a
   left-aligned column under a short ember top-rule with an uppercase numbered label, title, line.
   No filled card, no glow disc: reads as a classic three-chapter "how it works". Deliberately
   different from the .handled block below. Chevron arrows dropped (KI-tell A1/A3): the numbered
   01/02/03 chapters under ember top-rules already read as a sequence, no UI glyph needed. */
.flow { display: grid; grid-template-columns: repeat(3, 1fr); align-items: start; gap: clamp(1.2rem, 0.6rem + 2.5vw, 3rem); }
.flow-step { display: flex; flex-direction: column; gap: 0.5rem; padding: 1.3rem 0 0; text-align: left; border-top: 2px solid color-mix(in srgb, var(--ember) 60%, transparent); }
.flow-step .fno { font-size: var(--step--2); letter-spacing: 0.14em; text-transform: uppercase; color: var(--ember); font-weight: 600; }
.flow-step h3 { font-size: var(--step-1); letter-spacing: -0.015em; font-weight: 640; margin-top: 0.1rem; }
.flow-step p { color: var(--muted); font-size: var(--step--1); margin: 0; }

/* full-bleed atmosphere band */
/* min-height (not a hard height) so a larger heading / zoom / longer locale grows the band instead
   of being clipped; the image is absolute and clips, the caption flows and sets the height. */
.band-photo { position: relative; min-height: clamp(17rem, 32vw, 27rem); overflow: hidden; border-block: 1px solid var(--border); display: flex; align-items: flex-end; }
.band-photo img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 50% 58%; }
.band-photo .band-cap { position: relative; width: 100%; padding: clamp(2rem,4vw,3rem) var(--gutter); background: linear-gradient(180deg, transparent 0%, color-mix(in srgb, var(--bg) 55%, transparent) 40%, color-mix(in srgb, var(--bg) 94%, transparent) 86%, color-mix(in srgb, var(--bg) 96%, transparent) 100%); }
.band-photo .band-cap h2 { font-size: var(--step-2); max-width: 24ch; margin-top: 0.4rem; }
.band-photo .band-cap p { color: var(--text); opacity: 0.86; max-width: 42ch; margin-top: 0.6rem; }

/* split image + text */
.split { display: grid; grid-template-columns: 1fr 1fr; min-height: 22rem; }
.split.flip .sp-img { order: 2; }
.split .sp-img { position: relative; overflow: hidden; min-height: 16rem; }
.split .sp-img img { width: 100%; height: 100%; object-fit: cover; position: absolute; inset: 0; object-position: 50% 45%; }
/* keep each scene's subject in frame instead of a blind centre crop: sparks sit right-of-centre. */
.split.flip .sp-img img { object-position: 64% 50%; }
/* <picture> wrapper (responsive scenes) must fill its container; the <img> rules above target the
   inner <img>, so the wrapper itself needs to become the box. */
.cta-cine .bg picture { display: block; width: 100%; height: 100%; }
/* band-photo is a flex container (caption pinned bottom, growing the band); the image wrapper must
   be absolute so it is not a competing flex item. */
.band-photo picture { position: absolute; inset: 0; display: block; }
.split .sp-img picture { display: block; position: absolute; inset: 0; }
.split .sp-txt { display: flex; flex-direction: column; justify-content: center; padding: clamp(2rem,4vw,3.5rem); background: var(--surface); }
.split .sp-txt h2, .split .sp-txt .prose { max-width: 42ch; }
/* desktop two-column splits: align the text's OUTER edge to the same 67.5rem content column the
   centered sections use, so the left edge stops jumping between section and split. */
@media (min-width: 60.0625em) {
  .split .sp-txt { padding-inline: clamp(2rem,4vw,3.5rem) max(clamp(2rem,4vw,3.5rem), calc((100vw - 67.5rem) / 2 + var(--gutter))); }
  .split.flip .sp-txt { padding-inline: max(clamp(2rem,4vw,3.5rem), calc((100vw - 67.5rem) / 2 + var(--gutter))) clamp(2rem,4vw,3.5rem); }
}
.split .sp-txt h2 { font-size: var(--step-2); margin-top: 0.4rem; }
.split .sp-txt .prose { color: var(--muted); margin-top: 0.8rem; }
.split .sp-txt .prose p { margin: 0.7rem 0 0; }
.split .sp-txt .prose p:first-child { margin-top: 0; }

/* meet page: the two prose beats that break the image/text split rhythm must hold the same editorial
   weight as the split scenes and the "So laeuft's" ladder, never a centred slab of body text floating
   in the void (design-guardian, ANTI-KI 6.3 "alles zentriert/einspaltig"). */
/* helpers beat: the page's longest passage, set as an ember-ruled lead beside a measured prose
   column (echoes the .handled-lead / .flow top-rule vocabulary). */
.meet-circle { padding-block: clamp(2.75rem, 1.6rem + 4vw, 4.75rem); }
.circle-grid { display: grid; grid-template-columns: 0.82fr 1.18fr; gap: clamp(1.6rem, 0.8rem + 3.5vw, 4.25rem); align-items: start; }
.circle-lead { border-top: 2px solid var(--ember); padding-top: clamp(1rem, 0.7rem + 1vw, 1.5rem); font-size: var(--step-2); letter-spacing: -0.01em; line-height: 1.1; text-wrap: balance; max-width: 15ch; }
.circle-grid .prose { color: var(--muted); max-width: 54ch; }
.circle-grid .prose p { margin: 1.1rem 0 0; }
.circle-grid .prose p:first-child { margin-top: 0; }
@media (max-width: 60em) {
  .circle-grid { grid-template-columns: 1fr; gap: clamp(0.9rem, 0.5rem + 2vw, 1.5rem); }
  .circle-lead { max-width: 26ch; }
  .circle-grid .prose { max-width: 60ch; }
}

/* closing coda: a short, deliberately centred breath marked by a small ember rule so it reads as a
   composed pause; tighter bottom padding lets it lean into the cta-cine scene below. */
.meet-coda { padding-block: clamp(2.75rem, 1.6rem + 4vw, 4.75rem) clamp(1.25rem, 0.7rem + 1.5vw, 2.25rem); text-align: center; }
.coda-inner { max-width: 44ch; margin: 0 auto; }
.coda-inner::before { content: ""; display: block; width: 2.75rem; height: 2px; background: var(--ember); border-radius: 2px; margin: 0 auto clamp(1.1rem, 0.7rem + 1vw, 1.5rem); }
.coda-inner h2 { font-size: var(--step-2); letter-spacing: -0.01em; text-wrap: balance; }
.coda-inner .prose { color: var(--muted); margin-top: 0.9rem; text-wrap: pretty; }
.coda-inner .prose p { margin: 0; }

/* product proof (browser mockup) */
.proof { display: grid; grid-template-columns: 1.15fr 0.85fr; gap: clamp(1.5rem, 1rem + 3vw, 3rem); align-items: center; }
.proof-copy h2 { font-size: var(--step-2); margin-bottom: 0.9rem; }
.proof-copy p { color: var(--muted); margin: 0 0 1.4rem; }
.browser { border: 1px solid var(--border); border-radius: 0.8rem; overflow: hidden; background: var(--surface); box-shadow: 0 2rem 4rem -1.5rem rgba(0,0,0,0.8); }
/* Traffic-light dots dropped (KI-tell A2): the URL pill alone reads calmer and un-generic. */
.browser-bar { display: flex; align-items: center; padding: 0.6rem 0.8rem; background: var(--surface2); border-bottom: 1px solid var(--border); }
.browser-bar .url { font-size: 0.72rem; color: var(--faint); background: var(--bg); border-radius: 0.4rem; padding: 0.2rem 0.7rem; }

/* what's-handled: guided asymmetry, no icon grid (design-guardian B, KI-tell A1/B) */
/* One editorial lead field (the all-from-one-hand promise) beside a compact ember-keyline
   list of the four items. The 2px ember top-rule on the lead + hairline rows echo the .flow
   vocabulary; no stock icons, no 2x2 feature-grid read. */
.handled { display: grid; grid-template-columns: 0.9fr 1.1fr; gap: clamp(1.8rem, 1rem + 3.5vw, 4.5rem);
           align-items: start; margin-top: clamp(1.8rem, 1rem + 3vw, 3rem); }
.handled-lead { border-top: 2px solid var(--ember); padding-top: clamp(1rem, 0.6rem + 1vw, 1.4rem); }
.handled-lead .hl-key { margin: 0; font-size: var(--step-2); letter-spacing: -0.02em; font-weight: 660; line-height: 1.08; }
.handled-lead p { color: var(--muted); font-size: var(--step-0); margin: 0.7rem 0 0; max-width: 24ch; text-wrap: pretty; }
.handled-list { list-style: none; margin: 0; padding: 0; }
.handled-list li { padding: clamp(0.9rem, 0.6rem + 0.8vw, 1.25rem) 0; border-top: 1px solid var(--border); }
.handled-list li:first-child { border-top-color: color-mix(in srgb, var(--ember) 45%, transparent); }
.handled-list h3 { font-size: var(--step-0); letter-spacing: -0.01em; font-weight: 640; }
.handled-list p { color: var(--muted); font-size: var(--step--1); margin: 0.2rem 0 0; text-wrap: pretty; }

/* reassurance / trust layer: the calm, plain-spoken "you can't break anything, and there's a
   real person to reach" section, right before the closing CTA. */
/* calm "you're in the right place" air-point: one quiet, centred breath after the demo */
.air-point .air-inner { max-width: 42ch; margin: 0 auto; text-align: center; }
.air-point .air-inner h2 { font-size: var(--step-2); letter-spacing: -0.01em; text-wrap: balance; }
.air-point .air-inner .prose { color: var(--muted); margin-top: 0.9rem; text-wrap: pretty; }

/* landing FAQ: the three plain answers, each a bold question + reply, plus a door to reach */
.faq { max-width: 56ch; margin: clamp(1.4rem, 1rem + 1.5vw, 2.2rem) auto 0; }
.faq p { margin: 0 0 1.1rem; color: var(--muted); text-wrap: pretty; }
.faq p:last-child { margin-bottom: 0; }
.faq p strong { color: var(--text); font-weight: 640; }
.reach { max-width: 56ch; margin: clamp(1.8rem, 1rem + 2vw, 2.6rem) auto 0; padding-top: clamp(1.6rem, 1rem + 2vw, 2.2rem); border-top: 1px solid var(--border); display: flex; flex-direction: column; align-items: center; gap: 0.5rem; text-align: center; }
.reach span { color: var(--muted); font-size: var(--step--1); }
.reach a { font-size: var(--step-1); color: var(--ember); font-weight: 600; text-decoration: none; letter-spacing: -0.01em; }
.reach a:hover { text-decoration: underline; }

/* "So laeuft's" step ladder: numbered stations joined by one continuous warm spine, so the page
   reads as a sequence from first sentence to live (design-guardian). */
.steps { list-style: none; margin: 0 auto; padding: 0; max-width: 44rem; }
.step { position: relative; display: grid; grid-template-columns: auto 1fr; gap: clamp(1rem, 0.6rem + 1.5vw, 1.8rem); padding-bottom: clamp(2rem, 1.2rem + 2.5vw, 3.2rem); }
.step:last-child { padding-bottom: 0; }
.step-no { --sz: clamp(2.2rem, 1.8rem + 1vw, 2.8rem); position: relative; z-index: 1; width: var(--sz); height: var(--sz); border-radius: var(--r-pill); display: grid; place-items: center; background: var(--ember); color: var(--on-accent); font-family: var(--font-display); font-weight: 600; font-size: var(--step-0); box-shadow: var(--shadow-card); }
/* the spine runs down the centre of the number column, behind the badges */
.step::before { content: ""; position: absolute; left: calc(clamp(2.2rem, 1.8rem + 1vw, 2.8rem) / 2); top: 0; bottom: 0; width: 2px; transform: translateX(-1px); background: color-mix(in srgb, var(--ember) 42%, transparent); }
.step:first-child::before { top: clamp(1.1rem, 0.9rem + 0.5vw, 1.4rem); }
.step:last-child::before { bottom: auto; height: clamp(1.1rem, 0.9rem + 0.5vw, 1.4rem); }
.step-body h2 { font-size: var(--step-1); letter-spacing: -0.015em; margin-top: 0.15rem; text-wrap: balance; }
.step-body .prose { color: var(--muted); margin-top: 0.5rem; text-wrap: pretty; }
.step-body .prose p { margin: 0.6rem 0 0; }
.step-body .prose p:first-child { margin-top: 0; }

/* skip link: hidden off-canvas until keyboard focus, then it drops into view (A11y) */
.skip-link { position: fixed; left: 0.75rem; top: 0.75rem; z-index: 200; transform: translateY(-160%); background: var(--surface); color: var(--text); border: 1px solid var(--ember); border-radius: var(--r-sm); padding: 0.55rem 0.95rem; font-size: var(--step--1); font-weight: 600; text-decoration: none; transition: transform var(--t-fast, 0.15s) var(--ease); }
.skip-link:focus { transform: translateY(0); outline: 2px solid var(--ember); outline-offset: 2px; }
main:focus { outline: none; }

/* atmospheric closing with scene backdrop, generous top room so it never crowds the band above */
/* no border-top here: the band-photo above already carries a bottom hairline (border-block), two
   stacked 1px lines read as a thick double rule. */
.cta-cine { position: relative; text-align: center; padding: clamp(6rem, 4rem + 9vw, 11rem) 0 clamp(5rem, 3rem + 7vw, 8rem); overflow: hidden; }
.cta-cine .bg { position: absolute; inset: 0; }
.cta-cine .bg img { width: 100%; height: 100%; object-fit: cover; }
.cta-cine .bg::after { content: ""; position: absolute; inset: 0; background: radial-gradient(closest-side at 50% 44%, color-mix(in srgb, var(--bg) 34%, transparent), color-mix(in srgb, var(--bg) 92%, transparent) 84%); }
.cta-cine > .wrap { position: relative; z-index: 2; }
.cta-cine h2 { font-size: clamp(2rem, 1.2rem + 4.2vw, 3.6rem); }
.cta-cine .prose { color: var(--text); opacity: 0.88; max-width: 46ch; margin: 1.2rem auto; font-size: var(--step-1); }
.cta-cine .prose p { margin: 0.6rem 0 0; }
.cta-cine .prose p:first-child { margin-top: 0; }
.cta-cine .btn { margin-top: 1.8rem; }

/* Body font, self-hosted (no external Google Fonts request: keeps the site GDPR-clean and avoids a
   third-party round trip). Work Sans (humanistische, warme Grotesk) loest die Hanken-/Raycast-Kuehle
   als Body-Schrift ab (Audit Punkt 0); global auf den Body gelegt. Ein Variable-File deckt alle
   genutzten Gewichte (400-800). Die volle Typo-System-Ausarbeitung (Skala, Gewichte, metric-matched
   Fallback fuer Work Sans) folgt im 3b-Typo-Schritt. */
@font-face {
  font-family: "Work Sans";
  src: url("/static/fonts/worksans-normal.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}
/* Metric-matched fallback so the swap from Arial to Hanken Grotesk does not shift layout (CLS).
   Derived from the real font metrics (upm 1000, ascender 1000, descender -303, x-height 493) via the
   standard fallback formula: size-adjust = xHeightRatio(Hanken)/xHeightRatio(Arial) = 0.493/0.5186,
   ascent/descent overrides = metric / (upm * size-adjust). */
@font-face {
  font-family: "Hanken Fallback";
  src: local("Arial"), local("Helvetica Neue"), local("Liberation Sans");
  size-adjust: 95.06%;
  ascent-override: 105.2%;
  descent-override: 31.88%;
  line-gap-override: 0%;
}

/* Lina's closing is a handwritten signature: the last line of the closing prose (her sign-off, from
   brand/landingpage.<locale>.md). Self-hosted handwriting font with a cursive fallback, so it still
   reads as handwriting even if the file is missing (no external font request). */
@font-face {
  font-family: "Caveat";
  src: url("/static/fonts/caveat.woff2") format("woff2");
  font-weight: 400 700;
  font-display: swap;
}
.cta-cine .prose p:last-child {
  font-family: "Caveat", "Segoe Script", "Bradley Hand", cursive;
  font-size: clamp(1.7rem, 1.1rem + 2.4vw, 2.5rem);
  font-weight: 600; color: var(--ember); line-height: 1.2; margin-top: 1.9rem;
}
.cta-cine .prose p:last-child em { font-style: normal; }

/* "with lina4.ai" sign-off under the closing button */
.cta-with { margin: 1.6rem 0 0.6rem; color: var(--muted); font-size: var(--step--1); letter-spacing: 0.06em; }
.cta-logo { font-size: clamp(1.5rem, 1.1rem + 1.6vw, 2.1rem); justify-content: center; }
.cta-logo .lamp { width: 1.05rem; height: 1.34rem; }

.divider { border: 0; border-top: 1px solid var(--border); margin: 0; }

/* example badge on the product mockup */
.browser { position: relative; }
.example-badge {
  position: absolute; z-index: 3; top: 0.8rem; right: 0.8rem;
  font-size: 0.62rem; letter-spacing: 0.16em; text-transform: uppercase; font-weight: 800;
  color: var(--on-accent); background: var(--ember); border-radius: 2rem; padding: 0.25rem 0.7rem;
  box-shadow: 0 0.4rem 1rem -0.3rem rgba(0,0,0,0.6);
}
/* proof demo: a real screenshot of a live project (block-drop.lina4.ai) mid-play, framed as a
   browser window, plus a warm caption naming it. Honest proof, no fabricated mock site (Marketing
   HOCH 2). The shot is the portrait handheld, so the frame is capped and centred in its column. */
.proof-demo { display: flex; flex-direction: column; align-items: center; }
.browser { max-width: 21rem; width: 100%; }
.demo-site { padding: 0; min-height: 0; background: var(--bg); font-size: 0; }
.demo-shot { display: block; width: 100%; height: auto; }
.demo-cap { margin: 0.9rem 0 0; max-width: 24rem; color: var(--muted); font-size: var(--step--1); line-height: 1.5; text-align: center; text-wrap: pretty; }

/* samples / inspiration grid */
/* flex + centered wrap so an incomplete last row (e.g. the 10th card alone) sits centered
   instead of stranded on the left; cards keep a sensible max width so full rows stay tidy. */
/* Inspiration examples (design-guardian: not a uniform 10-icon twin grid). One large lead example
   up front, then an asymmetric editorial band. No boxed icon; a thin warm ember keyline carries the
   accent, one signature, echoing the landing handled-list. */
.sample-lead { background: var(--surface); border: 1px solid var(--border); border-top: 2px solid var(--ember); border-radius: var(--r-lg); padding: clamp(1.6rem, 1.1rem + 2vw, 2.6rem); margin-bottom: clamp(1rem, 0.6rem + 1.5vw, 1.6rem); box-shadow: var(--shadow-card); }
.sample-lead .s-tag { font-size: 0.7rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ember); font-weight: 600; }
.sample-lead h3 { font-size: var(--step-2); letter-spacing: -0.02em; margin: 0.5rem 0 0.6rem; text-wrap: balance; max-width: 24ch; }
.sample-lead p { color: var(--muted); font-size: var(--step-0); margin: 0; max-width: 54ch; text-wrap: pretty; }

.sample-band { display: grid; grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr)); gap: clamp(0.9rem, 0.6rem + 1.4vw, 1.8rem) clamp(1.2rem, 0.8rem + 1.6vw, 2.4rem); }
.sample-item { border-top: 1px solid var(--border); padding-top: clamp(0.9rem, 0.7rem + 0.6vw, 1.25rem); display: flex; flex-direction: column; gap: 0.35rem; }
.sample-item .s-tag { font-size: 0.7rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ember); font-weight: 600; }
.sample-item h3 { font-size: var(--step-0); letter-spacing: -0.015em; }
.sample-item p { color: var(--muted); font-size: var(--step--1); margin: 0; text-wrap: pretty; }

/* small inset note ("no idea yet?") */
.note-card { max-width: 46ch; margin: 0 auto; text-align: center; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg); padding: clamp(1.6rem, 1rem + 2.5vw, 2.4rem); }
.note-card .lab { display: block; margin-bottom: 0.5rem; }
.note-card h2 { font-size: var(--step-2); }
.note-card p { color: var(--muted); margin: 0.8rem 0 0; }

/* stack the landing grids earlier (60em/960px) so tablet portrait (768-834px) never shows the
   cramped multi-column desktop layout; iPad Pro 1024 stays multi-column. */
@media (max-width: 60em) {
  .flow { grid-template-columns: 1fr; gap: 0; }
  .flow-step { padding-top: 1.1rem; margin-top: 1.1rem; }
  .flow-step:first-child { margin-top: 0; }
  .split { grid-template-columns: 1fr; }
  .split.flip .sp-img { order: 0; }
  .proof { grid-template-columns: 1fr; }
  .handled { grid-template-columns: 1fr; gap: clamp(1.4rem, 1rem + 2vw, 2rem); }
  /* stacked: every left-aligned block shares the page gutter so the left edge stops jumping */
  .split .sp-txt, .split.flip .sp-txt { padding-inline: var(--gutter); }
}

/* --- Help pages (/help) -------------------------------------------------------------------- */
.help-wrap { max-width: 48rem; padding-top: 2.5rem; padding-bottom: 4rem; }
.help-wrap .back { margin: 0 0 1.2rem; }
.help-wrap .back a { color: var(--muted); font-size: var(--step--1); }
.help-wrap .back a:hover { color: var(--text); }
.help-head { margin: 0 0 1.8rem; }
.help-head h1 { margin: 0.4rem 0 0.6rem; }
.help-head .lead { font-size: var(--step-0); color: var(--muted); margin-inline: 0; }
.help-wrap h2 { margin: 2rem 0 0.9rem; font-size: var(--step-1); }

/* Catalogue index */
.help-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.9rem; }
.help-card {
  display: block; padding: 1.1rem 1.25rem; border: 1px solid var(--border);
  border-radius: 0.8rem; background: var(--surface); text-decoration: none;
}
.help-card:hover { border-color: var(--ember-deep); }
.help-card-title { display: block; color: var(--text); font-weight: 700; }
.help-card-sum { display: block; margin-top: 0.3rem; color: var(--muted); font-size: var(--step--1); }

/* Reassurance note + callouts */
.help-note, .help-callout, .help-warn {
  margin: 1.4rem 0; padding: 1rem 1.2rem; border: 1px solid var(--border);
  border-radius: 0.8rem; background: var(--surface2);
}
.help-note p, .help-callout p, .help-warn p { margin: 0.5rem 0 0; color: var(--muted); }
.help-note p:first-child, .help-callout p:first-child, .help-warn p:first-child { margin-top: 0; }
.help-callout h3, .help-warn h3 { margin: 0 0 0.2rem; font-size: var(--step-0); color: var(--text); }
.help-callout { border-color: color-mix(in srgb, var(--teal) 33%, transparent); }
.help-warn { border-color: var(--ember-deep); background: color-mix(in srgb, var(--ember-deep) 10%, transparent); }
.copy-example {
  display: block; margin: 0.7rem 0; padding: 0.7rem 0.85rem; border-radius: 0.5rem;
  background: var(--bg); border: 1px solid var(--border); color: var(--text);
  word-break: break-all; font-size: 0.85em;
}

/* SSH key registration (Connect-Spec 3.3): paste-and-register form + read-only list of own keys */
.ssh-form { display: flex; flex-direction: column; gap: 0.7rem; margin: 0.9rem 0 0; }
.ssh-form label { color: var(--text); font-size: var(--step--1); }
.ssh-input {
  width: 100%; box-sizing: border-box; padding: 0.7rem 0.85rem; border-radius: 0.6rem;
  background: var(--bg); border: 1px solid var(--border2); color: var(--text);
  font-family: var(--mono, monospace); font-size: 0.85em; resize: vertical; min-height: 3.4rem;
}
.ssh-input:focus { outline: none; border-color: var(--ember); }
.ssh-form .btn { align-self: flex-start; }
.ssh-keys { margin: 1.2rem 0 0; }
.ssh-keys h4 { margin: 0 0 0.5rem; font-size: var(--step--1); color: var(--text); }
.ssh-key-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.4rem; }
.ssh-key-row {
  padding: 0.55rem 0.75rem; border-radius: 0.5rem; background: var(--bg);
  border: 1px solid var(--border); color: var(--text); word-break: break-all; font-size: 0.8em;
}

/* OS picker: tabs with a no-JS fallback (all panels visible until JS turns them into tabs) */
.os-tabbar { display: flex; gap: 0.5rem; margin: 0 0 1rem; flex-wrap: wrap; }
.os-tab {
  padding: 0.5rem 1.1rem; border: 1px solid var(--border2); border-radius: 999px;
  background: transparent; color: var(--muted); font: inherit; font-size: var(--step--1);
  cursor: pointer;
}
.os-tab:hover { color: var(--text); }
.os-tab.on { background: var(--ember); border-color: var(--ember-deep); color: var(--on-accent); font-weight: 700; }
.os-tabs:not(.js) .os-tabbar { display: none; }      /* no JS: tabs are useless, hide them */
.os-panel { margin: 0 0 1.6rem; }
.os-tabs.js .os-panel { margin: 0; }
.os-panel-h { margin: 0 0 0.8rem; font-size: var(--step-1); }
.os-tabs.js .os-panel-h { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }  /* tab label already says the OS */

/* Numbered beginner steps */
.help-steps { margin: 0; padding-left: 1.4rem; display: grid; gap: 1rem; }
.help-steps li { color: var(--muted); line-height: 1.6; }
.help-steps li strong { color: var(--text); }
code.cmd {
  display: block; margin: 0.5rem 0; padding: 0.6rem 0.8rem; border-radius: 0.5rem;
  background: var(--bg); border: 1px solid var(--border); color: var(--text);
  font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 0.88em;
  white-space: pre-wrap; word-break: break-word;
}
.kbd {
  display: inline-block; padding: 0.05rem 0.4rem; border: 1px solid var(--border2);
  border-bottom-width: 2px; border-radius: 0.35rem; background: var(--surface);
  color: var(--text); font-size: 0.85em; white-space: nowrap;
}
.help-foot { margin: 2rem 0 0; color: var(--muted); }
.help-backup { margin: 0.8rem 0 0; color: var(--faint); font-size: var(--step--1); }
.help-backup a { color: var(--muted); }

/* Generated article body (markdown -> HTML via help_render). Reuses help-wrap heading sizes; here
   only the prose-level rules: comfortable paragraph rhythm, readable inline code and links. */
.help-prose { text-wrap: pretty; }
.help-prose > :first-child { margin-top: 0; }
.help-prose h2 { margin: 2rem 0 0.9rem; font-size: var(--step-1); color: var(--text); }
.help-prose h3 { margin: 1.5rem 0 0.6rem; font-size: var(--step-0); color: var(--text); }
.help-prose p { color: var(--muted); line-height: 1.7; margin: 0 0 1.1rem; }
.help-prose ul, .help-prose ol { margin: 0 0 1.2rem; padding-left: 1.4rem; display: grid; gap: 0.6rem; }
.help-prose li { color: var(--muted); line-height: 1.6; }
.help-prose strong { color: var(--text); }
.help-prose a { color: var(--ember); text-decoration: underline; text-underline-offset: 2px; }
.help-prose a:hover { color: var(--ember-deep); }
.help-prose code {
  padding: 0.05rem 0.35rem; border-radius: 0.35rem; background: var(--bg);
  border: 1px solid var(--border); color: var(--text);
  font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 0.88em;
  word-break: break-word;
}
.help-prose pre.cmd code { padding: 0; border: 0; background: none; color: inherit; }

/* =======================================================================================
   Polish 2026-06-21 (Max feedback)
   ======================================================================================= */

/* 1) Heading-to-first-line breathing room. The hero (.lead) and closing (.cta-cine .prose)
   already carry a generous top margin, so they read fine; the storytelling beats and the
   landing section heads sit their prose flush under the h2 (the prose's first <p> zeroes its
   own top margin), which looked cramped on /how-it-works. Match the calm split-text spacing. */
.section-head .prose { margin-top: 0.9rem; }

/* 2) Inline text links must read as links. The global reset `a { color: inherit;
   text-decoration: none }` is right for nav, buttons, cards and pills, but in running copy
   (form hints, onboarding/auth body, legal prose, story prose) a bare colour-inherited link is
   invisible until hovered. Give body-copy links the ember + underline treatment already used in
   .help-prose, excluding the deliberately button-/box-styled link classes. */
.auth-card a:not(.btn):not(.linkish):not(.ws-link),
.auth-foot a,
.doc p a, .doc li a,
.prose a:not(.btn) {
  color: var(--ember);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.auth-card a:not(.btn):not(.linkish):not(.ws-link):hover,
.auth-foot a:hover,
.doc p a:hover, .doc li a:hover,
.prose a:not(.btn):hover { color: var(--ember-deep); }

/* Abo-Wallet action row (D-180): the small per-subscription buttons (use / check / disconnect)
   laid out as one wrapping row under the entry, calm gap, not a vertical stack. Reusable class,
   not a one-off inline style (design-ui rule). */
.wallet-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 0.5rem;
}

/* =======================================================================================
   Agency polish 2026-06-30 (Max: "wie von der teuren Agentur"): cards that look alike now
   behave alike on hover, unified easing on colour hovers, resting elevation, finer detail.
   ======================================================================================= */

/* These cards are NOT clickable -> only a quiet border-color hint on hover, no lift/shadow
   (a lift would fake interactivity). The clickable .btn keeps its lift.
   .handled rows/.flow-step are borderless keyline/editorial blocks, not cards -> no hover chrome. */
.help-card {
  transition: border-color var(--t-med) var(--ease);
}
.help-card:hover {
  border-color: var(--ember-deep);
}

/* Soft, unified colour transitions instead of hard snaps on text/chip hovers. */
.navlinks a, .chip, .admin-table tbody tr {
  transition: color var(--t-fast) var(--ease), background-color var(--t-fast) var(--ease),
              border-color var(--t-fast) var(--ease);
}

/* Resting elevation on the big content cards: hairline + soft low shadow, not a hard drop. */
.band, .note-card { box-shadow: var(--shadow-card); }
/* Same quiet resting depth on the smaller feature cards (was border-only -> flat).
   .handled rows/.flow-step excluded: they are keyline/editorial blocks, a shadow would re-card them. */
.help-card { box-shadow: var(--shadow-card); }

/* KLEIN: inline links a touch finer; small multi-line headings get a hair more breathing room. */
.doc p a, .doc li a, .prose a:not(.btn), .help-prose a, .auth-foot a {
  text-decoration-thickness: 1px;
  text-decoration-color: color-mix(in srgb, var(--ember) 50%, transparent);
}
.handled-list h3, .flow-step h3, .step h3, .sample-lead h3 {
  letter-spacing: -0.015em;
  line-height: 1.15;
}

@media (prefers-reduced-motion: reduce) {
  .flow-step:hover, .help-card:hover { transform: none; }
}

/* =======================================================================================
   Help chat panel (partials/help_chat.html)
   A floating "Ask me" button opens a panel that sits OVER the help pages, so the guide list and its
   navigation never move and the page itself never grows. The thread scrolls inside the panel; on a
   phone the panel becomes a full-height sheet. Toggled by the hidden #chat-open checkbox so it also
   opens without JavaScript; with JS the chat posts via HTMX and the thread persists across pages.
   ======================================================================================= */
.chat-toggle { position: fixed; opacity: 0; width: 0; height: 0; pointer-events: none; }

.chat-fab {
  position: fixed; z-index: 60;
  right: clamp(1rem, 0.5rem + 2vw, 2rem); bottom: clamp(1rem, 0.5rem + 2vw, 2rem);
  display: inline-flex; align-items: center; gap: 0.5rem;
  padding: 0.7rem 1.1rem; border: 0; border-radius: 2rem;
  background: var(--grad); color: var(--on-accent); font-weight: 700; font-size: var(--step-0);
  box-shadow: 0 0.6rem 1.6rem -0.4rem rgba(0,0,0,0.55); cursor: pointer;
  transition: transform var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease);
}
.chat-fab:hover { transform: translateY(-1px); box-shadow: 0 0.8rem 1.8rem -0.4rem rgba(0,0,0,0.6); }
.chat-fab svg { width: 1.25rem; height: 1.25rem; }
.chat-fab-label { white-space: nowrap; }

.chat-scrim {
  position: fixed; inset: 0; z-index: 65; background: var(--scrim);
  opacity: 0; pointer-events: none; transition: opacity var(--t-med) var(--ease);
}

.chat-panel {
  position: fixed; z-index: 70;
  right: clamp(1rem, 0.5rem + 2vw, 2rem); bottom: clamp(1rem, 0.5rem + 2vw, 2rem);
  width: min(24rem, calc(100vw - 2rem)); height: min(34rem, calc(100vh - 4rem));
  display: flex; flex-direction: column; overflow: hidden;
  padding: 0;  /* reset the global `section` padding so the header sits flush at the top */
  background: var(--surface); border: 1px solid var(--border); border-radius: 1rem;
  box-shadow: 0 1.4rem 3rem -0.8rem rgba(0,0,0,0.7);
  opacity: 0; transform: translateY(0.8rem) scale(0.98); pointer-events: none;
  transition: opacity var(--t-med) var(--ease), transform var(--t-med) var(--ease);
}

.chat-toggle:checked ~ .chat-fab { opacity: 0; pointer-events: none; }
.chat-toggle:checked ~ .chat-scrim { opacity: 1; pointer-events: auto; }
.chat-toggle:checked ~ .chat-panel { opacity: 1; transform: none; pointer-events: auto; }

.chat-panel-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 0.85rem 1rem; border-bottom: 1px solid var(--border); background: var(--surface2);
}
.chat-panel-title { display: inline-flex; align-items: center; gap: 0.5rem; font-weight: 700; }
.chat-panel-title .d { width: 0.5rem; height: 0.5rem; border-radius: 50%; background: var(--grad); }
.chat-panel-close {
  display: inline-flex; align-items: center; justify-content: center;
  width: 2rem; height: 2rem; border-radius: 0.5rem; color: var(--muted); cursor: pointer;
}
.chat-panel-close:hover { color: var(--text); background: var(--bg); }
.chat-panel-close svg { width: 1.1rem; height: 1.1rem; }

.chat-scroll { flex: 1; overflow-y: auto; padding: 1rem; }
.chat-intro { color: var(--muted); font-size: var(--step--1); margin: 0 0 1rem; text-wrap: pretty; }

.chat-thread { display: flex; flex-direction: column; gap: 0.8rem; }
.chat-msg { max-width: 88%; padding: 0.7rem 0.9rem; border-radius: 0.9rem; line-height: 1.5; text-wrap: pretty; }
.chat-msg p { margin: 0 0 0.5rem; }
.chat-msg p:last-child { margin: 0; }
.chat-msg.user { align-self: flex-end; background: var(--grad); color: var(--on-accent); border-bottom-right-radius: 0.25rem; }
.chat-msg.assistant { align-self: flex-start; background: var(--bg); border: 1px solid var(--border); border-bottom-left-radius: 0.25rem; }
.chat-msg.notice { align-self: stretch; max-width: none; border-style: dashed; color: var(--muted); }
.chat-sources { margin: 0.6rem 0 0; padding: 0; list-style: none; font-size: var(--step--1); }
.chat-sources li { margin: 0.2rem 0; }
.chat-sources a { color: var(--ember); }

.chat-form { display: flex; gap: 0.5rem; padding: 0.75rem; border-top: 1px solid var(--border); background: var(--surface2); }
.chat-input {
  flex: 1; min-width: 0; padding: 0.7rem 0.85rem; border-radius: 0.7rem;
  border: 1px solid var(--border); background: var(--bg); color: var(--text); font: inherit;
}
.chat-input:focus { outline: none; border-color: var(--ember-deep); box-shadow: 0 0 0 2px color-mix(in srgb, var(--ember-deep) 18%, transparent); }
.chat-send {
  flex: none; width: 2.7rem; border: 0; border-radius: 0.7rem; background: var(--grad);
  color: var(--on-accent); cursor: pointer; display: inline-flex; align-items: center; justify-content: center;
}
.chat-send svg { width: 1.15rem; height: 1.15rem; }
.chat-inactive { padding: 1rem; border-top: 1px solid var(--border); color: var(--muted); font-size: var(--step--1); line-height: 1.6; }
.chat-inactive a { color: var(--ember); }

/* Phone: the panel becomes a bottom sheet that fills most of the screen. */
@media (max-width: 32rem) {
  .chat-panel {
    right: 0; left: 0; bottom: 0; width: 100%;
    height: 88vh; height: 88dvh;
    border-radius: 1rem 1rem 0 0; border-bottom: 0;
    transform: translateY(100%);
  }
  .chat-toggle:checked ~ .chat-panel { transform: none; }
  .chat-fab { right: 1rem; bottom: 1rem; }
}

/* =======================================================================================
   Landing signature moment "Atelier im Glutlicht" (body.lp only).
   One light source tells the page: Lina turns the workshop on. The hero glow ignites once on
   load (CSS-only), the brand lamp and kicker dot answer, then a differentiated scroll-reveal
   carries the page. Motion is transform/opacity only (no CLS, LCP untouched) and fully
   reduced-motion safe. Everything is scoped to body.lp so the rest of the platform is unchanged.
   ======================================================================================= */

/* --- Signature primary: hero ignite. The workshop turns on: the hero image ramps from dim to
   full once on load (the visible "light comes on" beat, a soft additive glow alone is invisible
   over the already-bright glass), with a warm ember bloom and a single flicker layered on top. */
.lp .lp-hero.hero-photo .hero-bg img {
  animation: lp-ignite-img 2.6s ease-in-out 0.2s both;
}
@keyframes lp-ignite-img {
  0%   { filter: brightness(0.38) saturate(0.7); }   /* dim workshop */
  78%  { filter: brightness(1.06) saturate(1.04); }  /* a gentle over-glow at the top of the rise */
  100% { filter: brightness(1) saturate(1); }        /* settle */
}
.lp .lp-hero.hero-photo .hero-bg::before {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: radial-gradient(46% 54% at 60% 42%, color-mix(in srgb, var(--ember) 50%, transparent), transparent 72%);
  mix-blend-mode: screen;
  animation: lp-ignite 2.6s ease-in-out 0.2s both;
}
@keyframes lp-ignite {
  0%   { opacity: 0; }     /* glow swells in step with the brightness rise, no dip */
  78%  { opacity: 1; }
  100% { opacity: 0.85; }
}
/* The brand lamp (nav) warms up and the hero kicker dot flares once in answer to the ignite. */
.lp .nav .logo .lamp .lamp-glow { animation: lp-lampglow 2.6s ease-in-out 0.2s both; }
.lp .lp-hero.hero-photo .kicker .d { animation: lp-lampflare 2.6s ease-in-out 0.2s both; }
@keyframes lp-lampflare {
  0%   { box-shadow: 0 0 0 var(--ember); }
  60%  { box-shadow: 0 0 1.4rem var(--ember), 0 0 0.3rem #fff8; }
  100% { box-shadow: 0 0 0.9rem var(--ember), 0 0 0.2rem #fff6; }
}
/* The lamp's light comes up (the ember glow ellipse brightens), as if switched on. */
@keyframes lp-lampglow {
  0%   { opacity: 0; }
  55%  { opacity: 0.6; }
  100% { opacity: 0.3; }
}
/* Mobile: the hero is a bounded portrait band; recentre the ignite over the glass there. */
@media (max-width: 51em) {
  .lp .lp-hero.hero-photo .hero-bg::before {
    background: radial-gradient(54% 44% at 50% 40%, color-mix(in srgb, var(--ember) 50%, transparent), transparent 72%);
  }
}

/* --- Scroll-reveal (differentiated, gated by reveal-ready so no-JS stays fully visible). */
html.reveal-ready [data-reveal] {
  opacity: 0; transform: translateY(14px);
  transition: opacity 0.6s var(--ease), transform 0.6s var(--ease);
}
html.reveal-ready [data-reveal].is-in { opacity: 1; transform: none; }
/* Photo bands settle cinematically instead of rising: the image eases out of a slight zoom
   inside its overflow:hidden frame (target the image, never the full-bleed wrapper). Shared by
   every image split (landing + meet use the same .split/.sp-img markup) so the motion vocabulary
   is one hand across the site, not a landing-only flourish. */
html.reveal-ready .split[data-reveal] .sp-img img {
  transform: scale(1.06); transition: transform 0.9s var(--ease);
}
html.reveal-ready .split[data-reveal].is-in .sp-img img { transform: none; }
/* The flow trio reveals left-to-right so the numbered editorial steps come up one after another. */
.lp .flow [data-reveal]:nth-child(2) { transition-delay: 90ms; }
.lp .flow [data-reveal]:nth-child(3) { transition-delay: 180ms; }
/* The how-it-works step ladder is a sequence: the first co-visible steps come up one after the
   other (below-fold steps still reveal individually on scroll via the observer). */
.steps .step[data-reveal]:nth-child(2) { transition-delay: 70ms; }
.steps .step[data-reveal]:nth-child(3) { transition-delay: 140ms; }
/* The what's-handled keyline rows come up one after another, like the flow chapters. */
.lp .handled-list li[data-reveal]:nth-child(2) { transition-delay: 80ms; }
.lp .handled-list li[data-reveal]:nth-child(3) { transition-delay: 160ms; }
.lp .handled-list li[data-reveal]:nth-child(4) { transition-delay: 240ms; }
/* Grace note: the handwritten signature line and the lamp logo arrive last, slightly offset. */
.lp .cta-cine .wrap[data-reveal].is-in .prose p:last-child,
.lp .cta-cine .wrap[data-reveal].is-in .cta-logo { animation: lp-gracenote 0.8s var(--ease) 0.18s both; }
@keyframes lp-gracenote { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

/* --- reduced-motion: the reset MUST match the gate's specificity, or hiding wins and content
   stays invisible. Everything lands in its final lit/settled state, fully visible, no motion. */
@media (prefers-reduced-motion: reduce) {
  html.reveal-ready [data-reveal],
  html.reveal-ready [data-reveal].is-in {
    opacity: 1; transform: none; transition: none;
  }
  html.reveal-ready .split[data-reveal] .sp-img img,
  html.reveal-ready .split[data-reveal].is-in .sp-img img { transform: none; transition: none; }
  .lp .lp-hero.hero-photo .hero-bg img { animation: none; filter: none; }
  .lp .lp-hero.hero-photo .hero-bg::before { animation: none; }
  .lp .nav .logo .lamp .lamp-glow,
  .lp .lp-hero.hero-photo .kicker .d { animation: none; }
  .lp .flow [data-reveal], .lp .handled-list li[data-reveal] { transition-delay: 0s; }
  .lp .cta-cine .wrap[data-reveal].is-in .prose p:last-child,
  .lp .cta-cine .wrap[data-reveal].is-in .cta-logo { animation: none; }
}

/* --- Admin-Konsole Umbau 2026-07-02: Sub-Navigation, Erklaerzeile+Hilfe, Uebersicht-Ampel --- */

/* Sub-navigation under the main admin nav (Ueberwachung / Kosten&Guthaben). */
.admin-subnav {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.4rem;
  padding: 0.7rem 0 0.2rem;
  border-top: 1px solid var(--border2);
  margin-top: 0.7rem;
}
.admin-subnav a {
  color: var(--muted);
  font-size: var(--step--1);
  padding: 0.25rem 0;
  border-bottom: 2px solid transparent;
}
.admin-subnav a:hover { color: var(--text); }
.admin-subnav a.active { color: var(--text); border-bottom-color: var(--ember); }

/* Server-Ansicht-Umschalter (Cockpit "Server"): one server at a time (Produktivserver /
   Entwicklungs-Server / Sonstiges). Pills, not underline tabs, so it reads as a choice of view rather
   than a page jump. Fluid + wrapping so it stays clean on phones and at 150% zoom (D-058). */
.server-switch {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin: 1rem 0 0.2rem;
}
.server-switch-tab {
  color: var(--muted);
  font-size: var(--step--1);
  line-height: 1.2;
  padding: 0.42rem 0.95rem;
  border: 1px solid var(--border2);
  border-radius: 999px;
  white-space: nowrap;
  transition: color 0.15s ease, border-color 0.15s ease, background-color 0.15s ease;
}
.server-switch-tab:hover { color: var(--text); border-color: var(--muted); }
.server-switch-tab.active {
  color: var(--bg);
  background: var(--ember);
  border-color: var(--ember);
  font-weight: 600;
}

/* Always-on explain line + "?"-help toggle on every admin page. */
.admin-explain { margin: 0.6rem 0 0; }
.admin-intro {
  color: var(--text);
  font-size: var(--step--1);
  max-width: 62ch;
  margin: 0;
  text-wrap: pretty;
}
.admin-help { margin-top: 0.5rem; }
.admin-help > summary {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  cursor: pointer;
  color: var(--muted);
  font-size: var(--step--1);
  list-style: none;
  width: max-content;
}
.admin-help > summary::-webkit-details-marker { display: none; }
.admin-help > summary:hover { color: var(--text); }
.admin-help-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.25rem;
  height: 1.25rem;
  border: 1px solid var(--border);
  border-radius: 50%;
  font-size: 0.78rem;
  color: var(--ember);
}
.admin-help-body {
  margin-top: 0.6rem;
  padding: 0.9rem 1.05rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  max-width: 68ch;
}
.admin-help-body p { margin: 0; color: var(--muted); font-size: var(--step--1); line-height: 1.55; text-wrap: pretty; }

/* Uebersicht landing page: one big traffic light + "X braucht dich" counter. */
.overview-hero { display: grid; gap: 1rem; }
.overview-lamp-wrap { display: flex; align-items: center; gap: 1.1rem; }
.overview-lamp {
  flex: none;
  width: 3.2rem;
  height: 3.2rem;
  border-radius: 50%;
  background: var(--faint);
}
.overview-lamp.is-gruen { background: var(--ok); box-shadow: 0 0 1.1rem color-mix(in srgb, var(--ok) 40%, transparent); }
.overview-lamp.is-rot   { background: var(--danger); box-shadow: 0 0 1.1rem color-mix(in srgb, var(--danger) 47%, transparent); }
.overview-lamp.is-grau  { background: var(--faint); }
.overview-headline { margin: 0; font-size: var(--step-1); letter-spacing: -0.01em; color: var(--text); }
.overview-count { margin: 0.25rem 0 0; color: var(--muted); font-size: var(--step--1); }
.overview-count strong { color: var(--text); font-size: 1.15em; }
.overview-note { margin: 0; color: var(--faint); font-size: var(--step--1); max-width: 68ch; text-wrap: pretty; }

.overview-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: 1rem;
}
.overview-card {
  display: grid;
  gap: 0.5rem;
  align-content: start;
  padding: 1.1rem 1.2rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  color: var(--text);
}
.overview-card:hover { border-color: var(--ember-deep); }
.overview-card-head { display: flex; align-items: center; justify-content: space-between; gap: 0.6rem; }
.overview-card-title { font-weight: 600; }
.overview-card-note { color: var(--muted); font-size: var(--step--1); text-wrap: pretty; }
