/* ============================================================
   parasignals.de — eigene Ergänzungen
   Speicherort: assets/css/custom.css

   site.css wird von tools/build.py aus den alten Blöcken erzeugt und bei
   jedem Lauf überschrieben. Diese Datei bleibt unberührt — hier gehören
   alle Regeln hin, die es auf der alten Seite noch nicht gab:
   Sprachumschalter, News-Liste, Formularmeldungen, Fehlerseite.
   ============================================================ */

/* ============================================================
   GRUNDGESTALTUNG — nicht entfernen
   ============================================================
   Diese Regeln kamen frueher vom WordPress-Theme (twentytwentyfive)
   und fehlten deshalb im Dump. Ohne sie erscheint die Seite mit
   weissem Hintergrund und Standardschrift — alle Bloecke darueber
   setzen naemlich nur ihre eigenen Farben, nie die der Seite.

   Die Werte stammen aus den Bloecken selbst:
     Hintergrund  aus .ps-header  rgba(10,10,12,.75)
     Textfarbe    aus .ps-nav a   #ccc
     Akzent       durchgaengig    #00c8ff
     Schrift      System-Schrift; 'Nerik' NUR fuer .ps-title
   ============================================================ */

:root {
    --ps-bg: #0a0a0c;
    --ps-bg-soft: #0f1116;
    --ps-text: #c9ced6;
    --ps-text-strong: #ffffff;
    --ps-accent: #00c8ff;
    --ps-line: rgba(0, 200, 255, .12);
}

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

html {
    /* Beides aus den alten globalen Stilen uebernommen: Ohne
       overflow-x:hidden schieben die Abschnitte, die mit
       margin-left:calc(50% - 50vw) ueber die volle Breite gehen,
       einen waagerechten Scrollbalken heraus. */
    overflow-x: hidden;
    width: 100%;
    scroll-behavior: smooth;
    -webkit-text-size-adjust: 100%;
}

body {
    overflow-x: hidden;
    width: 100%;
    margin: 0;
    background: var(--ps-bg);
    color: var(--ps-text);
    /* NICHT Nerik. Die Schrift gehoert im Original ausschliesslich zum
       grossen Schriftzug im Hero (.ps-title) — dort steht sie auch weiter
       im site.css. Als Fliesstext ist sie schlecht lesbar und war auf der
       alten Seite nie so eingesetzt. */
    font-family: system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
    /* clamp: waechst mit der Bildschirmbreite, bleibt aber zwischen
       15 und 17 Pixeln — so muss keine Schriftgroesse je Geraet
       nachgepflegt werden. */
    font-size: clamp(15px, .4vw + 14px, 17px);
    line-height: 1.7;
    -webkit-font-smoothing: antialiased;
}

img,
video,
canvas,
svg {
    max-width: 100%;
}

img,
video {
    height: auto;
}

h1, h2, h3, h4, h5, h6 {
    color: var(--ps-text-strong);
    line-height: 1.25;
    /* Ueberschriften duerfen nie ueber den Rand laufen, auch nicht bei
       langen zusammengesetzten Woertern auf schmalen Bildschirmen. */
    overflow-wrap: break-word;
}

h1 { font-size: clamp(2rem, 5vw, 3.4rem); }
h2 { font-size: clamp(1.6rem, 3.6vw, 2.5rem); }
h3 { font-size: clamp(1.2rem, 2.2vw, 1.5rem); }

a {
    color: var(--ps-accent);
}

p {
    overflow-wrap: break-word;
}

/* Die Seite fuellt immer mindestens den Bildschirm — sonst klebt der
   Fussbereich bei kurzen Seiten (404, Twitch) in der Mitte. */
body {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    min-height: 100dvh;   /* beruecksichtigt die Leisten auf Mobilgeraeten */
}

#ps-main {
    flex: 1;
}


/* ---------- Sprungmarke für Tastaturbedienung ---------- */
/* Sichtbar erst beim Anspringen mit Tab — für Besucher, die nicht mit der
   Maus arbeiten, sonst müssten sie sich durch das ganze Menü tabben. */
.ps-skip {
    position: absolute;
    left: -9999px;
    top: 0;
    z-index: 2000;
    padding: 12px 20px;
    background: #00c8ff;
    color: #06080c;
    font-weight: 700;
    border-radius: 0 0 8px 0;
}
.ps-skip:focus {
    left: 0;
}

/* ---------- Sprachumschalter (aufklappbar) ---------- */
/* Aufbau mit <details>/<summary>: Das Aufklappen kann der Browser selbst —
   kein JavaScript, funktioniert mit Tastatur und Screenreader. */
.ps-lang {
    position: relative;
    flex-shrink: 0;
}

.ps-lang summary {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-height: 40px;
    padding: 6px 12px;
    border: 1px solid rgba(0, 200, 255, .18);
    border-radius: 50px;
    color: #ccc;
    font-size: .85rem;
    font-weight: 700;
    letter-spacing: .5px;
    cursor: pointer;
    list-style: none;           /* das Standard-Dreieck weg */
    transition: color .25s ease, background .25s ease, border-color .25s ease;
}

/* Safari braucht dafuer eine eigene Zeile */
.ps-lang summary::-webkit-details-marker {
    display: none;
}

.ps-lang summary:hover,
.ps-lang[open] summary {
    color: #00c8ff;
    border-color: rgba(0, 200, 255, .5);
    background: rgba(0, 200, 255, .08);
}

.ps-lang-flag {
    font-size: 1.15rem;
    line-height: 1;
}

.ps-lang-arrow {
    width: 14px;
    height: 14px;
    fill: none;
    stroke: currentColor;
    stroke-width: 2.4;
    stroke-linecap: round;
    stroke-linejoin: round;
    transition: transform .25s ease;
}

.ps-lang[open] .ps-lang-arrow {
    transform: rotate(180deg);
}

.ps-lang-list {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    z-index: 1100;
    min-width: 170px;
    margin: 0;
    padding: 6px;
    list-style: none;
    background: rgba(12, 14, 18, .97);
    backdrop-filter: blur(14px);
    border: 1px solid rgba(0, 200, 255, .2);
    border-radius: 14px;
    box-shadow: 0 16px 40px rgba(0, 0, 0, .55);
}

.ps-lang-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 14px;
    border-radius: 10px;
    color: #ccc;
    text-decoration: none;
    font-size: .95rem;
    white-space: nowrap;
    transition: background .2s ease, color .2s ease;
}

.ps-lang-item:hover,
.ps-lang-item:focus-visible {
    background: rgba(0, 200, 255, .12);
    color: #00c8ff;
}

.ps-lang-item.is-active {
    color: #00c8ff;
    font-weight: 700;
}

/* ---------- Inhaltsbreite ---------- */
.ps-wrap {
    width: min(1400px, 92%);
    margin-inline: auto;
}

/* ---------- News-Übersicht ---------- */
.ps-news-grid {
    display: grid;
    /* auto-fit + minmax: die Anzahl der Spalten ergibt sich aus dem Platz,
       ganz ohne Umbruchpunkte. Unter 320 px wird einspaltig umbrochen. */
    grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr));
    gap: 28px;
    padding: 40px 0 80px;
}
.ps-news-card {
    display: flex;
    flex-direction: column;
    background: rgba(255, 255, 255, .03);
    border: 1px solid rgba(0, 200, 255, .12);
    border-radius: 16px;
    overflow: hidden;
    transition: transform .3s ease, border-color .3s ease, box-shadow .3s ease;
}
.ps-news-card:hover {
    transform: translateY(-4px);
    border-color: rgba(0, 200, 255, .4);
    box-shadow: 0 12px 34px rgba(0, 0, 0, .45);
}
.ps-news-img img {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: 4 / 3;
    object-fit: cover;
}
.ps-news-body {
    padding: 22px 24px 26px;
    display: flex;
    flex-direction: column;
    gap: 10px;
    flex: 1;
}
.ps-news-body time {
    font-size: .8rem;
    letter-spacing: 1px;
    text-transform: uppercase;
    color: #00c8ff;
}
.ps-news-body h3 {
    margin: 0;
    font-size: 1.25rem;
    line-height: 1.3;
}
.ps-news-body h3 a {
    color: #fff;
    text-decoration: none;
}
.ps-news-body h3 a:hover {
    color: #00c8ff;
}
.ps-news-body p {
    margin: 0;
    color: #b6bcc6;
    font-size: .95rem;
    line-height: 1.6;
    flex: 1;
}

/* ---------- Schaltfläche ---------- */
.ps-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 44px;
    padding: 12px 26px;
    border-radius: 50px;
    background: #00c8ff;
    color: #06080c;
    font-weight: 700;
    text-decoration: none;
    align-self: flex-start;
    transition: filter .25s ease, transform .25s ease;
}
.ps-btn:hover {
    filter: brightness(1.12);
    transform: translateY(-2px);
}
.ps-btn-sm {
    min-height: 38px;
    padding: 8px 18px;
    font-size: .9rem;
}

/* ---------- Meldung über dem Kontaktformular ---------- */
.ps-notice {
    margin: 24px 0;
    padding: 16px 20px;
    border-radius: 12px;
    border: 1px solid;
    font-size: 1rem;
    line-height: 1.5;
}
.ps-notice.is-ok {
    background: rgba(46, 204, 113, .1);
    border-color: rgba(46, 204, 113, .45);
    color: #8ff0b6;
}
.ps-notice.is-err {
    background: rgba(255, 90, 110, .1);
    border-color: rgba(255, 90, 110, .45);
    color: #ffb3bd;
}

/* ---------- Honigtopf ---------- */
/* Muss für Menschen unsichtbar sein, für Programme aber wie ein normales
   Feld aussehen. Deshalb NICHT display:none — manche Ausfüllprogramme
   überspringen versteckte Felder und würden die Falle bemerken. */
.ps-hp {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

/* ---------- Fehlerseite ---------- */
.ps-404 {
    padding: 120px 0 140px;
    text-align: center;
}
.ps-404 h1 {
    font-size: clamp(4rem, 18vw, 9rem);
    margin: 0 0 10px;
    color: #00c8ff;
    line-height: 1;
}
.ps-404 .ps-btn {
    align-self: center;
}

/* ---------- Kleine Bildschirme ---------- */
@media (max-width: 900px) {
    /* Im ausgeklappten Menü steht der Umschalter über den Symbolen */
    .ps-lang {
        order: 3;
        margin-top: 8px;
    }
}

/* ---------- Bewegung reduzieren ---------- */
/* ABSICHTLICH ENG GEFASST.
   Vorher stand hier eine Regel auf * mit !important, die JEDE Animation
   abgeschaltet hat — auch den Glitch-Schriftzug und die Karten-Effekte.
   Auf der alten WordPress-Seite gab es so etwas nicht; dadurch sah die
   neue Seite bei manchen Besuchern ohne Grund tot aus.

   Jetzt betroffen sind nur: das weiche Scrollen und die Einblende-
   Uebergaenge, die ich selbst ergaenzt habe. Die Animationen aus dem
   alten Design bleiben unangetastet — sie gehoeren zum Aussehen der
   Seite, nicht zur Bedienung. */
@media (prefers-reduced-motion: reduce) {
    html {
        scroll-behavior: auto;
    }

    .ps-reveal,
    .ps-reveal-left,
    .ps-reveal-right,
    .ps-f-reveal,
    .psa-reveal,
    .pso-reveal,
    .psl-reveal {
        transition: none;
    }

    .ps-totop,
    .ps-news-card,
    .ps-lang-arrow {
        transition: none;
    }
}


/* ============================================================
   Kontaktformular
   ============================================================
   Ersetzt das frühere WPForms-Plugin. Aufbau siehe
   content/de/kontakt.html, Verarbeitung in inc/contact.php.
   ============================================================ */

.ps-form {
    display: flex;
    flex-direction: column;
    gap: 20px;
    margin-top: 28px;
    text-align: left;
}

.ps-field {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.ps-field label {
    font-size: .95rem;
    font-weight: 600;
    letter-spacing: .3px;
    color: #e6edf3;
}

/* Pflichtfeld-Stern. aria-hidden im HTML, weil "Stern" vorgelesen
   nichts erklärt — die Pflicht steht ohnehin im required-Attribut. */
.ps-req {
    color: #00c8ff;
}

.ps-field input,
.ps-field select,
.ps-field textarea {
    width: 100%;
    /* 16px verhindert, dass iOS beim Antippen in das Feld hineinzoomt.
       Alles darunter löst den Zoom aus und verschiebt das Layout. */
    font: inherit;
    font-size: 16px;
    padding: 14px 16px;
    color: #e6edf3;
    background: rgba(0, 0, 0, .35);
    border: 1px solid rgba(0, 200, 255, .18);
    border-radius: 12px;
    transition: border-color .25s ease, box-shadow .25s ease, background .25s ease;
}

.ps-field textarea {
    resize: vertical;
    min-height: 140px;
    line-height: 1.6;
}

/* Eigener Pfeil für die Auswahlliste — der Standardpfeil des Browsers
   ist auf dunklem Grund oft kaum zu sehen. */
.ps-field select {
    appearance: none;
    -webkit-appearance: none;
    background-image:
        url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2300c8ff' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 14px center;
    background-size: 20px;
    padding-right: 46px;
}

.ps-field select option {
    background: #0b0f14;
    color: #e6edf3;
}

.ps-field input:hover,
.ps-field select:hover,
.ps-field textarea:hover {
    border-color: rgba(0, 200, 255, .35);
}

.ps-field input:focus-visible,
.ps-field select:focus-visible,
.ps-field textarea:focus-visible {
    outline: none;
    border-color: #00c8ff;
    background: rgba(0, 0, 0, .5);
    box-shadow: 0 0 0 3px rgba(0, 200, 255, .18);
}

/* Erst rot färben, wenn der Besucher das Feld auch angefasst hat.
   :user-invalid tut genau das — anders als :invalid, das schon beim
   Laden greift und ein unausgefülltes Formular sofort rot leuchten
   lässt, bevor überhaupt jemand getippt hat.
   Browser ohne :user-invalid ignorieren die Regel; dort bleibt der
   Rahmen neutral, und die Prüfung übernimmt der Server. */
.ps-field input:user-invalid,
.ps-field select:user-invalid,
.ps-field textarea:user-invalid {
    border-color: rgba(255, 90, 110, .55);
}

.ps-field input:user-valid,
.ps-field select:user-valid,
.ps-field textarea:user-valid {
    border-color: rgba(46, 204, 113, .4);
}

/* ---------- Einwilligung ---------- */
.ps-check label {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    font-weight: 400;
    font-size: .92rem;
    line-height: 1.6;
    color: #b6bcc6;
    cursor: pointer;
}

.ps-check input[type="checkbox"] {
    flex-shrink: 0;
    width: 22px;
    height: 22px;
    margin-top: 2px;
    accent-color: #00c8ff;
    cursor: pointer;
}

.ps-form-hint {
    margin: 0;
    font-size: .85rem;
    line-height: 1.6;
    color: #8b94a0;
}

.ps-form-hint a {
    color: #00c8ff;
}

.ps-form .ps-btn {
    align-self: flex-start;
    border: none;
    cursor: pointer;
    font: inherit;
    font-weight: 700;
}

/* ============================================================
   Tabellen (Chatbefehle, Cookie-Übersicht)
   ============================================================ */

/* Auf schmalen Bildschirmen scrollt die Tabelle IN SICH, statt die
   ganze Seite breit zu machen. Ohne das schiebt eine einzige Tabelle
   das gesamte Layout auseinander. */
.ps-table-scroll {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    margin: 24px 0;
    border: 1px solid rgba(0, 200, 255, .12);
    border-radius: 12px;
}

.ps-table {
    width: 100%;
    border-collapse: collapse;
    font-size: .95rem;
}

.ps-table th,
.ps-table td {
    padding: 12px 16px;
    text-align: left;
    border-bottom: 1px solid rgba(255, 255, 255, .06);
}

.ps-table thead th {
    background: rgba(0, 200, 255, .08);
    color: #00c8ff;
    font-size: .8rem;
    letter-spacing: 1px;
    text-transform: uppercase;
    white-space: nowrap;
}

.ps-table tbody tr:last-child td {
    border-bottom: none;
}

.ps-table tbody tr:hover {
    background: rgba(255, 255, 255, .03);
}

.ps-table code {
    color: #00c8ff;
    white-space: nowrap;
}

/* ============================================================
   Textseiten (Impressum, Datenschutz, News)
   ============================================================ */

.ps-legal-text,
.ps-post,
.ps-news-intro {
    padding: 60px 0 80px;
    max-width: 860px;      /* längere Zeilen liest niemand gern */
}

.ps-legal-text h1,
.ps-post h1,
.ps-news-intro h1 {
    margin: 0 0 24px;
    line-height: 1.2;
}

.ps-legal-text h2,
.ps-post h2 {
    margin: 44px 0 14px;
    padding-top: 20px;
    border-top: 1px solid rgba(0, 200, 255, .12);
    color: #00c8ff;
    font-size: 1.4rem;
}

.ps-legal-text h3,
.ps-post h3 {
    margin: 28px 0 10px;
    font-size: 1.1rem;
}

.ps-legal-text p,
.ps-post p,
.ps-news-intro p {
    margin: 0 0 16px;
    line-height: 1.75;
    color: #c3c9d2;
}

.ps-legal-text ul,
.ps-post ul {
    margin: 0 0 20px;
    padding-left: 22px;
    line-height: 1.8;
    color: #c3c9d2;
}

.ps-legal-text li,
.ps-post li {
    margin-bottom: 6px;
}

.ps-legal-text a,
.ps-post a,
.ps-news-intro a {
    color: #00c8ff;
}

.ps-legal-text code,
.ps-post code {
    padding: 2px 7px;
    background: rgba(0, 200, 255, .1);
    border-radius: 5px;
    font-size: .9em;
}

/* ---------- Reihe aus Schaltflächen ---------- */
.ps-btn-row {
    display: flex;
    flex-wrap: wrap;
    gap: 14px;
    margin: 28px 0;
}

/* ---------- Sichtbarer Fokus ---------- */
/* Wer mit der Tastatur navigiert, muss sehen, wo er gerade ist.
   :focus-visible trifft nur Tastaturbedienung — Mausklicks lösen
   den Rahmen nicht aus. */
a:focus-visible,
button:focus-visible,
summary:focus-visible {
    outline: 2px solid #00c8ff;
    outline-offset: 3px;
    border-radius: 4px;
}

/* ============================================================
   Nach-oben-Knopf
   ============================================================
   Markup in inc/layout.php, Verhalten in assets/js/site.js.
   Erscheint erst ab 500 Pixeln Scrolltiefe.
   ============================================================ */

.ps-totop {
    position: fixed;
    right: 22px;
    /* Auf Mobilgeräten sitzt unten oft eine Systemleiste. env(safe-area-...)
       schiebt den Knopf darüber; ohne Leiste ist der Wert 0. */
    bottom: calc(22px + env(safe-area-inset-bottom, 0px));
    z-index: 900;

    display: grid;
    place-items: center;
    width: 48px;
    height: 48px;
    padding: 0;

    border: 1px solid rgba(0, 200, 255, .35);
    border-radius: 50%;
    background: rgba(10, 10, 12, .8);
    backdrop-filter: blur(10px);
    color: #00c8ff;
    cursor: pointer;

    /* Ausgangszustand: unsichtbar, etwas tiefer und nicht anklickbar.
       visibility:hidden ist wichtig — sonst bliebe der Knopf für die
       Tastatur erreichbar, obwohl niemand ihn sieht. */
    opacity: 0;
    visibility: hidden;
    transform: translateY(14px);
    transition: opacity .3s ease, transform .3s ease, visibility .3s,
                background .25s ease, border-color .25s ease;
}

.ps-totop.show {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
}

.ps-totop:hover {
    background: rgba(0, 200, 255, .16);
    border-color: #00c8ff;
}

.ps-totop svg {
    width: 22px;
    height: 22px;
    fill: none;
    stroke: currentColor;
    stroke-width: 2.2;
    stroke-linecap: round;
    stroke-linejoin: round;
}

@media (max-width: 600px) {
    .ps-totop {
        right: 16px;
        bottom: calc(16px + env(safe-area-inset-bottom, 0px));
        width: 44px;
        height: 44px;
    }
}

/* ============================================================
   Knöpfe in Flex-Spalten
   ============================================================
   .ps-btn-primary ist inline-flex. Steht so ein Knopf aber in einem
   Container mit "display:flex; flex-direction:column" — also in der
   News-Karte und im Kontaktformular — zieht der Container ihn
   standardmäßig auf die volle Breite (align-items: stretch).

   Das sah aus wie ein Balken über die ganze Karte, mit dem Text
   irgendwo darin. align-self holt ihn auf seine natürliche Breite
   zurück, justify-content zentriert die Beschriftung darin.
   ============================================================ */

.ps-news-body .ps-btn-primary,
.ps-news-body .ps-btn-ghost,
.ps-form .ps-btn-primary,
.ps-form .ps-btn-ghost,
.ps-post .ps-btn-primary,
.ps-legal-text .ps-btn-primary {
    align-self: flex-start;
    justify-content: center;
    text-align: center;
}

/* Auch außerhalb von Flex-Spalten soll die Beschriftung mittig sitzen */
.ps-btn-primary,
.ps-btn-ghost {
    justify-content: center;
    text-align: center;
}

/* Der Absenden-Knopf ist ein <button>, kein <a>: Schrift und Rahmen
   erbt er nicht von selbst. */
.ps-form button.ps-btn-primary {
    font-family: inherit;
    cursor: pointer;
}

/* Kleinere Fassung für die News-Karten */
.ps-btn-sm {
    padding: 10px 22px;
    font-size: .9rem;
}

/* Auf sehr schmalen Bildschirmen darf der Knopf die volle Breite
   nehmen — dort ist ein breiter Tippbereich richtig, kein Fehler. */
@media (max-width: 420px) {
    .ps-news-body .ps-btn-primary,
    .ps-form .ps-btn-primary {
        align-self: stretch;
    }
}

/* ============================================================
   Hero-Zoom flüssig machen
   ============================================================
   .ps-hero::before skaliert ein 1894x922-Bild plus Farbverlauf,
   20 Sekunden lang, endlos. Ohne eigene Ebene zeichnet der Browser
   das komplette Bild in JEDEM Einzelbild neu — daher das Ruckeln.

   will-change sagt ihm vorher Bescheid, dass sich transform ändert.
   Er legt die Ebene dann einmal an und verschiebt sie nur noch auf
   der Grafikkarte, statt neu zu zeichnen.

   Sparsam einsetzen: will-change kostet Arbeitsspeicher. Deshalb nur
   auf den Elementen, die tatsächlich dauerhaft animiert sind — nicht
   auf allem, was mal einen Übergang hat.
   ============================================================ */

.ps-hero::before,
.psa-hero::before,
.pso-hero::before,
.psl-hero::before,
.ps-donate-hero::before {
    /* Die Animation laeuft von GROSS nach KLEIN.
       Der Grund fuer das stufenweise Ruckeln: Firefox rastert die Ebene
       beim Startwert. Faengt die Animation bei scale(1) an und waechst,
       wuerde das Bild unscharf — also rastert der Browser unterwegs immer
       wieder neu, und jede Neuberechnung ist eine sichtbare Stufe.

       Startet sie dagegen beim GROESSTEN Wert, wird einmal in voller
       Aufloesung gerastert und danach nur noch verkleinert. Verkleinern
       braucht keine Neuberechnung — es laeuft komplett auf der
       Grafikkarte. Durch "alternate" sieht man trotzdem beides:
       hinein und wieder hinaus. */
    animation: psHeroZoom 26s ease-in-out infinite alternate !important;

    will-change: transform;
    backface-visibility: hidden;
    /* Zwingt eine eigene Ebene auf der Grafikkarte, auch in aelteren
       Browsern, die will-change noch nicht auswerten. */
    transform: translateZ(0);
}

@keyframes psHeroZoom {
    from {
        transform: scale(1.14) translateZ(0);
    }
    to {
        transform: scale(1) translateZ(0);
    }
}

/* Der Schleier darueber (.ps-hero::after) bewegt sich ebenfalls dauerhaft.
   Ohne eigene Ebene zwingt er den Hintergrund darunter zum Neuzeichnen —
   dann nuetzt die Optimierung oben nichts. */
.ps-hero::after,
.psa-hero::after,
.pso-hero::after {
    will-change: transform;
    transform: translateZ(0);
}

/* ---------- Maus-Partikel ---------- */
/* Liegt über allem, fängt aber keine Klicks ab. z-index unter dem
   Kopfbereich (1000), damit das Menü bedienbar bleibt. */
#ps-cursor-fx {
    position: fixed;
    inset: 0;
    z-index: 999;
    pointer-events: none;
}
