/* Millions4.earth · Brief design system
   ─────────────────────────────────
   editorial / civic / serif — feels like a permanent letter to politics.
   Design tokens from design_handoff_brief/README.md §3, themes.brief.
*/

@import url("/assets/fonts/_fonts.css");

/* HTML5 hidden-Attribut respektieren auch wenn ein eigenes CSS display:
   flex/grid/block setzt — sonst verliert man die "Hide-via-attribute"-
   Semantik (z.B. data-show-if-* Pattern). Frank 2026-05-21. */
[hidden] { display: none !important; }

:root {
    /* colours ─────────────────────────────────────────────────────────── */
    --bg:          #f3ece0;   /* warm cream — between pages */
    --paper:       #faf6ec;   /* main reading surface       */
    --ink:         #1c1812;   /* body text, primary buttons */
    --ink-soft:    #6b5e4a;   /* secondary, captions        */
    --rule:        #d8cdb6;   /* hairlines, dividers        */
    --map-nodata:  var(--rule); /* Karte „keine Daten" — Light = --rule (#76)  */
    --accent:      #b8541a;   /* clay — primary accent      */
    --accent-2:    #2d5a3d;   /* forest — confirmation only */
    --accent-soft: #ebd7c1;   /* tint of accent             */

    /* typography ──────────────────────────────────────────────────────── */
    /* Font-Fallback-Stack 23.05.2026: Noto-Familien fuer non-Latin Skripte
     * (Beta-Wave ar/fa/he/sd/hi/as/kn/ja/zh-CN). Browser waehlt automatisch
     * via @font-face unicode-range — englische Leser laden KEIN Arabisch. */
    --font-head: "Source Serif 4", "Source Serif Pro", "Noto Sans Arabic", "Noto Sans Hebrew", "Noto Sans Devanagari", "Noto Sans Kannada", "Noto Sans SC", "Noto Sans JP", Georgia, "Times New Roman", serif;
    --font-body: "Inter", "Noto Sans Arabic", "Noto Sans Hebrew", "Noto Sans Devanagari", "Noto Sans Kannada", "Noto Sans SC", "Noto Sans JP", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
    --font-mono: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;

    /* geometry ────────────────────────────────────────────────────────── */
    --radius: 2px;
    --rule-weight: 1px;
    --max-content: 64rem;
    --max-headline: 760px;
    --max-lede: 620px;
}

/* ── Brief · Dark ─────────────────────────────────────────────────────── */
:root[data-mode="dark"],
:root[data-theme="brief"][data-mode="dark"] {
    --bg:          #1a1612;
    --paper:       #221d17;
    --ink:         #f1ead8;
    --ink-soft:    #aa9c83;
    --rule:        #463b2c;
    /* #76 (Stefan): „keine Daten"-Regionen fielen im Dark Mode auf var(--rule)
       (dunkelgrün) → wirkten schwarz + wie Höchst-Dichte. Eigenes neutrales,
       desaturiertes Grau (R≈G≈B) liest sich klar als „keine Daten" und hebt
       sich von der grünen Dichteskala ab. Gilt für alle Dark-Themes (dieser
       Block matcht :root[data-mode="dark"]; frisch-dark erbt ihn). */
    --map-nodata:  #3e423e;
    --accent:      #e07636;
    --accent-2:    #5c9b76;
    --accent-soft: #3a2b1d;
    color-scheme: dark;
}

/* ── Plakat · Light ───────────────────────────────────────────────────── */
:root[data-theme="plakat"] {
    --bg:          #ece7df;
    --paper:       #f7f3eb;
    --ink:         #0a0a08;
    --ink-soft:    #4a4944;
    --rule:        #0a0a08;
    --accent:      #e84a1f;
    --accent-2:    #f5c84e;
    --accent-soft: #fce0d4;
    --font-head: "Archivo", "Archivo Black", "Noto Sans Arabic", "Noto Sans Hebrew", "Noto Sans Devanagari", "Noto Sans Kannada", "Noto Sans SC", "Noto Sans JP", system-ui, sans-serif;
    --font-body: "Archivo", "Noto Sans Arabic", "Noto Sans Hebrew", "Noto Sans Devanagari", "Noto Sans Kannada", "Noto Sans SC", "Noto Sans JP", system-ui, sans-serif;
    --radius: 0;
    --rule-weight: 2px;
}

/* ── Plakat · Dark ────────────────────────────────────────────────────── */
:root[data-theme="plakat"][data-mode="dark"] {
    --bg:          #0a0a08;
    --paper:       #131311;
    --ink:         #f7f3eb;
    --ink-soft:    #c1bdb2;
    --rule:        #f7f3eb;
    --accent:      #ff6638;
    --accent-2:    #f5c84e;
    --accent-soft: #2a1810;
    color-scheme: dark;
}

/* ── Frisch · Light (third theme) ─────────────────────────────────────
   Grünes Theme aus Frisch.html — sage page, deep forest ink, fresh leaf
   accent. Uses display sans (Bricolage Grotesque) for headings instead of
   serif, with a lime underline accent and rounded card surfaces. */
:root[data-theme="frisch"] {
    --bg:          #eef3e7;
    --paper:       #ffffff;
    --paper-2:     #f7faf3;
    --ink:         #0d2818;
    --ink-soft:    #4a6655;
    --rule:        #cfdcc1;
    --rule-soft:   #e3ead8;
    --accent:      #2d8a52;
    --accent-2:    #b8d432;
    --accent-soft: #d4e8d8;
    --accent-ink:  #0b3a22;
    --accent-warm: #c4541a;
    color-scheme: light;
}

:root[data-theme="frisch"][data-mode="dark"] {
    --bg:          #0d2818;
    --paper:       #15321f;
    --paper-2:     #1b3a25;
    --ink:         #eef3e7;
    --ink-soft:    #9ab39d;
    --rule:        #2d4a37;
    --rule-soft:   #1f3b29;
    --accent:      #4caf6f;
    --accent-2:    #cbeb56;
    --accent-soft: #1d3d28;
    --accent-ink:  #d4e8d8;
    --accent-warm: #e07636;
    color-scheme: dark;
}

/* Frisch decorative tweaks — sans-display headings, pill buttons, rounded sage cards */
:root[data-theme="frisch"] {
    --font-head: "Bricolage Grotesque", "Inter", "Noto Sans Arabic", "Noto Sans Hebrew", "Noto Sans Devanagari", "Noto Sans Kannada", "Noto Sans SC", "Noto Sans JP", system-ui, sans-serif;
    --font-body: "Public Sans", "Inter", "Noto Sans Arabic", "Noto Sans Hebrew", "Noto Sans Devanagari", "Noto Sans Kannada", "Noto Sans SC", "Noto Sans JP", system-ui, sans-serif;
}
:root[data-theme="frisch"] h1, :root[data-theme="frisch"] h2, :root[data-theme="frisch"] h3,
:root[data-theme="frisch"] .counter-num, :root[data-theme="frisch"] .dashboard-greeting {
    font-family: var(--font-head); font-weight: 600; font-style: normal;
    letter-spacing: -0.025em;
}
:root[data-theme="frisch"] .lede        { font-style: normal; font-weight: 400; }
:root[data-theme="frisch"] .wordmark    { font-family: var(--font-head); font-weight: 600; letter-spacing: -0.01em; text-transform: none; }
:root[data-theme="frisch"] .wordmark__accent { color: var(--accent); }
:root[data-theme="frisch"] .kicker      { color: var(--accent); }
:root[data-theme="frisch"] .button {
    border-radius: 999px; background: var(--accent); color: #fff;
    border: none; font-weight: 600; text-transform: none; letter-spacing: 0;
    box-shadow: 0 6px 20px rgba(45,138,82,0.3);
    transition: transform 0.15s, box-shadow 0.15s;
}
:root[data-theme="frisch"] .button:hover { transform: translateY(-1px); box-shadow: 0 8px 24px rgba(45,138,82,0.4); }
:root[data-theme="frisch"] .button--outline {
    background: transparent; color: var(--ink);
    border: 1.5px solid var(--ink); box-shadow: none;
}
:root[data-theme="frisch"] .counter-strip {
    background: var(--paper-2);
    border-top: 1px solid var(--rule-soft); border-bottom: 1px solid var(--rule-soft);
}
:root[data-theme="frisch"] .counter-num {
    font-size: clamp(72px, 11vw, 140px); line-height: 0.85; letter-spacing: -0.045em;
}
:root[data-theme="frisch"] .invite-hero,
:root[data-theme="frisch"] .both-and__col,
:root[data-theme="frisch"] .petition-excerpt {
    background: var(--paper-2); border: 1px solid var(--rule-soft);
    border-radius: 18px;
}
/* Frisch macht aus diesen Elementen sichtbare Karten — also brauchen sie
   auch Karten-Padding rundum. Ohne diesen Override erbt .both-and__col nur
   `padding-top:16px` aus dem Base-Stil, dann klebt der Text am unteren und
   rechten/linken Karten-Rand. .petition-excerpt hat im Base gar kein
   Padding. .invite-hero behält sein eigenes clamp-Padding. */
:root[data-theme="frisch"] .both-and__col {
    padding: 28px 24px !important;
    border-top: 1px solid var(--rule-soft);
}
/* petition-excerpt ist KEIN Karten-Element wenn es als `<section class="section petition-excerpt">`
   genutzt wird — die Section liefert das normale Page-Inset. Frank-Feedback
   17.05.2026: der Text soll im gleichen Inset wie der Rest sitzen, der
   Background darf full-bleed bleiben. Background-Override via :where()-Selector
   damit das border-radius nur greift, wenn petition-excerpt NICHT als section
   gerendert wird (sonst sieht der grüne Balken zwischen rule-top/-bottom korrekt
   eckig aus). */
:root[data-theme="frisch"] .section.petition-excerpt {
    border-radius: 0;
    border-inline-start: none;
    border-inline-end: none;
}
@media (min-width: 720px) {
    :root[data-theme="frisch"] .both-and__col { padding: 32px 30px !important; }
}
:root[data-theme="frisch"] .section--bg { background: var(--paper-2); }
:root[data-theme="frisch"] .pill.is-active {
    background: var(--accent-soft); border-color: var(--accent); color: var(--accent-ink);
}
:root[data-theme="frisch"] .map-frame {
    background: var(--accent-soft); border-color: var(--rule); border-radius: 18px; padding: 16px;
}
:root[data-theme="frisch"] .map-toggle button {
    border-radius: 999px; padding: 8px 14px; border: 1.5px solid var(--rule);
    background: var(--paper);
}
:root[data-theme="frisch"] .map-toggle button.is-active {
    background: var(--ink); color: var(--paper); border-color: var(--ink);
}
:root[data-theme="frisch"] body.page > .footer-strip,
:root[data-theme="frisch"] .footer-strip {
    background: var(--ink); color: #b8c4bc;
}
:root[data-theme="frisch"] .footer-strip a { color: #e0eadd; }
:root[data-theme="frisch"] .footer-strip a:hover { color: var(--accent-2); }
/* #69 (Stefan 05.06.2026): Im frisch-Darkmode invertiert `background:var(--ink)`
   zu HELL (#eef3e7), die Footer-Links sind aber hartcodiert hell (#e0eadd) →
   hell auf hell, Impressum/Datenschutz unsichtbar. Footer im Darkmode bewusst
   DUNKEL halten (fester Wert, invertiert nicht); die hellen Links + #b8c4bc-Text
   bleiben dann lesbar. Betrifft den ganzen Footer, nicht nur die Legal-Links. */
:root[data-theme="frisch"][data-mode="dark"] body.page > .footer-strip,
:root[data-theme="frisch"][data-mode="dark"] .footer-strip {
    background: #12301d;
}
/* Der gedämpfte Tagline-Span (opacity .6) käme auf #12301d nur auf ~3,95:1
   (unter WCAG-AA für den 11px-Text) — im Darkmode leicht anheben → ~5,3:1. */
:root[data-theme="frisch"][data-mode="dark"] .footer-strip__muted { opacity: .78; }

/* Frisch · Hero — radial leaf-soft glow top-right + lime underline on h1 */
:root[data-theme="frisch"] .hero {
    background:
        radial-gradient(ellipse at top right, var(--accent-soft) 0%, transparent 60%),
        var(--paper);
    position: relative; overflow: hidden;
}
:root[data-theme="frisch"] .hero h1 {
    background-image: linear-gradient(
        transparent 78%,
        var(--accent-2) 78%, var(--accent-2) 96%,
        transparent 96%
    );
    background-repeat: no-repeat;
    background-size: 100% 100%;
    padding: 0 4px;
    display: inline; /* gradient hugs the actual text bounds */
}

/* Frisch · Pillars — Roman-numerals als kompakte Karten mit Erklärung */
:root[data-theme="frisch"] .pillars__item {
    border: 1px solid var(--rule-soft); border-radius: 10px;
    padding: 16px 20px;
    background: var(--paper);
    transition: border-color 0.2s, transform 0.2s;
    align-items: center;
}
:root[data-theme="frisch"] .pillars__item:last-child { padding-bottom: 16px; }
:root[data-theme="frisch"] .pillars__item:hover {
    border-color: var(--accent); transform: translateY(-2px);
}
:root[data-theme="frisch"] .pillars__num {
    font-family: var(--font-head); font-weight: 600;
    font-size: 40px; line-height: 0.9; letter-spacing: -0.04em;
    color: var(--accent);
    min-width: 1.4em;
}
:root[data-theme="frisch"] .pillars__label {
    font-family: var(--font-head); font-weight: 600;
    font-size: 17px; letter-spacing: -0.01em; color: var(--ink);
    font-style: normal;
}
:root[data-theme="frisch"] .pillars__desc {
    font-size: 13.5px; color: var(--ink-soft); line-height: 1.5;
}

/* Frisch · Counter strip — keine ::after-Deko mehr.
   Frank-Wunsch 2026-05-22: die statische 4%-gefuellte Pseudo-Bar ist durch
   eine echte Meilenstein-Bar ersetzt (siehe .counter-milestone-bar unten).
   Diese Regel bleibt nur als Layout-Anker fuer relative-positioniertes
   Innen-Element falls noch jemand drauf positioniert. */
:root[data-theme="frisch"] .counter-strip {
    position: relative;
}

/* Frisch · Stats — featured card in leaf-grün, others in white sage cards */
:root[data-theme="frisch"] .stats-counters > div {
    background: var(--paper); border: 1px solid var(--rule-soft);
    border-radius: 10px; padding: 18px 20px !important;
}
:root[data-theme="frisch"] .stats-counters > div:first-child {
    background: var(--accent); color: #fff; border-color: var(--accent);
}
:root[data-theme="frisch"] .stats-counters > div:first-child .counter-num {
    color: #fff;
}
:root[data-theme="frisch"] .stats-counters > div:first-child .counter-label {
    color: rgba(255,255,255,0.85);
}

/* Frisch · Map anonymity-note as leaf-soft strip */
:root[data-theme="frisch"] .k-anon-note,
:root[data-theme="frisch"] .map-progress {
    background: var(--accent-soft);
    border-inline-start: 3px solid var(--accent);
    border-radius: 6px;
    color: var(--accent-ink);
}

/* ── Plakat-specific decorative tweaks (apply in both modes) ─────────── */
/* Critique #01: wordmark stays canonical "Millions4.earth" mixed-case in every
   theme — only weight & letter-spacing change between Brief / Plakat /
   Frisch. The mono uppercase variant lives only in technical contexts
   (e.g. footer signature), never as the primary mark. */
:root[data-theme="plakat"] .wordmark        { font-weight: 900; letter-spacing: -0.02em; text-transform: none; }
:root[data-theme="plakat"] .kicker          { font-weight: 700; font-family: var(--font-body); }
/* Plakat headings: heavy weight + tight tracking only — no forced uppercase
   (siehe `feedback-no-uppercase-headings`). Brutalität kommt aus weight, nicht aus caps. */
:root[data-theme="plakat"] h1, h2, h3,
:root[data-theme="plakat"] .counter-num,
:root[data-theme="plakat"] .dashboard-greeting { font-weight: 900; letter-spacing: -0.025em; font-style: normal; }
:root[data-theme="plakat"] .lede            { font-style: normal; font-weight: 500; }
:root[data-theme="plakat"] .pillars__num    { font-weight: 900; }
:root[data-theme="plakat"] .button          { font-weight: 700; letter-spacing: 0.04em; }
:root[data-theme="plakat"] .map-frame svg [data-iso]:not([style]) { stroke-width: 1; }

/* Plakat-Dark: header → page sections need a visible divider, otherwise
   it all reads as one black plane. */
:root[data-theme="plakat"][data-mode="dark"] .site-header { border-bottom: 1px solid var(--rule); padding-bottom: 16px; }
:root[data-theme="plakat"][data-mode="dark"] .lang-suggest { border-bottom: 1px solid var(--ink-soft); }

/* The "Teilen" outline button on the accent-soft invite-hero loses contrast
   in Plakat-Dark; restore by inverting it explicitly. */
:root[data-theme="plakat"][data-mode="dark"] .invite-block--big button[data-share] {
    background: var(--paper); color: var(--ink); border-color: var(--paper);
}
:root[data-theme="plakat"][data-mode="dark"] .invite-block--big button[data-share]:hover {
    background: var(--accent); color: var(--paper); border-color: var(--accent);
}

/* The invite-hero accent-soft contrast in Plakat-Dark is very low against
   the black page; bump the border to ink-soft so the box reads as separate. */
:root[data-theme="plakat"][data-mode="dark"] .invite-hero {
    border-top-color: var(--ink-soft);
    border-bottom-color: var(--ink-soft);
}

/* Default light scheme; the dark variants opt in via [data-mode="dark"]. */
html { color-scheme: light; background: var(--ink); }
body { background: var(--paper); min-height: 100vh; }
/* Schutz gegen 1-2px horizontale Scrollbar wenn invite-hero `width:100vw`
   nutzt (100vw inkludiert die Scrollbar-Breite). Frank-Fix 18.05.2026. */
html, body { overflow-x: hidden; }

* { box-sizing: border-box; }

html, body {
    margin: 0; padding: 0;
    /* Zweischichtiges Background-Modell (Bug-Fix 18.05.2026 abend):
       - html  = ink: nur fuer Overscroll/Underfooter sichtbar
       - body  = paper + min-height:100vh: die Hauptflaeche, faengt auch
                 kurze Pages bis Viewport-Bottom ab
       - .footer-strip ist eh ink → passt zum overscrolling html
       Vorher hatte body selbst ink-bg. Das funktionierte auf der Home-
       Seite (deren Sections sind full-bleed), aber auf Content-Seiten
       (handeln/stats/map) hat main.section max-width:1180px — links/
       rechts neben der Reading-Column schimmerte der ink-body durch
       und sah aus wie "Footer-Farbe oben am Rand" (Frank-Bericht). */
    color: var(--ink);
    font-family: var(--font-body);
    font-size: 16px;
    line-height: 1.55;
    text-rendering: optimizeLegibility;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    font-feature-settings: "ss01", "cv11";
}

::selection { background: var(--accent-soft); color: var(--ink); }

/* typography defaults ─────────────────────────────────────────────────── */
h1, h2, h3, h4, h5 {
    font-family: var(--font-head);
    font-weight: 500;
    color: var(--ink);
    margin: 0;
}
h1 {
    font-size: clamp(36px, 6.4vw, 56px);
    line-height: 1.05;
    letter-spacing: -0.02em;
    max-width: var(--max-headline);
}
h2 {
    font-size: clamp(22px, 3.4vw, 28px);
    line-height: 1.2;
    font-style: italic;
}
h3 {
    font-size: 18px;
    line-height: 1.25;
}
p { margin: 0 0 1em; max-width: var(--max-lede); }
.lede {
    font-family: var(--font-head);
    font-size: clamp(16px, 2.1vw, 19px);
    font-style: italic;
    color: var(--ink);
    max-width: var(--max-lede);
    line-height: 1.5;
    margin: 0 0 22px;
}

a {
    color: var(--accent);
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 4px;
}
a:hover { text-decoration-thickness: 2px; }
a:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: var(--radius);
}

/* mono kickers ────────────────────────────────────────────────────────── */
.kicker {
    font-family: var(--font-mono);
    font-size: 11px;
    letter-spacing: 0.16em;
    color: var(--accent);
    font-weight: 400;
    display: inline-block;
}
.kicker--soft { color: var(--ink-soft); }

.mono { font-family: var(--font-mono); }
.italic { font-style: italic; }

/* wordmark — Pulse-Globe Logo System (Design Handoff 17.05.2026) ──────────
   Konstruktion: "Millions" + italic "4" + Globe-SVG (statt Punkt) + "earth"
   Theme-driven: Globe-SVG wird per CSS pro [data-theme][data-mode] gewechselt.
   Italic-4: nur im Brief-Theme markenrechtlich distinktiv, bleibt italic.
   Frank-Bestätigung 17.05.2026: KEINE Großbuchstaben, auch im Plakat-Wordmark
   nicht — Designer-Brief wird hier zugunsten der Memory-Regel übergangen. */
.wordmark {
    display: inline-flex;
    align-items: baseline;
    gap: 0;
    font-family: var(--font-head);
    font-weight: 600;
    letter-spacing: -0.01em;
    color: var(--ink);
    text-decoration: none;
    font-size: 24px;
}
.wordmark__text { display: inline; }
.wordmark__four { font-style: normal; font-weight: inherit; }
.wordmark__globe {
    display: inline-block;
    width: 0.95em; height: 0.95em;
    background-image: url('/assets/logo/globe-brief-light.svg');
    background-repeat: no-repeat;
    background-position: center;
    background-size: contain;
    margin: 0 0.04em;
    align-self: center;
    flex-shrink: 0;
}
/* Brief: italic 4, markenrechtlich distinktives Detail */
:root[data-theme="brief"] .wordmark__four,
:root:not([data-theme]) .wordmark__four { font-style: italic; }
/* Per-Theme + per-Mode Globe-SVG */
:root[data-theme="brief"][data-mode="dark"] .wordmark__globe { background-image: url('/assets/logo/globe-brief-dark.svg'); }
:root[data-theme="plakat"] .wordmark__globe { background-image: url('/assets/logo/globe-plakat.svg'); }
:root[data-theme="frisch"][data-mode="light"] .wordmark__globe,
:root[data-theme="frisch"]:not([data-mode]) .wordmark__globe { background-image: url('/assets/logo/globe-frisch-light.svg'); }
:root[data-theme="frisch"][data-mode="dark"] .wordmark__globe { background-image: url('/assets/logo/globe-frisch-dark.svg'); }
:root[data-theme="terminal"][data-mode="light"] .wordmark__globe { background-image: url('/assets/logo/globe-terminal-light.svg'); }
:root[data-theme="terminal"][data-mode="dark"] .wordmark__globe { background-image: url('/assets/logo/globe-terminal-dark.svg'); }
/* Bei prefers-color-scheme:dark als Fallback wenn kein data-mode gesetzt */
@media (prefers-color-scheme: dark) {
    :root[data-theme="brief"]:not([data-mode]) .wordmark__globe { background-image: url('/assets/logo/globe-brief-dark.svg'); }
    :root[data-theme="frisch"]:not([data-mode]) .wordmark__globe { background-image: url('/assets/logo/globe-frisch-dark.svg'); }
    :root[data-theme="terminal"]:not([data-mode]) .wordmark__globe { background-image: url('/assets/logo/globe-terminal-dark.svg'); }
}
/* Legacy: alter wordmark__accent-Span existiert nicht mehr im HTML, aber
   für Rückwärtskompatibilität (falls irgendwo noch zwischengespeichert) */
.wordmark__accent { color: var(--accent); display: none; }

/* layout primitives ──────────────────────────────────────────────────── */
/* .page (= <body class="page">) liefert die Bühne. Background wird in
   body.page weiter unten auf ink gesetzt, damit der Bereich UNTER dem
   Footer (Overscroll, kurze Pages) nicht weiß durchblitzt. Die inhalts-
   tragenden Elemente (.section, .site-header, .dashboard-page) bekommen
   explizit paper, sodass der ink nur am Body-Ende sichtbar wird.
   Frank-Bug 18.05.2026 (auf allen Seiten außer Dashboard war der weiße
   Streifen weiter sichtbar — paper-Override aus .page hatte gewonnen). */
.page { min-height: 100vh; }
.site-header { background: var(--paper); }

/* Share-Icons (Brand-Logos im Share-Sheet + prominenten Buttons).
   Inline-vertical-Alignment + leichter Abstand zum Label. Emoji-Fallback
   (✉, 🔗, 🐦) bekommt gleiche Größe. */
.share-icon {
    display: inline-block;
    vertical-align: -0.2em;
    width: 1.15em;
    height: 1.15em;
    margin-inline-end: 4px;
    line-height: 1;
}
img.share-icon { object-fit: contain; }
.section {
    /* Frank-Feedback 2026-05-21 (4): alles auf 1180px-Lese-Spalte vereinheitlichen,
       Header inkludiert. Vorher: Header voll-bleed, Content zentriert → Frank:
       "die anderen sind beim Header falsch". Jetzt: gleiche Geometrie ueberall.
       Background bleibt voll-bleed (kein max-width), Content sitzt auf 1180px
       zentriert. Auf Mobile gewinnt clamp(22,7vw,80) als Padding. */
    padding-block: clamp(28px, 5vw, 56px);
    padding-inline: max(clamp(22px, 7vw, 80px), calc((100% - 1180px) / 2));
    background: var(--paper);
}
.section--bg { background: var(--bg); }
/* Stats-Counter-Strip: gleiche Logik wie invite-hero — Background-Band geht
   über die volle Viewport-Breite, Counter-Cards bleiben im Content-Inset.
   !important auf padding-inline weil stats.php ein inline `padding:24px 0`
   am Element hat; das overridet sonst die CSS-Regel. Frank-Feedback 18.05.2026. */
main.section > .stats-counters {
    width: 100vw;
    margin-inline: calc(50% - 50vw);
    padding-block: 24px !important;
    padding-inline: max(
        clamp(22px, 7vw, 80px),
        calc((100vw - 1180px) / 2 + clamp(22px, 7vw, 80px))
    ) !important;
    /* #148 (Stefan): feste responsive Spalten statt auto-fit. Die 4 Metrik-
       Kacheln liefen auf iPad-Portrait (~768-810px) in ein hässliches 3+1
       („heute" allein in Reihe 2). Jetzt: 2×2 auf Tablet, 4 ab Desktop, 1 auf
       schmalen Handys — nie 3+1. (auto-fit-Spalten aus dem stats.php-Inline-
       Style entfernt, damit diese Regel greift.) */
    grid-template-columns: 1fr 1fr;
}
@media (max-width: 539px) {
    main.section > .stats-counters { grid-template-columns: 1fr; }
}
@media (min-width: 900px) {
    main.section > .stats-counters { grid-template-columns: repeat(4, 1fr); }
}
.section--ink { background: var(--ink); color: var(--paper); }
.rule-top    { border-top: var(--rule-weight) solid var(--rule); }
.rule-bottom { border-bottom: var(--rule-weight) solid var(--rule); }
.stack > * + * { margin-top: 18px; }

/* header / nav ──────────────────────────────────────────────────────────
   Frank-Wunsch 19.05.2026: Lang-Switcher + Mode-Toggle sollen rechts am
   Content-Reading-Column-Rand andocken, nicht am Viewport-Rand. Der
   Header bekommt deshalb dasselbe Layout-Constraint wie main.section
   (max-width:1180px, margin:0 auto). Stripe (= paper-Hintergrund)
   bleibt voll-bleed via parent body.page → paper. */
.site-header {
    display: flex; align-items: center; justify-content: space-between;
    gap: 16px; flex-wrap: wrap;
    /* Frank-Feedback 2026-05-21 (4): Header bekommt denselben Lese-Spalten-
       Trick wie .section und .dashboard-page. Damit liegen Logo links und
       Profil-Chip rechts auf exakt der gleichen Achse wie der Content
       jeder Page — Header passt jetzt zu allen Page-Layouts. */
    padding-top: clamp(20px, 3vw, 32px);
    padding-bottom: 0;
    padding-inline: max(clamp(22px, 7vw, 80px), calc((100% - 1180px) / 2));
}
/* Frank-Feedback 2026-05-21: align-items: center (vorher baseline → Logo,
   Nav und Extras hingen auf drei verschiedenen Linien). */
.primary-nav {
    /* #134/#139 (22.06.): 6 Menüpunkte + längeres „Unterstützende" + (für
       eingeloggte Admins) der Profil-Chip sprengten die 1180er-Lesespalte und
       die Sprach-/Mode-Gruppe brach hässlich in Zeile 2. gap 28→16 + flex-wrap
       am nav selbst (statt am Header die Extras umzubrechen) hält es kompakt;
       reicht der Platz wirklich nicht, umbrechen die Nav-Links sauber rechts. */
    display: flex; flex-wrap: wrap; gap: 16px 18px; justify-content: flex-end;
    font-family: var(--font-body);
    font-size: 14px;
}
.primary-nav a {
    color: var(--ink-soft);
    text-decoration: none;
}
.primary-nav a:hover,
.primary-nav a.is-active {
    color: var(--ink);
    text-decoration: underline;
    text-decoration-color: var(--accent);
    text-underline-offset: 4px;
}

.lang-switch select {
    font-family: var(--font-mono);
    font-size: 11px;
    letter-spacing: 0.12em;
    /* Frank-Feedback 2026-05-21: rechts mehr Platz fuer den nativen
       Caret/Dropdown-Pfeil — vorher 6px, der Pfeil wurde z.T. abgeschnitten.
       padding-right 20px laesst dem Browser-default-arrow genug Platz auf
       Chrome/Safari/Firefox. */
    padding: 4px 20px 4px 8px;
    background: transparent;
    border: 1px solid var(--rule);
    border-radius: var(--radius);
    color: var(--ink);
    cursor: pointer;
}

/* Beta-Label am Sprach-Umschalter (Frank 31.05.2026): nur fuer Nicht-DE-
   Sprachen. Dezentes Akzent-Badge, hilft per title-Tooltip ("noch in Arbeit").
   cursor:help signalisiert den Tooltip. */
.lang-beta {
    display: inline-block;
    margin-left: 6px;
    padding: 1px 6px;
    font-family: var(--font-mono);
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--accent);
    background: var(--accent-soft);
    border: 1px solid var(--accent);
    border-radius: var(--radius);
    cursor: help;
    vertical-align: middle;
    white-space: nowrap;
}

/* ── mode toggle (☼ ⇄ ☾) ────────────────────────────────────────────────
   Theme ist seit 19.05.2026 hartkodiert auf 'frisch'; nur Light/Dark
   ist noch user-toggleable. Gruppiert mit .lang-switch in .nav-extras. */
.nav-extras {
    display: inline-flex; gap: 8px; align-items: center;
}
.mode-switch {
    display: inline-flex; align-items: center;
    font-family: var(--font-mono);
}
.mode-toggle {
    background: transparent; color: var(--ink-soft);
    border: 1px solid var(--rule);
    border-radius: var(--radius);
    /* Reviewer-Feedback 2026-05-21: Toggle fuehlte sich wie Debug-UI an —
       11px-Schrift + 4/8-Padding war zu zaghaft fuer ein interaktives Element.
       Etwas mehr Atemluft + groessere Glyphen, ohne den Sprach-Switcher
       optisch zu ueberragen. */
    padding: 5px 10px;
    cursor: pointer;
    line-height: 1;
    font-family: inherit;
    font-size: 14px;
}
.mode-toggle:hover { color: var(--ink); border-color: var(--ink); }
.mode-toggle .m-light, .mode-toggle .m-dark { display: none; padding: 0 2px; }
.mode-toggle[data-active="light"] .m-dark { display: inline; }
.mode-toggle[data-active="dark"]  .m-light { display: inline; }
/* Falls noch ein altes data-theme-switch im Markup steckt (Cached HTML),
   nicht anzeigen — wird durch theme.js auch hidden gesetzt. */
[data-theme-switch] { display: none !important; }

/* hero ───────────────────────────────────────────────────────────────── */
.hero { padding-top: 48px; padding-bottom: 16px; }
.hero h1 { margin-top: 14px; margin-bottom: 22px; }
/* Hero-Head: Headline + Kicker nebeneinander (Flex), bei zu wenig Platz
   umbrechen — Kicker wandert dann unter die Headline.
   Frank-Wunsch 19.05.2026. */
.hero__head {
    display: flex;
    align-items: baseline;
    gap: 14px 22px;
    flex-wrap: wrap;
    justify-content: space-between;
}
/* H1 darf nicht wachsen — sonst dehnt sich die Frisch-Underline
   (background-image: linear-gradient) auf die ganze Flex-Item-Breite und
   der Strich laeuft weit ueber den Text hinaus (Bug 19.05.2026, Frank's
   Screenshot). flex:0 1 auto = "schrumpfen erlaubt, wachsen verboten,
   Basis = Inhalt", h1 ist damit text-breit. justify-content:space-between
   auf dem .hero__head schiebt den Kicker rechts an den Rand. */
.hero__head h1 { margin: 14px 0 0; flex: 0 1 auto; min-width: 0; }
.hero__head .hero__kicker {
    flex: 0 0 auto;
    align-self: baseline;
    margin-top: 18px;
}
@media (max-width: 480px) {
    .hero__head .hero__kicker { margin-top: 6px; }
}

/* counter strip ──────────────────────────────────────────────────────────
   Critique #10: this is the most important number on the page — the
   movement in one word. We give it twice the height (min 200 px), put
   the number at clamp(80–120 px) and weld the CTA to the SAME visual
   block on its right, so the eye-path is "X people are in → join now"
   without a horizontal split. */
/* Counter-Strip Layout (Tier D6, 2026-05-20, Frank-Feedback v3):
   Zwei-Spalten — links Counter + Invite-Hinweis, rechts Karte + Ticker.
   Auf Mobile: stacken (links zuerst, dann rechts). */
.counter-strip {
    display: flex; flex-wrap: wrap; align-items: start;
    gap: clamp(20px, 3vw, 40px);
    min-height: 200px;
    padding-block: clamp(28px, 4vw, 44px);
}
.counter-strip__left,
.counter-strip__right {
    flex: 1 1 320px; min-width: 0;
    display: flex; flex-direction: column;
}
.counter-strip__left { gap: 10px; justify-content: center; }
.counter-strip__right { gap: 14px; align-items: stretch; max-width: 460px; }
.counter-strip__map {
    width: 100%; max-width: 460px;
    aspect-ratio: 1010 / 497; /* Equal-Earth-Weltkarte (flächentreu, Afrika korrekt) */
    position: relative;
}
.counter-strip__map svg { width: 100%; height: 100%; display: block; }
/* Pause-Button unten rechts in jedem Karten-Panel — Frank-Wunsch 20.05.2026.
   Datenflug-Indikator: ⏸ wenn live, ▶ wenn pausiert. */
[data-map] { position: relative; }
.mp-live-pause {
    position: absolute; right: 6px; bottom: 6px;
    width: 28px; height: 28px;
    border: 1px solid var(--rule);
    background: var(--paper, var(--bg));
    color: var(--ink);
    font-family: var(--font-mono); font-size: 13px; line-height: 1;
    border-radius: 50%;
    cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    opacity: 0.6; transition: opacity 200ms ease-out, background 200ms ease-out;
}
.mp-live-pause:hover { opacity: 1; background: var(--bg, var(--paper)); }
.mp-live-pause[aria-pressed="true"] {
    background: var(--accent); color: var(--paper); border-color: var(--accent); opacity: 1;
}
.counter-strip__map .land,
.counter-strip__map path[data-iso],
.counter-strip__map polygon[data-iso] {
    fill: var(--map-nodata);
    stroke: var(--paper);
    stroke-width: 0.4;
}
@media (max-width: 760px) {
    .counter-strip__right { max-width: 100%; }
}
/* Counter-Schrift schrumpft im Personal-Counter-Modus, damit "Du + 7 deiner
   Kontakte + 3 weitere" nicht ueberfliesst wenn die Mini-Map daneben Platz
   nimmt. Frank-Wunsch 20.05.2026: "von Du+ weitere kann dann die Schrift
   kleiner werden". */
[data-counter-block-personal]:not([hidden]) .counter-num {
    font-size: clamp(40px, 5vw, 64px);
    line-height: 1.05;
    letter-spacing: -0.02em;
}

/* Meilenstein-Bar (Frank-Wunsch 2026-05-22): ersetzt den statischen
   Frisch-Theme-Deko-Strich. counter-live.js setzt die CSS-Variable
   --milestone-fill und das Label aus dem Total-Counter. Theme-agnostisch
   ueber CSS-Variablen — laeuft in Brief, Plakat, Frisch. */
.counter-milestone-bar {
    width: clamp(180px, 22vw, 280px);
    height: 8px;
    background: var(--rule-soft, var(--rule));
    border-radius: 999px;
    margin-top: 14px;
    overflow: hidden;
    position: relative;
}
.counter-milestone-bar__fill {
    height: 100%;
    width: var(--milestone-fill, 0%);
    background: linear-gradient(90deg, var(--accent), var(--accent-2, var(--accent)));
    border-radius: 999px;
    transition: width 600ms cubic-bezier(.22, 1, .36, 1);
}
.counter-milestone-bar__label {
    font-family: var(--font-mono);
    font-size: 12px;
    letter-spacing: 0.05em;
    color: var(--ink-soft);
    margin-top: 6px;
    margin-bottom: 0;
    min-height: 1.4em;
}
/* Meilenstein-Sprung: kurzer Brightness-Pulse beim Stufen-Crossing. */
.counter-milestone-bar.is-leveling-up .counter-milestone-bar__fill {
    animation: milestone-pop 800ms ease-out;
}
@keyframes milestone-pop {
    0%   { filter: brightness(1.0) saturate(1.0); }
    50%  { filter: brightness(1.4) saturate(1.35); }
    100% { filter: brightness(1.0) saturate(1.0); }
}
@media (prefers-reduced-motion: reduce) {
    .counter-milestone-bar__fill { transition: none; }
    .counter-milestone-bar.is-leveling-up .counter-milestone-bar__fill { animation: none; }
}
/* Mini-Activity-Ticker im counter-strip (Tier D6, 2026-05-20).
   Top-3 Klima-Aktionen aktuell — beantwortet "Was machen die Menschen?".
   Sitzt unter der Mini-Map im rechten Counter-Strip-Block. */
.counter-strip__ticker {
    width: 100%;
    text-align: start;
}
.counter-strip__ticker-kicker {
    font-family: var(--font-mono); font-size: 11px;
    letter-spacing: 0.14em; color: var(--ink-soft); text-transform: uppercase;
    display: block;
}
.counter-strip__ticker-list {
    list-style: none; padding: 0; margin: 6px 0 0;
    font-family: var(--font-head); font-size: 14px; line-height: 1.5;
}
.counter-strip__ticker-list li {
    padding: 4px 0; border-top: 1px solid var(--rule-soft, var(--rule));
    font-style: italic; color: var(--ink-soft);
    animation: mp-feed-in 360ms ease-out;
    transition: color 280ms ease-out;
    /* Frank-Bug 30.05. (Mini-Ticker analog .mp-live-feed__item): stable
       Höhe + ellipsis verhindert Hüpfen beim Rotate. */
    min-height: calc(2 * 1.5em + 8px);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* Top-Item = das aktive — visuell hervorgehoben, korrespondiert mit dem
   pulsierenden Karten-Punkt (highlightDot). */
.counter-strip__ticker-list li:first-child {
    border-top: 0;
    color: var(--accent);
    font-weight: 600;
}
.counter-strip__ticker-list .counter-strip__ticker-empty {
    color: var(--ink-soft); border: 0; animation: none; font-weight: 400;
}
.counter-num {
    font-family: var(--font-head);
    font-size: clamp(80px, 12vw, 120px);
    font-weight: 600;
    letter-spacing: -0.04em;
    color: var(--ink);
    line-height: 0.95;
    font-variant-numeric: tabular-nums;
    position: relative;
    transition: transform 0.4s cubic-bezier(.22,1,.36,1);
}
/* Live-pulse — counter-live.js adds .is-pulsing for ~600 ms after every
   incremental update; the small +1 chip rides on the top-right corner. */
.counter-num.is-pulsing { transform: translateY(-2px); }
.counter-pulse {
    position: absolute; top: 6px; right: -56px;
    font-family: var(--font-mono); font-size: 13px; font-weight: 500;
    color: var(--accent);
    background: var(--accent-soft);
    padding: 2px 8px; border-radius: 999px;
    opacity: 0; transform: translateX(-8px);
    transition: opacity 0.25s, transform 0.25s;
    pointer-events: none; white-space: nowrap;
}
.counter-pulse.is-visible { opacity: 1; transform: translateX(0); }
.counter-label {
    font-family: var(--font-mono);
    font-size: 11px;
    letter-spacing: 0.14em;
    color: var(--ink-soft);
    margin-top: 6px;
}

/* buttons ────────────────────────────────────────────────────────────── */
.button, button.cta, button[type="submit"] {
    appearance: none;
    font-family: var(--font-body);
    font-size: 14px;
    font-weight: 500;
    padding: 12px 22px;
    background: var(--ink);
    color: var(--paper);
    border: none;
    border-radius: var(--radius);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 10px;
    text-decoration: none;
    line-height: 1;
}
.button:hover,
button.cta:hover,
button[type="submit"]:hover { background: #2a241b; color: var(--paper); }
.button:focus-visible,
button.cta:focus-visible,
button[type="submit"]:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}
.button--outline {
    background: transparent;
    color: var(--ink);
    border: 1px solid var(--ink);
}
.button--outline:hover { background: var(--ink); color: var(--paper); }
/* Destruktive Aktion (Frank-Feedback 2026-05-21: Konto-Loeschen sichtbar
   machen). Dezent im Ruhezustand — kein Rot-Alarm — aber Hover signalisiert
   eindeutig: hier passiert was Folgenschweres. */
.button--outline.button--danger {
    color: var(--ink-soft);
    border-color: var(--rule);
}
.button--outline.button--danger:hover {
    background: #b03a2e;
    border-color: #b03a2e;
    color: #fff;
}
.button--accent {
    background: var(--accent);
    color: var(--paper);
}
.button--forest {
    background: var(--accent-2);
    color: var(--paper);
}
.button:disabled, button:disabled { opacity: 0.35; cursor: not-allowed; }
.button .arrow::after { content: "→"; margin-inline-start: 8px; display: inline-block; }

/* monthly bonus banner (H3) ──────────────────────────────────────────── */
.bonus-banner {
    position: fixed;
    left: 50%; bottom: 22px;
    transform: translateX(-50%);
    width: min(560px, calc(100% - 22px));
    background: var(--paper);
    border: 1px solid var(--ink);
    box-shadow: 0 8px 32px rgba(0,0,0,0.10);
    padding: 18px 22px;
    z-index: 999;
    display: flex; gap: 18px; align-items: start; flex-wrap: wrap;
    border-radius: var(--radius);
}
.bonus-banner__body { flex: 1; min-width: 240px; }
.bonus-banner__title { font-family: var(--font-head); font-style: italic; font-size: 17px; margin: 6px 0 2px; }
.bonus-banner__sub { font-family: var(--font-head); font-size: 14px; color: var(--ink-soft); margin: 0; }
.bonus-banner__actions { display: flex; gap: 8px; flex-wrap: wrap; }
@media (max-width: 480px) {
    .bonus-banner { left: 11px; right: 11px; transform: none; width: auto; }
}

/* info-i popover (H4) ────────────────────────────────────────────────── */
.info-i {
    display: inline-flex; align-items: center; justify-content: center;
    width: 18px; height: 18px;
    margin-inline-start: 6px;
    border: 1px solid var(--rule);
    border-radius: 50%;
    background: transparent;
    color: var(--ink-soft);
    font-family: var(--font-head);
    font-style: italic;
    font-size: 11px;
    line-height: 1;
    cursor: pointer;
    padding: 0;
    vertical-align: baseline;
}
.info-i:hover { color: var(--accent); border-color: var(--accent); }
/* Header-Variante (Fußabdruck/Handabdruck-Ueberschriften, Issue #53): ein
   sanft getoenter Kreis (accent-soft-Fuellung + Akzent-Kontur/"i") — sichtbar
   genug, dass man die Erklaerung findet, aber dezenter als der volle Akzent-
   Blob (Stefan 04.06.: "koennte wieder dezenter werden"). Hover fuellt voll. */
.info-i--head {
    width: 20px; height: 20px;
    background: var(--accent-soft); border-color: var(--accent);
    color: var(--accent); font-size: 12px; font-weight: 600;
    margin-inline-start: 8px; vertical-align: middle;
}
.info-i--head:hover { color: var(--paper); background: var(--accent); border-color: var(--accent); }
.info-pop {
    margin-top: 8px;
    padding: 12px 14px;
    background: var(--accent-soft);
    border-inline-start: 3px solid var(--accent);
    font-family: var(--font-head);
    font-style: italic;
    font-size: 13px;
    line-height: 1.5;
}
.info-pop[hidden] { display: none; }
.info-pop__more {
    display: inline-block;
    margin-top: 8px;
    font-family: var(--font-mono);
    font-size: 11px;
    font-style: normal;
    letter-spacing: 0.08em;
    color: var(--accent);
    text-decoration: none;
    border-bottom: 1px solid currentColor;
    padding-bottom: 1px;
}
.info-pop__more:hover { color: var(--ink); }
.info-pop .source {
    display: block;
    margin-top: 6px;
    font-family: var(--font-mono);
    font-style: normal;
    font-size: 10px;
    letter-spacing: 0.12em;
    color: var(--ink-soft);
}

/* share sheet (dialog element) ───────────────────────────────────────── */
dialog.share-sheet {
    border: 1px solid var(--ink);
    border-radius: var(--radius);
    background: var(--paper);
    color: var(--ink);
    padding: 0;
    width: min(420px, 92vw);
    max-width: 92vw;
}
dialog.share-sheet::backdrop { background: rgba(28,24,18,0.42); }
.share-sheet__head {
    display: flex; justify-content: space-between; align-items: baseline;
    padding: 18px 22px 0;
}
.share-sheet__close {
    background: transparent; border: 0;
    font-size: 22px; color: var(--ink-soft); cursor: pointer;
    padding: 0 4px;
}
.share-sheet__close:hover { color: var(--ink); }
.share-sheet__grid {
    display: grid; gap: 0;
    padding: 14px 0 22px;
}
.share-sheet__opt {
    display: block;
    padding: 14px 22px;
    border-top: 1px solid var(--rule);
    font-family: var(--font-head); font-style: italic; font-size: 16px;
    color: var(--ink); text-decoration: none;
    background: transparent; cursor: pointer; text-align: start; width: 100%;
}
.share-sheet__opt:hover { background: var(--accent-soft); }
.share-sheet__opt.share-sheet__copy { border: 0; border-top: 1px solid var(--rule); font-style: normal; font-family: var(--font-body); font-size: 14px; }
/* WeChat-QR-Modal: Variante des Share-Sheets mit QR-Code statt Grid (Frank 2026-05-29). */
dialog.share-sheet--qr { width: min(380px, 92vw); }
.share-sheet__qr { display: flex; flex-direction: column; align-items: center; padding: 18px 22px 24px; gap: 14px; }
.share-sheet__qr svg { width: 280px; height: 280px; max-width: 100%; background: #fff; border-radius: 8px; }
.share-sheet__qr-hint { margin: 0; font-family: var(--font-body); font-size: 14px; color: var(--ink-soft); text-align: center; }

/* Anonym-teilen-Knopf (Issue #27, Frank 01.06.2026) — abgesetzt unter dem
   Grid, dezenter als die Haupt-Optionen: es ist die bewusste Sonder-Wahl
   für Hochrisiko-Kontexte, nicht der Default-Weg. */
.share-sheet__anon {
    display: block; width: 100%; text-align: start; cursor: pointer;
    margin: 0; padding: 12px 22px;
    background: var(--accent-soft); border: 0; border-top: 1px solid var(--rule);
    font-family: var(--font-body); font-size: 14px; color: var(--ink);
}
.share-sheet__anon:hover { background: var(--accent); color: var(--paper); }
.share-sheet__anon-hint {
    margin: 0; padding: 8px 22px 16px;
    font-family: var(--font-head); font-style: italic; font-size: 12px;
    color: var(--ink-soft); line-height: 1.45; background: var(--accent-soft);
}

/* Mitmach-Wizard (Frank 30.05.) — Schritt-für-Schritt-Overlay ─────────── */
dialog.wizard-overlay {
    border: 1px solid var(--ink);
    border-radius: var(--radius);
    background: var(--paper);
    color: var(--ink);
    padding: 0;
    width: min(520px, 94vw);
    max-width: 94vw;
}
dialog.wizard-overlay::backdrop { background: rgba(28,24,18,0.55); }
.wizard__form { margin: 0; }
.wizard__head {
    display: flex; justify-content: space-between; align-items: baseline;
    padding: 18px 22px 0;
}
.wizard__close {
    background: transparent; border: 0;
    font-size: 22px; color: var(--ink-soft); cursor: pointer; padding: 0 4px;
}
.wizard__close:hover { color: var(--ink); }
.wizard__progress {
    padding: 4px 22px 0;
    font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.08em;
    color: var(--ink-soft);
}
.wizard__body { padding: 14px 22px 6px; }
.wizard__lower {
    margin: 0 0 8px; font-family: var(--font-head); font-style: italic;
    font-size: 14px; color: var(--accent);
}
.wizard__title { font-family: var(--font-head); font-size: clamp(20px, 3vw, 26px); line-height: 1.15; margin: 0 0 8px; }
.wizard__desc { font-size: 15px; line-height: 1.5; color: var(--ink); margin: 0 0 8px; }
.wizard__points { font-family: var(--font-mono); font-size: 12px; color: var(--accent); margin: 0 0 6px; }
.wizard__more { font-size: 13px; color: var(--ink-soft); text-decoration: underline; text-decoration-color: var(--rule); }
.wizard__choices {
    display: flex; flex-direction: column; gap: 8px;
    padding: 12px 22px 8px;
}
.wizard__choice { width: 100%; text-align: center; }
.wizard__nav {
    display: flex; justify-content: space-between;
    padding: 6px 22px 20px;
}
.wizard__navbtn {
    background: transparent; border: 0; cursor: pointer;
    font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.08em;
    color: var(--ink-soft); text-decoration: underline; text-decoration-color: var(--rule);
    padding: 4px 0;
}
.wizard__navbtn:hover { color: var(--ink); }
.wizard__summary { text-align: center; }
.wizard__summary-line { font-family: var(--font-head); font-size: 16px; margin: 6px 0; }

/* mailman / newsletter modal (same dialog) ──────────────────────────── */
dialog.newsletter-sheet { width: min(480px, 92vw); }
.newsletter-sheet__head { padding: 22px 22px 0; }
.newsletter-sheet__list {
    display: grid; gap: 0; padding: 14px 0 22px;
}
.newsletter-sheet__lang {
    display: flex; justify-content: space-between; align-items: baseline;
    gap: 16px;
    padding: 14px 22px;
    border-top: 1px solid var(--rule);
    font-family: var(--font-head); font-size: 16px;
    text-decoration: none; color: var(--ink);
}
.newsletter-sheet__lang:hover { background: var(--accent-soft); }
.newsletter-sheet__lang code {
    font-family: var(--font-mono); font-size: 13px; color: var(--ink-soft); background: transparent;
}

/* both-and block ─────────────────────────────────────────────────────── */
.both-and { background: var(--paper); }
.both-and__grid {
    display: grid; gap: 24px;
    margin-top: 18px;
    grid-template-columns: 1fr;
}
@media (min-width: 960px) {
    .both-and__grid { grid-template-columns: 1fr 60px 1fr; align-items: start; }
}
.both-and__col {
    border-top: 1px solid var(--rule);
    padding-top: 16px;
}
.both-and__cta {
    font-family: var(--font-mono);
    font-size: 13px;
    letter-spacing: 0.04em;
    color: var(--accent);
    text-decoration: underline;
    text-decoration-color: var(--rule);
    text-underline-offset: 4px;
    transition: text-decoration-color 0.15s;
}
.both-and__cta:hover { text-decoration-color: var(--accent); }

/* Counter-Personal-Link: stelle sicher dass der "jetzt einladen"-Link
   im Counter-Strip klickbar ist (war von leerer pointer-events Inheritance
   blockiert). */
[data-counter-personal-rest] a {
    color: var(--accent);
    text-decoration: underline;
    text-decoration-color: currentColor;
    text-underline-offset: 3px;
    pointer-events: auto;
    position: relative;
    z-index: 1;
}
[data-counter-personal-rest] a:hover { color: var(--ink); }

/* Counter-Anker (B1, 2026-05-21): typografische Hierarchie fuer "Du + X
   Kontakte + Y weitere". Ohne diese Klassen liest sich die Headline wie
   eine Plain-Aufzaehlung — mit ihnen wird "Du" zum Identitaets-Anker,
   die zwei Plus-Segmente dezent abgestuft.
   .counter-num setzt die Basis-Schriftgroesse (~5rem), wir nutzen em-Werte
   damit die Skalierung mitwaechst auf Mobile.
   .counter-anchor__self bleibt 1em (max), die Plus-Segmente werden visuell
   subordiniert: 0.55em / 0.40em. Display inline-block + vertical-align,
   damit das Strong/Number innerhalb des Segments seine eigene Linie haelt. */
[data-counter-personal-headline] {
    display: block;
    line-height: 1.05;
}
.counter-anchor__self {
    display: inline-block;
    color: var(--accent);
    font-weight: inherit;
    margin-inline-end: 0.18em;
}
.counter-anchor__known,
.counter-anchor__others {
    display: inline-block;
    font-weight: 500;
    color: var(--ink);
    vertical-align: baseline;
    line-height: 1.1;
    margin-inline-end: 0.14em;
}
.counter-anchor__known {
    font-size: 0.55em;
}
.counter-anchor__others {
    font-size: 0.40em;
    color: var(--ink-soft);
    font-style: italic;
}
.counter-anchor__known strong,
.counter-anchor__others strong {
    font-weight: 700;
    color: var(--ink);
}
@media (max-width: 640px) {
    /* Mobile: weniger drastischer Sprung, damit Du + Co auf einer Lese-Linie
       lesbar bleiben. */
    .counter-anchor__known  { font-size: 0.62em; }
    .counter-anchor__others { font-size: 0.50em; }
}

/* B2 (2026-05-21): "Jetzt einladen"-Sub-CTA als Pill statt unterstrichener
   Inline-Link. Bleibt klein (Counter-Strip-Kontext), aber visuell als
   Button-Affordance erkennbar. Hover-State + leichter Schatten geben
   Click-Affordance.
   Wichtig: hoehere Spezifitaet als die alte [data-counter-personal-rest] a
   Regel weiter oben, damit der Pill-Stil greift. */
[data-counter-personal-rest] a.counter-invite-cta {
    display: inline-block;
    padding: 4px 12px;
    margin-inline-start: 4px;
    background: var(--accent);
    color: var(--paper, #fff);
    text-decoration: none;
    border-radius: 999px;
    font-weight: 600;
    font-size: 0.95em;
    line-height: 1.4;
    transition: background 0.15s, transform 0.15s, box-shadow 0.15s;
    box-shadow: 0 1px 0 rgba(0,0,0,0.04);
}
[data-counter-personal-rest] a.counter-invite-cta:hover,
[data-counter-personal-rest] a.counter-invite-cta:focus-visible {
    background: var(--ink);
    color: var(--paper, #fff);
    box-shadow: 0 2px 8px rgba(0,0,0,0.12);
    transform: translateY(-1px);
}

.both-and__amp {
    font-family: var(--font-head);
    font-size: 80px;
    color: var(--accent);
    font-weight: 600;
    line-height: 1;
    text-align: center;
    display: none;
}
@media (min-width: 960px) {
    .both-and__amp { display: block; padding-top: 22px; }
}

/* petition excerpt + three pillars ──────────────────────────────────── */
.petition-excerpt {
    display: grid; gap: clamp(20px, 5vw, 64px);
}
@media (min-width: 960px) {
    .petition-excerpt { grid-template-columns: 1fr 260px; }
}
.petition-excerpt p {
    font-family: var(--font-head);
    font-size: clamp(15px, 1.6vw, 17px);
    line-height: 1.65;
    max-width: 640px;
    margin: 0;
}
.pillars {
    border-top: 1px solid var(--rule);
    padding-top: 18px;
}
@media (min-width: 960px) {
    .pillars { border-top: none; border-inline-start: 1px solid var(--rule); padding: 0; padding-inline-start: 32px; }
}
.pillars__list { margin-top: 14px; display: flex; flex-direction: column; gap: 14px; }
.pillars__item {
    display: flex;
    gap: 14px;
    align-items: start;
    padding: 0 0 14px;
    border-bottom: 1px solid var(--rule);
}
.pillars__item:last-child { border-bottom: none; padding-bottom: 0; }
.pillars__num {
    font-family: var(--font-head);
    font-size: 28px;
    line-height: 1;
    color: var(--accent);
    flex: 0 0 auto;
    min-width: 1.6em;
}
.pillars__body { flex: 1 1 auto; display: flex; flex-direction: column; gap: 4px; }
.pillars__label {
    font-family: var(--font-head);
    font-style: italic;
    font-size: 16px;
    color: var(--ink);
}
.pillars__desc {
    margin: 0;
    font-family: var(--font-head);
    font-size: 13.5px;
    line-height: 1.5;
    color: var(--ink-soft);
}

/* ink footer strip ───────────────────────────────────────────────────── */
.footer-strip {
    background: var(--ink);
    color: var(--paper);
    /* padding-inline-Trick (Bug-Fix 19.05.2026): horizontale Polster
       wachsen auf grossen Viewports so weit, dass der Footer-INHALT auf
       derselben 1180px-Reading-Column zentriert ist wie der Content
       darueber. Stripe selbst bleibt voll-bleed (Brand-Element).
       Vorher: clamp(22px, 7vw, 80px) → Footer-Inhalt streckte sich auf
       Desktops ueber die volle Viewport-Breite, wirkte ueberdimensioniert
       neben der schmaleren Reading-Column. */
    padding-block: 18px;
    padding-inline: max(clamp(22px, 7vw, 80px), calc((100% - 1180px) / 2));
    font-family: var(--font-mono);
    font-size: 11px;
    letter-spacing: 0.08em;
    display: flex; flex-wrap: wrap; justify-content: space-between; gap: 12px;
}
.footer-strip a { color: var(--paper); text-decoration: underline; text-decoration-color: var(--accent); }
.footer-strip__muted { opacity: 0.6; }
/* Rechtliches (#69): voll sichtbar statt im 0.6-muted-Span untergehen.
   opacity bleibt 1 (eigener Span), etwas mehr Gewicht macht Impressum/
   Datenschutz „leicht erkennbar" (TMG §5). */
.footer-strip__legal { font-weight: 600; }
.footer-strip__legal a { text-underline-offset: 2px; }

/* sign form (editorial) ──────────────────────────────────────────────── */
.sign-form {
    display: grid;
    gap: 22px;
    max-width: 520px;
}
.sign-form label.field { display: grid; gap: 6px; }
.sign-form label.field > .field-label {
    font-family: var(--font-mono);
    font-size: 10px;
    letter-spacing: 0.14em;
    color: var(--ink-soft);
}
.sign-form select, .sign-form input[type="text"] {
    font-family: var(--font-head);
    font-style: italic;
    font-size: 16px;
    padding: 8px 10px;
    border: 1px solid var(--ink);
    border-radius: 0;
    background: var(--paper);
    color: var(--ink);
    width: 100%;
    max-width: 320px;
}
.sign-form select:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 1px;
}

/* pill button groups ─────────────────────────────────────────────────── */
.pill-group { display: flex; flex-wrap: wrap; gap: 6px; }
.pill {
    appearance: none;
    cursor: pointer;
    padding: 6px 12px;
    border: 1px solid var(--ink);
    background: transparent;
    color: var(--ink);
    border-radius: 0;
}
.pill--mono { font-family: var(--font-mono); font-size: 12px; }
.pill--tag {
    font-family: var(--font-head);
    font-style: italic;
    font-size: 13px;
    border-radius: 14px;
    padding: 5px 12px;
}
.pill:hover { background: var(--accent-soft); }
.pill.is-active,
input:checked + .pill,
.pill--mono.is-active { background: var(--ink); color: var(--paper); }
.pill--tag.is-active { background: var(--accent); color: var(--paper); border-color: var(--accent); }

/* hide-but-keep-form-data radios AND checkboxes driving pills.
   Multi-select tag rows use checkboxes (sign.form `self_tags[]`);
   the click is captured by the surrounding <label> and reflected on
   the .pill via .is-active. */
.pill-group input[type="radio"],
.pill-group input[type="checkbox"] {
    position: absolute; left: -9999px; width: 1px; height: 1px;
    opacity: 0; pointer-events: none;
}
.pill-group label.pill { display: inline-flex; align-items: center; line-height: 1; }
.pill-group input[type="radio"]:focus-visible + .pill {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

/* ALTCHA host ────────────────────────────────────────────────────────── */
.altcha-host {
    --altcha-color-base: var(--paper);
    --altcha-color-text: var(--ink);
    --altcha-color-border: var(--rule);
    --altcha-border-radius: 0;
    --altcha-color-primary: var(--accent);
    margin-top: 4px;
}
.altcha-host altcha-widget { max-width: 320px; display: block; }

/* result block (after sign) ──────────────────────────────────────────── */
#sign-result:empty { display: none; }
#sign-result {
    background: var(--bg);
    border-inline-start: 4px solid var(--accent);
    padding: 18px 22px;
    margin-top: 18px;
    font-family: var(--font-head);
}
#sign-result h2 { font-style: italic; margin: 0 0 8px; }
#sign-result p { margin: 0 0 6px; }
#sign-result .sig-no {
    font-family: var(--font-head);
    font-size: 48px;
    font-weight: 600;
    letter-spacing: -0.03em;
    color: var(--ink);
    line-height: 1;
    margin: 4px 0 10px;
}
#sign-result .error {
    color: var(--accent);
    font-style: italic;
}

/* Sticky-footer pattern: every page is a flex column so the footer sits at
   the bottom of the viewport when content is short, and below the content
   otherwise. `margin-top: auto` on the footer pushes it away when there is
   spare space; when content overflows, the auto margin collapses to 0. */
body.page {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    /* Bug-Fix 19.05.2026: hier muss paper bleiben — sonst sickert auf
       Content-Pages (handeln/stats/map) der ink-BG links/rechts neben
       der max-width:1180px-Reading-Column durch und sieht aus wie
       hochgezogener Footer. Overscroll/Underfooter faengt das html-
       Element (ink) ab, der eigentliche Footer-Strip ist explizit ink. */
    background: var(--paper);
}
body.page > .footer-strip {
    margin-top: auto;
    flex-shrink: 0;
}

/* Page content container — every content page (dashboard / map / stats /
   handeln / petitionen / handlung / lokal / export / error / admin) uses
   `<main class="section">`. We give that main element a contained max-width
   so on wide screens the layout stays comfortable to read. home.php is
   exempt because it has its own multi-section landing structure.
   `width: 100%` ensures the inner content fills the available column. */
/* Frank-Feedback 2026-05-21 (4): die fruehere max-width:1180px-Regel auf
   <main class="section"> kollidierte mit dem padding-inline-max()-Trick
   in .section — Chrome-DevTools-Test ergab: main wurde auf 1180px outer
   width gecapt (box-sizing: border-box), Padding-Inline 363px wirkte aber
   relativ zum body, sodass Content nur 454px breit war. Loesung: max-width
   raus. Der Padding-Trick in .section zentriert den Content sauber auf der
   1180-Lese-Spalte, der Container bleibt voll-bleed wie auf Home. */
body.page main.section {
    width: 100%;
    margin: 0;
}
/* Admin pages got their own narrower constraint via inline style — that
   wins over the global max-width because it's a smaller value. */

/* Home `.home-page .section` — Override redundant, .section macht jetzt
   den Trick global. Bleibt als Anker fuer kuenftige Home-Tweaks. */
.home-page .section {
    padding-inline: max(clamp(22px, 7vw, 80px), calc((100% - 1180px) / 2));
}

/* dashboard ──────────────────────────────────────────────────────────── */
.dashboard-page {
    background: var(--paper);
    min-height: 100vh;
    /* Frank-Feedback 2026-05-21 (4): gleiche 1180-Lese-Spalte wie .section
       und .site-header — Header und Dashboard-Content liegen damit exakt
       auf derselben Achse. */
    padding-block: clamp(28px, 4vw, 48px);
    padding-inline: max(clamp(22px, 7vw, 80px), calc((100% - 1180px) / 2));
    max-width: none;
    margin: 0;
}
/* invite-hero: Background-Band geht über die volle VIEWPORT-Breite (full-bleed),
   der TEXT bleibt am normalen Content-Inset (gleich wie Header / Mein Beitrag).
   Frank-Feedback 18.05.2026: voriger Versuch (margin-inline = -padding) reichte
   nur über das Page-Padding hinaus, nicht über die max-width:1180px — der
   gruene Streifen war daher in der Mitte als Insel sichtbar, nicht als Band.
   Trick: width:100vw + margin-inline:calc(50% - 50vw) stretcht auf Viewport.
   Padding-inline mit max() addiert den freien Rand wenn Page max-width erreicht
   (bei kleinen Viewports bleibt's beim normalen Page-Padding). */
.dashboard-page > .invite-hero {
    width: 100vw;
    margin-inline: calc(50% - 50vw);
    padding-block: clamp(22px, 4vw, 36px);
    padding-inline: max(
        clamp(22px, 6vw, 64px),
        calc((100vw - 1180px) / 2 + clamp(22px, 6vw, 64px))
    );
}
/* Frisch-Theme rendert .invite-hero sonst als Card mit border-radius 18px;
   bei full-bleed über die Seite würde das hässlich abgeschnitten oder seltsam
   gerundet aussehen — Border-Radius weg, Background-Card wird zum Band. */
:root[data-theme="frisch"] .dashboard-page > .invite-hero {
    border-radius: 0;
}
/* Visual rules between sections sit flush with the content, not the viewport. */
.dashboard-page > hr.rule {
    margin-inline: 0;
}
.dashboard-header {
    display: flex; justify-content: space-between; align-items: baseline;
    margin-bottom: 24px;
}
.dashboard-week {
    font-family: var(--font-mono);
    font-size: 11px;
    color: var(--ink-soft);
    letter-spacing: 0.1em;
    flex-shrink: 0;
    align-self: start;
    padding-top: 8px;
    white-space: nowrap;
}
.dashboard-greeting {
    font-family: var(--font-head);
    font-style: italic;
    font-size: clamp(26px, 3.6vw, 38px);
    font-weight: 500;
    letter-spacing: -0.01em;
    margin: 0 0 6px;
}
.dashboard-lede {
    font-family: var(--font-head);
    font-style: italic;
    font-size: clamp(15px, 1.8vw, 18px);
    color: var(--ink-soft);
    max-width: 480px;
    margin: 0 0 26px;
}
.dashboard-grid {
    display: grid; gap: 24px;
    margin-bottom: 32px;
}
@media (min-width: 720px) {
    .dashboard-grid { grid-template-columns: 1fr 1fr; gap: 40px; }
}
.dashboard-col h3 {
    display: flex; align-items: baseline; gap: 10px;
    margin: 0 0 12px;
    padding-bottom: 6px;
    border-bottom: 1px solid var(--rule);
    font-family: var(--font-head);
    font-size: 22px;
    font-weight: 500;
}
.dashboard-col h3 small {
    font-style: italic; font-size: 13px; font-weight: 400; color: var(--ink-soft);
}
.action-row {
    display: flex; gap: 10px; align-items: start;
    padding: 8px 0;
}
/* Kategorie-Trennzeile zwischen Aktion-Gruppen — dezent, kein eigener
   Akkordeon-Toggle, nur visuelle Orientierung. Erstes Element der Spalte
   verzichtet auf den oberen Außenabstand. Frank-Plan 17.05.2026:
   "Mittelweg-UI ohne Filter, ohne Klick-Hierarchie". */
.category-divider {
    font-family: var(--font-mono);
    font-size: 11px;
    letter-spacing: 0.08em;
    text-transform: lowercase;
    color: var(--ink-soft);
    padding: 10px 0 4px;
    margin-top: 8px;
    border-top: 1px dashed var(--rule);
}
.category-divider:first-child {
    border-top: 0;
    margin-top: 0;
    padding-top: 0;
}

/* Post-Sign-Hub: drei Anschluss-Aktionen direkt nach erfolgreichem Sign
   (Wizard / Push / Newsletter). Vertikale Karten, jede mit Indikator-Zahl,
   kompaktem Titel, Lede-Text und Action-Button. Frank-Plan 17.05.2026. */
.post-sign-hub {
    display: flex;
    flex-direction: column;
    gap: 14px;
    margin: 28px 0 18px;
}
.post-sign-hub__card {
    display: flex;
    gap: 16px;
    align-items: start;
    padding: 18px 20px;
    border: 1px solid var(--rule);
    background: var(--paper);
    border-radius: 8px;
}
.post-sign-hub__card[hidden] { display: none; }
.post-sign-hub__num {
    flex: 0 0 auto;
    width: 32px;
    height: 32px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-family: var(--font-head);
    font-size: 17px;
    font-weight: 600;
    color: var(--paper);
    background: var(--accent);
    border-radius: 50%;
    line-height: 1;
}
.post-sign-hub__body {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
}
.post-sign-hub__title {
    font-family: var(--font-head);
    font-size: 16px;
    font-weight: 500;
    color: var(--ink);
    line-height: 1.3;
}
.post-sign-hub__lede {
    margin: 0 0 4px;
    font-family: var(--font-head);
    font-size: 13.5px;
    line-height: 1.55;
    color: var(--ink-soft);
}
.post-sign-hub__body .button {
    align-self: start;
    font-size: 14px;
    padding: 9px 16px;
    margin-top: 4px;
}
.post-sign-hub__mnemonic {
    margin: 26px 0 0;
    font-family: var(--font-head);
    font-style: italic;
    font-size: 13.5px;
    color: var(--ink-soft);
    line-height: 1.55;
}
.post-sign-hub__skip {
    font-family: var(--font-mono);
    font-size: 12px;
    letter-spacing: 0.06em;
    color: var(--ink-soft);
    text-decoration: underline;
    text-decoration-color: var(--rule);
    text-underline-offset: 3px;
}
.post-sign-hub__skip:hover { color: var(--accent); }
@media (max-width: 560px) {
    .post-sign-hub__card { flex-direction: column; gap: 10px; padding: 16px; }
    .post-sign-hub__body .button { align-self: stretch; text-align: center; }
}

/* Community-Tabs: gemeinsamer Switch zwischen /stats und /map unter dem
   "Wir sind viele"-Heading. URLs bleiben erhalten — die Tabs sind echte
   Links, kein clientside-Switch. Frank-Feedback 17.05.2026.

   Spezifitäts-Doppel (.community-tabs .community-tabs__tab), weil der
   Selektor sonst gegen `main a {...}` verliert und die Tabs als normale
   unterstrichene Inline-Links rendern. Plus text-decoration: none
   explizit, damit das Underline des Default-Link-Stils weicht. */
.community-tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 2px;
    margin: 22px 0 8px;
    border-bottom: 1px solid var(--rule);
}
.community-tabs .community-tabs__tab {
    display: inline-block;
    padding: 12px 22px;
    font-family: var(--font-head);
    font-size: 15px;
    font-weight: 500;
    color: var(--ink-soft);
    text-decoration: none;
    background: transparent;
    border: 1px solid transparent;
    border-bottom: 3px solid transparent;
    margin-bottom: -1px;
    border-radius: 6px 6px 0 0;
    transition: color 0.15s, background 0.15s, border-color 0.15s;
}
.community-tabs .community-tabs__tab:hover {
    color: var(--ink);
    background: var(--bg);
    border-bottom-color: var(--rule);
    text-decoration: none;
}
.community-tabs .community-tabs__tab.is-active {
    color: var(--accent);
    background: var(--paper);
    border-color: var(--rule);
    border-bottom-color: var(--accent);
    text-decoration: none;
}
.action-row .tick {
    color: var(--accent);
    font-family: var(--font-head);
    font-size: 16px;
    line-height: 1.4;
    margin-top: -1px;
}
.action-row .title {
    font-family: var(--font-head);
    font-size: 14px;
    line-height: 1.45;
}
.action-row .sub {
    font-family: var(--font-head);
    font-style: italic;
    font-size: 12px;
    color: var(--ink-soft);
    margin-top: 2px;
}
.dashboard-cta {
    display: inline-block;
    font-family: var(--font-body);
    font-size: 13px;
    color: var(--accent);
    text-decoration: underline;
    text-underline-offset: 3px;
    margin-top: 8px;
}

.dashboard-next {
    background: var(--bg);
    border: 1px solid var(--rule);
    padding: 22px 24px;
    margin-bottom: 24px;
}
.dashboard-next h3 {
    font-family: var(--font-head);
    font-style: italic;
    font-size: 22px;
    font-weight: 500;
    margin: 0 0 12px;
    border: none; padding: 0;
}
.dashboard-next .actions { display: flex; gap: 10px; flex-wrap: wrap; }

.dashboard-metrics {
    display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px;
    padding-top: 18px;
    border-top: 1px solid var(--rule);
}
.dashboard-metrics .num {
    font-family: var(--font-head);
    font-size: clamp(22px, 3vw, 30px);
    font-weight: 600;
    letter-spacing: -0.02em;
    line-height: 1.1;
    font-variant-numeric: tabular-nums;
}
.dashboard-metrics .cap {
    font-family: var(--font-head);
    font-style: italic;
    font-size: 12px;
    color: var(--ink-soft);
}

/* invite-hero — the centre of gravity of the dashboard ───────────────── */
.invite-hero {
    background: var(--accent-soft);
    border-top: 1px solid var(--ink);
    border-bottom: 1px solid var(--ink);
    padding: clamp(22px, 4vw, 36px) clamp(18px, 5vw, 40px);
    margin: 18px 0 0;
}
.invite-hero .kicker {
    color: var(--accent);
    font-size: 12px;
}
.invite-hero__title {
    font-family: var(--font-head);
    font-style: italic;
    font-weight: 500;
    font-size: clamp(26px, 3.6vw, 36px);
    line-height: 1.1;
    letter-spacing: -0.015em;
    margin: 8px 0 4px;
    color: var(--ink);
}
.invite-hero .lede {
    font-family: var(--font-head);
    font-style: italic;
    font-size: clamp(15px, 1.8vw, 18px);
    color: var(--ink);
    max-width: 560px;
    margin: 8px 0 18px;
    line-height: 1.5;
}
/* Generic "kicker + h2" pattern across dashboard sections — gives each
   subsection a real heading instead of using the kicker as the title. */
.dashboard-section__title,
.dashboard-next__title {
    font-family: var(--font-head);
    font-style: italic;
    font-weight: 500;
    font-size: clamp(20px, 2.6vw, 26px);
    line-height: 1.2;
    letter-spacing: -0.01em;
    margin: 6px 0 2px;
    color: var(--ink);
}
/* In Plakat, headings drop italic via the global override (line 81-83).
   These two classes inherit that, so nothing extra to do. */
.invite-metrics {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
    gap: 18px;
    margin-top: 22px;
    border-top: 1px solid var(--rule);
    padding-top: 18px;
}
.invite-metrics .num {
    font-family: var(--font-head);
    font-size: clamp(26px, 4vw, 36px);
    font-weight: 600;
    letter-spacing: -0.02em;
    color: var(--ink);
}
.invite-metrics .cap {
    font-family: var(--font-head);
    font-style: italic;
    font-size: 12px;
    color: var(--ink-soft);
    margin-top: 2px;
}
@media (max-width: 480px) {
    .invite-metrics { grid-template-columns: 1fr 1fr; }
    .invite-metrics > :nth-child(3) { grid-column: 1 / -1; border-top: 1px solid var(--rule); padding-top: 12px; }
}

/* invite link block ──────────────────────────────────────────────────── */
.invite-block {
    display: flex; gap: 0;
    margin: 16px 0 20px;
    max-width: 420px;
    flex-wrap: wrap;
}
.invite-block--big {
    max-width: 640px;
    gap: 0;
}
.invite-block--big input { font-size: 14px; padding: 12px 14px; }
.invite-block--big button { padding: 0 22px; font-size: 15px; }
.invite-block--big button[data-share] {
    background: transparent;
    color: var(--ink);
    border-inline-start: none;
    border-color: var(--ink);
    margin-inline-start: 8px;
}
.invite-block--big button[data-share]:hover { background: var(--ink); color: var(--paper); }
.invite-block input {
    flex: 1;
    font-family: var(--font-mono);
    font-size: 13px;
    padding: 10px 12px;
    border: 1px solid var(--ink);
    border-inline-end: none;
    border-radius: 0;
    background: var(--paper);
    color: var(--ink);
}
.invite-block button {
    font-family: var(--font-body);
    font-size: 14px;
    font-weight: 500;
    padding: 0 18px;
    background: var(--ink);
    color: var(--paper);
    border: 1px solid var(--ink);
    border-radius: 0;
    cursor: pointer;
    transition: background 200ms ease;
}
.invite-block button.is-copied {
    background: var(--accent-2);
    border-color: var(--accent-2);
}

/* mnemonic backup ─────────────────────────────────────────────────────── */
.mnemonic-block {
    background: var(--bg);
    border: 1px solid var(--rule);
    padding: 18px 22px;
}
.mnemonic-block .header {
    display: flex; justify-content: space-between; align-items: baseline;
    margin-bottom: 14px;
}
.mnemonic-grid {
    display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px 14px;
}
@media (min-width: 720px) {
    .mnemonic-grid { grid-template-columns: repeat(4, 1fr); }
}
.mnemonic-tile {
    display: flex; gap: 8px; align-items: baseline;
    padding: 6px 8px;
    background: var(--paper);
    border: 1px solid var(--rule);
}
.mnemonic-tile .idx {
    font-family: var(--font-mono);
    font-size: 10px;
    color: var(--ink-soft);
    min-width: 1.5em;
}
.mnemonic-tile .word {
    font-family: var(--font-head);
    font-style: italic;
    font-size: 17px;
    color: var(--ink);
}
.mnemonic-tile.is-hidden .word { filter: blur(6px); }

/* map page ───────────────────────────────────────────────────────────── */
.map-page { padding: clamp(28px, 4vw, 48px) clamp(22px, 7vw, 80px); }
.map-toggle { display: inline-flex; gap: 6px; margin-bottom: 18px; }
.map-toggle button {
    font-family: var(--font-body);
    font-size: 13px;
    padding: 6px 14px;
    border: 1px solid var(--ink);
    background: transparent;
    color: var(--ink);
    border-radius: var(--radius);
    cursor: pointer;
}
.map-toggle button.is-active { background: var(--ink); color: var(--paper); }
.map-frame {
    background: var(--bg);
    border: 1px solid var(--rule);
    padding: 14px;
}
.map-frame svg { width: 100%; height: auto; max-height: 60vh; display: block; }
.map-frame svg [data-iso] {
    fill: var(--map-nodata);
    stroke: var(--paper);
    stroke-width: 0.7;
    transition: stroke-width 80ms ease, stroke 80ms ease;
    cursor: default;
}
/* #76 (Stefan): Manche Subdivision-Pfade in den generierten Karten tragen KEIN
   data-iso (Build-Mapping-Lücke — z.B. Valencia in es.svg als id="valencia") und
   fielen dadurch auf den SVG-Default-Fill = SCHWARZ. Catch-all: jeder Region-Pfad
   ohne data-iso bekommt die neutrale „keine-Daten"-Farbe statt Schwarz. Trifft
   die per-Region-Regeln (alle mit data-iso) NICHT. */
.map-frame svg path:not([data-iso]),
.map-frame svg polygon:not([data-iso]) {
    fill: var(--map-nodata);
    stroke: var(--paper);
    stroke-width: 0.7;
}
.map-frame svg [data-iso]:hover { stroke-width: 1.6; stroke: var(--ink); }
/* Clickable countries (DE / AT / CH on the world map, all DE subdivisions
   on the DE map) get a pointer cursor + slightly stronger hover outline. */
.map-frame svg [data-iso].is-clickable { cursor: pointer; }
.map-frame svg [data-iso].is-clickable:hover { stroke-width: 2; stroke: var(--accent); }
.map-aside {
    background: var(--paper);
    padding: 8px 0 0;
}
.map-aside .total-label {
    font-family: var(--font-head);
    font-style: italic;
    font-size: 14px;
    color: var(--ink-soft);
}
.map-aside .total-num {
    font-family: var(--font-head);
    font-size: 36px;
    font-weight: 600;
    letter-spacing: -0.02em;
    line-height: 1.1;
    font-variant-numeric: tabular-nums;
}
.map-aside .legend {
    display: grid; grid-template-columns: 12px auto; gap: 6px 10px;
    font-family: var(--font-mono);
    font-size: 11px;
    color: var(--ink-soft);
    margin-top: 18px;
}
.map-aside .swatch {
    width: 12px; height: 12px;
    border: 1px solid var(--rule);
}
.map-aside .k-anon-note {
    background: var(--accent-soft);
    padding: 12px 14px;
    margin-top: 18px;
    font-family: var(--font-head);
    font-style: italic;
    font-size: 13px;
    color: var(--ink);
}

/* utilities ──────────────────────────────────────────────────────────── */
.sr-only {
    position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden;
    clip: rect(0 0 0 0);
}
.flex-row { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; }
.flex-row--between { justify-content: space-between; }
hr.rule { border: none; border-top: 1px solid var(--rule); margin: 28px 0; }

/* honeypot — keep accessible-hidden but never visible */
.honeypot {
    position: absolute !important;
    inset-inline-start: -9999px !important;
    width: 1px !important;
    height: 1px !important;
    overflow: hidden !important;
}

/* Hamburger sits next to the wordmark — desktop hides it, mobile shows. */
.nav-hamburger {
    display: none;
    background: transparent; border: 1px solid var(--rule);
    color: var(--ink); cursor: pointer;
    width: 36px; height: 36px; padding: 0;
    font-size: 22px; line-height: 1;
    border-radius: 6px;
}
.nav-hamburger:hover { border-color: var(--ink); }

/* Profil-Seite (Tier E, 2026-05-20) — /sig/<invite_code>. Frank-Vorgabe:
   nichts ist frei waehlbar, alles ist entweder aus der Signatur ableitbar
   (Sig-Nr, Region), aus dem Catalog (Aktionen) oder ein verifizierter
   OAuth-Snapshot (Display-Name, Avatar — Phase 2). */
/* Frank-Feedback 2026-05-22: .profile-page hatte max-width:720px, was mit dem
   neuen padding-inline-max()-Trick in .section kollidierte — Container 720
   wide minus 2×363px Padding = Content auf 0px gecippt. Profilseite hat eine
   eigene innere Lese-Spalte ueber .profile-card (max-width siehe unten); der
   .section-Wrapper braucht hier keine extra-Begrenzung. */
.profile-page {
    /* keine max-width mehr — Lese-Spalte kommt aus .section padding-inline */
}
.profile-card {
    max-width: 720px;
    margin: 0 auto;
}

/* Static-Pages (Datenschutz, Impressum, Ueber uns) — gleiche Loesung wie
   .profile-card: max-width auf den inneren Lese-Block, nicht aufs <main>.
   780px ist die typische Lese-Spalte fuer Mengen-Text (Datenschutz hat
   ~5000 Worte). */
.static-page__inner {
    max-width: 780px;
    margin: 0 auto;
}

/* Unterstuetzende Organisationen (#60) — Logo-Reihe unter dem About-Text. */
.support-orgs { margin-top: 48px; border-top: 1px solid var(--rule); padding-top: 28px; }
.support-orgs__title {
    font-family: var(--font-head); font-style: italic; font-weight: 500;
    font-size: 18px; color: var(--ink-soft); margin: 0 0 18px;
}
.support-orgs__grid {
    list-style: none; margin: 0; padding: 0;
    display: flex; flex-wrap: wrap; align-items: center; gap: 24px 36px;
}
.support-orgs__item { margin: 0; }
.support-orgs__logo {
    display: block; height: 92px; width: auto; max-width: 220px; object-fit: contain;
}
.profile-preview-banner {
    background: var(--accent-soft, #fff6d6);
    border: 1px dashed var(--accent, #c89b1f);
    color: var(--ink);
    padding: 10px 14px;
    margin-bottom: 14px;
    border-radius: 6px;
    font-size: 14px;
}
.profile-preview-banner strong { margin-inline-end: 4px; }

/* ─ Dashboard-Profil-Konfiguration (Phase 2.5, 2026-05-21) ──────────────── */
.profile-config { display: grid; gap: 16px; margin-top: 18px; }
.profile-config__card {
    background: var(--paper, var(--bg));
    border: 1px solid var(--rule);
    border-radius: 10px;
    padding: 18px 20px;
}
.profile-config__heading {
    margin: 0 0 4px;
    font-family: var(--font-head);
    font-size: 16px;
    letter-spacing: -0.005em;
}
.profile-config__subheading {
    margin: 14px 0 8px;
    font-family: var(--font-mono);
    font-size: 11px;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--ink-soft);
}
.profile-config__lede {
    margin: 0 0 12px;
    font-size: 13px;
    color: var(--ink-soft);
}
.profile-config__url-row {
    display: flex; flex-wrap: wrap; gap: 8px; align-items: center;
    margin: 4px 0 12px;
}
.profile-config__url {
    font-family: var(--font-mono); font-size: 13px;
    padding: 7px 10px;
    background: var(--bg);
    border: 1px solid var(--rule);
    border-radius: 4px;
    flex: 1 1 260px; min-width: 0;
    overflow-wrap: anywhere;
}
.profile-config__master {
    display: flex; align-items: center; gap: 10px;
    padding: 10px 12px;
    border-top: 1px solid var(--rule);
    margin-top: 8px;
}
.profile-config__master input[type="checkbox"] {
    width: 18px; height: 18px;
    accent-color: var(--accent, #2d8a52);
}
.profile-config__toggles { display: grid; gap: 8px; }
.profile-config__toggle {
    display: flex; align-items: center; gap: 10px;
    padding: 8px 10px;
    border: 1px solid var(--rule);
    border-radius: 6px;
    cursor: pointer;
    font-size: 14px;
    transition: border-color 0.12s;
}
.profile-config__toggle:hover { border-color: var(--accent); }
.profile-config__toggle input[type="checkbox"] {
    accent-color: var(--accent, #2d8a52);
}

/* Provider-Karten */
.profile-config__provider-cards {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: 10px;
    margin: 10px 0 4px;
}
.profile-provider-card {
    display: flex; flex-direction: column; align-items: start; justify-content: center;
    gap: 4px;
    /* Frank-Fix 2026-05-22: position:relative als Anker fuer das
       --linked::before-Haken, plus padding-right Platz dafuer. */
    position: relative;
    padding: 12px 30px 12px 14px;
    background: var(--bg);
    border: 1px solid var(--rule);
    border-radius: 8px;
    font-family: var(--font-head);
    font-size: 14px;
    cursor: pointer;
    text-align: start;
    transition: border-color 0.12s, transform 0.12s;
}
.profile-provider-card:hover {
    border-color: var(--accent);
    transform: translateY(-1px);
}
.profile-provider-card__name { font-weight: 600; }
.profile-provider-card__state {
    font-family: var(--font-mono);
    font-size: 11px;
    color: var(--ink-soft);
    letter-spacing: 0.02em;
}
.profile-provider-card--linked {
    border-color: var(--accent);
    background: var(--accent-soft, var(--paper));
}
.profile-provider-card--linked .profile-provider-card__state {
    color: var(--accent-ink, var(--accent));
}
.profile-provider-card--linked::before {
    content: "✓";
    position: absolute;
    top: 10px;
    inset-inline-end: 12px;
    color: var(--accent);
    font-size: 16px;
    font-weight: 700;
    line-height: 1;
}

/* Per-Feld Source-Picker */
.profile-config__sources {
    margin-top: 14px;
    padding-top: 14px;
    border-top: 1px dashed var(--rule);
}
.profile-config__field-row {
    display: flex; align-items: center; gap: 12px;
    padding: 8px 0;
}
.profile-config__field-row[hidden] { display: none; }
.profile-config__field-toggle {
    display: flex; align-items: center; gap: 10px;
    flex: 1;
    cursor: pointer;
    font-size: 14px;
}
.profile-config__field-toggle input[type="checkbox"] {
    accent-color: var(--accent, #2d8a52);
}
.profile-config__source-picker {
    flex: 0 0 auto;
    padding: 6px 10px;
    border: 1px solid var(--rule);
    border-radius: 4px;
    background: var(--bg);
    font-family: var(--font-mono);
    font-size: 12px;
    color: var(--ink);
    cursor: pointer;
}
.profile-config__source-picker:empty { display: none; }

/* Personalisierte Greeting mit Avatar (Phase 2.5b). */
.dashboard-greeting--has-avatar {
    display: flex !important;
    align-items: center;
    gap: 18px;
    flex-wrap: wrap;
}
.dashboard-greeting__text {
    flex: 1 1 280px; min-width: 0;
}
.dashboard-greeting-avatar {
    width: 72px; height: 72px;
    border-radius: 50%;
    object-fit: cover;
    object-position: center 25%; /* Portraits: Gesicht ist oberhalb der Mitte */
    background: var(--rule);
    flex: 0 0 72px;
    box-shadow: 0 4px 14px rgba(0,0,0,0.08);
    border: 2px solid var(--paper, #fff);
}

/* Header-Profile-Link mit Avatar — wirkt wie ein User-Chip, nicht wie ein
 * Underline-Link. Pill mit Avatar links, Name dezent rechts. */
.header-profile {
    display: inline-flex; align-items: center; gap: 8px;
    padding: 3px 12px 3px 3px;
    border: 1px solid var(--rule);
    border-radius: 999px;
    text-decoration: none !important;
    color: var(--ink);
    font-family: var(--font-head, system-ui);
    font-size: 13px;
    line-height: 1;
    transition: border-color 0.12s, background 0.12s, transform 0.12s;
    max-width: 200px;
}
.header-profile:hover {
    border-color: var(--accent);
    background: var(--paper-2, var(--paper, #fff));
    transform: translateY(-1px);
}
.header-profile__avatar {
    width: 30px; height: 30px;
    border-radius: 50%;
    object-fit: cover;
    object-position: center 25%;
    background: var(--rule);
    flex: 0 0 30px;
    display: block; /* eliminate inline-baseline gap */
}
/* Reviewer-Feedback 2026-05-21: Initialen-Bubble als Avatar-Fallback
   (statt leerer grauer Kreis). Akzentfarbe + zentrierte Initiale. */
.header-profile__avatar--initial {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--accent);
    color: var(--paper, #fff);
    font-family: var(--font-head, system-ui);
    font-weight: 600;
    font-size: 13px;
    line-height: 1;
    text-transform: uppercase;
}
.header-profile__name {
    overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
    min-width: 0;
    font-weight: 500;
}
@media (max-width: 640px) {
    .header-profile__name { display: none; }
    .header-profile { padding: 2px; gap: 0; }
}

.profile-card {
    background: var(--paper, var(--bg));
    border: 1px solid var(--rule);
    padding: clamp(20px, 4vw, 36px);
    border-radius: 6px;
}
.profile-card__head {
    display: flex; gap: 18px; align-items: center;
    margin-bottom: 18px;
}
.profile-card__avatar {
    width: 128px; height: 128px;
    border-radius: 50%;
    object-fit: cover;
    background: var(--rule);
    flex: 0 0 128px;
    box-shadow: 0 4px 18px rgba(0,0,0,0.08);
}
.profile-card__avatar--anonymous {
    display: flex; align-items: center; justify-content: center;
    font-family: var(--font-head); font-style: italic; font-weight: 600;
    font-size: 38px; color: var(--ink-soft);
    border: 2px dashed var(--rule);
    background: transparent;
    box-shadow: none;
}
.profile-card__head-text { flex: 1; min-width: 0; }
.profile-card__name {
    margin: 0;
    font-family: var(--font-head); font-size: clamp(24px, 4vw, 34px);
    line-height: 1.1; letter-spacing: -0.01em;
}
.profile-card__name--anonymous { color: var(--ink-soft); font-style: italic; }
.profile-card__handle {
    margin: 6px 0 0;
    font-family: var(--font-mono); font-size: 13px;
    color: var(--accent); letter-spacing: 0.01em;
    word-break: break-all;
}
.profile-card__provider {
    margin: 6px 0 0;
    font-family: var(--font-mono); font-size: 12px;
    color: var(--ink-soft);
}

/* Hero-Variante: nur Avatar (kein Display-Name) → zentriertes Layout.
   Macht Sinn wenn User nur das Bild und die Sig-Nr zeigt — sauberer
   Look ohne den schiefen "links Avatar, rechts leer"-Effekt. */
.profile-card--hero .profile-card__head {
    flex-direction: column; align-items: center; text-align: center;
    gap: 14px;
}
.profile-card--hero .profile-card__head-text { width: 100%; }
.profile-card--hero .profile-card__name { font-size: clamp(22px, 4vw, 28px); }
.profile-card__stats {
    display: grid; gap: 12px 24px;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    margin: 0 0 22px;
    padding: 14px 0;
    border-top: 1px solid var(--rule);
    border-bottom: 1px solid var(--rule);
}
.profile-card__stats > div { display: block; }
.profile-card__stats dt {
    font-family: var(--font-mono); font-size: 11px;
    letter-spacing: 0.14em; color: var(--ink-soft);
    text-transform: uppercase;
}
.profile-card__stats dd {
    margin: 4px 0 0;
    font-family: var(--font-head); font-size: 18px;
    color: var(--ink);
}
.profile-card__stats .profile-card__of { color: var(--ink-soft); font-size: 14px; }
.profile-card__actions h2 {
    font-family: var(--font-head); font-size: 18px;
    margin: 0 0 12px;
}
.profile-card__action-list {
    list-style: none; padding: 0; margin: 0;
    display: grid; gap: 8px;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}
.profile-card__action {
    padding: 10px 14px;
    border: 1px solid var(--rule);
    border-radius: 8px;
    font-family: var(--font-head); font-size: 14px;
    background: var(--paper, transparent);
    transition: transform 0.12s ease, border-color 0.12s ease;
    position: relative;
}
.profile-card__action:hover { transform: translateY(-1px); border-color: var(--accent); }
.profile-card__action a {
    color: var(--ink); text-decoration: none;
    display: block; padding-inline-start: 22px;
}
.profile-card__action a:hover { color: var(--accent); }
.profile-card__action a::before {
    content: ""; position: absolute; left: 14px; top: 50%;
    width: 8px; height: 8px; transform: translateY(-50%);
    border-radius: 50%; background: var(--rule);
}
.profile-card__action--footprint a::before { background: var(--accent-soft, #d6e8c8); }
.profile-card__action--handprint a::before { background: var(--accent, #5a8a3a); }
.profile-card__action--intent a::before {
    background: transparent;
    border: 2px dashed var(--accent, #5a8a3a);
    width: 10px; height: 10px;
}
.profile-card__footer {
    margin-top: 28px; padding-top: 18px;
    border-top: 1px solid var(--rule);
}
.profile-card__footer-actions {
    display: flex; flex-wrap: wrap; gap: 10px; align-items: center;
    margin-top: 12px;
}
.profile-card__verified {
    display: inline-flex; align-items: center; justify-content: center;
    width: 22px; height: 22px;
    margin-inline-start: 8px;
    background: var(--accent, #5a8a3a); color: #fff;
    border-radius: 50%;
    font-size: 13px; font-weight: bold;
    vertical-align: middle;
}
.profile-card__own-share {
    display: flex; align-items: center; gap: 10px;
    flex: 1 1 280px; min-width: 0; flex-wrap: wrap;
}
.profile-card__own-url {
    flex: 1 1 200px; min-width: 0;
    font-family: var(--font-mono); font-size: 12px;
    padding: 8px 10px;
    background: var(--bg);
    border: 1px solid var(--rule);
    border-radius: 4px;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.profile-card__own-lang {
    padding: 7px 10px;
    border: 1px solid var(--rule);
    border-radius: 4px;
    background: var(--bg);
    font-family: var(--font-mono); font-size: 12px;
    color: var(--ink);
    cursor: pointer;
}
.profile-card__report-btn {
    background: none; border: none;
    color: var(--ink-soft); font-family: var(--font-mono);
    font-size: 12px; letter-spacing: 0.04em;
    cursor: pointer; padding: 6px 10px;
    margin-inline-start: auto;
    text-decoration: underline; text-underline-offset: 3px;
}
.profile-card__report-btn:hover { color: var(--ink); }
.profile-report-dialog {
    border: 1px solid var(--rule);
    background: var(--paper, var(--bg));
    padding: 24px 26px;
    max-width: 480px; width: calc(100vw - 40px);
    border-radius: 8px;
    box-shadow: 0 12px 40px rgba(0,0,0,0.18);
}
.profile-report-dialog::backdrop { background: rgba(0,0,0,0.32); }
.profile-report-dialog h2 {
    font-family: var(--font-head); font-size: 22px;
    margin: 0 0 12px;
}

/* Nav → Hamburger/Drawer ab Tablet abwärts (#149, 28.06.): die volle Nav
   (Logo + 6 Punkte + Sprach-/Mode-Schalter + Avatar-Chip) passt erst ab der
   1180er-Lesespalte in EINE Zeile; darunter brach der Header auf iPad in zwei
   Zeilen (Stefan). Eigene Query NUR für die Nav-Umschaltung — die Phone-Styles
   (Section-Padding, Footer-Spalte …) bleiben in der 640er, damit Tablets nicht
   mobil-gestylt werden. */
@media (max-width: 1180px) {
    .nav-hamburger { display: inline-flex; align-items: center; justify-content: center; }
    /* Primary nav: hidden by default, shown when the hamburger is open. */
    .primary-nav {
        order: 9;
        width: 100%;
        display: none;
        flex-direction: column; align-items: start; gap: 8px;
        padding: 12px 0;
        border-top: 1px solid var(--rule);
        font-size: 15px;
    }
    .primary-nav.is-open { display: flex; }
    .primary-nav a { padding: 6px 0; width: 100%; }
    /* Lang-Switcher + Mode-Toggle wandern in den Burger-Drawer (order nach den
       Nav-Links). */
    .nav-extras {
        order: 10;
        width: 100%;
        display: none;
        justify-content: start;
        gap: 14px;
        padding: 12px 0 4px;
        border-top: 1px dashed var(--rule);
    }
    .primary-nav.is-open ~ .nav-extras { display: inline-flex; }
    .lang-switch select { padding: 3px 6px; font-size: 13px; }
    .mode-toggle { padding: 3px 10px; font-size: 13px; }
}

/* responsive — mobile (≤ 640px) ───────────────────────────────────────── */
@media (max-width: 640px) {
    /* Critique #12: row 1 = wordmark + hamburger, row 2 = lang+theme as
       a thin 28-32 px tools bar, primary nav collapsed behind the
       hamburger. Headline becomes visible at the first viewport pixel. */
    .site-header {
        padding: 12px 16px;
        gap: 8px;
        align-items: center;
        flex-wrap: wrap;
    }
    .wordmark { font-size: 19px; flex: 1; }
    /* Nav-Umschaltung (Hamburger/Drawer) lebt jetzt in der breiteren
       @media (max-width:1180px) — hier nur noch die Phone-Feinheiten. */

    /* Section padding: consistent 22px on phones, no clamp wobble.
       Frank-Feedback 16.05.2026: die both-and-Box und petition-excerpt
       wirkten am Phone-Viewport zu eng am Rand — die Border-Tops der
       Sub-Spalten erzeugen einen Box-Eindruck, der mehr Atemraum braucht. */
    .section { padding: 24px 22px; }
    .section.hero { padding: 28px 22px 22px; }
    .section.counter-strip { padding: 22px; }
    .section.both-and { padding: 28px 22px; }
    .section.petition-excerpt { padding: 28px 22px; }
    .section#sign { padding: 24px 22px; }
    .dashboard-page { padding: 22px; }
    .dashboard-page > .invite-hero { margin-inline: 0; }

    .counter-num { font-size: 46px; }
    .dashboard-greeting { font-size: 32px; }
    .dashboard-header { display: block; }
    .dashboard-week { display: block; margin-top: 8px; }

    .footer-strip { padding: 14px 18px; flex-direction: column; gap: 10px; }
}

/* browser-language suggestion banner (K4) ────────────────────────────── */
.lang-suggest {
    display: flex; align-items: baseline; gap: 14px; flex-wrap: wrap;
    padding: 8px 22px;
    background: var(--ink);
    color: var(--paper);
    font-family: var(--font-head); font-size: 14px; font-style: italic;
}
.lang-suggest__msg { flex: 1; min-width: 200px; }
.lang-suggest__form { display: inline; margin: 0; }
.lang-suggest__go,
.lang-suggest__no {
    font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.08em;
    background: transparent;
    color: var(--paper); border: 1px solid var(--paper);
    padding: 4px 10px; cursor: pointer;
}
.lang-suggest__go:hover { background: var(--accent); border-color: var(--accent); }
.lang-suggest__no { border-color: transparent; opacity: 0.7; }
.lang-suggest__no:hover { opacity: 1; }
@media (max-width: 480px) {
    .lang-suggest { padding: 8px 14px; font-size: 13px; }
}

/* Scroll-Reveal — Tier C1 (2026-05-20).
   Section/Block faded ein wenn IntersectionObserver feuert (home-anim.js).
   prefers-reduced-motion: kein Transition, Element sofort sichtbar. */
.reveal-on-scroll {
    opacity: 0;
    transform: translateY(18px);
    transition: opacity 600ms ease-out, transform 600ms ease-out;
    will-change: opacity, transform;
}
.reveal-on-scroll.is-revealed {
    opacity: 1;
    transform: translateY(0);
}
@media (prefers-reduced-motion: reduce) {
    .reveal-on-scroll,
    .reveal-on-scroll.is-revealed {
        opacity: 1;
        transform: none;
        transition: none;
    }
}

/* Live-Activity-Feed (Tier D6, 2026-05-20).
   Aside neben/unter der Karte, befuellt von map-live.js renderFeed(). */
.mp-live-feed { display: block; }
.mp-live-feed__item {
    padding: 6px 0;
    border-top: 1px solid var(--rule);
    color: var(--ink);
    font-style: italic;
    animation: mp-feed-in 360ms ease-out;
    /* Frank-Bug 30.05.: lange Region-Namen (z.B. „Mecklenburg-Vorpommern")
       plus lange Action-Titel haben den Feed-Eintrag auf 2-3 Zeilen
       gestreckt. Beim Ticker-Rotate sprang die Container-Höhe → Layout-
       Hüpfen unter der Karte. Fix: max 2 Zeilen via line-clamp, ellipsis
       am Ende. min-height auf 2-Zeilen-Höhe damit kürzere Einträge keinen
       Sprung verursachen. */
    min-height: calc(2 * 1.5em + 12px);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    text-overflow: ellipsis;
}
.mp-live-feed__item:first-child { border-top: 0; }
.mp-live-feed__item--fade {
    opacity: 0;
    transition: opacity 280ms ease-out;
}
@keyframes mp-feed-in {
    from { opacity: 0; transform: translateY(-4px); }
    to   { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
    .mp-live-feed__item { animation: none; }
}

/* Live-Karten-Punkte — Tier D4 (2026-05-20).
   map-live.js fuegt circle.mp-live-dot in g.mp-live-layer ein. Pop-in
   per CSS-Animation, kein JS-Timing. Farbe folgt --accent. */
.mp-live-layer { pointer-events: none; }
.mp-live-dot {
    fill: var(--accent);
    fill-opacity: 0.55;
    stroke: var(--paper);
    stroke-width: 0.6;
    transform-origin: center;
    transform-box: fill-box;
    animation: mp-live-pop 480ms ease-out backwards;
    transition: fill-opacity 300ms ease-out;
}
@keyframes mp-live-pop {
    0%   { transform: scale(0); opacity: 0; }
    65%  { transform: scale(1.4); opacity: 1; }
    100% { transform: scale(1);   opacity: 1; }
}
/* Sync mit Ticker (Tier D7, 2026-05-20): das Top-Ticker-Item korrespondiert
   zu einem pulsierenden Karten-Punkt. Ungekoppelte Punkte bleiben ruhig,
   der aktive pulsiert (~1.6 s loop) und faerbt voll. */
.mp-live-dot.is-highlighted {
    fill-opacity: 1;
    animation: mp-live-pop 480ms ease-out backwards, mp-live-pulse 1600ms ease-in-out 600ms infinite;
}
/* Diff-Rendering: Punkt nicht mehr im aktuellen Feed — langsam verblassen
   ueber ~8 s statt sofort verschwinden. Frank-Feedback 20.05.2026:
   "Die alten Punkte koennen gerne irgendwann auch wieder verblassen".
   Sollte der Punkt vor Ablauf wieder im Feed auftauchen, nimmt JS die
   is-fading-Klasse weg und der Punkt fade-t zurueck auf voll. */
.mp-live-dot.is-fading {
    transition: opacity 8000ms linear, fill-opacity 8000ms linear;
    opacity: 0; fill-opacity: 0;
    animation: none;
}
@keyframes mp-live-pulse {
    0%, 100% { transform: scale(1);    opacity: 1; }
    50%      { transform: scale(1.45); opacity: 0.7; }
}
@media (prefers-reduced-motion: reduce) {
    .mp-live-dot,
    .mp-live-dot.is-highlighted { animation: none; }
}

/* Praesenz-Punkte (Frank 01.06.2026): pro Land mit >=1 Unterschrift ein
   kleiner, ruhiger Punkt auf der Startseiten-Mini-Karte. Bewusst dezenter
   als die Live-Aktivitaetspunkte (kleiner, kein Puls) — sie zeigen Reichweite
   ("die Welt macht mit"), nicht Live-Aktivitaet. */
.mp-presence-layer { pointer-events: none; }
.mp-presence-dot {
    fill: var(--accent);
    fill-opacity: 0.7;
    stroke: var(--paper);
    stroke-width: 0.5;
    transform-origin: center;
    transform-box: fill-box;
    animation: mp-presence-in 500ms ease-out backwards;
}
@keyframes mp-presence-in {
    0%   { transform: scale(0); opacity: 0; }
    100% { transform: scale(1); opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
    .mp-presence-dot { animation: none; }
}

/* "Hier bist du"-Marker (Reviewer-Feedback 2026-05-21).
   Narrative Bruecke zwischen "Du + 2 + 602" und der Welt-Karte: ein
   persistenter Pulse-Ring zentriert auf das Country des signed Users.
   Distinkt von den Live-Feed-Dots durch staerkeren Pulse + Solid-Dot
   im Inneren. */
.mp-you-here-layer { pointer-events: none; }
.mp-you-here-dot {
    fill: var(--accent);
    stroke: var(--paper, #fff);
    stroke-width: 0.8;
}
.mp-you-here-ring {
    fill: none;
    stroke: var(--accent);
    stroke-width: 1.4;
    transform-origin: center;
    transform-box: fill-box;
    animation: mp-you-here-pulse 2400ms ease-out infinite;
}
@keyframes mp-you-here-pulse {
    0%   { transform: scale(0.6); opacity: 0.9; stroke-width: 1.6; }
    80%  { transform: scale(2.4); opacity: 0.0; stroke-width: 0.4; }
    100% { transform: scale(2.4); opacity: 0.0; stroke-width: 0.4; }
}
@media (prefers-reduced-motion: reduce) {
    .mp-you-here-ring { animation: none; }
}

/* ── Konfetti-Feier-Banner (confetti.js / counter-live.js, 2026-06-04) ───────
   Kurze Ansage bei runden Zahlen (1.000, 10.000 …). Liegt UNTER dem Konfetti-
   Canvas (z-index niedriger), damit die Partikel ueber der Ansage "regnen".
   pointer-events:none → blockiert die Sign-Form nicht. Bei reduced-motion
   erscheint nur dieser Banner (ohne bewegte Partikel) — der Moment bleibt
   wahrnehmbar, role="status"/aria-live kuendigt ihn auch nicht-visuell an. */
.mp-confetti-banner {
    position: fixed;
    left: 50%;
    top: 26%;
    z-index: 2147483000;
    transform: translate(-50%, -8px) scale(0.96);
    opacity: 0;
    transition: opacity 0.32s ease,
                transform 0.32s cubic-bezier(0.2, 0.8, 0.3, 1.1);
    pointer-events: none;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    padding: 18px 30px;
    border-radius: 14px;
    background: var(--paper);
    border: var(--rule-weight) solid var(--rule);
    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.18);
    text-align: center;
    max-width: min(86vw, 460px);
}
.mp-confetti-banner.is-on {
    opacity: 1;
    transform: translate(-50%, 0) scale(1);
}
.mp-confetti-banner__num {
    font-family: var(--font-head);
    font-weight: 600;
    font-size: clamp(30px, 7vw, 52px);
    line-height: 1.05;
    color: var(--accent-2);
}
.mp-confetti-banner__sub {
    font-family: var(--font-body);
    font-size: clamp(13px, 2.6vw, 16px);
    color: var(--ink-soft);
}
@media (prefers-reduced-motion: reduce) {
    .mp-confetti-banner,
    .mp-confetti-banner.is-on {
        transition: opacity 0.2s ease;
        transform: translate(-50%, 0);
    }
}

/* Burst-Limiter-Banner — Tier A1 (2026-05-20).
   Erscheint nur wenn counter-live.js paused=true vom Server liest.
   [hidden]-Override explizit, sonst gewinnt display:flex und der Banner
   bleibt permanent sichtbar. */
.mp-pause-banner[hidden] { display: none; }
.mp-pause-banner {
    display: flex; align-items: baseline; gap: 14px; flex-wrap: wrap;
    padding: 10px 22px;
    background: var(--ink); color: var(--paper);
    border-bottom: 3px solid var(--accent);
    font-family: var(--font-head); font-size: 14px;
}
.mp-pause-banner__msg { font-weight: 700; font-style: italic; }
.mp-pause-banner__lede { flex: 1; min-width: 220px; font-size: 13px; opacity: 0.9; }
@media (max-width: 640px) {
    .mp-pause-banner { padding: 10px 14px; font-size: 13px; }
}

/* local groups list (J1) ──────────────────────────────────────────────── */
.local-list {
    list-style: none; padding: 0; margin: 8px 0 0;
}
.local-row {
    border-top: 1px solid var(--rule);
    padding: 10px 0;
    display: flex; gap: 14px; align-items: baseline; flex-wrap: wrap;
}
.local-row a {
    font-family: var(--font-head); font-style: italic; font-size: 15px;
    color: var(--ink); text-decoration: none;
}
.local-row a:hover { color: var(--accent); }
.local-row__arrow { color: var(--accent); font-style: normal; }
.local-row__sub {
    font-family: var(--font-head); font-style: italic; font-size: 13px;
    color: var(--ink-soft); flex: 1; min-width: 200px;
}

/* in-app reminder banner (H2) ─────────────────────────────────────────── */
.mp-banner {
    display: flex; gap: 14px; align-items: baseline; flex-wrap: wrap;
    padding: 12px 22px;
    background: var(--accent-soft);
    color: var(--ink);
    border-bottom: 1px solid var(--ink);
    font-family: var(--font-head);
}
.mp-banner__kicker {
    font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.14em;
    color: var(--ink-soft);
}
.mp-banner__body { font-style: italic; font-size: 15px; flex: 1; min-width: 220px; }
.mp-banner__cta {
    font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.08em;
    color: var(--ink); border-bottom: 1px solid currentColor;
    text-decoration: none; padding-bottom: 2px;
}
.mp-banner__cta:hover { color: var(--accent); }
.mp-banner__push {
    font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.08em;
    background: transparent; color: var(--ink);
    border: 1px solid var(--ink); padding: 6px 10px; cursor: pointer;
}
.mp-banner__push:hover { background: var(--ink); color: var(--paper); }
.mp-banner__close {
    background: transparent; border: 0; cursor: pointer;
    font-size: 18px; line-height: 1; color: var(--ink-soft);
    padding: 4px 8px;
}
.mp-banner__close:hover { color: var(--ink); }
@media (max-width: 480px) {
    .mp-banner { padding: 10px 14px; }
    .mp-banner__body { font-size: 14px; }
}

/* Petition body — Markdown-rendered prose. Default browser margins on
   blockquote (~40px) make quotes feel pushed into the viewport rim on
   phones; we replace with a calmer accent rule + padded indent that
   scales with the surrounding section padding. Frank-Feedback 16.05.2026. */
.petition-body p { margin: 0 0 12px; }
.petition-body p:last-child { margin-bottom: 0; }
.petition-body h2, .petition-body h3 { margin-top: 28px; }
.petition-body blockquote {
    margin: 22px 0;
    padding: 12px 18px;
    border-inline-start: 3px solid var(--accent);
    background: rgba(0, 0, 0, .03);
    font-family: var(--font-head);
    font-style: italic;
    font-size: 15px;
    line-height: 1.6;
    color: var(--ink);
}
.petition-body blockquote p { margin: 0; }
.petition-body ul, .petition-body ol { padding-inline-start: 22px; margin: 12px 0; }
.petition-body li { margin: 4px 0; }
.petition-body a { text-decoration: underline; text-underline-offset: 3px; }

/* Invite-Banner — gezeigt wenn der Visitor über einen `/m/SLUG`-Link
   kommt. Server hat die Sig-Nr des Inviters aufgelöst und als Cookie
   gesetzt. Banner sitzt direkt unter dem Site-Header. */
.invite-banner {
    display: flex; align-items: center; gap: 14px;
    padding: 14px clamp(22px, 7vw, 80px);
    background: var(--accent-soft, rgba(45,138,82,.10));
    border-bottom: 1px solid var(--accent);
    font-family: var(--font-head, var(--font-body));
}
.invite-banner__icon { font-size: 22px; line-height: 1; }
.invite-banner__text { font-size: 15px; line-height: 1.45; color: var(--ink); }
.invite-banner__text strong { color: var(--accent); margin-inline-end: 6px; }
@media (max-width: 480px) {
    .invite-banner { padding: 12px 18px; gap: 10px; }
    .invite-banner__text { font-size: 14px; }
}

/* Sticky-CTA — persistente Bottom-Bar auf Landing-Seiten mit Counter +
   Sign-Button. Wird via [data-signed-here] ausgeblendet (siehe weiter unten). */
.sticky-cta {
    position: fixed; left: 0; right: 0; bottom: 0;
    z-index: 50;
    display: flex; align-items: center; justify-content: space-between;
    gap: 14px;
    padding: 12px 18px;
    background: var(--ink); color: var(--paper);
    border-top: 1px solid rgba(255,255,255,0.08);
    box-shadow: 0 -4px 18px rgba(0,0,0,0.15);
    font-family: var(--font-body, system-ui);
    transform: translateY(100%);
    animation: stickyCtaIn 0.4s ease 0.6s forwards;
}
@keyframes stickyCtaIn { to { transform: translateY(0); } }
.sticky-cta__count {
    display: flex; align-items: baseline; gap: 6px;
    font-family: var(--font-mono); font-size: 12px;
    color: rgba(255,255,255,0.72);
}
.sticky-cta__count strong {
    font-family: var(--font-display, var(--font-head));
    font-size: 18px; color: var(--paper); font-weight: 700;
}
.sticky-cta__btn {
    background: var(--accent); color: #fff;
    padding: 10px 18px; border-radius: 999px;
    text-decoration: none; font-weight: 600; font-size: 14px;
    white-space: nowrap;
    transition: transform 0.15s, box-shadow 0.15s;
}
.sticky-cta__btn:hover { transform: translateY(-1px); box-shadow: 0 4px 14px rgba(0,0,0,0.2); }
@media (max-width: 480px) {
    .sticky-cta { padding: 10px 14px; }
    .sticky-cta__btn { padding: 8px 14px; font-size: 13px; }
}
/* Reserved Space fuer die fixed sticky-cta-Leiste — frueher auf body
   geparkt, was nach dem Body→paper-Fix einen sichtbaren paper-Streifen
   UNTER dem ink-Footer erzeugte. Jetzt aufs main verlegt, damit der
   Reserved-Space VOR dem Footer liegt; der Footer selbst bleibt
   buendig am Body-Bottom (Bug-Fix 19.05.2026).
   Bei signed users (`:root[data-signed-here]`) ist die CTA per CSS
   `display:none` — sie bleibt im DOM (`:has()` matcht weiterhin),
   der Reserved-Space wird aber unnoetig und wirkte als sichtbarer
   paper-Streifen. Override mit hoeherer Spezifitaet setzt ihn dann
   auf 0 zurueck.
   Frank-Bug 02.06.2026 (Herbert Thielen): der Footer steht NACH </main>,
   bekam also keinen Reserved-Space — die fixe CTA-Leiste verdeckte die
   Impressum-/Datenschutz-Links. Padding daher zusaetzlich auf den
   .footer-strip; der Footer ist selbst ink-farben -> kein paper-Streifen. */
body:has(.sticky-cta) > main { padding-bottom: 56px; }
body:has(.sticky-cta) > .footer-strip { padding-bottom: 70px; }
@media (max-width: 480px) {
    body:has(.sticky-cta) > main { padding-bottom: 64px; }
    body:has(.sticky-cta) > .footer-strip { padding-bottom: 78px; }
}
:root[data-signed-here] body:has(.sticky-cta) > main { padding-bottom: 0; }
:root[data-signed-here] body:has(.sticky-cta) > .footer-strip { padding-bottom: 0; }

/* Sign-state visibility — driven by sign-init.js (synchronous, runs before
   the body renders). When `<html data-signed-here>` is set:
     - the sign form (#sign + the hero CTA pointing to #sign) is hidden
     - the "you're already in" stub (#sign-done) becomes visible
   This eliminates the brief flash of the sign form on returning visitors
   that earlier relied on a DOMContentLoaded toggle in sign.js. */
:root[data-signed-here] #sign { display: none !important; }
:root[data-signed-here] #sign-done { display: flex !important; }
:root[data-signed-here] [data-hide-when-signed] { display: none !important; }

/* Push UI — "soon" / pending state.
   push.js setzt .is-push-pending am Container, .is-pending an den Buttons
   wenn der Browser Push kann, das Backend aber noch nicht aktiviert ist.
   Der Reminder-Block bleibt sichtbar (Frank-Wunsch: prominentere Anzeige). */
.push-block.is-push-pending .push-block__pending { display: block !important; }
.push-block.is-push-pending .push-block__pending[hidden] { display: block !important; }
.push-block__pending {
    font-size: 14px; color: var(--ink-soft); font-style: italic;
    background: var(--bg-soft, rgba(0,0,0,.04)); padding: 10px 14px;
    border-radius: 8px; margin-top: 6px;
}
[data-push-enable].is-pending {
    background: transparent; color: var(--ink-soft); border: 1px dashed var(--rule);
    cursor: help;
}
[data-push-enable].is-pending:hover { color: var(--ink); border-color: var(--ink); }

/* Mitmach-Wizard — Schritt-für-Schritt-Durchgang durch alle Actions.
   Frank-Feedback 16.05.2026 / Phase „Wizard". Nutzt die share-sheet-
   Dialog-Basis (CSS oben), ergänzt um Karten-Layout + Visual-Stand-in. */
dialog.wizard { width: min(520px, 94vw); }
.wizard-head { padding: 18px 22px 0; align-items: baseline; }
.wizard-progress {
    font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.08em;
    color: var(--ink-soft);
}
.wizard-progress__cat { color: var(--accent); margin-inline-start: 6px; }
.wizard-card {
    padding: 18px 24px 22px;
    display: flex; flex-direction: column; gap: 12px;
}
.wizard-visual {
    align-self: center;
    width: 96px; height: 96px;
    display: flex; align-items: center; justify-content: center;
    font-size: 56px; line-height: 1;
    background: var(--accent-soft, rgba(45,138,82,.10));
    border-radius: 50%;
    margin: 8px 0 4px;
}
.wizard-visual--summary { background: var(--accent); color: var(--paper); font-size: 48px; }
.wizard-title {
    margin: 0; font-family: var(--font-head);
    font-size: clamp(22px, 3vw, 28px); line-height: 1.15;
    text-align: center; color: var(--ink);
}
.wizard-desc {
    margin: 0; font-family: var(--font-head); font-style: italic;
    font-size: 15px; line-height: 1.55; color: var(--ink);
    text-align: center; max-width: 42em; align-self: center;
}
.wizard-details {
    align-self: stretch; margin-top: 4px;
    font-size: 14px; line-height: 1.55; color: var(--ink-soft);
    border-top: 1px solid var(--rule); padding-top: 10px;
}
.wizard-details > summary {
    cursor: pointer; font-family: var(--font-mono); font-size: 12px;
    letter-spacing: 0.06em; color: var(--accent); list-style: none;
}
.wizard-details > summary::-webkit-details-marker { display: none; }
.wizard-details > summary::before { content: "▸ "; }
.wizard-details[open] > summary::before { content: "▾ "; }

/* #134 — FAQ-Akkordeon (CSS-only <details>/<summary>, kein JS). */
.faq-list { display: flex; flex-direction: column; }
.faq-item { border-bottom: 1px solid var(--rule); }
.faq-item:first-child { border-top: 1px solid var(--rule); }
.faq-item > summary {
    cursor: pointer; list-style: none;
    display: flex; align-items: flex-start; gap: 12px;
    padding: 16px 2px;
    font-family: var(--font-head); font-size: 18px; line-height: 1.35;
    color: var(--ink);
}
.faq-item > summary::-webkit-details-marker { display: none; }
.faq-item > summary::before {
    content: "+"; flex: 0 0 auto;
    font-family: var(--font-mono); font-size: 20px; line-height: 1.25;
    color: var(--accent);
}
.faq-item[open] > summary::before { content: "\2013"; /* en dash */ }
.faq-item > summary:hover { color: var(--accent); }
.faq-item__a { padding: 0 2px 18px 32px; color: var(--ink-soft); line-height: 1.6; }
.faq-item__a p { margin: 0 0 10px; }
.faq-item__a p:last-child { margin-bottom: 0; }
.faq-item__a a { color: var(--accent); }
.wizard-long { margin-top: 10px; color: var(--ink); }
.wizard-long h2, .wizard-long h3 { font-family: var(--font-head); margin: 12px 0 6px; }
.wizard-long ul, .wizard-long ol { padding-inline-start: 22px; margin: 8px 0; }
.wizard-long p { margin: 8px 0; }
.wizard-points {
    margin: 6px 0 0; text-align: center; color: var(--accent);
    font-family: var(--font-mono); font-size: 12px; letter-spacing: 0.06em;
}
.wizard-choices {
    display: flex; flex-direction: column; gap: 10px; margin-top: 8px;
}
.wizard-choice { justify-content: center; padding: 12px 18px; }
/* Default: alle drei Buttons sind outline (kein Pre-Select).
   Erst wenn der User vorher schon eine Wahl getroffen hat, hebt sich der
   entsprechende Button optisch ab — solid accent + Häkchen-Indikator. */
.wizard-choice.is-active {
    background: var(--accent) !important;
    color: var(--paper) !important;
    border-color: var(--accent) !important;
    box-shadow: 0 0 0 2px var(--accent), 0 4px 12px rgba(0,0,0,.08);
    outline: none;
}
.wizard-nav {
    display: flex; justify-content: space-between; align-items: center;
    padding: 12px 22px 18px; border-top: 1px solid var(--rule);
    font-family: var(--font-mono); font-size: 12px; letter-spacing: 0.06em;
}
.wizard-nav button {
    background: transparent; border: 0; color: var(--ink-soft); cursor: pointer;
    padding: 6px 8px;
}
.wizard-nav button:hover:not([disabled]) { color: var(--ink); }
.wizard-nav button[disabled] { opacity: 0.35; cursor: not-allowed; }
.wizard-summary-list {
    list-style: none; padding: 0; margin: 4px 0 14px;
    font-family: var(--font-head); font-style: italic; font-size: 16px;
    color: var(--ink); text-align: center; line-height: 1.6;
}
.wizard-card--summary { align-items: center; text-align: center; }

/* Vormerk-Status (intent) auf Action-Pills im Dashboard-Grid */
.action-row.is-intent .tick { opacity: 0.65; color: var(--accent); }
.action-row.is-intent .title { color: var(--ink); }

/* Frank-Wunsch 29.05.: implizierte Tier-Stufen sind durch eine höhere
   aktive Pyramiden-Stufe abgedeckt — visuell ausgrauen + Klick blockieren.
   Punkte zählen über die Top-Stufe (bonus.js dedupliziert via tier_group).
   pointer-events:none schluckt auch Form-Submit beim Click → kein Toggle. */
.action-row.is-tier-implied { opacity: 0.45; pointer-events: none; cursor: not-allowed; }
.action-row.is-tier-implied input[type="checkbox"] { cursor: not-allowed; }
.tier-implied-hint {
    font-family: var(--font-head); font-style: italic; font-size: 12px;
    color: var(--ink-soft); margin-top: 2px;
}

/* Engagement-Kategorie (Frank 29.05.). Dezenter Container, Badges fuer
   Status-Indicator. Punkte zaehlen nur bei aktueller Rueckkehr (active_-
   this_month) — UI zeigt das ueber den „wartet"-Badge wenn der User
   abonniert ist aber gerade nicht aktiv. */
.dashboard-engagement { margin-top: 26px; }
.dashboard-engagement h3 small {
    font-family: var(--font-head); font-style: italic;
    color: var(--ink-soft); font-weight: 400; font-size: 0.6em;
    margin-inline-start: 6px;
}
.engagement-badge {
    display: inline-block; margin-inline-start: 8px;
    font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.08em;
    padding: 2px 6px; border-radius: 999px; vertical-align: middle;
    border: 1px solid currentColor;
}
.engagement-badge--yes  { color: var(--accent); background: var(--accent-soft, rgba(45,138,82,.08)); }
.engagement-badge--no   { color: var(--ink-soft); background: transparent; }
.engagement-badge--wait { color: var(--ink-soft); background: var(--rule); font-style: italic; }

.intent-badge {
    display: inline-block; margin-inline-start: 8px;
    font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.08em;
    color: var(--accent); padding: 2px 6px;
    border: 1px solid var(--accent); border-radius: 999px;
    background: var(--accent-soft, rgba(45,138,82,.08));
    vertical-align: middle;
}

/* Wizard-Hinweis nach abgeschlossenem Durchgang */
.dashboard-next__hint {
    margin-top: 14px; font-family: var(--font-head); font-style: italic;
    font-size: 13px; color: var(--ink-soft);
}

/* Personal counter + share block — Frank-Feedback 16.05.2026 Phase 2. */
.my-contribution {
    background: linear-gradient(135deg, var(--bg-soft, rgba(0,0,0,.04)) 0%, transparent 60%);
    border: 1px solid var(--rule); border-radius: 16px; padding: 20px 22px;
    margin: 20px 0;
}
.my-contribution__row { display: flex; flex-wrap: wrap; gap: 28px; align-items: baseline; }
.my-contribution__col { min-width: 140px; }
.my-contribution__col--lede { flex: 1; min-width: 220px; }
.my-contribution__num { font-family: var(--font-display, var(--font-sans));
    font-size: clamp(40px, 7vw, 64px); font-weight: 800; line-height: 1; color: var(--accent, var(--ink));
    margin-top: 6px; }
.my-contribution__sub  { font-size: 14px; color: var(--ink-soft); margin-top: 4px; }
.my-contribution__total { font-size: 13px; color: var(--ink-soft); }
.my-contribution__share { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 16px; }
.my-contribution__share button {
    font-size: 13px; padding: 8px 14px; border: 1px solid var(--rule); border-radius: 999px;
    background: var(--paper); color: var(--ink); cursor: pointer;
    display: inline-flex; align-items: center; gap: 6px;
}
.my-contribution__share button:hover { background: var(--ink); color: var(--paper); border-color: var(--ink); }

/* Newsletter Tabs (Anmelden / Abmelden) — Frank-Feedback 16.05.2026. */
.newsletter-tabs {
    display: flex; gap: 4px;
    padding: 6px 22px 0;
    border-bottom: 1px solid var(--rule);
    margin-bottom: 4px;
}
.newsletter-tab {
    background: transparent; border: 0; cursor: pointer;
    padding: 10px 14px; margin-bottom: -1px;
    font-family: var(--font-mono); font-size: 12px; letter-spacing: 0.06em;
    color: var(--ink-soft);
    border-bottom: 2px solid transparent;
}
.newsletter-tab:hover { color: var(--ink); }
.newsletter-tab.is-active {
    color: var(--accent);
    border-bottom-color: var(--accent);
    font-weight: 600;
}

/* Newsletter inline form — Phase 2.3 (Mailman-Proxy). */
.newsletter-form { display: flex; flex-direction: column; gap: 10px; margin-top: 8px; }
.newsletter-form label { font-size: 13px; color: var(--ink-soft); }
.newsletter-form input[type="email"],
.newsletter-form select {
    padding: 9px 12px; border: 1px solid var(--rule); border-radius: 8px;
    background: var(--paper); color: var(--ink); font-size: 15px;
}
.newsletter-form__note { font-size: 12px; color: var(--ink-soft); line-height: 1.5; }
.newsletter-form__result {
    font-size: 13px; padding: 10px 14px; border-radius: 8px; margin-top: 6px;
}
.newsletter-form__result--ok { background: rgba(46,160,67,.10); color: #1f7a32; }
.newsletter-form__result--err { background: rgba(207,34,46,.10); color: #b1232e; }

/* =============================================================================
 * Admin UI Components (23.05.2026) — ersetzen die zahllosen Inline-Styles
 * in app/views/admin/*.php durch wiederverwendbare Klassen.
 * ========================================================================= */

.admin-page {
    max-width: 1100px;
    margin: 0 auto;
    padding-block-start: 22px;
}
.admin-page--narrow { max-width: 780px; }
.admin-page--wide   { max-width: 1280px; }
/* Frank-Bug 2026-05-28: wenn admin-page mit .section kombiniert wird (so
   bauen alle app/views/admin/*.php ihren <main>), kollidiert .section's
   `padding-inline: max(80, calc((100% - 1180px)/2))` mit der admin-page-
   max-width. Tueckisch: 100% in padding-inline referenziert den containing
   block (body = viewport), nicht das Element selbst. Auf Desktop 1920px
   wird padding zu ~370px je Seite gerechnet — auf einem 780px-narrow-
   container bleibt content-box gerade noch 40px breit (Wort-pro-Zeile-
   Symptom auf /admin/login). Loesung: bei .section.admin-page das
   padding-inline auf gewoehnliche Werte zurueck — der admin-page-eigene
   `margin: 0 auto` uebernimmt das Zentrieren. */
.section.admin-page {
    padding-inline: clamp(22px, 5vw, 56px);
    /* `body.page main.section { margin: 0 }` (Commit d3ec4dc) hat hoehere
       Spezifitaet als `.admin-page { margin: 0 auto }` und wuerde den
       Container links kleben statt zu zentrieren. Hier explizit
       wiederherstellen. */
    margin-inline: auto;
}

.admin-back {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-family: var(--font-mono);
    font-size: 11px;
    letter-spacing: 0.12em;
    color: var(--ink-soft);
    text-decoration: none;
    text-transform: uppercase;
}
.admin-back:hover { color: var(--ink); }

.admin-header { margin-block: 18px 28px; }
.admin-header__kicker {
    display: inline-block;
    font-family: var(--font-mono);
    font-size: 11px;
    letter-spacing: 0.14em;
    color: var(--ink-soft);
    text-transform: uppercase;
}
.admin-header__title {
    margin-block-start: 8px;
    font-family: var(--font-head);
    font-size: clamp(28px, 4vw, 40px);
    line-height: 1.15;
}
.admin-header__lede {
    margin-block-start: 10px;
    max-width: 680px;
    font-family: var(--font-head);
    font-style: italic;
    color: var(--ink-soft);
    line-height: 1.4;
}

.admin-tiles {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: 16px;
    margin-block-start: 12px;
}
.admin-tile {
    display: block;
    padding: 22px 22px 24px;
    background: var(--paper);
    border: 1px solid var(--rule);
    border-radius: 4px;
    text-decoration: none;
    color: inherit;
    transition: border-color 0.14s, transform 0.14s, box-shadow 0.14s;
}
.admin-tile:hover {
    border-color: var(--ink);
    transform: translateY(-1px);
    box-shadow: 0 4px 12px rgba(0,0,0,0.04);
}
.admin-tile__title {
    margin: 0;
    font-family: var(--font-head);
    font-size: 19px;
    line-height: 1.2;
}
.admin-tile__desc {
    margin-block-start: 8px;
    font-family: var(--font-head);
    font-style: italic;
    font-size: 13px;
    line-height: 1.45;
    color: var(--ink-soft);
}
.admin-tile__badge {
    display: inline-block;
    margin-block-start: 12px;
    padding: 2px 8px;
    font-family: var(--font-mono);
    font-size: 10px;
    letter-spacing: 0.1em;
    color: var(--accent);
    border: 1px solid var(--accent);
    border-radius: 3px;
    text-transform: uppercase;
}

.admin-table {
    width: 100%;
    border-collapse: collapse;
    margin-block-start: 22px;
    font-family: var(--font-head);
    font-size: 14px;
}
.admin-table thead tr { border-bottom: 1px solid var(--ink); }
.admin-table th {
    padding: 10px 8px;
    text-align: start;
    font-family: var(--font-mono);
    font-size: 11px;
    letter-spacing: 0.12em;
    color: var(--ink-soft);
    text-transform: uppercase;
    font-weight: 500;
}
.admin-table th--num { text-align: end; }
.admin-table tbody tr { border-bottom: 1px solid var(--rule); }
.admin-table tbody tr:hover { background: color-mix(in srgb, var(--accent) 4%, transparent); }
.admin-table td { padding: 12px 8px; vertical-align: middle; }
.admin-table td--code {
    font-family: var(--font-mono);
    font-size: 12px;
    color: var(--ink);
}
.admin-table td--meta {
    font-family: var(--font-mono);
    font-size: 11px;
    color: var(--ink-soft);
}
.admin-table td--num {
    text-align: end;
    font-family: var(--font-mono);
}

.admin-locale-badges {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
}
.admin-locale-badge {
    display: inline-block;
    padding: 2px 8px;
    font-family: var(--font-mono);
    font-size: 10px;
    letter-spacing: 0.08em;
    text-decoration: none;
    border: 1px solid var(--rule);
    color: var(--ink-soft);
    border-radius: 3px;
    text-transform: uppercase;
    transition: border-color 0.12s, color 0.12s;
}
.admin-locale-badge:hover { border-color: var(--ink); color: var(--ink); }
.admin-locale-badge--published { border-color: var(--accent); color: var(--accent); }
.admin-locale-badge--draft     { border-color: var(--ink-soft); color: var(--ink-soft); }
.admin-locale-badge--missing   { border-style: dashed; }

.admin-lang-tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    margin-block: 18px 24px;
    border-bottom: 1px solid var(--rule);
}
.admin-lang-tab {
    padding: 8px 14px;
    border-bottom: 2px solid transparent;
    color: var(--ink-soft);
    text-decoration: none;
    font-family: var(--font-mono);
    font-size: 12px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    transition: color 0.12s, border-color 0.12s;
}
.admin-lang-tab:hover { color: var(--ink); }
.admin-lang-tab--active {
    color: var(--accent);
    border-bottom-color: var(--accent);
}

.admin-fieldset {
    border: 1px solid var(--rule);
    padding: 22px;
    margin-block-end: 18px;
    border-radius: 4px;
}
.admin-fieldset__legend {
    padding: 0 8px;
    font-family: var(--font-mono);
    font-size: 11px;
    letter-spacing: 0.12em;
    color: var(--ink-soft);
    text-transform: uppercase;
}

.admin-form { display: grid; gap: 18px; }
.admin-form__field { display: grid; gap: 6px; }
.admin-form__field-row {
    display: grid;
    gap: 14px;
    grid-template-columns: 1fr 1fr;
}
@media (max-width: 640px) {
    .admin-form__field-row { grid-template-columns: 1fr; }
}
.admin-form__label {
    font-family: var(--font-mono);
    font-size: 11px;
    letter-spacing: 0.08em;
    color: var(--ink-soft);
    text-transform: uppercase;
}
.admin-form__input,
.admin-form__select,
.admin-form__textarea {
    padding: 10px 12px;
    border: 1px solid var(--ink);
    background: var(--paper);
    color: var(--ink);
    font-family: var(--font-head);
    font-size: 16px;
    border-radius: 3px;
}
.admin-form__input:focus,
.admin-form__select:focus,
.admin-form__textarea:focus {
    outline: 2px solid var(--accent);
    outline-offset: 1px;
}
.admin-form__input--title { font-size: 18px; }
.admin-form__input--italic { font-style: italic; }
.admin-form__textarea {
    font-family: var(--font-mono);
    font-size: 13px;
    line-height: 1.5;
    resize: vertical;
}
.admin-form__select {
    font-family: var(--font-mono);
    font-size: 14px;
    cursor: pointer;
}
.admin-form__checkbox {
    display: flex;
    align-items: center;
    gap: 10px;
    font-family: var(--font-head);
    font-size: 15px;
    cursor: pointer;
}
.admin-form__checkbox input { width: 16px; height: 16px; }

.admin-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin-block-start: 8px;
}

.admin-hint {
    margin-block-start: 24px;
    max-width: 640px;
    font-family: var(--font-head);
    font-style: italic;
    font-size: 13px;
    line-height: 1.5;
    color: var(--ink-soft);
}

.admin-status-dot {
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--ink-soft);
}
.admin-status-dot--on { background: var(--accent); }

/* =============================================================================
 * Translation-Edit-Mode · Inline-Pencil (Phase 2, Frank-Wunsch 28.05.2026)
 *
 * Wirkt nur, wenn edit-translations.js den Sentinel-Pass durchlaufen hat
 * und Spans/data-Attribute gesetzt sind. Im Production-Mode kommt diese
 * Klasse nie ins DOM, also kein Overhead.
 *
 * Hover-Verhalten:
 *   .mp-edit       — direkt am gerenderten Text (Element-Content).
 *   [data-mp-msgid]— am Träger eines übersetzten Attributs (placeholder etc).
 *
 * Beide bekommen einen dezenten gestrichelten Outline auf Hover. Der
 * Pencil-Indicator erscheint absolut positioniert oben-rechts (RTL: oben-
 * links). Klick wird in edit-translations.js delegiert.
 * ========================================================================= */
/* Body-Marker: dezenter Akzent-Rand am Viewport-Rand. Hat KEINE Pointer-
   Events (pointer-events: none ueber das Pseudo), klaut also nichts. */
body.mp-editing { position: relative; }
body.mp-editing::before {
    content: "";
    position: fixed;
    inset: 0;
    pointer-events: none;
    box-shadow: inset 0 0 0 1px var(--accent);
    z-index: 99998;
    opacity: 0.5;
}
/* Hover-Outline auf den uebersetzten Stellen. Der eigentliche Stift ist
   ein einzelner schwebender Button (#mp-edit-pencil), siehe edit-
   translations.js — er wird bei Hover ueber dem Element positioniert.
   Der Outline hier ist nur visuelles Feedback "diesen Text kannst du
   uebersetzen". */
.mp-edit {
    outline: 1px dashed transparent;
    outline-offset: 1px;
    transition: outline-color 0.15s ease;
}
.mp-edit:hover { outline-color: var(--accent); }
[data-mp-msgid] {
    outline: 1px dashed transparent;
    outline-offset: 2px;
    transition: outline-color 0.15s ease;
}
[data-mp-msgid]:hover { outline-color: var(--accent); }

/* Telefonlawine-Picker (Frank-Wunsch 29.05.2026) — Pfeil-Buttons mit
   dezenter Hover-Fuellung. Inline-Styles im JS reichen fuer Basis, der
   :focus-within-Outline am Container ist nur per-CSS sauber. */
[data-variant-prev]:hover,
[data-variant-next]:hover { background: var(--rule); }
[data-variant-picker]:focus-within {
    outline: 1px dashed var(--accent);
    outline-offset: 4px;
    border-radius: 4px;
}
