Files
KantSites/public/assets/admin.css
T
kantarciandClaude Opus 5 d6d476177a
CMS quality / php (8.2) (push) Canceled after 0s
CMS quality / php (8.4) (push) Canceled after 0s
CMS quality / browser (push) Canceled after 0s
CMS quality / mysql (push) Canceled after 0s
Fassung 1.4.3: Update ohne Git, Verwaltung auf dem Telefon, eigene Symbole
Vier Wuensche und ein Fund beim Nachmessen.

- Farbwaehler im Designbereich. Das Textfeld bleibt massgeblich, damit
  "@akzent" ein Verweis auf die Palette bleibt und nicht beim ersten
  Klick zu einem festen Hexwert erstarrt (ADR 066).
- Die Verwaltung auf dem Telefon: das Menue klappt unter 760 px zu und
  nennt den Bereich, in dem man steht; Ziele 44 px, kein Skript.
- Eigene SVG-Symbole statt Unicode-Zeichen - ein Telefon ersetzt die
  sonst durch Emoji in fremdem Stil. Zwei Eintraege trugen dabei
  denselben Pfad; ein Test findet beides (ADR 067).
- Update aus dem Releasearchiv: der Weg fuer Installationen ohne Git.
  Zwei Schritte, weil ein Prozess, der sich selbst ausgetauscht hat,
  mit dem alten Code weiterarbeitet. var/, .env, hochgeladene
  Schriften und das erzeugte Buendel bleiben unberuehrt; public/ wird
  dazu Datei fuer Datei zusammengefuehrt. Geprueft ohne Netz gegen
  eine Releaseseite im Speicher (ADR 068).

Beim Nachmessen der echten Startseite statt einer Testseite: das
groesste Element ueber der Falz ist dort kein <img>, sondern der
Hintergrund des ersten Abschnitts - und der steht nur im Stylesheet.
Drei Vorabverweise mit denselben Geraetegrenzen wie der Compiler holen
genau die Variante, die die Regel auch nimmt. LCP 1,3 s -> 1,1 s.
Dabei gefunden: dasselbe Bild wurde je Geraeteregel neu abgefragt -
Startseite 19 -> 15 Abfragen (ADR 069).

Geprueft: 428 Tests auf PHP 8.2 und 8.4, Editor-, Browser- und
Linkpruefung, Lighthouse auf drei echten Seiten (alles ausser der
Leistung der Startseite 100).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-13 23:01:32 +02:00

691 lines
28 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* Administration: shared foundation and the management screens.
The editor has its own stylesheet (editor.css) that only the editor and the media page load. */
:root {
/* One family of greens. The sidebar is the dark end of it, so the administration reads as one
place instead of a set of forms. */
--ink: #1b2a24;
--muted: #5d6b64;
--line: #e2e7e1;
--paper: #fff;
--ground: #f3f5f1;
--shell: #16241e;
--shell-ink: #e7eee8;
--shell-muted: #9fb0a6;
--mint: #e5f0b6;
--accent: #2c6b4f;
--ring: #b55b12;
--danger: #8b2f22;
/* System fonts: nothing to download, and the administration looks native on the machine it
runs on. Google Fonts are for the website itself, where Umut picks them. */
font-family: "Segoe UI Variable Text", "Segoe UI", system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif;
color: var(--ink);
background: var(--ground);
font-synthesis: none;
}
* { box-sizing: border-box }
body { margin: 0 }
a { color: inherit; text-underline-offset: 4px }
button, input, select, textarea { font: inherit }
button, a, input, textarea, select { -webkit-tap-highlight-color: transparent }
button { cursor: pointer }
button:disabled { cursor: default; opacity: .48 }
button:focus-visible, a:focus-visible, input:focus-visible, select:focus-visible,
textarea:focus-visible, summary:focus-visible, iframe:focus-visible {
outline: 3px solid var(--ring);
outline-offset: 3px;
}
h1, h2, h3, p { margin-top: 0 }
h1 { font-size: 27px; font-weight: 650; letter-spacing: -.7px; line-height: 1.2; margin-bottom: 0 }
h2 { font-size: 17px; letter-spacing: -.3px }
h3 { font-size: 15px }
[hidden] { display: none !important }
.muted { color: var(--muted); line-height: 1.6 }
.eyebrow { font-size: 10px; font-weight: 700; letter-spacing: 1.7px; color: var(--accent); margin-bottom: 14px }
.footnote { font-size: 11px; color: var(--muted); margin: 34px 0 0 }
.count { font-size: 12px; font-weight: 600; color: var(--muted) }
.danger-text { color: var(--danger) }
.visually-hidden {
position: absolute; width: 1px; height: 1px; padding: 0;
overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}
.skip-link { position: fixed; top: -100px; left: 16px; z-index: 100; background: var(--ink); color: #fff; padding: 15px }
.skip-link:focus { top: 10px }
/* ---- fields ---------------------------------------------------------------------------- */
input, textarea, select {
width: 100%;
border: 1px solid #c3cec7;
border-radius: 8px;
background: var(--paper);
color: var(--ink);
padding: 10px 12px;
min-height: 42px;
}
input:hover, textarea:hover, select:hover { border-color: #a9b8af }
textarea { resize: vertical; min-height: 110px; line-height: 1.6 }
label { display: block; margin: 18px 0 7px; font-size: 13px; font-weight: 600 }
.field-help { font-size: 11px; line-height: 1.55; color: var(--muted); margin: 7px 0 0 }
.field-help code, .card code { background: #eef2ea; padding: 1px 5px; border-radius: 4px; font-size: .95em }
.check-label { display: flex; align-items: center; gap: 8px; font-weight: 500 }
.check-label input { width: 16px; min-height: 16px }
/* A grid of fields that becomes one column when there is no room. */
.fields { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 0 24px }
.fields > div > label:first-child, .field > label:first-child { margin-top: 14px }
/* ---- buttons --------------------------------------------------------------------------- */
.primary, .secondary, .subtle, .text-button {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 9px;
border: 1px solid var(--line);
border-radius: 8px;
padding: 10px 16px;
text-decoration: none;
font-size: 13px;
font-weight: 600;
background: var(--paper);
color: var(--ink);
white-space: nowrap;
min-height: 40px;
}
.primary { background: var(--accent); color: #fff; border-color: var(--accent) }
.primary:hover:not(:disabled) { background: #22553e }
.secondary:hover:not(:disabled) { background: #eef2ea; border-color: #cfd8d1 }
.subtle, .text-button { border-color: transparent; background: transparent }
.subtle:hover:not(:disabled) { background: #e8ede6 }
.text-button { padding: 4px 8px; min-height: 28px; font-size: 12px }
.full-width { width: 100% }
@media (prefers-reduced-motion: no-preference) {
button, a, summary { transition: background-color .12s, border-color .12s, color .12s }
}
/* ---- the shell: one sidebar, always the same, so every screen is one click away --------- */
.admin-shell { display: grid; grid-template-columns: 244px minmax(0, 1fr); min-height: 100dvh }
.shell-nav {
display: flex;
flex-direction: column;
gap: 4px;
padding: 20px 14px;
background: var(--shell);
color: var(--shell-ink);
position: sticky;
top: 0;
height: 100dvh;
overflow: auto;
}
.shell-nav .brand { color: #fff; margin: 4px 6px 22px }
.shell-nav .brand-icon { background: var(--mint); color: var(--shell) }
.nav-label {
font-size: 9px;
font-weight: 700;
letter-spacing: 1.6px;
color: var(--shell-muted);
margin: 18px 8px 7px;
}
.nav-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px }
.nav-item {
display: flex;
align-items: center;
gap: 11px;
padding: 9px 10px;
border-radius: 8px;
text-decoration: none;
font-size: 13px;
color: var(--shell-ink);
}
.nav-item:hover { background: #21362d }
.nav-item[aria-current=page] { background: #2b4a3b; color: #fff; font-weight: 650 }
.nav-item[aria-current=page] .nav-icon { color: var(--mint) }
.nav-icon { width: 18px; height: 18px; color: var(--shell-muted); flex-shrink: 0 }
.nav-out::after { content: '↗'; margin-left: auto; color: var(--shell-muted); font-size: 11px }
.shell-foot { margin-top: auto; padding-top: 20px; border-top: 1px solid #2a3d35; display: grid; gap: 6px }
.shell-user { display: flex; align-items: center; gap: 10px; padding: 8px 10px; font-size: 12px }
.shell-user strong { font-weight: 650; overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
.shell-avatar {
display: grid;
place-items: center;
width: 28px; height: 28px;
border-radius: 50%;
background: #2b4a3b;
color: var(--mint);
font-size: 12px;
font-weight: 700;
flex-shrink: 0;
}
.shell-foot form { margin: 0 }
.shell-foot button {
width: 100%;
justify-content: flex-start;
color: var(--shell-muted);
font-size: 12px;
font-weight: 500;
min-height: 34px;
padding: 6px 10px;
}
.shell-foot button:hover { background: #21362d; color: var(--shell-ink) }
.brand {
display: inline-flex;
align-items: center;
font-size: 22px;
font-weight: 700;
text-decoration: none;
letter-spacing: -1.1px;
gap: 2px;
}
.brand > span:last-child { font-weight: 400 }
.brand-icon {
display: grid;
place-items: center;
width: 31px; height: 31px;
background: var(--ink);
color: var(--mint);
border-radius: 9px;
margin-right: 7px;
font-size: 15px;
}
/* ---- the screen itself ----------------------------------------------------------------- */
.shell-main { min-width: 0; display: flex; flex-direction: column }
.shell-top {
display: flex;
align-items: flex-end;
justify-content: space-between;
gap: 20px 30px;
flex-wrap: wrap;
padding: 30px 38px 24px;
border-bottom: 1px solid var(--line);
background: var(--paper);
}
.shell-heading { min-width: 0 }
.shell-heading p { font-size: 13px; margin: 7px 0 0; max-width: 62ch }
.shell-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap }
.shell-body { padding: 30px 38px 60px; max-width: 1180px; width: 100% }
.stack { display: grid; gap: 20px }
.notice { padding: 13px 17px; border-radius: 8px; line-height: 1.6; font-size: 13px; margin: 0 }
.notice.ok { background: #edf3dc; color: #2c5340; border: 1px solid #c5d89a }
.error, .notice.error { background: #fff0eb; color: var(--danger); border: 1px solid #e2b2a7 }
.shell-body > .notice { margin-bottom: 4px }
/* ---- cards and sections ---------------------------------------------------------------- */
.card { background: var(--paper); border: 1px solid var(--line); border-radius: 12px }
.card-head {
display: flex;
align-items: baseline;
justify-content: space-between;
gap: 8px 20px;
flex-wrap: wrap;
padding: 19px 22px;
border-bottom: 1px solid var(--line);
}
.card-head h2, .card-head h3 { margin: 0 }
.card-head .muted { font-size: 12px }
.card-body { padding: 8px 22px 24px }
/* A heading for a group of rows, outside any card. */
.section-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px 20px; flex-wrap: wrap; margin: 16px 2px -6px }
.section-head h2 { margin: 0 }
.section-head .muted { font-size: 12px }
.card-body > p:first-child { margin-top: 14px }
.card-body .primary, .card-body .secondary { margin-top: 22px }
.card-foot { padding: 16px 22px; border-top: 1px solid var(--line); background: #fafbf8; border-radius: 0 0 12px 12px }
/* A card that opens: used for everything secondary, so a screen starts calm. */
details.card > summary {
padding: 17px 22px;
font-size: 13px;
font-weight: 650;
cursor: pointer;
border-radius: 12px;
list-style: none;
display: flex;
align-items: center;
gap: 10px;
}
details.card > summary::before { content: '+'; color: var(--accent); font-size: 16px; width: 12px }
details.card[open] > summary { border-bottom: 1px solid var(--line); border-radius: 12px 12px 0 0 }
details.card[open] > summary::before { content: '–' }
details.card > summary:hover { background: #fafbf8 }
/* ---- rows: one line per page, menu, area or file ---------------------------------------- */
.rows { display: grid; gap: 9px }
.row {
display: flex;
align-items: center;
gap: 14px;
flex-wrap: wrap;
padding: 14px 18px;
background: var(--paper);
border: 1px solid var(--line);
border-radius: 11px;
}
.row-top { align-items: flex-start }
/* A row that carries its own disclosure is a stack, not a line. */
.row-stack { display: block; padding: 0 }
.row-line { display: flex; align-items: center; gap: 14px; padding: 14px 18px; flex-wrap: wrap }
.row-icon {
display: grid;
place-items: center;
width: 38px; height: 38px;
border-radius: 9px;
background: #eef3e7;
color: var(--accent);
font-size: 17px;
flex-shrink: 0;
}
.row-main { flex: 1; min-width: 170px }
.row-main h3 { margin: 0; font-size: 14px; font-weight: 650 }
.row-main h3 a { text-decoration: none }
.row-main h3 a:hover { text-decoration: underline }
.row-main p { margin: 4px 0 0; font-size: 12px; color: var(--muted) }
.row-actions { display: flex; align-items: center; gap: 7px; flex-wrap: wrap }
.row-actions .secondary, .row-actions .text-button { font-size: 12px; padding: 8px 12px; min-height: 36px }
/* The hierarchy of the page tree. A class, not a style attribute: the administration forbids
inline styles, so an attribute would be dropped and the tree would look flat. */
.row.depth-1 { margin-left: 26px }
.row.depth-2 { margin-left: 52px }
.row.depth-3 { margin-left: 78px }
.pill {
font-size: 11px;
font-weight: 650;
padding: 5px 11px;
border-radius: 20px;
white-space: nowrap;
background: #eef2ea;
color: #4a5751;
}
.pill-live { background: #e7f0d6; color: #2c5340 }
.pill-draft { background: #fff2d9; color: #6f4e18 }
.pill-off { background: #f1f2f0; color: #5a635e }
/* The per-row settings. One disclosure that opens in place, instead of six competing popovers
that clip each other at the edge of the card. */
.sheet { border-top: 1px solid var(--line) }
.row > .sheet:first-of-type { border-top: 0 }
.sheet > summary {
list-style: none;
cursor: pointer;
padding: 11px 18px;
font-size: 12px;
font-weight: 600;
color: var(--muted);
display: flex;
align-items: center;
gap: 8px;
}
.sheet > summary::before { content: '⚙'; font-size: 13px }
.sheet > summary:hover { color: var(--ink); background: #fafbf8 }
.sheet[open] > summary { color: var(--ink); border-bottom: 1px solid var(--line) }
.sheet-body { padding: 4px 18px 22px; background: #fafbf8; border-radius: 0 0 11px 11px }
.sheet-body form { margin: 0 }
.sheet-part { padding-top: 14px; margin-top: 18px; border-top: 1px solid var(--line) }
.sheet-part:first-child { padding-top: 0; margin-top: 0; border-top: 0 }
.sheet-part > h4 { margin: 0; font-size: 12px; font-weight: 700; letter-spacing: .3px }
.sheet-part > p { font-size: 12px; line-height: 1.6; color: var(--muted); margin: 7px 0 0 }
.sheet-part .primary, .sheet-part .secondary { margin-top: 18px }
.sheet-actions { display: flex; gap: 8px; flex-wrap: wrap; align-items: center }
.sheet-actions form { margin: 0 }
/* ---- the media library, rendered as a page rather than fetched ------------------------- */
.library-grid {
list-style: none;
margin: 0;
padding: 0;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
gap: 14px;
}
.library-tile {
background: var(--paper);
border: 1px solid var(--line);
border-radius: 11px;
overflow: hidden;
display: flex;
flex-direction: column;
}
.library-tile > a { display: block; background: #eef1ed; line-height: 0 }
.library-tile img { width: 100%; height: 160px; object-fit: cover }
.library-body { padding: 12px 14px; display: grid; gap: 3px; flex: 1 }
.library-body strong { font-size: 13px; overflow-wrap: anywhere }
.library-body span { font-size: 11px }
.library-body code { font-size: 10px; color: var(--muted); overflow-wrap: anywhere; background: #f2f4f0; padding: 2px 5px; border-radius: 4px; justify-self: start }
.library-tile .sheet { margin-top: auto }
.library-tile .sheet > summary { padding: 9px 14px }
.library-tile .sheet-body { padding: 2px 14px 18px }
.library-tile .sheet-body label:first-of-type { margin-top: 12px }
/* The upload field: a drop area instead of the browser's file widget. The input itself stays a
real, focusable file input - the ring is drawn on the area via :focus-within. */
.dropzone {
position: relative;
border: 2px dashed #c3cec7;
border-radius: 12px;
background: #fafbf8;
margin-top: 8px;
}
.dropzone:hover { border-color: var(--accent); background: #f5f8f1 }
.dropzone.is-dragging { border-color: var(--accent); background: #eef4e3 }
.dropzone:focus-within { outline: 3px solid var(--ring); outline-offset: 3px }
.dropzone-label {
display: grid;
justify-items: center;
gap: 5px;
margin: 0;
padding: 30px 20px;
cursor: pointer;
text-align: center;
font-weight: 400;
}
.dropzone-label strong { font-size: 14px; font-weight: 650 }
.dropzone-icon { font-size: 24px; color: var(--accent); line-height: 1 }
.dropzone-hint { font-size: 12px; color: var(--muted) }
/* Hidden from sight, not from the keyboard or from assistive technology. */
.dropzone-input {
position: absolute;
width: 1px; height: 1px;
padding: 0;
opacity: 0;
inset-inline-start: 50%;
inset-block-start: 50%;
}
.dropzone-chosen { font-size: 12px; line-height: 1.55; color: var(--ink); margin: 10px 0 0 }
.pager { display: flex; align-items: center; justify-content: center; gap: 16px; flex-wrap: wrap; margin-top: 10px }
.pager .muted { font-size: 12px }
/* ---- tables ---------------------------------------------------------------------------- */
/* A table scrolls sideways instead of pushing the card out of the screen. As a block it also
stops stretching its columns to the full width. */
.table { display: block; overflow-x: auto; max-width: 100%; border-collapse: collapse; font-size: 13px }
.table th {
text-align: left;
font-size: 11px;
letter-spacing: .4px;
color: var(--muted);
padding: 0 10px 9px 0;
font-weight: 700;
white-space: nowrap;
}
.table td { padding: 5px 10px 5px 0; vertical-align: top }
.table tbody tr + tr td { border-top: 1px solid #eef1ed }
.table input, .table select { font-size: 12px; min-height: 38px; padding: 8px 10px }
.table .check-cell { text-align: center }
.table .check-cell input { width: 18px; min-height: 18px }
.table-new input, .table-new select { background: #fafbf8 }
.table form { margin: 0 }
/* Column widths per screen: the two tables carry different things. */
.menu-table td:first-child input { width: 82px }
.menu-table td:nth-child(2) select { width: 148px }
.menu-table td:nth-child(3) input { min-width: 170px }
.menu-table td:nth-child(4) select { width: 108px }
.menu-table td:nth-child(5) select { min-width: 190px }
.menu-table td:nth-child(6) input { width: 130px }
.menu-table td:nth-child(7) input { min-width: 190px }
.field-table td:first-child input { width: 140px }
.field-table td:nth-child(2) select { width: 150px }
.field-table td:nth-child(3) input { min-width: 170px }
.field-table td:nth-child(5) input { min-width: 180px }
.field-table td:nth-child(6) input { min-width: 170px }
.theme-table td input { width: 190px }
.theme-table td select { width: 150px }
.theme-table td input[type=color] { width: 52px }
.theme-table .weights-cell { white-space: nowrap }
.redirect-table td { padding: 8px 12px 8px 0; font-size: 12px }
/* Headings inside a card separate its parts without a second border. */
.card-body .section-head { margin: 28px 0 12px }
.card-body .section-head:first-child { margin-top: 14px }
.card-body > .primary, .card-body > .secondary { margin-top: 24px }
/* A screen made of several equal sections (menu slots, form definitions). */
.stack-section { display: grid; gap: 10px }
.menu-form > label:first-of-type, .form-def > label:first-of-type { margin-top: 16px }
.menu-form > input[name=name] { max-width: 420px }
.menu-form .table, .form-def .table { margin-top: 22px }
.menu-form .primary, .form-def .primary { margin-top: 20px }
.empty {
padding: 34px;
border: 1px dashed #cfd8d1;
border-radius: 12px;
background: var(--paper);
text-align: center;
}
.empty h3 { margin-bottom: 8px }
.empty p { margin: 0; font-size: 13px; color: var(--muted) }
/* ---- contrast hints on the design screen ----------------------------------------------- */
.contrast-note { margin: 14px 0 0; padding: 10px 12px; border-radius: 7px; font-size: 12px; line-height: 1.5; font-weight: 600 }
.contrast-ok { background: #edf3dc; color: #2c5340; border: 1px solid #c5d89a }
.contrast-warn { background: #fff6e2; color: #6f4e18; border: 1px solid #e6cf9c }
.contrast-bad { background: #fff0eb; color: var(--danger); border: 1px solid #e2b2a7 }
.theme-form .theme-swatch { width: 52px; min-height: 38px; padding: 2px; cursor: pointer }
.theme-form .weights-cell { white-space: nowrap }
.theme-form .weights-cell label { display: inline-flex; align-items: center; gap: 4px; margin: 0 9px 0 0; font-size: 11px; font-weight: 400 }
.theme-form .weights-cell input { width: 14px; min-height: 14px }
/* ---- submissions ----------------------------------------------------------------------- */
.submission-data { display: grid; grid-template-columns: auto 1fr; gap: 4px 16px; margin: 10px 0 0; font-size: 12px }
.submission-data dt { font-weight: 600; color: var(--muted) }
.submission-data dd { margin: 0; overflow-wrap: anywhere }
/* ---- login ----------------------------------------------------------------------------- */
.login-body {
min-height: 100dvh;
display: grid;
place-items: center;
background: radial-gradient(ellipse at 20% 0%, #dfeab0, transparent 60%), var(--ground);
padding: 30px;
}
.login-card {
width: 100%;
max-width: 430px;
padding: 40px;
background: var(--paper);
border: 1px solid var(--line);
border-radius: 16px;
box-shadow: 0 20px 60px #1b2a2411;
}
.login-card .brand { margin-bottom: 38px }
.login-card h1 { font-size: 26px }
.login-card .muted { font-size: 14px; margin-top: 8px }
.login-card .primary { margin-top: 26px }
.login-card .notice { margin: 22px 0 0 }
.quiet-link { display: block; font-size: 12px; text-align: center; margin-top: 24px; color: var(--muted) }
/* ---- narrow screens: the sidebar becomes a strip above the content --------------------- */
@media (max-width: 1000px) {
.admin-shell { grid-template-columns: 1fr }
.shell-nav {
position: static;
height: auto;
flex-direction: row;
align-items: center;
flex-wrap: nowrap;
overflow-x: auto;
gap: 6px;
padding: 11px 14px;
}
.shell-nav .brand { margin: 0 10px 0 0; font-size: 0 }
.shell-nav .brand-icon { margin: 0; font-size: 15px }
.nav-label { display: none }
.nav-list { display: flex; gap: 4px }
.nav-item { white-space: nowrap; padding: 8px 12px }
.shell-foot { margin: 0 0 0 auto; padding: 0 0 0 14px; border-top: 0; border-left: 1px solid #2a3d35; display: flex; align-items: center }
.shell-user strong { display: none }
.shell-foot button { width: auto }
.shell-top { padding: 22px 20px 18px }
.shell-body { padding: 20px 20px 48px }
}
@media (max-width: 620px) {
h1 { font-size: 23px }
.row-line { padding: 13px 14px; gap: 10px }
.row-actions { width: 100%; justify-content: flex-start }
.card-head, .sheet > summary { padding-inline: 16px }
.card-body, .sheet-body { padding-inline: 16px }
.row.depth-1, .row.depth-2, .row.depth-3 { margin-left: 14px }
.login-card { padding: 26px }
.login-body { padding: 16px }
}
/* A group of related checkboxes needs a name of its own, not just a label per box. */
.field-set { border: 1px solid var(--line); border-radius: 10px; padding: 4px 16px 16px; margin: 18px 0 0 }
.field-set > legend { font-size: 12px; font-weight: 700; padding: 0 6px }
.field-set .check-label { margin-top: 14px }
/* ---- statistics: charts drawn by the server, styled by class ---------------------------- */
.range-switch { display: flex; gap: 8px; flex-wrap: wrap }
.range-switch a { font-size: 12px; padding: 8px 14px; min-height: 36px }
.chart { display: block; width: 100%; height: 180px; overflow: visible }
.chart-bar { fill: var(--accent) }
.chart-bar:hover { fill: #1c4735 }
.chart-axis { stroke: var(--line); stroke-width: 1 }
.chart-legend { display: flex; justify-content: space-between; margin: 8px 0 0; font-size: 11px; color: var(--muted) }
.chart-table { margin-top: 18px }
.chart-table > summary { cursor: pointer; font-size: 12px; font-weight: 600; padding: 6px 0 }
.table-wrap { max-height: 320px; overflow: auto; margin-top: 10px }
.stats-columns { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 16px }
.stats-list { list-style: none; margin: 14px 0 0; padding: 0; display: grid; gap: 2px; counter-reset: rank }
.stats-list li {
display: flex;
align-items: baseline;
justify-content: space-between;
gap: 12px;
padding: 8px 0;
border-top: 1px solid #eef1ed;
font-size: 13px;
}
.stats-list li:first-child { border-top: 0 }
.stats-list span, .stats-list a { overflow-wrap: anywhere; min-width: 0 }
.stats-list strong { font-variant-numeric: tabular-nums; white-space: nowrap }
/* ---- system: preflight, update steps, log ---------------------------------------------- */
.facts { display: grid; grid-template-columns: auto 1fr; gap: 8px 20px; margin: 14px 0 0; font-size: 13px }
.facts dt { color: var(--muted) }
.facts dd { margin: 0; overflow-wrap: anywhere }
.check-list { list-style: none; margin: 14px 0 0; padding: 0; display: grid; gap: 10px; font-size: 13px; line-height: 1.55 }
.check-list li { display: flex; gap: 11px; align-items: flex-start }
.check-mark {
display: grid;
place-items: center;
width: 20px; height: 20px;
border-radius: 50%;
flex-shrink: 0;
font-size: 12px;
font-weight: 700;
}
.check-ok .check-mark { background: #e7f0d6; color: #2c5340 }
.check-bad .check-mark { background: #fff0eb; color: var(--danger) }
.check-bad { color: var(--danger) }
.log-list { list-style: none; margin: 14px 0 0; padding: 0; display: grid; gap: 6px }
.log-list code { font-size: 11px; overflow-wrap: anywhere }
.shell-version { margin: 0 0 4px; padding: 0 10px; font-size: 10px; color: var(--shell-muted) }
/* ---- the installer: six screens on an otherwise empty server ---------------------------- */
.install-body {
min-height: 100dvh;
display: grid;
place-items: start center;
background: radial-gradient(ellipse at 20% 0%, #dfeab0, transparent 60%), var(--ground);
padding: 40px 20px 60px;
}
.install-shell { width: 100%; max-width: 640px }
.install-shell .card { margin-top: 18px }
.install-shell h1 { font-size: 24px }
.install-shell form { margin-top: 4px }
.install-shell .sheet-actions { margin-top: 24px }
.install-shell h2 { font-size: 15px; margin: 30px 0 0 }
/* The step list is the only orientation there is: no navigation exists yet. */
.install-steps {
list-style: none;
margin: 14px 0 0;
padding: 0;
display: flex;
flex-wrap: wrap;
gap: 6px 16px;
font-size: 12px;
color: var(--muted);
}
.install-steps li { display: flex; align-items: center; gap: 7px }
.install-steps .current { color: var(--ink); font-weight: 700 }
.install-step-number {
display: grid;
place-items: center;
width: 19px; height: 19px;
border-radius: 50%;
background: #e4e9df;
font-size: 11px;
font-weight: 700;
}
.install-steps .current .install-step-number { background: var(--accent); color: #fff }
.install-steps .done .install-step-number { background: #e7f0d6; color: #2c5340 }
/* A finding that is worth saying but does not block anything. */
.check-warn .check-mark { background: #f3f0e2; color: #6b6550 }
.button-link { text-decoration: none }
.install-details { margin-top: 18px; border: 1px solid var(--line); border-radius: 10px; padding: 0 16px 16px }
.install-details > summary { padding: 14px 0; font-size: 13px; font-weight: 600; cursor: pointer }
.install-details[open] > summary { border-bottom: 1px solid var(--line); margin-bottom: 6px }
.favicon-field{display:flex;align-items:center;gap:12px}
.favicon-field select{flex:1}
.favicon-preview{border-radius:6px;background:#fff;box-shadow:0 0 0 1px rgba(0,0,0,.12)}
.color-field { display: flex; gap: 8px; align-items: center }
.color-field input[type="text"], .color-field > input:not([type="color"]) { flex: 1; min-width: 0 }
.color-field-swatch { width: 46px; min-height: 38px; padding: 2px; flex: 0 0 auto; cursor: pointer }
.color-field-palette { flex: 0 0 auto; max-width: 40% }
/* Die Verwaltung auf dem Telefon.
Bis 1000px stand die Navigation als waagerechte Wischleiste da - zwei Listen untereinander,
also zwei Zeilen, und der letzte Eintrag ausserhalb des Bildes. Auf einem Telefon ist ein
Klappmenue ehrlicher: eine Zeile im Ruhezustand, aufgeklappt die vollstaendige Liste mit
Flaechen, die ein Daumen trifft. Das details-Element macht das ohne Skript. */
.shell-menu > summary { display: none }
@media (max-width: 760px) {
.shell-nav { flex-wrap: wrap; padding: 10px 14px; gap: 10px; overflow: visible }
.shell-menu { flex: 1 1 100%; order: 3 }
.shell-menu > summary {
display: flex; align-items: center; gap: 10px; list-style: none; cursor: pointer;
min-height: 44px; padding: 0 14px; border-radius: 10px;
background: #ffffff14; color: #fff; font-weight: 600; font-size: 15px;
}
.shell-menu > summary::-webkit-details-marker { display: none }
.shell-menu > summary:focus-visible { outline: 3px solid var(--mint); outline-offset: 2px }
.shell-menu-icon { font-size: 17px }
.shell-menu[open] > summary { margin-bottom: 8px }
.shell-menu nav { display: block }
.shell-menu:not([open]) nav { display: none }
.nav-label { display: block; margin: 12px 4px 6px; font-size: 11px; letter-spacing: 1.4px; color: #9db3a8 }
.nav-list { display: grid; gap: 2px }
/* Vierundvierzig Pixel: die Flaeche, die ein Daumen zuverlaessig trifft. */
.nav-item { min-height: 44px; display: flex; align-items: center; gap: 12px; padding: 10px 14px; white-space: normal }
.shell-foot { margin-left: auto; border-left: 0; padding-left: 0; gap: 10px }
.shell-version { display: none }
.shell-user strong { display: none }
}