/* ===========================================================================
   ostkind.social - eigenes CSS
   ---------------------------------------------------------------------------
   Quelle (HIER bearbeiten):  /opt/mastodon/branding/custom.css
   Aktiv über:                Admin -> Servereinstellungen -> Erscheinungsbild
                              (Feld "Eigenes CSS", entspricht Setting.custom_css)
   Stand:                     2026-08-02

   ENTWURF: clean, flach, ohne Zierrat. Dunkel orientiert an X "Lights out",
   der Grund aber leicht angehoben (#0A0A0B statt reinem Schwarz), das nimmt
   die Härte, ohne den Look zu verlieren. Hell ist die saubere Weiß-Variante.
   Keine Verläufe, keine Schatten, keine Bewegung außer einem Farbwechsel.
   Struktur trägt Linie und Abstand, nicht Dekoration.

   Nach dem Bearbeiten der Datei neu einspielen:
     cd /opt/mastodon
     docker compose cp branding/custom.css web:/tmp/custom.css
     docker compose exec -T web bin/rails runner \
       'Setting.custom_css = File.read("/tmp/custom.css")'
     docker compose exec -T web bin/rails runner \
       'Rails.cache.delete(:setting_digest_custom_css)'

   Komplett zurücknehmen (wirkt sofort, kein Neustart nötig):
     docker compose exec -T web bin/rails runner \
       'Setting.custom_css = ""; Rails.cache.delete(:setting_digest_custom_css)'

   Die zweite Zeile ist NICHT optional: theme_helper.rb hält den SHA256 des CSS
   im Cache und baut daraus den Dateinamen. Ohne die Invalidierung verweist die
   Seite weiter auf den alten Hash.

   AUFBAU: Abschnitt 1 und 2 fassen nur Design-Tokens an und sind upgrade-fest.
   Ab Abschnitt 3 stehen Klassennamen. Fällt einer bei einem Upgrade weg,
   verschwindet nur dieser Effekt, es bricht nichts.
   =========================================================================== */


/* --- 1. Palette ----------------------------------------------------------
   Mastodon 4.6 leitet jede Farbe aus zwei Rohrampen ab (theme/_base.scss):
   Indigo trägt die Marke, Grau trägt Grund, Text und Linien. Hier ansetzen
   färbt die komplette Oberfläche um, hell wie dunkel.                       */

html {
  /* 1a) Marke: aus dem Branding-Blurple #6364FF in OKLCH erzeugt. Je Stufe
     die Helligkeit der Originalrampe behalten, nur Farbton und Sättigung
     getauscht, deshalb bleiben alle Kontraste erhalten. */
  --color-indigo-50: #eef1ff;
  --color-indigo-100: #dee3ff;
  --color-indigo-200: #c4ceff;
  --color-indigo-300: #9facff;
  --color-indigo-400: #7780ff;
  --color-indigo-500: #6364ff;  /* exakt die Branding-Farbe */
  --color-indigo-600: #5246f4;
  --color-indigo-700: #4638d9;
  --color-indigo-800: #3937a6;
  --color-indigo-900: #313384;
  --color-indigo-950: #1d204d;

  /* 1b) Neutralrampe nach dem Vorbild von X: kühl, entsättigt, an den Enden
     weit auseinander. Mastodons Standardgrau hat einen violetten Unterton
     (#67678e, #181820), der die Oberfläche weich und bunt wirken lässt.
     Diese Rampe ist praktisch farblos, dadurch der nüchterne Eindruck. */
  --color-grey-50: #f7f9f9;
  --color-grey-100: #eff1f3;
  --color-grey-200: #e3e6e9;   /* Linien im hellen Modus */
  --color-grey-300: #c9cdd2;
  --color-grey-400: #9ba1a8;
  --color-grey-500: #82858c;
  --color-grey-600: #536471;   /* Nebentext hell, X-Wert */
  --color-grey-700: #3d4046;
  --color-grey-800: #2e3035;   /* Linien im dunklen Modus, X-Wert */
  --color-grey-900: #17181c;   /* Karten und erhöhte Flächen, X-Wert */
  --color-grey-950: #0a0a0b;   /* Seitengrund */

  /* Runde Avatare. Standard sind 8px. Der Kreis ist das auffälligste
     Einzelmerkmal von X und kostet eine Zeile. */
  --avatar-border-radius: 50%;

  /* Dünne, farblose Rollbalken. */
  scrollbar-color: var(--color-grey-700) transparent;
  scrollbar-width: thin;
}


/* --- 2. Semantische Tokens je Modus --------------------------------------
   Die Selektoren sind wörtlich die aus theme/index.scss, damit die Spezifität
   passt. Gewinnen tut diese Datei, weil sie zuletzt geladen wird.

   Der Hochkontrast-Modus bleibt unangetastet: dessen Regeln tragen
   [data-contrast='high'] zusätzlich im Selektor und sind damit spezifischer. */

[data-color-scheme='dark'],
html:not([data-color-scheme]) {
  --color-text-primary: #e7e9ea;                 /* auf Grund 16,3:1 */
  --color-text-secondary: var(--color-grey-500); /* auf Grund 5,4:1, auf Karte 4,8:1 */
  --color-text-tertiary: var(--color-grey-500);

  /* X selbst benutzt #71767B für Nebentext. Das ergibt auf erhöhten Flächen
     nur 3,95:1 und reißt damit die Lesbarkeitsnorm (AA verlangt 4,5). Die
     Rampe liegt deshalb acht Punkte heller. Optisch ist der Unterschied
     kaum zu sehen, an der Norm entscheidet er. */
}

[data-color-scheme='light'] {
  --color-text-primary: #0f1419;  /* auf Weiß 18,5:1, X-Wert */
}


/* --- 3. Flächen flach legen ----------------------------------------------
   Mastodon rundet Spalten und Spaltenköpfe mit 4px an. Das wirkt bei
   randlosen Zeitleisten wie ein halber Kasten. X ist an dieser Stelle
   kantig: durchgehende Fläche, Trennung nur über Haarlinien.                */

.column-header,
.column-header__wrapper,
.column > .scrollable {
  border-radius: 0;
}


/* --- 4. Luft -------------------------------------------------------------
   glitch setzt die Beitragspolsterung bewusst herunter (10px 14px). Für den
   ruhigen Eindruck ist Abstand aber das wirksamste Mittel überhaupt, mehr
   als jede Farbe. X liegt bei 12px 16px, hier etwas großzügiger.            */

.status {
  padding: 14px 16px;
}


/* --- 5. Knöpfe -----------------------------------------------------------
   Pille, halbfett, ein reiner Farbwechsel beim Überfahren. Kein Anheben,
   kein Schein, keine Skalierung.                                            */

.button {
  border-radius: 999px;
  font-weight: 600;
  transition: background-color 0.15s ease;
}


/* --- 6. Kleinkram --------------------------------------------------------
   Textauswahl in Markenfarbe, und Code aus Markdown-Beiträgen (glitch kann
   das) auf einer ruhigen Fläche statt nackter Monospace. Fokusrahmen sind
   bewusst NICHT angefasst: Mastodon 4.6 bringt dafür bereits
   --outline-focus-default mit, das greift die Markenfarbe von allein ab.    */

::selection {
  background: color-mix(in oklab, var(--color-indigo-500) 30%, transparent);
}

.status__content code {
  background: var(--color-bg-secondary);
  border-radius: 4px;
  padding: 0.05em 0.35em;
  font-size: 0.92em;
}

.status__content pre code {
  display: block;
  padding: 0.7em 0.9em;
  overflow-x: auto;
}


/* --- 7. Schreibfeld als Fenster in der Mitte (EXPERIMENT) ----------------
   Mastodon 4.6 kennt kein zentriertes Schreibfenster. In der Modal-Liste steht
   nur COMPOSE_PRIVACY, kein COMPOSE. Das Feld hängt fest in der linken Spalte
   (`.compose-panel`), und beim Antworten wird lediglich das Textfeld fokussiert.

   Dieser Block täuscht das Verhalten von X und Bluesky mit reinem CSS vor:
   sobald das Schreibfeld den Fokus hat, springt es in die Bildschirmmitte, mit
   Abdunkelung dahinter. Klick daneben nimmt den Fokus weg, es geht zurück.
   Beim Antworten greift es ebenfalls, weil Mastodon dabei fokussiert.

   >>> Das ist eine Krücke, keine Lösung. Siehe "Bekannte Lücken" unten. <<<

   ---------------------------------------------------------------------------
   AUSLÖSER IST `.compose-form__highlightable`, NICHT `.compose-form`

   Im Formular stecken neben der Pille auch `<ReplyIndicator/>`,
   `<NavigationBar/>` und `<Warning/>` (compose_form.jsx:284 ff.). Die
   NavigationBar zeigt Profilbild und Handle, und sie ist verlinkt.

   Stand hier `.compose-form:focus-within`, riss ein Klick auf das eigene
   Profilbild das Schreibfenster auf, statt zum Profil zu führen: Browser
   fokussieren Links beim Anklicken, und der Link liegt im selben Formular.

   Der Auslöser sitzt deshalb auf `.compose-form__highlightable`, also allein
   auf der Pille. Antworten funktioniert weiter, weil Mastodon dabei das
   Textfeld fokussiert und das darin liegt.
   ---------------------------------------------------------------------------

   ---------------------------------------------------------------------------
   DER FALLSTRICK, DER DEN ERSTEN ANLAUF GEKOSTET HAT

   `position: fixed` erzeugt IMMER einen eigenen Stapelkontext, auch ohne
   z-index. Der Behälter der linken Spalte, `.columns-area__panels__pane__inner`,
   ist fix positioniert. Ein z-index am Schreibfeld wirkt damit nur INNERHALB
   dieses Behälters, und der Behälter selbst liegt auf der Ebene `auto`, also
   unter jedem Element mit positivem z-index in der Wurzel. Der Schleier am
   body lag dadurch ÜBER dem Fenster.

   Sichtbar war davon nichts: im dunklen Modus liegt ein fast schwarzes Fenster
   unter einem zu 55 % schwarzen Schleier auf fast schwarzem Grund. Es sah aus,
   als würde das Textfeld verschwinden, dabei war es die ganze Zeit da.

   Deshalb wird hier der BEHÄLTER angehoben, nicht das Feld. Alles Weitere
   passiert dann innerhalb seines Kontextes.
   ---------------------------------------------------------------------------

   Zentriert wird NUR `.compose-form`, nicht `.compose-panel`. Im Panel stecken
   auch Suchfeld und Link-Fußzeile. Weil der angehobene Behälter beide mit über
   den Schleier zieht, werden sie währenddessen ausgeblendet.

   Unter 1175px greift der Block absichtlich nicht: dort rendert Mastodon das
   Panel gar nicht erst (`useBreakpoint('full')`), und `ensureComposeIsVisible()`
   schickt einen ohnehin auf die Seite `/publish`. Das ist das bessere Verhalten,
   es soll nicht überschrieben werden.

   Kein `transform` zum Zentrieren, sondern `inset: 0` mit `margin: auto`.
   Ein transform würde ebenfalls einen Containing Block aufmachen und alles
   darin Positionierte ans Fenster binden statt an den Bildschirm.

   z-index 3000 liegt über der Oberfläche (die bleibt unter 2000), aber unter
   Mastodons eigener Modalebene (9998/9999). Emoji-Auswahl und
   Sichtbarkeitsdialog liegen dadurch weiterhin obenauf und nicht darunter.

   Die drei Auslöser stehen als Liste in einem einzigen `:has()`. Das ist
   erlaubt und spart es, jede Regel dreimal zu schreiben.                      */

@media (min-width: 1175px) {
  /* 7a) Den fix positionierten Behälter der linken Spalte über den Schleier
     heben. Ohne diese Regel bleibt alles Weitere unsichtbar. */
  body:has(
      .compose-panel .compose-form__highlightable:focus-within,
      .emoji-picker-dropdown__menu,
      .visibility-modal
    )
    .columns-area__panels__pane--compositional
    .columns-area__panels__pane__inner {
    z-index: 3000;
  }

  /* 7b) Das Schreibfeld als Fenster in die Bildschirmmitte. */
  body:has(
      .compose-panel .compose-form__highlightable:focus-within,
      .emoji-picker-dropdown__menu,
      .visibility-modal
    )
    .compose-panel
    .compose-form {
    position: fixed;
    /* Oben angeschlagen, nicht mittig. X und Bluesky setzen das Fenster
       deutlich höher als die Bildschirmmitte, dort erwartet es das Auge.
       `clamp` hält den Abstand auf sehr flachen wie sehr hohen Bildschirmen
       in einem brauchbaren Bereich.
       Waagerecht zentriert über `inset-inline` statt `left`/`right`, damit
       es in RTL-Sprachen genauso sitzt (Mastodon bringt rtl.scss mit). */
    top: clamp(24px, 7vh, 88px);
    bottom: auto; /* hebt die Pillen-Position aus Abschnitt 8e auf */
    inset-inline: 0;
    margin-inline: auto;
    z-index: 1;
    width: min(600px, calc(100vw - 48px));
    height: fit-content;
    max-height: min(78vh, 700px);
    overflow-y: auto;
    padding: 16px;
    background: var(--color-bg-primary);
    /* Bewusst eine Stufe heller als die übrigen Linien: gegen den abgedunkelten
       Grund ist der Rahmen die einzige Kante, die das Fenster abgrenzt. */
    border: 1px solid var(--color-grey-700);
    border-radius: 16px;
    box-shadow: 0 24px 64px rgb(0 0 0 / 55%);
  }

  /* 7c) Suchfeld und Fußzeile verstecken, solange das Fenster offen ist. Sie
     hängen im selben angehobenen Behälter und lägen sonst als einzige Reste
     der Seitenspalte unabgedunkelt über dem Schleier. */
  body:has(
      .compose-panel .compose-form__highlightable:focus-within,
      .emoji-picker-dropdown__menu,
      .visibility-modal
    )
    .compose-panel
    > :not(.compose-form) {
    opacity: 0;
    pointer-events: none;
  }

  /* 7d) Abdunkelung als ::after am body, nicht als ::before am Fenster selbst.
     Ein negativer z-index innerhalb des Fensters würde nach den Malregeln
     dessen eigenen Hintergrund mit abdunkeln, nicht nur die Seite dahinter.
     Der Schleier fängt Klicks ab, und genau das schließt das Fenster: der
     Klick nimmt dem Textfeld den Fokus. */
  body:has(
      .compose-panel .compose-form__highlightable:focus-within,
      .emoji-picker-dropdown__menu,
      .visibility-modal
    )::after {
    content: '';
    position: fixed;
    inset: 0;
    z-index: 2999;
    background: rgb(0 0 0 / 55%);
  }
}

/* Bekannte Lücken, bewusst nicht geflickt:

   1. Emoji-Auswahl und Sichtbarkeitsdialog rendern über Portale AUSSERHALB des
      Schreibfelds (react-overlays mit `strategy: fixed`, die Sichtbarkeit sogar
      als eigenes Modal). Damit ist `:focus-within` weg und das Fenster würde
      zurückspringen. Die beiden Zusatzeinträge in der `:has()`-Liste fangen
      genau diese zwei Fälle ab.
   2. Andere Aufklapper im Schreibfeld (Sprache, Umfrage, bei glitch der
      Inhaltstyp) sind NICHT abgefangen. Sie benutzen die allgemeine Klasse
      `.dropdown-menu`, und die auszuwerten würde das Fenster auch bei jedem
      unbeteiligten Menü irgendwo auf der Seite aufziehen. Beim Öffnen eines
      solchen Menüs klappt das Fenster also kurz in die Seitenspalte zurück.
   3. `.visibility-modal` in der Liste greift auch, wenn der Sichtbarkeitsdialog
      aus dem Kontextmenü eines fremden Beitrags kommt. Dann zentriert sich das
      leere Schreibfeld ohne Anlass.
   4. Ein angefangener Entwurf verschwindet beim Wegklicken zurück in die
      Seitenspalte, statt wie bei X das Fenster offen zu halten. Ohne
      JavaScript gibt es keinen Zustand, an dem sich das festmachen ließe.

   Nach jedem Mastodon-Upgrade prüfen: ändern sich `.compose-panel`,
   `.compose-form`, `.columns-area__panels__pane__inner`,
   `.emoji-picker-dropdown__menu` oder `.visibility-modal`, fällt der Block
   still aus. Er bricht nichts, das Feld klebt dann wieder links wie vorher. */


/* --- 8. Spaltenaufteilung wie bei X (EXPERIMENT) ------------------------
   Baut auf Abschnitt 7 auf und ist ohne diesen sinnlos.

       links   Navigationsmenü, unten der Post-Knopf
       mitte   Zeitleiste
       rechts  oben die Suche, unten die Trends

   Zwei sehr verschiedene Dinge, beim Nachbessern auseinanderhalten:

     8a     Spaltentausch. Robust. `.columns-area__panels` ist ein Flexbox,
            also genügt `order`. Kein Klassenname aus dem Innenleben nötig.
     8b-8g  Der Rest. Bastelei. Hängt an Klassennamen aus dem Innenleben und
            an einer Rechnung mit Mastodons Spaltenmaßen. Fällt bei einem
            Upgrade etwas aus, hier zuerst nachsehen.

   Warum überhaupt gerechnet wird: Suche und Trends stehen im Markup in
   verschiedenen Zweigen. Die Suche sitzt in der Schreibspalte, die Trends
   stecken im Navigationsmenü (`navigation_panel/index.tsx`, `<Trends />` nach
   dem `flex-spacer`). CSS kann kein Element in einen anderen Zweig umhängen.
   Die Trends müssen also aus dem Fluss genommen und an die Stelle gesetzt
   werden, wo die rechte Spalte steht. Dasselbe gilt für den Post-Knopf.      */

@media (min-width: 1175px) {
  html {
    /* Mastodon-Werte, nachgeschlagen in components.scss:
       Seitenspalte 285px (`__pane__inner`), Hauptspalte max. 600px
       (`__panels__main`), Abstand 16px (`gap` in `__panels`).
       Zusammen 285 + 16 + 600 + 16 + 285 = 1202px, mittig ausgerichtet.
       Die halbe Breite davon ist 601px. */
    --ostkind-rand: max(10px, calc(50% - 601px));
    --ostkind-spaltenbreite: 285px;

    /* Höhe, die unten rechts für die Link-Fußzeile freigehalten wird. Die
       Trends enden darüber. Der einzige geratene Wert in diesem Abschnitt:
       die Fußzeile ist eine Liste, ihre Höhe hängt an Sprache und daran, ob
       Nutzungsbedingungen aktiv sind. Klebt sie an den Trends, hier erhöhen;
       klafft eine Lücke, hier verringern. */
    --ostkind-fussbereich: 210px;

    /* Beschriftung des Post-Knopfes. CSS kann den Platzhaltertext des
       Textfelds nicht ändern, deshalb liegt hier eine eigene Beschriftung
       darüber. Wer die Sprache umstellt, ändert sie hier von Hand. */
    --ostkind-postknopf: 'Posten';
  }

  /* 8a) Navigation nach links, Schreibspalte nach rechts.
     Die DOM-Reihenfolge bleibt unberührt, damit Tabulator-Reihenfolge und
     Screenreader nicht durcheinanderkommen.
     `justify-content` muss mitwandern: die Panes sind breiter als ihr Inhalt,
     und der Inhalt hängt sich per justify an die Kante zur Hauptspalte. Beide
     Werte tauschen daher ebenfalls. */
  .columns-area__panels__pane--navigational {
    order: -1;
    justify-content: flex-end;
  }

  .columns-area__panels__pane--compositional {
    order: 1;
    justify-content: flex-start;
  }

  /* 8b) In der rechten Spalte bleibt oben die Suche stehen. Sie ist im Markup
     das erste Kind der Schreibspalte, sitzt also von allein oben und braucht
     keine Regel.

     Die Link-Fußzeile mit dem Versionshinweis kommt ganz nach unten rechts.
     Sie hat keine feste Klasse (CSS-Module, `classes.wrapper`), ist aber das
     einzige <footer> in diesem Zweig, und darüber lässt sie sich sicher
     greifen. Aus dem Fluss genommen, weil sie im Markup direkt unter der
     Suche steht und dort oben kleben würde. */
  .compose-panel > footer {
    position: fixed;
    inset-inline-end: var(--ostkind-rand);
    bottom: 24px;
    width: var(--ostkind-spaltenbreite);
    max-height: calc(var(--ostkind-fussbereich) - 32px);
    overflow-y: auto;
  }

  /* 8c) Trends darüber. Aus dem Navigationsmenü herausgelöst und an die rechte
     Spalte gesetzt, sie enden über der Fußzeile.
     Angeschlagen wird unten, nicht oben: so hängen Trends und Fußzeile
     zusammen und die Höhe des Suchfelds spielt keine Rolle. Die Deckelung
     verhindert, dass die Liste bei vielen Trends nach oben in die Suche
     hineinwächst. */
  .navigation-panel__portal {
    position: fixed;
    inset-inline-end: var(--ostkind-rand);
    bottom: var(--ostkind-fussbereich);
    width: var(--ostkind-spaltenbreite);
    max-height: 50vh;
    overflow-y: auto;
  }

  /* 8d) Mastodons eigener Post-Knopf in der Navigation wäre doppelt. Er führt
     außerdem auf die Seite `/publish` statt das Fenster aus Abschnitt 7 zu
     öffnen, ist hier also der falsche Knopf. */
  .navigation-panel__menu > li:has(> .navigation-panel__compose-button) {
    display: none;
  }

  /* Platz, damit die untersten Menüpunkte nicht unter dem Post-Knopf liegen. */
  .navigation-panel {
    padding-bottom: 88px;
  }

  /* 8e) Der Post-Knopf unten links.
     Es ist DASSELBE Element wie das Schreibfeld, nur eingeklappt, kein
     zweiter Knopf daneben. CSS kann einen Klick auf ein Element nicht in
     einen Fokus auf ein anderes übersetzen. Angeklickt bekommt das Textfeld
     den Fokus, und damit greift Abschnitt 7 und zieht dieselbe Fläche zum
     Fenster auf. */
  .compose-panel .compose-form {
    position: fixed;
    bottom: 24px;
    inset-inline-start: var(--ostkind-rand);
    width: var(--ostkind-spaltenbreite);
    z-index: 1;
  }

  .compose-panel .compose-form__highlightable {
    height: 48px;
    overflow: hidden;
    border-radius: 999px;
    border-color: transparent;
    cursor: pointer;
  }

  /* Die Beschriftung liegt als deckende Fläche über dem Textfeld. Deckend,
     damit weder Platzhalter noch ein angefangener Entwurf durchscheinen, und
     damit an Textfarbe und Platzhalter nichts angefasst werden muss.
     `pointer-events: none` lässt den Klick durch auf das Textfeld darunter,
     sonst ginge der Knopf ins Leere.
     Schwarz auf Weiß im dunklen Modus, im hellen dreht es sich um: die beiden
     inverted-Tokens von Mastodon machen das von allein. Fest verdrahtetes
     Weiß wäre im hellen Modus ein weißer Knopf auf weißem Grund. */
  .compose-panel .compose-form__highlightable::after {
    content: var(--ostkind-postknopf);
    position: absolute;
    inset: 0;
    display: grid;
    place-items: center;
    border-radius: 999px;
    background: var(--color-bg-inverted);
    color: var(--color-text-inverted);
    font-weight: 700;
    font-size: 15px;
    pointer-events: none;
  }

  /* Im Markup stehen die Aufklapper über dem Eingabefeld. Ohne diese Zeile
     läge nicht das Textfeld unter der Beschriftung, sondern eine Reihe
     abgeschnittener Knöpfe, und der Klick träfe einen davon. */
  .compose-panel .compose-form__input {
    order: -1;
  }

  /* Mauszeiger. Die Beschriftung ist für Klicks durchlässig, also entscheidet
     das Element DARUNTER über den Zeiger, und das ist ein Textfeld: es zeigt
     einen Schreibstrich. Auf dem Elternelement reicht `cursor` deshalb nicht,
     es muss aufs Textfeld selbst. */
  .compose-panel .compose-form__input,
  .compose-panel .compose-form__input textarea {
    cursor: pointer;
  }

  /* 8f) Aufgezogen ist es wieder ein normales Schreibfeld.
     Höhere Spezifität als 8e durch das vorangestellte `body:has(...)`,
     die Reihenfolge im Stylesheet entscheidet hier also nicht. */
  body:has(
      .compose-panel .compose-form__highlightable:focus-within,
      .emoji-picker-dropdown__menu,
      .visibility-modal
    )
    .compose-panel
    .compose-form__highlightable {
    height: auto;
    overflow: visible;
    border-radius: 4px;
    border-color: var(--color-border-primary);
    cursor: auto;
  }

  body:has(
      .compose-panel .compose-form__highlightable:focus-within,
      .emoji-picker-dropdown__menu,
      .visibility-modal
    )
    .compose-panel
    .compose-form__highlightable::after {
    content: none;
  }

  body:has(
      .compose-panel .compose-form__highlightable:focus-within,
      .emoji-picker-dropdown__menu,
      .visibility-modal
    )
    .compose-panel
    .compose-form__input {
    order: 0;
  }

  /* Aufgezogen ist es wieder ein Textfeld und darf den Schreibstrich zeigen. */
  body:has(
      .compose-panel .compose-form__highlightable:focus-within,
      .emoji-picker-dropdown__menu,
      .visibility-modal
    )
    .compose-panel
    .compose-form__input,
  body:has(
      .compose-panel .compose-form__highlightable:focus-within,
      .emoji-picker-dropdown__menu,
      .visibility-modal
    )
    .compose-panel
    .compose-form__input
    textarea {
    cursor: auto;
  }
}


/* --- 9. Fenster nach dem Absenden schließen (EXPERIMENT) ----------------
   Nach dem Veröffentlichen blieb das Fenster offen. Der Grund steht in
   `compose_form.jsx:242`:

       } else if (prevProps.isSubmitting && !this.props.isSubmitting) {
         this.textareaRef.current.focus();
       }

   Mastodon setzt den Fokus nach dem Absenden ABSICHTLICH zurück ins Textfeld,
   damit man gleich weiterschreiben kann. `:focus-within` bleibt damit wahr, und
   Abschnitt 7 hält das Fenster offen.

   „Gerade geöffnet" und „gerade abgeschickt" sind für CSS derselbe Zustand:
   Textfeld fokussiert und leer. Es braucht ein Signal von außen. Das Signal ist
   der Veröffentlichungs-Toast: `show_published_toast` steht in glitch
   standardmäßig auf `true`, und nur dieser Toast bekommt über
   `action: messages.open` einen `.notification-bar__action`-Knopf
   (actions/compose.js:313). Fehlermeldungen haben keinen.

   Der Griff: ein Element, das nicht gerendert wird, kann keinen Fokus halten.
   Für einen Moment wird der Inhalt der Pille unsichtbar geschaltet, der Browser
   nimmt den Fokus weg, `:focus-within` wird falsch, das Fenster klappt zu.

   Gebraucht wird das nur für EINEN Moment, nämlich den, in dem Mastodon den
   Fokus zurücksetzt. Danach darf alles sofort zurückkommen. 0,6 Sekunden sind
   reichlich und decken auch ab, dass die Reihenfolge von Fokus (React,
   componentDidUpdate) und Toast (Redux) nicht garantiert ist.

   ---------------------------------------------------------------------------
   DREI ANLÄUFE, DIE NICHT FUNKTIONIERT HABEN. NICHT WIEDERHOLEN.

   1. `display: none` als Keyframe-Animation.
      "Setting the display property to none will terminate any running
       animation applied to the element and its descendants."
      Die Animation schaltet sich mit ihrem eigenen ersten Keyframe selbst ab.

   2. `display: none` als feste Regel, aber nur auf dem Textfeld.
      Der Fokus lag gar nicht dort. Wer den Absende-Knopf anklickt, hat ihn auf
      dem Knopf. Mastodon findet das Textfeld ausgeblendet vor, der Fokus bleibt
      auf dem Knopf liegen, und der steckt im selben Formular.

   3. `display: none` als feste Regel auf allem, was Fokus halten kann.
      Wirkte, war aber zu grob und für die ganze Toast-Dauer aktiv:
        - `<NavigationBar/>` gehört dazu, und die trägt das Profilbild. Das
          verschwand also bei jeder Veröffentlichung für fünf Sekunden.
        - Ohne Textfeld war der Post-Knopf in dieser Zeit tot.

   Jetzt: `visibility: hidden` per Animation. Beendet Animationen NICHT, ist
   also zeitlich begrenzbar, und nimmt einem Element ebenso den Fokus.
   Beide Keyframes tragen denselben Wert, damit die Sonderregel für die
   Interpolation von `visibility` gar nicht erst greift.
   ---------------------------------------------------------------------------

   Angefasst wird nur der Inhalt von `.compose-form__highlightable`. Dort sitzen
   Textfeld, Aufklapper und der Absende-Knopf, also alles, was nach dem Absenden
   den Fokus tragen kann. Die Geschwister im Formular (`<ReplyIndicator/>`,
   `<NavigationBar/>` mit dem Profilbild, `<Warning/>`) bleiben unberührt.

   Die Beschriftung des Post-Knopfes hängt als `::after` an
   `.compose-form__highlightable` selbst, ist also kein Kind. Der Knopf sieht
   während der 0,6 Sekunden unverändert aus.

   Fällt aus, wenn der Toast in den glitch-Einstellungen abgeschaltet wird
   (Lokale Einstellungen -> Beitragsfeld). Dann bleibt es beim alten Verhalten,
   kaputt geht nichts.                                                        */

@keyframes ostkind-fokus-loesen {
  from,
  to {
    visibility: hidden;
  }
}

@media (min-width: 1175px) {
  body:has(.notification-bar__action)
    .compose-panel
    .compose-form__highlightable
    > * {
    animation: ostkind-fokus-loesen 0.6s;
  }
}


/* --- 10. Mastodon-Logo oben, anklickbar -------------------------------
   Auf dem Desktop ist das Logo GAR NICHT im DOM. `home_timeline/index.jsx:158`
   tauscht es nur auf schmalen Fenstern gegen das Haus-Icon ein:

       iconComponent={matchesBreakpoint ? SymbolLogo : HomeIcon}

   Es lässt sich also nicht einblenden, es muss eingebettet werden. Verbaut ist
   Mastodons eigene `app/javascript/images/logo.svg`, unverändert, nur
   zeilenweise zusammengezogen und fürs `url()` kodiert.

   Als Hintergrundbild, NICHT als Maske: das Logo besteht aus zwei Pfaden, einer
   mit dem violetten Verlauf, einer in Weiß für das „m". Eine Maske würde beide
   zu einer Fläche verschmelzen und das „m" verschlucken.

   ---------------------------------------------------------------------------
   ANKLICKBAR, OBWOHL ES EIN PSEUDOELEMENT IST

   Ein Pseudoelement kann kein Link sein. Es ist aber TEIL des Elements, an dem
   es hängt, und zählt zu dessen Klickfläche. Es hängt deshalb nicht mehr an der
   Navigationsspalte, sondern am Startseiten-Menüpunkt
   (`navigation_panel/index.tsx:301`, `to='/home'`). Ein Klick auf das Logo ist
   damit ein Klick auf diesen Link und führt nach /home.

   Damit es trotzdem ÜBER dem Menü sitzt und nicht im Menüpunkt:

     - Das Menü bekommt oben 52px Polster als Standfläche.
     - Das Logo wird absolut positioniert, 46px über der Oberkante des
       Menüpunkts, landet also genau in diesem Polster.
     - `position: relative` steht ausdrücklich am Link, damit der Bezugsrahmen
       nicht davon abhängt, ob Mastodon den Link zufällig positioniert.

   Das Polster gehört zum Scrollbereich des Menüs, das Logo wird also nicht vom
   `overflow-y: auto` abgeschnitten. Es scrollt allerdings mit, wenn das Menü so
   lang wird, dass es scrollt.

   Nebenwirkung, bewusst in Kauf genommen: wer über das Logo fährt, hebt den
   Menüpunkt „Startseite" darunter mit hervor. Es ist dasselbe Element. Das ist
   eher hilfreich, es zeigt an, dass da ein Link liegt.
   ---------------------------------------------------------------------------

   Die 11px Einrückung setzen die Mitte des 34px-Logos auf die Mitte der
   24px-Menüicons (die stehen bei 16px). Wird das Logo größer, hier mitziehen.

   Austauschen gegen das eigene Branding: die Datenadresse unten durch
   `branding/ostkind-favicon.svg` ersetzen, gleiches Verfahren.               */

@media (min-width: 1175px) {
  .navigation-panel__menu {
    padding-top: 52px;
  }

  .navigation-panel__menu a[href='/home'] {
    position: relative;
  }

  .navigation-panel__menu a[href='/home']::before {
    content: '';
    position: absolute;
    top: -46px;
    inset-inline-start: 11px;
    width: 34px;
    height: 34px;
    background-image: url("data:image/svg+xml,%3Csvg width='65' height='65' viewBox='0 0 61 65' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M60.7539 14.3904C59.8143 7.40642 53.7273 1.90257 46.5117 0.836066C45.2943 0.655854 40.6819 0 29.9973 0H29.9175C19.2299 0 16.937 0.655854 15.7196 0.836066C8.70488 1.87302 2.29885 6.81852 0.744617 13.8852C-0.00294988 17.3654 -0.0827298 21.2237 0.0561464 24.7629C0.254119 29.8384 0.292531 34.905 0.753482 39.9598C1.07215 43.3175 1.62806 46.6484 2.41704 49.9276C3.89445 55.9839 9.87499 61.0239 15.7344 63.0801C22.0077 65.2244 28.7542 65.5804 35.2184 64.1082C35.9295 63.9428 36.6318 63.7508 37.3252 63.5321C38.8971 63.0329 40.738 62.4745 42.0913 61.4937C42.1099 61.4799 42.1251 61.4621 42.1358 61.4417C42.1466 61.4212 42.1526 61.3986 42.1534 61.3755V56.4773C42.153 56.4557 42.1479 56.4345 42.1383 56.4151C42.1287 56.3958 42.1149 56.3788 42.0979 56.3655C42.0809 56.3522 42.0611 56.3429 42.04 56.3382C42.019 56.3335 41.9971 56.3336 41.9761 56.3384C37.8345 57.3276 33.5905 57.8234 29.3324 57.8156C22.0045 57.8156 20.0336 54.3384 19.4693 52.8908C19.0156 51.6397 18.7275 50.3346 18.6124 49.0088C18.6112 48.9866 18.6153 48.9643 18.6243 48.9439C18.6333 48.9236 18.647 48.9056 18.6643 48.8915C18.6816 48.8774 18.7019 48.8675 18.7237 48.8628C18.7455 48.858 18.7681 48.8585 18.7897 48.8641C22.8622 49.8465 27.037 50.3423 31.2265 50.3412C32.234 50.3412 33.2387 50.3412 34.2463 50.3146C38.4598 50.1964 42.9009 49.9808 47.0465 49.1713C47.1499 49.1506 47.2534 49.1329 47.342 49.1063C53.881 47.8507 60.1038 43.9097 60.7362 33.9301C60.7598 33.5372 60.8189 29.8148 60.8189 29.4071C60.8218 28.0215 61.2651 19.5781 60.7539 14.3904Z' fill='url(%23paint0_linear_89_8)'/%3E%3Cpath d='M50.3943 22.237V39.5876H43.5185V22.7481C43.5185 19.2029 42.0411 17.3949 39.036 17.3949C35.7325 17.3949 34.0778 19.5338 34.0778 23.7585V32.9759H27.2434V23.7585C27.2434 19.5338 25.5857 17.3949 22.2822 17.3949C19.2949 17.3949 17.8027 19.2029 17.8027 22.7481V39.5876H10.9298V22.237C10.9298 18.6918 11.835 15.8754 13.6453 13.7877C15.5128 11.7049 17.9623 10.6355 21.0028 10.6355C24.522 10.6355 27.1813 11.9885 28.9542 14.6917L30.665 17.5633L32.3788 14.6917C34.1517 11.9885 36.811 10.6355 40.3243 10.6355C43.3619 10.6355 45.8114 11.7049 47.6847 13.7877C49.4931 15.8734 50.3963 18.6899 50.3943 22.237Z' fill='white'/%3E%3Cdefs%3E%3ClinearGradient id='paint0_linear_89_8' x1='30.5' y1='0' x2='30.5' y2='65' gradientUnits='userSpaceOnUse'%3E%3Cstop stop-color='%236364FF'/%3E%3Cstop offset='1' stop-color='%23563ACC'/%3E%3C/linearGradient%3E%3C/defs%3E%3C/svg%3E");
    background-size: contain;
    background-repeat: no-repeat;
    background-position: center;
  }
}


