/*
  out-of-the-box-thinking.net

  Eine Visitenkarte im Wortsinn: Wortmarke, zwei Wege, sonst nichts. Der
  Charakter der alten Seite bleibt - viel Weissraum, die Marke in der Mitte,
  eine Zeile Navigation, Georgia als Serifenschrift. Ersetzt ist nur die
  Technik darunter: Flex statt absoluter Positionierung und Layouttabelle,
  Groessen am Viewport statt fester Pixel.

  Kein Webfont, kein CDN, kein Analytics. Georgia liegt auf Windows und macOS,
  darunter greift die Kette bis zu einer beliebigen Serifenschrift durch. Das
  ist der Grund, warum diese Seite ohne Einwilligungsbanner auskommt: es gibt
  nichts einzuwilligen.

  Hell und dunkel liegen allein an prefers-color-scheme. Kein Umschalter,
  also auch kein Skript - und damit bleibt das Impressum erreichbar, egal was
  der Browser mit JavaScript macht.

  ---

  Die Seite nimmt sich die Flaeche, die sie bekommt. Es gibt genau eine
  Schraube: den Schriftgrad am Viewport. Alles andere - Zeilenabstaende,
  Ueberschriften, die Breite der Textspalte, der Briefkopf - haengt in `em`
  daran und waechst mit. Auf 360 px sind das 16 px, auf 1280 px knapp 17 px,
  auf 4K 30 px.

  Die Textspalte steht deshalb auf `34em` und nicht auf einer Pixelzahl: die
  Zeilenlaenge bleibt bei rund 70 Zeichen, die Spalte wird auf einem grossen
  Schirm trotzdem breiter statt als Handystreifen in der Mitte zu kleben.

  Die Wortmarke auf der Startseite ist der einzige Wert am Viewport statt an
  der Schrift - dort steht sonst nichts, was ihr Mass geben koennte. Sie ist
  ein Vektor, gross werden kostet sie nichts.
*/

:root {
  color-scheme: light dark;

  --grund: #ffffff;
  --tinte: #16181c;
  --leise: #5a5d66;
  --blau: #2b387d;
  --linie: #e4e4e1;

  /* Nur fuer die Wortmarke: die Fuellung des Kastens und seine Kontur.
     Dieselben Werte stehen noch einmal in out-of-the-box-thinking.svg - die
     Datei ist die eigenstaendige Fassung der Marke und sieht dieses
     Stylesheet nicht. Auf den Seiten selbst steht die Marke ausgeschrieben
     im HTML und faerbt sich von hier; nur so folgt sie dem Schalter. */
  --marke-kasten: #eeeeee;
  --marke-linie: #686868;

  --schrift: Georgia, "Iowan Old Style", "Palatino Linotype", Palatino,
    "Times New Roman", Times, serif;

  --luft: clamp(1.5rem, 4vw, 8rem);

  --ist-dunkel: 0;
}

/*
  Dunkel gibt es auf zwei Wegen, und beide muessen zum selben Ergebnis
  fuehren: die Voreinstellung des Systems und die ausdrueckliche Wahl am
  Schalter. Deshalb stehen die Werte zweimal da - einmal hinter der
  Media-Query, aber nur solange niemand ausdruecklich "hell" gewaehlt hat,
  einmal hinter dem Attribut, das der Schalter setzt.

  --ist-dunkel ist die Auskunft fuer das Skript: es liest den Wert, statt die
  Media-Query ein zweites Mal in JavaScript nachzubauen. So gibt es nur eine
  Wahrheit, und der Ausgangszustand "wie das System es will" bleibt erhalten,
  bis jemand ausdruecklich waehlt.
*/
@media (prefers-color-scheme: dark) {
  :root:not([data-thema="hell"]) {
    --ist-dunkel: 1;

    --grund: #0e121d;
    --tinte: #eceef2;
    --leise: #9aa0ad;
    /* #2b387d traegt auf dunklem Grund nicht mehr - aufgehellt auf 7,8:1. */
    --blau: #97a4e8;
    --linie: #262b3a;

    --marke-kasten: #1d212b;
    --marke-linie: #4a5060;
  }
}

:root[data-thema="dunkel"] {
  --ist-dunkel: 1;

  --grund: #0e121d;
  --tinte: #eceef2;
  --leise: #9aa0ad;
  --blau: #97a4e8;
  --linie: #262b3a;

  --marke-kasten: #1d212b;
  --marke-linie: #4a5060;
}

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

html {
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  padding: var(--luft);
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  align-items: center;

  background: var(--grund);
  color: var(--tinte);
  font-family: var(--schrift);
  /* die eine Schraube: 16px auf dem Telefon, 30px auf 4K */
  font-size: clamp(1rem, 0.65rem + 0.5vw, 1.875rem);
  line-height: 1.65;

  /* info@out-of-the-box-thinking.net passt auf einem schmalen Telefon nicht in
     eine Zeile. Browser brechen zwar nach Bindestrichen um, aber nicht vor dem
     @ - ohne das hier steht die Adresse auf 360 px ueber dem Rand. */
  overflow-wrap: break-word;
}

/* Die Startseite steht mittig, die Textseiten beginnen oben. */
body.start {
  justify-content: center;
  text-align: center;
}

a {
  color: var(--blau);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.15em;
}

:focus-visible {
  outline: 2px solid var(--blau);
  outline-offset: 3px;
  border-radius: 1px;
}

/* ----------------------------------------------------------- Wortmarke */

/* Volle Breite, damit `100%` am Bild darunter eine echte Zahl meint. Ohne das
   ist die Marke als Flex-Element nur so breit wie ihr Inhalt - und `max-width:
   100%` am Bild bezoege sich auf das Bild selbst. Der Browser loest den Zirkel
   mit der Eigenbreite auf, und der Briefkopf klebte bei 439px fest. */
.marke {
  display: block;
  width: 100%;
  line-height: 0;
}

/* Auf der Startseite ist die Wortmarke die Ueberschrift - sie traegt den
   Namen der Seite, deshalb steht der Text im alt-Attribut und nicht daneben.

   font-size zurueck auf den Fliesstext: sonst erbt das Bild die 1.9em der
   Ueberschrift, und die `em` in seiner Breite rechnen mit dem falschen Mass. */
h1.marke {
  margin: 0;
  font-size: inherit;
}

.marke-bild {
  display: block;
  margin-inline: auto;
  aspect-ratio: 439 / 131;
  /* 32vw haelt auf jedem Schirm dasselbe Verhaeltnis wie frueher 439px auf
     1280px, gedeckelt bei 1200px. Die 26em davor sind kein Schoenheitsmass,
     sondern eine Reihenfolge: zwischen etwa 700 und 1000 px faellt 32vw unter
     den Briefkopf der Textseiten (22em) - die Marke auf der Startseite waere
     dann kleiner als die auf den Unterseiten. max() haelt sie darueber.
     Nach unten faengt max-width das Telefon ab.

     clamp und nicht max(): bei clamp gewinnt der Deckel gegen die Untergrenze,
     bei max() haette 26em ihn auf 4K ueberrannt. */
  width: clamp(26em, 32vw, 1200px);
  max-width: 100%;
  height: auto;
}

/* Auf den Textseiten fuehrt die Ueberschrift, die Marke wird zum Briefkopf -
   deshalb haengt sie hier an der Schrift und nicht am Viewport. */
.marke-klein .marke-bild {
  width: 22em;
}

/* Farben der eingebetteten Wortmarke. Auf den Unterseiten steht dieselbe
   Zuordnung im SVG selbst. */
.marke-bild .kasten {
  fill: var(--marke-kasten);
  stroke: var(--marke-linie);
  stroke-width: 2;
}

/* Der Kasten ist hier ein volles Rechteck; die abgeschnittene Ecke entsteht
   aus einer Deckflaeche in der Farbe des Seitengrunds und der Diagonalen
   darauf. Nur so laesst sie sich am Ende herauswachsen - der Umriss eines
   Pfades ist in reinem CSS nicht ueberall animierbar. */
.marke-bild .ecke {
  fill: var(--grund);
}

/* Dieselbe Strichstaerke wie der Kastenrand, und zwar in Einheiten der
   viewBox - nicht in Geraetepixeln. `non-scaling-stroke` waere hier falsch:
   der Rand des Kastens waechst mit der Anzeigegroesse mit, die Diagonale
   bliebe stehen, und auf 1200 px stuenden 5,5 px gegen 2 px. */
.marke-bild .falz {
  fill: none;
  stroke: var(--marke-linie);
  stroke-width: 2;
  /* Die Enden stossen stumpf auf die Mitte der senkrechten und der
     waagerechten Kante. Ohne Verlaengerung bliebe aussen je eine winzige
     Kerbe stehen; die quadratische Kappe legt genau die halbe Strichstaerke
     zu und schliesst sie. Im ruhenden SVG stellt sich die Frage nicht, dort
     ist der Kasten ein einziger Umriss. */
  stroke-linecap: square;
}

.marke-bild .blau {
  fill: var(--blau);
}

.marke-bild .tinte {
  fill: var(--tinte);
}

.marke-bild .leise {
  fill: var(--leise);
}

/*
  Der Einlauf. Die Buchstaben blenden von links nach rechts auf, versetzt nach
  ihrer linken Kante - so kommen i-Punkt und Stamm gemeinsam. Nach knapp einer
  Sekunde steht alles still. Der Kasten bleibt unberuehrt: er ist zuerst da,
  die Schrift kommt hinein.

  Die Verschiebung greift am Pfad, dessen Huelle die Position traegt. Stuende
  beides am selben Element, ersetzte die CSS-Transformation das
  transform-Attribut und der Buchstabe spraenge in die linke obere Ecke.

  Ohne die Media-Query entsteht gar keine Regel - wer "Bewegung reduzieren"
  gesetzt hat, bekommt die fertige Marke sofort und vollstaendig.
*/
@media (prefers-reduced-motion: no-preference) {
  .marke-bild .e {
    animation: einlauf var(--d, 0.26s) ease-out backwards;
    animation-delay: var(--t, 0s);
  }

  @keyframes einlauf {
    from {
      opacity: 0;
      transform: translateY(2px);
    }
  }

  /* Zuletzt schneidet sich die Ecke heraus: Deckflaeche und Diagonale wachsen
     aus dem Eckpunkt des Kastens. Der Bezug ist die viewBox und nicht die
     eigene Flaeche, weil beide denselben Punkt brauchen - er liegt auf der
     Diagonalen nicht drauf. */
  .marke-bild .ecke,
  .marke-bild .falz {
    transform-box: view-box;
    transform-origin: 439px 131px;
    animation: eckeschneiden 0.34s cubic-bezier(0.4, 0, 0.2, 1) 1s backwards;
  }

  @keyframes eckeschneiden {
    from {
      transform: scale(0);
    }
  }
}

/* --------------------------------------------------------------- Wege */

.wege {
  margin-top: 2em;
  font-size: 0.92em;
  color: var(--leise);
}

.wege a {
  text-decoration: none;
}

.wege a:hover,
.wege a:focus-visible {
  text-decoration: underline;
}

.wege .punkt {
  margin: 0 0.75em;
}

/* --------------------------------------------------------------- Blatt */

.blatt {
  width: 100%;
  /* in em, damit die Zeilenlaenge steht und die Spalte trotzdem mitwaechst */
  max-width: 34em;
  margin-top: 3em;
}

/*
  Ab einer gewissen Breite hilft ein groesserer Schriftgrad nicht mehr: eine
  einzelne Spalte mitten in einem 4K-Schirm bleibt eine Handy-Spalte, nur
  groesser, und die Datenschutzseite wird entsprechend lang. Deshalb bricht
  der Text ab hier in Spalten um. Die Zeilenlaenge bleibt dabei stehen - die
  Breite des Blattes ist so gewaehlt, dass jede Spalte wieder auf 34em
  herauskommt: zwei Spalten plus eine Rinne sind 72em, drei plus zwei sind
  110em.

  Die Grenzen stehen in Pixeln und nicht in em, weil sie eine Aussage ueber
  den Schirm treffen und nicht ueber die Schrift.
*/
@media (min-width: 1500px) {
  .blatt {
    max-width: 72em;
  }

  .felder {
    columns: 2;
    column-gap: 4em;
  }
}

@media (min-width: 2800px) {
  .blatt {
    max-width: 110em;
  }

  .felder {
    columns: 3;
  }
}

/* Ein Abschnitt wird nicht auseinandergerissen. Der Abstand sitzt unten und
   nicht oben an der Ueberschrift - sonst begaenne jede Spalte mit einer
   Leerzeile. */
.feld {
  margin-bottom: 2.2em;
  break-inside: avoid;
}

.feld > :first-child {
  margin-top: 0;
}

.feld > :last-child {
  margin-bottom: 0;
}

h1 {
  margin: 0 0 0.9em;
  font-size: 1.9em;
  font-weight: normal;
  letter-spacing: 0.01em;
  line-height: 1.25;
}

h2 {
  margin: 2.2em 0 0.5em;
  font-size: 0.95em;
  font-weight: normal;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--leise);
}

h2 + p,
h2 + address,
h2 + ul {
  margin-top: 0;
}

p {
  margin: 0 0 1em;
}

address {
  font-style: normal;
  margin: 0 0 1em;
}

ul {
  margin: 0 0 1em;
  padding-left: 1.2em;
}

li {
  margin-bottom: 0.35em;
}

.klein {
  font-size: 0.9em;
  color: var(--leise);
}

code {
  font-family: ui-monospace, "Cascadia Mono", Consolas, "DejaVu Sans Mono", monospace;
  font-size: 0.875em;
}

/* Die Zeile unter dem Text: zurueck und quer zur Schwesterseite. */
.fuss {
  margin-top: 4em;
  padding-top: 1.4em;
  border-top: 1px solid var(--linie);
  font-size: 0.92em;
}

.fuss a {
  text-decoration: none;
}

.fuss a:hover,
.fuss a:focus-visible {
  text-decoration: underline;
}

.fuss .punkt {
  margin: 0 0.75em;
  color: var(--leise);
}

/* ------------------------------------------------------------ Schalter */

/*
  Hell und dunkel folgen ohne Zutun der Systemeinstellung. Der Schalter ist
  Zugabe: er steht als hidden im Markup und wird erst vom Skript freigegeben.
  Ohne JavaScript ist er also nicht bloss wirkungslos, sondern gar nicht da -
  und die Seite bleibt vollstaendig, das Impressum eingeschlossen.

  Welche Beschriftung gilt, entscheidet das Stylesheet ueber --ist-dunkel,
  nicht das Skript.
*/
/* Sieht aus wie die Wege daneben und verhaelt sich auch so - nur dass es kein
   Weg ist, sondern eine Handlung. Deshalb bleibt es ein button: mit Tastatur
   erreichbar, von Vorleseprogrammen als Schalter angesagt. Der Rahmen, den
   ein Browser dafuer mitbringt, faellt weg. */
.thema {
  padding: 0;
  border: 0;
  background: none;
  color: var(--blau);
  font: inherit;
  cursor: pointer;
}

.thema:hover,
.thema:focus-visible {
  text-decoration: underline;
}

.thema-nach-hell {
  display: none;
}

:root[data-thema="dunkel"] .thema-nach-dunkel {
  display: none;
}

:root[data-thema="dunkel"] .thema-nach-hell {
  display: inline;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-thema="hell"]) .thema-nach-dunkel {
    display: none;
  }

  :root:not([data-thema="hell"]) .thema-nach-hell {
    display: inline;
  }
}
