Ein Feld an der App, kein zweites Datenmodell: Eine Kategorie besteht genau so lange, wie eine App sie traegt. Damit gibt es nichts anzulegen, nichts zu loeschen und keine zweite Reihenfolge, die mit der bestehenden aus dem Tritt geraten koennte. Die Reihenfolge der Ueberschriften ist die ihres ersten Auftretens in der Liste -- also ordnen dieselben Pfeile wie bisher beides. Am Rand einer Gruppe haengt der Pfeil die App in die Nachbargruppe um, statt zu tauschen: derselbe Knopf zum Sortieren und zum Umkategorisieren, und keine App kann zwischen zwei Gruppen liegen bleiben. Eingesammelt wird im Server, beim Schreiben wie beim Lesen. Das war nicht der erste Entwurf: Zuerst sortierte die Oberflaeche und die HoneyBar setzte ihre Ueberschriften beim Durchlaufen -- prompt stand eine App ohne Kategorie in der HoneyBar unter der letzten Ueberschrift und auf dem Schreibtisch ganz oben. Bei zwei Lesern derselben Liste gehoert die Reihenfolge dorthin, wo die Liste liegt. Ueberschriften erscheinen, wo man sucht: Kacheln, Schublade beider Leisten, Programme-Fenster. Nicht im App-Streifen (32 Pixel) und nicht bei den Schreibtischsymbolen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1454 lines
40 KiB
CSS
1454 lines
40 KiB
CSS
/*
|
|
* HoneyOS — Amber-CRT-Desktop.
|
|
*
|
|
* Farben laufen ausschließlich über die Phosphor-Variablen unten. Wer eine
|
|
* neue Röhre will, ergänzt einen [data-phosphor]-Block und fasst sonst nichts an.
|
|
*/
|
|
|
|
/* ── Phosphor ──────────────────────────────────────────────────────────── */
|
|
:root,
|
|
[data-phosphor="amber"] {
|
|
--p: #ffb641; /* Vollton — Text, Rahmen im Fokus */
|
|
--p-mid: #c8842a; /* halb — Sekundärtext */
|
|
--p-dim: #6b4718; /* schwach — Rahmen, Trennlinien */
|
|
--p-faint: #2a1c0c; /* Andeutung — Füllungen */
|
|
--bg: #0a0705;
|
|
--bg-raised: #140d07;
|
|
--glow: 0 0 6px rgba(255, 182, 65, 0.45);
|
|
}
|
|
[data-phosphor="green"] {
|
|
--p: #5cff8f;
|
|
--p-mid: #2fa85c;
|
|
--p-dim: #17512c;
|
|
--p-faint: #08200f;
|
|
--bg: #040803;
|
|
--bg-raised: #071206;
|
|
--glow: 0 0 6px rgba(92, 255, 143, 0.4);
|
|
}
|
|
[data-phosphor="ice"] {
|
|
--p: #cfe8ff;
|
|
--p-mid: #7fa6c4;
|
|
--p-dim: #395366;
|
|
--p-faint: #12202a;
|
|
--bg: #04070a;
|
|
--bg-raised: #0a1118;
|
|
--glow: 0 0 6px rgba(207, 232, 255, 0.35);
|
|
}
|
|
|
|
* {
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
/* Boot- und Desktop-Ebene tragen `display:flex` — das schlägt das
|
|
hidden-Attribut des Browsers, beide lägen sonst gleichzeitig da. */
|
|
[hidden] {
|
|
display: none !important;
|
|
}
|
|
|
|
html,
|
|
body {
|
|
height: 100%;
|
|
margin: 0;
|
|
}
|
|
|
|
body {
|
|
background: var(--bg);
|
|
color: var(--p);
|
|
font-family: ui-monospace, "SF Mono", "Cascadia Mono", "DejaVu Sans Mono", Menlo, Consolas, monospace;
|
|
font-size: 14px;
|
|
line-height: 1.5;
|
|
-webkit-font-smoothing: antialiased;
|
|
overflow: hidden;
|
|
}
|
|
|
|
/* ── Bildschirm + Effekte ──────────────────────────────────────────────── */
|
|
.crt {
|
|
position: fixed;
|
|
inset: 0;
|
|
display: flex;
|
|
flex-direction: column;
|
|
overflow: hidden;
|
|
/* Sanftes Glimmen aus der Mitte, wie eine aufgewärmte Röhre */
|
|
background:
|
|
radial-gradient(120% 90% at 50% 45%, color-mix(in srgb, var(--p) 7%, transparent), transparent 70%),
|
|
var(--bg);
|
|
text-shadow: var(--glow);
|
|
}
|
|
|
|
.scanlines,
|
|
.vignette,
|
|
.flicker {
|
|
position: absolute;
|
|
inset: 0;
|
|
pointer-events: none;
|
|
z-index: 90;
|
|
}
|
|
|
|
.scanlines {
|
|
background: repeating-linear-gradient(to bottom, rgba(0, 0, 0, 0.28) 0 1px, transparent 1px 3px);
|
|
opacity: 0.7;
|
|
}
|
|
|
|
.vignette {
|
|
background: radial-gradient(115% 105% at 50% 50%, transparent 55%, rgba(0, 0, 0, 0.75) 100%);
|
|
}
|
|
|
|
.flicker {
|
|
background: var(--p);
|
|
opacity: 0;
|
|
mix-blend-mode: overlay;
|
|
animation: flicker 7s infinite steps(1);
|
|
}
|
|
|
|
@keyframes flicker {
|
|
0%, 96%, 100% { opacity: 0; }
|
|
97% { opacity: 0.035; }
|
|
98% { opacity: 0; }
|
|
99% { opacity: 0.02; }
|
|
}
|
|
|
|
/* Wer die Effekte abschaltet, schaltet sie wirklich ab. */
|
|
[data-scanlines="off"] .scanlines,
|
|
[data-flicker="off"] .flicker {
|
|
display: none;
|
|
}
|
|
[data-glow="off"] .crt {
|
|
text-shadow: none;
|
|
}
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.flicker { animation: none; }
|
|
}
|
|
|
|
/* ── Boot ──────────────────────────────────────────────────────────────── */
|
|
.boot {
|
|
flex: 1;
|
|
padding: clamp(16px, 5vw, 56px);
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: flex-start;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.boot-log {
|
|
margin: 0;
|
|
font: inherit;
|
|
white-space: pre-wrap;
|
|
color: var(--p);
|
|
}
|
|
|
|
.boot-log .ok { color: var(--p); }
|
|
.boot-log .warn { color: var(--p-mid); }
|
|
.boot-log b { font-weight: 700; }
|
|
|
|
.boot-hint {
|
|
margin-top: auto;
|
|
color: var(--p-dim);
|
|
font-size: 12px;
|
|
}
|
|
|
|
.caret::after {
|
|
content: "\2588";
|
|
animation: blink 1s steps(1) infinite;
|
|
}
|
|
|
|
@keyframes blink {
|
|
50% { opacity: 0; }
|
|
}
|
|
|
|
/* ── Desktop ───────────────────────────────────────────────────────────── */
|
|
.desktop {
|
|
flex: 1;
|
|
display: flex;
|
|
flex-direction: column;
|
|
min-height: 0;
|
|
animation: warmup 0.5s ease-out;
|
|
}
|
|
|
|
@keyframes warmup {
|
|
from { opacity: 0; transform: scaleY(0.9); filter: brightness(2.5); }
|
|
to { opacity: 1; transform: none; filter: none; }
|
|
}
|
|
|
|
/* Menüleiste — Zwilling von honeybar.js */
|
|
.menubar {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
/* 8 px wie die HoneyBar, damit das Logo an derselben Stelle anfängt. */
|
|
padding: 0 8px;
|
|
/* 32 px — dieselbe Höhe wie honeybar.js in den Apps (BAR_H). Wer von einer
|
|
App auf den Schreibtisch wechselt, soll keinen Sprung sehen. */
|
|
border-bottom: 1px solid var(--p-dim);
|
|
background: var(--bg-raised);
|
|
/* 12 px wie in honeybar.js. Ohne das erbte die Leiste die 14 px des Körpers,
|
|
und weil nur das Logo direkt darin hängt (alles andere sitzt in .mb-right
|
|
oder trägt seine eigene Größe), stand ausgerechnet das HONEYOS größer da
|
|
als dasselbe Logo in den Apps. */
|
|
font-size: 12px;
|
|
padding-top: env(safe-area-inset-top);
|
|
height: calc(32px + env(safe-area-inset-top));
|
|
flex: 0 0 calc(32px + env(safe-area-inset-top));
|
|
}
|
|
|
|
.mb-logo {
|
|
background: none;
|
|
border: 0;
|
|
color: var(--p);
|
|
font: inherit;
|
|
letter-spacing: 0.14em;
|
|
cursor: pointer;
|
|
padding: 3px 9px 3px 2px;
|
|
white-space: nowrap;
|
|
}
|
|
.mb-logo b { font-weight: 400; color: var(--p-mid); }
|
|
/* Das Wappen bleibt gelb, während der Rest die Röhre wechselt: Ein Zeichen,
|
|
das die Farbe mitwechselt, ist ein Symbol wie „wolke" — eines, das seine
|
|
Farbe behält, ist ein Wappen. */
|
|
.mb-logo .hex { display: inline-block; width: 20px; height: 20px; vertical-align: -6px; }
|
|
.mb-logo .hex svg { display: block; width: 100%; height: 100%; }
|
|
|
|
/* Die Biene aus Schriftzeichen — im System-Fenster und über dem Startlauf.
|
|
Ein Zeichen ist halb so breit wie hoch, deshalb ist im Raster jeder Pixel
|
|
zwei Zeichen breit (siehe tools/biene.py). */
|
|
.biene-text {
|
|
margin: 0 0 8px;
|
|
color: var(--p);
|
|
font-family: inherit;
|
|
font-size: 9px;
|
|
line-height: 1.1;
|
|
overflow-x: auto;
|
|
}
|
|
.boot-biene { font-size: 11px; margin-bottom: 14px; }
|
|
|
|
.mb-apps {
|
|
display: flex;
|
|
gap: 4px;
|
|
overflow-x: auto;
|
|
scrollbar-width: none;
|
|
/* Wie in der HoneyBar: Bei vielen Apps schiebt man seitwärts, statt dass die
|
|
Namen zusammengequetscht werden. Der Schatten rechts zeigt, dass es
|
|
weitergeht. */
|
|
flex: 1 1 auto;
|
|
min-width: 0;
|
|
-webkit-overflow-scrolling: touch;
|
|
mask-image: linear-gradient(90deg, #000 calc(100% - 18px), transparent);
|
|
}
|
|
.mb-apps::-webkit-scrollbar { display: none; }
|
|
|
|
.mb-app {
|
|
flex: 0 0 auto;
|
|
background: none;
|
|
border: 1px solid transparent;
|
|
color: var(--p-mid);
|
|
font: inherit;
|
|
letter-spacing: 0.08em;
|
|
padding: 2px 9px;
|
|
cursor: pointer;
|
|
white-space: nowrap;
|
|
}
|
|
.mb-app:hover { color: var(--p); border-color: var(--p-dim); }
|
|
/* Symbol und Name in einer Zeile, wie in der HoneyBar. Das Symbol trägt die
|
|
Textfarbe, also stimmt es auch im umgekehrten Zustand der aktiven App. */
|
|
.mb-app { display: inline-flex; align-items: center; gap: 6px; }
|
|
.mb-ico,
|
|
.sm-ico { display: block; width: 12px; height: 12px; flex: 0 0 auto; }
|
|
.mb-ico svg,
|
|
.sm-ico svg { width: 12px; height: 12px; display: block; }
|
|
.mb-app[aria-current="true"] {
|
|
color: var(--bg);
|
|
background: var(--p);
|
|
border-color: var(--p);
|
|
text-shadow: none;
|
|
}
|
|
|
|
.mb-right {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
color: var(--p-mid);
|
|
}
|
|
.mb-clock { font-variant-numeric: tabular-nums; color: var(--p); }
|
|
|
|
.mb-btn {
|
|
background: none;
|
|
border: 1px solid var(--p-dim);
|
|
color: var(--p);
|
|
font: inherit;
|
|
line-height: 1;
|
|
padding: 3px 7px;
|
|
cursor: pointer;
|
|
}
|
|
.mb-btn:hover { background: var(--p-faint); }
|
|
|
|
/* Bühne */
|
|
.stage {
|
|
flex: 1;
|
|
min-height: 0;
|
|
overflow-y: auto;
|
|
padding: clamp(14px, 3vw, 32px);
|
|
display: grid;
|
|
gap: clamp(14px, 3vw, 28px);
|
|
grid-template-columns: minmax(0, 1fr);
|
|
align-content: start;
|
|
max-width: 1100px;
|
|
width: 100%;
|
|
margin: 0 auto;
|
|
}
|
|
|
|
@media (min-width: 860px) {
|
|
.stage {
|
|
grid-template-columns: 320px minmax(0, 1fr);
|
|
align-items: start;
|
|
}
|
|
/* Zwei Bereiche, keine Einzelplätze mehr: Links die Widgetspalte, rechts
|
|
die Apps. Vorher hatte jedes Widget seinen festen Platz im Raster — beim
|
|
dritten hätte man das Raster wieder anfassen müssen. */
|
|
.widgetspalte { grid-column: 1; }
|
|
.tiles { grid-column: 2; }
|
|
}
|
|
|
|
/* Fenster */
|
|
.win {
|
|
border: 1px solid var(--p-dim);
|
|
background: var(--bg-raised);
|
|
}
|
|
|
|
.win-bar {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: 8px;
|
|
padding: 3px 8px;
|
|
border-bottom: 1px solid var(--p-dim);
|
|
background: var(--p-faint);
|
|
font-size: 11px;
|
|
letter-spacing: 0.16em;
|
|
text-transform: uppercase;
|
|
color: var(--p-mid);
|
|
}
|
|
.win-dots { letter-spacing: 2px; opacity: 0.5; }
|
|
.win-close {
|
|
background: none;
|
|
border: 0;
|
|
color: var(--p);
|
|
font: inherit;
|
|
font-size: 16px;
|
|
line-height: 1;
|
|
cursor: pointer;
|
|
padding: 0 4px;
|
|
}
|
|
|
|
.win-body { padding: 14px; }
|
|
|
|
.statlist {
|
|
margin: 0;
|
|
display: grid;
|
|
grid-template-columns: auto 1fr;
|
|
gap: 3px 12px;
|
|
font-size: 12.5px;
|
|
}
|
|
.statlist dt { color: var(--p-dim); }
|
|
.statlist dd { margin: 0; color: var(--p-mid); text-align: right; font-variant-numeric: tabular-nums; }
|
|
.statlist dd.up { color: var(--p); }
|
|
.statlist dd.down { color: var(--p-mid); opacity: 0.6; }
|
|
|
|
/* App-Kacheln */
|
|
.tiles {
|
|
display: grid;
|
|
gap: clamp(12px, 2.5vw, 20px);
|
|
grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
|
|
align-content: start;
|
|
}
|
|
|
|
.tile {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 10px;
|
|
padding: 16px;
|
|
min-height: 168px;
|
|
border: 1px solid var(--p-dim);
|
|
background: var(--bg-raised);
|
|
color: var(--p);
|
|
font: inherit;
|
|
text-align: left;
|
|
text-decoration: none;
|
|
cursor: pointer;
|
|
position: relative;
|
|
transition: background 0.12s, border-color 0.12s, transform 0.12s;
|
|
}
|
|
.tile:hover,
|
|
.tile:focus-visible {
|
|
background: var(--p-faint);
|
|
border-color: var(--p);
|
|
transform: translateY(-2px);
|
|
outline: none;
|
|
}
|
|
.tile:active { transform: none; }
|
|
|
|
|
|
.tile-icon {
|
|
width: 46px;
|
|
height: 46px;
|
|
color: var(--p);
|
|
}
|
|
.tile-icon svg { display: block; width: 100%; height: 100%; }
|
|
|
|
.tile-name {
|
|
font-size: 16px;
|
|
letter-spacing: 0.16em;
|
|
}
|
|
.tile-sub {
|
|
font-size: 12px;
|
|
color: var(--p-mid);
|
|
margin-top: -6px;
|
|
}
|
|
|
|
.tile-state {
|
|
margin-top: auto;
|
|
font-size: 11px;
|
|
letter-spacing: 0.1em;
|
|
color: var(--p-dim);
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
}
|
|
.tile-state .led {
|
|
width: 7px;
|
|
height: 7px;
|
|
background: var(--p-dim);
|
|
border-radius: 50%;
|
|
}
|
|
.tile-state[data-state="up"] { color: var(--p); }
|
|
.tile-state[data-state="up"] .led { background: var(--p); box-shadow: var(--glow); }
|
|
.tile-state[data-state="down"] { color: var(--p-mid); }
|
|
.tile-state[data-state="down"] .led { background: transparent; border: 1px solid var(--p-mid); }
|
|
|
|
/* leerer Zustand */
|
|
.tile-add {
|
|
align-items: center;
|
|
justify-content: center;
|
|
color: var(--p-dim);
|
|
border-style: dashed;
|
|
min-height: 168px;
|
|
}
|
|
|
|
/* Statuszeile */
|
|
.statusbar {
|
|
flex: 0 0 auto;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
gap: 12px;
|
|
padding: 4px 10px;
|
|
padding-bottom: calc(4px + env(safe-area-inset-bottom));
|
|
border-top: 1px solid var(--p-dim);
|
|
background: var(--bg-raised);
|
|
color: var(--p-dim);
|
|
font-size: 11px;
|
|
letter-spacing: 0.06em;
|
|
}
|
|
.sb-right { color: var(--p-mid); white-space: nowrap; }
|
|
|
|
@media (max-width: 620px) {
|
|
.statusbar { display: none; }
|
|
|
|
/* Am Handy wird aus der Kachelwand eine Liste. Sechs Kacheln zu je 168 px
|
|
sind ein Bildschirm Gescrolle, bevor man die dritte App sieht — das Raster
|
|
ist für den grossen Schirm gedacht, hier zählt der Überblick.
|
|
Symbol links, Name und Zustand rechts, eine Zeile pro App. */
|
|
.tiles { grid-template-columns: minmax(0, 1fr); gap: 8px; }
|
|
.tile {
|
|
display: grid;
|
|
grid-template-columns: 40px minmax(0, 1fr) auto;
|
|
grid-template-areas: "symbol name zustand" "symbol unter zustand";
|
|
align-items: center;
|
|
column-gap: 12px;
|
|
row-gap: 0;
|
|
min-height: 0;
|
|
padding: 10px 12px;
|
|
}
|
|
.tile-icon { grid-area: symbol; width: 32px; height: 32px; }
|
|
.tile-name { grid-area: name; }
|
|
.tile-sub { grid-area: unter; }
|
|
.tile-state { grid-area: zustand; margin: 0; white-space: nowrap; }
|
|
}
|
|
|
|
/* ── Modal ─────────────────────────────────────────────────────────────── */
|
|
.modal {
|
|
position: absolute;
|
|
inset: 0;
|
|
z-index: 80;
|
|
display: grid;
|
|
place-items: center;
|
|
padding: 16px;
|
|
background: rgba(0, 0, 0, 0.65);
|
|
}
|
|
.modal[hidden] { display: none; }
|
|
|
|
.win-modal {
|
|
width: min(520px, 100%);
|
|
max-height: min(78vh, 640px);
|
|
display: flex;
|
|
flex-direction: column;
|
|
box-shadow: 0 0 0 1px var(--p-faint), 0 18px 60px rgba(0, 0, 0, 0.7);
|
|
}
|
|
.win-modal .win-body { overflow-y: auto; }
|
|
|
|
.field {
|
|
display: block;
|
|
margin-bottom: 16px;
|
|
}
|
|
.field > .label {
|
|
display: block;
|
|
font-size: 11px;
|
|
letter-spacing: 0.16em;
|
|
text-transform: uppercase;
|
|
color: var(--p-dim);
|
|
margin-bottom: 6px;
|
|
}
|
|
|
|
/* ── Einstellungen: Abschnitte statt einer langen Spalte ───────────────────
|
|
Beschriftung links, Schalter rechts. Bei zwölf Einstellungen untereinander
|
|
sucht man sonst; mit Überschriften weiß man, wo man ist. */
|
|
.sek { margin-bottom: 18px; }
|
|
.sek + .sek { border-top: 1px solid var(--p-faint); padding-top: 14px; }
|
|
.sek-titel {
|
|
margin: 0 0 10px;
|
|
font-size: 11px;
|
|
font-weight: 400;
|
|
letter-spacing: 0.18em;
|
|
text-transform: uppercase;
|
|
color: var(--p);
|
|
}
|
|
.sek-hinweis { margin: 8px 0 0; color: var(--p-dim); font-size: 11px; line-height: 1.4; }
|
|
.reihe {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: 10px;
|
|
margin-bottom: 7px;
|
|
}
|
|
.reihe .r-label { font-size: 12.5px; color: var(--p-mid); }
|
|
.reihe .seg { justify-content: flex-end; }
|
|
@media (max-width: 460px) {
|
|
.reihe { flex-direction: column; align-items: stretch; gap: 4px; }
|
|
.reihe .seg { justify-content: flex-start; }
|
|
}
|
|
|
|
/* Die Widget-Liste: an/aus, Name, Pfeile — dieselben Pfeile wie bei den Apps. */
|
|
.wl { list-style: none; margin: 0; padding: 0; }
|
|
.wl-zeile {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
border: 1px solid var(--p-faint);
|
|
padding: 5px 6px;
|
|
margin-bottom: 4px;
|
|
}
|
|
.wl-zeile.wl-aus .wl-name { color: var(--p-dim); }
|
|
.wl-an {
|
|
background: var(--p);
|
|
border: 1px solid var(--p);
|
|
color: var(--bg);
|
|
font: inherit;
|
|
font-size: 11px;
|
|
text-shadow: none;
|
|
padding: 2px 8px;
|
|
cursor: pointer;
|
|
flex: none;
|
|
width: 44px;
|
|
}
|
|
.wl-an[aria-pressed="false"] { background: none; border-color: var(--p-dim); color: var(--p-dim); text-shadow: inherit; }
|
|
.wl-name { flex: 1; min-width: 0; font-size: 13px; color: var(--p-mid); }
|
|
.wl-name em { font-style: normal; color: var(--p-dim); font-size: 11px; margin-left: 6px; }
|
|
.wl .ae-move { margin-left: 0; }
|
|
|
|
.seg { display: flex; flex-wrap: wrap; gap: 6px; }
|
|
.seg button {
|
|
background: none;
|
|
border: 1px solid var(--p-dim);
|
|
color: var(--p-mid);
|
|
font: inherit;
|
|
font-size: 12px;
|
|
padding: 4px 12px;
|
|
cursor: pointer;
|
|
}
|
|
.seg button:hover { border-color: var(--p); color: var(--p); }
|
|
.seg button[aria-pressed="true"] {
|
|
background: var(--p);
|
|
border-color: var(--p);
|
|
color: var(--bg);
|
|
text-shadow: none;
|
|
}
|
|
|
|
.field input[type="text"],
|
|
.field input[type="url"] {
|
|
width: 100%;
|
|
background: var(--bg);
|
|
border: 1px solid var(--p-dim);
|
|
color: var(--p);
|
|
font: inherit;
|
|
font-size: 13px;
|
|
padding: 6px 8px;
|
|
}
|
|
.field input:focus {
|
|
outline: none;
|
|
border-color: var(--p);
|
|
}
|
|
|
|
.url-row {
|
|
display: grid;
|
|
grid-template-columns: 88px 1fr;
|
|
gap: 8px;
|
|
align-items: center;
|
|
margin-bottom: 8px;
|
|
}
|
|
.url-row span { font-size: 12px; color: var(--p-mid); letter-spacing: 0.1em; }
|
|
|
|
.modal-actions {
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
gap: 8px;
|
|
margin-top: 18px;
|
|
padding-top: 12px;
|
|
border-top: 1px solid var(--p-faint);
|
|
}
|
|
.btn {
|
|
background: none;
|
|
border: 1px solid var(--p-dim);
|
|
color: var(--p);
|
|
font: inherit;
|
|
font-size: 12px;
|
|
letter-spacing: 0.1em;
|
|
padding: 5px 14px;
|
|
cursor: pointer;
|
|
}
|
|
.btn:hover { background: var(--p-faint); border-color: var(--p); }
|
|
.btn-primary { background: var(--p); border-color: var(--p); color: var(--bg); text-shadow: none; }
|
|
.btn-primary:hover { background: var(--p); filter: brightness(1.1); }
|
|
|
|
.about p { margin: 0 0 10px; color: var(--p-mid); font-size: 13px; }
|
|
.about code {
|
|
color: var(--p);
|
|
background: var(--p-faint);
|
|
padding: 1px 4px;
|
|
}
|
|
.keys {
|
|
display: grid;
|
|
grid-template-columns: auto 1fr;
|
|
gap: 4px 14px;
|
|
font-size: 12.5px;
|
|
margin-top: 12px;
|
|
}
|
|
.keys dt { color: var(--p); }
|
|
.keys dd { margin: 0; color: var(--p-mid); }
|
|
|
|
/* ── Desktop-Modus ─────────────────────────────────────────────────────────
|
|
* Dieselbe Röhre, andere Betriebsart: Symbole auf der Fläche, echte Fenster,
|
|
* Taskleiste unten. Die Menüleiste oben bleibt in beiden Modi dieselbe — sie
|
|
* ist die Klammer, die HoneyOS mit den Apps teilt.
|
|
*/
|
|
.deskspace {
|
|
flex: 1;
|
|
min-height: 0;
|
|
position: relative;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.desk-icons {
|
|
position: absolute;
|
|
inset: 0;
|
|
padding: 12px 8px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
flex-wrap: wrap;
|
|
align-content: flex-start;
|
|
gap: 2px;
|
|
}
|
|
|
|
.deskicon {
|
|
width: 94px;
|
|
padding: 8px 4px 6px;
|
|
text-align: center;
|
|
background: none;
|
|
border: 1px solid transparent;
|
|
color: var(--p);
|
|
font: inherit;
|
|
cursor: pointer;
|
|
}
|
|
.deskicon:hover { border-color: var(--p-dim); }
|
|
.deskicon:focus-visible { outline: 1px dotted var(--p); outline-offset: -3px; }
|
|
|
|
.di-glyph {
|
|
/* inline-Elemente ignorieren Breite und Höhe — ohne block wächst das SVG
|
|
auf seine Eigengröße und sprengt das Symbol. */
|
|
display: block;
|
|
width: 34px;
|
|
height: 34px;
|
|
margin: 0 auto 6px;
|
|
color: var(--p);
|
|
}
|
|
.di-glyph svg { display: block; width: 100%; height: 100%; }
|
|
|
|
.di-label {
|
|
display: inline-block;
|
|
font-size: 11.5px;
|
|
padding: 1px 4px;
|
|
letter-spacing: 0.06em;
|
|
}
|
|
|
|
.deskicon[data-sel="1"] { background: var(--p-faint); border-color: var(--p-dim); }
|
|
.deskicon[data-sel="1"] .di-label { background: var(--p); color: var(--bg); text-shadow: none; }
|
|
|
|
/* Erreichbarkeitslampe am Symbol */
|
|
.deskicon[data-app] .di-label::after { content: ""; }
|
|
.deskicon[data-state="down"] .di-glyph { opacity: 0.45; }
|
|
|
|
/* Fenster im Desktop-Modus */
|
|
.windows {
|
|
position: absolute;
|
|
inset: 0;
|
|
pointer-events: none;
|
|
}
|
|
|
|
.dwin {
|
|
position: absolute;
|
|
pointer-events: auto;
|
|
border: 1px solid var(--p-dim);
|
|
background: var(--bg-raised);
|
|
box-shadow: 0 12px 34px rgba(0, 0, 0, 0.55);
|
|
display: flex;
|
|
flex-direction: column;
|
|
max-height: calc(100% - 16px);
|
|
}
|
|
.dwin[data-focus="1"] { border-color: var(--p); }
|
|
.dwin[data-min="1"] { display: none; }
|
|
|
|
.dwin .win-bar {
|
|
cursor: grab;
|
|
touch-action: none;
|
|
user-select: none;
|
|
}
|
|
.dwin[data-drag="1"] .win-bar { cursor: grabbing; }
|
|
.dwin[data-focus="0"] .win-bar { color: var(--p-dim); }
|
|
|
|
.dwin .win-body {
|
|
overflow: auto;
|
|
min-height: 0;
|
|
}
|
|
|
|
.win-btns { display: flex; gap: 2px; }
|
|
.win-btn {
|
|
background: none;
|
|
border: 1px solid var(--p-dim);
|
|
color: var(--p);
|
|
font: inherit;
|
|
font-size: 10px;
|
|
line-height: 1;
|
|
padding: 1px 5px;
|
|
cursor: pointer;
|
|
}
|
|
.win-btn:hover { background: var(--p-faint); border-color: var(--p); }
|
|
|
|
/* Programme-Fenster */
|
|
.applist { display: flex; flex-direction: column; gap: 2px; }
|
|
.applist button {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
width: 100%;
|
|
background: none;
|
|
border: 1px solid transparent;
|
|
color: var(--p);
|
|
font: inherit;
|
|
font-size: 13px;
|
|
text-align: left;
|
|
padding: 5px 6px;
|
|
cursor: pointer;
|
|
}
|
|
.applist button:hover { background: var(--p-faint); border-color: var(--p-dim); }
|
|
.applist .al-glyph { width: 18px; height: 18px; flex: none; }
|
|
.applist .al-glyph svg { display: block; width: 100%; height: 100%; }
|
|
.applist .al-sub { margin-left: auto; color: var(--p-dim); font-size: 11px; }
|
|
|
|
/* Taskleiste */
|
|
.taskbar {
|
|
flex: 0 0 auto;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
padding: 3px 6px;
|
|
padding-bottom: calc(3px + env(safe-area-inset-bottom));
|
|
border-top: 1px solid var(--p-dim);
|
|
background: var(--bg-raised);
|
|
}
|
|
|
|
.task-start {
|
|
background: var(--p-faint);
|
|
border: 1px solid var(--p-dim);
|
|
color: var(--p);
|
|
font: inherit;
|
|
font-size: 11px;
|
|
letter-spacing: 0.16em;
|
|
padding: 3px 10px;
|
|
cursor: pointer;
|
|
flex: none;
|
|
}
|
|
.task-start:hover, .task-start[aria-expanded="true"] { background: var(--p); color: var(--bg); text-shadow: none; }
|
|
|
|
.task-list {
|
|
display: flex;
|
|
gap: 4px;
|
|
flex: 1;
|
|
overflow-x: auto;
|
|
scrollbar-width: none;
|
|
}
|
|
.task-list::-webkit-scrollbar { display: none; }
|
|
|
|
.task-btn {
|
|
background: none;
|
|
border: 1px solid var(--p-dim);
|
|
color: var(--p-mid);
|
|
font: inherit;
|
|
font-size: 11px;
|
|
padding: 3px 10px;
|
|
min-width: 96px;
|
|
max-width: 160px;
|
|
text-align: left;
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
cursor: pointer;
|
|
}
|
|
.task-btn:hover { color: var(--p); }
|
|
.task-btn[data-active="1"] { background: var(--p-faint); color: var(--p); border-color: var(--p); }
|
|
|
|
.task-date { color: var(--p-dim); font-size: 11px; white-space: nowrap; }
|
|
|
|
/* Startmenü */
|
|
.startmenu {
|
|
position: absolute;
|
|
left: 6px;
|
|
bottom: 4px;
|
|
min-width: 208px;
|
|
z-index: 70;
|
|
border: 1px solid var(--p);
|
|
background: var(--bg-raised);
|
|
padding: 4px;
|
|
display: none;
|
|
flex-direction: column;
|
|
gap: 1px;
|
|
box-shadow: 0 -8px 30px rgba(0, 0, 0, 0.6);
|
|
}
|
|
.startmenu[data-open="1"] { display: flex; }
|
|
/* Dasselbe Menü, nur andersherum aufgehängt: das Startmenü wächst aus der
|
|
Taskleiste nach oben, das Systemmenü aus der Menüleiste nach unten. */
|
|
.sysmenu {
|
|
top: calc(32px + env(safe-area-inset-top) + 2px);
|
|
bottom: auto;
|
|
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.6);
|
|
}
|
|
.mb-logo[aria-expanded="true"] { background: var(--p-faint); }
|
|
/* Das App-Menü hängt am Pfeil rechts — sonst dasselbe Feld. */
|
|
.appmenu {
|
|
top: calc(32px + env(safe-area-inset-top) + 2px);
|
|
bottom: auto;
|
|
left: auto;
|
|
right: 6px;
|
|
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.6);
|
|
}
|
|
|
|
/* Abmelden steht unten in den Einstellungen, im letzten Abschnitt: Es ist die
|
|
einzige Schaltfläche dort, die nicht etwas einstellt, sondern etwas beendet. */
|
|
.btn-out { width: 100%; color: var(--p-mid); margin-top: 10px; }
|
|
.btn-out:hover { color: var(--bg); background: var(--p); }
|
|
.startmenu .sm-head {
|
|
padding: 4px 8px;
|
|
font-size: 10px;
|
|
letter-spacing: 0.18em;
|
|
text-transform: uppercase;
|
|
color: var(--p-dim);
|
|
}
|
|
.startmenu button {
|
|
background: none;
|
|
border: 0;
|
|
color: var(--p-mid);
|
|
font: inherit;
|
|
font-size: 12.5px;
|
|
text-align: left;
|
|
padding: 6px 9px;
|
|
cursor: pointer;
|
|
/* Symbol links, Name daneben — in den Menüs stehen die Symbole immer. */
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
}
|
|
.startmenu button:hover { background: var(--p); color: var(--bg); text-shadow: none; }
|
|
.startmenu hr { border: 0; border-top: 1px solid var(--p-faint); margin: 3px 0; }
|
|
|
|
/* Die Schublade — der Zwilling der Schublade in honeybar.js. Symbol groß,
|
|
Name darunter, Untertitel als dritte Zeile: Wer sie aufmacht, sucht etwas,
|
|
und acht geteilte Pixelsymbole allein sagen dafür zu wenig. */
|
|
.appmenu { min-width: 318px; max-width: min(360px, calc(100vw - 12px)); }
|
|
/* minmax(0, 1fr): Ohne das darf eine lange Beschreibung ihre Spalte
|
|
auseinanderdrücken, und die Schublade wird breiter als der Schirm. */
|
|
.drawer { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 2px; }
|
|
.startmenu .drawer button.d-app {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
gap: 5px;
|
|
padding: 9px 4px;
|
|
text-align: center;
|
|
border: 1px solid transparent;
|
|
min-width: 0;
|
|
}
|
|
.startmenu .drawer .d-name,
|
|
.startmenu .drawer .d-sub { max-width: 100%; }
|
|
.startmenu .drawer .d-name { overflow: hidden; text-overflow: ellipsis; }
|
|
.startmenu .drawer button.d-app:hover {
|
|
background: none;
|
|
color: var(--p);
|
|
border-color: var(--p-dim);
|
|
text-shadow: var(--glow);
|
|
}
|
|
.d-ico { width: 24px; height: 24px; }
|
|
.d-ico svg { width: 24px; height: 24px; display: block; }
|
|
.d-name { letter-spacing: 0.08em; }
|
|
/* Umbrechen darf er, wachsen nicht — sonst stehen die Kacheln unterschiedlich
|
|
hoch und das Raster franst aus. */
|
|
.d-sub {
|
|
font-size: 10px;
|
|
line-height: 1.25;
|
|
color: var(--p-dim);
|
|
display: -webkit-box;
|
|
-webkit-line-clamp: 2;
|
|
-webkit-box-orient: vertical;
|
|
overflow: hidden;
|
|
}
|
|
|
|
@media (max-width: 620px) {
|
|
.task-btn { min-width: 0; }
|
|
.task-date { display: none; }
|
|
}
|
|
|
|
/* ── Anmeldung ─────────────────────────────────────────────────────────────
|
|
* Derselbe Bildschirm wie der Boot, nur endet er nicht von selbst. Wer nicht
|
|
* angemeldet ist, sieht vom Schreibtisch nichts — auch nicht die App-Liste.
|
|
*/
|
|
.login {
|
|
flex: 1;
|
|
display: flex;
|
|
flex-direction: column;
|
|
padding: clamp(16px, 5vw, 56px);
|
|
overflow: hidden;
|
|
}
|
|
|
|
/* Dasselbe Wappen wie in der Leiste, nur groß. Es schwebt ein wenig — sechs
|
|
Sekunden für zwei Pixel, also eher ein Atmen als eine Bewegung. Wer Bewegung
|
|
abgestellt hat, bekommt es ruhig. */
|
|
.login-biene {
|
|
display: block;
|
|
width: clamp(128px, 28vw, 176px);
|
|
height: auto;
|
|
margin: 22px 0 0;
|
|
image-rendering: pixelated;
|
|
animation: schweben 6s ease-in-out infinite;
|
|
}
|
|
@keyframes schweben {
|
|
50% { transform: translateY(-4px); }
|
|
}
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.login-biene { animation: none; }
|
|
}
|
|
|
|
.login-box {
|
|
margin-top: 20px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: flex-start;
|
|
gap: 12px;
|
|
}
|
|
|
|
.login-btn {
|
|
background: none;
|
|
border: 1px solid var(--p);
|
|
color: var(--p);
|
|
font: inherit;
|
|
font-size: 15px;
|
|
letter-spacing: 0.14em;
|
|
padding: 10px 22px;
|
|
cursor: pointer;
|
|
animation: pulse 2.4s ease-in-out infinite;
|
|
}
|
|
.login-btn:hover, .login-btn:focus-visible {
|
|
background: var(--p);
|
|
color: var(--bg);
|
|
text-shadow: none;
|
|
outline: none;
|
|
animation: none;
|
|
}
|
|
|
|
@keyframes pulse {
|
|
50% { box-shadow: 0 0 14px color-mix(in srgb, var(--p) 45%, transparent); }
|
|
}
|
|
|
|
.login-note {
|
|
margin: 0;
|
|
color: var(--p-dim);
|
|
font-size: 12px;
|
|
max-width: 52ch;
|
|
line-height: 1.6;
|
|
}
|
|
.login-note b { color: var(--p-mid); font-weight: 400; }
|
|
|
|
/* Nutzer in der HoneyBar */
|
|
|
|
/* ── App-Verwaltung ────────────────────────────────────────────────────── */
|
|
.apped { display: flex; flex-direction: column; gap: 10px; }
|
|
|
|
.approw {
|
|
border: 1px solid var(--p-dim);
|
|
background: var(--bg);
|
|
}
|
|
.approw > summary {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 9px;
|
|
padding: 7px 9px;
|
|
cursor: pointer;
|
|
list-style: none;
|
|
font-size: 13px;
|
|
}
|
|
.approw > summary::-webkit-details-marker { display: none; }
|
|
.approw[open] > summary { border-bottom: 1px solid var(--p-dim); background: var(--p-faint); }
|
|
.approw .ae-glyph { width: 18px; height: 18px; flex: none; }
|
|
.approw .ae-glyph svg { display: block; width: 100%; height: 100%; }
|
|
.approw .ae-url { margin-left: auto; color: var(--p-dim); font-size: 11px; max-width: 40%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
.approw .ae-body { padding: 10px; display: flex; flex-direction: column; gap: 8px; }
|
|
|
|
/* Sortieren, ohne die Zeile aufzumachen: Die Pfeile sitzen in der Kopfzeile.
|
|
Die Adresse rückt dafür ein Stück nach links (kein margin-left:auto mehr an
|
|
ihr allein, sondern hier). */
|
|
.approw .ae-move { margin-left: 8px; display: flex; gap: 2px; flex: none; }
|
|
.ae-arrow {
|
|
background: none;
|
|
border: 1px solid var(--p-dim);
|
|
color: var(--p-mid);
|
|
font: inherit;
|
|
font-size: 10px;
|
|
line-height: 1;
|
|
padding: 4px 6px;
|
|
cursor: pointer;
|
|
}
|
|
.ae-arrow:hover:not(:disabled) { background: var(--p); color: var(--bg); border-color: var(--p); text-shadow: none; }
|
|
.ae-arrow:disabled { opacity: 0.3; cursor: default; }
|
|
|
|
.ae-field { display: grid; grid-template-columns: 92px 1fr; gap: 8px; align-items: center; }
|
|
.ae-field > span { font-size: 11px; color: var(--p-dim); letter-spacing: 0.1em; }
|
|
.ae-field input, .ae-field select {
|
|
background: var(--bg-raised);
|
|
border: 1px solid var(--p-dim);
|
|
color: var(--p);
|
|
font: inherit;
|
|
font-size: 12.5px;
|
|
padding: 5px 7px;
|
|
min-width: 0;
|
|
}
|
|
.ae-field input:focus, .ae-field select:focus { outline: none; border-color: var(--p); }
|
|
/* Hinweise stehen unter ihrem Feld, bündig mit der Eingabe — nicht daneben. */
|
|
.ae-hint { margin: -4px 0 0 100px; color: var(--p-dim); font-size: 11px; }
|
|
|
|
@media (max-width: 520px) {
|
|
.ae-field { grid-template-columns: 1fr; gap: 3px; }
|
|
.ae-hint { margin-left: 0; }
|
|
}
|
|
|
|
.ae-actions { display: flex; gap: 6px; justify-content: flex-end; padding-top: 2px; }
|
|
.btn-danger { border-color: var(--p-dim); color: var(--p-mid); }
|
|
.btn-danger:hover { border-color: #d0563a; color: #ff7a5c; background: none; }
|
|
|
|
.apped-empty {
|
|
border: 1px dashed var(--p-dim);
|
|
padding: 18px;
|
|
text-align: center;
|
|
color: var(--p-dim);
|
|
font-size: 12.5px;
|
|
}
|
|
|
|
.saveline {
|
|
min-height: 16px;
|
|
font-size: 11.5px;
|
|
color: var(--p-mid);
|
|
}
|
|
.saveline[data-kind="err"] { color: #ff7a5c; }
|
|
|
|
/* ── Wetter ────────────────────────────────────────────────────────────────
|
|
Zweimal dasselbe Feld: als Fenster im Terminal-Modus, als kleines Schild
|
|
oben rechts auf dem Schreibtisch. Ein Aufbau, zwei Rahmen. */
|
|
.wx {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 12px;
|
|
}
|
|
.wx-glyph {
|
|
display: block;
|
|
width: 44px;
|
|
height: 44px;
|
|
flex: 0 0 44px;
|
|
color: var(--p);
|
|
}
|
|
.wx-glyph svg { width: 100%; height: 100%; display: block; }
|
|
.wx-text { display: flex; flex-direction: column; line-height: 1.25; min-width: 0; }
|
|
.wx-temp { font-size: 22px; color: var(--p); }
|
|
.wx-desc { color: var(--p-mid); }
|
|
.wx-city {
|
|
color: var(--p-dim);
|
|
font-size: 12px;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Schreibtisch-Modus: schwebendes Schild, rechts unter der Menüleiste. Nicht
|
|
verschiebbar wie ein Fenster — ein Widget, das man erst suchen muss, ist
|
|
keins. */
|
|
.deskwidget {
|
|
position: absolute;
|
|
top: 14px;
|
|
right: 14px;
|
|
z-index: 5;
|
|
padding: 10px 14px;
|
|
background: var(--bg);
|
|
border: 1px solid var(--p-faint);
|
|
box-shadow: 0 0 0 1px var(--bg), 4px 4px 0 rgba(0, 0, 0, 0.5);
|
|
}
|
|
@media (max-width: 620px) {
|
|
/* Am Handy stünde es über der Symbolspalte. */
|
|
.deskwidget { position: static; margin: 10px; }
|
|
}
|
|
|
|
/* Ortssuche in den Einstellungen */
|
|
.wx-city-row { display: flex; gap: 6px; margin-top: 8px; }
|
|
.wx-city-row input { flex: 1; min-width: 0; }
|
|
.wx-results { display: flex; flex-direction: column; gap: 2px; margin-top: 6px; }
|
|
.wx-hit {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
gap: 10px;
|
|
padding: 5px 8px;
|
|
background: transparent;
|
|
border: 1px solid transparent;
|
|
color: var(--p-mid);
|
|
font: inherit;
|
|
text-align: left;
|
|
cursor: pointer;
|
|
}
|
|
.wx-hit span { color: var(--p-dim); font-size: 12px; }
|
|
.wx-hit:hover { border-color: var(--p-faint); color: var(--p); }
|
|
|
|
/* Wetter in der Menüleiste — dasselbe Maß wie in honeybar.js, damit die
|
|
HoneyBar hier und die in den Apps nicht unterschiedlich aussehen. */
|
|
.mb-wx {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 5px;
|
|
color: var(--p-mid);
|
|
}
|
|
.mb-wx[hidden] { display: none; }
|
|
.mb-wx svg { width: 14px; height: 14px; display: block; }
|
|
@media (max-width: 700px) { .mb-wx-temp { display: none; } }
|
|
|
|
/* ── Wer angemeldet ist ────────────────────────────────────────────────────
|
|
Zwei Rahmen, ein Aufbau — Fenster im Terminal-Modus, Schild auf dem
|
|
Schreibtisch, genau wie beim Wetter. */
|
|
.uw { display: flex; align-items: center; gap: 12px; }
|
|
.uw-bild {
|
|
width: 40px;
|
|
height: 40px;
|
|
flex: 0 0 40px;
|
|
display: block;
|
|
border: 1px solid var(--p-dim);
|
|
object-fit: cover;
|
|
image-rendering: pixelated;
|
|
}
|
|
.uw-leer { color: var(--p-dim); padding: 4px; }
|
|
.uw-leer svg { width: 100%; height: 100%; display: block; }
|
|
.uw-text { display: flex; flex-direction: column; line-height: 1.3; min-width: 0; }
|
|
.uw-name { color: var(--p); font-size: 15px; }
|
|
.uw-gruss { color: var(--p-mid); }
|
|
.uw-host { color: var(--p-dim); font-size: 12px; }
|
|
/* Die Spalte selbst hält die Breite — vorher trug sie jedes Widget einzeln,
|
|
und ein neues ohne diese Zeile stand quer. */
|
|
.widgetspalte {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: clamp(14px, 3vw, 28px);
|
|
align-self: start;
|
|
min-width: 0;
|
|
}
|
|
@media (min-width: 860px) {
|
|
.widgetspalte { max-width: 320px; }
|
|
}
|
|
|
|
/* Die vier Zustände, die der Rahmen kennt. „lädt" und „nicht erreichbar"
|
|
stehen im selben Kasten wie der Inhalt — ein Widget, das bei einem Fehler
|
|
verschwindet, sieht aus wie eines, das man nie eingeschaltet hat. */
|
|
.w-zustand { color: var(--p-dim); margin: 0; font-size: 12.5px; }
|
|
.w-fehler { color: var(--p-mid); }
|
|
|
|
/* ── Notiz ─────────────────────────────────────────────────────────────────
|
|
* Gesetzt ist der Normalfall — roh ist nur die Zeile, in der man steht (und im
|
|
* Quelltext-Modus das ganze Feld). Beide sind gleich hoch, damit der Kasten
|
|
* beim Umschalten nicht springt. */
|
|
.notiz-text,
|
|
.notiz-feld {
|
|
min-height: 112px;
|
|
max-height: 320px;
|
|
overflow-y: auto;
|
|
}
|
|
.notiz-feld {
|
|
display: block;
|
|
width: 100%;
|
|
background: var(--bg);
|
|
border: 1px solid var(--p-dim);
|
|
color: var(--p);
|
|
font: inherit;
|
|
font-size: 13px;
|
|
line-height: 1.45;
|
|
padding: 8px;
|
|
resize: vertical;
|
|
}
|
|
.notiz-feld:focus { outline: none; border-color: var(--p); }
|
|
|
|
.notiz-text { font-size: 13px; line-height: 1.45; color: var(--p-mid); }
|
|
.notiz-text h3,
|
|
.notiz-text h4,
|
|
.notiz-text h5 {
|
|
margin: 10px 0 4px;
|
|
color: var(--p);
|
|
font-weight: 400;
|
|
letter-spacing: 0.08em;
|
|
text-transform: uppercase;
|
|
}
|
|
.notiz-text h3 { font-size: 13px; }
|
|
.notiz-text h4 { font-size: 12px; }
|
|
.notiz-text h5 { font-size: 11px; color: var(--p-mid); }
|
|
.notiz-text > :first-child { margin-top: 0; }
|
|
.notiz-text p { margin: 0 0 6px; }
|
|
.notiz-text ul,
|
|
.notiz-text ol { margin: 0 0 6px; padding-left: 18px; }
|
|
.notiz-text li { margin: 1px 0; }
|
|
.notiz-text code {
|
|
background: var(--p-faint);
|
|
padding: 0 3px;
|
|
color: var(--p);
|
|
}
|
|
.notiz-text b { color: var(--p); font-weight: 400; }
|
|
.notiz-text hr { border: 0; border-top: 1px solid var(--p-faint); margin: 8px 0; }
|
|
|
|
/* Häkchen: anklickbar, ohne in den Text zu springen. Die Aufzählungspunkte
|
|
fallen weg — das Kästchen ist der Punkt. */
|
|
.notiz-text .notiz-hak { list-style: none; margin-left: -18px; }
|
|
.notiz-text .notiz-hak label {
|
|
display: flex;
|
|
align-items: baseline;
|
|
gap: 7px;
|
|
cursor: pointer;
|
|
}
|
|
.notiz-text .notiz-hak input {
|
|
appearance: none;
|
|
flex: none;
|
|
width: 11px;
|
|
height: 11px;
|
|
border: 1px solid var(--p-dim);
|
|
background: var(--bg);
|
|
cursor: pointer;
|
|
position: relative;
|
|
top: 1px;
|
|
}
|
|
.notiz-text .notiz-hak input:checked { background: var(--p); border-color: var(--p); }
|
|
.notiz-text .notiz-hak.ab span { color: var(--p-dim); text-decoration: line-through; }
|
|
.notiz-text i { color: var(--p-mid); font-style: italic; }
|
|
|
|
/* Die Zeile, in der die Schreibmarke steht: als Feld, aber ohne wie eines
|
|
auszusehen. Sie soll an der Stelle sitzen, an der eben noch der gesetzte
|
|
Text stand — gleiche Schrift, gleiche Höhe, nur ein Streifen links zeigt,
|
|
dass hier gerade der Quelltext steht. */
|
|
.notiz-zeile {
|
|
display: block;
|
|
width: 100%;
|
|
box-sizing: border-box;
|
|
background: var(--p-faint);
|
|
border: 0;
|
|
border-left: 2px solid var(--p);
|
|
color: var(--p);
|
|
font: inherit;
|
|
font-size: 13px;
|
|
line-height: 1.45;
|
|
padding: 1px 4px 1px 6px;
|
|
margin: 1px 0;
|
|
resize: none;
|
|
overflow: hidden;
|
|
}
|
|
.notiz-zeile:focus { outline: none; }
|
|
.notiz-rohli { list-style: none; margin-left: -18px; }
|
|
.notiz-leer { cursor: text; }
|
|
|
|
/* Werkzeugleiste: klein, einreihig, immer da. Sie wirkt auf die Zeile, in der
|
|
man steht — deshalb steht sie oben und nicht neben dem Knopf zum Umschalten. */
|
|
.notiz-werkzeuge { display: flex; gap: 4px; margin-bottom: 6px; }
|
|
.notiz-wz {
|
|
background: none;
|
|
border: 1px solid var(--p-faint);
|
|
color: var(--p-mid);
|
|
font: inherit;
|
|
font-size: 12px;
|
|
line-height: 1;
|
|
width: 24px;
|
|
height: 22px;
|
|
cursor: pointer;
|
|
padding: 0;
|
|
}
|
|
.notiz-wz:hover:not(:disabled) { border-color: var(--p); color: var(--p); }
|
|
.notiz-wz:disabled { opacity: 0.35; cursor: default; }
|
|
.nw-fett { font-weight: 700; }
|
|
|
|
.w-fuss {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: 8px;
|
|
margin-top: 8px;
|
|
}
|
|
.w-stand { color: var(--p-dim); font-size: 11px; }
|
|
.w-fuss .btn { font-size: 12px; padding: 3px 9px; }
|
|
|
|
/* ── Bild ──────────────────────────────────────────────────────────────────
|
|
* Fester Rahmen, das Bild füllt ihn. Verzerren wäre die Alternative — und
|
|
* Zuschneiden von Hand ein eigenes Stück Arbeit. */
|
|
.bildw {
|
|
border: 1px solid var(--p-faint);
|
|
background: var(--bg);
|
|
aspect-ratio: 16 / 10;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
overflow: hidden;
|
|
}
|
|
.bildw-bild { width: 100%; height: 100%; object-fit: cover; display: block; }
|
|
.bildw .w-zustand { padding: 0 12px; text-align: center; }
|
|
|
|
/* Die Knöpfe stehen in den Einstellungen, nicht im Widget: links eine kleine
|
|
Vorschau, rechts was man damit tun kann. */
|
|
.bildset { display: flex; gap: 10px; align-items: flex-start; }
|
|
.bildset-vorschau {
|
|
flex: none;
|
|
width: 84px;
|
|
height: 56px;
|
|
border: 1px solid var(--p-faint);
|
|
background: var(--bg);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
overflow: hidden;
|
|
}
|
|
.bildset-bild { width: 100%; height: 100%; object-fit: cover; display: block; }
|
|
.bildset-leer { color: var(--p-dim); font-size: 11px; }
|
|
.bildset-rechts { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
|
|
.bildset-knoepfe { display: flex; gap: 4px; flex-wrap: wrap; }
|
|
.bildset-knoepfe .btn { font-size: 12px; padding: 3px 9px; }
|
|
|
|
.bildw-linkzeile { display: flex; gap: 6px; margin-top: 8px; }
|
|
.bildw-linkzeile input {
|
|
flex: 1;
|
|
min-width: 0;
|
|
background: var(--bg);
|
|
border: 1px solid var(--p-dim);
|
|
color: var(--p);
|
|
font: inherit;
|
|
font-size: 12px;
|
|
padding: 4px 6px;
|
|
}
|
|
.bildw-linkzeile input:focus { outline: none; border-color: var(--p); }
|
|
|
|
/* Einspaltig (Handy, schmales Fenster) sollen die Widgets so breit sein wie das
|
|
Systemfenster. Drei verschieden breite Kästen untereinander sehen aus wie ein
|
|
Fehler, nicht wie Absicht. Muss hinter den Regeln stehen, die es aufhebt —
|
|
eine Medienabfrage erhöht die Spezifität nicht. */
|
|
|
|
|
|
/* Die Schilder auf dem Schreibtisch stapeln sich oben rechts. */
|
|
.deskwidgets {
|
|
position: absolute;
|
|
top: 14px;
|
|
right: 14px;
|
|
z-index: 5;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 10px;
|
|
align-items: flex-end;
|
|
}
|
|
.deskwidgets .deskwidget { position: static; }
|
|
@media (max-width: 620px) {
|
|
.deskwidgets { position: static; align-items: stretch; margin: 10px; }
|
|
}
|
|
|
|
/* ── Kategorien ────────────────────────────────────────────────────────────
|
|
*
|
|
* Eine Überschrift je Gruppe, in derselben Sprache wie die übrigen Etiketten:
|
|
* klein, gesperrt, gedimmt. Sie soll die Kacheln gliedern, nicht mit ihnen um
|
|
* Aufmerksamkeit ringen.
|
|
*/
|
|
.tiles-kopf {
|
|
/* Bleibt ein Kind desselben Rasters und spannt über alle Spalten — ein
|
|
eigenes Raster je Gruppe hätte die Kacheln zweier Gruppen gegeneinander
|
|
verschoben. */
|
|
grid-column: 1 / -1;
|
|
margin: 6px 0 -4px;
|
|
font-size: 11px;
|
|
font-weight: normal;
|
|
letter-spacing: .18em;
|
|
text-transform: uppercase;
|
|
color: var(--p-dim);
|
|
}
|
|
.tiles-kopf:first-child { margin-top: 0; }
|
|
|
|
.applist .al-kopf {
|
|
padding: 8px 8px 3px;
|
|
font-size: 10px;
|
|
letter-spacing: .18em;
|
|
text-transform: uppercase;
|
|
color: var(--p-dim);
|
|
}
|
|
.applist .al-kopf:first-child { padding-top: 2px; }
|
|
|
|
/* Im Editor trägt die Überschrift die Pfeile für die ganze Gruppe. */
|
|
.ae-gruppe {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: 8px;
|
|
padding: 10px 4px 3px;
|
|
font-size: 10px;
|
|
letter-spacing: .18em;
|
|
text-transform: uppercase;
|
|
color: var(--p-dim);
|
|
}
|
|
.ae-gruppe:first-of-type { padding-top: 2px; }
|
|
|
|
/* Die Schublade ist ein Raster mit drei Spalten — die Überschrift spannt
|
|
darüber, sonst stünde sie als vierte Kachel neben den Apps. */
|
|
.drawer .d-kopf {
|
|
grid-column: 1 / -1;
|
|
padding: 7px 4px 1px;
|
|
font-size: 10px;
|
|
letter-spacing: .18em;
|
|
text-transform: uppercase;
|
|
color: var(--p-dim);
|
|
}
|
|
.drawer .d-kopf:first-child { padding-top: 0; }
|