@charset "utf-8";
/* ===========================================================================
   Dynasty of Gods — Stylesheet
   ---------------------------------------------------------------------------
   Direktion: modern, minimalistisch, nach gemessenen Werten von ascension.gg.
   Zierrat, Rahmenbilder und Ornamente sind bewusst NICHT enthalten.

   Drei Regeln, die die Seite tragen:
     1. Gold ist Akzent, nicht Textfarbe. Ueberschriften laufen hell.
        (Ascension setzt Gold nur auf Knoepfe, Eyebrows und Zahlen.)
     2. Flaechen sind gestaffelt: Leiste HELLER als der Grund,
        Karte DUNKLER als der Grund. Nicht umgekehrt.
     3. Display-Serif nur fuer Ueberschriften, Nav und Knoepfe.
        Fliesstext, Zahlen und Labels laufen in Sans.

   Randbedingungen, die jede Zeile hier praegen:
     - Onion ueber http. Bei Tor-Sicherheitsstufe "Safest" sind JS, SVG und
       Webfonts aus. Alles muss ohne diese drei vollstaendig AUSSEHEN.
     - prefers-reduced-motion matcht im Tor Browser nie (resistFingerprinting).
       Ersatz ist der Schalter ?motion=off -> .motion-off.
     - Breakpoints nur 600/1000/1400 — Tor-Letterboxing quantisiert die Breite.
     - 17 Locales inkl. ae (Arabisch, RTL) -> durchgehend logische
       Eigenschaften. Kein left/right, kein margin-left, kein text-align:left.
   =========================================================================== */

/* ======================================================= Schriften ===== */
/*
   Zwei Familien, selbst ausgeliefert — kein Google-Aufruf. Eine Onion-Seite,
   die ein Stylesheet von fonts.googleapis.com nachlaedt, verraet jeden
   Aufruf ans Clearnet und wartet dabei auf eine zweite Tor-Strecke.

   Beaufort  Ueberschriften, Nav, Knoepfe. Deckt Latein, Kyrillisch und
             Griechisch vollstaendig ab (709 Zeichen), Arabisch nicht.
   Inter     Fliesstext, Zahlen, Labels. Variabel 100-900, nach Schriftraum
             zerlegt: wer /de/ liest, laedt 48 KB, nicht 220 KB.
   Noto      springt nur ein, wo die beiden nichts haben: Arabisch.

   font-display:swap heisst: Text steht sofort in der Ersatzschrift und
   wechselt, wenn die Datei da ist. Bei Tor-Sicherheitsstufe "Safest" sind
   Webfonts ganz aus — dann traegt die Ersatzkette in --d/--t allein.
*/
@font-face{font-family:Beaufort;font-style:normal;font-weight:400;font-display:swap;
  src:url(../fonts/beaufort-regular.woff2) format("woff2")}
@font-face{font-family:Beaufort;font-style:italic;font-weight:400;font-display:swap;
  src:url(../fonts/beaufort-italic.woff2) format("woff2")}
@font-face{font-family:Beaufort;font-style:normal;font-weight:700;font-display:swap;
  src:url(../fonts/beaufort-bold.woff2) format("woff2")}

/* Inter, variabel. Die unicode-range-Grenzen sind die von Google Fonts —
   der Browser laedt nur die Schnitte, in denen Zeichen der Seite liegen. */
@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;
  src:url(../fonts/inter-latin.woff2) format("woff2");
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,
    U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,
    U+FEFF,U+FFFD}
@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;
  src:url(../fonts/inter-latin-ext.woff2) format("woff2");
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,
    U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,
    U+2113,U+2C60-2C7F,U+A720-A7FF}
@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;
  src:url(../fonts/inter-cyrillic.woff2) format("woff2");
  unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;
  src:url(../fonts/inter-cyrillic-ext.woff2) format("woff2");
  unicode-range:U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}
@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;
  src:url(../fonts/inter-greek.woff2) format("woff2");
  unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF}
@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;
  src:url(../fonts/inter-greek-ext.woff2) format("woff2");
  unicode-range:U+1F00-1FFF}
@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;
  src:url(../fonts/inter-vietnamese.woff2) format("woff2");
  unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,
    U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB}

/* Arabisch. Weder Beaufort noch Inter haben ein einziges Zeichen davon;
   ohne diese beiden Schnitte entscheidet das Betriebssystem, wie /ae/
   aussieht — und auf einem nackten Linux-Tor-Browser heisst das Kaestchen. */
@font-face{font-family:"Noto Kufi Arabic";font-style:normal;font-weight:400 700;
  font-display:swap;src:url(../fonts/noto-kufi-arabic.woff2) format("woff2");
  unicode-range:U+0600-06FF,U+0750-077F,U+0870-088E,U+0890-0891,U+0897-08E1,
    U+08E3-08FF,U+200C-200E,U+2010-2011,U+204F,U+2E41,U+FB50-FDFF,U+FE70-FEFF}
@font-face{font-family:"Noto Sans Arabic";font-style:normal;font-weight:400 700;
  font-display:swap;src:url(../fonts/noto-sans-arabic.woff2) format("woff2");
  unicode-range:U+0600-06FF,U+0750-077F,U+0870-088E,U+0890-0891,U+0897-08E1,
    U+08E3-08FF,U+200C-200E,U+2010-2011,U+204F,U+2E41,U+FB50-FDFF,U+FE70-FEFF}

:root{
  color-scheme:dark;

  /* --- Flaechen ------------------------------------------------------- */
  --page:#0B0A08;        /* Seitengrund               Ascension #171717 */
  --bar:#16130F;         /* Kopfleiste, Fuss, Panel   Ascension #1E1E1E */
  --card:#070605;        /* Karten, tiefer als Grund  Ascension #0A0A0A */
  --card-act:#100E0A;    /* Karte bei Hover                             */
  --sunk:#040403;        /* Eingabefeld, Slot: tiefste Ebene            */

  /* --- Linien ---------------------------------------------------------- */
  --edge:#241F19;        /* Kartenrand, ruhend  — bewusst leiser als    */
  --edge-lit:#3A3228;    /* Kartenrand, aktiv     Ascensions #404040    */
  --engrave-dark:#070605;/* Gravurrille, obere Zeile: unter jeder Flaeche */
  --engrave-light:#332C23;/* Gravurrille, untere Zeile: die Lichtkante   */

  /* --- Atmosphaere: die drei Stellschrauben ---------------------------
     Gemessen am gerenderten Bild, nicht geschaetzt. Werte in
     Helligkeitsstufen gegen den Seitengrund (#0B0A08 = 10.1):
       Nebelbank  .07 -> etwa +9      deutlich, ohne die Kante zu zeigen
       Laterne    .09 -> etwa +5      als Tiefe lesbar, nicht als Fleck
       Vignette   .45 -> etwa -4.5    Rand faellt ab, Text bleibt frei
     Hoeher drehen macht die Seite nicht epischer, sondern fleckig. */
  --atmo-fog:.07;
  --atmo-lamp:.09;
  /* --atmo-vignette entfiel mit den Bildern: das gemalte
     Laternenlicht gestaltet den Rand, eine zusaetzliche
     Abdunklung haette dagegen gearbeitet. */
  --edge-in:#4A4136;     /* Eingabefeldrand           Ascension #525252 */

  /* --- Schrift --------------------------------------------------------- */
  --fg:#E3DDD0;          /* Ueberschriften, Hauptton                    */
  --fg-body:#C6BFB1;     /* Fliesstext                Ascension #CDCDCD */
  --fg-mut:#948B7C;      /* gedaempft                 Ascension #A3A3A3 */
  --fg-faint:#635C4F;    /* Labels, Datumszeilen                        */

  /* --- Akzent ---------------------------------------------------------- */
  --gold:#D2A24C;
  --gold-hi:#F0D6A6;
  --gold-dim:#AD8642;
  --gold-deep:#8A6A32;
  --alarm:#C0442F;
  --ok:#6FA55C;

  /* --- Ingame-Fassungen (am Client gemessen) --------------------------- */
  --frame:#5E564B;
  --frame-dim:#3A342C;
  --frame-face:#1A1918;

  /* --- Typografie ------------------------------------------------------ */
  --d:Beaufort,"Noto Kufi Arabic",Georgia,"Times New Roman",serif;
  --t:Inter,"Noto Sans Arabic",Arial,Helvetica,Verdana,sans-serif;
  --n:ui-monospace,"Cascadia Mono","Courier New",monospace;

  --shadow-head:0 0 5px rgba(0,0,0,.9),0 4px 6px rgba(0,0,0,.75);
  --shadow-sub:0 0 5px rgba(0,0,0,.85),0 1px 5px rgba(0,0,0,.7);

  /* --- Mass ------------------------------------------------------------ */
  --col:880px;           /* Inhaltsspalte  */
  --measure:660px;       /* Absatzmass     */
  --wide:1200px;         /* Fuss, Fries    */
  --gap:52px;            /* Sektionsrhythmus */
  --gutter:16px;
  --head:64px;
  --r:10px;              /* Radius Karte. 16px wirkt bei dunklen Flaechen
                            weich bis gummiartig; 10 haelt die Kante. */
  --r-s:4px;             /* Radius Bedienelement */
  --ease:cubic-bezier(.22,1,.36,1);
}
@media (min-width:1000px){:root{--gutter:24px}}

/* ======================================================= Grundlagen ==== */
*{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth}
.motion-off{scroll-behavior:auto}
body{background:var(--page);color:var(--fg-body);
  font:400 16px/1.62 var(--t);padding-block-start:var(--head);
  overflow-x:hidden;-webkit-font-smoothing:antialiased}
img,picture,svg,canvas{display:block;max-width:100%}
h1,h2,h3,h4{font-family:var(--d);font-weight:600;text-wrap:balance;color:var(--fg)}
a{color:var(--gold);text-decoration:underline;text-underline-offset:2px;
  transition:color .2s var(--ease)}
a:hover{color:var(--gold-hi)}
:focus-visible{outline:2px solid var(--gold-hi);outline-offset:3px;
  box-shadow:0 0 0 5px rgba(7,6,5,.95)}
::selection{background:var(--gold-deep);color:#000}
.vh{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);
  white-space:nowrap}
.num{font-variant-numeric:tabular-nums}
.skip{position:absolute;inset-block-start:-100px;inset-inline-start:16px;z-index:60;
  background:var(--gold);color:#000;padding:12px 20px;text-decoration:none;
  font:700 14px var(--d);text-transform:uppercase}
.skip:focus{inset-block-start:8px}

/* ======================================================= Kopfleiste ==== */
.hdr{flex-wrap:wrap;row-gap:0;position:fixed;inset-block-start:0;inset-inline:0;
  block-size:var(--head);z-index:40;
  background:var(--bar);box-shadow:0 1px 0 0 var(--edge-in);
  display:flex;align-items:center;gap:12px;padding-inline:var(--gutter)}
.brand{display:flex;align-items:center;gap:10px;text-decoration:none;flex:0 0 auto}
.brand .mark{width:20px;height:27px;flex:0 0 auto}
.brand span{font:600 16px/1 var(--d);color:var(--fg);letter-spacing:.09em;
  text-transform:uppercase;white-space:nowrap}
/* Die Navigation ist eine Liste — eine Vorleseansage sagt dann "6
   Eintraege" statt sechs Links hintereinander. Die Punkte nimmt
   list-style weg, den Einzug das padding:0.

   Unter 1000px war sie frueher ganz ausgeblendet: auf dem Telefon gab es
   ausser der Fusszeile keinen Weg zu einer anderen Seite. Statt eines
   Klappmenues (das JS oder einen Kontrollkasten braucht und bei
   Tor-Safest wackelt) scrollt die Leiste jetzt waagerecht — alle Punkte
   bleiben da und erreichbar. */
.nav{display:block;margin-inline-start:20px;min-inline-size:0;
  overflow-x:auto;scrollbar-width:none;-webkit-overflow-scrolling:touch}
.nav::-webkit-scrollbar{display:none}
.nav ul{display:flex;gap:2px;margin:0;padding:0;list-style:none}
.nav li{flex:0 0 auto}
@media (max-width:999px){
  :root{--head:106px}   /* eine Zeile Kopf + eine Zeile Navigation */
  .hdr{align-content:start;padding-block-start:6px}
  .nav{order:3;flex-basis:100%;margin-inline-start:0;
    border-block-start:1px solid var(--edge)}
  .nav a{padding:12px 11px;font-size:13.5px}
  .nav a::after{inset-block-end:8px;inset-inline:11px}
}
.nav a{position:relative;font:700 15px var(--d);text-transform:uppercase;
  color:var(--fg-mut);text-decoration:none;padding:20px 12px;
  transition:color .2s var(--ease);white-space:nowrap}
.nav a::after{content:"";position:absolute;inset-inline:12px;inset-block-end:16px;
  height:1px;background:var(--gold);transform:scaleX(0);transform-origin:0 50%;
  transition:transform .28s var(--ease)}
.nav a:hover{color:var(--fg)}
.nav a:hover::after,.nav a[aria-current]::after{transform:scaleX(1)}
.nav a[aria-current]{color:var(--fg)}
.acct{display:flex;gap:8px;align-items:center;margin-inline-start:auto;flex:0 0 auto}
/* Sprachwahl: <details> in der festen Kopfleiste, klappt ohne JS auf */
.lng{position:relative}
.lng summary{list-style:none;cursor:pointer;display:flex;align-items:center;gap:7px;
  padding:6px 9px;border:1px solid var(--edge-in);border-radius:var(--r-s);
  font:700 13px/1 var(--d);letter-spacing:.06em;color:var(--fg-mut);
  transition:color .2s var(--ease),border-color .2s var(--ease)}
.lng summary::-webkit-details-marker{display:none}
.lng summary::after{content:"";border:4px solid transparent;
  border-block-start-color:currentColor;margin-block-start:4px}
.lng summary:hover,.lng[open] summary{color:var(--fg);border-color:var(--gold)}
.flag{inline-size:22px;block-size:15px;flex:0 0 auto;border-radius:2px;
  box-shadow:0 0 0 1px rgba(255,255,255,.18)}
.lng__menu{position:absolute;inset-block-start:calc(100% + 8px);inset-inline-end:0;
  z-index:45;list-style:none;display:grid;gap:2px;
  grid-template-columns:repeat(2,minmax(0,1fr));
  inline-size:min(340px,calc(100vw - 2 * var(--gutter)));
  max-block-size:calc(100svh - var(--head) - 16px);overflow-y:auto;padding:8px;
  background:var(--bar);border:1px solid var(--edge-in);border-radius:var(--r-s);
  box-shadow:0 12px 32px rgba(0,0,0,.55)}
.lng__menu a{display:flex;align-items:center;gap:10px;padding:8px 10px;
  border-radius:var(--r-s);color:var(--fg-mut);text-decoration:none;
  font-size:14px;white-space:nowrap}
.lng__menu a:hover{background:rgba(210,162,76,.12);color:var(--fg)}
.lng__menu a[aria-current]{color:var(--gold)}
@media (max-width:479px){.lng__code{display:none}.lng summary{padding:6px 7px}}
/* Handy (08.10.2026): Schriftzug + Anmelden/Registrieren passten nicht in
   eine Zeile. Die Knoepfe brachen in eine eigene Zeile um, das Menue rutschte
   unter die feste Kopfleiste (106px) und die Zierlinie lief durch die Schrift.
   Unter 600px bleibt nur das Symbol (der Link hat sein aria-label), die
   Knoepfe werden kleiner. Der Name steht ohnehin im Banner darunter. */
@media (max-width:599px){
  .hdr .brand span{display:none}
  .acct{gap:6px}
  .acct .btn{padding:5px 10px;font-size:12.5px;white-space:nowrap}
  .hero .cta{flex-direction:column;align-items:stretch}
}
/* Handy-Menue (08.10.2026): unter 1000px statt der zweiten Kopfzeile ein
   Menue-Knopf rechts, die Punkte klappen als Liste unter der Kopfleiste auf.
   Die Leiste .nav bleibt fuer breite Fenster. */
.navm{display:none}
@media (max-width:999px){
  :root{--head:64px}
  .hdr{flex-wrap:nowrap;align-content:center;padding-block-start:0}
  .nav{display:none}
  .navm{display:block;flex:0 0 auto}
  .navm summary{list-style:none;cursor:pointer;display:flex;align-items:center;justify-content:center;
    inline-size:40px;block-size:36px;border:1px solid var(--edge-in);border-radius:var(--r-s);
    color:var(--fg-mut);transition:color .2s var(--ease),border-color .2s var(--ease)}
  .navm summary::-webkit-details-marker{display:none}
  .navm summary:hover,.navm[open] summary{color:var(--fg);border-color:var(--gold)}
  .navm__ico{inline-size:22px;block-size:22px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round}
  .navm__menu{position:absolute;inset-block-start:calc(100% + 3px);inset-inline:0;z-index:45;
    max-block-size:calc(100svh - var(--head) - 3px);overflow-y:auto;
    background:var(--bar);border-block-end:1px solid var(--edge-in);box-shadow:0 14px 30px rgba(0,0,0,.5)}
  .navm__menu ul{list-style:none;margin:0;padding:4px 0}
  .navm__menu li+li a{border-block-start:1px solid var(--edge)}
  .navm__menu a{display:block;padding:13px var(--gutter);font:700 15px var(--d);letter-spacing:.04em;
    text-transform:uppercase;color:var(--fg-mut);text-decoration:none;border-inline-start:3px solid transparent}
  .navm__menu a:hover{color:var(--fg);background:rgba(210,162,76,.12)}
  .navm__menu a[aria-current]{color:var(--fg);border-inline-start-color:var(--gold)}
}
@media (max-width:599px){.hdr{gap:8px}}

/* ======================================================= Knoepfe ======= */
.btn{font-family:var(--d);font-weight:700;text-transform:uppercase;
  text-decoration:none;cursor:pointer;display:inline-flex;align-items:center;
  justify-content:center;gap:8px;border-radius:var(--r-s);
  transition:background .2s var(--ease),color .2s var(--ease),
             border-color .2s var(--ease),box-shadow .2s var(--ease)}
.btn-s{border:2px solid var(--gold);color:var(--gold);background:transparent;
  padding:5px 14px;font-size:14px}
.btn-s:hover{background:var(--gold);color:#000}
.btn-p{background:var(--gold);color:#000;border:2px solid var(--gold);
  padding:5px 14px;font-size:14px}
.btn-p:hover{background:var(--gold-hi);border-color:var(--gold-hi)}
.btn-hero{background:var(--gold);color:#000;border:1px solid var(--gold);
  padding:13px 34px;min-inline-size:190px;min-block-size:50px;font-size:18px;
  box-shadow:0 8px 24px -8px rgba(210,162,76,.5)}
.btn-hero:hover{background:var(--gold-hi);border-color:var(--gold-hi);
  box-shadow:0 10px 30px -8px rgba(240,214,166,.6)}
.btn-ghost{border:1px solid var(--edge-in);color:var(--fg);background:transparent;
  padding:13px 30px;min-block-size:50px;font-size:18px}
.btn-ghost:hover{background:var(--fg);color:#000;border-color:var(--fg)}
.btn:active{transform:translateY(1px)}
.btn[disabled],.btn[aria-disabled=true]{opacity:.45;pointer-events:none}

/* ======================================================= Buehne ========
   Parallaxe ohne JS. Die Sektion bekommt clip-path:inset(0), das Bild
   position:fixed. Das Bild steht dann still, waehrend die Sektion darueber
   scrollt — der Zuschnitt haelt es innerhalb der Sektion.
   Achtung: clip-path erzeugt KEINEN Containing Block fuer fixed. Der Effekt
   entsteht durch den Zuschnitt, nicht durch Positionsverankerung. Wer das
   zu "transform statt clip-path" korrigiert, macht es kaputt.
   ====================================================================== */
.stage{position:relative;overflow:hidden;clip-path:inset(0)}
.stage__art{position:fixed;inset-block-start:0;inset-inline-start:0;
  inline-size:100%;block-size:100%;z-index:0;pointer-events:none}
.stage__art img{position:absolute;inset:0;inline-size:100%;block-size:100%;
  object-fit:cover;object-position:68% 42%}
  /* Kein Drift mehr: das Artwork IST die Szene. Ein Bild, das sich
     dauernd verschiebt, ist ein Bildschirmschoner. */
.stage__scrim{position:absolute;inset:0;z-index:2;pointer-events:none;
  background:
   linear-gradient(180deg,rgba(11,10,8,.55) 0%,rgba(11,10,8,0) 52%,rgba(11,10,8,.97) 100%),
   linear-gradient(90deg,rgba(11,10,8,.92) 0%,rgba(11,10,8,.35) 55%,rgba(11,10,8,0) 100%)}
.stage__inner{position:relative;z-index:3;
  min-block-size:min(calc(100svh - var(--head)),720px);
  display:flex;align-items:center;padding-inline:var(--gutter)}

/* Der Buehnennebel liegt im Parallax-Block weiter unten. Hier bleibt
   nur der Rahmen: `.fog` traegt die Ebenen, hat selbst keine Hoehe und
   bildet den Stapelkontext zwischen Artwork und Scrim. */
.fog{position:sticky;inset-block-start:var(--head);block-size:0;z-index:1;
  pointer-events:none}

.hero{max-inline-size:580px}
.hero__emblem{inline-size:min(460px,84vw);block-size:auto;margin-block-end:20px}
.hero p{font-size:19px;line-height:1.5;color:#D6D0C3;max-inline-size:34rem;
  text-shadow:var(--shadow-sub)}
.cta{display:flex;gap:12px;margin-block-start:26px;flex-wrap:wrap}

/* Beta-Siegel ueber dem Emblem. Glut pulsiert, ein Lichtstreif zieht
   durch. Ohne Webfonts faellt --d auf die Serif zurueck, das Siegel
   bleibt lesbar. ?motion=off und reduced-motion halten beides an.
   Absolut ueber dem Hero, damit es dessen Hoehe nicht aendert: .hero
   wird senkrecht zentriert, im Fluss rutschte das Emblem ~28px tiefer.
   Bei sehr niedrigen Fenstern zurueck in den Fluss, sonst schneidet
   .stage (overflow:hidden) das Siegel oben ab. */
.hero{position:relative}
.hero .beta-seal{position:absolute;inset-block-end:100%;inset-inline-start:0}
.beta-seal{position:relative;display:flex;inline-size:fit-content;align-items:center;
  gap:12px;margin-block-end:18px;padding:9px 16px 9px 14px;overflow:hidden;
  border:1px solid rgba(210,162,76,.55);border-radius:3px;
  background:linear-gradient(180deg,rgba(22,19,15,.85),rgba(7,6,5,.85));
  box-shadow:0 0 0 1px rgba(0,0,0,.6),0 0 24px -6px rgba(210,162,76,.45),
    inset 0 1px 0 rgba(240,214,166,.12)}
.beta-seal__ember{inline-size:8px;block-size:8px;border-radius:50%;
  background:var(--gold-hi);box-shadow:0 0 6px 2px rgba(240,180,90,.9);
  animation:beta-ember 2.4s ease-in-out infinite}
.beta-seal__lbl{font:700 12px var(--d);letter-spacing:.24em;
  text-transform:uppercase;color:var(--fg-mut)}
.beta-seal__sep{inline-size:1px;block-size:16px;background:rgba(210,162,76,.45)}
.beta-seal__when{font:700 15px var(--d);letter-spacing:.14em;text-transform:uppercase;
  background:linear-gradient(90deg,var(--gold-dim),var(--gold-hi) 50%,var(--gold-dim));
  -webkit-background-clip:text;background-clip:text;color:transparent}
.beta-seal::after{content:"";position:absolute;inset:0;transform:translateX(-120%);
  background:linear-gradient(100deg,transparent 30%,rgba(240,214,166,.28) 50%,transparent 70%);
  animation:beta-sweep 4.5s var(--ease) infinite 1s}
@keyframes beta-ember{0%,100%{opacity:.55;transform:scale(.85)}
                      50%{opacity:1;transform:scale(1.15)}}
@keyframes beta-sweep{0%{transform:translateX(-120%)}45%,100%{transform:translateX(120%)}}
.motion-off .beta-seal__ember,.motion-off .beta-seal::after{animation:none}
@media (max-height:600px){.hero .beta-seal{position:relative;inset:auto}}
/* Registrierung bis zur Beta geschlossen (auth/register_closed.html). */
.reg-closed{display:grid;justify-items:center;gap:8px;text-align:center}
.reg-closed h1{margin-block:2px 0}
.reg-closed .cta{justify-content:center;margin-block-start:18px}

/* ======================================================= Sektionen ===== */
.sect{position:relative;z-index:4;background-color:var(--page);
  background-repeat:no-repeat;
  padding-block:76px;padding-inline:var(--gutter)}
.sect--bar{background-color:var(--bar)}
.sect--tight{padding-block:52px}
.col{max-inline-size:var(--col);margin-inline:auto;
  display:flex;flex-direction:column;gap:var(--gap)}
.col--wide{max-inline-size:var(--wide)}

h2{font-size:clamp(29px,4vw,42px);line-height:1.15;color:var(--fg);
  text-shadow:var(--shadow-head)}
h2.big{font-size:clamp(36px,5.5vw,58px)}
h2 em{font-style:normal;color:var(--gold)}   /* Akzent im Satz, nicht am Satz */
.sub{font-size:clamp(18px,2vw,22px);font-weight:400;color:var(--fg-body);
  text-shadow:var(--shadow-sub);margin-block-start:12px;max-inline-size:var(--measure)}
.body{font-size:15px;color:var(--fg-mut);max-inline-size:var(--measure)}
.eyebrow{font:700 12px var(--d);letter-spacing:.18em;text-transform:uppercase;
  color:var(--gold-deep);margin-block-end:10px}
/* Der Akzent sitzt am Anfang, nicht ueberall — jetzt als Pinselzug
   statt als Haarlinie.

   Das Asset dient als MASKE, nicht als Bild: die Farbe bleibt damit
   `--gold-deep` und folgt jedem spaeteren Themenwechsel. Ein Bild
   muesste man fuer jede Farbe neu schreiben. */
.eyebrow::before{content:"";display:inline-block;
  inline-size:34px;block-size:9px;vertical-align:.12em;
  margin-inline-end:10px;background:var(--gold-deep);
  -webkit-mask:url("../img/atmo/stroke-dash.webp") no-repeat left center/contain;
  mask:url("../img/atmo/stroke-dash.webp") no-repeat left center/contain}
/* Bei RTL laeuft der Zug in die andere Richtung — sonst zeigt seine
   Spitze vom Text weg. */
:dir(rtl) .eyebrow::before{transform:scaleX(-1)}


/* ======================================================= Atmosphaere == */
/* Licht kommt aus dem RAUM, nicht aus den Objekten. Karten, Zeilen und
   Baender bleiben flach — eine Lichtkante auf jeder Flaeche waere Bevel.

   Alles hier liegt ZWEIMAL: zuerst der CSS-Verlauf, dann das Bild
   darueber. Faellt ein Bild aus, bleibt der Verlauf stehen und nichts
   bricht — das ist Bedingung aus 00_DESIGN_SPEC (nur das Hero-Artwork
   ist Pflichtbild).

   Warum ueberhaupt Bilder: ein radial-gradient ist eine glatte Blase.
   Gemalter Nebel hat Struktur, Richtung und Korn. Das ist der ganze
   Unterschied zwischen "wirkt billig" und "wirkt gemalt".

   Alle Assets sind auf Schwarz gemalt und tragen ihre Form im
   ALPHAKANAL (ChatGPT liefert kein Alpha). Zusammen 89 KB. */

:root{
  --atmo:url("../img/atmo/");
  /* Native Kachelbreiten. Teilerfremd gewaehlt: zwei uebereinander
     liegende Ebenen wiederholen sich erst nach ihrem kgV, also nie. */
  --fog-1:1720px;
  --fog-2:2080px;
  --fog-3:1460px;
  --fog-w:1720px;            /* Schleifenweg der Hero-Ebene 1 */
}

/* --- Grundkorn ueber allem ------------------------------------------
   Der groesste Effekt pro Byte: 14 KB, und jede Flaeche der Seite hoert
   auf, wie ein Formular auszusehen. Die Kachel ist gespiegelt gebaut,
   dadurch ist die Naht eine Spiegelachse und kann nicht springen
   (gemessen: Sprung 0.0 an allen vier Kanten). */
body::before{content:"";position:fixed;inset:0;z-index:0;
  pointer-events:none;opacity:.42;
  background:url("../img/atmo/tex-grain.webp") repeat;
  background-size:256px 256px}

/* --- Saum an den Sektionsgrenzen ------------------------------------ */
.sect--bar + .sect::before,
.sect + .sect--bar::before,
.status + .sect::before,
main.sect::before{
  content:"";position:absolute;inset-inline:0;inset-block-start:0;
  z-index:-1;pointer-events:none}
.sect--bar + .sect::before{block-size:120px;
  background:linear-gradient(to bottom,#16130F,rgba(22,19,15,0))}
.sect + .sect--bar::before{block-size:120px;
  background:linear-gradient(to bottom,#0B0A08,rgba(11,10,8,0))}
.status + .sect::before{block-size:120px;
  background:linear-gradient(to bottom,#070605,rgba(7,6,5,0))}

/* --- Kopfband der Unterseiten ---------------------------------------
   Der groesste Hebel fuer die zehn Unterseiten: sie haben kein
   Hero-Artwork und begannen mit einer nackten Flaeche. Das Band ist
   dasselbe Motiv wie das Hero, nur schmal — Bergruecken im Nebel, rechts
   eine Pagode. Es laeuft nach unten in den Seitengrund aus. */
main.sect::before{block-size:280px;
  background:
    linear-gradient(to bottom,#16130F,rgba(22,19,15,0)),
    url("../img/atmo/band-head.webp") no-repeat center top;
  background-size:auto,cover;
  /* Auslauf nach unten: ohne Maske endete das Bild mit harter Kante (Benni 29.09.) */
  -webkit-mask-image:linear-gradient(to bottom,#000 45%,transparent);
  mask-image:linear-gradient(to bottom,#000 45%,transparent)}

/* --- Abschnittsgrenze: ein gezogener Strich -------------------------
   Vorher stand hier an jeder Grenze dasselbe Wolkenband. Dreimal
   dasselbe Bild liest als Tapete, nicht als Gestaltung — und ein Nebel
   an einer Abschnittskante hat ohnehin keinen Grund, er trennt nur.

   Der Strich wird beim Scrollen GEMALT: die Maske zieht von links nach
   rechts auf, und weil ihre Kante weich ist, hat der Zug eine
   Pinselspitze. Ohne Scroll-Timeline steht er einfach da. */
.sect--bar + .sect::after,
.sect + .sect--bar::after,
.status + .sect::after{
  content:"";position:absolute;inset-inline:0;inset-block-start:-16px;
  block-size:34px;z-index:-1;pointer-events:none;opacity:.5;
  background:url("../img/atmo/sweep.webp") no-repeat
             center top/min(1180px,88%) 34px}

/* --- Kopf der Unterseiten: Nebel, der zieht ------------------------
   Das Kopfband ist ein Standbild. Darueber liegt eine eigene, bewegte
   Ebene — sonst ist der Kopf jeder Unterseite tot, waehrend die
   Startseite lebt. main.sect::after ist hier frei: der Grenznebel
   greift nicht, weil eine Unterseite kein Geschwister-.sect vor sich
   hat. */
main.sect::after{content:"";position:absolute;
  inset-inline:0;inset-block-start:0;block-size:280px;
  z-index:-1;pointer-events:none;opacity:.30;
  -webkit-mask-image:linear-gradient(to bottom,
    rgba(0,0,0,1) 40%,rgba(0,0,0,0) 100%);
  mask-image:linear-gradient(to bottom,
    rgba(0,0,0,1) 40%,rgba(0,0,0,0) 100%);
  background-image:url("../img/atmo/fog-2.webp");
  background-repeat:repeat-x;background-size:2080px 100%}

/* --- Laternenschein --------------------------------------------------
   Das Hero-Artwork hat EINE haengende Laterne. Das hier ist dieselbe,
   weiter unten. Bild und Verlauf liegen als LAYER im selben background:
   laedt das Bild nicht, bleibt der Verlauf stehen. Deshalb kein
   @supports-Test — der waere ohnehin immer wahr.

   Die rechte Seite braucht ein eigenes, gespiegeltes Asset: CSS kann ein
   background-image nicht spiegeln, und die Pseudoelemente sind belegt. */
.sect:nth-of-type(odd){background-image:
  radial-gradient(62% 72% at 0% 38%,
    rgba(138,106,50,var(--atmo-lamp)),rgba(138,106,50,0) 70%)}
.sect:nth-of-type(even){background-image:
  radial-gradient(62% 72% at 100% 38%,
    rgba(138,106,50,var(--atmo-lamp)),rgba(138,106,50,0) 70%)}

@media (min-width:1000px){
  .sect:nth-of-type(odd){
    background-image:
      url("../img/atmo/light-lantern.webp"),
      radial-gradient(62% 72% at 0% 38%,
        rgba(138,106,50,calc(var(--atmo-lamp) * .45)),rgba(138,106,50,0) 70%);
    background-repeat:no-repeat,no-repeat;
    background-position:left center,left center;
    background-size:auto 74%,auto}
  .sect:nth-of-type(even){
    background-image:
      url("../img/atmo/light-lantern-r.webp"),
      radial-gradient(62% 72% at 100% 38%,
        rgba(138,106,50,calc(var(--atmo-lamp) * .45)),rgba(138,106,50,0) 70%);
    background-repeat:no-repeat,no-repeat;
    background-position:right center,right center;
    background-size:auto 74%,auto}
  /* Bei RTL tauschen die Seiten — dann muss auch die Kachel tauschen,
     sonst faellt das Licht aus der Wand heraus statt herein. */
  :dir(rtl) .sect:nth-of-type(odd){
    background-image:url("../img/atmo/light-lantern-r.webp"),
      radial-gradient(62% 72% at 100% 38%,
        rgba(138,106,50,calc(var(--atmo-lamp) * .45)),rgba(138,106,50,0) 70%);
    background-position:right center,right center}
  :dir(rtl) .sect:nth-of-type(even){
    background-image:url("../img/atmo/light-lantern.webp"),
      radial-gradient(62% 72% at 0% 38%,
        rgba(138,106,50,calc(var(--atmo-lamp) * .45)),rgba(138,106,50,0) 70%);
    background-position:left center,left center}
}



/* --- PARALLAXEBENEN UEBER DEM HERO ---------------------------------
   Acht Schichten, jede mit eigenem Tempo. Je naeher am Betrachter,
   desto schneller — das ist die ganze Parallaxe.

   Ohne Markup-Aenderung: das HTML hat nur drei Kinder in der Buehne
   (.f1 .f2 .glow), der Rest haengt an deren Pseudoelementen und an
   denen von .fog und .stage__inner.

   Tiefenordnung:
     z 0  .stage__art     Hero-Artwork, driftet 90 s (Bestand)
     z 1  .fog            f1/f2/glow + ::before
     z 2  .stage__scrim   Abdunklung (Bestand)
     z 3  .stage__inner   ::before/::after mit z-index -1, dann Text

   Ast und Felskante haengen bewusst an .stage__inner: sie sind
   Vordergrund und duerfen nicht unter dem Dunstschleier liegen.
   Innerhalb von .stage__inner stehen sie auf z-index -1, also hinter
   dem Hero-Text — aber als Gruppe ueber dem Scrim. */

.fog i{position:absolute;display:block;inset-inline-start:0;
  background-repeat:repeat-x}

/* Die dritte Nebeltiefe ist entfallen — zwei reichen, und die dritte
   kostete 34 % Flaeche fuer einen Unterschied, den niemand benennen
   kann. Das Element bleibt als Traeger der Mondstrahlen. */
.fog .f1{inset-block-start:22vh;block-size:34vh;
  inline-size:100%}

/* Ebene 2 — Mondstrahlen. Bewegen sich NICHT seitlich, sie atmen nur:
   ein wandernder Lichtschacht wuerde sofort als Schleife auffallen. */
.fog .f1::after{content:"";position:absolute;inset:0;
  inset-block-start:-14vh;block-size:52vh;pointer-events:none;
  background:url("../img/atmo/rays.webp") no-repeat right top/auto 100%;
  opacity:.42}
  /* Statisch. Licht, das dauernd pulst, liest als Effekt; Licht, das
     einfach da ist, liest als Mondlicht. */

/* Ebene 3 — Talnebel, die tragende Schicht. */
.fog .f2{inset-block-start:38vh;block-size:26vh;opacity:.40;
  inline-size:calc(100% + 1840px);
  background-image:url("../img/atmo/veil-mid.webp");
  background-size:1840px 100%;
  animation:par-r 61s linear infinite}

/* Ebene 4 — Fetzen, nah. Schnellste Nebelebene, grosse Formen, viel
   Schwarz dazwischen. Sie macht den Tiefeneindruck. */
.fog .f2::after{content:"";position:absolute;
  inset-inline-start:0;inset-block-start:6vh;
  inline-size:100%;block-size:30vh;pointer-events:none;opacity:.52;
  background:url("../img/atmo/veil-near.webp") repeat-x 0 50%/2120px 100%;
  animation:drift-near 23s linear infinite,
            reissen 37s ease-in-out 1.4s infinite}

/* Ebene 5 — Halo der Laterne. Sitzt ueber der Laterne im Artwork. */
/* Der Halo ist auf die Laterne im Artwork ZENTRIERT, nicht neben sie
   gesetzt: hellster warmer Punkt des gerenderten Bildes bei 72,4 % /
   39,2 %, davon die halbe Halogroesse abgezogen. Vorher lag der Schein
   60 px links und 98 px unter seiner Quelle — das liest das Auge nicht
   als Licht, sondern als Fleck. */
.fog .glow{inset-block-start:6.1vh;inset-inline-start:60.2%;inset-inline-end:auto;
  inline-size:min(340px,44vw);block-size:min(340px,44vw);opacity:.52;
  background:url("../img/atmo/lantern-halo.webp") no-repeat center/contain;
  animation:halo 1.3s ease-in-out infinite}
/* Der Halo hat vorher eigenstaendig gepulst (4,7 s) und mit der Flamme
   um Aufmerksamkeit konkurriert. Jetzt laeuft er auf DERSELBEN Dauer
   wie sie: 1,3 s. Damit sind es nicht mehr zwei Animationen an einem
   Ort, sondern eine Ursache und ihre Wirkung — der Schein schwankt,
   weil die Flamme schwankt. Die Ausschlaege sind klein, aber sie sitzen
   auf grosser Flaeche und machen deshalb den Unterschied zwischen
   "brennt" und "Bild einer Laterne". */
@keyframes halo{
    0%{opacity:.38}
   23%{opacity:.62}
   41%{opacity:.44}
   58%{opacity:.68}
   76%{opacity:.46}
  100%{opacity:.38}}

/* Die Staubpartikel sind entfallen. 60 % der Buehnenflaeche in
   Bewegung fuer einen Effekt, den man weder benennen noch vermissen
   kann — das ist der teuerste Posten im Bewegungsbudget gewesen. */


/* Ebene 7 und 8 — Vordergrund. Ueber dem Scrim, unter dem Text. */
.stage__inner{position:relative}
.stage__inner::before,.stage__inner::after{
  content:"";position:absolute;z-index:-1;pointer-events:none}
.stage__inner::before{
  inset-block-start:26vh;inset-inline-start:-6%;
  inline-size:min(680px,56vw);block-size:min(623px,51vw);
  background:url("../img/atmo/branch-left.webp") no-repeat left top/contain;
  animation:schweben 37s ease-in-out infinite}
.stage__inner::after{
  inset-inline:0;inset-block-end:0;block-size:120px;
  background:url("../img/atmo/ridge-front.webp") repeat-x 0 bottom/1720px 100%}
  /* Keine Drift: Fels bewegt sich nicht. Das war der Fehler, der am
     Bild sofort auffiel — ein wandernder Boden hat keine Ursache. */

@keyframes par-r{
    0%{transform:translate3d(-1840px,0,0)}
   22%{transform:translate3d(-1288px,0,0)}
   38%{transform:translate3d(-1215px,0,0)}
   70%{transform:translate3d(-405px,0,0)}
   84%{transform:translate3d(-332px,0,0)}
  100%{transform:translate3d(0px,0,0)}}
@keyframes drift-near{
    0%{background-position:0px 50%}
   22%{background-position:636px 50%}
   38%{background-position:720px 50%}
   70%{background-position:1653px 50%}
   84%{background-position:1738px 50%}
  100%{background-position:2120px 50%}}
/* Der Ast schwebt nicht gleichmaessig — er steht still, bis eine Boe
   kommt. 88 Prozent des Zyklus passiert nichts. */
@keyframes schweben{
    0%{transform:translate3d(0,0,0) rotate(0deg)}
   62%{transform:translate3d(0,0,0) rotate(0deg)}
   68%{transform:translate3d(-9px,3px,0) rotate(-.7deg)}
   74%{transform:translate3d(6px,-4px,0) rotate(.5deg)}
   80%{transform:translate3d(-3px,1px,0) rotate(-.2deg)}
   88%{transform:translate3d(0,0,0) rotate(0deg)}
  100%{transform:translate3d(0,0,0) rotate(0deg)}}
/* Dieselbe Boe, die den Ast bewegt, reisst hier den Nebelfaden
   auseinander — 1,4 s spaeter, weil der Wind Zeit braucht. Das ist der
   Unterschied zwischen drei Animationen nebeneinander und einer
   Ursache mit Folge. */
@keyframes reissen{
    0%{opacity:.52}
   62%{opacity:.52}
   70%{opacity:.18}
   78%{opacity:.70}
   88%{opacity:.52}
  100%{opacity:.52}}


/* Nebelbank an der Buehnenunterkante — bleibt, aber mit dem neuen
   tiefen Band statt des alten. */
.stage::after{content:"";position:absolute;inset-inline:0;inset-block-end:0;
  block-size:30%;z-index:2;pointer-events:none;opacity:.30;
  background:url("../img/atmo/fog-4.webp") repeat-x center bottom/1660px 100%}


/* --- SPRITE-ANIMATIONEN ---------------------------------------------
   Bis hierher verschiebt sich alles nur. Diese fünf veraendern sich:
   `steps(n)` springt hart von Frame zu Frame, wie ein Daumenkino. Der
   Weg ist jeweils die volle Streifenbreite, dadurch landet der letzte
   Frame exakt auf dem ersten.

   Alle fuenf zusammen wiegen 55 KB. Sprites lohnen sich nur fuer
   kleine, dichte Bewegung — ein Sheet fuer eine grosse Flaeche waere
   unbezahlbar (8 Frames eines 1400-px-Nebels = 11.200 px breit). */

/* Flamme in der Laterne. 16 Frames, kleinste Flaeche der Seite, und
   das Erste, was einem Auge auffaellt, das Ruhe gewohnt ist. */
.fog .glow::before{content:"";position:absolute;
  inset-inline-start:50%;inset-block-start:50%;
  inline-size:26px;block-size:35px;
  margin-inline-start:-13px;margin-block-start:-18px;
  pointer-events:none;
  /* Das Sheet ist nativ 1536x128 — 96 px je Frame. Auf 17 px
     heruntergerechnet blieben davon 26 sichtbare Pixel uebrig, also
     nichts. 26 px Breite ist immer noch klein, entspricht aber der
     Laterne im Artwork und ist das Zehnfache an Substanz. */
  background:url("../img/atmo/flame.webp") 0 0/416px 35px;
  animation:flame 1.3s steps(16) infinite}
@keyframes flame{to{background-position:-416px 0}}

/* Die Glut ist entfallen: sie sass am selben Ort wie die Flamme und
   hat um dieselbe Aufmerksamkeit konkurriert. Zwei Bewegungen an einem
   Punkt sind eine zu viel. */


/* Wehendes Gras auf der Felskante. Liegt ueber dem Scrim, unter dem
   Text — deshalb z-index 3 und nicht 2. */
/* Das Gras ist entfallen. Es lag an der Buehnenunterkante, und dort
   deckt der Scrim zu 97 % ab — gemessen null sichtbare Pixel bei 19,5
   KB Dateigroesse. Ein Element, das im fertigen Bild nicht vorkommt,
   ist kein Element. */

/* Der Nebelknoten ist raus. 9 Frames auf 7,3 s sind 0,81 s je Bild —
   das sieht man einzeln springen. Fluessig braeuchte es rund 12 Bilder
   je Sekunde, dann waere der Zyklus 0,75 s lang und ein Nebelwirbel
   haette die Hektik eines Ventilators. Mit neun Frames ist beides nicht
   zu haben; das Sprite bleibt liegen, bis das Konzept dafuer steht. */



/* DAS SELTENE EREIGNIS. Zwei Animationen: die Fluegel schlagen alle
   0,7 s, der Flugweg dauert 53 s — sichtbar ist sie davon 8. Die
   uebrigen 45 Sekunden passiert hier nichts, und genau deshalb faellt
   der Moment auf, in dem sie kommt. */
/* Die Fledermaus ist entfallen. Sie flog durch den schwarzen oberen
   Bildrand und war auch dann nicht zu sehen, wenn sie gerade da war.
   Ihre Rolle — das seltene Ereignis — hat der Vogel uebernommen, der
   im helleren Bildteil quert. */


/* --- DAS GEMALTE EREIGNIS -------------------------------------------
   Drei fallende Blaetter und ein Vogel. Zusammen 1,5 KB.

   Ein Blatt taumelt, weil es sich um die LAENGSACHSE dreht — mal zeigt
   es die Flaeche, mal die Kante. Das sind die acht Frames im Sheet. Die
   Bahn nach unten, das seitliche Pendeln und die Neigung macht CSS.
   Deshalb reichen acht Frames: von Bild zu Bild aendert sich wenig.
   (Der Nebelwirbel, der hier frueher ruckelte, drehte ueber neun Bilder
   volle 360 Grad — 40 Grad je Sprung, und die sieht das Auge einzeln.)

   Jedes Blatt ist nur rund ein Drittel seines Takts im Bild. Die Takte
   sind teilerfremd (23/31/41 s), dadurch faellt kein Muster auf und
   selten sind zwei gleichzeitig zu sehen. Ein Blattregen waere genau
   der Bildschirmschoner, der gerade abgebaut wurde.

   Traeger ohne Markup-Aenderung:
     .stage__scrim::before   Blatt nah    ueber dem Nebel (z 2)
     .stage__scrim::after    Blatt mittig
     .fog::before            Blatt fern   unter dem Scrim, gedaempft
     .fog .f1::before        Vogel        .f1 steht still, taugt als Traeger

   Nicht .fog .f2::*: diese Ebene wird selbst verschoben, ein Kind wuerde
   mitwandern. */

.stage__scrim::before,.stage__scrim::after,.fog::before{
  content:"";position:absolute;pointer-events:none;opacity:0;
  inline-size:34px;block-size:39px;
  background:url("../img/atmo/leaf.webp") 0 0/272px 39px;
  will-change:transform}

/* Die drei Startpunkte liegen ALLE im hellen Nebelband. Ein Blatt, das
   im schwarzen Himmel startet, ist die ersten Sekunden schlicht nicht
   vorhanden — gemessen und bestaetigt. */
.stage__scrim::before{
  inset-block-start:41vh;inset-inline-start:52%;
  animation:leaf-turn 1.05s steps(8) infinite,
            leaf-a 19s linear infinite}
.stage__scrim::after{
  inset-block-start:45vh;inset-inline-start:76%;transform-origin:50% 0;
  animation:leaf-turn 1.31s steps(8) infinite,
            leaf-b 23s linear infinite}
/* Das ferne Blatt ist kleiner und blasser — Tiefe entsteht aus Groesse
   und Kontrast, nicht aus Geschwindigkeit allein. */
.fog::before{
  inset-block-start:47vh;inset-inline-start:33%;
  inline-size:22px;block-size:25px;background-size:176px 25px;
  animation:leaf-turn 1.67s steps(8) infinite,
            leaf-c 29s linear infinite}

@keyframes leaf-turn{to{background-position:-272px 0}}

/* Die Bahn ist kein Sturz, sondern ein Pendeln: ein Blatt gleitet zur
   Seite, kippt, faellt durch, gleitet zurueck. Deshalb wechselt die
   waagerechte Richtung mehrfach, und die Neigung folgt ihr.

   Sichtbar ist jedes Blatt rund ein Drittel seines Takts. Bei
   teilerfremden Dauern (23/31/41 s) faellt kein Muster auf, und selten
   sind zwei gleichzeitig unterwegs. Ein Blattregen waere genau der
   Bildschirmschoner, der gerade abgebaut wurde. */
@keyframes leaf-a{
    0%{transform:translate3d(0,0,0) rotate(-6deg);opacity:0}
    3%{opacity:.60}
    8%{transform:translate3d(34px,7vh,0) rotate(28deg)}
   14%{transform:translate3d(2px,15vh,0) rotate(-19deg)}
   20%{transform:translate3d(46px,23vh,0) rotate(33deg)}
   26%{transform:translate3d(10px,31vh,0) rotate(-13deg)}
   31%{transform:translate3d(40px,38vh,0) rotate(25deg);opacity:.44}
   35%{transform:translate3d(24px,44vh,0) rotate(9deg);opacity:0}
  100%{transform:translate3d(24px,44vh,0) rotate(9deg);opacity:0}}

@keyframes leaf-b{
    0%{transform:translate3d(0,0,0) scale(.84) rotate(9deg);opacity:0}
    3%{opacity:.52}
    8%{transform:translate3d(-31px,7vh,0) scale(.84) rotate(-23deg)}
   14%{transform:translate3d(-3px,14vh,0) scale(.84) rotate(18deg)}
   20%{transform:translate3d(-38px,22vh,0) scale(.84) rotate(-30deg)}
   26%{transform:translate3d(-9px,30vh,0) scale(.84) rotate(15deg)}
   30%{transform:translate3d(-27px,36vh,0) scale(.84) rotate(-9deg);opacity:.36}
   34%{transform:translate3d(-19px,41vh,0) scale(.84) rotate(3deg);opacity:0}
  100%{transform:translate3d(-19px,41vh,0) scale(.84) rotate(3deg);opacity:0}}

@keyframes leaf-c{
    0%{transform:translate3d(0,0,0) rotate(3deg);opacity:0}
    3%{opacity:.38}
    9%{transform:translate3d(24px,6vh,0) rotate(-17deg)}
   16%{transform:translate3d(-2px,13vh,0) rotate(14deg)}
   23%{transform:translate3d(28px,20vh,0) rotate(-22deg)}
   28%{transform:translate3d(9px,26vh,0) rotate(7deg);opacity:.24}
   32%{transform:translate3d(18px,31vh,0) rotate(-4deg);opacity:0}
  100%{transform:translate3d(18px,31vh,0) rotate(-4deg);opacity:0}}

/* Der Vogel. 71 s Takt, davon ist er 8 s zu sehen — die uebrigen 63
   passiert an dieser Stelle nichts, und genau deshalb faellt der Moment
   auf, in dem er kommt. Vier Frames sind hier kein Notbehelf: der
   sichtbare Sprung IST das Stilmittel. */
.fog .f1::before{content:"";position:absolute;
  inset-block-start:2vh;inset-inline-start:0;
  inline-size:34px;block-size:34px;pointer-events:none;opacity:0;
  /* Gemalter Kranich, 6 Frames a 72 px. Die sechs Voegel standen im
     gelieferten Blatt an verschiedenen Stellen und in verschiedenen
     Groessen — so abgespielt waere er durchs Bild gezappelt statt mit
     den Fluegeln zu schlagen. Sie sind auf eine gemeinsame Mitte
     gesetzt, bezogen auf den liegenden Koerper, nicht auf den
     Schwerpunkt: der wandert mit der Fluegelstellung nach oben. */
  background:url("../img/atmo/crane.webp") 0 0/204px 34px;
  animation:bird-wing .52s steps(6) infinite,
            bird-path 71s linear infinite}
@keyframes bird-wing{to{background-position:-204px 0}}
@keyframes bird-path{
    0%{transform:translate3d(-8vw,0,0) scale(1);opacity:0}
    2%{opacity:.52}
    5%{transform:translate3d(26vw,-2vh,0) scale(.92);opacity:.52}
    8%{transform:translate3d(58vw,1vh,0) scale(.82);opacity:.44}
   11%{transform:translate3d(104vw,-3vh,0) scale(.72);opacity:0}
  100%{transform:translate3d(104vw,-3vh,0) scale(.72);opacity:0}}


/* --- GEMALTE EBENEN IN DEN ABSCHNITTEN -------------------------------
   Drei Tuschmalereien, je ein Abschnitt, alle statisch. Sie haengen an
   `.col` statt an `.sect`, weil fuer `.sect::before` in Verbindung mit
   Geschwisterselektoren bereits Regeln bestehen und sich zwei
   Deklarationen sonst ueber die Spezifitaet streiten.

   z-index -1 und nicht 0: mit 0 wuerden sie NACH dem Textinhalt gemalt
   und lagen ueber der Schrift. */
/* Der Drache setzt bei translate3d(26vw) an und der Zweig bei 7 % —
   im Startbild ihrer Animation ragen beide ueber den rechten Rand. Ohne
   Klippen erzeugt das eine waagerechte Bildlaufleiste, und zwar auf der
   GANZEN Seite.

   `overflow-x:clip` statt `hidden`: hidden macht den Abschnitt zum
   Scrollcontainer und bricht damit `position:sticky` bei Kindern, clip
   schneidet nur ab. Firefox kann es seit 111, der Tor Browser ist 140. */
.sect{overflow-x:clip}
.sect .col{position:relative}

/* ZWEI DARSTELLUNGEN DESSELBEN MOTIVS. Im Grundzustand traegt das
   Pseudoelement ein Hintergrundbild. Laeuft `js/zeichnen.js`, haengt es
   eine Leinwand in denselben Kasten, auf der sich das Motiv zeichnet —
   und setzt `zeichnet` auf die Spalte, woraufhin das Bild weicht.

   Position und Groesse stehen deshalb EINMAL und gelten fuer beide.
   Zwei getrennte Angaben wuerden auseinanderlaufen, und das Motiv
   spraenge genau in dem Augenblick, in dem die Leinwand uebernimmt. */
#chronik .col::after,#konto .col::before{
  content:"";background-repeat:no-repeat}
#chronik .col::after,#chronik .col>.motiv,
#konto .col::before,#konto .col>.motiv{
  position:absolute;z-index:-1;pointer-events:none}
/* Die Leinwand haelt das Motiv in Originalgroesse; `object-fit` passt
   es in den Kasten wie `background-size:contain` das Bild. */
#chronik .col>.motiv,#konto .col>.motiv{object-fit:contain}
/* Faellt das Skript aus oder fehlt ein Bild, wird `zeichnet` nie
   gesetzt und das Hintergrundbild bleibt stehen. */
#chronik .col.zeichnet::after,#konto .col.zeichnet::before{display:none}

/* Die ferne Bergkette ist entfallen. Sie stand als breites Band
   hinter den Klassenkarten und war genau das, was hier zu viel war:
   Flaeche ohne Aussage. */


/* Der Drache liegt hinter der Chronik, rechts, und ist nur angedeutet.
   Bei dieser Deckkraft ist er kein Bild, sondern ein Hauch — mehr
   vertraegt eine Spalte mit Nachrichten nicht. */
#chronik .col::after,#chronik .col>.motiv{
  inset-inline-end:-6vw;inset-block-start:-40px;
  inline-size:min(660px,54vw);block-size:min(384px,32vw);
  opacity:.20}
#chronik .col::after{
  background-image:url("../img/atmo/dragon.webp");
  background-size:contain;background-position:right top}
#chronik .col>.motiv{object-position:right top}

/* Kiefernzweig, gespiegelt in die RECHTE obere Ecke. Gemalt ist er
   von links oben hereinwachsend — dort liegt aber die Textspalte, und
   die Nadeln legten sich ueber die Ueberschrift. Rechts ist der
   Abschnitt frei. `scaleX(-1)` spiegelt das Bild, denn ein Zweig hat
   keine Leserichtung.

   Bei RTL steht der Text rechts, also wandert der Zweig nach links und
   die Spiegelung entfaellt. */
#konto .col::before,#konto .col>.motiv{
  inset-inline-end:-4vw;inset-inline-start:auto;inset-block-start:-56px;
  inline-size:min(520px,40vw);block-size:min(386px,30vw);
  transform:scaleX(-1);opacity:.30}
#konto .col::before{
  background-image:url("../img/atmo/pine-corner.webp");
  background-size:contain;background-position:left top}
#konto .col>.motiv{object-position:left top}
/* Die Spiegelung gilt fuer beide — ein Zweig, der auf der Leinwand
   anders herum laege als im Bild, waere der sichtbarste Fehler. */
:dir(rtl) #konto .col::before,:dir(rtl) #konto .col>.motiv{
  inset-inline-end:auto;inset-inline-start:-4vw;transform:none}

/* Unter 1000 px tragen die Abschnitte den Text, nicht das Bild: dort
   ueberlagern sich Motiv und Schrift zu sehr. */
@media (max-width:999px){
  #chronik .col::after,#konto .col::before,
  #chronik .col>.motiv,#konto .col>.motiv{display:none}
}

/* --- Ornament statt Rille -------------------------------------------
   Fragment 1 der Gestaltungsvorgabe: eine Trennung ist nie eine
   1px-Linie, sondern eine zweizeilige Rille. Beide liegen als Layer
   uebereinander — faellt das Ornament aus, bleibt die Rille. */
.col h2::after{content:"";display:block;
  block-size:25px;inline-size:360px;max-inline-size:100%;
  margin-block:14px 2px;
  background:
    url("../img/atmo/ink-rule.webp") no-repeat left center,
    linear-gradient(to bottom,
      var(--engrave-dark) 0 1px,var(--engrave-light) 1px 2px,
      rgba(0,0,0,0) 2px) no-repeat left top;
  background-size:contain,88px 2px}
:dir(rtl) .col h2::after{
  background-position:right center,right top}

/* Die Messingecken sind entfallen. Sie waren plastisch-dreidimensional
   gemalt, waehrend alles andere flaechig und pinselhaft ist — genau der
   Stilbruch, den eine einheitliche Bildsprache nicht vertraegt. */


/* --- Der Fuss laeuft aus -------------------------------------------- */
.foot::after{content:"";position:absolute;inset:0;
  z-index:-1;pointer-events:none;
  background:linear-gradient(to bottom,rgba(4,4,3,0) 40%,rgba(4,4,3,.85))}

/* --- Schmale Schirme -------------------------------------------------
   Unter 600px zaehlt jedes Byte doppelt (Mobilfunk ueber Tor) und der
   Platz fehlt ohnehin: Kopfband niedriger, Laterne aus, Ecken aus. */
@media (max-width:599px){
  main.sect::before{block-size:170px}
  body::before{opacity:.35}
  /* Unter 600px zaehlt jedes Byte doppelt (Mobilfunk ueber Tor) und
     jede Compositing-Ebene auch. Es bleiben: EIN Nebelschleier, das
     Laternenhalo mit der Flamme und EIN fallendes Blatt. Der Vogel und
     die beiden anderen Blaetter fallen weg — auf 380 px Breite waere
     das Gedraenge, was auf 1400 px Rhythmus ist. */
  .fog .f1::after,.fog .f2,.fog::before,  .fog .f1::before,.stage__scrim::after,
  .stage__inner::before,.stage__inner::after{display:none}
  .fog .f1{opacity:.26}
}
@media (max-width:999px) and (min-width:600px){
  /* Mittlere Schirme: Partikel und Ast raus, Nebel bleibt. */
  .fog::before,.stage__inner::before{display:none}
}

/* ======================================================= Statusfries === */
.status{background:var(--card);border-block:1px solid var(--edge);
  padding-block:13px;padding-inline:var(--gutter);position:relative;z-index:4}
.status ul{max-inline-size:var(--wide);margin-inline:auto;list-style:none;
  display:flex;flex-wrap:wrap;gap:10px 40px;align-items:baseline}
.status li{display:flex;align-items:baseline;gap:8px;font-size:14px}
.status .k{color:var(--fg-faint);text-transform:uppercase;letter-spacing:.1em;
  font-size:11px}
.status .v{color:var(--fg);font-weight:700;font-variant-numeric:tabular-nums}
.status .on{color:var(--ok)}
.status .dot{inline-size:7px;block-size:7px;border-radius:50%;background:var(--ok);
  display:inline-block;margin-inline-end:3px;
  box-shadow:0 0 0 0 rgba(111,165,92,.55);animation:pulse 2.8s ease-out infinite}

/* ======================================================= Karten ======== */
.cards{display:grid;gap:20px;grid-template-columns:1fr}
@media (min-width:600px){.cards{grid-template-columns:repeat(2,1fr)}}
@media (min-width:1000px){.cards{grid-template-columns:repeat(3,1fr)}}
.card{background:var(--card);border:1px solid var(--edge);border-radius:var(--r);
  padding:24px;transition:background .25s var(--ease),border-color .25s var(--ease),
  transform .25s var(--ease)}
.card:hover{background:var(--card-act);border-color:var(--edge-lit);
  transform:translateY(-2px)}
.card h3{font-size:20px;line-height:1.3;color:var(--fg);margin-block-end:10px}
.card p{font-size:14px;color:var(--fg-mut)}

/* ======================================================= Bildkarten ==== */
.tiles{display:grid;gap:14px;grid-template-columns:repeat(2,1fr)}
@media (min-width:1000px){.tiles{grid-template-columns:repeat(4,1fr)}}
.tile{position:relative;display:block;text-decoration:none;
  border-radius:var(--r);overflow:hidden;border:1px solid var(--edge);
  background:var(--card);aspect-ratio:3/4;
  transition:border-color .25s var(--ease)}
.tile:hover{border-color:var(--edge-lit)}
.tile img{position:absolute;inset:0;inline-size:100%;block-size:100%;
  object-fit:cover;transition:transform .6s var(--ease)}
.tile:hover img{transform:scale(1.035)}
.tile .veil{position:absolute;inset:0;
  background:linear-gradient(180deg,rgba(11,10,8,0) 36%,rgba(11,10,8,.94) 100%)}
.tile .cap{position:absolute;inset-inline:0;inset-block-end:0;padding:14px 16px}
.tile .nm{font:600 19px/1.2 var(--d);color:var(--fg);
  text-shadow:var(--shadow-sub);display:block}
.tile .ro{font-size:13px;color:var(--fg-mut);margin-block-start:3px;display:block}

/* ======================================================= Chronik ======= */
.news{display:flex;flex-direction:column;gap:2px}
.news a{display:grid;gap:3px 20px;grid-template-columns:1fr;padding:16px 18px;
  text-decoration:none;background:var(--card);border:1px solid var(--edge);
  border-radius:var(--r-s);transition:background .2s var(--ease),
  border-color .2s var(--ease),padding-inline-start .2s var(--ease)}
@media (min-width:600px){.news a{grid-template-columns:104px 1fr auto;
  align-items:baseline}}
.news a:hover{background:var(--card-act);border-color:var(--edge-lit);
  padding-inline-start:24px}
.news time{font-size:13px;color:var(--fg-faint);font-variant-numeric:tabular-nums}
.news .t{font:600 17px/1.35 var(--d);color:var(--fg)}
.news a:hover .t{color:var(--gold)}
.news .k{font-size:10px;letter-spacing:.16em;text-transform:uppercase;
  color:var(--fg-faint)}
.news .x{font-size:14px;color:var(--fg-mut);grid-column:1/-1;
  max-inline-size:var(--measure)}
@media (min-width:600px){.news .x{grid-column:2/3}}

/* ======================================================= Preistafel ==== */
.packs{display:grid;gap:0;max-inline-size:var(--measure);
  border:1px solid var(--edge);border-radius:var(--r);overflow:hidden}
.pack{display:flex;align-items:center;gap:14px;padding:14px 20px;
  background:var(--card);border-block-end:1px solid var(--edge);
  transition:background .2s var(--ease);font-size:15px}
.pack:last-child{border-block-end:0}
.pack:hover{background:var(--card-act)}
.pack .c{font-weight:700;color:var(--fg);font-variant-numeric:tabular-nums;
  min-inline-size:6.5ch}
.pack .b{color:var(--gold);font-variant-numeric:tabular-nums;font-size:14px}
.pack .p{margin-inline-start:auto;font-variant-numeric:tabular-nums;
  color:var(--fg-mut)}
.pack--pop{background:#0E0C09}
.tag{font:700 10px var(--d);letter-spacing:.12em;text-transform:uppercase;
  color:#000;background:var(--gold);padding:2px 7px;border-radius:2px}

/* ======================================================= Formular ====== */
.panel{background:var(--bar);border:1px solid var(--edge);border-radius:var(--r);
  padding:28px;max-inline-size:460px}
.field{margin-block-end:16px}
.field label{display:block;font-size:13px;color:var(--fg-mut);margin-block-end:6px}
.field input,.field select{inline-size:100%;block-size:46px;font:400 15px var(--t);
  background:var(--sunk);color:var(--fg);border:1px solid var(--edge-in);
  border-radius:var(--r-s);padding-inline:12px}
.field input:focus,.field select:focus{border-color:var(--gold)}
.hint{font-size:13px;color:var(--fg-faint);margin-block-start:5px}

/* ======================================================= Fuss ========== */
.foot{background:var(--bar);border-block-start:1px solid var(--edge-in);
  padding:36px var(--gutter);position:relative;z-index:4}
.fgrid{max-inline-size:var(--wide);margin-inline:auto;display:grid;gap:26px;
  grid-template-columns:1fr}
@media (min-width:600px){.fgrid{grid-template-columns:repeat(2,1fr)}}
@media (min-width:1000px){.fgrid{grid-template-columns:repeat(3,1fr)}}
.foot h4{font:700 13px var(--d);text-transform:uppercase;letter-spacing:.11em;
  color:var(--fg);margin-block-end:12px}
.foot ul{list-style:none;display:grid;gap:7px}
.foot a{color:var(--fg-mut);text-decoration:none;font-size:14px}
.foot a:hover{color:var(--gold)}
.onion{max-inline-size:var(--wide);margin:28px auto 0;padding-block-start:20px;
  border-block-start:1px solid var(--edge)}
.onion code{font:400 13px var(--n);color:var(--fg-mut);user-select:all;
  overflow-wrap:anywhere;display:block}
.onion .chk{font-size:12px;color:var(--fg-faint);margin-block-start:4px}
.copy{max-inline-size:var(--wide);margin:18px auto 0;font-size:13px;
  color:var(--fg-faint);display:flex;gap:18px;flex-wrap:wrap;align-items:center}

/* =======================================================================
   BEWEGUNG
   Zwei Achsen, bewusst getrennt:
     ZEIT   — Drift, Glut, Puls. Laeuft immer, sehr langsam, kleine Amplitude.
              Perioden teilerfremd (90 / 55 / 34 / 6.5 s), damit sich das
              Gesamtbild nicht sichtbar wiederholt.
     SCROLL — Eintritt und Tiefe. Gekoppelt an die Scrollposition, nicht an
              eine Uhr. Dadurch bewegt sich der Vordergrund GENAU so weit,
              wie der Hintergrund sich verschiebt: das ist die Kopplung,
              nach der gefragt war.

   Der Scroll-Teil laeuft ueber animation-timeline: view(). Firefox
   kann das seit 136; der Tor Browser ist Firefox 140 und deaktiviert es
   nicht. Wo es doch fehlt, greift der @supports-Boden: alles steht
   sofort sichtbar da. Kein Element wartet auf einen Trigger.
   ======================================================================= */
@keyframes pulse{
  0%  {box-shadow:0 0 0 0 rgba(111,165,92,.5)}
  70% {box-shadow:0 0 0 7px rgba(111,165,92,0)}
  100%{box-shadow:0 0 0 0 rgba(111,165,92,0)}}
@keyframes enter{from{opacity:0;transform:translateY(14px)}
                 to  {opacity:1;transform:none}}

/* Eintritt beim Laden — nur was im ersten Bild steht. */
.in-1{animation:enter .55s var(--ease) both}
.in-2{animation:enter .55s .08s var(--ease) both}
.in-3{animation:enter .55s .16s var(--ease) both}

/* Der scrollgekoppelte Eintritt startet bei .55, NICHT bei 0.

   Grund: view() misst den Scrollfortschritt. Wer die Seite mit einem sehr
   hohen Fenster oeffnet, sie als Bild aufnimmt oder eine Vorschau erzeugt,
   scrollt nie — dann bleibt jedes Element in seinem Startzustand stehen.
   Bei opacity:0 heisst das: der halbe Seiteninhalt ist unsichtbar, und
   zwar genau in dem einen Bild, das Vorschau und Teilen-Karte zeigen.
   Ab .55 ist alles lesbar, und die Bewegung bleibt trotzdem spuerbar. */
@keyframes lift-in{from{opacity:.55;transform:translateY(10px)}
                   to  {opacity:1;transform:none}}
/* Die frueher hier stehende `.lift`-Kopplung an
   `animation-timeline: view()` ist entfallen: im Tor Browser lief sie
   nie, und fuer alle anderen macht jetzt der Beobachter dieselbe
   Arbeit — an einer Stelle statt an zweien. */



/* Ein einziger grosser Zug, hinter der ersten Ueberschrift. Er liegt
   auf z-index -1 und sehr blass: er soll die Zeile tragen, nicht
   umrahmen. Genau ein solcher Akzent auf der Seite — der zweite waere
   wieder Tapete. */
.status + .sect .col h2{position:relative}
.status + .sect .col h2::before{
  content:"";position:absolute;z-index:-1;pointer-events:none;
  inset-inline-start:-4%;inset-block-start:-42px;
  inline-size:min(760px,62%);block-size:170px;
  background:url("../img/atmo/stroke-arc.webp") no-repeat left top/contain;
  opacity:.16}

/* === AUFTRITT BEIM SCROLLEN =========================================
   Gesteuert von `js/auftritt.js`: ein IntersectionObserver setzt die
   Klasse `da`, sobald ein Element ins Bild kommt.

   WARUM NICHT `animation-timeline: view()`. Das waere die CSS-Loesung
   und braeuchte kein Skript — aber der Tor Browser kann sie nicht.
   Gemessen in Firefox 140: `animation-timeline` und `animation-range`
   melden beide False, das Feature steht dort hinter einem Flag. Und die
   Seite wird ueber Tor gelesen.

   DIE RICHTUNG DER ZUSTAENDE ist deshalb umgekehrt zum ueblichen
   Muster: Der Grundzustand ist SICHTBAR. Erst `html.js` — gesetzt vom
   Skript selbst, und nur wenn IntersectionObserver vorhanden ist —
   versteckt den Startzustand. Faellt JavaScript aus (Tor "Safest"),
   steht alles da. Kein Inhalt haengt an einem Trigger.
   =================================================================== */

/* Der Strich, der sich malt. Die Maske ist im Grundzustand voll
   aufgezogen; das Skript laesst sie wachsen. Ihre rechte Kante ist
   weich, dadurch hat der Zug eine Spitze statt einer Schnittkante. */
.col h2::after,
.sect--bar + .sect::after,
.sect + .sect--bar::after,
.status + .sect::after{
  -webkit-mask-image:linear-gradient(to right,#000 0 84%,rgba(0,0,0,0) 100%);
  mask-image:linear-gradient(to right,#000 0 84%,rgba(0,0,0,0) 100%);
  -webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;
  -webkit-mask-size:130% 100%;mask-size:130% 100%}

@media (prefers-reduced-motion:no-preference){
  /* --- Startzustaende, NUR wenn das Skript laeuft ------------------ */
  html.js .col h2::after,
  html.js .sect--bar + .sect::after,
  html.js .sect + .sect--bar::after,
  html.js .status + .sect::after{
    -webkit-mask-size:0% 100%;mask-size:0% 100%;
    transition:mask-size 1.1s cubic-bezier(.22,.61,.36,1),
               -webkit-mask-size 1.1s cubic-bezier(.22,.61,.36,1)}
  html.js .col h2.da::after,
  html.js .sect--bar + .sect.da::after,
  html.js .sect + .sect--bar.da::after,
  html.js .status + .sect.da::after{
    -webkit-mask-size:130% 100%;mask-size:130% 100%}

  /* Der kleine Pinselzug vor dem Label wird gezogen. clip-path statt
     Maske: das Element traegt seine FORM bereits als Maske, und eine
     zweite gibt es nicht. */
  /* Der kleine Pinselzug vor dem Label. Hier ist der Fall schwieriger
     als beim Bogen: das Element traegt seine FORM bereits als Maske,
     eine zweite Maske wuerde sie also nicht beschneiden, sondern
     hinzufuegen — aus dem Strich wuerde ein Balken.

     `mask-composite:intersect` SCHNEIDET die Schichten stattdessen:
     sichtbar bleibt, was in beiden liegt — die Form des Strichs, soweit
     der Zug schon gelaufen ist. Im Tor Browser (Firefox 140) gemessen
     vorhanden; das @supports haelt den Rueckfall offen. */
  html.js .eyebrow::before{
    clip-path:inset(0 100% 0 0);
    transition:clip-path .75s cubic-bezier(.22,.61,.36,1)}
  html.js .eyebrow.da::before{clip-path:inset(0 -2% 0 0)}

  @supports (mask-composite:intersect){
    html.js .eyebrow::before,html.js .eyebrow.da::before{clip-path:none}
    html.js .eyebrow::before{
      -webkit-mask-image:url("../img/atmo/stroke-dash.webp"),
                         linear-gradient(to right,#000 0 58%,rgba(0,0,0,0) 100%);
      mask-image:url("../img/atmo/stroke-dash.webp"),
                 linear-gradient(to right,#000 0 58%,rgba(0,0,0,0) 100%);
      -webkit-mask-repeat:no-repeat,no-repeat;mask-repeat:no-repeat,no-repeat;
      -webkit-mask-position:left center,left center;
      mask-position:left center,left center;
      -webkit-mask-size:contain,0% 100%;mask-size:contain,0% 100%;
      -webkit-mask-composite:source-in;mask-composite:intersect;
      transition:mask-size .8s cubic-bezier(.3,.7,.4,1),
                 -webkit-mask-size .8s cubic-bezier(.3,.7,.4,1)}
    html.js .eyebrow.da::before{
      -webkit-mask-size:contain,142% 100%;mask-size:contain,142% 100%}
  }

  /* Der grosse Bogen wird gezogen, nicht aufgedeckt. Der Unterschied
     sitzt in der Kante: `clip-path` schneidet hart ab, das sieht aus
     wie ein aufgehender Vorhang. Eine Maske mit weichem Auslauf hat
     eine SPITZE — vorne duenn, dahinter voll, genau wie ein Pinsel,
     der Farbe verliert und sie beim Aufsetzen wieder aufnimmt.

     Die 138 % am Ende sind kein Tippfehler: die Maske muss ueber das
     Element hinauslaufen, sonst bliebe ihr weicher Auslauf als
     dauerhaft blasse Stelle am rechten Ende stehen. */
  html.js .status + .sect .col h2::before{
    clip-path:none;
    -webkit-mask-image:linear-gradient(to right,#000 0 64%,rgba(0,0,0,0) 100%);
    mask-image:linear-gradient(to right,#000 0 64%,rgba(0,0,0,0) 100%);
    -webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;
    -webkit-mask-size:0% 100%;mask-size:0% 100%;
    transition:mask-size 1.4s cubic-bezier(.3,.7,.4,1) .15s,
               -webkit-mask-size 1.4s cubic-bezier(.3,.7,.4,1) .15s}
  html.js .status + .sect .col h2.da::before{
    clip-path:none;
    -webkit-mask-size:138% 100%;mask-size:138% 100%}

  /* RUECKFALL fuer Drache und Kiefernzweig. Laeuft `js/zeichnen.js`,
     traegt eine Leinwand die beiden Motive und zeichnet sie Strich um
     Strich — dann ist das Pseudoelement `display:none` und alles hier
     wirkungslos. Diese Regeln greifen nur, wenn die Leinwand ausfaellt:
     kein Canvas, fehlendes Bild, abgebrochener Ladevorgang. Dann kommt
     das Motiv wenigstens herein, statt hart zu erscheinen. */
  html.js #chronik .col::after{
    opacity:0;transform:translate3d(26vw,-7vh,0) scale(.88) rotate(5deg);
    transition:opacity 1.5s ease-out,
               transform 1.7s cubic-bezier(.16,.68,.3,1)}
  html.js #chronik .col.da::after{
    opacity:.2;transform:translate3d(0,0,0) scale(1) rotate(0deg)}

  /* scaleX(-1) steht in BEIDEN Zustaenden: es ist die Spiegelung, nicht
     Teil der Bewegung. Faellt es in einem weg, klappt der Zweig um. */
  html.js #konto .col::before{
    opacity:0;transform:scaleX(-1) translate3d(7%,-9%,0) scale(.9);
    transition:opacity 1.3s ease-out,
               transform 1.5s cubic-bezier(.16,.68,.3,1)}
  html.js #konto .col.da::before{
    opacity:.3;transform:scaleX(-1) translate3d(0,0,0) scale(1)}

  /* Die Karten kommen nacheinander. Hier ist eine Verzoegerung richtig:
     die Staffelung laeuft innerhalb EINES Auftritts ab, nicht ueber den
     Scrollweg verteilt. */
  html.js .tiles .tile,
  html.js .card{
    opacity:0;transform:translateY(16px);
    transition:opacity .7s ease-out,transform .7s cubic-bezier(.22,.61,.36,1)}
  html.js .tiles .tile.da,
  html.js .card.da{opacity:1;transform:none}
  html.js .tiles .tile:nth-child(2){transition-delay:.09s}
  html.js .tiles .tile:nth-child(3){transition-delay:.18s}
  html.js .tiles .tile:nth-child(4){transition-delay:.27s}
}

.motion-off *,.motion-off *::before,.motion-off *::after{
  animation:none!important;transition:none!important}
/* Ohne das bliebe der Nebel dort stehen, wo die Animation abbrach —
   eine halb aus dem Bild geschobene Ebene. Zurueck auf Anfang. */
.motion-off .fog i{transform:none!important}
/* Ohne das bliebe ein halb gezogener Strich stehen, wenn jemand den
   Schalter mitten im Ablauf umlegt. */
.motion-off .col h2::after,
.motion-off .sect--bar + .sect::after,
.motion-off .sect + .sect--bar::after,
.motion-off .status + .sect::after{
  -webkit-mask-size:130% 100%!important;mask-size:130% 100%!important}
.motion-off #chronik .col::after{opacity:.20!important;transform:none!important}
.motion-off #konto .col::before{opacity:.30!important;transform:scaleX(-1)!important}
/* Sonst bliebe ein halb gezogener Strich stehen. */
.motion-off .eyebrow::before,
.motion-off .status + .sect .col h2::before{
  clip-path:none!important;transition:none!important}
/* Die beiden Zuege werden nicht mehr beschnitten, sondern maskiert.
   Ein aufgezogener Wert allein genuegt nicht: bliebe die Maske auf
   0 % stehen, waere der Strich bei abgeschalteter Bewegung ganz weg. */
.motion-off .status + .sect .col h2::before{
  -webkit-mask-size:138% 100%!important;mask-size:138% 100%!important}
.motion-off .eyebrow::before{
  -webkit-mask-size:contain,142% 100%!important;
  mask-size:contain,142% 100%!important}
/* Bei abgeschalteter Bewegung gibt es keinen Auftritt: alles steht
   sofort in seinem Endzustand. Die Uebergaenge werden mit abgeraeumt,
   sonst faehrt beim Umlegen des Schalters noch eine Animation zu Ende. */
.motion-off .tiles .tile,.motion-off .card{
  opacity:1!important;transform:none!important;transition:none!important}
.motion-off .col h2::after,
.motion-off .sect--bar + .sect::after,
.motion-off .sect + .sect--bar::after,
.motion-off .status + .sect::after{
  -webkit-mask-size:130% 100%!important;mask-size:130% 100%!important;
  transition:none!important}
/* Dasselbe fuer die Ebenen, die per background-position wandern —
   sonst friert der Nebel an einer beliebigen Stelle des Musters ein. */
.motion-off .sect::after,
.motion-off main.sect::after,
.motion-off .stage::after,
.motion-off .fog .f2::after,
.motion-off .fog::before,
.motion-off .stage__inner::after{background-position:0 50%!important}
/* Die Vordergrundebenen duerfen nicht verschoben einfrieren. */
.motion-off .stage__inner::before{transform:none!important}
/* Sprites frieren sonst auf einem beliebigen Frame ein — bei der
   Fledermaus womoeglich mitten im Bild. Zurueck auf Frame 1, und die
   Fledermaus verschwindet ganz. */
.motion-off .fog .glow::before,
.motion-off .fog .glow::after,
.motion-off .stage__scrim::before{background-position:0 0!important}
.motion-off .stage__scrim::before,
.motion-off .stage__scrim::after,
.motion-off .fog::before,
.motion-off .fog .f1::before{opacity:0!important}
/* Blaetter und Vogel verschwinden ganz, statt auf einem beliebigen
   Frame mitten im Bild einzufrieren. Der Halo bekommt seinen festen
   Wert zurueck — ohne das stuende er auf dem Wert, den die Animation
   gerade hielt. */
.motion-off .fog .glow{opacity:.52!important}
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation:none!important;transition-duration:.01ms!important}
}

/* Abmelden ist POST-only und damit ein Formular, kein Link — es
   steht trotzdem in einer Reihe mit den Knoepfen. */
.acct .inline{display:inline-flex;margin:0}

/* Klassenkachel mit Freisteller statt randlosem Foto: die Figur steht auf
   dem Kartengrund, nicht in einem Bildrahmen. object-fit:contain haelt sie
   ganz im Bild — bei cover fehlten Kopf oder Fuesse, je nach Klasse. */
.tile--figur{background:linear-gradient(180deg,#141109,#0A0907 62%);
  border:1px solid var(--edge)}
.tile--figur{aspect-ratio:2/3}
.tile--figur img{inline-size:100%;block-size:100%;object-fit:contain;
  object-position:50% 100%;transform:none;
  filter:drop-shadow(0 14px 18px rgba(0,0,0,.6))}
.tile--figur:hover img{transform:scale(1.04)}
.tile--figur .veil{background:linear-gradient(180deg,transparent 52%,rgba(7,6,5,.88))}

/* Der Serverzustand ist gemessen (laufende Spiel-Cores), nicht gesetzt.
   Rot ist hier kein Fehler, sondern eine Auskunft — deshalb dieselbe
   ruhige Form wie bei "Online", nur in anderer Farbe. */
.status .off{color:#D9765F}
.status .off .dot{background:#D9765F;box-shadow:0 0 0 3px rgba(217,118,95,.14)}

/* Formularseiten stehen in einer schmalen Spalte: ein Eingabefeld ueber
   die halbe Bildschirmbreite laedt niemanden zum Ausfuellen ein. */
.col--schmal{max-inline-size:480px}

/* Kontrollkasten mit Beschriftung — ein Klick auf den Text schaltet mit,
   weil beides in EINEM <label> steht. */
.kasten{display:flex;align-items:center;gap:10px;cursor:pointer;
  color:var(--fg-body);font-size:14px}
.kasten input{inline-size:17px;block-size:17px;accent-color:var(--gold);
  flex:0 0 auto;cursor:pointer}

/* Fehler stehen AM Feld. Farbe allein reicht nicht — der Rahmen wird
   zusaetzlich kraeftiger, damit es auch ohne Farbsehen auffaellt. */
.field--bad input,.field--bad select{border-color:#C0442F;
  box-shadow:0 0 0 1px rgba(192,68,47,.45)}
.hint--bad{color:#D9765F}
/* Captcha (ALTCHA) im Login: Farben aus den Seitentokens */
altcha-widget{display:block;margin-block-end:16px;--altcha-max-width:100%;
  --altcha-border-radius:var(--r-s);--altcha-border-color:var(--edge-in);
  --altcha-color-base:var(--sunk);--altcha-color-base-content:var(--fg-body);
  --altcha-color-primary:var(--gold);--altcha-color-primary-content:var(--page);
  --altcha-color-error:var(--alarm);--altcha-color-success:var(--ok);
  --altcha-checkbox-border-color:var(--edge-in)}
/* Falle fuer Bots in der Registrierung: aus dem Bild geschoben, nicht
   display:none (das erkennen manche Bots) */
.falle{position:absolute;inset-inline-start:-10000px;inline-size:1px;block-size:1px;overflow:hidden}

/* ======================================================= Meldungen ===== */
/* Rueckmeldung der App nach einer Aktion. Im Fluss unter der Kopfleiste,
   nicht als Einblendung: bei Tor-Safest gibt es kein JS, ein Toast waere
   dort unsichtbar.

   Farbe traegt die Bedeutung NICHT allein — jede Art bekommt zusaetzlich
   einen eigenen Rand links. Wer Rot und Gruen nicht unterscheidet (etwa
   acht Prozent der Maenner), sieht sonst nur graue Kaesten.             */
.meld{margin-block-start:14px}
/* Den Abstand macht das Layout, nicht das Kind. `.col` ist ein
   Flex-Behaelter mit `gap: var(--gap)` (~48px fuer Seitenabschnitte) —
   ein margin am <p> kommt dagegen nicht an, und drei Meldungen standen
   so weit auseinander wie drei Kapitel. */
.meld > .col{gap:8px}
.meld__i{margin:0;padding:11px 15px 12px;
  border:1px solid var(--edge);border-inline-start-width:3px;
  border-radius:var(--r);background:var(--card);
  color:var(--fg-body);font-size:14.5px;line-height:1.55}
.meld__i--success{border-color:color-mix(in srgb,#6FA55C 34%,transparent);
  border-inline-start-color:#6FA55C;color:#B6D8A8}
/* Die App nennt Fehler mal "error", mal "danger" — beides gilt hier,
   damit keine Meldung ungestylt durchrutscht.                           */
.meld__i--error,
.meld__i--danger{border-color:color-mix(in srgb,var(--alarm) 38%,transparent);
  border-inline-start-color:var(--alarm);color:#E8B0A4}
.meld__i--info{border-color:color-mix(in srgb,var(--gold) 30%,transparent);
  border-inline-start-color:var(--gold-dim);color:var(--gold-hi)}

/* Tickets: Zahl offener Tickets im Menue, nur fuers Team (07.10.2026) */
.nav__zahl{display:inline-block;min-inline-size:18px;padding:0 5px;margin-inline-start:6px;border-radius:9px;background:var(--alarm);color:#fff;font:600 11px/18px var(--t);text-align:center;vertical-align:1px}
