/*
 * a11y-tool — Anpassungs-Tokens und Effekte
 *
 * Diese Datei enthält:
 *   1. Default-Werte aller anpassbaren CSS-Custom-Properties.
 *   2. Anwendung dieser Properties auf typografische Basis-Eigenschaften.
 *   3. Flag-Klassen am <html>-Element für boolean-artige Modi.
 *   4. Respekt vor System-Präferenzen (prefers-reduced-motion).
 *
 * Wird global geladen (vor widget.css / layout.css). JS schreibt die
 * Werte an document.documentElement; CSS reagiert.
 */

/* ---------- 1. Defaults ------------------------------------------------ */

:root {
    --a11y-font-size-scale: 1;
    --a11y-line-height-scale: 1;
    --a11y-letter-spacing-em: 0;
    --a11y-word-spacing-em: 0;

    /* Farb-Tokens werden nur in den Hochkontrast-/Monochrom-Modi aktiv. */
    --a11y-focus-color: #0066ff;
    --a11y-focus-width: 3px;
}

/* ---------- 2. Anwendung auf Typografie -------------------------------- */

/*
 * Schriftgröße skalieren — bewusst über `zoom`, NICHT über root-font-size.
 *
 * Reines root-font-size-Scaling wirkt nur auf rem/em-Text. Viele Themes
 * geben Fließtext in absoluten px an (p,li{font-size:19px}, body 14px) —
 * solche Werte ignorieren root-font-size-Skalierung. `zoom` skaliert die
 * gerenderte Größe und überschreibt damit ZUVERLÄSSIG auch px, ohne
 * Spezifitäts-/Ladereihenfolge-Kampf mit dem Theme.
 *
 * Default 1 → `zoom: 1` ist ein No-op (inaktiv bis User die Größe ändert).
 * Tradeoff: zoom vergrößert den gesamten Inhalt (Layout/Bilder/Toolbar),
 * nicht nur Schrift — genau das macht es theme-unabhängig wirksam.
 * `!important` analog zur Text-Spacing-Regel (WCAG 1.4.4).
 */
:root {
    zoom: var(--a11y-font-size-scale, 1) !important;
}

/*
 * Reflow-Schutz bei aktiver Schriftskalierung — WCAG 1.4.10 (Reflow).
 *
 * `zoom` am :root verkleinert den Layout-Raum entsprechend: bei Faktor 1.5
 * rechnet der Browser mit 402/1.5 = 268 CSS-px Breite und skaliert das
 * Ergebnis wieder hoch. Normale Layouts (%, max-width, Flex, Grid) fließen
 * dadurch von selbst korrekt um. Drei Dinge tun das NICHT und schieben den
 * Inhalt auf schmalen Viewports aus dem Bild — gemessen auf 402 px (iPhone):
 *
 *   1. Viewport-Einheiten. `width: 100vw` bleibt bei 402 px, obwohl der
 *      Layout-Raum nur noch 268 px breit ist → gerendert 603 px. Der
 *      klassische Full-Bleed-Hero. Deshalb `max-width: 100%`: vw-Boxen
 *      werden auf ihren Container zurückgeholt.
 *   2. `white-space: nowrap` (Navigation, Buttons, Badges). Im engeren
 *      Layout-Raum passt der Text nicht mehr in eine Zeile und läuft
 *      heraus. `pre`/`code`/`textarea` bleiben ausgenommen — dort ist
 *      Nicht-Umbrechen inhaltlich gewollt.
 *   3. Flex-Reihen ohne `flex-wrap`: NICHT behandelt — siehe unten.
 *
 * Bewusst NICHT gesetzt: `flex-wrap: wrap` auf allen Elementen. Die
 * Annahme, das sei unschädlich, weil die Eigenschaft nur auf
 * Flex-Container wirkt, ist falsch. Bei `flex-direction: column` mit
 * begrenzter Höhe (z. B. ein Hero mit `height: 100vh`) erzeugt `wrap`
 * MEHRSPALTIGE Flex-Layouts: was nicht in die Höhe passt, fliesst in
 * eine neue Spalte RECHTS daneben. Auf einem 402-px-Viewport landet der
 * komplette Inhalt dadurch ausserhalb des Bildes und wird von
 * `overflow-x: hidden` weggeschnitten — die Seite ist weiss.
 * (Gemessen an g-m-m.de: Hero-Row bei left 390 px statt 0.)
 *
 * Nicht umbrechende Flex-Reihen bleiben damit ein Theme-Thema: das Theme
 * weiss, welche seiner Reihen gefahrlos umbrechen duerfen, dieses
 * Stylesheet weiss es nicht.
 *
 * Tabellen (und `pre`) können nicht unter ihre Mindestbreite umbrechen —
 * sie bekommen deshalb einen eigenen horizontalen Scroll-Container statt
 * die ganze Seite zu verschieben. WCAG 1.4.10 nimmt genau solche Inhalte
 * ausdrücklich aus.
 *
 * `!important` analog zu den übrigen User-Anpassungen: die Wahl des Users
 * hat Vorrang vor dem Theme-Design. `:where()` hält die Spezifität bei 0,
 * damit ein Theme im Bedarfsfall gezielt gegensteuern kann.
 *
 * Die Flag-Klasse setzt store.js ausschließlich beim Vergrößern
 * (Faktor > 1) — nur dann wird der Layout-Raum enger als der Viewport;
 * im Default- wie im Verkleinerungs-Fall ändert sich nichts.
 */
/*
 * Kein horizontaler Seiten-Scroll bei aktiver Schriftskalierung.
 *
 * Das ist NICHT nur Kosmetik, sondern die Voraussetzung dafür, dass das
 * Tool selbst bedienbar bleibt. Mechanik (gemessen, Chrome Mobile, 360 px):
 *
 *   1. Bleibt trotz der Regeln oben ein Rest-Überlauf stehen (Theme-Reihen,
 *      die nicht umbrechen können), multipliziert `zoom` am :root ihn mit
 *      dem Faktor: 356 px Inhalt × 1.6 = 570 px gerenderte Dokumentbreite.
 *   2. Mobile Browser vergrößern daraufhin den LAYOUT-Viewport auf die
 *      Dokumentbreite — `innerWidth` meldet 570, sichtbar sind weiter 360.
 *   3. Der Layout-Viewport ist der enthaltende Block für `position: fixed`.
 *      Toolbar-Button und Panel hängen an `right: 1rem` — also an 570 statt
 *      an 360 — und stehen damit rund 210 px RECHTS NEBEN dem Bildschirm.
 *      Genau das ist das „Panel aus dem Bild geschoben"-Bild vom Handy;
 *      am Desktop tritt es nie auf, weil dort kein Überlauf entsteht.
 *
 * `overflow-x: hidden` am <html> hält den Layout-Viewport auf der
 * sichtbaren Breite (gemessen: 570 → 360) und bringt damit die gesamte
 * fixe UI zurück ins Bild. Vertikal bleibt alles normal scrollbar:
 * die Überlauf-Angabe propagiert vom <html> auf den Viewport, das
 * Element selbst behält `overflow: visible` — `position: sticky` im
 * Theme funktioniert unverändert weiter.
 *
 * `clip` statt `hidden` wäre die modernere Wahl, löst das Problem hier
 * aber nur halb (gemessen: 570 → 413, Panel weiterhin außerhalb).
 *
 * Nur aktiv, solange der User wirklich vergrößert hat — im Default-Fall
 * bleibt das Scroll-Verhalten der Seite unangetastet. Inhalte, die
 * grundsätzlich breiter sein dürfen (Tabellen, `pre`), haben weiter
 * unten ihren eigenen Scroll-Container und werden daher nicht
 * abgeschnitten.
 */
html.a11y-font-scale-active {
    overflow-x: hidden !important;
}

/*
 * Gegenstueck zur Regel darueber: verhindert eine ZWEITE Scrollbar.
 *
 * Solange <html> auf 'visible' steht, reicht der Browser die
 * Overflow-Angabe des <body> an den Viewport durch — ein
 * 'body { overflow-x: hidden }' (in vielen Themes vorhanden) kostet dann
 * nichts. Sobald <html> selbst einen Wert bekommt, entfaellt diese
 * Weitergabe: der <body> behaelt seinen Wert fuer sich und wird damit zum
 * eigenen Scroll-Container. Ergebnis sind zwei Scrollbalken nebeneinander,
 * sobald der User vergroessert.
 *
 * 'clip' klemmt genauso ab wie 'hidden', erzeugt aber per Definition
 * keinen Scroll-Container — die Absicht des Themes bleibt erhalten, der
 * zweite Balken verschwindet.
 *
 * Wichtig ist dabei die getrennte Achse: 'overflow-x: visible' waere hier
 * falsch, denn sobald das Theme die Seite senkrecht sperrt (z. B.
 * 'body.overflow-hidden' bei offener Navigation) wuerde der Browser das
 * 'visible' der anderen Achse in 'auto' umdeuten — und der waagerechte
 * Balken waere zurueck. 'clip' bleibt in dieser Kombination stehen.
 *
 * Zwei Deklarationen: Engines ohne 'clip' verwerfen die zweite Zeile und
 * behalten 'visible'. Abgeschnitten wird dort ohnehin schon am <html>.
 */
html.a11y-font-scale-active > body {
    overflow-x: visible;
    overflow-x: clip;
}

html.a11y-font-scale-active :where(*) {
    max-width: 100% !important;
    overflow-wrap: break-word;
}

html.a11y-font-scale-active :where(:not(pre, code, kbd, samp, textarea, pre *, code *)) {
    white-space: normal !important;
}

html.a11y-font-scale-active :where(table, pre) {
    display: block;
    width: max-content;
    max-width: 100% !important;
    overflow-x: auto;
}

/*
 * Table-Layout-Wrapper aufbrechen.
 *
 * Ein `display: table`-Kasten schrumpft nie unter seine Mindestbreite —
 * und die ist bei einem enthaltenen Bild dessen Eigenbreite. `max-width`
 * greift dort also nicht: das Bild ragt heraus, obwohl die Regel oben
 * gesetzt ist (gemessen an einer FSC-Galerie: Container 177 px,
 * Figure 323 px). Als Block-Box klappt `max-width: 100%` am Bild dagegen
 * normal.
 *
 * `figure` ist semantisches Markup — `display: table` ist dort immer ein
 * Layout-Kniff. Die `ce-*`-Klassen kommen aus fluid_styled_content
 * (Core): `.ce-gallery` ist eine Tabelle, `.ce-column` eine Tabellenzelle.
 * Als Blöcke stapeln sich die Spalten untereinander — genau das erwartet
 * man bei 200 % Schriftgröße auf einem Telefon.
 */
html.a11y-font-scale-active :where(figure, .ce-gallery, .ce-row, .ce-column) {
    display: block !important;
    width: auto !important;
}

/*
 * Ersetzte Elemente: Breite deckeln und Höhe mitziehen lassen, sonst
 * werden Bilder beim Deckeln gestaucht statt proportional verkleinert.
 */
html.a11y-font-scale-active :where(img, svg, video, canvas, iframe, embed, object) {
    max-width: 100% !important;
    height: auto !important;
}

/*
 * Zeilen-/Wort-/Buchstabenabstand: nur dort wirken, wo der User
 * explizit etwas anfordert (Default 1 bzw. 0 → no-op).
 */
body {
    line-height: calc(1.5 * var(--a11y-line-height-scale, 1));
    letter-spacing: calc(1em * var(--a11y-letter-spacing-em, 0));
    word-spacing: calc(1em * var(--a11y-word-spacing-em, 0));
}

/*
 * Aggressives line-height-Override: greift NUR, wenn der User die
 * Zeilenhöhe per Tool wirklich verändert hat (Flag-Klasse aus store.js).
 * Themes setzen line-height häufig explizit auf einzelne Elemente
 * (h1/h2/p/.card-title etc.) — ohne diese Regel würde die Body-Regel
 * von genau diesen Stellen wieder „überstimmt" und die User-Wahl wäre
 * wirkungslos. !important ist hier gewollt: WCAG 1.4.12 (Text Spacing)
 * verlangt, dass diese User-Anpassung Vorrang vor Design hat.
 *
 * Die Skala 1.5 entspricht der WCAG-Baseline (Zeilenhöhe ≥ 1.5 × font-size).
 */
html.a11y-line-height-active *,
html.a11y-line-height-active *::before,
html.a11y-line-height-active *::after {
    line-height: calc(1.5 * var(--a11y-line-height-scale, 1)) !important;
}

/* ---------- 3. Flag-Klassen am <html> ---------------------------------- */

/*
 * Hochkontrast-Modus — robuste, aber verträgliche Überschreibung.
 *
 * Vererbung allein (color am body) reicht NICHT: jedes Element mit eigener
 * color-/background-Regel würde gewinnen. Deshalb universelle Selektoren +
 * !important (per css-vars-architect für User-Anpassungen legitim). Die
 * dreifache Flag-Klasse hebt die Spezifität auf (0,3,x) an, damit color UND
 * background IMMER gemeinsam gewinnen — sonst passiert der Worst Case:
 * background gewinnt (Theme setzt keine bg-Regel), color verliert gegen eine
 * spezifischere Theme-Regel → dunkler Text auf Schwarz = unlesbar.
 *
 * WICHTIG — background-color NUR auf echte Elemente, NICHT auf ::before/::after:
 * dekorative Overlay-Pseudoelemente (position:absolute; inset:0) würden sonst
 * zu opaken schwarzen Kästen und verdecken den gesamten Text ("alles schwarz").
 *
 * Bewusst OHNE `background-image: none`: Verläufe/Hintergrundbilder bleiben
 * erhalten (funktionale Icons via CSS-Hintergrund gehen nicht verloren).
 *
 * Die eigenen Shadow-DOM-Komponenten sind per :not(...) ausgenommen — sonst
 * bekäme ihr Host schwarzen Hintergrund, während der Text im Shadow-DOM (den
 * diese Regel nicht erreicht) dunkel bliebe. Sie stylen sich selbst über die
 * reflektierte Host-Klasse .a11y-contrast-high (siehe Komponenten).
 */
html.a11y-contrast-high {
    --a11y-bg: #000000;
    --a11y-fg: #ffffff;
    --a11y-link: #ffff00;
    --a11y-link-visited: #ff9bff;
    color-scheme: dark;                 /* native Controls/Scrollbars dunkel */
    background-color: var(--a11y-bg);
    color: var(--a11y-fg);
}

/* Die dreifache Flag-Klasse hebt die Basis-Spezifität auf (0,3,x), damit color
   UND background gemeinsam auch spezifischere Theme-Regeln schlagen. Die
   semantischen Regeln (Links, Buttons, SVG …) stehen danach und gewinnen bei
   Gleichstand per Quellreihenfolge. */

/* 1a) Basis: alle echten Elemente Schwarz/Weiß. -webkit-text-fill-color folgt
       via currentColor der jeweiligen `color` — so bleiben Links/Hover farbig
       (sonst würde die Basis-Weiß-Füllung die Glyphen übermalen). */
html.a11y-contrast-high.a11y-contrast-high.a11y-contrast-high * {
    background-color: var(--a11y-bg) !important;
    color: var(--a11y-fg) !important;
    border-color: var(--a11y-fg) !important;
    -webkit-text-fill-color: currentColor !important;
}

/* 1b) Eigene Shadow-Komponenten NICHT schwärzen — sie stylen sich selbst über
       die gespiegelte Host-Klasse. Höhere Spezifität (0,3,2) als die Basis. */
html.a11y-contrast-high.a11y-contrast-high.a11y-contrast-high
    :is(a11y-toolbar, a11y-settings-panel, a11y-magnifier) {
    background-color: transparent !important;
    color: inherit !important;
    border-color: currentColor !important;
    -webkit-text-fill-color: currentColor !important;
}

/* 1c) Kontrastschädliche Effekte raus — auch auf Pseudo-Elementen, aber OHNE
       deren Hintergrund zu schwärzen: Overlay-::before/::after würden sonst zu
       opaken schwarzen Kästen und verdecken den Text ("alles schwarz"). */
html.a11y-contrast-high *,
html.a11y-contrast-high *::before,
html.a11y-contrast-high *::after {
    box-shadow: none !important;
    text-shadow: none !important;
}

/* 2) Links unterscheidbar — auch verschachtelte Inline-Kinder */
html.a11y-contrast-high.a11y-contrast-high.a11y-contrast-high a,
html.a11y-contrast-high.a11y-contrast-high.a11y-contrast-high a * {
    color: var(--a11y-link) !important;
    text-decoration: underline !important;
}
html.a11y-contrast-high.a11y-contrast-high.a11y-contrast-high a:visited,
html.a11y-contrast-high.a11y-contrast-high.a11y-contrast-high a:visited * {
    color: var(--a11y-link-visited) !important;
}
html.a11y-contrast-high.a11y-contrast-high.a11y-contrast-high a:hover,
html.a11y-contrast-high.a11y-contrast-high.a11y-contrast-high a:focus,
html.a11y-contrast-high.a11y-contrast-high.a11y-contrast-high a:hover *,
html.a11y-contrast-high.a11y-contrast-high.a11y-contrast-high a:focus * {
    color: var(--a11y-bg) !important;
    background-color: var(--a11y-link) !important;   /* invertierter Hover */
}

/* 3) Bedienelemente mit sichtbarem Rahmen (sonst verschwinden sie im Schwarz) */
html.a11y-contrast-high.a11y-contrast-high.a11y-contrast-high button,
html.a11y-contrast-high.a11y-contrast-high.a11y-contrast-high input,
html.a11y-contrast-high.a11y-contrast-high.a11y-contrast-high select,
html.a11y-contrast-high.a11y-contrast-high.a11y-contrast-high textarea,
html.a11y-contrast-high.a11y-contrast-high.a11y-contrast-high [role="button"] {
    border: 2px solid var(--a11y-fg) !important;
}
html.a11y-contrast-high ::placeholder {
    color: #cccccc !important;
    opacity: 1 !important;
}

/* 4) SVG-Icons folgen der Textfarbe */
html.a11y-contrast-high.a11y-contrast-high.a11y-contrast-high svg,
html.a11y-contrast-high.a11y-contrast-high.a11y-contrast-high svg * {
    fill: currentColor !important;
    stroke: currentColor !important;
}

/* 5) Bilder/Videos NICHT einfärben, nur auf Schwarz absetzen + Theme-Filter lösen */
html.a11y-contrast-high.a11y-contrast-high.a11y-contrast-high img,
html.a11y-contrast-high.a11y-contrast-high.a11y-contrast-high picture,
html.a11y-contrast-high.a11y-contrast-high.a11y-contrast-high video,
html.a11y-contrast-high.a11y-contrast-high.a11y-contrast-high canvas {
    background-color: var(--a11y-bg) !important;
    filter: none !important;
}

/* 6) Fokus hochsichtbar */
html.a11y-contrast-high :focus-visible {
    outline: var(--a11y-focus-width, 3px) solid var(--a11y-link) !important;
    outline-offset: 2px !important;
}

/* Schwarz-Weiß-Modus (Monochrom) */
html.a11y-monochrome body {
    filter: grayscale(1);
}

/* Link- und Fokus-Hervorhebung als zusätzlich aktivierbare Modi */
html.a11y-link-highlight a {
    text-decoration: underline;
    text-decoration-thickness: 2px;
    text-underline-offset: 0.15em;
    outline: 1px dashed currentColor;
    outline-offset: 2px;
}

html.a11y-focus-highlight :focus-visible {
    outline: var(--a11y-focus-width, 3px) solid var(--a11y-focus-color, #0066ff);
    outline-offset: 3px;
    box-shadow: 0 0 0 6px rgba(0, 102, 255, 0.25);
}

/* ---------- 4. Bewegungsreduktion -------------------------------------- */

/*
 * System-Präferenz: wenn der User auf OS-Ebene reduced-motion gewählt
 * hat, schalten wir aggressiv Animationen ab. Das gilt immer und kann
 * vom Tool nicht überstimmt werden.
 */
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}

/*
 * User-Override über das Tool: derselbe Effekt, auch wenn das OS keine
 * Präferenz signalisiert hat.
 */
html.a11y-reduced-motion *,
html.a11y-reduced-motion *::before,
html.a11y-reduced-motion *::after {
    animation: none !important;
    transition: none !important;
}

/* ---------- 5. Manueller Auslöser-Button ------------------------------- */

/*
 * Default-Styling für den im manuellen Einbau-Modus selbst platzierten
 * Auslöser (lib.a11yToolTrigger → <button class="a11y-tool-trigger">).
 * Bewusst dezent und vollständig überschreibbar — das Markup gehört dem
 * Integrator. Nutzt die im Backend gewählten Farb-Tokens, damit der Button
 * zum Rest des Tools passt.
 */
.a11y-tool-trigger {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    min-height: 48px;
    padding: 0.5rem 1rem;
    background: var(--a11y-color-base, #003a73);
    color: #ffffff;
    border: 2px solid transparent;
    border-radius: 0.375rem;
    font: inherit;
    font-weight: 600;
    line-height: 1.2;
    cursor: pointer;
}

.a11y-tool-trigger:hover {
    background: color-mix(in srgb, var(--a11y-color-base, #003a73) 80%, black);
}

.a11y-tool-trigger:focus-visible {
    outline: 3px solid var(--a11y-color-accent, #ffd400);
    outline-offset: 3px;
    /* Der Auslöser steht im manuellen Modus auf einem unbekannten (oft
       hellen) Hintergrund. Der gelbe Ring allein erreicht dort keine
       3:1 (SC 1.4.11 / 2.4.13). Ein dunkler Begleitring sorgt dafür,
       dass der Fokus auf jedem Untergrund sichtbar bleibt. */
    box-shadow: 0 0 0 1px #1a1a1a, 0 0 0 6px #1a1a1a;
}

/* ---------- 6. Ausgelagerter runder Button (wie der Toolbar-Button) ---- */

/*
 * Übernimmt das Aussehen des schwebenden Toolbar-Buttons (<a11y-toolbar>):
 * runder Button in der Basisfarbe mit weißem Rand, Schatten, Hover-Scale
 * und Fokusring — ABER ohne position:fixed / z-index. Damit lässt sich der
 * Auslöser im manuellen Einbau-Modus selbst platzieren (z. B. in der
 * Navigation), ohne die feste Verankerung oben rechts.
 *
 * Verwendung (icon-only → aria-label nicht vergessen):
 *   <button type="button" class="a11y-tool-button"
 *           data-a11y-tool-trigger aria-label="Barrierefreiheit">
 *       <span aria-hidden="true">👁</span>
 *   </button>
 * Eigenes Bild statt Glyph: <img class="a11y-tool-button__icon" src="…" alt="">
 *
 * Nutzt dieselben Farb-Tokens wie der Original-Button; vollständig
 * überschreibbar, das Markup gehört dem Integrator.
 */
.a11y-tool-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 48px;
    min-height: 48px;
    padding: 0.5rem;
    background: var(--a11y-color-base, #003a73);
    color: #ffffff;
    border: 2px solid #ffffff;
    border-radius: 50%;
    cursor: pointer;
    font-size: 2rem;
    line-height: 1;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.35);
}

/* Eigenes Bild quadratisch einpassen, weißer Kreis als Hintergrund (analog
   zum Original-Toolbar-Button). */
.a11y-tool-button__icon {
    width: 28px;
    height: 28px;
    object-fit: contain;
    border-radius: 50%;
    background: #ffffff;
    padding: 2px;
}

.a11y-tool-button:hover {
    background: color-mix(in srgb, var(--a11y-color-base, #003a73) 80%, black);
}

.a11y-tool-button:focus-visible {
    outline: 3px solid var(--a11y-color-accent, #ffd400);
    outline-offset: 3px;
    /* Dunkler Begleitring: hält den Fokus auch auf hellem/unbekanntem
       Untergrund über 3:1 sichtbar (SC 1.4.11 / 2.4.13). */
    box-shadow: 0 0 0 1px #1a1a1a, 0 0 0 6px #1a1a1a;
}

/* Bewegung nur ohne reduced-motion-Präferenz. */
@media (prefers-reduced-motion: no-preference) {
    .a11y-tool-button {
        transition: transform 0.15s ease-out, background-color 0.15s ease-out;
    }
    .a11y-tool-button:hover {
        transform: scale(1.05);
    }
}

@media (prefers-reduced-motion: reduce) {
    .a11y-tool-button {
        transition: none;
    }
    .a11y-tool-button:hover {
        transform: none;
    }
}
