/* ============================================================
   Praxis Krüger — Die Seitenhülle
   Was auf jeder Seite gleich ist: der Kopf mit PRAXIS und dem Titel,
   der freigehaltene Streifen des Menüs, die Maße des Zeichens.

   Werte stehen hier keine, die nicht aus einem Token gerechnet sind.
   Die Bausteine selbst stehen in komponenten.css, die Schrift in
   textstile.css.
   ============================================================ */
*{box-sizing:border-box}

/* Die Grade kommen aus tokens.css und sind dort über ihre Aufgabe definiert:
   --fs-mark, --fs-nav, --fs-lead, --fs-read, --fs-caption. Hier steht nur,
   was diese Seiten damit anstellen. */
:root{
  /* --body-lg, --body-md und --zeilenmass kommen aus tokens.css und sind im
     Werkzeug einstellbar. --ch-width misst seite.js zur Laufzeit an der
     Schrift; ohne das Skript greift der Vorgabewert im Token. */
  /* Maße des Overlays. Sie stehen hier und nicht in der Komponente, weil
     sie zu dieser Website gehören, nicht zur Gattung Menü. */
  --menue-breite:min(100%, 60rem);
  /* Luft um das Zeichen im Anschnitt: links wie rechts dieselbe. Ein halbes
     Gutter — mit dem vollen stand der Streifen zu weit in die Seite hinein,
     er soll das Menü ankündigen und nicht schon eine Spalte sein. */
  --menue-luft:calc(var(--gutter) / 2);
  /* Der Anschnitt ist genau so breit, dass das Zeichen samt Luft darin steht —
     er wird daraus gerechnet, nicht daneben gesetzt. */
  --menue-anschnitt:calc(var(--burger-breite) + var(--menue-luft) * 2);
  /* PRAXIS sitzt auf einer Sprosse der Skala wie jedes andere Element auch —
     --fs-3xl. Vorher wurde sein Grad hier ausgerechnet, damit seine
     Versalhöhe genau die zwei Titelzeilen daneben überspannte. Das ergab
     einen Wert, den die Skala nicht kannte: 87 px, in keiner Liste, in
     keinem Regler. Die optische Feinheit ist den Preis nicht wert. */
  /* Überhang des Wortes: der Weg von der Oberkante der Zeile bis zur
     Oberkante der Versalien — halbe Durchschusshälfte plus der Rest des
     Schriftkastens über der Versalhöhe. Alle drei Maße misst seite.js an
     der Schrift. Der Kopf zieht sich um genau diesen Betrag nach oben,
     dann steht PRAXIS oben so weit von der Kante wie links. */
  --mark-ueberhang:calc((var(--lh-display) - (var(--font-ascent, 1.165)
    + var(--font-descent, .34))) / 2
    + var(--font-ascent, 1.165) - var(--cap-height, .712));
  --burger-spalt:round(calc(var(--fs-mark) * var(--cap-height, .712)), 1px);
  --burger-breite:calc(var(--burger-spalt) * 1.35);
  /* Der Strich des Zeichens hängt am Stamm von PRAXIS: --stem-width wird zur
     Laufzeit gemessen, --fs-mark ist der Grad des Wortes daneben.
     Nachgemessen am gerenderten Wort bei 108 px Grad: die Stämme von P, R, A,
     I sind 10,5 bis 10,85 px breit. Geometrisch gleich dick sind die Striche
     des Zeichens damit bei 10 px — und sehen trotzdem doppelt so fett aus.
     Der Grund ist die Länge: ein Stamm ist 77 px hoch, ein Strich des Zeichens
     104 px lang, und die Striche liegen zu dritt übereinander. Gleiche Stärke,
     dreifache Fläche. Der Faktor nimmt genau das zurück — er ist keine
     Schätzung, sondern die Korrektur einer nachgewiesenen Täuschung.
     Wenn es noch dünner soll: diese eine Zahl.
     round() auf ganze Pixel, sonst rastet jeder der drei Striche anders ein
     und sie sehen verschieden dick aus, obwohl sie es nicht sind. */
  --burger-optik:.55;
  /* Heller Strich auf dunklem Grund wirkt fetter als dunkler auf hellem —
     Irradiation: die helle Fläche strahlt in die dunkle hinein. Derselbe
     Pixelwert liest sich auf der Seite deshalb dünner als auf dem Streifen.
     Dieser Zuschlag gleicht das aus und greift nur dort, wo das Zeichen auf
     hellem Grund steht; auf dem Streifen bleibt es bei 1. */
  --burger-irradiation:1;
  --burger-strich:round(calc(var(--fs-mark) * var(--stem-width, .095)
    * var(--burger-optik) * var(--burger-irradiation)), 1px);
}

body{
  margin:0;
  min-height:100svh;
  display:flex;flex-direction:column;
  /* Ein Wert rundum: das Gutter. Es ist der Abstand, mit dem das Raster
     ohnehin arbeitet — dann gilt er auch nach oben und unten. */
  padding:var(--gutter);
  /* Oben kein Polster: der Kopf klebt am oberen Rand und bringt seine Luft
     selbst mit. Läge sie hier, schöbe sie ihn beim Scrollen weg. */
  padding-top:0;
  /* Rechts liegt dauerhaft der Streifen des Menüs. Die Seite hält ihn frei —
     fest, nicht wandernd: beim Öffnen rückt hier nichts. */
  padding-right:calc(var(--menue-anschnitt) + var(--gutter));
}

/* ---- Kopf ----
   PRAXIS und der Titel auf einer Grundlinie: die LETZTE des Titels. Der
   Grad von PRAXIS ist darauf gerechnet, nicht gewählt — seine Versalhöhe
   reicht von der Oberkante der ersten Zeile bis zur Grundlinie der zweiten,
   der Titel steht also genau in seinem Versalband.
   PRAXIS bleibt dabei auf jeder Seite an derselben Stelle: über der
   gemeinsamen Grundlinie ist es das höhere Element, und damit bestimmt es
   die Oberkante des Kopfs — gleich ob der Titel daneben ein- oder
   zweizeilig ist. Bei schmalem Fenster fallen sie untereinander. */
.kopf{display:flex;align-items:last baseline;
  /* Der Abstand kommt aus dem Gutter, dem einen Abstandswert der Seite —
     kein zweiter Wert für dieselbe Aufgabe. */
  gap:calc(var(--gutter) * 2);
  flex-wrap:wrap;
  /* Über der Versalhöhe von PRAXIS steckt Luft im Glyphenkasten, unter der
     Grundlinie weniger. Gleicher Abstand sähe oben größer aus — die Differenz
     wird hier abgezogen: Ascent 1,169 − Versalhöhe 0,712 abzüglich des halben
     negativen Durchschusses.
     Sie hängt am GANZEN Kopf, nicht an PRAXIS selbst. Ein negativer Rand am
     Wort würde seinen Anteil über der Grundlinie verkleinern; auf der
     Startseite wäre dann der zweizeilige Titel das höhere Element und
     bestimmte die Oberkante — PRAXIS säße dort elf Pixel tiefer als auf den
     Unterseiten. So bleibt PRAXIS das höhere Element und damit überall
     gleich hoch. */
  /* Der Kopf bleibt oben stehen und der Inhalt läuft darunter durch. Keine
     Linie, kein Schatten, keine Kante: nur die Fläche der Seite selbst. Damit
     sie bis an die Fensterränder reicht, zieht sich der Kopf um das Polster
     des Körpers nach außen und legt es sich innen wieder an — sonst
     schimmerte links und rechts Text an ihm vorbei.
     Die optische Korrektur sitzt jetzt im Polster statt im Rand: ein
     negativer Rand oben verschöbe den Kasten selbst, und ein klebender
     Kasten darf sich nicht verschieben. */
  position:sticky;top:0;z-index:40;
  background:var(--bg-base-default);
  margin-left:calc(var(--gutter) * -1);
  margin-right:calc((var(--menue-anschnitt) + var(--gutter)) * -1);
  padding-left:var(--gutter);
  padding-right:calc(var(--menue-anschnitt) + var(--gutter));
  /* Die Luft über der Versalhöhe soll so groß sein wie das Polster links.
     Ein Teil davon steckt schon im Glyphenkasten — der Überhang wird deshalb
     abgezogen. Ist er größer als das Polster, bleibt nichts abzuziehen: dann
     steht PRAXIS eben so tief, wie seine eigene Oberlänge es verlangt. Ein
     negatives Polster gäbe es nicht, und ein negativer Rand verschöbe den
     klebenden Kasten. */
  padding-top:max(0px, calc(var(--gutter) - var(--fs-mark) * var(--mark-ueberhang)));
  /* Unten dasselbe Maß, von der Grundlinie aus gemessen: unter ihr hält der
     Glyphenkasten noch eine Unterlänge Luft, die das Auge mitzählt. Ohne den
     Abzug säße die Kante optisch tiefer als oben, obwohl beide Zahlen gleich
     wären. Gemessen wird an der letzten Zeile, und die steht im Aufmachergrad. */
  padding-bottom:max(0px, calc(var(--gutter) - var(--fs-lead) * var(--descent-ink, .193)));
}
.kopf .praxis{
  margin:0;max-width:none;
  /* Auf schmalen Schirmen setzt die Regel unten --praxis-eng, damit das Wort
     neben das Zeichen passt. Sonst gilt --fs-mark. */
  font-size:var(--praxis-eng, var(--fs-mark));
  /* Displaydurchschuss aus dem System statt fest 1 — sonst hätte der Regler
     im Werkzeug keinen Leser auf der Seite. */
  line-height:var(--lh-display);letter-spacing:0}
/* Jede Seite hat genau eine h1: ihren Titel. Das ist keine Rubrik —
   deshalb der Seitengrad und nicht der Displaygrad. */
.kopf h1{font-size:var(--fs-lead);line-height:var(--lh-title-lead, var(--lh-body));
  letter-spacing:var(--tracking-lead, var(--tracking-display));margin:0;max-width:none}
/* Ohne data-modus steht das Zeichen auf der hellen Seite, nicht auf dem
   dunklen Streifen. Nur dann der Zuschlag — der Wert wird hier gesetzt, nicht
   die Strichstärke selbst, damit auch die Ausrichtung an der Grundlinie
   (siehe unten) mit derselben Zahl rechnet. */
.menu-knopf:not([data-modus]){--burger-irradiation:1.15}

/* Der unterste Strich des Zeichens sitzt auf der Grundlinie von PRAXIS.
   Beide hängen am selben Anker: die Versalhöhe von PRAXIS beginnt beim
   Gutter und endet eine Versalhöhe tiefer, und genau eine Versalhöhe ist der
   Abstand vom obersten zum untersten Strich. Der Kasten des Zeichens ist um
   seine eigene Strichstärke höher — also setzt er um diese höher an. */
.menu-knopf{padding-top:calc(var(--gutter) - var(--burger-strich))}

/* Der Verweis im Kopf trägt keine ruhende Linie. PRAXIS daneben steht ohne,
   und ein Strich unter der Anschrift läse sich als Unterstreichung des
   Titels statt als Verweis. Beim Überfahren baut sie sich auf und bleibt.
   Übergang statt der Keyframes aus komponenten.css: die laufen gegen die
   ruhende Breite 0 an und fielen am Ende darauf zurück. */
.kopf h1 a{animation:none;background-size:0 var(--underline-weight);
  transition:background-size var(--underline-speed) cubic-bezier(.22,1,.36,1)}
.kopf h1 a:hover,.kopf h1 a:focus-visible,.kopf h1 a.is-hover{
  background-size:100% var(--underline-weight)}
@media (prefers-reduced-motion:reduce){.kopf h1 a{transition:none}}

/* PRAXIS führt auf allen Unterseiten zurück zur Startseite. Nur dort, wo
   man schon ist, ist es kein Verweis — dann steht es als Satz da. */
a.praxis{text-decoration:none;color:inherit;background-image:none;animation:none;
  /* Dieselbe Zeit wie beim Knopf: eine Handlung, eine Geschwindigkeit. */
  transition:color .25s}
/* Beim Überfahren nimmt das Wort zurück, statt sich zu färben: die Marke soll
   nicht plötzlich wie ein Verweis im Fließtext aussehen.

   Wie weit es zurücknimmt, sagt der Knopf: dessen Puck liegt als heller Wasch
   mit 10 % Deckung auf der Markenfläche, und das ergibt optisch L 0,233. Die
   Sprosse, die dort liegt, ist neutral-900 (L 0,221) — dieselbe Helligkeit,
   nur als Schriftfarbe statt als Fläche. Nicht fg-base-muted: das ist mit
   L 0,495 fast doppelt so hell und lässt die Marke ausgehen. */
a.praxis:hover,a.praxis.is-hover{color:var(--color-neutral-900)}
a.praxis:focus-visible{
  outline:var(--border-width-strong) solid var(--focus-ring);outline-offset:4px}

/* ---- Inhalt einer Unterseite ----
   Eine Spalte, eine Größe: die der Seite. Nur PRAXIS ist größer, sonst
   nichts — dieselbe Regel wie auf der Startseite. */
.inhalt{
  /* Unten derselbe Abstand wie oben zum Kopf: vier Zeilen. Eine Seite soll
     nicht mit der letzten Zeile an der Fensterkante enden — dort fehlt dem
     Auge der Boden, und man weiß nicht, ob noch etwas kommt. Nebenbei gibt
     es damit überall etwas zu scrollen, auch auf kurzen Seiten. */
  padding-bottom:calc(var(--fs-lead) * var(--lh-body) * 4);
  /* Der Abstand zum Kopf ist das Doppelte des Abstands zwischen zwei
     Blöcken — vier Zeilen gegen zwei. Damit steht eine Staffel: Zeile,
     Absatz (eine Zeile), Block (zwei), Kopf (vier). Gerechnet auf den
     Seitengrad, nicht auf den des ersten Blocks, sonst begänne eine Seite
     mit kleiner gesetztem Anfang auch enger unter dem Kopf. */
  margin-top:calc(var(--fs-lead) * var(--lh-body) * 4);
  /* Durchschuss aus dem System, ohne Zuschlag: hier steht Fließtext, keine
     Aufzählung kurzer Zeilen. */
  /* Fließtext, also die Laufweite des Fließtextes — nicht die des
     Displaygrads. Groß gesetzt sieht dieser Satz nach Display aus, gelesen
     wird er trotzdem Zeile für Zeile. */
  font-size:var(--fs-lead);line-height:var(--lh-body);
  letter-spacing:var(--tracking-lead, var(--tracking-display));
  /* Die Spalte ist in Zeichen gedeckelt, nicht in Pixeln: ch wächst mit dem
     Grad, also trägt eine Zeile immer dieselbe Zahl Zeichen — gleich wie groß
     das Fenster ist. Wörter pro Zeile und Durchschuss stehen damit in einem
     festen Verhältnis, und das ist das, was sich liest. */
  max-width:calc(var(--zeilenmass) * 1ch)}
/* p trägt in textstile.css seine eigene Größe und holte sie sich sonst
   zurück. Hier erbt alles den Grad der Seite. */
.inhalt p{font-size:inherit;line-height:inherit;letter-spacing:inherit;
  /* Ein Absatz muss sich vom nächsten absetzen, und zwar deutlicher als eine
     Zeile von der nächsten. Eine volle Zeile Abstand — der Durchschuss steckt
     schon in der Zeilenhöhe, dazu kommt hier noch einmal so viel. */
  margin:0 0 calc(var(--lh-body) * 1em);max-width:none}

/* ---- Abschnitte ----
   Ein Abschnitt setzt sich deutlicher ab als ein Absatz: zwei Zeilen statt
   einer. Gerechnet auf den SEITENGRAD, nicht auf den des Abschnitts — sonst
   bekäme die kleiner gesetzte Marginalie auch einen kleineren Abstand,
   obwohl sie im selben Raster steht. */
.inhalt .block{margin-bottom:calc(var(--fs-lead) * var(--lh-body) * 2)}
.inhalt .block > p:last-child{margin-bottom:0}
.inhalt .block:last-child{margin-bottom:0}

/* Der Knopf gehört zum Satz unmittelbar darüber — er ist dessen Fortsetzung,
   kein neuer Absatz. Also kein voller Absatzabstand dazwischen, aber auch
   nicht null: eine halbe Zeile. Er hängt am Satz, ohne ihn zu berühren. */
.inhalt p:has(+ p > .button){margin-bottom:calc(var(--lh-body) * .5em)}

/* ---- Die zwei Grade im Inhalt ----
   Der erste Absatz steht im großen Grad, alles danach eine Stufe kleiner.
   Das steht in der STRUKTUR, nicht in einer Klasse: der erste Absatz ist der
   erste Absatz, dafür braucht es keinen Namen. Wer die Reihenfolge ändert,
   ändert damit auch die Auszeichnung — genau das soll er.
   Wo eine Seite durchgehend eine Größe tragen soll (Impressum), steht das
   Attribut ein-grad am Inhalt. */
.inhalt > p,
.inhalt > .block > p{font-size:var(--fs-read);
  /* Laufweite ausdrücklich, nicht geerbt: sie vererbt ihren BERECHNETEN
     Pixelwert. Ein kleiner gesetzter Absatz bekäme sonst die Pixel des
     größeren und liefe zu eng. */
  letter-spacing:var(--tracking-read, var(--tracking-body));
  /* Die zweite Rasterachse: dort, wo im Kopf die Titelspalte neben der
     Wortmarke beginnt. Der Lesetext hängt sich darunter, Aufmacher und
     Überschriften bleiben links — so entsteht eine senkrechte Linie über
     die ganze Seite, ohne dass irgendwo eine Zahl steht. Gemessen wird sie
     im Kopf selbst (seite.js); bricht der Kopf um, ist sie null. */
  margin-left:var(--raster-achse, 0px);
  max-width:calc(var(--zeilenmass) * 1ch)}
/* Alles andere im Lesegrad steht in derselben Spalte: Listen, Tabellen,
   Zitate. Sonst risse die Linie beim ersten Aufzählungspunkt ab. */
.inhalt > ul,
.inhalt > ol,
.inhalt > table,
.inhalt > figure,
.inhalt > blockquote,
.inhalt > .block > ul,
.inhalt > .block > ol,
.inhalt > .block > table,
.inhalt > .block > figure,
.inhalt > .block > blockquote{margin-left:var(--raster-achse, 0px)}
/* Größer gesetzt heißt auch: enger gesetzt. Die Laufweite wird deshalb
   zusammen mit dem Grad umgestellt, nie allein. */
.inhalt > p:first-of-type,
.inhalt > .block:first-child > p{font-size:var(--fs-lead);
  letter-spacing:var(--tracking-lead, var(--tracking-display));
  /* Der Aufmacher steht links, nicht in der zweiten Spalte — er gehört zum
     Kopf der Seite, nicht zum Lesetext darunter. */
  margin-left:0}
/* Eine Seite, ein Grad: das Impressum wird nicht gelesen wie ein Aufmacher,
   sondern durchgesehen wie eine Liste von Angaben. Also durchgehend der
   Lesegrad — und damit auch durchgehend die Lesespalte. Kein Absatz fällt
   hier heraus, auch der erste nicht. */
.inhalt[data-ein-grad] > p,
.inhalt[data-ein-grad] > .block > p,
.inhalt[data-ein-grad] > p:first-of-type,
.inhalt[data-ein-grad] > .block:first-child > p{font-size:var(--fs-read);
  letter-spacing:var(--tracking-read, var(--tracking-body));
  margin-left:var(--raster-achse, 0px)}

/* ---- Randnotiz ----
   Ein aside ist eine Randnotiz — dafür gibt es ein Element, also braucht es
   keine Klasse. Eingerückt wie ein Zitat, mit demselben Einzug, den
   blockquote in textstile.css benutzt, und schmaler: eine eingerückte Spalte,
   die so weit läuft wie der Haupttext, ist keine Randnotiz mehr, sondern ein
   verschobener Absatz. */
/* Die Randnotiz steht selbst in der Lesespalte — sie bekommt die Achse
   einmal, und ihre Absätze dann nicht noch einmal. Sonst läge sie doppelt
   eingerückt. */
.inhalt aside{margin-left:calc(var(--raster-achse, 0px) + var(--quote-indent));
  max-width:calc(var(--zeilenmass) * .66 * 1ch)}
/* Spezifisch genug, um die Regel der Lesespalte zu schlagen: sonst zählt
   dort .inhalt > .block > p und die Achse käme ein zweites Mal dazu. */
.inhalt aside > p,
.inhalt aside.block > p,
.inhalt aside > p > .button{max-width:none;margin-left:0}

/* Der Knopf bringt aus komponenten.css den Fließtextgrad mit. Auf einer
   Seite, die in einer Größe gesetzt ist, wäre er der einzige Ausreißer. */
.inhalt .button{font-size:inherit}

/* Schmale Schirme: PRAXIS nimmt dann fast die ganze Zeile, und das Zeichen
   steht ihm im Weg — seine Striche laufen optisch durch das Wort. Also rückt
   der Kopf darunter statt daneben. Der Wert ist die Höhe des Zeichens plus
   sein eigenes Polster, nicht geschätzt. */
@media (max-width:44rem){
  /* Kein Anschnitt: ein Streifen, der ein Drittel des Schirms schwarz färbt,
     ist kein Hinweis mehr, sondern ein Hindernis. Das Menü liegt dann ganz
     außerhalb, das Zeichen steht auf der Seite. */
  :root{
    --menue-anschnitt:0px;
    /* PRAXIS steht auf einer Zeile mit dem Zeichen und darf dafür unter
       seinen Grad: was nach Abzug des Zeichens und dreier Gutter von der
       Fensterbreite übrig bleibt, geteilt durch die zur Laufzeit gemessene
       Laufweite des Wortes in Em. Das Zeichen bleibt bei --fs-mark und
       schrumpft nicht mit. */
    --praxis-eng:min(var(--fs-mark),
      calc((100vw - var(--gutter) * 3 - var(--burger-breite))
           / var(--praxis-breite, 3.43)));
  }
  body{padding-right:var(--gutter)}
  /* Der Kopf hält rechts das Zeichen frei, statt darunter zu beginnen. */
  .kopf{padding-right:calc(var(--burger-breite) + var(--gutter) * 2)}
}
