/* Pandaloop Admin Plane. Blueprint-Grau, Raster, Rot als Wuerze.
   Variablennamen wie in pandaloop.de/assets/styles.css. */

@font-face { font-family: 'Mozilla Headline'; src: url('/static/fonts/Mozilla_Headline_VF.woff2') format('woff2-variations');
             font-weight: 200 700; font-display: swap; }
@font-face { font-family: 'Geist'; src: url('/static/fonts/Geist_VF.woff2') format('woff2-variations');
             font-weight: 100 900; font-display: swap; }
@font-face { font-family: 'Geist Mono'; src: url('/static/fonts/Geist_Mono_VF.woff2') format('woff2-variations');
             font-weight: 100 900; font-display: swap; }

:root {
  --white:       #e4e4e4;
  --grey:        #959595;
  --black:       #222222;
  --red:         #e94b27;
  --orange:      #e66100;
  --lightgrey:   #bbb;
  --lightergrey: #ddd;
  /* --grey auf dem Kachelgrund ergibt 2,2:1 -- unter der Haelfte dessen,
     was lesbar heisst. Betroffen war nicht Beiwerk, sondern die ganze
     Erklaerlogik: jeder .hint, jede UUID, jedes Gruppenband im Menue.
     Also ein zweiter Ton fuer Text; --grey bleibt fuer Striche. */
  --grey-text:   #6a6a6a;

  --sp:  min(95vw, 2500px);
  --px:  calc(1 / 1600 * var(--sp));
  --gap: calc(12 * var(--px));
  --s1: calc((var(--sp) - 7 * var(--gap)) / 8);
  --s2: calc(2 * var(--s1) + var(--gap));
  --s4: calc(4 * var(--s1) + 3 * var(--gap));
  --s6: calc(6 * var(--s1) + 5 * var(--gap));

  --border-solid:  1px solid var(--black);
  --border-dashed: 1px dashed var(--black);
  --radius: calc(5 * var(--px));

  --ls-headline: calc(-1 / 40);
  --ls-mono:     calc(-1 / 15);
  --ls-body:     calc(-1 / 30);
}

/* Bis hierher zog '--px' die gesamte Typografie mit der Fensterbreite: auf
   einem Telefon mit 390 px ergab die Grundschrift 3,9 px und der Hinweistext
   2,8 px. Rechnerisch schluessig, praktisch unlesbar -- und eine Control
   Plane macht man gerade unterwegs auf, um zu sehen, ob ein Deploy durch
   ist. Unterhalb von 900 px bekommt '--px' deshalb einen festen Wert; das
   Raster rechnet weiter in '--px', hoert aber auf zu schrumpfen. */
@media (max-width: 900px) {
  :root {
    --sp: calc(100vw - 8vw);
    --px: 0.92px;
    --gap: 4vw;
  }
}

@media (max-width: 800px) { :root { --gap: 5vw; } }



* { box-sizing: border-box; }

html {
  font-family: 'Geist', system-ui, sans-serif;
  font-size: calc(17 * var(--px));
  letter-spacing: calc(var(--ls-body) * 1em);
  color: var(--black);
  background: var(--white);
}
body { margin: 0; min-height: 100vh; }

/* Hintergrund-Spaltenraster, liegt fest hinter allem. */
.bggrid {
  position: fixed; inset: 0; z-index: -2;
  display: flex; gap: var(--gap);
  width: var(--sp); margin: 0 auto;
  pointer-events: none;
}
.bggrid .cell { flex: 1; border-left: 1px dashed var(--lightgrey); }
.bggrid .cell:last-child { border-right: 1px dashed var(--lightgrey); }

/* Registerkreuze an den Rasterkanten. Passermarken aus dem Druck.
   Im selben Kasten wie das Raster, nicht am Fensterrand: der Kasten ist
   zentriert, und 100vw zaehlt den Scrollbalken mit, das Raster nicht.
   '--linie' ist die Nummer der gestrichelten Linie von links (0 bis 7);
   die Mitte des Kreuzes sitzt genau darauf. Das Raster steht fest, seine
   Linien sehen beim Scrollen gleich aus; die Kreuze sind Marken auf der
   Seite und scrollen mit. */
body { position: relative; }
.crosses {
  position: absolute; inset: 0; z-index: -1; pointer-events: none;
  width: var(--sp); margin: 0 auto;
}
.crosses span {
  --kreuz: calc(14 * var(--px));
  position: absolute; width: var(--kreuz); height: var(--kreuz);
  left: calc(var(--linie) * (var(--s1) + var(--gap)) - var(--kreuz) / 2);
  background: url('/static/cross.svg') no-repeat center / contain; opacity: .5;
}

.wrap { width: var(--sp); margin: 0 auto; padding: calc(28 * var(--px)) 0 calc(60 * var(--px)); }

/* -- Kopf ------------------------------------------------------------- */

header.top {
  display: flex; align-items: center; gap: var(--gap);
  padding-bottom: calc(14 * var(--px)); border-bottom: var(--border-solid);
}
header.top img.mark { height: calc(34 * var(--px)); width: auto; }
header.top .wordmark {
  font-family: 'Mozilla Headline', 'Geist', sans-serif; font-weight: 600;
  font-size: calc(26 * var(--px)); letter-spacing: calc(var(--ls-headline) * 1em);
  line-height: 1;
}
header.top nav { margin-left: auto; display: flex; gap: calc(6 * var(--px)); align-items: center; }

.navlink {
  font-family: 'Geist Mono', ui-monospace, monospace;
  font-size: calc(13 * var(--px)); text-transform: uppercase;
  letter-spacing: calc(var(--ls-mono) * 1em);
  padding: calc(6 * var(--px)) calc(11 * var(--px));
  background: #aeaeaea1; backdrop-filter: blur(10px);
  border-radius: var(--radius); color: var(--black); text-decoration: none;
  border: none; cursor: pointer; transition: background 150ms;
}
.navlink:hover { background: #e94b27a1; }

/* -- Der Regler im Kopf ------------------------------------------------
   Elf Knoepfe nebeneinander sind eine Liste, keine Ordnung. Was selten
   gebraucht wird, liegt hinter einem Zeichen; 'details' statt eines
   Schwebefensters, wie bei '.info': mit der Tastatur zu oeffnen, ohne
   Mauszeiger bedienbar. */
.kopfmenue { position: relative; display: inline-block; }
.kopfmenue > summary { list-style: none; cursor: pointer; display: inline-flex; align-items: center; }
.kopfmenue > summary::-webkit-details-marker { display: none; }
.kopfmenue > summary .icon { width: 1.1em; height: 1.1em; }
.kopfmenue[open] > summary { background: #e94b27a1; }
.kopfmenue .menu-panel {
  position: absolute; right: 0; top: calc(100% + 6 * var(--px)); z-index: 20;
  display: grid; gap: calc(8 * var(--px));
  min-width: calc(260 * var(--px));
  padding: calc(10 * var(--px)) calc(12 * var(--px));
  border: var(--border-solid); background: var(--lightergrey);
  text-align: left;
}
.kopfmenue-punkt { display: block; text-decoration: none; }
.kopfmenue-punkt .wort {
  font-family: 'Geist Mono', ui-monospace, monospace;
  font-size: calc(13 * var(--px)); text-transform: uppercase;
  letter-spacing: calc(var(--ls-mono) * 1em);
}
.kopfmenue-punkt .hint { display: block; font-size: calc(12 * var(--px)); }
.kopfmenue-punkt:hover .wort, .kopfmenue-punkt.on .wort { color: var(--red); }

/* -- Abschnittslabel: roter Slash, Mono-Versalien, Haarlinie ---------- */

.section-label {
  display: flex; align-items: baseline; gap: calc(8 * var(--px));
  font-family: 'Geist Mono', ui-monospace, monospace;
  font-size: calc(15 * var(--px)); text-transform: uppercase;
  letter-spacing: calc(var(--ls-mono) * 1em);
  margin: calc(38 * var(--px)) 0 calc(14 * var(--px));
  border-bottom: var(--border-solid); padding-bottom: calc(6 * var(--px));
}
.section-label .slash { color: var(--red); }
.section-label .count { margin-left: auto; color: var(--grey-text); }
.section-label .act { margin-left: auto; }

/* Ein Abschnitt, den sein eigenes Label aufklappt: fuer das, was nicht
   einen Fehlgriff weit offen liegen soll. Das Zeichen sitzt rechts, wo
   sonst die Zahl steht. */
summary.section-label { list-style: none; cursor: pointer; }
summary.section-label::-webkit-details-marker { display: none; }
summary.section-label::after {
  content: "+"; margin-left: auto; color: var(--red);
  display: inline-block; width: 1ch; text-align: center;
}
details[open] > summary.section-label::after { content: "\2013"; }

/* Running state of an app: label column, then what it is. */
table.stand { border-collapse: collapse; margin: 0 0 calc(14 * var(--px)); }
table.stand th {
  font-family: 'Geist Mono', ui-monospace, monospace; font-weight: normal;
  font-size: calc(13 * var(--px)); text-transform: uppercase; text-align: left;
  letter-spacing: calc(var(--ls-mono) * 1em); color: var(--grey-text);
  padding: calc(4 * var(--px)) calc(16 * var(--px)) calc(4 * var(--px)) 0; vertical-align: baseline;
}
table.stand td { padding: calc(4 * var(--px)) 0; vertical-align: baseline; }

h1 {
  font-family: 'Mozilla Headline', 'Geist', sans-serif;
  font-size: calc(75 * var(--px)); font-weight: 700; line-height: .8;
  letter-spacing: calc(var(--ls-headline) * 1em);
  margin: calc(24 * var(--px)) 0 calc(8 * var(--px));
}
h2 {
  font-family: 'Mozilla Headline', 'Geist', sans-serif;
  font-size: calc(36 * var(--px)); font-weight: 600; line-height: .9;
  letter-spacing: calc(var(--ls-headline) * 1em); margin: 0;
}

.mono { font-family: 'Geist Mono', ui-monospace, monospace; letter-spacing: calc(var(--ls-mono) * 1em); }
.caps { text-transform: uppercase; }
.dim  { color: var(--grey-text); }
.num  { color: var(--black); }
.num::before { content: '['; color: var(--red); }
.num::after  { content: ']'; color: var(--red); }

/* -- Instanzkarte als Terminalfenster --------------------------------- */

/* flex-start statt des voreingestellten stretch: sonst zieht die hoechste
   Kachel einer Zeile alle anderen auf ihre Hoehe, und wer eine aufklappt,
   laesst ihre Nachbarn mitwachsen, ohne dass dort etwas zu sehen waere. */
.grid { display: flex; flex-wrap: wrap; gap: var(--gap); align-items: flex-start; }

.product-window {
  width: var(--s2); min-width: calc(260 * var(--px));
  border: var(--border-solid); background: var(--lightergrey);
  display: flex; flex-direction: column;
}
.product-window .head {
  display: flex; align-items: center; gap: calc(8 * var(--px));
  padding: calc(8 * var(--px)) calc(10 * var(--px));
  font-family: 'Geist Mono', ui-monospace, monospace;
  font-size: calc(13 * var(--px)); text-transform: uppercase;
  letter-spacing: calc(var(--ls-mono) * 1em);
}
.product-window .head img { width: calc(14 * var(--px)); height: calc(14 * var(--px)); }
.product-window .head .n { margin: 0 auto; }
.product-window hr { border: none; border-top: var(--border-dashed); margin: 0; }
.product-window .body { padding: calc(12 * var(--px)) calc(10 * var(--px)); flex: 1; }
.product-window .body .name {
  font-family: 'Mozilla Headline', 'Geist', sans-serif; font-weight: 600;
  font-size: calc(28 * var(--px)); line-height: 1;
  letter-spacing: calc(var(--ls-headline) * 1em);
  word-break: break-word;
}
.product-window .marken { margin-top: calc(8 * var(--px)); display: flex; flex-wrap: wrap; gap: calc(5 * var(--px)); }
.product-window dl { margin: calc(10 * var(--px)) 0 0; font-size: calc(14 * var(--px)); }
.product-window dl div { display: flex; gap: calc(8 * var(--px)); padding: calc(3 * var(--px)) 0; }
.product-window dt {
  font-family: 'Geist Mono', ui-monospace, monospace; text-transform: uppercase;
  font-size: calc(12 * var(--px)); color: var(--grey-text); min-width: calc(74 * var(--px));
  letter-spacing: calc(var(--ls-mono) * 1em);
}
/* 'break-all' bricht immer mitten im Wort, auch wenn eine Leerstelle in
   Reichweite ist. Fuer einen Imagenamen ohne Leerzeichen war das richtig,
   fuer einen Satz zerhackt es die Woerter. 'anywhere' bricht am Wortende,
   solange es eines gibt, und erst im Notfall mittendrin, beides also
   richtig. 'min-width: 0', weil das dd ein Flex-Kind ist: ohne das schrumpft
   es nicht unter seine Inhaltsbreite und laeuft aus der Kachel heraus. */
.product-window dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }
.product-window dd ul { margin: calc(3 * var(--px)) 0 0; padding-left: 1.1em; }
.product-window dd li { margin-bottom: calc(2 * var(--px)); }
.product-window .foot {
  display: flex; gap: calc(6 * var(--px)); padding: calc(10 * var(--px));
  border-top: var(--border-dashed);
}

/* Verwaltete Instanzen sind der Normalfall: ruhige Flaeche, fester Rahmen.
   Fremde fallen auf, gestrichelter Rahmen und Punktraster, wie eine
   Flaeche in einer technischen Zeichnung, die nicht zum Bauteil gehoert. */
.product-window.unmanaged {
  border: var(--border-dashed);
  background-image: radial-gradient(var(--lightgrey) calc(1 * var(--px)), transparent calc(1 * var(--px)));
  background-size: calc(9 * var(--px)) calc(9 * var(--px));
}
.product-window.unmanaged .name { color: var(--grey-text); }
.product-window.unmanaged .head { color: var(--grey-text); }

.taglabel {
  display: inline-block;
  font-family: 'Geist Mono', ui-monospace, monospace;
  font-size: calc(12 * var(--px)); text-transform: uppercase;
  letter-spacing: calc(var(--ls-mono) * 1em);
  padding: calc(2 * var(--px)) calc(7 * var(--px));
  border: 2px dotted var(--grey); border-radius: calc(3 * var(--px));
  background: linear-gradient(#ececec, #dcdcdc);
  transition: background 150ms, border-color 150ms;
}
.taglabel.hot { border-style: solid; border-color: var(--black); font-weight: 700; }
/* A state that wants attention, on a label or on a sentence. Before these,
   every page wrote the colour itself: 41 labels and 29 lines of text. The
   colour itself sits at the end of this file -- see .bad / .warn there. */
.taglabel.bad { border-color: var(--red); }
.taglabel.warn { border-color: var(--orange); }

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

form.panel { width: var(--s4); min-width: calc(300 * var(--px)); }
.field { margin-bottom: calc(14 * var(--px)); }
.field label, .field .feldkopf {
  display: block; font-family: 'Geist Mono', ui-monospace, monospace;
  font-size: calc(12 * var(--px)); text-transform: uppercase; color: var(--grey-text);
  letter-spacing: calc(var(--ls-mono) * 1em); margin-bottom: calc(4 * var(--px));
}
.field input, .field select, .field textarea {
  width: 100%; font-family: 'Geist Mono', ui-monospace, monospace;
  font-size: calc(15 * var(--px)); letter-spacing: calc(var(--ls-mono) * 1em);
  padding: calc(8 * var(--px)) calc(10 * var(--px));
  border: var(--border-solid); border-radius: 0;
  background: var(--lightergrey); color: var(--black);
}
/* Die Regel darueber meint Textfelder. Auf ein Ankreuzfeld angewandt zieht
   sie das Kaestchen ueber die ganze Zeile, es steht dann mittig, und der
   Text daneben rutscht darunter. Ein Kaestchen ist so breit, wie es ist. */
.field input[type="checkbox"], .field input[type="radio"] {
  width: auto; padding: 0; margin: 0 calc(8 * var(--px)) 0 0;
  vertical-align: baseline;
}
/* Und die Zeile um ein Kaestchen ist Fliesstext, keine Feldbeschriftung.
   Getroffen wird sie ueber ihren Inhalt, nicht ueber ein fehlendes 'for':
   Beschriftungen ohne 'for' gibt es auch anderswo, und die sollen
   Beschriftungen bleiben. */
.field label:has(> input[type="checkbox"]),
.field label:has(> input[type="radio"]) {
  display: block; text-transform: none; color: var(--black);
  font-family: inherit; font-size: calc(14 * var(--px));
  letter-spacing: normal; margin-bottom: calc(6 * var(--px));
}
.field textarea { min-height: calc(90 * var(--px)); resize: vertical; }
/* Ein Textfeld, das in einer Zeile neben etwas anderem steht, der Zweig
   beim Nachziehen, die Version je Modul, die Domain eines Stacks. Die Regel
   oben haengt an '.field', und diese Felder stehen nicht darin: sie kamen
   bisher in der Vorgabe des Browsers daher, mitten zwischen Flaechen, die
   alle gleich aussehen. Gleicher Rahmen, gleicher Grund, gleiche Schrift,
   nur die Breite bringt der Aufrufer mit, denn sie steht neben etwas. */
/* Solange ein Verweis oder Knopf seine Seite im Hintergrund holt. Ohne das
   sieht ein Knopf, der nicht mehr neu laedt, aus wie einer, der nichts tut,
   und wird ein zweites Mal gedrueckt. */
[data-laeuft] { opacity: .55; cursor: progress; pointer-events: none; }
[data-laeuft]::after { content: " …"; }

.feld-inline {
  font-family: 'Geist Mono', ui-monospace, monospace;
  font-size: calc(14 * var(--px)); letter-spacing: calc(var(--ls-mono) * 1em);
  padding: calc(5 * var(--px)) calc(8 * var(--px));
  border: var(--border-solid); border-radius: 0;
  background: var(--lightergrey); color: var(--black);
  vertical-align: baseline;
}
/* Das Domainfeld in der Containerzeile soll am Schreibtisch nicht auf die
   Breite seiner Zelle zusammenfallen. Auf dem Telefon nimmt der Abschnitt
   ganz unten dieses Mindestmass zurueck: dort war es die Zelle, die die
   Tabelle ueber den Seitenrand schob. */
table.listing .feld-inline { min-width: calc(180 * var(--px)); }

/* A list's search: field, hit count and the clear control in one line. The
   browser's own clear cross would be a second, differently drawn one. */
.list-search {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: calc(12 * var(--px));
  margin: calc(18 * var(--px)) 0 0; font-size: calc(13 * var(--px));
}
.list-search input { width: calc(340 * var(--px)); max-width: 100%; }
.list-search input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }
/* Free tags (src/tags.rs): the field on an app's or stack's page, and the
   small labels in the list; a click on one searches for it. */
.tags-form {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: calc(8 * var(--px));
  margin: calc(12 * var(--px)) 0; font-size: calc(13 * var(--px));
}
.tags-form input { width: calc(340 * var(--px)); max-width: 100%; }
.taglabel.tag {
  font-size: calc(10 * var(--px)); padding: calc(1 * var(--px)) calc(5 * var(--px));
  margin: calc(4 * var(--px)) calc(4 * var(--px)) 0 0;
  background: none; color: var(--black); cursor: pointer;
}
.taglabel.tag:hover, .taglabel.tag:focus-visible { background: var(--red); color: var(--white); border-color: var(--black); }
/* Ein Hinweis erklaert, er behauptet nicht. Bisher galt das nur innerhalb
   eines Formularfelds, ein '<p class="hint">' auf der Seite bekam gar keinen
   Stil und stand in voller Textgroesse da wie Fliesstext. Die laengsten waren
   damit 400 Zeichen Prosa in Erzaehlgroesse; sie sind jetzt das, was sie sein
   sollten: eine Nebenbemerkung. Die Breite deckelt mit, weil eine graue Zeile
   ueber die ganze Seite niemand liest. */
.hint {
  font-size: calc(13 * var(--px));
  color: var(--grey-text);
  line-height: 1.45;
  max-width: 72ch;
}
.field .hint { font-size: calc(12 * var(--px)); color: var(--grey-text); margin-top: calc(4 * var(--px)); }

/* Das lange Warum hinter einem Aufklapper: die Seite liest sich kurz, das
   Wissen bleibt einen Klick entfernt. */
details.warum { max-width: 72ch; margin: calc(6 * var(--px)) 0 calc(12 * var(--px)); }
details.warum > summary {
  font-size: calc(12 * var(--px)); color: var(--grey-text);
  text-transform: uppercase; letter-spacing: calc(var(--ls-mono) * 1em);
  cursor: pointer; list-style: none;
}
details.warum > summary::-webkit-details-marker { display: none; }
details.warum > summary::before { content: "+"; }
details.warum[open] > summary::before { content: "\2013"; }
details.warum > summary:hover { color: var(--black); }
details.warum > p { font-size: calc(13 * var(--px)); color: var(--grey-text); line-height: 1.45; }

.action {
  font-family: 'Geist Mono', ui-monospace, monospace;
  font-size: calc(14 * var(--px)); text-transform: uppercase;
  letter-spacing: calc(var(--ls-mono) * 1em);
  padding: calc(8 * var(--px)) calc(14 * var(--px));
  border: var(--border-solid); border-radius: 0;
  background: var(--white); color: var(--black); cursor: pointer;
  transition: background 150ms, color 150ms;
  /* Auch fuer ein <a>: die Regel hing am Elementnamen, und fuenf Seiten
     stellten ihre Hauptaktion als Fliesstextlink dar -- bei den
     Einstellungen ausgerechnet den einzigen Weg, die Coolify-Verbindung zu
     pruefen. Die Unterstreichung kommt hier aus border-bottom, deshalb wird
     die mit abgeraeumt und nicht text-decoration. */
  display: inline-block; text-decoration: none; border-bottom: var(--border-solid);
}
.action:hover { background: var(--red); color: var(--white); }

/* A button with its explanation beside it. Inline, the second line of the
   explanation started under the button; as a column of its own it stays
   under itself, and on a narrow tile it drops below the button. */
.action-row { display: flex; align-items: center; flex-wrap: wrap; gap: calc(8 * var(--px)); }
.action-row .hint { flex: 1 1 calc(220 * var(--px)); }
.action.quiet:hover { background: var(--black); }

/* -- Meldungen --------------------------------------------------------- */

.note { border: var(--border-solid); padding: calc(12 * var(--px)); margin: calc(16 * var(--px)) 0; background: var(--lightergrey); }
.note.bad { border-left: calc(4 * var(--px)) solid var(--red); }
.note.good { border-left: calc(4 * var(--px)) solid var(--black); }
.note .k { font-family: 'Geist Mono', ui-monospace, monospace; text-transform: uppercase; font-size: calc(12 * var(--px)); color: var(--grey-text); }

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

.login-shell { display: flex; align-items: center; justify-content: center; min-height: 100vh; }
.login-box { width: var(--s2); min-width: calc(320 * var(--px)); border: var(--border-solid); background: var(--lightergrey); }
.login-box .head { display: flex; align-items: center; gap: calc(8 * var(--px)); padding: calc(9 * var(--px)) calc(11 * var(--px)); font-family: 'Geist Mono', ui-monospace, monospace; font-size: calc(13 * var(--px)); text-transform: uppercase; letter-spacing: calc(var(--ls-mono) * 1em); }
.login-box .head img { width: calc(14 * var(--px)); height: calc(14 * var(--px)); }
.login-box .body { padding: calc(16 * var(--px)); }

/* Randannotation in Mono, wie die Koordinaten am Hero-Rand. */
.annotation {
  position: fixed; bottom: calc(12 * var(--px)); left: calc(14 * var(--px));
  font-family: 'Geist Mono', ui-monospace, monospace;
  font-size: calc(11 * var(--px)); color: var(--grey-text);
  letter-spacing: calc(var(--ls-mono) * 1em); text-transform: uppercase;
}

/* -- Navigation: Logo als Heimweg, aktiver Punkt ---------------------- */

header.top .home {
  display: flex; align-items: center; gap: var(--gap);
  text-decoration: none; color: var(--black);
}
header.top .home img.mark { transition: transform 150ms; }
header.top .home:hover img.mark { transform: rotate(-4deg); }
.navlink.on { background: #e94b27a1; }

/* -- Tabelle: Zeilen als Raster, kein Kasten -------------------------- */

table.listing {
  width: 100%; border-collapse: collapse;
  margin-top: calc(4 * var(--px));
}
table.listing th {
  text-align: left;
  font-family: 'Geist Mono', ui-monospace, monospace;
  font-size: calc(12 * var(--px)); text-transform: uppercase;
  letter-spacing: calc(var(--ls-mono) * 1em);
  color: var(--grey-text); font-weight: 400;
  padding: calc(6 * var(--px)) calc(8 * var(--px));
  border-bottom: var(--border-solid);
}
table.listing td {
  padding: calc(9 * var(--px)) calc(8 * var(--px));
  border-bottom: var(--border-dashed);
  font-size: calc(15 * var(--px)); vertical-align: top;
}
table.listing tr:hover td { background: var(--lightergrey); }

/* Kacheln des Dashboards duerfen schmaler stehen als Produktfenster. */
.grid .product-window { min-width: calc(220 * var(--px)); }

/* -- Filterzeile ------------------------------------------------------ */

.filters {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: calc(6 * var(--px));
  margin: calc(10 * var(--px)) 0 calc(4 * var(--px));
}
.filters a.taglabel { text-decoration: none; color: var(--black); }
.filters a.taglabel:hover { background: var(--red); color: var(--white); border-color: var(--black); }
.filters a.taglabel.hot { background: var(--black); color: var(--white); border-color: var(--black); }
.filters a.taglabel.hot .dim { color: var(--lightgrey); }
.filters .sep { color: var(--grey-text); margin: 0 calc(4 * var(--px)); }

/* -- Links: kein Browser-Blau, roter Marker beim Überfahren ------------ */

a { color: var(--black); text-decoration: none; }
/* '.nurikon' ausgenommen: ein Zeichen ist keine Textstelle, die man
   unterstreicht. Und weil diese Regel nur auf 'a' greift, bekamen Stift und
   Papier eine Linie, Duplizieren (summary) und Entfernen (button) keine -
   was aussah, als staenden die Zeichen auf verschiedenen Hoehen. */
.wrap p a:not(.blank), .wrap dd a:not(.blank),
td a:not(.navlink):not(.action):not(.nurikon):not(.blank) {
  border-bottom: 1px solid var(--grey);
  transition: border-color 150ms, color 150ms;
}
.wrap p a:not(.blank):hover, .wrap dd a:not(.blank):hover,
td a:not(.navlink):not(.action):not(.nurikon):not(.blank):hover {
  border-bottom-color: var(--red);
}
/* Trennzeichen in Linkzeilen bleibt grau, der Slash rot, wie im Fußzeilen-
   Muster "Seite 1 / 3". */
.linkline { display: flex; gap: calc(8 * var(--px)); align-items: baseline; }
.linkline .sep { color: var(--red); }

/* -- Kachelfuß: Mono-Labels statt Knöpfe ------------------------------- */

.product-window .foot {
  display: flex; flex-wrap: wrap; align-items: center; gap: calc(10 * var(--px));
  padding: calc(8 * var(--px)) calc(10 * var(--px));
  border-top: var(--border-dashed);
  font-family: 'Geist Mono', ui-monospace, monospace;
  font-size: calc(12 * var(--px)); text-transform: uppercase;
  letter-spacing: calc(var(--ls-mono) * 1em);
}
.product-window .foot form { display: inline; }
/* A summary and a button both wear .act and read exactly the same, so
   nothing said which one opens something. The red + says it, in the
   language the section labels and the "warum" expanders already speak.
   Icon-only summaries keep out of it: their icon is the whole word.
   The fixed box matters: + and - are not the same width, and without it
   the word beside them moves every time one is opened. */
/* The native triangle is suppressed per place (product-window, ikonzeile,
   kopfmenue ...), which left the instance page drawing both it and the +.
   Wherever a summary wears .act, the + is its only marker. */
summary.act { list-style: none; cursor: pointer; }
summary.act::-webkit-details-marker { display: none; }
summary.act:not(.nurikon)::before { content: "+"; }
details[open] > summary.act:not(.nurikon)::before { content: "\2013"; }
summary.act:not(.nurikon)::before,
details.warum > summary::before {
  color: var(--red); display: inline-block;
  width: 1ch; margin-right: calc(5 * var(--px)); text-align: center;
}

.act {
  background: none; border: none; padding: 0; cursor: pointer;
  font: inherit; letter-spacing: inherit; text-transform: inherit;
  color: var(--black); border-bottom: 1px solid var(--grey);
  transition: color 150ms, border-color 150ms;
}
.act:hover { color: var(--red); border-bottom-color: var(--red); }
/* "Nach aussen oeffnen" trug die Klasse und sah trotzdem aus wie jeder
   andere Knopf -- eine Regel dafuer gab es nicht. Der Knopf oeffnet eine
   Kopie echter Kundendaten nach draussen; er darf nicht grau sein. */
.act.gefahr { color: var(--red); border-bottom-color: var(--red); }
.act.gefahr:hover { background: var(--red); color: var(--white); }
.act.danger { color: var(--grey-text); }
.act.danger:hover { color: var(--red); border-bottom-color: var(--red); }
.product-window .foot .right { margin-left: auto; }

/* Zugeklappt ist ein Ausklapper nur sein Wort und steht in der Reihe.
   Aufgeklappt ist das Formular breiter als der Platz daneben, also nimmt
   es eine eigene Zeile ueber die volle Kachelbreite, statt rechts
   herauszuragen. */
.product-window .foot > * { min-width: 0; max-width: 100%; }
.product-window details.remove > summary { list-style: none; cursor: pointer; }
.product-window details.remove > summary::-webkit-details-marker { display: none; }
/* Every expander in the row, not only the one that deletes: a triangle
   beside a word that looks like a button reads like a mistake. */
.product-window .foot > details > summary { list-style: none; cursor: pointer; }
.product-window .foot > details > summary::-webkit-details-marker { display: none; }
.product-window .foot > details[open] {
  flex-basis: 100%; width: 100%; margin-left: 0;
  padding-top: calc(8 * var(--px));
}
/* Das Menue: eine Spalte, kein Feld nebeneinander. Wer hier ist, sucht eine
   Handlung und keine Anordnung. */
.product-window .menu > summary { list-style: none; cursor: pointer; }
.product-window .menu > summary::-webkit-details-marker { display: none; }
.product-window .menu-panel {
  display: grid; gap: calc(10 * var(--px));
  padding-top: calc(10 * var(--px));
}
.product-window .menu-panel > form { display: block; }
.product-window .menu-panel details[open] { padding-bottom: calc(4 * var(--px)); }
/* Innerhalb des Menues sind es Zeilen, keine Woerter in einer Reihe. */
.product-window .menu-panel .act { display: inline-block; }

/* Gruppen im Menue.
   Acht Eintraege untereinander sind eine Liste, keine Ordnung: alles gleich
   laut, Haeufiges neben Seltenem, und das Loeschen mittendrin. Eine
   Ueberschrift je Gruppe kostet eine Zeile und beantwortet die Frage, in
   welcher Gegend man sucht -- dieselbe Geste wie '/ SYNOPSIS' im Web, nur
   kleiner. */
/* Die Gruppe ist eine Ueberschrift, kein Aufklapper mehr.
   Sie war einer, und damit lagen drei Ebenen uebereinander: Mehr, dann die
   Gruppe, dann die Aktion. Loeschen kostete drei Aufklapper, und die
   mittlere Ebene trug ausgerechnet die kleinste Schrift der Seite und nach
   eigenem Entschluss kein Auf-Zu-Zeichen -- ein Klickziel, das nicht
   aussah wie eines, auf halbem Weg zum Ziel.
   Die Ordnung bleibt, der Klick faellt weg. */
/* The instance page carries what the tile's menu used to hide: the same
   items, one column, with the room a page has instead of a card's. */
.instance-panel { display: grid; gap: calc(10 * var(--px)); width: min(var(--s6), 100%); }
.instance-panel > form { display: block; }
.instance-panel details[open] { padding-bottom: calc(4 * var(--px)); }
.instance-panel .act { display: inline-block; }

.menu-gruppe {
  font-family: 'Geist Mono', ui-monospace, monospace;
  font-size: calc(11 * var(--px)); text-transform: uppercase;
  letter-spacing: calc(var(--ls-mono) * 1em);
  color: var(--black);
  margin-top: calc(12 * var(--px));
  border-bottom: var(--border-dashed);
  padding-bottom: calc(5 * var(--px));
}
.menu-gruppe:first-child { margin-top: 0; }
/* Die Linie liegt unter der Ueberschrift, nicht neben ihr: ein Strich links
   nimmt die Ueberschrift mit und ruecht sie aus der Spalte der anderen. Nur
   der Inhalt ruecht ein. */
.menu-gruppe ~ :not(.menu-gruppe) { margin-left: calc(10 * var(--px)); }
.menu-gruppe .slash { color: var(--red); margin-right: calc(4 * var(--px)); }
/* Der gefaehrliche Teil steht unten und hinter einer Linie -- man kommt
   dort nicht aus Versehen vorbei. */
.menu-gruppe.gefahr { border-top: var(--border-dashed); padding-top: calc(8 * var(--px)); }
/* Das Kreuz in der Kopfleiste ist jetzt ein Knopf und soll trotzdem
   aussehen wie vorher. */
.product-window .chrome-x {
  background: none; border: 0; padding: 0; margin: 0; line-height: 0;
  cursor: pointer; opacity: 0.75; transition: opacity 150ms;
}
.product-window .chrome-x:hover { opacity: 1; }

/* -- QR-Code: auf heller Flaeche, sonst lesen ihn manche Kameras nicht -- */

.qr {
  display: inline-block;
  background: #fff; padding: calc(8 * var(--px));
  border: var(--border-solid);
  margin: calc(8 * var(--px)) 0;
}
.qr svg { display: block; width: calc(190 * var(--px)); height: auto; }

/* Aktueller Punkt der Unternavigation: sichtbar der Ort - und trotzdem ein
   Link, weil man von jeder Unterseite dorthin zurueck will. */
.linkline .hier { color: var(--black); border-bottom: 1px solid var(--black); }

/* Link ohne Unterstreichung: auf den Kacheln traegt schon die Umgebung die
   Bedeutung, eine Linie waere nur eine weitere Kante zwischen vielen. Beim
   Ueberfahren wird sie sichtbar, dann, wenn die Frage aufkommt. */
/* '.wrap dd a' zeichnet Links mit einem grauen border-bottom, nicht mit
   text-decoration, ein 'text-decoration: none' lief deshalb ins Leere und
   die Domain stand unterstrichen da. Hier wird die Kante genommen und beim
   Ueberfahren in Rot zurueckgegeben, wie im uebrigen Haus. */
.wrap dd a.blank, .wrap p a.blank, a.blank {
  color: inherit; text-decoration: none; border-bottom: none;
}
.wrap dd a.blank:hover, .wrap p a.blank:hover, a.blank:hover,
a.blank:focus-visible { border-bottom: 1px solid var(--red); }
a.blank:focus-visible { outline: 1px solid var(--red); outline-offset: 2px; }

/* Aktionssymbole. Register 1 der Icon-Regeln: das Icon ist Text. Groesse in
   em, Farbe geerbt, keine Kachel, kein Rahmen, keine eigene Farbe. Das
   vertical-align setzt es auf die Grundlinie, wie Odoo es fuer seine
   Glyphen tut. */
.icon { vertical-align: -0.14em; flex: none; }
a.act .icon, button.act .icon { pointer-events: none; }
.act.nurikon {
  display: inline-flex; align-items: center; justify-content: center;
  width: calc(26 * var(--px)); height: calc(26 * var(--px));
  padding: 0; border: 1px solid transparent; border-bottom: 1px solid transparent;
  vertical-align: top;
}
.act.nurikon:hover, .act.nurikon:focus-visible {
  border-color: var(--black); background: var(--white);
}
.act.nurikon.gefahr:hover, .act.nurikon.gefahr:focus-visible {
  border-color: var(--red); color: var(--red);
}
/* Eine Zeile Aktionszeichen: gleiche Groesse, gleicher Abstand, nichts
   umbricht mitten in einer Gruppe. */
/* The numbers of an entry as a row of label and value, instead of a
   sentence with three figures and two timestamps in it. Wraps on a narrow
   screen. New class names are English; the older German ones stay as they
   are until somebody renames them on purpose. */
.figures {
  display: flex; flex-wrap: wrap; gap: calc(4 * var(--px)) calc(18 * var(--px));
  font-size: calc(12 * var(--px)); color: var(--grey-text);
}
.figures > span { white-space: nowrap; }
.figures .value { color: var(--black); }

.ikonzeile { display: flex; align-items: center; gap: calc(7 * var(--px)); flex-wrap: wrap; }
.ikonzeile details > summary { list-style: none; }
.ikonzeile details > summary::-webkit-details-marker { display: none; }
/* Die Hauptaktion einer Zeile traegt ihr Wort: ein Zeichen allein muss man
   raten, und gerade diese Handlung baut ein Image und schiebt es hinaus. */
.act.mitikon { display: inline-flex; align-items: center; gap: calc(5 * var(--px)); }
/* Das Loeschen bekommt etwas Luft: direkt neben der Hauptaktion zu stehen
   laedt zu dem einen Klick ein, den niemand zuruecknehmen kann. */
.ikonzeile .gefahr { margin-left: calc(8 * var(--px)); }


/* Der Hinweis, wenn sich etwas geaendert hat, waehrend jemand tippt. Unten
   rechts, weil er nichts verdecken soll, was gerade bearbeitet wird. */
#puls-balken {
  position: fixed; right: calc(16 * var(--px)); bottom: calc(16 * var(--px));
  z-index: 50;
  background: var(--lightergrey); border: var(--border-solid);
  padding: calc(8 * var(--px)) calc(12 * var(--px));
  font-size: calc(13 * var(--px));
}
#puls-balken a { color: var(--red); }

/* Nur-Lese-Betrieb (PANGU_NUR_LESEN, Rust only): a parallel Pangu that must
   not be mistaken for the real one. Sticky on top of every page. */
.nur-lesen {
  position: sticky; top: 0; z-index: 60;
  background: var(--orange); color: var(--black);
  padding: calc(6 * var(--px)) calc(12 * var(--px));
  font-size: calc(14 * var(--px)); font-weight: 600; text-align: center;
}


/* --- Reiter -------------------------------------------------------------
   Zwei Wege zum selben Ziel nebeneinander zu stellen heisst, dass man beide
   liest, um zu merken, dass man nur einen braucht. Der Reiter zeigt einen
   und nennt den anderen.

   Radiogruppe statt Skript: die Auswahl ueberlebt ein Neuladen nicht, aber
   sie funktioniert ohne JavaScript, und der Browser fuehrt die Tastatur
   richtig (Pfeiltasten wandern durch die Gruppe). */
.reiter { margin: calc(10 * var(--px)) 0 0; }
.reiter > input[type="radio"] { position: absolute; opacity: 0; pointer-events: none; }
.reiter-leiste { display: flex; gap: calc(6 * var(--px)); border-bottom: var(--border-solid); }
.reiter-leiste label {
  font-family: 'Geist Mono', ui-monospace, monospace;
  font-size: calc(12 * var(--px)); text-transform: uppercase;
  letter-spacing: calc(var(--ls-mono) * 1em);
  padding: calc(6 * var(--px)) calc(10 * var(--px));
  border: var(--border-solid); border-bottom: none;
  margin-bottom: -1px; background: transparent; color: var(--grey-text);
  cursor: pointer;
}
.reiter-leiste label:hover { color: var(--black); }
/* '~' statt '+': die beiden Radios stehen vor der Leiste, nur das zweite
   grenzt unmittelbar an sie. Mit '+' bekam der erste gar keine Fokusanzeige
   und der zweite liess beide Beschriftungen leuchten, bei Radios, die
   'opacity: 0' tragen, ist das die einzige Anzeige, die es gibt. */
.reiter > input:nth-of-type(1):focus-visible ~ .reiter-leiste label[for$="-1"],
.reiter > input:nth-of-type(2):focus-visible ~ .reiter-leiste label[for$="-2"] {
  outline: 2px solid var(--red); outline-offset: 2px;
}
.reiter-blatt { display: none; padding-top: calc(12 * var(--px)); }

/* Der gewaehlte Reiter sitzt auf der Linie, statt davor zu stehen. */
.reiter > input:nth-of-type(1):checked ~ .reiter-leiste label[for$="-1"],
.reiter > input:nth-of-type(2):checked ~ .reiter-leiste label[for$="-2"] {
  background: var(--white); color: var(--black); border-bottom: 1px solid var(--white);
}

/* Die Blaetter bekommen eigene Klassen statt ':nth-of-type'. Das zaehlt
   Geschwister derselben *Elementart*, und die Reiterleiste ist selbst ein
   div: ':nth-of-type(1)' meinte also die Leiste, nicht das erste Blatt.
   Folge war ein Reiter, unter dem gar nichts stand. */
.reiter > input:nth-of-type(1):checked ~ .blatt-1,
.reiter > input:nth-of-type(2):checked ~ .blatt-2 { display: block; }

/* --- Infozeichen --------------------------------------------------------
   Ein Erklaertext gehoert nicht neben jedes Feld, sondern dahinter. Die
   Seite liest sich kurz, das Wissen ist einen Klick entfernt.

   <details>/<summary>, kein Skript und kein Schwebefenster: es laesst sich
   mit der Tastatur oeffnen, es steht beim Ausdruck mit im Text, und auf
   einem Zeigegeraet ohne Mauszeiger funktioniert es ebenso. */
details.info { display: inline; }
details.info > summary {
  display: inline; list-style: none; cursor: help;
  color: var(--grey-text); vertical-align: baseline;
}
details.info > summary::-webkit-details-marker { display: none; }
details.info > summary:hover { color: var(--red); }
details.info > summary svg { width: 1em; height: 1em; vertical-align: -0.12em; }
details.info[open] > summary { color: var(--red); }
details.info > .info-text {
  display: block;
  font-size: calc(13 * var(--px)); color: var(--grey-text); line-height: 1.45;
  max-width: 72ch;
  margin: calc(4 * var(--px)) 0 calc(6 * var(--px));
  padding-left: calc(10 * var(--px));
  border-left: 1px solid var(--grey);
}



/* Das Duplizieren-Formular steckt in der Aktionsspalte und bekam deren
   Breite, zwei Felder, jedes einzeln umgebrochen. Eine Mindestbreite
   genuegt: die Zelle waechst beim Aufklappen, statt dass das Formular
   ueber die Zeilen darueber schwebt und sie verdeckt. */
.ikonzeile details[open] > form { min-width: calc(260 * var(--px)); text-align: left; }

.nur-bei-auffrischen[hidden] { display: none; }

/* Ein verstecktes Element mit eigener Anzeigeart braucht die Ausnahme --
   sonst gewinnt die Klasse gegen '[hidden]'. Dasselbe Muster wie bei
   '.nur-bei-auffrischen', und derselbe Fehler waere sonst wieder da. */
.kopie-form button[hidden], .kopie-hinweis[hidden] { display: none; }

/* Ein Fehlversuch im Protokoll. Rot als Zeichen, nicht als Flaeche: die
   Zeile bleibt lesbar, aber das Auge findet sie beim Ueberfliegen. Ohne
   Markierung stuenden Gelungenes und Gescheitertes in derselben grauen
   Spalte, und das Aufzeichnen haette wenig genutzt. */
tr.fehlversuch td:nth-child(3) { color: var(--red); }
tr.fehlversuch td:nth-child(3)::before { content: "! "; color: var(--red); }

/* -- Telefon ----------------------------------------------------------

   Alles steht hier in einer Spalte. Die Spaltenmasse rechneten aber
   weiter in Achteln, und ein Achtel von 92vw sind bei 390 px Breite
   28 px: ein Formular mit '--s6' wurde 264 px breit und liess ein
   Viertel der Seite leer, eine Kachel 239 px. Sie heissen deshalb hier
   volle Breite -- das Raster bleibt, es hat nur keine Spalten mehr zu
   verteilen. */
@media (max-width: 800px) {
  :root { --s2: var(--sp); --s4: var(--sp); --s6: var(--sp); }

  /* Die Mindestbreiten halten am Schreibtisch ein zu schmales Fenster
     auf. Neben der vollen Breite koennen sie nur noch ueberstehen. */
  .product-window, .grid .product-window, form.panel, .login-box { min-width: 0; }

  /* Das Menue hing mit 'margin-left: auto' rechts am Kopf und war ab dem
     dritten Eintrag abgeschnitten -- auf dem Telefon kam man damit auf
     keine andere Seite mehr. Es bricht jetzt unter die Wortmarke. */
  header.top { flex-wrap: wrap; }
  header.top nav { margin-left: 0; width: 100%; flex-wrap: wrap; }

  /* Dasselbe eine Zeile tiefer: Zaehler und Knoepfe der Abschnittszeile
     standen rechts ausserhalb des Bildes. */
  .section-label { flex-wrap: wrap; }
  .reiter-leiste { flex-wrap: wrap; }

  /* Eine Domain oder uuid ohne Trennstelle ist breiter als ihr Achtel
     der Tabelle; die Tabelle wuchs darueber hinaus und schob die Seite
     nach rechts. Lieber eine hohe Tabelle als eine, deren letzte
     Spalten niemand sieht. */
  table.listing th, table.listing td {
    padding-left: calc(4 * var(--px)); padding-right: calc(4 * var(--px));
    overflow-wrap: break-word;
  }
  /* Nur was keine Trennstelle hat, darf irgendwo brechen: eine Domain,
     ein Imagename, eine uuid. Fuer Fliesstext waere es falsch -- der
     stand sonst als "Umgebun g von Pangu" da. */
  table.listing .mono, table.listing code { overflow-wrap: anywhere; }
  /* Feld und Knopf nebeneinander gaben der Spalte ihre Breite und
     schoben die Tabelle ueber den Rand; untereinander nicht mehr. */
  table.listing form { flex-wrap: wrap; }
  table.listing .feld-inline { min-width: 0; }

  /* Fingerbreit statt mauszeigerbreit, und genug Abstand, dass nicht der
     Nachbar getroffen wird. */
  .navlink { padding: calc(10 * var(--px)) calc(13 * var(--px)); }
  .action-row, .ikonzeile, .linkline, .product-window .foot { gap: calc(16 * var(--px)); }
  /* Die Unterzeile der Odoo-Seiten (Instanzen / Pakete / Varianten / ...)
     ist ein Flex ohne Umbruch und stand 44 px ueber dem Rand. */
  .linkline { flex-wrap: wrap; }

  /* Das Reglermenue haengt am Zeichen und oeffnet nach links; auf einem
     Telefon steht das Zeichen aber schon fast am linken Rand, und der
     Zettel lag zur Haelfte ausserhalb. Hier haengt er an der Kopfzeile
     und nimmt deren ganze Breite. */
  header.top { position: relative; }
  .kopfmenue { position: static; }
  .kopfmenue .menu-panel { left: 0; right: 0; min-width: 0; }

  /* Unter 16 px zoomt iOS beim Hineintippen und laesst die Seite
     verschoben zurueck. */
  .field input, .field select, .field textarea { font-size: 16px; }

  /* Die grosse Ueberschrift ist auf 75 Einheiten gesetzt, und
     "Einstellungen" wurde damit 418 px breit auf einer 359 px breiten
     Seite -- die Seite liess sich seitwaerts schieben. Sie waechst hier
     nur noch mit der Fensterbreite und darf trennen; 'anywhere' bleibt
     fuer den Namen ohne Trennstelle, etwa eine Instanz. */
  h1 { font-size: min(calc(75 * var(--px)), 9.5vw); overflow-wrap: anywhere; }

  /* Punktraster, Passermarken und die Randannotation zeigen den
     Achtelrhythmus des Satzspiegels. Wo alles untereinander steht,
     zeigen sie Striche -- und die Annotation klebte fest ueber dem
     Seitenfuss. */
  .bggrid, .crosses, .annotation { display: none; }
}

/* Auf den schmalsten Telefonen (320 px) passt auch die umgebrochene
   Tabelle nicht mehr -- ein Imagename und eine Domain nebeneinander sind
   breiter als die Zeile. Dann rollt sie lieber selbst, als die ganze
   Seite seitwaerts mitzunehmen.

   Die zweite Zeile ist noetig, weil eine Klasse mit eigener Anzeigeart
   gegen '[hidden]' gewinnt: ohne sie stuenden die Gruppen wieder da, die
   die Suche gerade ausgeblendet hat. Derselbe Fall wie bei
   '.nur-bei-auffrischen'. */
@media (max-width: 420px) {
  table.listing { display: block; overflow-x: auto; }
  table.listing[hidden] { display: none; }
}

/* -- Zustandsfarbe, zuletzt ------------------------------------------- */
/* Hier und nicht oben: .hint steht weiter oben mit derselben Spezifitaet,
   und damit gewann grau. Nicht auf einem Notizfeld: dort ist .bad der linke
   Rand, und der Rumpf behaelt seine eigene Farbe. */
.bad:not(.note) { color: var(--red); }
.warn:not(.note) { color: var(--orange); }

/* Reiter als Links: Seiten eines Bereichs (Mail), jede mit eigener Adresse.
   Gleiche Leiste wie die Radioreiter, der aktuelle sitzt auf der Linie. */
.reiter-leiste a {
  font-family: 'Geist Mono', ui-monospace, monospace;
  font-size: calc(12 * var(--px)); text-transform: uppercase;
  letter-spacing: calc(var(--ls-mono) * 1em);
  padding: calc(6 * var(--px)) calc(10 * var(--px));
  border: var(--border-solid); border-bottom: none;
  margin-bottom: -1px; color: var(--grey-text); text-decoration: none;
}
.reiter-leiste a:hover { color: var(--black); }
.reiter-leiste a.on { background: var(--white); color: var(--black); border-bottom: 1px solid var(--white); }
.reiter-leiste.seiten { margin: calc(10 * var(--px)) 0 calc(18 * var(--px)); }

/* Eine Mail-Instanz: Kopf mit Name und Stand, Fakten, unten die Knöpfe. */
.instanz { border: var(--border-solid); background: var(--white); padding: calc(14 * var(--px)); margin-bottom: calc(14 * var(--px)); }
.instanz-kopf { display: flex; flex-wrap: wrap; align-items: baseline; gap: calc(10 * var(--px)); margin-bottom: calc(8 * var(--px)); }
.instanz-kopf .name { font-family: 'Geist Mono', ui-monospace, monospace; font-size: calc(20 * var(--px)); }
.instanz-knoepfe { display: flex; flex-wrap: wrap; align-items: flex-start; gap: calc(10 * var(--px)); margin-top: calc(12 * var(--px)); }
.instanz-knoepfe form { display: inline; }
.instanz-knoepfe details[open] { flex-basis: 100%; }

/* Ressourcen eines Kunden zum Anhaken */
.wahl-liste { display: grid; grid-template-columns: repeat(auto-fill, minmax(calc(220 * var(--px)), 1fr)); gap: calc(4 * var(--px)) calc(16 * var(--px)); margin: calc(4 * var(--px)) 0 calc(8 * var(--px)); }
.wahl { display: flex; align-items: baseline; gap: calc(6 * var(--px)); flex-wrap: wrap; font-size: calc(14 * var(--px)); cursor: pointer; }
.wahl input { margin: 0; }
