/* ============================================================================
   atomAI — site.css
   The shop pages: home, /products, /products/atom, /products/scribe.

   The atomAI house style: glass surfaces built from 158deg gradients, hairline edges
   carried as a gradient BACKGROUND on a 1px border (a border-colour cannot bend light
   around a corner), one accent colour, calm motion.

   Self-contained on purpose. It does NOT load base.css or landing.css, so nothing
   here can change the app or the old landing page.
   ========================================================================== */

/* ----------------------------------------------------------------- fonts ---
   Self-hosted (SIL OFL 1.1, licence in fonts/InstrumentSans-OFL.txt): no call to
   Google on page load, which is what keeps the pages GDPR-clean.
   ONE variable file per subset carries 400-700 — the upstream per-weight files are
   byte-identical (checked with md5), so shipping four of them downloaded the same
   120 KB four times. */
@font-face {
  font-family: 'Instrument Sans';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('../fonts/InstrumentSans-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Instrument Sans';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('../fonts/InstrumentSans-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* The app's three families (see css/base.css), all variable files. Declared under their
   OWN names: css/fonts.css (still loaded by the legal pages) declares "Fraunces" and
   "Inter" as single static weights, and two declarations of one family with different
   weight descriptors would make the browser pick between them per weight. */
@font-face { font-family: 'Atom Serif'; font-style: normal; font-weight: 300 700; font-display: swap;
  src: url('../fonts/Fraunces-500.woff2') format('woff2'); }
/* the real italic of the serif (2026-10-15: the start page asks its question in italics — a slanted
   upright would look cheap). Latin only, from the Fraunces project (OFL, see Fraunces-OFL.txt). */
@font-face { font-family: 'Atom Serif'; font-style: italic; font-weight: 300 700; font-display: swap;
  src: url('../fonts/Fraunces-Italic.woff2') format('woff2'); }
@font-face { font-family: 'Atom Sans'; font-style: normal; font-weight: 100 900; font-display: swap;
  src: url('../fonts/Inter-400.woff2') format('woff2'); }
@font-face { font-family: 'Atom Brand'; font-style: normal; font-weight: 300 700; font-display: swap;
  src: url('../fonts/SpaceGrotesk-500.woff2') format('woff2'); }

/* ---------------------------------------------------------------- tokens ---
   2026-10-02 · NEW DRESS (REDESIGN.md). Same token NAMES as before, new values — that is
   what lets every page keep its markup. The house style is now the app's own: its
   surface colours, its typefaces, hairlines, one accent. No glass, no wallpaper.

   ⚠️ --glass*, --edge*, --sink and --wall stay GRADIENTS (of one colour). They are used
   as background IMAGES all over this file ("background: var(--glass2)" next to a
   background-color); a plain colour in their place would be an invalid image and the
   surface would vanish. */
:root {
  color-scheme: light;

  --font:  'Atom Sans', 'Inter', 'Segoe UI', system-ui, sans-serif;
  --serif: 'Atom Serif', 'Fraunces', Georgia, 'Times New Roman', serif;
  --brand: 'Atom Brand', 'Space Grotesk', 'Atom Sans', 'Segoe UI', sans-serif;
  --mono:  ui-monospace, 'JetBrains Mono', 'Cascadia Mono', Consolas, monospace;

  /* the app's light theme */
  --ground:   #f6f7f9;
  --surface:  #ffffff;
  --surface2: #eef0f4;

  --ink:  #14161c;
  --ink1: rgba(20, 22, 28, .88);
  --ink2: rgba(20, 22, 28, .66);
  --ink3: rgba(20, 22, 28, .6);

  --glass:    linear-gradient(var(--surface), var(--surface));
  --glass2:   linear-gradient(var(--surface), var(--surface));
  --glass3:   linear-gradient(var(--surface), var(--surface));
  --glassHov: linear-gradient(var(--surface2), var(--surface2));

  --edgeC: rgba(20, 22, 28, .12);
  --edge:  linear-gradient(var(--edgeC), var(--edgeC));
  --edge2: linear-gradient(var(--edgeC), var(--edgeC));

  --line:     rgba(20, 22, 28, .1);
  --cardLine: rgba(20, 22, 28, .15);
  --sinkC:    rgba(20, 22, 28, .045);
  --sink:     linear-gradient(var(--sinkC), var(--sinkC));

  --shadow:    0 26px 50px -30px rgba(20, 30, 60, .34), 0 2px 6px rgba(20, 30, 60, .05);
  --lift:      0 1px 2px rgba(20, 30, 60, .04);
  --hoverLift: 0 10px 22px -16px rgba(20, 30, 60, .34);
  --hl:        rgba(255, 255, 255, 0);

  /* The one screw. Everything accent-coloured derives from it — see the
     :root, [data-acc] block below for why the derivations live there. */
  --acc: #4a7dff;

  --ok:     #2fb84f;
  --okInk:  #0d5d24;
  --okBg:   rgba(47, 184, 79, .16);
  --okLine: rgba(47, 184, 79, .35);
  --bad:    #e8443a;
  --badInk: #c8402f;

  --scrim: rgba(18, 26, 44, .5);

  --r-sm: 8px;
  --r:    11px;
  --r-lg: 14px;
  --r-xl: 16px;

  --ease: cubic-bezier(.22, 1, .36, 1);
}

/* the app's dark theme */
[data-theme="dark"] {
  color-scheme: dark;

  --ground:   #0c0d11;
  --surface:  #14161c;
  --surface2: #1b1e26;

  --ink:  #edeef1;
  --ink1: rgba(237, 238, 241, .9);
  --ink2: rgba(237, 238, 241, .64);
  --ink3: rgba(237, 238, 241, .5);

  --edgeC: rgba(255, 255, 255, .13);
  --line:     rgba(255, 255, 255, .085);
  --cardLine: rgba(255, 255, 255, .15);
  --sinkC:    rgba(255, 255, 255, .04);

  --shadow:    0 30px 60px -32px rgba(0, 0, 0, .9), 0 2px 8px rgba(0, 0, 0, .3);
  --lift:      0 0 0 0 transparent;
  --hoverLift: 0 12px 24px -16px rgba(0, 0, 0, .85);

  --okInk:  #8ceea3;
  --okBg:   rgba(47, 184, 79, .2);
  --badInk: #ffa39b;

  --scrim: rgba(3, 6, 12, .66);
}

/* ----------------------------------------------- accent, derived ---------
   These are declared for :root AND for any element carrying data-acc, because a
   custom property is resolved against the element it is DECLARED on. Listing
   them only on :root meant a product colour could be set per PAGE but never per
   CARD — the Scribe card on a blue page stayed blue. With this block, putting
   data-acc="scribe" on the card is enough, and the same rule colours a whole
   page when it sits on <html>. */
:root, [data-acc] {
  /* the gradient of the primary button — the one from the earlier site, kept on purpose (Adrian) */
  --accSoft: oklch(from var(--acc) calc(l + .087) calc(c * .78)  h);
  --accDeep: oklch(from var(--acc) calc(l - .095) calc(c * 1.09) h);
  --accTint: linear-gradient(rgb(from var(--acc) r g b / .11), rgb(from var(--acc) r g b / .11));
  --accFill: linear-gradient(158deg, var(--accSoft), var(--accDeep));
  --accGlow: rgb(from var(--acc) r g b / .9);
  --accLine: rgb(from var(--acc) r g b / .4);
  --accRing: rgb(from var(--acc) r g b / .16);
  --accInk:  oklch(from var(--acc) .5 c h);

  --cardBase: var(--surface);
  --wall: linear-gradient(var(--ground), var(--ground));
}

[data-theme="dark"], [data-theme="dark"] [data-acc] {
  --accTint: linear-gradient(rgb(from var(--acc) r g b / .15), rgb(from var(--acc) r g b / .15));
  --accInk:  oklch(from var(--acc) .8 c h);
}

/* THE product colours. One line each. */
[data-acc="scribe"] { --acc: #8b3ede; }
[data-acc="atom"]   { --acc: #4a7dff; }
[data-acc="video"]  { --acc: #35acd2; }   /* Video (since 2026-10-14): a calm cyan — next to blue and purple, never one of the apps (orange was "zu böse", Adrian 2026-10-15) */

/* Browsers without relative colour syntax (oklch(from …)) would drop every
   derived value and leave buttons unpainted. Plain values from the same ramp. */
@supports not (color: oklch(from #fff l c h)) {
  :root, [data-acc] {
    --accSoft: #79a0ff;
    --accDeep: #2f5fe0;
    --accTint: linear-gradient(rgba(74, 125, 255, .11), rgba(74, 125, 255, .11));
    --accGlow: rgba(74, 125, 255, .9);
    --accLine: rgba(74, 125, 255, .4);
    --accRing: rgba(74, 125, 255, .16);
    --accInk:  #2f5fe0;
  }
  [data-theme="dark"], [data-theme="dark"] [data-acc] { --accInk: #a9c4fb; }
  [data-acc="scribe"] { --accSoft: #9d5be8; --accDeep: #7a2fd0; --accInk: #7a2fd0;
    --accTint: linear-gradient(rgba(139, 62, 222, .12), rgba(139, 62, 222, .12));
    --accGlow: rgba(139, 62, 222, .5); --accLine: rgba(139, 62, 222, .4); --accRing: rgba(139, 62, 222, .16); }
  [data-theme="dark"] [data-acc="scribe"] { --accInk: #c9a8f8; }
  [data-acc="video"] { --accSoft: #5cc4e6; --accDeep: #1f8db4; --accInk: #1b7fa3;
    --accTint: linear-gradient(rgba(53, 172, 210, .12), rgba(53, 172, 210, .12));
    --accGlow: rgba(53, 172, 210, .5); --accLine: rgba(53, 172, 210, .4); --accRing: rgba(53, 172, 210, .16); }
  [data-theme="dark"] [data-acc="video"] { --accInk: #8fd6ef; }
}


/* ------------------------------------------------------------------ base --- */
*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
/* Grundfarbe fuer die Flaeche HINTER dem Verlauf (sichtbar nur beim Ueberscrollen/Nachfedern).
   Frueher lieferte sie der body-Hintergrund; seit der Verlauf auf body::before liegt, ist der
   body durchsichtig — ohne diese Zeile blitzte im Dunkelmodus Weiss auf. Mitte der Verlaufs-Rampe. */
html { background-color: var(--ground); }

body {
  margin: 0;
  min-height: 100vh;
  font: 400 16px/1.6 var(--font);
  color: var(--ink1);
  /* ⚠️ Der Verlauf liegt NICHT mehr als `background: var(--wall) fixed` auf dem body.
     `background-attachment: fixed` zwingt den Browser, bei JEDEM Scroll-Bild die ganze
     Flaeche neu zu malen — hier bis zu fuenf Verlaeufe, und darueber rechnet die klebende
     Kopfleiste ihren Weichzeichner neu. Das war das leichte Ruckeln (Adrian, /cancel,
     2026-09-24), auf JEDER oeffentlichen Seite. Jetzt traegt ihn eine eigene feststehende
     Ebene (body::before, unten), die die Grafikkarte nur verschiebt statt neu zu malen.
     Optisch identisch. Der body MUSS transparent bleiben: ein body-Hintergrund wuerde ueber
     der Ebene gemalt (Malreihenfolge: html-Hintergrund → z-index:-1 → body-Hintergrund). */
  background: transparent;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
body::before {
  content: "";
  position: fixed;
  top: 0; left: 0; right: 0;
  height: 100vh;
  height: 100lvh;              /* grosse Viewport-Hoehe: keine Luecke, wenn die Handy-Adressleiste einklappt */
  z-index: -1;
  pointer-events: none;
  background: var(--wall);
  will-change: transform;      /* eigene Grafik-Ebene → Scrollen ohne Neumalen */
  /* 2026-10-02: the ground is one flat colour now and html carries it — the layer is
     no longer needed (kept above, switched off, so nothing that relied on it moves). */
  display: none;
}
@media print { body::before { display: none; } }

h1, h2, h3 { color: var(--ink); margin: 0; font-weight: 600; letter-spacing: -.02em; line-height: 1.12; }
/* ⚠️ Optical size is PINNED. On "auto" a headline of 90px picks the opsz-144 cut, whose
   hairlines vanish on a screen: "save" reads "savc". And these two properties must come
   AFTER any `font:` shorthand on the same element — the shorthand resets both. */
h1, h2 { font-family: var(--serif); font-weight: 370; font-optical-sizing: none; font-variation-settings: "opsz" 64; }
h1 { font-size: clamp(40px, 6.6vw, 84px); letter-spacing: -.032em; line-height: 1; text-wrap: balance; }
h2 { font-size: clamp(28px, 4vw, 46px); letter-spacing: -.026em; line-height: 1.06; text-wrap: balance; }
h3 { font-size: 17px; letter-spacing: -.01em; }
p  { margin: 0; }

/* Emoji stay in the system's own colour font — recolouring them makes them muddy */
/* Drawn, not an emoji: Windows has no flag glyphs, so the German flag emoji
   renders there as the bare letters "DE". */
.flag {
  display: inline-block;
  width: 1.05em; height: .63em;
  margin-left: 7px;
  vertical-align: baseline;
  border-radius: 2px;
  box-shadow: 0 0 0 1px rgb(from var(--ink) r g b / .14);
}
img, svg { max-width: 100%; }
img { height: auto; }

a { color: var(--accInk); text-decoration: none; }
a:hover { text-decoration: underline; }

:focus-visible {
  outline: 2px solid var(--acc);
  outline-offset: 2px;
  border-radius: 6px;
}

.skip {
  position: absolute; left: -9999px; top: 8px; z-index: 100;
  padding: 10px 14px; border-radius: var(--r);
  background: var(--glass3); color: var(--ink); box-shadow: var(--lift);
}
.skip:focus { left: 8px; }

.wrap { width: min(1180px, 100% - 40px); margin-inline: auto; }
.sec  { padding: 76px 0; }
.sec--tight { padding: 52px 0; }

.lede { color: var(--ink2); font-size: 17px; line-height: 1.62; }
.small { font-size: 15px; color: var(--ink2); line-height: 1.65; }
.tiny  { font-size: 12.5px; color: var(--ink2); line-height: 1.6; }
.mid   { text-align: center; }
.mid .lede { margin-inline: auto; max-width: 58ch; }
/* a centred intro block sat straight on the cards below it */
.mid + .grid-3, .mid + .grid-2, .mid + .tiers, .mid + .plans,
.mid + .products, .mid + .faq, .mid + .table-wrap, .mid + .rise-stagger,
.mid + .marquee, .mid + .flowmap, .mid + .showcase, .mid + .tiles,
.mid + .saidwrote, .mid + .steps4, .mid + .path { margin-top: 34px; }
.mid + .mid { margin-top: 24px; }
.sec > h2 + .faq, .sec > h2 + .grid-3, .sec > h2 + .grid-2 { margin-top: 26px; }
.bill + .plans, .bill + .tiers { margin-top: 30px; }
/* a run of paragraphs needs air between them — p has no margin by default here */
p + p { margin-top: 11px; }
.tiny.mid { margin-inline: auto; max-width: 78ch; margin-top: 20px; }
/* a footnote under a table or a card row sat flush against it */
.table-wrap + .tiny, .tiers + .tiny, .plans + .tiny, .grid-3 + .tiny, .grid-2 + .tiny,
.facts + .tiny, .sec > .tiny { margin-top: 20px; }

.eyebrow {
  display: inline-block;
  font: 500 12px/1 var(--brand);
  letter-spacing: .15em;
  text-transform: uppercase;
  color: var(--ink2);
  margin-bottom: 14px;
}

/* --------------------------------------------------------------- buttons --- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 12px 17px;
  border-radius: var(--r);
  border: 1px solid var(--cardLine);
  font: 560 14px/1 var(--font);
  color: var(--ink);
  background: var(--glass3);
  box-shadow: none;
  cursor: pointer;
  transition: transform .18s var(--ease), box-shadow .18s var(--ease), background .18s var(--ease), color .18s var(--ease), border-color .18s var(--ease);
}
.btn:hover {
  background: var(--glassHov);
  color: var(--ink);
  border-color: rgb(from var(--ink) r g b / .3);
  text-decoration: none;
}
.btn:hover { transform: translateY(-2px); }
.btn:active { transform: translateY(0) scale(.97); }

.btn-primary {
  color: #fff;
  background: var(--accFill);
  border-color: transparent;
  font-weight: 600;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .45), 0 8px 18px -8px var(--accGlow);
}
.btn-primary:hover {
  color: #fff;
  background: var(--accFill);
  border-color: transparent;
  transform: translateY(-2px);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .5), 0 14px 26px -8px var(--accGlow);
}

.btn-big { padding: 15px 22px; font-size: 15px; border-radius: 16px; }

/* the buy button breathes — barely, so it draws the eye without nagging */
.btn-buy { animation: buy-breathe 3.4s ease-in-out infinite; }
@keyframes buy-breathe {
  0%, 100% { transform: scale(1);     box-shadow: inset 0 1px 0 rgba(255,255,255,.45), 0 8px 18px -8px var(--accGlow); }
  50%      { transform: scale(1.022); box-shadow: inset 0 1px 0 rgba(255,255,255,.5), 0 14px 30px -8px var(--accGlow); }
}
.btn-buy:hover { animation-play-state: paused; }
@media (prefers-reduced-motion: reduce) { .btn-buy { animation: none; } }
.btn-ghost { background: transparent; box-shadow: none; }
.btn-ghost:hover { background: var(--glass3); box-shadow: none; }
.btn:disabled { opacity: .45; pointer-events: none; }

.btn svg { width: 17px; height: 17px; flex: 0 0 auto; }

/* Ein Knopf MIT Icon war 41px hoch, einer ohne 38px — das Icon (17px) ist
   hoeher als die Zeilenhoehe (14px). In der Navigationsleiste faellt das als
   unterschiedlich hohe Kopfzeile je Seite auf. Feste Hoehe statt Polsterung
   macht beide gleich, ohne das Icon zu verkleinern. */
.nav .btn { height: 38px; padding-top: 0; padding-bottom: 0; }

.cta-row { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; }
.mid-row { justify-content: center; margin-top: 26px; }

/* ----------------------------------------------------------------- cards --- */
/* A card has to sit ON the page, not be drawn into it: the inset highlight alone
   left the boxes flat against the ground. */
.card {
  border-radius: var(--r-lg);
  background: var(--glass2);
  background-color: var(--cardBase);
  border: 1px solid var(--line);
  box-shadow: inset 0 1px 0 var(--hl), var(--lift);
  padding: 22px 24px;
}

/* The raised card carries its edge as a 1px gradient PADDING, so the highlight
   travels around the corner instead of stopping at it. */
.card-raised {
  border: none;
  border-radius: var(--r-xl);
  padding: 1px;
  background: var(--edge2);
  box-shadow: var(--lift);
}
.card-raised > .in {
  border-radius: calc(var(--r-xl) - 1px);
  padding: 26px 28px;
  background: var(--glass2);
  background-color: var(--cardBase);
  box-shadow: inset 0 1px 0 var(--hl);
  height: 100%;
}

/* a heading sits directly on its text otherwise: both have margin 0 here */
.card h3 + p, .card h3 + .small, .card h3 + .lede { margin-top: 9px; }
/* a full-width card would otherwise run 140 characters to the line */
.card > p, .card > .small { max-width: 84ch; }

.card-lift { transition: transform .35s var(--ease), box-shadow .35s ease; }
.card-lift:hover { transform: translateY(-2px); box-shadow: var(--shadow); }

/* ------------------------------------------------------------------- nav --- */
/* Floating bar, not a lid: it keeps 14px of air on every side so the page
   scrolls UNDER it. Stuck to the top edge it read as browser chrome. */
/* 2026-10-02: a plain row across the page with a hairline under it — no floating box.
   The inner width is set with PADDING (not a wrapper), so every page keeps its markup:
   the content lines up with .wrap (1180px). */
.nav {
  position: sticky;
  top: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  gap: 18px;
  height: 64px;
  margin: 0;
  padding: 0 max(20px, calc((100% - 1180px) / 2));
  background: rgb(from var(--ground) r g b / .82);
  border-bottom: 1px solid var(--line);
  /* ⚠️ Der teuerste Posten beim Scrollen. Die Leiste steht `sticky` ueber dem
     Inhalt, also muss der Browser den Bereich dahinter in JEDEM Frame neu
     unschaerfen. 18 px Radius PLUS saturate() sind dafuer zu viel — sichtbar
     ist der Unterschied zu 12 px kaum, spuerbar beim Scrollen schon.
     `contain: paint` sagt dem Browser ausserdem, dass nichts aus der Leiste
     herausragt: er muss beim Neuzeichnen nur diesen Kasten anfassen. */
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
}
/* ⚠️ `contain: paint` NUR AB 901 px. Es schneidet alles ab, was aus der Leiste ragt —
   und das Handy-Menue klappt genau UNTER der Leiste auf. Mit der Zeile fuer alle
   Breiten war das Menue auf jedem Handy unsichtbar und die Links darin nicht
   antippbar ("man kann sich nirgends anmelden", Adrian 2026-09-28). */
@media (min-width: 901px) { .nav { contain: paint; } }

/* Wer Bewegung reduziert haben will, braucht die Unschaerfe auch nicht. */
@media (prefers-reduced-motion: reduce) {
  .nav { backdrop-filter: none; -webkit-backdrop-filter: none; }
}

.brand { display: inline-flex; align-items: center; gap: 10px; color: var(--ink); font: 600 19px/1 var(--brand); letter-spacing: -.012em; }
.brand:hover { text-decoration: none; }
.brand img { width: 28px; height: 28px; display: block; }
.foot .brand { font-size: 16px; }
.foot .brand img { width: 26px; height: 26px; }

.nav-links { display: flex; align-items: center; gap: 6px; margin-left: auto; }
.nav-links a {
  padding: 8px 12px;
  border-radius: var(--r-sm);
  font: 450 14.5px/1 var(--font);
  color: var(--ink2);
  transition: color .18s var(--ease);
}
.nav-links a:hover { color: var(--ink); text-decoration: none; }
/* the page you are on, or the area it belongs to (Apps on /scribe and /atomAI) */
.nav-links a[aria-current] { color: var(--ink); }

/* A product link carries its own colour as a dot, so the palette of each page is
   announced before you click it. The dot, not the text: coloured link text next to
   plain link text reads as "one of these is broken". */
.nav-links a { display: inline-flex; align-items: center; gap: 7px; }
.nav-links a svg { width: 15px; height: 15px; flex: 0 0 auto; opacity: .85; }
.nav-links a.nav-ic { padding: 8px 10px; }
.nav-links a.nav-ic svg { width: 18px; height: 18px; opacity: .7; }
.nav-links a.nav-ic:hover svg { opacity: 1; }
/* 2026-10-02: the product's own icon, small and close in front of its name (Adrian) — set as
   a background, so every page gets it from here without touching its markup */
.nav-links a[data-acc]::before {
  content: "";
  width: 20px; height: 20px; margin-right: -2px;
  background: center / contain no-repeat;
  border-radius: 0;
  box-shadow: none !important;
}
.nav-links a[data-acc="atom"]::before   { background-image: url('../img/atom-icon.webp'); }
/* 2026-10-15 (Adrian): the two areas carry a quiet sign in the bar — line icons in the colour of the
   text, centred on the word (the coloured tiles before them "looked vibe-coded"). */
.nav-links a svg.nav-gl { width: 16px; height: 16px; opacity: .8; }
.nav-links a:hover svg.nav-gl, .nav-links a[aria-current] svg.nav-gl { opacity: 1; }
.nav-links a[data-acc]::after {
  content: none;
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--accFill);
  box-shadow: 0 0 0 3px rgb(from var(--acc) r g b / .16);
  flex: 0 0 auto;
}

.nav-right { display: flex; align-items: center; gap: 4px; }
.nav-right .btn { margin-left: 8px; }

.icon-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; padding: 0;
  border-radius: 10px;
  border: 0;
  background: none;
  color: var(--ink2);
  cursor: pointer;
  transition: color .18s var(--ease), background .18s var(--ease);
}
.icon-btn:hover { color: var(--ink); background: rgb(from var(--ink) r g b / .08); }
.icon-btn svg { width: 17px; height: 17px; }

/* one button, two glyphs: show the mode you would switch TO */
[data-theme="dark"] .t-sun  { display: none; }
:root:not([data-theme="dark"]) .t-moon { display: none; }

.burger { display: none; }

@media (max-width: 900px) {
  .nav { gap: 10px; }
  .burger { display: inline-flex; }
  /* Auf dem Handy liegt die Menueliste nicht mehr im Fluss (position:absolute), ihr
     `margin-left:auto` schiebt also nichts mehr nach rechts — ohne diese Zeile standen
     die Knoepfe direkt hinter dem Logo statt am rechten Rand. */
  .nav-right { margin-left: auto; }
  .nav-links {
    position: absolute;
    top: 100%; left: 0; right: 0;
    height: calc(100vh - 64px); height: calc(100dvh - 64px);
    overflow-y: auto;
    flex-direction: column;
    align-items: stretch;
    justify-content: center;
    gap: 0;
    padding: 0 20px 64px;
    /* DECKEND, nicht Glas: die Leiste hat selbst einen Weichzeichner, und ein
       Weichzeichner in einem Weichzeichner sieht nur den Inhalt der Leiste — die
       Ueberschrift darunter schien gestochen scharf durch das Menue. */
    background: var(--ground);
    display: none;
  }
  .nav.open { background: var(--ground); }
  .nav.open .nav-links { display: flex; }
  .nav-links a { padding: 10px 0; border-radius: 0; border-bottom: 1px solid var(--line);
    font: 370 clamp(34px, 9.5vw, 50px)/1.2 var(--serif); letter-spacing: -.02em; color: var(--ink);
    font-optical-sizing: none; font-variation-settings: "opsz" 64; }
  .nav-links a svg { display: none; }
  .nav-links a svg.nav-gl { display: block; width: 28px; height: 28px; margin-right: 6px; stroke-width: 1.4; opacity: .75; }
  .nav-links a[data-acc]::before { width: 30px; height: 30px; margin-right: 4px; }
  .nav-hide-sm { display: none; }
  /* „Sign in" traegt `nav-hide-sm`, damit er in der schmalen LEISTE nicht steht — im
     aufgeklappten Menue muss er aber da sein, sonst gibt es am Handy keinen Weg zur
     Anmeldung. Abgesetzt, weil es kein Produkt ist. */
  .nav-links .nav-hide-sm { display: flex; }
}

/* ------------------------------------------------------------------ hero --- */
.hero { padding: 96px 0 64px; }
.hero h1 { max-width: 16ch; }
.hero .lede { margin-top: 20px; max-width: 46ch; font-size: 19px; }
.hero .cta-row { margin-top: 30px; }
.hero .tiny { margin-top: 18px; }

.hero-split {
  display: grid;
  grid-template-columns: 1.12fr .88fr;
  gap: 44px;
  align-items: center;
}
@media (max-width: 880px) {
  h1 br { display: none; }
  .hero-split { grid-template-columns: 1fr; gap: 34px; }
  .hero { padding: 56px 0 40px; }
}

/* alternating feature rows: text one side, a model on the other */
.split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 52px;
  align-items: center;
}
.split + .split { margin-top: 74px; }
.split h2 { margin-bottom: 14px; }
.split .lede { max-width: 46ch; }
.split ul { margin: 18px 0 0; padding: 0; list-style: none; display: grid; gap: 10px; }
.split li { position: relative; padding-left: 26px; font-size: 15px; color: var(--ink1); line-height: 1.55; }
.split li::before {
  content: ""; position: absolute; left: 0; top: 7px;
  width: 8px; height: 8px; border-radius: 50%; background: var(--accFill);
}
.split-art { display: grid; place-items: center; }
.split--flip .split-art { order: -1; }
@media (max-width: 880px) {
  .split { grid-template-columns: 1fr; gap: 30px; }
  .split + .split { margin-top: 52px; }
  .split--flip .split-art { order: 0; }
}

/* The mark: a 45deg glass lozenge. It is the same frame every atomAI app icon
   uses, which is what ties the shop and the apps together. */
.lozenge {
  position: relative;
  width: 168px; height: 168px;
  margin-inline: auto;
  display: grid;
  place-items: center;
}
/* THE SHADOW MUST NOT LIVE ON THE ROTATED BOX. box-shadow is drawn in the
   element's own coordinates, so rotate(45deg) swings the light source 45 degrees
   with it — that is the dark wedge that showed up at the lower left. The glass
   square rotates; a drop-shadow filter on the unrotated parent lights it. */
.lozenge { filter: drop-shadow(0 26px 34px rgb(from var(--acc) r g b / .22)) drop-shadow(0 6px 10px rgba(24, 38, 76, .10)); }
.lozenge::before {
  content: "";
  position: absolute;
  inset: 12%;
  border-radius: 26px;
  transform: rotate(45deg);
  background: var(--glass3);
  border: 1px solid var(--cardLine);
  box-shadow: inset 0 2px 0 var(--hl);
}
.lozenge > * { position: relative; }

/* -------------------------------------------------------------- the atom ---
   The house mark, carrying the products that actually exist — two today. It
   gains a ring when a third ships, and not before: a placeholder on an orbit is
   a promise nobody made.

   Two rules learned the hard way:
   - the rings turn slowly. Fast orbits read as a loading spinner.
   - each product turns BACK at exactly its ring's rate, so it never spins on
     its own axis. Same duration, opposite direction, no exceptions.
   ------------------------------------------------------------------------- */
.atom {
  position: relative;
  width: min(430px, 88vw);
  aspect-ratio: 1;
  margin-inline: auto;
  display: grid;
  place-items: center;
}

.atom-core {
  position: relative;
  z-index: 3;
  /* a plain dot, not the logo again: the logo already sits on a ring as the
     workspace app, and the same mark twice reads as a mistake. 77px = 20% down
     from the 96px it started at. */
  width: 77px; height: 77px;
  border-radius: 50%;
  /* ⚠️ Der Kern haengt an `--atom-ton`, NICHT an `--acc`. Sonst bleibt er blau, waehrend
     Ringe und Leuchten lila werden — im Bild war er der einzige blaue Fleck in einem lila
     Modell, und genau das sah falsch aus (gemessen am 02.10.2026).
     Die Keyframes unten tragen dieselbe Variable: Keyframes schlagen Transitions, also muss
     die Farbe IN den Keyframes stehen — sie loesen sich bei jeder Aenderung von `--atom-ton`
     neu auf und folgen damit dessen weichem Verlauf. */
  background: linear-gradient(158deg,
    rgb(from var(--atom-ton) r g b / .82),
    color-mix(in srgb, var(--atom-ton) 82%, #0a1d4a));
  box-shadow: 0 0 0 9px rgb(from var(--atom-ton) r g b / .07),
              0 0 46px rgb(from var(--atom-ton) r g b / .3),
              inset 0 2px 0 rgba(255, 255, 255, .42);
  animation: core-breathe 5.5s ease-in-out infinite;
}
@keyframes core-breathe {
  0%, 100% { transform: scale(1);    box-shadow: 0 0 0 9px rgb(from var(--atom-ton) r g b / .07), 0 0 46px rgb(from var(--atom-ton) r g b / .3), inset 0 2px 0 rgba(255,255,255,.42); }
  50%      { transform: scale(1.045); box-shadow: 0 0 0 15px rgb(from var(--atom-ton) r g b / .05), 0 0 68px rgb(from var(--atom-ton) r g b / .42), inset 0 2px 0 rgba(255,255,255,.42); }
}

/* the glow behind the core, so the mark sits in light rather than on a flat page */
.atom::before {
  content: "";
  position: absolute;
  width: 34%; aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle, rgb(from var(--atom-ton) r g b / .22), rgb(from var(--atom-ton) r g b / 0) 70%);
}

.ring {
  position: absolute;
  top: 50%; left: 50%;
  border-radius: 50%;
  border: 1.5px solid rgb(from var(--acc) r g b / .4);
  animation: atom-spin var(--dur) linear infinite;
}
.ring-1 { width: 46%;  height: 46%;  margin: -23% 0 0 -23%;  --dur: 84s; }
.ring-2 { width: 74%;  height: 74%;  margin: -37% 0 0 -37%;  --dur: 116s; animation-direction: reverse; }

@keyframes atom-spin { to { transform: rotate(360deg); } }
@keyframes atom-spin-back { to { transform: rotate(-360deg); } }

/* THREE layers, and all three are needed. Placing a chip on a circle costs two
   rotations, and BOTH have to be undone or the icon hangs crooked:

     .node       rotate(--a) then translateY(-r)  — puts it on the ring at its angle
     .node-spin  animation, undoes the RING's turn — same duration, opposite direction
     .node-chip  rotate(-a),  undoes the ANGLE     — static, and it was missing

   Without the last one the icon sits permanently tilted by its own angle (118deg
   for the second one), and the box-shadow tilts with it, which is what looked like
   a broken shadow. Net rotation of the chip is now zero at every moment, so the
   shadow falls the same way as on every other card on the page. */
.node {
  position: absolute;
  top: 50%; left: 50%;
  width: 0; height: 0;
  transform: rotate(var(--a)) translateY(-50cqw);
}
.node-spin {
  display: block;
  animation: atom-spin-back var(--dur) linear infinite;
}
/* ring 2 turns the other way, so its chips have to as well */
.ring-2 .node-spin { animation-direction: reverse; }

/* No tile behind the mark: the app icons already ARE tiles, and putting one
   inside another read as a frame around a frame. */
.node-mark {
  position: absolute;
  left: -38px; top: -38px;
  width: 76px; height: 76px;
  display: grid; place-items: center;
  /* ⚠️ EINZELNE Transform-Eigenschaft (`rotate:`), NICHT `transform:`. Grund: die
     Hover-Vergroesserung und die 360°-Drehung muessen NEBENEINANDER laufen. In EINEM
     `transform` geht das nicht — jede Regel ersetzt die andere, und genau daran stand
     das untere Zeichen in den Vorversuchen 118° schief. `rotate:`, `scale:` und
     `translate:` sind getrennte Eigenschaften und stoeren sich nicht. */
  rotate: calc(var(--a) * -1);
}
/* the app icon is light now, so on a light page it needs a shadow of its own to
   sit ON the ring instead of dissolving into it */
/* ---- Die Marken im Atom sind Links auf ihr Produkt -----------------------
   Beide Zeichen sind Links. Beim Ueberfahren dreht sich das Zeichen EINMAL ganz,
   es leuchtet dahinter, und das GANZE Modell nimmt die Farbe DIESES Produkts an:
   atomAI #4A7DFF, Scribe #8b3ede (Adrian, 02.10.2026).

   ⚠️ VIER FEHLER AUS DEN VORVERSUCHEN — und was hier stattdessen gemacht wird:

   1. **Eine gewoehnliche Variable blendet NICHT.** `--tint` sprang hart, und erst die
      daraus ABGELEITETE Farbe wurde danach ueberblendet — zwischen zwei Farbraeumen,
      daher die matschigen Zwischentoene („erst lila, dann blau, dann gruen").
      → Hier ist die Variable mit `@property` ANGEMELDET (`syntax: '<color>'`). Damit
        rechnet der Browser SIE selbst sauber durch, in einem Farbraum.
   2. **Zwei Dinge gleichzeitig animieren erfindet Zwischentoene.** Wenn die Farbe
      blendet UND zusaetzlich `border-color` eine eigene Transition hat, laufen zwei
      Rechnungen uebereinander. → Es blenden GENAU ZWEI angemeldete Groessen:
      `--atom-ton` (welche Farbe) und `--atom-kraft` (wie stark, 0…1). Alles andere
      leitet daraus ab und hat KEINE eigene Transition.
   3. **Eine `:hover`-Animation bricht beim Wegfahren ab** und springt zurueck („dreht
      sich halb und backt zurueck"). CSS kann das nicht. → Die Drehung setzt ein
      winziges Stueck JavaScript (site.js) als Klasse `.dreht`, und nimmt sie erst im
      `animationend` wieder weg. Sie laeuft also immer ganz durch.
   4. **`.node-mark` trug sein Winkel-Zurueckdrehen in `transform`.** Jeder Hover-Zweig
      mit `transform` ersetzte es → schiefes Zeichen. → Oben steht jetzt `rotate:`, die
      Vergroesserung steht in `scale:`. Getrennte Eigenschaften, kein Verdraengen.
   -------------------------------------------------------------------------- */

/* Die zwei Groessen, die wirklich blenden. Angemeldet, damit der Browser sie
   interpolieren KANN — eine nicht angemeldete Variable springt. */
@property --atom-ton {
  syntax: '<color>';
  inherits: true;
  initial-value: #5888f0;
}
@property --atom-kraft {
  syntax: '<number>';
  inherits: true;
  initial-value: 0;
}

.atom .ring, .atom .node, .atom .node-spin, .atom-core { pointer-events: none; }

/* Ruhezustand: die Hausfarbe, Staerke 0. Beides blendet gemeinsam, gleich lang. */
.atom {
  --atom-ton: var(--acc);
  --atom-kraft: 0;
  transition: --atom-ton .55s var(--ease), --atom-kraft .55s var(--ease);
}
.atom:has(a.node-mark[data-acc="atom"]:hover),
.atom:has(a.node-mark[data-acc="atom"]:focus-visible)   { --atom-ton: #4a7dff; --atom-kraft: 1; }
.atom:has(a.node-mark[data-acc="scribe"]:hover),
.atom:has(a.node-mark[data-acc="scribe"]:focus-visible) { --atom-ton: #8b3ede; --atom-kraft: 1; }

a.node-mark {
  pointer-events: auto;
  cursor: pointer;
  border-radius: 22px;
  transition: scale .45s var(--ease);
}
a.node-mark:hover,
a.node-mark:focus-visible { scale: 1.06; }
a.node-mark:focus-visible { outline: 2px solid var(--atom-ton); outline-offset: 7px; }

/* Die 360°-Drehung. Sie setzt auf dem Winkel-Zurueckdrehen AUF (deshalb steht es in
   beiden Bildern) und laeuft ueber `rotate:`, stoert die Vergroesserung also nicht.
   Die Klasse kommt und geht ueber site.js — siehe Fehler 3 oben. */
@keyframes mark-dreh {
  from { rotate: calc(var(--a) * -1); }
  to   { rotate: calc(var(--a) * -1 + 360deg); }
}
a.node-mark.dreht { animation: mark-dreh .95s var(--ease); }

/* Das Leuchten HINTER dem Zeichen. Jedes Zeichen traegt seine eigene, FERTIGE Farbe —
   hier wird nichts ueberblendet, nur die Deckkraft. Dezent: kein harter Rand. */
a.node-mark[data-acc="atom"]   { --mark-ton: #4a7dff; }
a.node-mark[data-acc="scribe"] { --mark-ton: #8b3ede; }
a.node-mark::before {
  content: "";
  position: absolute;
  inset: -34%;
  border-radius: 50%;
  background: radial-gradient(circle at 50% 50%,
    rgb(from var(--mark-ton) r g b / .5) 0%,
    rgb(from var(--mark-ton) r g b / .22) 44%,
    rgb(from var(--mark-ton) r g b / 0) 72%);
  opacity: 0;
  transition: opacity .45s var(--ease);
}
a.node-mark:hover::before,
a.node-mark:focus-visible::before { opacity: 1; }

/* Das Modell faerbt sich mit. ⚠️ KEINE Folie ueber das ganze Modell — die nimmt auf der
   hellen Seite Ringen und Kern den Kontrast und sieht fahl aus statt farbig (gemessen).
   Stattdessen tragen die Teile die Farbe SELBST: ein Leuchten um die Mitte, die Ringe,
   der Kern. Alle drei leiten aus `--atom-ton`/`--atom-kraft` ab und blenden deshalb
   gemeinsam, ohne eigene Transition. */
.atom-schein {
  position: absolute;
  inset: 14%;
  border-radius: 50%;
  pointer-events: none;
  /* ⚠️ Staerke gemessen, nicht geschaetzt: mit .30 war der Unterschied bei atomAI im Bild
     kaum zu sehen — dessen Blau liegt nah an der Ruhefarbe der Seite. Scribe (lila) sah man
     sofort. Also hoeher, und der Kreis reicht weiter nach aussen. */
  background: radial-gradient(circle at 50% 50%,
    rgb(from var(--atom-ton) r g b / calc(.44 * var(--atom-kraft))) 0%,
    rgb(from var(--atom-ton) r g b / calc(.22 * var(--atom-kraft))) 48%,
    rgb(from var(--atom-ton) r g b / 0) 76%);
}

/* Die Ringe: Farbton UND Deckkraft kommen aus denselben zwei Groessen. */
.ring {
  border-color: rgb(from var(--atom-ton) r g b / calc(.4 + .55 * var(--atom-kraft)));
  /* ein weicher Hauch nach aussen — kein harter Ring, nur damit die Linie traegt */
  box-shadow: 0 0 calc(14px * var(--atom-kraft)) rgb(from var(--atom-ton) r g b / calc(.30 * var(--atom-kraft)));
}

/* Die Ringe drehen sich sehr langsam — beim Ueberfahren halten sie an, damit das
   Ziel nicht wegwandert. Das ist kein Abbruch: sie stehen still und laufen
   danach an derselben Stelle weiter. */
.atom:has(a.node-mark:hover) .ring,
.atom:has(a.node-mark:hover) .node-spin,
.atom:has(a.node-mark:focus-visible) .ring,
.atom:has(a.node-mark:focus-visible) .node-spin { animation-play-state: paused; }

@media (prefers-reduced-motion: reduce) {
  a.node-mark, a.node-mark::before, .atom { transition: none; }
  a.node-mark.dreht { animation: none; }
}

.node img { width: 76px; height: 76px; display: block;
  filter: drop-shadow(0 10px 18px rgb(from var(--atom-ton) r g b / .3)) drop-shadow(0 2px 4px rgba(24,38,76,.12)); }

.ring { container-type: size; }
@supports not (width: 1cqw) {
  .ring-1 .node { transform: rotate(var(--a)) translateY(-99px); }
  .ring-2 .node { transform: rotate(var(--a)) translateY(-159px); }
}

.a-0   { --a:   0deg; }
.a-118 { --a: 118deg; }

@media (max-width: 880px) {
  .atom { width: min(320px, 82vw); }
  .atom-core { width: 60px; height: 60px; }
  .node-mark { width: 58px; height: 58px; left: -29px; top: -29px; }
  .node img { width: 58px; height: 58px; }
}

@media (prefers-reduced-motion: reduce) {
  .ring, .node-spin, .atom-core { animation: none; }
}

/* An app icon is delivered WITH its own shadow and its own rounded corners. It
   gets neither a frame nor a second shadow — that was the clipped-shadow bug. */
.mark-xl { display: block; width: clamp(120px, 20vw, 168px); height: auto; }

/* ------------------------------------------------- models inside a card ---
   These have to SAY what the app is, not just look busy. Each one names the jobs
   it does and shows them happening.
   ------------------------------------------------------------------------- */
.prod-model {
  margin: 4px 0 2px;
  padding: 14px;
  border-radius: var(--r);
  background: var(--sink);
  border: 1px solid var(--line);
  overflow: hidden;
}

/* --- atomAI: three tools of one workspace, lighting up in turn --- */
.wsrow {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px;
  border-radius: 9px;
  opacity: .42;
  transition: opacity .4s ease;
  animation: ws 7.5s ease-in-out infinite;
}
.wsrow + .wsrow { margin-top: 5px; }
.wsrow:nth-child(1) { animation-delay: 0s; }
.wsrow:nth-child(2) { animation-delay: 2.5s; }
.wsrow:nth-child(3) { animation-delay: 5s; }
@keyframes ws {
  0%, 2%    { opacity: .42; background: transparent; }
  6%, 28%   { opacity: 1;   background: rgb(from var(--acc) r g b / .12); }
  34%, 100% { opacity: .42; background: transparent; }
}
.wsrow i {
  width: 26px; height: 26px; flex: 0 0 auto;
  display: grid; place-items: center;
  border-radius: 7px;
  color: var(--accInk);
  background: var(--accTint);
  border: 1px solid var(--accLine);
}
.wsrow i svg { width: 15px; height: 15px; }
.wsrow b { font: 600 13.5px/1 var(--font); color: var(--ink); }
.wsrow span { margin-left: auto; font: 500 11px/1 var(--mono); color: var(--ink2); }

/* --- Scribe: a voice going in, text coming out --- */
.say {
  display: flex; align-items: center; gap: 11px;
  padding-bottom: 11px;
  margin-bottom: 11px;
  border-bottom: 1px solid var(--line);
}
.say-mic {
  width: 30px; height: 30px; flex: 0 0 auto;
  display: grid; place-items: center;
  border-radius: 50%;
  color: #fff;
  background: var(--accFill);
  box-shadow: 0 0 0 0 rgb(from var(--acc) r g b / .45);
  animation: pill-pulse 2.4s ease-out infinite;
}
.say-mic svg { width: 15px; height: 15px; }
.mini-bars { display: flex; align-items: center; gap: 3px; height: 24px; }
.mini-bars i {
  display: block; width: 3.5px; border-radius: 99px;
  background: var(--accFill);
  animation: bar var(--t, 1s) ease-in-out infinite alternate;
}
.mini-bars i:nth-child(1) { --h: 10px; --t: .62s; animation-delay: -.42s; }
.mini-bars i:nth-child(2) { --h: 20px; --t: .48s; animation-delay: -.18s; }
.mini-bars i:nth-child(3) { --h: 14px; --t: .55s; animation-delay: -.33s; }
.mini-bars i:nth-child(4) { --h: 24px; --t: .44s; animation-delay: -.06s; }
.mini-bars i:nth-child(5) { --h: 12px; --t: .60s; animation-delay: -.25s; }
.mini-bars i:nth-child(6) { --h: 18px; --t: .50s; animation-delay: -.38s; }
.say em {
  margin-left: auto;
  font: 600 11px/1 var(--font); font-style: normal;
  letter-spacing: .06em; text-transform: uppercase;
  color: var(--ink2);
}
.say-out { display: flex; align-items: baseline; gap: 9px; }
.say-out > svg { width: 15px; height: 15px; color: var(--accInk); flex: 0 0 auto; align-self: center; }
/* Words arrive one at a time, then the whole line clears at once and starts over.
   The staggering is done INSIDE the keyframes, not with animation-delay: a delay
   shifts the entire cycle, so each word also disappeared at its own moment and the
   line unravelled backwards. Same duration, no delay, different percentages —
   every word vanishes on the same frame. */
.mini-type { font: 400 14px/1.5 var(--font); color: var(--ink); white-space: nowrap; }
.mini-type i {
  display: inline-block;
  max-width: 0;
  overflow: hidden;
  vertical-align: bottom;
  font-style: normal;
  animation-duration: 7s;
  animation-iteration-count: infinite;
  animation-timing-function: ease-in-out;
}
.mini-type i:nth-child(1) { animation-name: w1; }
.mini-type i:nth-child(2) { animation-name: w2; }
.mini-type i:nth-child(3) { animation-name: w3; }
.mini-type i:nth-child(4) { animation-name: w4; }
.mini-type i:nth-child(5) { animation-name: w5; }
@keyframes w1 { 0% { max-width: 0; } 6%, 84% { max-width: 9em; } 86%, 100% { max-width: 0; } }
@keyframes w2 { 0%, 8% { max-width: 0; } 14%, 84% { max-width: 9em; } 86%, 100% { max-width: 0; } }
@keyframes w3 { 0%, 16% { max-width: 0; } 22%, 84% { max-width: 9em; } 86%, 100% { max-width: 0; } }
@keyframes w4 { 0%, 24% { max-width: 0; } 30%, 84% { max-width: 9em; } 86%, 100% { max-width: 0; } }
@keyframes w5 { 0%, 32% { max-width: 0; } 38%, 84% { max-width: 9em; } 86%, 100% { max-width: 0; } }

.mini-caret {
  display: inline-block;
  width: 2px; height: 1.02em;
  /* text-bottom sits on the font's own baseline box; plain bottom used the line
     box and left the caret riding above the letters */
  vertical-align: text-bottom;
  position: relative; top: .08em;
  background: var(--acc);
  animation: caret 1.05s steps(1) infinite;
}

@media (prefers-reduced-motion: reduce) {
  .wsrow, .say-mic, .mini-bars i, .mini-type i, .mini-caret { animation: none; }
  .mini-type i { max-width: 9em; }
  .wsrow { opacity: 1; }
  .mini-bars i { height: 15px; }
}

/* ------------------------------------------------------------- product --- */
.products { display: grid; grid-template-columns: repeat(2, 1fr); gap: 22px; }
@media (max-width: 880px) { .products { grid-template-columns: 1fr; } }

.prod { display: flex; flex-direction: column; gap: 16px; }
/* the icon used to hang above the name; centring the row lines them up */
.prod-top { display: flex; align-items: center; gap: 15px; }
/* The icon file already contains its own rendered shadow and its own rounded
   corners. A border-radius here clips that shadow off at the corners, and a
   box-shadow adds a second one beside it — that was the broken shadow. */
.prod-icon {
  width: 60px; height: 60px; flex: 0 0 auto;
  display: block;
}
.prod-name { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; }
.prod h3 { font-size: 21px; }
.prod-kind { font: 500 13.5px/1 var(--font); color: var(--ink2); margin-top: 7px; }
.prod p { color: var(--ink2); font-size: 15px; line-height: 1.6; }
.prod ul { margin: 0; padding: 0; list-style: none; display: grid; gap: 9px; }
.prod li { position: relative; padding-left: 26px; font-size: 16px; color: var(--ink1); line-height: 1.5; }
.prod li::before {
  content: "";
  position: absolute; left: 3px; top: 8px;
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--accFill);
}
.prod-foot { margin-top: auto; padding-top: 6px; display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.prod-price { font: 600 17px/1 var(--font); color: var(--ink); }
.prod-price span { font-weight: 400; color: var(--ink2); font-size: 13px; }

.tag {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 10px;
  border-radius: 99px;
  font: 600 11px/1.5 var(--font);
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--accInk);
  background: var(--accTint);
  border: 1px solid var(--accLine);
}
.tag-quiet { color: var(--ink2); background: var(--glass3); border-color: var(--line); }

/* FUER WELCHE PLATTFORM ein Produkt ist (Adrian, 2026-09-29): bevor jemand herunterlaedt, soll er
   sehen, dass es ein Windows-Programm ist — leise, nicht als Warnung. Bewusst allgemein gehalten:
   ein spaeteres Produkt (Erweiterung, Web) setzt hier seinen eigenen Text und sein eigenes Zeichen.
   Das Zeichen sind vier gleiche Quadrate (Windows-11-Form); die perspektivische alte Fahne wird bei
   12 px zu Matsch — visuell gegengeprueft. */
.plat {
  display: inline-flex; align-items: center; gap: 7px;
  margin-top: 9px;
  font: 600 13px/1.4 var(--font);
  color: var(--ink2);
}
.plat .plat-ico { width: 14px; height: 14px; flex: 0 0 auto; }
/* in mittig gesetzten Bloecken (Schluss-Aufruf) mittig statt links */
.plat-mid { display: flex; justify-content: center; }

/* „Weiterlesen"-Liste (auch auf den Produktseiten, die legacy-bridge.css nicht laden) */
.weiter { margin-top: 10px; }
.weiter h2 { font-size: 20px; margin: 0 0 14px; }
.weiter ul { margin: 0; padding: 0; list-style: none; display: grid; gap: 10px; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.weiter li a { display: block; padding: 13px 16px; border: 1px solid var(--line); border-radius: var(--r);
  background: var(--glass2); color: var(--ink1); font-size: 14.5px; line-height: 1.45; }
.weiter li a:hover { border-color: var(--accLine); color: var(--ink); text-decoration: none; }
.tag-ok { color: var(--okInk); background: var(--okBg); border-color: var(--okLine); }

/* ------------------------------------------------------------- features --- */
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; }
.grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 18px; }
@media (max-width: 880px) { .grid-3, .grid-2 { grid-template-columns: 1fr; } }

.feat h3 { margin-bottom: 8px; }
.feat p { color: var(--ink2); font-size: 15.5px; line-height: 1.62; }
.feat-ic {
  width: 38px; height: 38px;
  display: grid; place-items: center;
  border-radius: 11px;
  margin-bottom: 14px;
  color: var(--accInk);
  background: var(--accTint);
  border: 1px solid var(--accLine);
}
.feat-ic svg { width: 19px; height: 19px; }

/* ------------------------------------------------------- product models ---
   A small working model of what the app DOES beats a screenshot of its settings
   window: it reads at a glance, it costs 4 KB instead of 400, and it keeps the
   page's own palette instead of dragging a second one in.
   ------------------------------------------------------------------------- */
.model {
  position: relative;
  display: grid;
  place-items: center;
  padding: 26px 10px;
}

/* --- Scribe: the dictation pill, listening --- */
.pill {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 18px;
  padding: 16px 26px;
  border-radius: 999px;
  background: var(--glass3);
  background-color: var(--cardBase);
  border: 1px solid var(--cardLine);
  box-shadow: inset 0 1px 0 var(--hl), var(--shadow);
  animation: pill-float 6s ease-in-out infinite;
}
@keyframes pill-float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-7px); } }

.pill-dot {
  width: 11px; height: 11px; border-radius: 50%;
  background: var(--accFill);
  box-shadow: 0 0 0 0 rgb(from var(--acc) r g b / .5);
  animation: pill-pulse 2.2s ease-out infinite;
  flex: 0 0 auto;
}
@keyframes pill-pulse {
  0%   { box-shadow: 0 0 0 0 rgb(from var(--acc) r g b / .5); }
  70%  { box-shadow: 0 0 0 13px rgb(from var(--acc) r g b / 0); }
  100% { box-shadow: 0 0 0 0 rgb(from var(--acc) r g b / 0); }
}

/* the level meter — the one thing the app shows while you talk */
.bars { display: flex; align-items: center; gap: 5px; height: 38px; }
.bars i {
  display: block;
  width: 5px;
  border-radius: 99px;
  background: var(--accFill);
  animation: bar var(--t, 1s) ease-in-out infinite alternate;
  transform-origin: center;
}
@keyframes bar { from { height: 7px; opacity: .55; } to { height: var(--h, 26px); opacity: 1; } }
.bars i:nth-child(1) { --h: 15px; --t: .62s; animation-delay: -.42s; }
.bars i:nth-child(2) { --h: 30px; --t: .48s; animation-delay: -.18s; }
.bars i:nth-child(3) { --h: 21px; --t: .55s; animation-delay: -.33s; }
.bars i:nth-child(4) { --h: 36px; --t: .44s; animation-delay: -.06s; }
.bars i:nth-child(5) { --h: 17px; --t: .60s; animation-delay: -.25s; }
.bars i:nth-child(6) { --h: 27px; --t: .50s; animation-delay: -.38s; }
.bars i:nth-child(7) { --h: 12px; --t: .66s; animation-delay: -.12s; }

.pill-key {
  font: 600 11.5px/1 var(--mono);
  color: var(--ink2);
  padding: 6px 9px;
  border-radius: 8px;
  background: var(--sink);
  border: 1px solid var(--line);
  white-space: nowrap;
}

/* the sentence landing at the cursor, underneath */
.landing {
  margin-top: 22px;
  max-width: 440px;
  width: 100%;
  padding: 15px 18px;
  border-radius: var(--r);
  background: var(--glass2);
  background-color: var(--cardBase);
  border: 1px solid var(--line);
  box-shadow: inset 0 1px 0 var(--hl), var(--lift);
  font: 400 15px/1.55 var(--font);
  color: var(--ink1);
}
.landing b { font-weight: 400; color: var(--ink); }
.caret {
  display: inline-block;
  width: 2px; height: 1.05em;
  margin-left: 1px;
  vertical-align: text-bottom;
  background: var(--acc);
  animation: caret 1.05s steps(1) infinite;
}
@keyframes caret { 0%, 50% { opacity: 1; } 51%, 100% { opacity: 0; } }

.landing-tag {
  display: block;
  margin-top: 9px;
  font: 500 11.5px/1 var(--font);
  color: var(--ink2);
}

@media (prefers-reduced-motion: reduce) {
  .pill, .pill-dot, .bars i, .caret { animation: none; }
  .bars i { height: 22px; }
}

@media (max-width: 560px) {
  .pill { gap: 12px; padding: 13px 18px; }
  .bars { gap: 4px; height: 32px; }
  .pill-key { display: none; }
}

/* --- atomAI: one long recording becoming three vertical clips --- */
.reel { width: 100%; max-width: 420px; display: grid; gap: 18px; }

.strip {
  position: relative;
  display: flex; align-items: center; gap: 3px;
  height: 62px;
  padding: 0 14px;
  border-radius: var(--r);
  background: var(--glass2);
  background-color: var(--cardBase);
  border: 1px solid var(--line);
  box-shadow: inset 0 1px 0 var(--hl), var(--lift);
  overflow: hidden;
}
.strip i {
  display: block; flex: 1 1 auto;
  min-width: 2px;
  border-radius: 99px;
  background: rgb(from var(--acc) r g b / .32);
}
/* the three stretches that get picked, brighter than the rest */
.strip i.on { background: var(--accFill); }
.strip::after {
  content: "";
  position: absolute; top: 0; bottom: 0; left: 0;
  width: 2px;
  background: var(--acc);
  box-shadow: 0 0 12px var(--accGlow);
  animation: playhead 7s linear infinite;
}
@keyframes playhead { from { left: 2%; } to { left: 98%; } }

.clips { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
.clip {
  position: relative;
  aspect-ratio: 9 / 16;
  border-radius: 13px;
  background: var(--accTint);
  border: 1px solid var(--accLine);
  box-shadow: inset 0 1px 0 var(--hl), var(--lift);
  display: flex; align-items: flex-end;
  padding: 9px;
  overflow: hidden;
  animation: clip-in 5.5s ease-in-out infinite;
}
.clip:nth-child(2) { animation-delay: .5s; }
.clip:nth-child(3) { animation-delay: 1s; }
@keyframes clip-in {
  0%, 12%  { transform: translateY(7px); opacity: .55; }
  26%, 88% { transform: translateY(0);   opacity: 1; }
  100%     { transform: translateY(7px); opacity: .55; }
}
/* the burnt-in caption, which is the point of the clip */
.clip span {
  display: block; width: 100%;
  height: 7px; border-radius: 99px;
  background: rgb(from var(--acc) r g b / .55);
  box-shadow: 0 -13px 0 -3px rgb(from var(--acc) r g b / .3);
}

/* --- the numbers, climbing --- */
.chart {
  width: 100%; max-width: 380px;
  padding: 16px 18px 12px;
  border-radius: var(--r-lg);
  background: var(--glass2);
  background-color: var(--cardBase);
  border: 1px solid var(--line);
  box-shadow: inset 0 1px 0 var(--hl), var(--shadow);
}
.chart-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.chart-head b { font: 600 12.5px/1 var(--font); color: var(--ink2); }
.chart-up { display: inline-flex; align-items: center; gap: 4px; font: 700 13px/1 var(--font); color: var(--accInk); }
.chart-up svg { width: 14px; height: 14px; }
.chart svg.graph { display: block; width: 100%; height: 86px; overflow: visible; }
.chart .line {
  fill: none; stroke: var(--acc); stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round;
  stroke-dasharray: 260; stroke-dashoffset: 260;
  animation: draw 2.6s var(--ease) forwards;
}
@keyframes draw { to { stroke-dashoffset: 0; } }
.chart .tip { fill: var(--acc); animation: tip 2.6s var(--ease) forwards; opacity: 0; }
@keyframes tip { 0%, 80% { opacity: 0; } 100% { opacity: 1; } }
.chart-foot { margin-top: 8px; font: 500 11.5px/1 var(--font); color: var(--ink2); }

@media (prefers-reduced-motion: reduce) {
  .strip::after, .clip, .chart .line, .chart .tip { animation: none; }
  .chart .line { stroke-dashoffset: 0; }
  .chart .tip { opacity: 1; }
}

/* ------------------------------------------------------------------ shot --- */
.shot {
  border-radius: var(--r-xl);
  padding: 1px;
  background: var(--edge2);
  box-shadow: var(--shadow);
  overflow: hidden;
}
.shot img { display: block; width: 100%; border-radius: calc(var(--r-xl) - 1px); }
.shot-cap { margin-top: 12px; text-align: center; }

/* ----------------------------------------------------------------- plans --- */
.bill {
  display: inline-flex;
  gap: 4px;
  padding: 4px;
  border-radius: 12px;
  background: var(--sink);
  border: 1px solid var(--line);
}
.bill-btn {
  padding: 8px 15px;
  border-radius: 9px;
  border: 1px solid transparent;
  background: transparent;
  font: 560 13.5px/1 var(--font);
  color: var(--ink2);
  cursor: pointer;
  transition: all .18s var(--ease);
}
.bill-btn.active {
  color: var(--ink);
  background: var(--glass3);
  border-color: var(--line);
  box-shadow: inset 0 1px 0 var(--hl);
}
.bill-save { color: var(--accInk); font-weight: 600; margin-left: 6px; }

.buy-switch {
  display: inline-flex;
  gap: 4px;
  margin: 24px 0 -6px;
  padding: 4px;
  border-radius: 12px;
  background: var(--sink);
  border: 1px solid var(--line);
}
.buy-switch[hidden] { display: none; }

.plans { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; align-items: stretch; }
@media (max-width: 1000px) { .plans { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 600px)  { .plans { grid-template-columns: 1fr; } }

.plan { display: flex; flex-direction: column; gap: 4px; padding: 22px 20px; }
.plan-name { font: 600 14px/1 var(--font); color: var(--ink); }
.plan-price { display: flex; align-items: baseline; gap: 4px; margin-top: 12px; }
.plan-price .amount { font: 600 32px/1 var(--font); color: var(--ink); letter-spacing: -.03em; }
.plan-price .per { font-size: 13px; color: var(--ink2); }
.plan-bill { font-size: 12.5px; color: var(--ink2); min-height: 19px; margin-top: 4px; }
.plan ul { margin: 18px 0 22px; padding: 0; list-style: none; display: grid; gap: 9px; }
.plan li { position: relative; padding-left: 21px; font-size: 13.5px; line-height: 1.5; color: var(--ink1); }
.plan li::before {
  content: "";
  position: absolute; left: 2px; top: 7px;
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--accFill);
}
.plan li .dim { color: var(--ink2); }
.plan .btn { margin-top: auto; width: 100%; }
.plan-featured { position: relative; border-color: var(--accLine); box-shadow: inset 0 1px 0 var(--hl), 0 14px 30px -20px var(--accGlow); }
.plan-tag {
  position: absolute; top: -10px; left: 50%; transform: translateX(-50%);
  padding: 3px 11px; border-radius: 99px;
  font: 600 10.5px/1.6 var(--font); letter-spacing: .05em; text-transform: uppercase;
  color: #fff; background: var(--accFill);
  box-shadow: 0 6px 14px -8px var(--accGlow);
  white-space: nowrap;
}

/* ----------------------------------------------------------------- table --- */
.table-wrap { overflow-x: auto; border-radius: var(--r-lg); border: 1px solid var(--line); background: var(--glass2); box-shadow: inset 0 1px 0 var(--hl); }
table.cmp { width: 100%; border-collapse: collapse; font-size: 13.5px; min-width: 680px; }
table.cmp th, table.cmp td { padding: 11px 14px; text-align: center; border-bottom: 1px solid var(--line); }
table.cmp thead th { font: 600 13px/1 var(--font); color: var(--ink); position: sticky; top: 0; background: var(--glass3); }
table.cmp th:first-child, table.cmp td:first-child { text-align: left; color: var(--ink1); min-width: 240px; }
table.cmp td { color: var(--ink2); }
table.cmp tbody tr:last-child th, table.cmp tbody tr:last-child td { border-bottom: none; }
table.cmp .hot { background: rgb(from var(--acc) r g b / .06); color: var(--ink1); }
table.cmp .dim { color: var(--ink2); font-size: 12px; }
.tbl-hint { display: none; }
/* Handy: die Tabelle ist breiter als der Bildschirm und wird seitlich gewischt. Die
   erste Spalte bleibt dabei stehen — sonst wischt man die Zeilennamen weg und sieht
   nur noch Zahlen ohne Bedeutung. Schmaler als am PC, damit neben ihr noch eine
   Spalte Platz hat. */
@media (max-width: 700px) {
  table.cmp { font-size: 13px; min-width: 560px; }
  table.cmp th, table.cmp td { padding: 10px 10px; }
  table.cmp th:first-child, table.cmp td:first-child {
    min-width: 132px; max-width: 150px;
    position: sticky; left: 0; z-index: 1;
    background: var(--cardBase);
    box-shadow: 1px 0 0 var(--line);
  }
  table.cmp thead th:first-child { z-index: 2; }
  .tbl-hint { display: block; margin: 0 0 10px; font-size: 13px; color: var(--ink2); text-align: right; }
}

/* ------------------------------------------------------------------- faq --- */
.faq { display: grid; gap: 10px; }
.faq details {
  border-radius: var(--r);
  border: 1px solid var(--line);
  background: var(--glass2);
  box-shadow: inset 0 1px 0 var(--hl);
  overflow: hidden;
}
.faq summary {
  padding: 15px 18px;
  cursor: pointer;
  font: 560 15px/1.45 var(--font);
  color: var(--ink);
  list-style: none;
  display: flex;
  align-items: center;
  gap: 12px;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: "";
  margin-left: auto;
  width: 9px; height: 9px;
  border-right: 1.8px solid var(--ink3);
  border-bottom: 1.8px solid var(--ink3);
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform .22s var(--ease);
  flex: 0 0 auto;
}
.faq details[open] summary::after { transform: rotate(-135deg) translate(-2px, -2px); }
.faq summary:hover { background: var(--glass3); }
.faq .answer { padding: 0 18px 17px; color: var(--ink2); font-size: 14.5px; line-height: 1.65; }

/* ------------------------------------------------------------------ band --- */
.band {
  border-radius: var(--r-xl);
  padding: 1px;
  background: var(--edge2);
  box-shadow: var(--shadow);
}
.band > .in {
  border-radius: calc(var(--r-xl) - 1px);
  padding: 46px 32px;
  text-align: center;
  background: var(--glass2);
  background-color: var(--cardBase);
  box-shadow: inset 0 1px 0 var(--hl);
}
.band .cta-row { justify-content: center; margin-top: 24px; }
.band .lede { margin: 14px auto 0; max-width: 46ch; }

/* A closing row, not another banner: the home page and the product pages used to
   end in the identical box, which made them read as the same page twice. */
.closer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 30px;
  flex-wrap: wrap;
  padding: 34px 38px;
  border-radius: var(--r-xl);
  background: var(--glass2);
  background-color: var(--cardBase);
  border: 1px solid var(--line);
  box-shadow: inset 0 1px 0 var(--hl), var(--lift);
}
.closer h2 { font-size: clamp(24px, 3vw, 31px); }
.closer .lede { margin-top: 10px; font-size: 16px; max-width: 42ch; }
.closer .cta-row { flex: 0 0 auto; }
@media (max-width: 760px) { .closer { padding: 26px 24px; } .closer .cta-row { width: 100%; } }

/* ---------------------------------------------------------------- footer --- */
.foot {
  margin-top: 40px;
  padding: 34px 0 40px;
  border-top: 1px solid var(--line);
  background: var(--glass2);
}
.foot-in { display: flex; flex-wrap: wrap; gap: 18px 26px; align-items: center; }
.foot-links { display: flex; flex-wrap: wrap; gap: 6px 16px; margin-left: auto; }
.foot-links a, .foot-links button {
  font: 400 13px/1 var(--font);
  color: var(--ink2);
  background: none; border: none; padding: 0; cursor: pointer;
}
.foot-links a:hover, .foot-links button:hover { color: var(--ink); text-decoration: underline; }
.foot-note { width: 100%; font-size: 12.5px; color: var(--ink2); }

/* --------------------------------------------------------------- support --- */
.support-overlay {
  position: fixed; inset: 0; z-index: 90;
  display: grid; place-items: center;
  padding: 20px;
  background: var(--scrim);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
}
.support-dialog {
  position: relative;
  width: min(520px, 100%);
  max-height: 90vh;
  overflow-y: auto;
  padding: 26px;
  border-radius: var(--r-lg);
  border: 1px solid var(--cardLine);
  background: var(--glass);
  box-shadow: inset 0 1px 0 var(--hl), var(--shadow);
}
.support-dialog h2 { font-size: 19px; margin-bottom: 8px; }
.support-copy { color: var(--ink2); font-size: 13.5px; line-height: 1.55; margin-bottom: 14px; }
.support-dialog label { display: block; font: 600 11.5px/1 var(--font); color: var(--ink2); margin: 12px 0 6px; }
.support-dialog input, .support-dialog textarea {
  width: 100%;
  padding: 10px 12px;
  border-radius: var(--r-sm);
  border: 1px solid var(--line);
  background: var(--sink);
  color: var(--ink);
  font: 400 14px/1.5 var(--font);
}
.support-dialog textarea { resize: vertical; min-height: 130px; }
.support-dialog input:focus, .support-dialog textarea:focus {
  outline: none;
  border-color: var(--accLine);
  box-shadow: 0 0 0 3px var(--accRing);
}
.support-x {
  position: absolute; top: 12px; right: 12px;
  width: 30px; height: 30px;
  display: grid; place-items: center;
  border-radius: 8px;
  border: 1px solid var(--line);
  background: var(--glass3);
  color: var(--ink2);
  font-size: 18px; line-height: 1;
  cursor: pointer;
}
.support-x:hover { color: var(--ink); background: var(--glassHov); }
.support-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 16px; flex-wrap: wrap; }
.support-msg { min-height: 16px; margin-top: 10px; font-size: 12.5px; color: var(--ink2); }
.support-msg.ok { color: var(--okInk); }
.support-msg.bad { color: var(--badInk); }
@media (max-width: 520px) {
  .support-dialog { padding: 18px; }
  .support-actions .btn { width: 100%; }
}

/* ------------------------------------------------------------ step flow ---
   Scribe's own shape. Three beats on one line, joined by a rule that runs behind
   them — the product IS a sequence, and a row of identical cards hid that.
   ------------------------------------------------------------------------- */
.flow { position: relative; display: grid; grid-template-columns: repeat(3, 1fr); gap: 26px; }
.flow::before {
  content: "";
  position: absolute; left: 12%; right: 12%; top: 31px;
  height: 1.5px;
  background: linear-gradient(90deg, rgb(from var(--acc) r g b / 0), rgb(from var(--acc) r g b / .45) 18%, rgb(from var(--acc) r g b / .45) 82%, rgb(from var(--acc) r g b / 0));
}
.step { position: relative; text-align: center; }
.step-n {
  position: relative;
  width: 62px; height: 62px;
  margin: 0 auto 18px;
  display: grid; place-items: center;
  border-radius: 20px;
  color: #fff;
  background: var(--accFill);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.4), 0 14px 26px -12px var(--accGlow);
}
.step-n svg { width: 26px; height: 26px; }
.step h3 { margin-bottom: 8px; }
.step p { color: var(--ink2); font-size: 14.5px; line-height: 1.6; max-width: 30ch; margin-inline: auto; }
@media (max-width: 820px) {
  .flow { grid-template-columns: 1fr; gap: 30px; }
  .flow::before { left: 31px; right: auto; top: 10%; bottom: 10%; width: 1.5px; height: auto;
    background: linear-gradient(180deg, rgb(from var(--acc) r g b / 0), rgb(from var(--acc) r g b / .45) 18%, rgb(from var(--acc) r g b / .45) 82%, rgb(from var(--acc) r g b / 0)); }
  .step { display: grid; grid-template-columns: 62px 1fr; gap: 18px; text-align: left; align-items: start; }
  .step-n { margin: 0; }
  .step p { margin-inline: 0; }
  .step h3 { grid-column: 2; }
  .step p { grid-column: 2; }
}

/* a bare list of facts, for a page that already has enough boxes */
.facts { display: grid; grid-template-columns: repeat(2, 1fr); gap: 2px 40px; }
/* '>' matters: .facts div also caught the inner wrapper and laid the heading
   out beside its own paragraph. */
.facts > div { display: flex; gap: 14px; align-items: flex-start; padding: 17px 0; border-top: 1px solid var(--line); }
.facts svg { width: 20px; height: 20px; color: var(--accInk); flex: 0 0 auto; margin-top: 2px; }
.facts b { display: block; font: 600 15px/1.4 var(--font); color: var(--ink); margin-bottom: 4px; }
.facts p { font-size: 14px; color: var(--ink2); line-height: 1.55; }
@media (max-width: 760px) { .facts { grid-template-columns: 1fr; } }

/* What is set BIG is what you get, not what you pay. A 92px "19" reads as a lot
   of money; the same 92px on the hours saved reads as a lot of value, and the
   price underneath looks small next to it. Same two facts, opposite impression. */
.value { text-align: center; }
.value-n {
  display: block;
  font: 700 clamp(58px, 10vw, 104px)/1 var(--font);
  letter-spacing: -.045em;
  color: var(--ink);
  background: var(--accFill);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent;
}
.value-l { display: block; margin-top: 14px; font-size: 18px; color: var(--ink1); }
.value-assume { display: block; margin-top: 8px; font-size: 13px; color: var(--ink2); }
.value-price {
  display: inline-flex; align-items: baseline; gap: 9px;
  margin-top: 28px; padding: 12px 22px;
  border-radius: 999px;
  background: var(--glass3);
  background-color: var(--cardBase);
  border: 1px solid var(--line);
  box-shadow: inset 0 1px 0 var(--hl), var(--lift);
}
.value-price b { font: 700 24px/1 var(--font); color: var(--ink); letter-spacing: -.02em; }
.value-price span { font-size: 14.5px; color: var(--ink2); }

/* ------------------------------------------------------- said vs written ---
   The clearest way to show what the cleanup does: the sentence as it was spoken,
   and the sentence as it lands. No explanation needed.
   ------------------------------------------------------------------------- */
.saidwrote { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; align-items: stretch; }
@media (max-width: 760px) { .saidwrote { grid-template-columns: 1fr; } }
.sw {
  padding: 20px 22px;
  border-radius: var(--r-lg);
  background: var(--glass2);
  background-color: var(--cardBase);
  border: 1px solid var(--line);
  box-shadow: inset 0 1px 0 var(--hl), var(--lift);
}
.sw-l {
  display: block;
  font: 600 11.5px/1 var(--font);
  letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink2);
  margin-bottom: 12px;
}
.sw p { font: 400 17px/1.6 var(--font); color: var(--ink1); }
.sw--out { border-color: var(--accLine); box-shadow: inset 0 1px 0 var(--hl), 0 14px 30px -20px var(--accGlow); }
.sw--out .sw-l { color: var(--accInk); }
.sw--out p { color: var(--ink); font-weight: 500; }
.sw s { color: var(--ink3); text-decoration-color: rgb(from var(--bad) r g b / .55); }

/* --- where the audio goes, and where it does not ---
   Three stations in a row and the cloud hanging off the top, cut off. The point
   of the picture is the branch that is NOT taken, so that branch is drawn.
   ------------------------------------------------------------------------- */
.flowmap {
  position: relative;
  padding: 74px 0 8px;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
  max-width: 760px;
  margin-inline: auto;
}

/* the line through the three stations */
.flowmap::before {
  content: "";
  position: absolute;
  left: 17%; right: 17%; top: 104px;
  height: 2px;
  background: repeating-linear-gradient(90deg,
    rgb(from var(--acc) r g b / .5) 0 7px, transparent 7px 14px);
}
/* the pulse that runs it */
.flowmap::after {
  content: "";
  position: absolute;
  top: 99px; left: 17%;
  width: 11px; height: 11px;
  border-radius: 50%;
  background: var(--acc);
  box-shadow: 0 0 14px var(--accGlow);
  animation: pulse-run 4s cubic-bezier(.45,0,.55,1) infinite;
}
@keyframes pulse-run {
  0%        { left: 17%; opacity: 0; transform: scale(.4); }
  10%       { left: 17%; opacity: 1; transform: scale(1); }
  50%       { left: 50%; opacity: 1; transform: scale(1); }
  88%       { left: 83%; opacity: 1; transform: scale(1); }
  96%, 100% { left: 83%; opacity: 0; transform: scale(.4); }
}

.stn { position: relative; text-align: center; z-index: 1; }
.stn-ic {
  width: 54px; height: 54px;
  margin: 0 auto 12px;
  display: grid; place-items: center;
  border-radius: 16px;
  color: #fff;
  background: var(--accFill);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.4), 0 12px 24px -12px var(--accGlow);
}
.stn-ic svg { width: 23px; height: 23px; }
.stn b { display: block; font: 600 14.5px/1.3 var(--font); color: var(--ink); margin-bottom: 4px; }
.stn p { font-size: 13px; line-height: 1.5; color: var(--ink2); }

/* the middle station is where the work happens, so it glows */
.stn--core .stn-ic {
  width: 62px; height: 62px;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.45), 0 0 0 7px rgb(from var(--acc) r g b / .1),
              0 16px 32px -12px var(--accGlow);
}

/* the cloud, hanging above the middle and cut off */
.cloudoff {
  position: absolute;
  top: 0; left: 50%;
  transform: translateX(-50%);
  text-align: center;
}
.cloudoff-box {
  position: relative;
  display: inline-flex; align-items: center; gap: 9px;
  padding: 10px 17px;
  border-radius: 999px;
  border: 1px dashed rgb(from var(--bad) r g b / .45);
  background: rgb(from var(--bad) r g b / .05);
  color: var(--ink2);
  font: 500 13.5px/1 var(--font);
}
.cloudoff-box svg { width: 17px; height: 17px; color: rgb(from var(--bad) r g b / .8); }
.cloudoff-x {
  position: absolute; top: -8px; right: -8px;
  width: 21px; height: 21px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--bad);
  color: #fff;
  font: 700 12px/1 var(--font);
  box-shadow: 0 4px 10px -3px rgb(from var(--bad) r g b / .6);
}
/* the dead branch down to the line */
.cloudoff::after {
  content: "";
  position: absolute;
  left: 50%; top: 100%;
  width: 2px; height: 26px;
  transform: translateX(-50%);
  background: repeating-linear-gradient(180deg,
    rgb(from var(--bad) r g b / .4) 0 5px, transparent 5px 10px);
}

/* Phone: STILL three in a row with the line through them — the row is the picture; stacked,
   it was a list of three icons and a screen long (Adrian, 2026-10-03). What goes instead is
   the one-line explanation under each name: the names carry it. */
@media (max-width: 760px) {
  .flowmap { gap: 6px; }
  .flowmap::before { top: 99px; }
  .flowmap::after { top: 95px; }
  .stn-ic { width: 46px; height: 46px; border-radius: 14px; margin-bottom: 10px; }
  .stn--core .stn-ic { width: 54px; height: 54px; }
  .stn-ic svg { width: 20px; height: 20px; }
  .stn b { font-size: 13.5px; margin-bottom: 0; }
  .stn p { display: none; }
}
@media (prefers-reduced-motion: reduce) { .flowmap::after { animation: none; opacity: 0; } }

/* --------------------------------------------------------- app marquee ---
   Names, deliberately NOT logos. Scribe types into these because Windows lets
   it, not because anyone partnered with us — a row of brand logos would imply
   exactly that, and borrowed marks in a sales context are a fight nobody needs.
   Naming a product to describe compatibility is fine; wearing its logo is not.
   ------------------------------------------------------------------------- */
.marquee {
  position: relative;
  overflow: hidden;
  padding: 6px 0;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
}
.marquee-track {
  display: flex;
  gap: 10px;
  width: max-content;
  animation: marquee 34s linear infinite;
}
.marquee:hover .marquee-track { animation-play-state: paused; }
@keyframes marquee { to { transform: translateX(-50%); } }

/* The marks run as flat silhouettes in one ink, never in brand colours: a row of
   full-colour logos reads as "these companies endorse us", which is not true and
   not ours to imply. A grey outline says "it writes here" and nothing more. */
.marquee-track > span {
  display: inline-flex; align-items: center; justify-content: center;
  width: 62px; height: 62px;
  flex: 0 0 auto;
  border-radius: 16px;
  background: var(--glass3);
  background-color: var(--cardBase);
  border: 1px solid var(--line);
  box-shadow: inset 0 1px 0 var(--hl), 0 6px 14px -10px rgba(24, 38, 76, .45);
}
.marquee-track svg {
  width: 26px; height: 26px;
  fill: var(--ink1);
  opacity: .62;
  transition: opacity .25s ease;
}
.marquee-track > span:hover svg { opacity: 1; }

@media (prefers-reduced-motion: reduce) { .marquee-track { animation: none; } }

/* ---------------------------------------------------- showcase cards ---
   Two big tiles that demonstrate instead of describe: the sentence being
   cleaned, and the dictionary doing its job on real words.
   --------------------------------------------------------------------- */
.showcase { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-bottom: 16px; }
@media (max-width: 860px) { .showcase { grid-template-columns: 1fr; } }
.show {
  padding: 22px 24px;
  border-radius: var(--r-lg);
  background: var(--glass2);
  background-color: var(--cardBase);
  border: 1px solid var(--line);
  box-shadow: inset 0 1px 0 var(--hl), var(--lift);
}
.show-k {
  display: block;
  font: 700 10.5px/1 var(--font);
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--accInk);
  margin-bottom: 7px;
}
.show h3 { font-size: 18px; margin-bottom: 16px; }
.show-note { margin-top: 13px; font-size: 12.5px; color: var(--ink2); }

.line-in, .line-out {
  padding: 12px 14px;
  border-radius: 10px;
  font: 400 14.5px/1.55 var(--font);
}
.line-in { background: var(--sink); color: var(--ink2); }
.line-in s { text-decoration-color: rgb(from var(--bad) r g b / .6); }
.line-arrow { display: grid; place-items: center; padding: 8px 0; color: var(--accInk); }
.line-arrow svg { width: 17px; height: 17px; }
.line-out {
  background: var(--accTint);
  border: 1px solid var(--accLine);
  color: var(--ink);
  font-weight: 500;
}

/* the dictionary, as a list of real corrections */
.dict { display: grid; gap: 1px; border-radius: 10px; overflow: hidden; background: var(--line); }
.dict div {
  display: grid; grid-template-columns: 1fr 22px 1fr;
  align-items: center; gap: 8px;
  padding: 10px 14px;
  background: var(--sink);
  font-size: 13.5px;
}
.dict span:first-child { color: var(--ink2); }
.dict span:last-child { color: var(--ink); font-weight: 600; text-align: right; }
.dict svg { width: 15px; height: 15px; color: var(--accInk); }

/* ------------------------------------------------------------ feature grid ---
   Icon, two or three words, one short line. The tile does the explaining, so the
   copy does not have to.
   ------------------------------------------------------------------------- */
/* centred, not left-aligned: a trailing row of one or two tiles hanging on the
   left edge looks like something fell off */
.tiles { display: flex; flex-wrap: wrap; justify-content: center; gap: 14px; }
.tiles .tile { flex: 0 1 300px; }
/* phone: two beside each other (an odd last one takes the full row) instead of a long single file */
@media (max-width: 520px) { .tiles { gap: 14px 16px; } .tiles .tile { flex: 1 1 calc(50% - 8px); } }

.tile {
  padding: 20px 18px;
  border-radius: var(--r);
  background: var(--glass2);
  background-color: var(--cardBase);
  border: 1px solid var(--line);
  box-shadow: inset 0 1px 0 var(--hl), 0 8px 18px -14px rgba(24, 38, 76, .5);
  transition: transform .3s var(--ease), box-shadow .3s ease;
}
.tile:hover { transform: translateY(-2px); box-shadow: inset 0 1px 0 var(--hl), var(--lift); }
.tile-ic {
  width: 34px; height: 34px;
  display: grid; place-items: center;
  border-radius: 10px;
  margin-bottom: 13px;
  color: var(--accInk);
  background: var(--accTint);
  border: 1px solid var(--accLine);
}
.tile-ic svg { width: 18px; height: 18px; }
.tile b { display: block; font: 600 15px/1.35 var(--font); color: var(--ink); margin-bottom: 5px; }
.tile p { font-size: 13.5px; line-height: 1.5; color: var(--ink2); }

/* ----------------------------------------------------------------- proof ---
   Only numbers we can stand behind go here. The founders' reach is the one hard
   figure this company actually has; user counts and testimonials are left out
   until they are real, because a made-up one is worth less than none.
   ------------------------------------------------------------------------- */
.proof {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px 34px;
  padding: 26px 30px;
  border-radius: var(--r-xl);
  background: var(--glass2);
  background-color: var(--cardBase);
  border: 1px solid var(--line);
  box-shadow: inset 0 1px 0 var(--hl), var(--lift);
}
.proof-item { text-align: center; }
.proof-n {
  display: block;
  font: 700 clamp(28px, 3.4vw, 40px)/1 var(--font);
  letter-spacing: -.035em;
  color: var(--ink);
}
.proof-l { display: block; margin-top: 7px; font: 500 12.5px/1.4 var(--font); color: var(--ink2); }
@media (max-width: 720px) {
  .proof { grid-template-columns: 1fr; gap: 18px; padding: 22px; }
  .proof-item + .proof-item { padding-top: 18px; border-top: 1px solid var(--line); }
}

/* The laurel, for the one number that is actually ours. It frames a fact, not a
   quote — we have no customer quotes yet, and a made-up one is worse than none. */
.laurel { display: flex; align-items: center; justify-content: center; gap: 18px; }
/* two of them side by side, right under the hero */
.laurels { display: flex; justify-content: center; gap: clamp(28px, 7vw, 92px); flex-wrap: wrap; }
.laurels .laurel-n { font-size: clamp(26px, 3.4vw, 38px); }
.laurels .laurel-l { font-size: 13.5px; }
.laurels .laurel-svg { width: 36px; height: 52px; }
@media (max-width: 620px) { .laurels { gap: 26px; } .laurels .laurel-svg { width: 28px; height: 40px; } }
/* Gruen (Adrian, 2026-10-01). ⚠️ Sonst gilt: Gruen gehoert der Privacy — hier ausdruecklich
   gewollt. `--ok` traegt in beiden Themes, die Deckkraft nimmt ihm den Signalcharakter. */
.laurel-svg { width: 44px; height: 63px; color: var(--ok); opacity: .72; flex: 0 0 auto; display: block; }
.laurel-r { display: inline-flex; transform: scaleX(-1); }
.laurel-mid { text-align: center; }
.laurel-n {
  display: block;
  font: 700 clamp(38px, 5.2vw, 56px)/1 var(--font);
  letter-spacing: -.04em;
  color: var(--ink);
}
.laurel-l { display: block; margin-top: 8px; font: 500 14px/1.4 var(--font); color: var(--ink2); }
@media (max-width: 560px) { .laurel-svg { width: 32px; height: 46px; } .laurel { gap: 12px; } }

/* the quiet row of guarantees — icon, two words, no sales pitch.
   It sat flush against the cards above it: a flex row has no margin of its own. */
.trust { display: flex; flex-wrap: wrap; justify-content: center; gap: 12px; margin-top: 40px; }
.grid-3 + .trust, .grid-2 + .trust { margin-top: 44px; }
.trust span {
  display: inline-flex; align-items: center; gap: 9px;
  padding: 12px 18px;
  border-radius: 999px;
  font: 600 15px/1 var(--font);
  color: var(--ink1);
  background: var(--glass3);
  background-color: var(--cardBase);
  border: 1px solid var(--line);
  box-shadow: inset 0 1px 0 var(--hl), 0 6px 14px -10px rgba(24, 38, 76, .5);
}
.trust svg { width: 18px; height: 18px; color: var(--accInk); flex: 0 0 auto; }

/* one sentence that carries weight, set larger than body copy */
.claim {
  font: 400 clamp(19px, 2.4vw, 25px)/1.5 var(--font);
  color: var(--ink);
  letter-spacing: -.015em;
  max-width: 30ch;
}
.claim b { font-weight: 700; }

/* ----------------------------------------------------------------- price --- */
/* The anchor: what it costs month to month, struck through, next to what it
   costs on the yearly plan. Both numbers are real and both are charged — this
   is the actual difference, not a made-up "list price". */
.price-was { color: var(--ink2); text-decoration: line-through; text-decoration-thickness: 1.5px; font-weight: 400; font-size: 15px; }
.price-was[hidden] { display: none; }
[data-day-note][hidden] { display: none; }
.price-day.mid { margin-top: 22px; text-align: center; }
.price-hero { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.price-hero .amount { font: 700 44px/1 var(--font); color: var(--ink); letter-spacing: -.035em; }
.price-hero .per { font-size: 14px; color: var(--ink2); }
.price-day { margin-top: 8px; font-size: 13.5px; color: var(--ink2); }
.price-day b { color: var(--ink); font-weight: 600; }

.tiers { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
@media (max-width: 760px) { .tiers { grid-template-columns: 1fr; } }
.tier { display: flex; flex-direction: column; gap: 3px; padding: 20px; }
/* Der Stufenname ist das, wonach der Kunde sucht („welche nehme ich?") — er stand kleiner da
   als die Fliesstext-Zeile darunter (Adrian, 2026-10-01: „schreibe die namen … groesser"). */
.tier-name { font: 700 21px/1.15 var(--font); color: var(--ink); letter-spacing: -.02em; }
.tier-price { font: 700 27px/1 var(--font); color: var(--ink); letter-spacing: -.03em; margin: 10px 0 2px; }
.tier-note { font-size: 12.5px; color: var(--ink2); }
.tier ul { margin: 14px 0 18px; padding: 0; list-style: none; display: grid; gap: 7px; }
.tier li { position: relative; padding-left: 19px; font-size: 13px; color: var(--ink1); line-height: 1.5; }
.tier li::before { content: ""; position: absolute; left: 2px; top: 7px; width: 5px; height: 5px; border-radius: 50%; background: var(--accFill); }
/* Die empfohlene Stufe soll man SEHEN, ohne dass es schreit: ein voller Akzent-Rahmen statt der
   Haarlinie, etwas angehoben, und ein ruhiger Schatten darunter. Keine Farbfuellung — die Karte
   bleibt eine Karte (Adrian, 2026-10-01: „mach dass die recommended option mehr heraussticht"). */
.tier-best {
  position: relative;
  border-color: var(--acc);
  box-shadow: inset 0 1px 0 var(--hl), 0 0 0 1px var(--acc), 0 22px 44px -26px var(--accGlow);
  transform: translateY(-8px);
}
/* Das Etikett traegt die Empfehlung — gross genug zum Lesen, nicht groesser. */
.tier-best .plan-tag { top: -13px; font-size: 11.5px; padding: 5px 14px; letter-spacing: .06em; }
/* Auf schmalen Schirmen stehen die Karten untereinander; dort wuerde das Anheben nur eine
   Luecke erzeugen — Rahmen und Etikett reichen. */
@media (max-width: 860px) { .tier-best { transform: none; } }

/* CTA rows line up: same height, same radius, same minimum width, so two
   buttons next to each other read as a pair instead of two loose objects. */
.cta-row .btn { min-width: 172px; }
.cta-row .btn-big { min-width: 208px; }
@media (max-width: 480px) { .cta-row { flex-direction: column; align-items: stretch; } .cta-row .btn { width: 100%; } }

/* Kaufknopf in der Preiskarte. `margin-top:auto` schiebt ihn ans Kartenende,
   damit die drei Knoepfe auf einer Linie sitzen, auch wenn eine Karte eine
   Zeile mehr Text hat. */
/* Beim Jahrespreis steht der Einmalpreis durchgestrichen daneben, damit man
   den Unterschied sieht statt ihn auszurechnen. */
.tier-was { font-size: 15px; font-weight: 500; color: var(--ink3); text-decoration: line-through; margin-right: 7px; }

/* Hinweis fuer jemanden, der das Produkt schon besitzt. */
.owned-note { margin-top: 10px; }
.owned-note a { color: var(--acc); text-decoration: none; border-bottom: 1px solid var(--accLine); }
.owned-note a:hover { border-bottom-color: var(--acc); }

.tier-cta { margin-top: auto; width: 100%; justify-content: center; }
.tier .tier-cta { margin-top: auto; }
.tier { min-height: 100%; }

/* Der Umschalter ueber den Preiskarten steht mittig, nicht linksbuendig wie
   im Hero. */
.buy-switch.mid-row { display: flex; width: max-content; margin: 0 auto 18px; }
.buy-switch.mid-row[hidden] { display: none; }

/* ---------------------------------------------------------- checkout --- */
/* Die Kauf- und Geraeteseiten baut der Server, nicht eine HTML-Datei. Sie
   hatten deshalb nur die Grundregeln und sahen aus wie ein rohes Formular:
   riesige Ueberschrift, winzige Kaestchen. Wer die Pflichthaken uebersah,
   klickte auf "weiter" und es passierte sichtbar nichts. */
.co-top { display: flex; align-items: center; justify-content: space-between; gap: 14px;
          max-width: 1180px; margin: 0 auto; padding: 18px 22px; }
.co-top .brand { display: inline-flex; align-items: center; gap: 9px; text-decoration: none;
                 color: var(--ink); font-weight: 680; font-size: 15px; }
.co-top .brand img { width: 24px; height: 24px; }
.co-step { font-size: 12.5px; color: var(--ink3); display: inline-flex; align-items: center; gap: 7px; }
.co-step svg { width: 14px; height: 14px; }

.co-wrap { max-width: 560px; margin: 0 auto; padding: 8px 22px 64px; }
.co-card { padding: 26px 26px 24px; }
/* Die Kennfarbe kommt ueber eine Klasse, nicht ueber ein style-Attribut:
   `style-src 'self'` verbietet Inline-Styles, die Farbe waere still verfallen.
   ⚠️ `--acc` allein reicht NICHT: die abgeleiteten Toene (--accFill, --accLine,
   --accGlow) sind auf :root schon ausgerechnet und erben den fertigen Wert,
   nicht die Formel. Wer nur --acc setzt, bekommt einen blauen Knopf auf einer
   lila Seite — gemessen. */
.co-scribe {
  --acc:     #8b3ede;
  --accSoft: #9f6ce4;
  --accDeep: #7200c6;
  --accPale: #b18cea;
  --accFill: linear-gradient(158deg, #9f6ce4, #7200c6);   /* wie der blaue: ein Verlauf, keine Flaeche */
  --accGlow: rgb(139 62 222 / .9);
  --accLine: rgb(139 62 222 / .4);
}
.co-kicker { margin: 0 0 4px; font-size: 12px; font-weight: 640; letter-spacing: .04em;
             text-transform: uppercase; color: var(--acc); }
.co-h { margin: 0 0 2px; font-size: 26px; line-height: 1.15; letter-spacing: -.02em; font-weight: 700; }
.co-sub { margin: 0; font-size: 13.5px; color: var(--ink2); }

.co-sum { display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
          margin: 18px 0 4px; padding: 14px 16px; border-radius: 14px;
          background: var(--sink); border: 1px solid var(--line); }
.co-sum-l { font-size: 13.5px; color: var(--ink1); }
.co-sum-p { font-size: 22px; font-weight: 700; letter-spacing: -.02em; }
.co-sum-p span { font-size: 12.5px; font-weight: 500; color: var(--ink2); margin-left: 5px; }
.co-note { margin: 8px 2px 0; font-size: 12.5px; color: var(--ink2); }

/* Die Pflichthaken sind der Grund, warum der Knopf nicht reagiert — sie
   muessen gross genug sein, dass man sie nicht uebersieht. Ganze Zeile klickbar. */
.co-check { display: flex; gap: 11px; align-items: flex-start; margin: 12px 0 0;
            padding: 13px 14px; border: 1px solid var(--line); border-radius: 13px;
            background: var(--glass3); cursor: pointer; font-size: 13px; line-height: 1.5; color: var(--ink1); }
.co-check:hover { border-color: var(--accLine); }
.co-check input { width: 19px; height: 19px; flex: 0 0 auto; margin: 0; accent-color: var(--acc); cursor: pointer; }
.co-check a { color: var(--acc); }
.co-go { width: 100%; justify-content: center; margin-top: 16px; }
.co-foot { margin: 14px 2px 0; font-size: 12px; color: var(--ink3); }
.co-links { margin: 18px 0 0; text-align: center; font-size: 12.5px; color: var(--ink3); }
.co-links a { color: var(--ink2); }
/* Handy-Download: ein Feld und ein Knopf (2026-10-13). Auf schmalen Schirmen untereinander. */
.co-label { display: block; margin: 16px 0 6px; font-size: 13px; font-weight: 600; color: var(--ink1); }
.co-zeile { display: flex; gap: 10px; flex-wrap: wrap; }
.co-feld { flex: 1 1 220px; min-width: 0; height: 46px; padding: 0 14px; border: 1px solid var(--line); border-radius: 12px;
  background: var(--surface); color: var(--ink); font: 400 16px/1.2 var(--font); }
.co-feld:focus { outline: 2px solid var(--accLine); outline-offset: 1px; border-color: var(--acc); }
.co-zeile .btn { flex: 0 0 auto; height: 46px; }
.co-oder { margin: 18px 0 10px; font-size: 12.5px; color: var(--ink3); text-transform: uppercase; letter-spacing: .08em; }
.co-senden + .co-msg { margin: 12px 0 0; }
.co-fern { position: fixed; left: -9999px; top: 0; opacity: 0; }
@media (max-width: 480px) { .co-zeile .btn { flex: 1 1 100%; justify-content: center; } }
.co-msg { margin: 0 0 14px; padding: 11px 13px; border-radius: 12px; font-size: 13px;
          background: color-mix(in oklab, var(--acc) 10%, transparent);
          border: 1px solid var(--accLine); color: var(--ink1); }

/* Geraetezeilen auf der Server-Seite */
.co-dev { display: flex; align-items: center; justify-content: space-between; gap: 12px;
          padding: 12px 0; border-top: 1px solid var(--line); font-size: 13.5px; }
.co-dev form { margin: 0; }
.co-inline { display: inline; margin: 0; }

@media (max-width: 560px) { .co-card { padding: 20px 18px; } .co-h { font-size: 22px; } }

/* Scribe price section: the "Recommended" tag of the middle tier sits ABOVE its card and
   touched the One-time / Yearly switch (Adrian, 2026-10-02) — only the gap changes here. */
.buy-switch + .tiers { margin-top: 46px; }

/* ------------------------------------------------------------ note pages ---
   The small pages the server builds itself — an OAuth result, "e-mail confirmed",
   carrying out a cancellation, "page not found": one centred card, the mark, one
   serif line, one sentence, at most one button. */
.note-page { min-height: 100vh; min-height: 100svh; display: grid; place-items: center; padding: 24px; }
.note-card { width: 100%; max-width: 440px; padding: 34px 30px 30px; text-align: center; }
.note-logo { display: block; width: 44px; height: 44px; margin: 0 auto 18px; }
.note-h { font-size: clamp(26px, 5vw, 32px); line-height: 1.08; letter-spacing: -.024em; margin-bottom: 12px; }
.note-p { color: var(--ink2); font-size: 15px; line-height: 1.6; }
.note-card b { color: var(--ink); font-weight: 600; }
.note-card .btn { margin-top: 20px; }

/* ---------------------------------------------------------------- motion ---
   ⚠️ "Hidden until seen" holds ONLY while site.js is alive: it puts .js on <html> first thing
   (it loads in <head>, so nothing flashes). Before 2026-10-03 the hiding was unconditional —
   with the script blocked or failing to load, every section below the hero stayed invisible.
   Now a page without the script is simply all there. */
.js .rise { opacity: 0; transform: translateY(26px); transition: opacity .7s var(--ease), transform .7s var(--ease); }
.rise.seen { opacity: 1; transform: none; }
/* children arrive one after another, so a row of cards reads left to right */
.js .rise-stagger > * { opacity: 0; transform: translateY(26px) scale(.985); transition: opacity .65s var(--ease), transform .65s var(--ease); }
.rise-stagger.seen > * { opacity: 1; transform: none; }
.rise-stagger.seen > *:nth-child(1) { transition-delay: .02s; }
.rise-stagger.seen > *:nth-child(2) { transition-delay: .11s; }
.rise-stagger.seen > *:nth-child(3) { transition-delay: .2s; }
.rise-stagger.seen > *:nth-child(4) { transition-delay: .24s; }
.rise-stagger.seen > *:nth-child(5) { transition-delay: .32s; }
.rise-stagger.seen > *:nth-child(6) { transition-delay: .4s; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    transition-duration: .001ms !important;
  }
  .js .rise, .js .rise-stagger > * { opacity: 1; transform: none; }
}

/* "Was ist neu" auf der Download-Seite — gefuellt aus dem Update-Feed (site.js).
   Bleibt leer und per `hidden` unsichtbar, wenn der Build keine Release-Notes
   mitgibt; ein Kasten mit Ueberschrift und ohne Inhalt sieht nach Fehler aus. */
.dl-notes { margin-top: 18px; padding: 14px 16px; border: 1px solid var(--line); border-radius: 12px; max-width: 520px; }
.dl-notes h3 { margin: 0 0 8px; font-size: .95rem; font-weight: 600; }
.dl-notes ul { margin: 0; padding-left: 18px; }
.dl-notes li { font-size: .9rem; line-height: 1.55; color: var(--muted); }
.dl-notes li + li { margin-top: 4px; }

/* ---------------------------------------------------------------- handy ---
   Nachgemessen 2026-09-28 mit echten Handy-Groessen (320 / 375 / 390 / 412 px). */
@media (max-width: 900px) {
  /* Fusszeilen-Links waren 13 px hoch — daneben tippen war die Regel. */
  .foot-links { gap: 0 18px; }
  .foot-links a, .foot-links button { padding: 9px 0; }
  .l-footer-links a { display: inline-block; padding: 6px 0; }
}
/* iOS vergroessert die ganze Seite, sobald man in ein Feld mit weniger als 16 px
   Schrift tippt — und zoomt danach nicht zurueck. Betraf Anmeldung, Kuendigung und
   Konto (14 px). `!important`, weil einige Seiten ihre Felder im eigenen <style>
   kleiner setzen; gilt nur fuer Finger-Geraete, am PC bleibt alles wie es ist. */
@media (pointer: coarse) {
  input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="file"]),
  select, textarea { font-size: 16px !important; }
}
