/* kontor.css — Aussehen und Layout.
 *
 * Typografie streng: alles 12 pt in einer Größe, Zeilenabstand 12 pt,
 * keine Hierarchien. Unterschieden wird nur durch Unterstreichen und
 * durch Abstufen auf 33 % Schwarz.
 */

/* ------------------------------------------------------------ Schriften */

@font-face {
  font-family: "WT Saltburn";
  src: url("/static/schrift/WTSaltburn-Regular.otf") format("opentype");
  font-weight: normal;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "WT Garamono";
  src: url("/static/schrift/WTGaramono-Italic.otf") format("opentype");
  font-weight: normal;
  font-style: italic;
  font-display: swap;
}

/* ---------------------------------------------------------------- Werte */

:root {
  --schrift: "WT Saltburn", system-ui, sans-serif;
  --schrift-kursiv: "WT Garamono", Georgia, serif;

  --groesse: 12pt;
  --zeile: 12pt;            /* Zeilenabstand = Schriftgröße */
  --leerzeile: 12pt;        /* eine Leerzeile */
  --menueabstand: 36pt;     /* drei Leerzeilen */

  --schwarz: #000;
  --grau: rgba(0, 0, 0, 0.33);   /* 33 % Schwarz */
  --haarlinie: rgba(0, 0, 0, 0.33);
  --papier: #fff;

  --spalte-links: 360px;    /* Breite der Nabe-Spalte */
  --nabe-radius: 10mm;      /* Abstand Speichentext zum Mittelpunkt */
  --logo-groesse: 8mm;      /* Bildkasten; die sichtbare Marke füllt davon
                               52,8 % der Höhe und steht damit auf 12 pt */
  --rand: 24pt;
}

/* ------------------------------------------------------------- Grundlage */

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

html, body {
  margin: 0;
  padding: 0;
  /* Kein Nachfedern am Rand: die Shell füllt den Schirm, es gibt nichts
     zu scrollen. Gescrollt wird nur im Fenster. */
  overscroll-behavior: none;
  background: var(--papier);
  color: var(--schwarz);
}

body,
input, button, select, textarea {
  font-family: var(--schrift);
  font-size: var(--groesse);
  line-height: var(--zeile);
  font-weight: normal;
  font-style: normal;
}

/* Keine Größenabstufung, kein Fett — auch nicht durch Vorgaben des Browsers. */
h1, h2, h3, h4, h5, h6, strong, b, th {
  font-size: inherit;
  font-weight: inherit;
  margin: 0;
}

p, ul, ol { margin: 0; }
ul, ol { padding: 0; list-style: none; }

a { color: inherit; text-decoration: underline; text-underline-offset: 0.18em; }

.grau { color: var(--grau); }

/* Die dritte Auszeichnung neben Unterstreichen und 33 % Schwarz:
   Durchgestrichenes ist erledigt. */
.durchgestrichen,
.name.durchgestrichen { text-decoration: line-through; }

/* Vorlagen unter "weiter an:" — je Zeile eine, ohne Unterstreichung
   (sie tragen Projektnamen mit Unterstrichen). */
.vorlage { display: block; text-decoration: none; }
.vorlage + .vorlage { margin-top: var(--leerzeile); }

/* Ein Name, der selbst Unterstriche trägt (04_Wohnhaus an der Lahn),
   bekommt keine zweite Unterstreichung — die beiden stoßen sich.
   Als Knopf legt er alles ab, was ein Knopf sonst mitbringt. */
.name {
  appearance: none;
  border: 0;
  background: transparent;
  padding: 0;
  font: inherit;
  color: inherit;
  text-align: left;
  text-decoration: none;
  cursor: pointer;
}
.unterstrichen { text-decoration: underline; text-underline-offset: 0.18em; }

/* ----------------------------------------------------------------- Shell */

.shell {
  display: grid;
  grid-template-columns: var(--spalte-links) 1fr;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    "kopf  arbeitsraum"
    "nabe  arbeitsraum"
    "fuss  arbeitsraum";
  height: 100vh;
  height: 100dvh;
}

.kopf {
  grid-area: kopf;
  padding: var(--rand);
  padding-top: calc(var(--rand) + env(safe-area-inset-top));
}

/* Am Home-Bildschirm-Start liegt unten der Home-Streifen: der Fuß rückt
   darüber, sonst klebte die Uhr daran. */
.fuss {
  grid-area: fuss;
  padding: var(--rand);
  padding-bottom: calc(var(--rand) + env(safe-area-inset-bottom));
}
/* Über dem Rad gehört die senkrechte Wischgeste dem Rad, nicht der
   Seite — sonst scrollt Safari, statt zu drehen. */
.nabe {
  grid-area: nabe;
  position: relative;
  touch-action: none;
}
.arbeitsraum {
  grid-area: arbeitsraum;
  padding: var(--rand);
  overflow: auto;
}

/* Wortmarke: "build" in Saltburn, "Bild" und "Kontor" in Garamono-Italic,
   "Kontor" auf 33 % Schwarz. */
.wortmarke { display: inline-block; text-decoration: none; }
.wort-build  { font-family: var(--schrift); }
.wort-bild   { font-family: var(--schrift-kursiv); font-style: italic; }
.wort-kontor { font-family: var(--schrift-kursiv); font-style: italic; color: var(--grau); }

.uhr { color: var(--schwarz); }
.uhr span { display: block; }

/* Läuft eine Erfassung, steht es hier — eine Zeile über der Uhr,
   im selben Zeilenmaß, ohne Extraabstand. */
.stand { margin: 0 0 var(--leerzeile) 0; color: var(--grau); }
/* Ohne Unterstreichung: die Zeile ist eine Auskunft, keine Aufforderung.
   Anklickbar bleibt sie trotzdem — sie öffnet die Zeiterfassung. */
.stand a { color: var(--grau); text-decoration: none; }
.stand:empty { display: none; }

/* Uhr links, abmelden rechts daneben — auf der Höhe des Datums, also
   der letzten Zeile. */
.fusszeile {
  display: flex;
  align-items: flex-end;
  gap: var(--menueabstand);
}

.abmelden { margin: 0; }

/* ------------------------------------------------------------ Anmeldung */

/* Eine Seite, keine Shell: nur die Wortmarke und das Nötige. */
.anmeldung {
  padding: var(--rand);
  max-width: 60ch;
}

.anmeldung .wortmarke { display: block; margin-bottom: var(--menueabstand); }

input[type="password"] {
  appearance: none;
  border: 0;
  border-bottom: 1px solid var(--haarlinie);
  border-radius: 0;
  background: transparent;
  color: var(--schwarz);
  padding: 0 0 2pt 0;
  line-height: var(--zeile);
  flex: 1 1 20ch;
}

input[type="password"]:focus { outline: none; border-bottom-color: var(--schwarz); }

/* ------------------------------------------------------------------- Rad */

/* Das Rad dreht sich; nur die aktive Speiche steht am horizontal
   lesbaren Punkt (rechts, zum Arbeitsraum hin). */
.rad {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 0;
  height: 0;
  transform: rotate(var(--drehung, 0deg));
  transition: transform 0.45s cubic-bezier(0.22, 0.61, 0.36, 1);
}

.speiche {
  position: absolute;
  left: 0;
  top: 0;
  margin-top: calc(var(--zeile) / -2);   /* Textmitte auf den Mittelpunkt */
  transform-origin: 0 50%;               /* Drehpunkt = Radmitte */
  transform: rotate(calc(var(--i) * 45deg)) translateX(var(--nabe-radius));
}

.speiche-text {
  display: block;
  white-space: nowrap;
  text-decoration: none;
  color: var(--grau);
  line-height: var(--zeile);
}

.speiche--aktiv .speiche-text {
  color: var(--schwarz);
  text-decoration: underline;
}

.speiche-text:focus-visible { outline: 1px solid var(--haarlinie); outline-offset: 2px; }

.nabe-logo {
  position: absolute;
  left: 50%;
  top: 50%;
  display: block;
  width: var(--logo-groesse);
  height: var(--logo-groesse);
  transform: translate(-50%, -50%);
  user-select: none;
  cursor: pointer;
}

.nabe-logo img { display: block; width: 100%; height: 100%; }

@media (prefers-reduced-motion: reduce) {
  .rad { transition: none; }
}

/* --------------------------------------------------------------- Fenster */

/* Ein Ding zur Zeit: das native <dialog>, aber nicht modal und nicht über
   der Shell — es sitzt in der rechten Hälfte, das Rad bleibt bedienbar. */
.fenster {
  display: none;
  position: fixed;
  left: 50%;
  right: var(--rand);
  top: var(--rand);
  bottom: var(--rand);
  width: auto;
  height: auto;
  max-width: none;
  max-height: none;
  margin: 0;
  padding: 0;
  border: 1px solid rgba(0, 0, 0, 0.22);
  border-radius: 8px;
  background: var(--papier);
  color: var(--schwarz);
  /* Am Rechner liegt das Fenster über der Fläche — wie bei macOS.
     Am Telefon füllt es die halbe Höhe und liegt nicht über etwas;
     dort fällt der Schatten weg (siehe unten). */
  box-shadow: 0 12px 48px rgba(0, 0, 0, 0.20);
  overflow: hidden;
}

.fenster[open] { display: flex; flex-direction: column; }

/* Bezugsmaß für die Vorschau der Anhänge: 1cqw = ein Hundertstel der
   Fensterbreite. */
.fenster { container-type: inline-size; }

/* Breit gestellt (grüner Knopf): über die ganze Fläche. */
.fenster.breit { left: var(--rand); }

/* Eingeklappt (gelber Knopf): nur die Titelleiste. */
.fenster.eingeklappt { bottom: auto; }
.fenster.eingeklappt .fenster-inhalt { display: none; }

.fenster-rahmen {
  display: flex;
  flex-direction: column;
  min-height: 0;
  flex: 1 1 auto;
}

/* Titelleiste bleibt stehen: Ampel links, Titel mittig. */
.fenster-titel {
  position: relative;
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  padding: 8pt var(--leerzeile);
  background: #ececec;
  border-bottom: 1px solid rgba(0, 0, 0, 0.18);
}

.fenster-name {
  position: absolute;
  left: 0;
  right: 0;
  text-align: center;
  pointer-events: none;
}

.ampel { display: flex; gap: 6px; }

.ampel button {
  appearance: none;
  width: 12px;
  height: 12px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  cursor: pointer;
}

.ampel-rot   { background: #ff5f57; }
.ampel-gelb  { background: #febc2e; }
.ampel-gruen { background: #28c840; }

/* ... der Inhalt scrollt, sobald er höher ist als das Fenster. */
.fenster-inhalt {
  flex: 1 1 auto;
  min-height: 0;
  overflow: auto;
  padding: var(--menueabstand);
  padding-bottom: calc(var(--menueabstand) + env(safe-area-inset-bottom));
}

.fenster-inhalt p + p { margin-top: var(--leerzeile); }

/* -------------------------------------------------------------- Formular */

/* Drei Leerzeilen zwischen den Zeilen, eine innerhalb einer Zeile —
   dieselbe Logik wie im Menü. */
.reihe {
  display: grid;
  grid-template-columns: max-content 1fr;
  column-gap: var(--menueabstand);
  row-gap: var(--leerzeile);
  align-items: baseline;
}

/* Drei Leerzeilen zwischen den Zeilen — auch über eine Formulargrenze
   hinweg (die Anhänge stehen außerhalb des großen Formulars).
   Mit ~ statt +: ein verstecktes Feld zwischen zwei Zeilen darf den
   Abstand nicht aufheben. */
.reihe ~ .reihe,
.formular + .reihe,
.reihe ~ .formular { margin-top: var(--menueabstand); }

.marke { white-space: nowrap; }

/* Der Wert steht rechts am Rand — wie im Mockup. */
.wert {
  text-align: right;
  min-width: 0;
}

/* Mehrzeiliges behält seine Umbrüche — Anzeige wie Wert. */
.mehrzeilig { white-space: pre-line; }

/* Das Tuwort: grau und unterstrichen. Was gerade nicht geht, ruht:
   grau ohne Unterstreichung, also ohne Aufforderung zum Klicken. */
.tun {
  appearance: none;
  border: 0;
  background: transparent;
  padding: 0;
  font: inherit;
  color: var(--grau);
  text-decoration: underline;
  text-underline-offset: 0.18em;
  cursor: pointer;
}

.tun + .tun { margin-left: var(--menueabstand); }

.tun.ruht {
  text-decoration: none;
  cursor: default;
}

/* Zugeklappt ist zugeklappt: eine eigene display-Regel würde das
   hidden-Attribut des Browsers sonst überstimmen. */
[hidden] { display: none !important; }

/* Das aufgeklappte Eingabefeld klappt über die ganze Zeilenbreite auf,
   unter Bezeichnung und Wert — sonst bliebe ihm nur die halbe Spalte. */
.eingabe {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  align-items: baseline;
  gap: var(--leerzeile);
  text-align: left;
}

/* Ein Formular in der Eingabe ordnet sich genauso. */
.eingabe form {
  flex: 1 1 100%;
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  align-items: baseline;
  gap: var(--leerzeile);
}

/* Eingaben tragen nur eine Haarlinie — kein Kasten, keine Rundung. */
input[type="text"],
input[type="search"],
textarea,
select {
  appearance: none;
  border: 0;
  border-bottom: 1px solid var(--haarlinie);
  border-radius: 0;
  background: transparent;
  color: var(--schwarz);
  padding: 0 0 2pt 0;
  line-height: var(--zeile);
  text-align: left;
}

input[type="text"], input[type="search"] { flex: 1 1 20ch; }
textarea { flex: 1 1 100%; resize: none; overflow: hidden; }
select { flex: 0 1 auto; min-width: 20ch; }

input[type="text"]:focus,
input[type="search"]:focus,
textarea:focus,
select:focus { outline: none; border-bottom-color: var(--schwarz); }

.kaestchen { flex: 1 1 100%; display: flex; flex-wrap: wrap; gap: var(--leerzeile); justify-content: flex-end; }
.kaestchen label { display: inline-flex; align-items: baseline; gap: 4pt; }

/* Anhänge: Dateiname, dann die Vorschau darunter — beides rechtsbündig.
   Kein Symbol; welche Datei es ist, sagt der Name. */
.anhang { display: block; }
.anhang + .anhang { margin-top: var(--leerzeile); }
.anhang a { color: var(--grau); }

/* Die Vorschau misst immer ein Drittel der Fensterbreite: liegende
   Dateien in der Breite, stehende in der Höhe. Welche Lage eine Datei
   hat, trägt vorschau.js ein. */
.vorschau {
  display: block;
  margin: var(--leerzeile) 0 0 auto;
}

/* Ohne JavaScript: beide Maße begrenzen, dann stößt das längere zuerst an. */
img.vorschau { max-width: 33.333cqw; max-height: 33.333cqw; width: auto; height: auto; }

img.vorschau.liegend {
  width: 33.333cqw;
  height: auto;
  max-width: none;
  max-height: none;
}

img.vorschau.stehend {
  height: 33.333cqw;
  width: auto;
  max-width: none;
  max-height: none;
}

/* PDF im A4-Verhältnis, in der Lage, die beim Ablegen aus der Datei
   gelesen wurde. */
object.vorschau { border: 1px solid var(--haarlinie); }

object.vorschau.stehend {
  height: 33.333cqw;
  width: calc(33.333cqw / 1.414);
}

object.vorschau.liegend {
  width: 33.333cqw;
  height: calc(33.333cqw / 1.414);
}

/* Wird etwas über den Zettel gezogen, zeigt eine Haarlinie, dass er es
   nimmt — kein Kasten, kein Symbol. */
.fenster-inhalt.nimmt-dateien {
  outline: 1px solid var(--schwarz);
  outline-offset: calc(-1 * var(--leerzeile));
}

/* Der Dateiwähler ist ein Systemelement — er bekommt nur die Zeile. */
.eingabe input[type="file"] { flex: 1 1 100%; line-height: var(--zeile); }

/* Eine Liste: die Zeilen gehören zusammen, also eine Leerzeile
   dazwischen statt drei. */
.liste .reihe ~ .reihe { margin-top: var(--leerzeile); }

/* Trägt die Bezeichnung den Inhalt (ein Titel, ein Projektname), bekommt
   sie zwei Drittel der Breite: sie darf umbrechen, aber nicht die rechte
   Spalte aufzehren. Wo der Inhalt rechts steht, bleibt die Zeile
   inhaltsgetrieben. */
.namensliste .reihe { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); }

/* Umgekehrt: steht der Inhalt rechts, bekommt er die zwei Drittel. */
.breitliste .reihe { grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); }

/* Ein langer Titel bricht in sich um; der Griff daneben bleibt auf der
   ersten Zeile stehen, statt allein in die nächste zu rutschen. */
.namensliste .marke {
  display: flex;
  flex-wrap: nowrap;
  align-items: baseline;
  gap: var(--leerzeile);
  white-space: normal;
}

.namensliste .marke > .name { min-width: 0; }
.namensliste .marke > .tun { flex: none; }

/* Beiwerk: Feld und Projekt unter einer Listenzeile — sie gehören zur
   Zeile darüber, stehen also direkt darunter. */
.liste .reihe.beiwerk { margin-top: 0; }
.reihe ~ .liste, .liste ~ .reihe { margin-top: var(--menueabstand); }

/* Eine Liste, die zur Zeile darüber gehört, rückt nur eine Leerzeile
   nach — Überschrift und Posten bleiben zusammen. */
.reihe ~ .liste.angehaengt { margin-top: var(--leerzeile); }

/* Eine enge Trennung: eine Leerzeile darüber und darunter statt drei.
   Muss nach der allgemeinen Abstandsregel stehen, sonst gewönne die. */
.reihe.eng { margin-top: var(--leerzeile); }
.reihe.eng + .reihe,
.reihe.eng + .formular { margin-top: var(--leerzeile); }

/* Die Vorlagen unter "weiter an" stehen untereinander, rechtsbündig. */
.vorlagen { flex: 1 1 100%; text-align: right; }

/* Umschalter: das Gewählte schwarz, die übrigen auf 33 % — wie am Rad.
   Eine Leerzeile Abstand (nicht drei): die Wörter gehören zusammen. Und
   umbrechen statt überlaufen — rechtsbündiger Inhalt, der zu breit wird,
   liefe sonst nach links über die Bezeichnung. */
.wahl {
  display: flex;
  flex-wrap: wrap;
  gap: var(--leerzeile);
  justify-content: flex-end;
}
.wahl a { color: var(--grau); }
.wahl a.gewaehlt { color: var(--schwarz); }
.wahl.ganz { grid-column: 1 / -1; }

/* Das erste Wort rückt nach links, dorthin, wo sonst die Bezeichnung
   steht — die übrigen bleiben rechts. Links eines, rechts der Rest:
   dasselbe Gefälle wie in jeder anderen Zeile. */
.wahl.ganz > :first-child { margin-right: auto; }

/* -------------------------------------------------------------- Kalender */

/* Acht Spalten — KW und Mo bis So. Nur Anordnung, keine zweite
   Formensprache: gleiche Schrift, gleiches Maß, gleicher Zeilenabstand. */
/* Das Raster hebt sich von selbst ab — es braucht keinen Strich davor
   oder dahinter, nur den üblichen Abstand. */
.reihe ~ .kalender { margin-top: var(--menueabstand); }
.kalender ~ .reihe,
.kalender ~ .liste { margin-top: var(--menueabstand); }

.kalender {
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  row-gap: var(--leerzeile);
  text-align: right;
}

.kalender .kw,
.kalender .wochentag { color: var(--grau); }

/* Ein Tag ohne Fälligkeit steht zurück, einer mit etwas tritt hervor,
   heute ist unterstrichen. */
.kalender .tag { color: var(--grau); }
.kalender .tag.faellig { color: var(--schwarz); }
.kalender .tag.heute { text-decoration: underline; text-underline-offset: 0.18em; }

/* ------------------------------------------------------------- Schmal */

/* Unter ~820 px: das Rad bleibt das Rad — es ist die Gestalt des
   Werkzeugs und fällt nicht weg, nur weil der Schirm schmal ist.
   Stattdessen teilt sich die Fläche: oben das Rad, unten das Fenster. */
@media (max-width: 820px) {
  .shell {
    grid-template-columns: 1fr;
    grid-template-rows: auto 1fr auto;
    grid-template-areas:
      "kopf"
      "nabe"
      "fuss";
    height: 100dvh;
  }

  /* Der Arbeitsraum entfällt: hier nimmt das Fenster die untere Hälfte. */
  .arbeitsraum { display: none; }

  /* Ist ein Fenster offen, rückt die Shell in die obere Hälfte. */
  .fenster-offen .shell { height: 50dvh; }

  .fenster {
    left: 0;
    right: 0;
    top: 50dvh;
    bottom: 0;
    border: 0;
    border-top: 1px solid rgba(0, 0, 0, 0.22);
    border-radius: 0;
    /* Kein Schlagschatten: das Fenster liegt hier nicht über der Fläche,
       es teilt sie — auf reinem Weiß wirkte der Schatten fremd. */
    box-shadow: none;
  }

  /* Grün stellt das aktive Fenster über den ganzen Schirm. */
  .fenster.breit { left: 0; top: 0; }

  /* Gelb gibt es nicht: einklappen hätte hier keinen Ort. */
  .ampel-gelb { display: none; }

  /* Enger Schirm, engere Spalte. */
  .reihe { column-gap: var(--leerzeile); }
  .kalender { column-gap: 0; }
}
