diff --git a/CloudronManifest.json b/CloudronManifest.json index d9a8cd8..0ef0fba 100644 --- a/CloudronManifest.json +++ b/CloudronManifest.json @@ -3,7 +3,7 @@ "title": "Sendewerk", "description": "Redaktionelle Planung und Durchführung von heinzlive-Sendungen.", "tagline": "Vom Fundstück bis zur Livesendung", - "version": "0.1.0", + "version": "0.1.1", "healthCheckPath": "/healthz", "httpPort": 3000, "addons": { diff --git a/docs/ACCEPTANCE.md b/docs/ACCEPTANCE.md index 82c34f6..33ec8b7 100644 --- a/docs/ACCEPTANCE.md +++ b/docs/ACCEPTANCE.md @@ -2,18 +2,19 @@ ## Etappe 1 -| Kriterium | Nachweis | Stand | -| ------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | ---------------------------- | -| Frischer Checkout startet ohne Cloudron | `npm ci` erfolgreich; README-Setup und lokaler Produktionsstart ausgeführt | erfüllt am 21.10.2026 | -| Typprüfung und Build erfolgreich | `npm run check`, `npm run build` | erfüllt am 21.10.2026 | -| Theme bleibt nach Neuladen erhalten | Playwright: System auf Hell wechseln, Reload, DOM und Schalterzustand prüfen | erfüllt am 21.10.2026 | -| Testdaten überleben Neustart | Gebauten Server zweimal gegen `.data/sendewerk.sqlite` gestartet; Fundusdaten und `/healthz` jeweils vorhanden | erfüllt am 21.10.2026 | -| Migration wiederholt ausführbar | lokal mehrfach ausgeführt; Verhaltenstest führt Migration zweimal in temporärer DB aus | erfüllt am 21.10.2026 | -| Seed reproduzierbar | lokal und im Verhaltenstest zweimal ausgeführt; danach 4 Pieces, 1 Sendung und 3 Verwendungen | erfüllt am 21.10.2026 | -| Tests verwenden getrennte Daten | Vitest und Playwright erzeugen je eigene Datenbank im Betriebssystem-Tempdir | erfüllt am 21.10.2026 | -| Desktop und Smartphone ohne horizontales Scrollen | 4 Playwright-Abläufe; 1440x1000, 1280x900 und 390x844; Screenshots visuell kontrolliert | erfüllt am 21.10.2026 | -| Cloudron-Pfade und Healthcheck vorbereitet | Manifestpfad `/app/data/sendewerk.sqlite`, `/healthz`, `start.sh`; JSON-Kernfelder und Bash-Syntax geprüft | vorbereitet; Container offen | -| Echte Cloudron-Prüfung | Installation, Backup/Restore, Proxy und read-only Laufzeit | offen, kein Serverzugang | +| Kriterium | Nachweis | Stand | +| ------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | ---------------------------- | +| Frischer Checkout startet ohne Cloudron | `npm ci` erfolgreich; README-Setup und lokaler Produktionsstart ausgeführt | erfüllt am 21.10.2026 | +| Typprüfung und Build erfolgreich | `npm run check`, `npm run build` | erfüllt am 21.10.2026 | +| Theme bleibt nach Neuladen erhalten | Playwright: System auf Hell wechseln, Reload, DOM und Schalterzustand prüfen | erfüllt am 21.10.2026 | +| Testdaten überleben Neustart | Gebauten Server zweimal gegen `.data/sendewerk.sqlite` gestartet; Fundusdaten und `/healthz` jeweils vorhanden | erfüllt am 21.10.2026 | +| Migration wiederholt ausführbar | lokal mehrfach ausgeführt; Verhaltenstest führt Migration zweimal in temporärer DB aus | erfüllt am 21.10.2026 | +| Seed reproduzierbar | lokal und im Verhaltenstest zweimal ausgeführt; danach 4 Pieces, 1 Sendung und 3 Verwendungen | erfüllt am 21.10.2026 | +| Tests verwenden getrennte Daten | Vitest und Playwright erzeugen je eigene Datenbank im Betriebssystem-Tempdir | erfüllt am 21.10.2026 | +| Desktop und Smartphone ohne horizontales Scrollen | 8 Playwright-Abläufe bei 390, 768, 960, 1280 und 1440 Pixeln; Screenshots visuell kontrolliert | erfüllt am 21.10.2026 | +| Kompakte Arbeitsoberfläche in beiden Farbmodi | 390, 768 und 1440 Pixel jeweils in Light/Dark; einspaltige Mobilkarten, lange Titel, Metadatenumbrüche und Leerzustände | erfüllt am 21.10.2026 | +| Cloudron-Pfade und Healthcheck vorbereitet | Manifestpfad `/app/data/sendewerk.sqlite`, `/healthz`, `start.sh`; JSON-Kernfelder und Bash-Syntax geprüft | vorbereitet; Container offen | +| Echte Cloudron-Prüfung | Installation, Backup/Restore, Proxy und read-only Laufzeit | offen, kein Serverzugang | ## Ausgeführte Prüfungen @@ -23,7 +24,9 @@ - `npm run lint`: erfolgreich - `npm run check`: 0 Fehler und 0 Warnungen - `npm run build`: erfolgreich mit `@sveltejs/adapter-node` -- `npm run test:e2e`: 4 von 4 Browsertests erfolgreich +- `npm run test:e2e`: 8 von 8 Browsertests erfolgreich; 390, 768 und 1440 Pixel + jeweils in Light- und Darkmode sowie Tastaturbedienung, feste Navigation, + einspaltige Funduskarten, lange Inhalte und Überläufe geprüft - Zwei getrennte `npm start`-Läufe: Healthcheck und persistente Daten erfolgreich - `bash -n start.sh` und programmatische Manifest-Kernfeldprüfung: erfolgreich diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index f8bb81c..4fb1976 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -66,8 +66,12 @@ getrennt. ## Oberflächenstruktur Die Hauptnavigation umfasst Eingang, Fundus, Sendungen, Archiv und Verwaltung. -Auf breiten Ansichten stehen Fundus und Ablauf nebeneinander. Auf schmalen -Ansichten werden sie über eine gut erreichbare Umschaltung einzeln gezeigt. +Auf dem Desktop bleibt eine feste Seitenleiste sichtbar; Verwaltung liegt an +ihrem unteren Ende. Bis einschließlich `52rem` ersetzen eine obere Leiste und +die untere Hauptnavigation die Seitenleiste vollständig. Auf breiten Ansichten +stehen Fundus und Ablauf nebeneinander. Bis einschließlich `72rem` werden sie +über eine gut erreichbare Umschaltung einzeln gezeigt, damit auch schmale +Desktopfenster ohne horizontalen Überlauf bedienbar bleiben. Der Live-Modus ist eine eigene, fokussierte Ansicht; die spätere Präsentationsausgabe erhält eine separate, strikt reduzierte Datenansicht. diff --git a/docs/DECISIONS.md b/docs/DECISIONS.md index 7fce92a..752ad8d 100644 --- a/docs/DECISIONS.md +++ b/docs/DECISIONS.md @@ -81,3 +81,16 @@ Vorschauseiten lesen echte persistente SQLite-Seed-Daten, bieten aber keine funktionslosen Speichern- oder Live-Schaltflächen. Ein sichtbarer Hinweis grenzt Gestaltungsvorschauen von den späteren Fachfunktionen ab. Damit wird keine noch nicht implementierte Funktion als fertig dargestellt. + +## D-007: Arbeitsansicht nach verfügbarem Platz + +Die feste Desktop-Seitenleiste wird bis `52rem` verwendet und dann vollständig +durch mobile Kopf- und Fußnavigation ersetzt. Der Sendungsbau schaltet bereits +bis `72rem` von zwei Spalten auf eine bedienbare Pane-Umschaltung um. Dadurch +bleibt die Desktopnavigation in schmalen Fenstern erhalten, ohne Fundus und +Ablauf zusammenzudrücken. + +Der Fundus erscheint auf dem Desktop als kompakte Liste und auf kleinen +Bildschirmen als Kartenfolge. Vorschau- und Schreibschutzinformationen sind in +einem nativen, tastaturbedienbaren `details`-Element gebündelt. Diese +Darstellungsentscheidung ändert weder Datenmodell noch Funktionsumfang. diff --git a/docs/STATUS.md b/docs/STATUS.md index 35c52a2..7a9c63e 100644 --- a/docs/STATUS.md +++ b/docs/STATUS.md @@ -13,6 +13,8 @@ lokaler Betriebsweg sind dokumentiert. Etappe 2 wurde nicht begonnen. - persistentes Light-/Dark-/System-Theme - responsive Navigation und gekennzeichnete Vorschauen für Fundus, Sendungsbau und Live-Modus +- kompakte Desktop-Arbeitsansicht mit fester Seitenleiste, Fundusliste und + zweigeteiltem Sendungsbau; auf schmalen Ansichten Umschaltung statt Engpass - Healthcheck, Produktionsstart und frühes Cloudron-Paket - getrennte Unit-/Integrations- und Browser-Testdaten @@ -20,6 +22,18 @@ Die Vorschauen lesen echte Daten aus SQLite. Suche und mobile Pane-Umschaltung funktionieren lokal; redaktionelle Schreiboperationen bleiben bewusst den späteren Etappen vorbehalten. +Die abschließende Oberflächenüberarbeitung von Etappe 1 reduziert große +Seitenköpfe und verschachtelte Karten, bündelt den Schreibschutzhinweis +aufklappbar und hält Entwicklungsinformationen aus der Arbeitsoberfläche heraus. +Eingang und Archiv zeigen kurze Leerzustände, die Verwaltung trennt +Abschnittskategorien, Formate und Themen kompakt. + +Die abschließende responsive Prüfung verdichtet Seitenleiste, Navigation und +Funduszeilen weiter. Mobile Funduskarten sind intern einspaltig; lange Titel, +Beschreibungen und Metadaten bleiben ohne feste Kartenhöhe sichtbar. Suche und +Statusfilter sind gleich hoch, und die Filtergruppe wird nur als Ganzes +umgebrochen. + ## Nicht Bestandteil dieser Etappe Anmeldung, Rollen, echte Inhaltsbearbeitung, Autospeichern, Sendungsplanung, diff --git a/package-lock.json b/package-lock.json index a022a60..903a7ce 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "sendewerk", - "version": "0.1.0", + "version": "0.1.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "sendewerk", - "version": "0.1.0", + "version": "0.1.1", "dependencies": { "better-sqlite3": "^13.0.3" }, diff --git a/package.json b/package.json index 99bc18e..1ebf5be 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "sendewerk", "private": true, - "version": "0.1.0", + "version": "0.1.1", "type": "module", "engines": { "node": ">=22.17 <25" diff --git a/src/app.css b/src/app.css index 0cf4695..783c151 100644 --- a/src/app.css +++ b/src/app.css @@ -25,7 +25,7 @@ --gold: #c99530; --danger: #a94a43; --shadow: 0 18px 45px rgba(56, 52, 44, 0.08); - --sidebar-width: 15rem; + --sidebar-width: 14rem; --radius-large: 1.5rem; --radius-medium: 1rem; --radius-small: 0.7rem; @@ -124,10 +124,11 @@ a { display: flex; width: var(--sidebar-width); flex-direction: column; - padding: 1.5rem 1rem 1.1rem; + padding: 1.25rem 0.85rem 1rem; border-right: 1px solid var(--line); background: color-mix(in srgb, var(--bg-elevated) 90%, transparent); backdrop-filter: blur(24px) saturate(1.3); + overflow-y: auto; } .brand { @@ -174,15 +175,16 @@ a { .main-navigation { display: grid; gap: 0.28rem; - margin-top: 2.25rem; + margin-top: 1.5rem; } -.main-navigation a { +.main-navigation a, +.utility-navigation a { display: flex; align-items: center; gap: 0.82rem; - min-height: 2.85rem; - padding: 0.65rem 0.8rem; + min-height: 2.65rem; + padding: 0.45rem 0.7rem; border-radius: 0.8rem; color: var(--text-muted); font-weight: 590; @@ -192,12 +194,14 @@ a { transform 140ms ease; } -.main-navigation a:hover { +.main-navigation a:hover, +.utility-navigation a:hover { background: color-mix(in srgb, var(--panel-strong) 66%, transparent); color: var(--text); } -.main-navigation a.active { +.main-navigation a.active, +.utility-navigation a.active { background: var(--panel-strong); box-shadow: 0 7px 20px rgba(48, 48, 43, 0.07); color: var(--accent); @@ -209,6 +213,12 @@ a { margin-top: auto; } +.utility-navigation { + display: grid; + padding-top: 0.85rem; + border-top: 1px solid var(--line); +} + .theme-toggle { display: flex; width: 100%; @@ -240,33 +250,6 @@ a { line-height: 1; } -.stage-indicator { - display: flex; - align-items: center; - gap: 0.65rem; - padding: 0.72rem; - color: var(--text-muted); -} - -.stage-indicator > span { - width: 0.48rem; - height: 0.48rem; - border-radius: 50%; - background: #58a66b; - box-shadow: 0 0 0 0.25rem color-mix(in srgb, #58a66b 14%, transparent); -} - -.stage-indicator div { - display: grid; -} -.stage-indicator strong { - color: var(--text); - font-size: 0.75rem; -} -.stage-indicator small { - font-size: 0.69rem; -} - .mobile-header, .mobile-navigation { display: none; @@ -280,7 +263,7 @@ a { .page-wrap { width: min(100%, 92rem); margin: 0 auto; - padding: 3.4rem clamp(2rem, 4vw, 4.6rem) 5rem; + padding: 2rem clamp(1.5rem, 3vw, 3.25rem) 3rem; } .narrow-page { @@ -288,17 +271,16 @@ a { } .page-heading { - margin-bottom: 1.75rem; + margin-bottom: 1rem; } -.page-heading h1, -.live-header h1 { - max-width: 18ch; - margin: 0.22rem 0 0; - font-size: clamp(2rem, 4vw, 3.65rem); +.page-heading h1 { + max-width: 24ch; + margin: 0; + font-size: clamp(1.7rem, 2.4vw, 2.3rem); font-weight: 690; - letter-spacing: -0.055em; - line-height: 1.02; + letter-spacing: -0.04em; + line-height: 1.08; } .eyebrow { @@ -312,76 +294,98 @@ a { .page-intro { max-width: 42rem; - margin: 0.9rem 0 0; + margin: 0.35rem 0 0; color: var(--text-muted); - font-size: 1.04rem; + font-size: 0.88rem; } .split-heading, -.show-heading, -.live-header { +.show-heading { display: flex; - align-items: flex-end; + align-items: center; justify-content: space-between; - gap: 2rem; + gap: 1.25rem; } .heading-stat { - display: grid; - min-width: 6.5rem; - padding: 0.8rem 1rem; - border-left: 1px solid var(--line-strong); + display: flex; + align-items: baseline; + gap: 0.38rem; + padding: 0.45rem 0.7rem; + border: 1px solid var(--line); + border-radius: 0.65rem; + background: var(--panel); } .heading-stat strong { - font-size: 1.7rem; + font-size: 1rem; line-height: 1; } .heading-stat span { - margin-top: 0.25rem; color: var(--text-muted); - font-size: 0.78rem; + font-size: 0.7rem; } .preview-notice { - display: flex; - align-items: flex-start; - gap: 0.8rem; - margin: 0 0 1.3rem; - padding: 0.85rem 1rem; + margin: 0 0 0.85rem; border: 1px solid color-mix(in srgb, var(--accent) 22%, var(--line)); border-radius: var(--radius-small); background: color-mix(in srgb, var(--accent-soft) 45%, transparent); color: var(--accent-text); } -.preview-notice strong { - font-size: 0.79rem; +.preview-notice summary { + display: flex; + align-items: center; + gap: 0.55rem; + min-height: 2.35rem; + padding: 0.45rem 0.7rem; + cursor: pointer; + list-style: none; } + +.preview-notice summary::-webkit-details-marker { + display: none; +} + +.preview-notice strong { + font-size: 0.72rem; +} + .preview-notice p { - margin: 0.08rem 0 0; + margin: 0; + padding: 0 0.7rem 0.65rem 1.8rem; color: var(--text-muted); - font-size: 0.76rem; + font-size: 0.72rem; } .preview-dot { flex: 0 0 auto; - width: 0.55rem; - height: 0.55rem; - margin-top: 0.38rem; + width: 0.48rem; + height: 0.48rem; border: 2px solid var(--accent); border-radius: 50%; } +.preview-chevron { + margin-left: auto; + color: var(--text-muted); + font-size: 0.85rem; + transition: transform 140ms ease; +} + +.preview-notice[open] .preview-chevron { + transform: rotate(180deg); +} + .library-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 1rem; - margin-bottom: 1.25rem; + margin-bottom: 0.75rem; } -.search-field, -.compact-search { +.search-field { display: flex; align-items: center; gap: 0.6rem; @@ -391,22 +395,20 @@ a { } .search-field { - width: min(100%, 28rem); - height: 2.85rem; + width: min(100%, 24rem); + height: 2.5rem; padding: 0 0.9rem; border-radius: 0.88rem; box-shadow: 0 6px 20px rgba(48, 48, 43, 0.035); } -.search-field span:first-child, -.compact-search span:first-child { +.search-field span:first-child { font-size: 1.35rem; line-height: 1; transform: rotate(-15deg); } -.search-field input, -.compact-search input { +.search-field input { width: 100%; border: 0; outline: 0; @@ -414,8 +416,7 @@ a { color: var(--text); } -.search-field input::placeholder, -.compact-search input::placeholder { +.search-field input::placeholder { color: var(--text-faint); } @@ -427,6 +428,10 @@ a { background: var(--panel-soft); } +.filter-tabs { + height: 2.5rem; +} + .filter-tabs button, .mobile-pane-switch button { padding: 0.48rem 0.82rem; @@ -439,6 +444,12 @@ a { font-weight: 640; } +.filter-tabs button { + height: 2rem; + padding-block: 0.35rem; + white-space: nowrap; +} + .filter-tabs button.active, .mobile-pane-switch button.active { background: var(--panel-strong); @@ -448,33 +459,30 @@ a { .piece-grid { display: grid; - grid-template-columns: repeat(2, minmax(0, 1fr)); - gap: 1rem; + gap: 0; + overflow: hidden; + border: 1px solid var(--line); + border-radius: var(--radius-medium); + background: var(--panel); } .piece-card { - display: flex; + display: grid; + grid-template-columns: minmax(0, 1.8fr) minmax(8.5rem, 0.9fr) minmax(12rem, auto); + align-items: center; + gap: 1rem; min-width: 0; - min-height: 17rem; - flex-direction: column; - padding: 1.25rem; - border: 1px solid var(--line); - border-radius: var(--radius-large); - background: var(--panel); - box-shadow: 0 8px 25px rgba(55, 52, 46, 0.035); + padding: 0.85rem 1rem; + border-bottom: 1px solid var(--line); transition: - border-color 150ms ease, - transform 150ms ease, - box-shadow 150ms ease; + background-color 150ms ease, + border-color 150ms ease; } -.piece-card:hover { - transform: translateY(-2px); - border-color: var(--line-strong); - box-shadow: var(--shadow); +.piece-card:last-child { + border-bottom: 0; } -.piece-card-topline, .source-card > div, .live-kicker { display: flex; @@ -517,25 +525,37 @@ a { color: var(--accent-text); } -.piece-card h2 { - margin: 1.35rem 0 0.55rem; - font-size: 1.35rem; - font-weight: 670; - letter-spacing: -0.025em; - line-height: 1.18; +.piece-primary { + min-width: 0; } -.piece-card > p { +.piece-primary h2 { + margin: 0 0 0.2rem; + font-size: 0.98rem; + font-weight: 670; + letter-spacing: -0.015em; + line-height: 1.25; + overflow-wrap: anywhere; +} + +.piece-primary p { margin: 0; color: var(--text-muted); - font-size: 0.88rem; + font-size: 0.76rem; + line-height: 1.4; +} + +.piece-classification { + display: grid; + min-width: 0; + gap: 0.45rem; } .piece-tags { display: flex; flex-wrap: wrap; gap: 0.35rem; - margin-top: 1.1rem; + margin: 0; } .piece-tags span { @@ -546,25 +566,30 @@ a { font-size: 0.67rem; } -.piece-card footer { +.piece-state { display: flex; - justify-content: space-between; - gap: 1rem; - margin-top: auto; - padding-top: 1.1rem; - border-top: 1px solid var(--line); + align-items: flex-end; + flex-direction: column; + gap: 0.3rem; color: var(--text-faint); - font-size: 0.72rem; + font-size: 0.66rem; } -.piece-card footer b { +.piece-facts { + display: flex; + align-items: center; + flex-wrap: wrap; + justify-content: flex-end; + gap: 0.25rem 0.7rem; +} + +.piece-state b { color: var(--text); font-weight: 680; } -.empty-state, -.planned-panel { - padding: clamp(2rem, 7vw, 5rem); +.empty-state { + padding: 1.5rem; text-align: center; } @@ -575,13 +600,16 @@ a { .empty-state > span { color: var(--text-faint); - font-size: 2rem; + font-size: 1.4rem; } .empty-state h2 { - margin-bottom: 0.3rem; + margin: 0.35rem 0 0.2rem; + font-size: 1rem; } .empty-state p { + margin: 0 0 0.8rem; color: var(--text-muted); + font-size: 0.78rem; } .empty-state button { padding: 0.65rem 0.9rem; @@ -595,14 +623,14 @@ a { .show-summary { display: flex; - align-items: stretch; - gap: 0.65rem; + align-items: center; + gap: 0.5rem; } .show-summary > div { display: grid; min-width: 5.8rem; - padding: 0.6rem 0.85rem; + padding: 0.35rem 0.7rem; border-left: 1px solid var(--line-strong); } @@ -618,7 +646,8 @@ a { display: flex; align-items: center; gap: 0.55rem; - padding: 0.7rem 0.9rem; + min-height: 2.45rem; + padding: 0.55rem 0.8rem; border-radius: 0.72rem; background: var(--text); color: var(--bg); @@ -631,22 +660,39 @@ a { font-size: 1rem; } +.show-heading-copy { + min-width: 0; +} + +.show-title { + margin: 0.3rem 0 0; + font-size: 0.9rem; + font-weight: 680; + overflow-wrap: anywhere; +} + +.show-date { + margin: 0.08rem 0 0; + color: var(--text-muted); + font-size: 0.72rem; +} + .mobile-pane-switch { display: none; } .builder-workspace { display: grid; - grid-template-columns: minmax(18rem, 0.78fr) minmax(28rem, 1.35fr); - gap: 1rem; + grid-template-columns: minmax(15rem, 0.72fr) minmax(24rem, 1.45fr); + gap: 0.75rem; align-items: start; } .builder-pane { min-width: 0; - padding: 1.15rem; + padding: 0.9rem; border: 1px solid var(--line); - border-radius: var(--radius-large); + border-radius: var(--radius-medium); background: var(--panel); } @@ -655,7 +701,7 @@ a { align-items: flex-start; justify-content: space-between; gap: 1rem; - margin-bottom: 1rem; + margin-bottom: 0.65rem; } .pane-heading h2 { @@ -672,27 +718,15 @@ a { font-weight: 680; } -.compact-search { - height: 2.5rem; - padding: 0 0.75rem; - border-radius: 0.72rem; -} - -.compact-search:has(input:disabled) { - opacity: 0.72; -} - .source-list { display: grid; - gap: 0.55rem; - margin-top: 0.8rem; + gap: 0; + border-top: 1px solid var(--line); } .source-card { - padding: 0.9rem; - border: 1px solid var(--line); - border-radius: 0.9rem; - background: var(--panel-strong); + padding: 0.72rem 0.2rem; + border-bottom: 1px solid var(--line); } .source-card > div > span:last-child { @@ -700,9 +734,10 @@ a { font-size: 0.68rem; } .source-card h3 { - margin: 0.72rem 0 0.2rem; + margin: 0.42rem 0 0.12rem; font-size: 0.88rem; line-height: 1.25; + overflow-wrap: anywhere; } .source-card p { margin: 0; @@ -711,8 +746,8 @@ a { } .reserve-box { - margin-top: 0.8rem; - padding: 0.9rem; + margin-top: 0.65rem; + padding: 0.7rem; border: 1px dashed color-mix(in srgb, var(--gold) 48%, var(--line)); border-radius: 0.9rem; background: color-mix(in srgb, var(--gold) 7%, transparent); @@ -745,14 +780,13 @@ a { .run-list { display: grid; - gap: 0.7rem; + gap: 0; + border-top: 1px solid var(--line); } .run-section { - padding: 0.95rem; - border: 1px solid var(--line); - border-radius: 1rem; - background: var(--panel-strong); + padding: 0.78rem 0.2rem; + border-bottom: 1px solid var(--line); } .run-section > header { @@ -770,6 +804,7 @@ a { margin: 0.13rem 0 0; font-size: 0.95rem; letter-spacing: -0.012em; + overflow-wrap: anywhere; } .section-number { @@ -787,32 +822,26 @@ a { .usage-list { display: grid; gap: 0.42rem; - margin: 0.8rem 0 0 2.8rem; + margin: 0.55rem 0 0 2.8rem; } .usage-row { display: grid; - grid-template-columns: auto minmax(0, 1fr) auto; + grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 0.65rem; - padding: 0.68rem; + padding: 0.55rem 0.65rem; border-radius: 0.72rem; background: var(--panel-soft); } -.drag-hint { - color: var(--text-faint); - font-size: 1.05rem; -} .usage-row div { display: grid; min-width: 0; } .usage-row strong { - overflow: hidden; font-size: 0.78rem; - text-overflow: ellipsis; - white-space: nowrap; + overflow-wrap: anywhere; } .usage-row small { color: var(--text-muted); @@ -830,8 +859,8 @@ a { color: var(--accent-text); } .section-placeholder { - margin: 0.75rem 0 0 2.8rem; - padding: 0.65rem; + margin: 0.5rem 0 0 2.8rem; + padding: 0.5rem 0.65rem; border: 1px dashed var(--line-strong); border-radius: 0.7rem; color: var(--text-muted); @@ -842,11 +871,18 @@ a { max-width: 88rem; } .live-header { - margin-bottom: 1.5rem; + display: flex; + align-items: center; + justify-content: space-between; + gap: 1.25rem; + margin-bottom: 1rem; } .live-header h1 { max-width: 24ch; - font-size: clamp(1.65rem, 3vw, 2.65rem); + margin: 0.18rem 0 0; + font-size: clamp(1.5rem, 2.5vw, 2.1rem); + letter-spacing: -0.035em; + line-height: 1.08; } .live-pulse { @@ -899,7 +935,7 @@ a { .live-current { min-width: 0; - padding: clamp(1.4rem, 4vw, 3rem); + padding: clamp(1.25rem, 3vw, 2.25rem); border: 1px solid var(--line); border-radius: 1.8rem; background: var(--panel); @@ -918,8 +954,8 @@ a { } .live-current h2 { max-width: 20ch; - margin: 1.4rem 0 2rem; - font-size: clamp(2rem, 4vw, 3.4rem); + margin: 1rem 0 1.4rem; + font-size: clamp(1.8rem, 3.2vw, 2.8rem); font-weight: 670; letter-spacing: -0.05em; line-height: 1.03; @@ -933,7 +969,7 @@ a { .moderation-card, .transition-card { - margin-top: 2rem; + margin-top: 1.25rem; padding: 1rem 1.1rem; border-radius: 0.9rem; background: var(--panel-soft); @@ -1070,43 +1106,49 @@ a { } .planned-panel { - margin-top: 2.5rem; + display: grid; + grid-template-columns: auto minmax(0, 1fr); + column-gap: 0.85rem; + align-items: center; + margin-top: 1.25rem; + padding: 1rem; + text-align: left; } .planned-panel h2 { - margin: 0.55rem 0; - font-size: 1.55rem; - letter-spacing: -0.03em; + margin: 0; + font-size: 0.98rem; + letter-spacing: -0.015em; } .planned-panel > p:last-child { - max-width: 40rem; - margin: 0 auto; + grid-column: 2; + margin: 0.18rem 0 0; color: var(--text-muted); + font-size: 0.78rem; } .planned-icon { display: grid; - width: 3.2rem; - height: 3.2rem; - margin: 0 auto 1rem; + grid-row: 1 / span 2; + width: 2.35rem; + height: 2.35rem; + margin: 0; place-items: center; - border-radius: 1rem; + border-radius: 0.7rem; background: var(--accent-soft); color: var(--accent); - font-size: 1.6rem; + font-size: 1.15rem; } .settings-grid { display: grid; - grid-template-columns: repeat(2, minmax(0, 1fr)); - gap: 1rem; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 0.75rem; } -.taxonomy-panel, -.planned-settings { - padding: 1.3rem; +.taxonomy-panel { + padding: 1rem; } -.taxonomy-panel h2, -.planned-settings h2 { - margin: 0.25rem 0 1.1rem; - font-size: 1.08rem; +.taxonomy-panel h2 { + margin: 0.2rem 0 0.7rem; + font-size: 0.95rem; } .taxonomy-list { display: flex; @@ -1117,11 +1159,13 @@ a { display: flex; align-items: center; gap: 0.4rem; - padding: 0.42rem 0.68rem; + min-width: 0; + padding: 0.32rem 0.55rem; border: 1px solid var(--line); border-radius: 2rem; color: var(--text-muted); - font-size: 0.75rem; + font-size: 0.7rem; + overflow-wrap: anywhere; } .taxonomy-list i { width: 0.48rem; @@ -1129,27 +1173,41 @@ a { border-radius: 50%; background: var(--tax-color); } -.planned-settings { - background: color-mix(in srgb, var(--panel) 72%, var(--accent-soft)); -} -.planned-settings p:last-child { +.settings-footnote { + margin: 0.75rem 0 0; color: var(--text-muted); - font-size: 0.82rem; + font-size: 0.72rem; } -@media (min-width: 84rem) { - .piece-grid { - grid-template-columns: repeat(3, minmax(0, 1fr)); - } -} - -@media (max-width: 70rem) { - .builder-workspace { - grid-template-columns: minmax(16rem, 0.72fr) minmax(24rem, 1.2fr); - } +@media (max-width: 72rem) { .page-wrap { padding-inline: 2rem; } + .mobile-pane-switch { + display: flex; + width: 100%; + margin-bottom: 0.65rem; + } + .mobile-pane-switch button { + flex: 1; + } + .builder-workspace { + display: block; + } + .builder-pane.mobile-hidden { + display: none; + } +} + +@media (max-width: 64rem) and (min-width: 52.001rem) { + .library-toolbar { + align-items: stretch; + flex-direction: column; + } + + .library-toolbar .filter-tabs { + align-self: flex-start; + } } @media (max-width: 52rem) { @@ -1211,6 +1269,7 @@ a { font-weight: 620; } .mobile-navigation a.active { + background: var(--accent-soft); color: var(--accent); } .mobile-navigation a svg { @@ -1219,24 +1278,20 @@ a { } #main-content { margin-left: 0; - padding: var(--mobile-header) 0 var(--mobile-nav); + padding: var(--mobile-header) 0 calc(var(--mobile-nav) + env(safe-area-inset-bottom) + 1rem); } .page-wrap { width: 100%; - padding: 1.6rem 1rem 3rem; + padding: 1.25rem 1rem 2rem; } .page-heading h1 { - font-size: clamp(2rem, 10vw, 3rem); + font-size: 1.75rem; } - .split-heading, .show-heading, .live-header { align-items: flex-start; flex-direction: column; - gap: 1.15rem; - } - .heading-stat { - display: none; + gap: 0.75rem; } .library-toolbar { align-items: stretch; @@ -1253,10 +1308,50 @@ a { flex: 1 0 auto; } .piece-grid { - grid-template-columns: 1fr; + gap: 0.7rem; + overflow: visible; + border: 0; + border-radius: 0; + background: transparent; } .piece-card { - min-height: 15.5rem; + display: flex; + align-items: stretch; + flex-direction: column; + gap: 0.7rem; + grid-template-columns: none; + padding: 1rem; + border: 1px solid var(--line); + border-radius: var(--radius-medium); + background: var(--panel); + } + .piece-card:last-child { + border-bottom: 1px solid var(--line); + } + .piece-classification { + gap: 0.55rem; + } + .piece-primary, + .piece-classification, + .piece-state { + min-width: 0; + width: 100%; + } + .piece-primary h2 { + font-size: 1.08rem; + } + .piece-state { + display: flex; + align-items: center; + flex-direction: row; + flex-wrap: wrap; + justify-content: flex-start; + gap: 0.5rem 0.75rem; + padding-top: 0.7rem; + border-top: 1px solid var(--line); + } + .piece-facts { + justify-content: flex-start; } .show-summary { width: 100%; @@ -1269,20 +1364,6 @@ a { flex: 1 0 100%; justify-content: center; } - .mobile-pane-switch { - display: flex; - width: 100%; - margin-bottom: 0.8rem; - } - .mobile-pane-switch button { - flex: 1; - } - .builder-workspace { - display: block; - } - .builder-pane.mobile-hidden { - display: none; - } .builder-pane { padding: 0.85rem; } @@ -1293,9 +1374,6 @@ a { .usage-row { grid-template-columns: minmax(0, 1fr) auto; } - .drag-hint { - display: none; - } .live-header-actions { width: 100%; justify-content: space-between; @@ -1310,6 +1388,11 @@ a { .live-current h2 { margin: 1.1rem 0 1.5rem; } + .live-kicker { + align-items: flex-start; + flex-direction: column; + gap: 0.2rem; + } .live-rail { grid-template-columns: 1fr; } @@ -1322,10 +1405,7 @@ a { .page-wrap { padding-inline: 0.75rem; } - .preview-notice { - padding: 0.75rem; - } - .piece-card footer { + .piece-state { align-items: flex-start; flex-direction: column; gap: 0.25rem; diff --git a/src/lib/components/PreviewNotice.svelte b/src/lib/components/PreviewNotice.svelte index e0720b3..d8b2d5c 100644 --- a/src/lib/components/PreviewNotice.svelte +++ b/src/lib/components/PreviewNotice.svelte @@ -2,12 +2,13 @@ let { area }: { area: string } = $props(); - +
+ + + Vorschau · {area} + + +

+ Diese Ansicht ist schreibgeschützt. Bearbeiten und Speichern folgen in einer späteren Etappe. +

+
diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 35444a3..3c5ec36 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -6,13 +6,14 @@ import ThemeToggle from '#lib/components/ThemeToggle.svelte'; let { children } = $props(); - const navigation = [ + const primaryNavigation = [ { href: '/eingang', label: 'Eingang', icon: 'inbox' }, { href: '/fundus', label: 'Fundus', icon: 'library' }, { href: '/sendungen', label: 'Sendungen', icon: 'shows' }, - { href: '/archiv', label: 'Archiv', icon: 'archive' }, - { href: '/verwaltung', label: 'Verwaltung', icon: 'settings' } + { href: '/archiv', label: 'Archiv', icon: 'archive' } ] as const; + const administration = { href: '/verwaltung', label: 'Verwaltung', icon: 'settings' } as const; + const mobileNavigation = [...primaryNavigation, administration]; function isActive(href: string) { return ( @@ -36,7 +37,7 @@