diff --git a/frontend/index.html b/frontend/index.html index 2c5762f..5d815bd 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -3,7 +3,22 @@ - SwyxWeb + SwyxWeb · STADTBOTE + + + + + +
diff --git a/frontend/src/components/StadtboteSignet.tsx b/frontend/src/components/StadtboteSignet.tsx new file mode 100644 index 0000000..87f67fb --- /dev/null +++ b/frontend/src/components/StadtboteSignet.tsx @@ -0,0 +1,29 @@ +/** + * Das STADTBOTE-Signet aus dem Corporate-Design-Manual: ein offener roter Ring + * mit einem „S" in der Mitte. Als Inline-SVG nachgebaut, weil das Brandbook das + * Logo nur als Pixelbild enthält; die Farbe kommt über currentColor vom Umfeld. + */ +export default function StadtboteSignet({ className }: { className?: string }) { + return ( + + ) +} diff --git a/frontend/src/index.css b/frontend/src/index.css index af44552..df54ff2 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -1,26 +1,48 @@ +/* + * Farb- und Schriftvorgaben aus dem STADTBOTE-Styleguide (HANSETRANS Brandbook): + * Primär Rot #CA0D38 (Pantone 185 C) und Grau #7C7F7E (Pantone 424 C), + * Off-Black #222222 für Fließtext, Grauabstufungen als Flächen. + * Schrift: Red Hat Display (Überschriften, Versalien, Laufweite 4 %) und + * Red Hat Text (Fließtext). Buttons: primär vollflächig, sekundär mit Rahmen, + * Kästen und Linien mit leichter Abrundung. + */ :root { - --bg: #0f1116; - --surface: #171a21; - --surface-2: #1f2530; - --border: #2b3341; - --text: #e6e9ef; - --text-muted: #98a2b3; - --accent: #4f8cff; - --ok: #35c98a; - --warn: #e0b341; - --err: #f2585b; - color-scheme: dark; + --bg: #ffffff; + --surface: #ffffff; + --surface-2: #f6f6f6; + --border: #dcdcdd; + --border-strong: #b4b4b5; + --text: #222222; + --text-muted: #7c7f7e; + /* Vollflächen (Buttons, Balken) – immer das Markenrot mit weißer Schrift. */ + --brand: #ca0d38; + --brand-strong: #a30a2d; + --brand-soft: rgb(202 13 56 / 8%); + /* Rot als Text- und Konturfarbe; im Dunkelmodus eine hellere Abstufung. */ + --accent: #ca0d38; + --ok: #2f9e6e; + --warn: #b98a1c; + --err: #d92b1f; + color-scheme: light; } -@media (prefers-color-scheme: light) { +@media (prefers-color-scheme: dark) { :root { - --bg: #f5f7fa; - --surface: #ffffff; - --surface-2: #eef1f6; - --border: #d8dee9; - --text: #1b2230; - --text-muted: #5c6779; - color-scheme: light; + --bg: #17181a; + --surface: #1f2023; + --surface-2: #28292d; + --border: #3a3b40; + --border-strong: #55565c; + --text: #f1f1f2; + --text-muted: #a4a7a8; + --brand: #ca0d38; + --brand-strong: #e33e60; + --brand-soft: rgb(227 62 96 / 14%); + --accent: #ef7d95; + --ok: #43c78f; + --warn: #e0b341; + --err: #f2665b; + color-scheme: dark; } } @@ -32,9 +54,21 @@ body { margin: 0; background: var(--bg); color: var(--text); - font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif; + font-family: 'Red Hat Text', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif; font-size: 15px; - line-height: 1.5; + line-height: 1.4; +} + +h1, +h2, +h3 { + /* Überschriften laut Styleguide: Red Hat Display Semibold in Versalien, + Laufweite 4 %, Zeilenabstand 100 %. */ + font-family: 'Red Hat Display', 'Red Hat Text', system-ui, sans-serif; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.04em; + line-height: 1; } code { @@ -59,14 +93,38 @@ code { flex-wrap: wrap; } -.page__header h1 { +/* Abgerundete Linie als Trennlinie unter dem Kopf – Gestaltungselement des CI. */ +.page__header::after { + content: ''; + flex-basis: 100%; + height: 3px; + border-radius: 999px; + background: var(--brand); +} + +.brand { + display: flex; + align-items: center; + gap: 14px; + color: var(--accent); +} + +.brand__signet { + width: 46px; + height: 46px; + flex: 0 0 auto; +} + +.brand__name { margin: 0; - font-size: 26px; - letter-spacing: -0.02em; + font-weight: 700; + font-size: 24px; + letter-spacing: 0.06em; + color: var(--accent); } .page__subtitle { - margin: 2px 0 0; + margin: 4px 0 0; color: var(--text-muted); } @@ -84,7 +142,7 @@ code { .card { background: var(--surface); border: 1px solid var(--border); - border-radius: 12px; + border-radius: 8px; padding: 18px; display: flex; flex-direction: column; @@ -93,8 +151,8 @@ code { .card h2 { margin: 0; - font-size: 16px; - font-weight: 600; + font-size: 15px; + color: var(--text); } .card__header { @@ -134,9 +192,9 @@ code { .field__input { width: 100%; padding: 9px 12px; - border-radius: 8px; - border: 1px solid var(--border); - background: var(--surface-2); + border-radius: 6px; + border: 1px solid var(--border-strong); + background: var(--surface); color: var(--text); font: inherit; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; @@ -144,27 +202,30 @@ code { } .field__input:focus { - outline: 2px solid var(--accent); + outline: 2px solid var(--brand); outline-offset: 1px; + border-color: var(--brand); } .field__input:disabled { opacity: 0.55; + background: var(--surface-2); } +/* Sekundärbutton laut Styleguide: schlichter roter Rahmen, leichte Abrundung. */ .button { padding: 9px 16px; - border-radius: 8px; - border: 1px solid var(--border); - background: var(--surface-2); - color: var(--text); + border-radius: 6px; + border: 1px solid var(--accent); + background: transparent; + color: var(--accent); font: inherit; font-weight: 500; cursor: pointer; } .button:hover:not(:disabled) { - border-color: var(--accent); + background: var(--brand-soft); } .button:disabled { @@ -172,13 +233,20 @@ code { cursor: not-allowed; } +/* Primärbutton laut Styleguide: vollflächig im Markenrot. */ .button--primary { - background: var(--accent); - border-color: var(--accent); + background: var(--brand); + border-color: var(--brand); color: #fff; } +.button--primary:hover:not(:disabled) { + background: var(--brand-strong); + border-color: var(--brand-strong); +} + .button--ghost { + border-color: transparent; background: transparent; padding: 5px 10px; font-size: 13px; @@ -200,21 +268,25 @@ code { .tabs { display: flex; - gap: 4px; + gap: 18px; border-bottom: 1px solid var(--border); + flex-wrap: wrap; } .tabs__button { - padding: 9px 16px; - border: 1px solid transparent; - /* Die aktive Kante überdeckt die Linie der Leiste. */ - border-bottom: none; + padding: 10px 2px; + border: none; + border-bottom: 3px solid transparent; margin-bottom: -1px; - border-radius: 10px 10px 0 0; + border-radius: 0; background: transparent; color: var(--text-muted); font: inherit; - font-weight: 500; + font-family: 'Red Hat Display', 'Red Hat Text', system-ui, sans-serif; + font-weight: 600; + font-size: 13px; + text-transform: uppercase; + letter-spacing: 0.04em; cursor: pointer; } @@ -223,9 +295,8 @@ code { } .tabs__button--active { - background: var(--surface); - border-color: var(--border); - color: var(--text); + color: var(--accent); + border-bottom-color: var(--brand); } [role='tabpanel'] { @@ -354,7 +425,12 @@ code { .button--accept { background: var(--ok); border-color: var(--ok); - color: #06281c; + color: #fff; +} + +.button--accept:hover:not(:disabled) { + background: var(--ok); + opacity: 0.9; } .button--reject { @@ -363,6 +439,11 @@ code { color: #fff; } +.button--reject:hover:not(:disabled) { + background: var(--err); + opacity: 0.9; +} + .button--small { padding: 5px 12px; font-size: 13px; @@ -387,7 +468,7 @@ code { gap: 12px; flex-wrap: wrap; padding: 10px 12px; - border-radius: 8px; + border-radius: 6px; border: 1px solid var(--border); background: var(--surface-2); } @@ -400,7 +481,7 @@ code { .history__line { flex: 0 0 auto; padding: 2px 8px; - border-radius: 6px; + border-radius: 4px; background: var(--border); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; @@ -463,8 +544,8 @@ code { } .history__badge--ended { - border-color: var(--err); - color: var(--err); + border-color: var(--border-strong); + color: var(--text-muted); } .history__number { @@ -492,7 +573,7 @@ code { align-items: center; gap: 12px; padding: 10px 12px; - border-radius: 8px; + border-radius: 6px; border: 1px solid var(--border); background: var(--surface-2); } @@ -504,7 +585,7 @@ code { .tablist__id { flex: 0 0 auto; padding: 2px 8px; - border-radius: 6px; + border-radius: 4px; background: var(--border); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; @@ -561,15 +642,15 @@ code { .dialog { width: min(420px, 100%); padding: 24px; - border-radius: 12px; + border-radius: 8px; border: 1px solid var(--border); background: var(--surface); - box-shadow: 0 24px 60px rgb(0 0 0 / 45%); + box-shadow: 0 24px 60px rgb(0 0 0 / 25%); } .dialog__title { margin: 0 0 16px; - font-size: 18px; + font-size: 17px; } .dialog__status { @@ -591,14 +672,15 @@ code { .progress { height: 8px; border-radius: 999px; - background: var(--border); + background: var(--surface-2); + border: 1px solid var(--border); overflow: hidden; } .progress__bar { height: 100%; border-radius: 999px; - background: var(--accent); + background: var(--brand); transition: width 120ms linear; } @@ -634,7 +716,7 @@ code { align-items: center; gap: 12px; padding: 10px 12px; - border-radius: 8px; + border-radius: 6px; border: 1px solid var(--border); background: var(--surface-2); } @@ -672,7 +754,7 @@ code { height: 300px; overflow-y: auto; padding: 12px; - border-radius: 8px; + border-radius: 6px; border: 1px solid var(--border); background: var(--surface-2); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; @@ -732,7 +814,7 @@ code { flex-direction: column; gap: 8px; padding: 10px 12px; - border-radius: 8px; + border-radius: 6px; border: 1px solid var(--border); background: var(--surface-2); } @@ -753,7 +835,7 @@ code { .webhook__id { padding: 1px 8px; - border-radius: 6px; + border-radius: 4px; background: var(--border); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; @@ -772,7 +854,7 @@ code { .webhook__json { margin: 0; padding: 10px 12px; - border-radius: 6px; + border-radius: 4px; background: var(--surface); border: 1px solid var(--border); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; @@ -789,8 +871,8 @@ code { margin-left: 8px; padding: 1px 7px; border-radius: 999px; - background: var(--accent); - color: var(--surface); + background: var(--brand); + color: #fff; font-size: 12px; font-weight: 700; font-variant-numeric: tabular-nums; diff --git a/frontend/src/pages/HomePage.tsx b/frontend/src/pages/HomePage.tsx index 06d0a5c..9579331 100644 --- a/frontend/src/pages/HomePage.tsx +++ b/frontend/src/pages/HomePage.tsx @@ -5,6 +5,7 @@ import { useCallNotifications } from '../hooks/useCallNotifications' import { useWebhook } from '../hooks/useWebhook' import { countUnseen } from '../webhook' import StatusBadge from '../components/StatusBadge' +import StadtboteSignet from '../components/StadtboteSignet' import MessageLog from '../components/MessageLog' import IncomingCallCard from '../components/IncomingCallCard' import DialPanel from '../components/DialPanel' @@ -99,9 +100,12 @@ export default function HomePage() { return (
-
-

SwyxWeb

-

Telefonie über die SwyxTray-App

+
+ +
+

Stadtbote

+

SwyxWeb · Telefonie über die SwyxTray-App

+