monitor/html/css/office.css
fds2610-bot cfe82b6a4d Buero-Szene fuellt den sichtbaren Bereich statt Full-Screen zu erwarten
Die Szene war auf volle Fensterbreite ausgelegt und lief im normalen
Fenstermodus unten aus dem Bild (bei 1440x700 z.B. um 232px).

- body als Flex-Spalte ueber die Viewport-Hoehe. Bewusst height statt
  min-height: nur eine definite Hoehe laesst die prozentualen
  max-height-Angaben der Szene aufloesen.
- #office-scene nimmt die Resthoehe (flex: 1, min-height: 0) und
  zentriert das SVG.
- Das SVG richtet sich an der jeweils knapperen Achse aus - zwei
  Media-Queries auf 16/9 schalten zwischen hoehen- und breitenbegrenzt
  um, max-width/max-height sind das Sicherheitsnetz fuer den
  Grenzbereich (die Header-Hoehe geht in das Verhaeltnis der
  Szenenflaeche ein, in die Media-Query aber nicht).
- Bei knappem Platz weicht der erklaerende Fliesstext im Header.

Gemessen in Chromium ueber 1920x1080 bis 500x900: kein Overflow,
Seitenverhaeltnis durchgehend exakt 16:9.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-28 18:25:16 +02:00

550 lines
9.6 KiB
CSS

/* Buero-Visualisierung (Phase 2, statische Szene). Bewusst ohne UI-Framework, siehe
Visualization.md Abschnitt 5. Farbschema hell/freundlich (F9: "Zeichentrick"-Anmutung). */
:root {
--color-floor: #eef2f7;
--color-wall: #cfe0f0;
--color-wall-side: #bcd3ea;
--color-door: #8fb8dd;
--color-board-frame: #94622f;
--color-note: #fde68a;
--color-note-border: #d9b34f;
--color-note-stack-badge: #d97706;
--color-monitor-frame: #2b2f38;
--color-monitor-screen: #10131a;
--color-monitor-placeholder: #1a2436;
--color-desk-table: #b98a54;
--color-desk-chair: #6b7280;
--color-desk-screen-idle: #3a3f4b;
--color-text: #1f2937;
--color-text-inverse: #f8fafc;
}
* {
box-sizing: border-box;
}
/* Die Szene soll immer vollstaendig sichtbar sein - auch im normalen Fenstermodus,
ohne Scrollen. Dazu spannt der body eine Flex-Spalte ueber die Viewport-Hoehe auf:
Header nimmt seine natuerliche Hoehe, #office-scene bekommt den Rest, und das SVG
skaliert sich per aspect-ratio in diesen Rest hinein (siehe unten). */
html {
height: 100%;
}
body {
margin: 0;
font-family: "Segoe UI", Verdana, Arial, sans-serif;
background: #dbe7f3;
color: var(--color-text);
/* height (nicht min-height): Nur eine definite Hoehe laesst die prozentualen
max-height-Angaben weiter unten aufloesen. dvh rechnet mobile Browserleisten
mit, vh ist der Fallback fuer aeltere Engines. */
height: 100vh;
height: 100dvh;
display: flex;
flex-direction: column;
overflow: hidden;
}
header.office-header {
flex: 0 0 auto;
padding: 12px 24px;
display: flex;
align-items: baseline;
gap: 16px;
}
header.office-header h1 {
margin: 0;
font-size: 1.4rem;
}
header.office-header p {
margin: 0;
color: #475569;
font-size: 0.9rem;
}
#office-scene {
flex: 1 1 auto;
/* min-height: 0 hebt die Flex-Default-Mindesthoehe (min-content) auf - sonst kann
das Kind den Container nicht unterschreiten und die Szene laeuft aus dem Bild. */
min-height: 0;
display: flex;
align-items: center;
justify-content: center;
padding: 0 16px 16px;
}
/* Das SVG soll sich an der jeweils knapperen Achse ausrichten. Welche das ist, haengt
vom Seitenverhaeltnis des Fensters ab - daher die beiden Media-Queries unten. Die
max-*-Grenzen sind das Sicherheitsnetz fuer den Grenzbereich (die Header-Hoehe geht
in das Verhaeltnis der Szenenflaeche ein, in die Media-Query aber nicht): Dort wird
die Elementbox notfalls leicht gestaucht - der Szeneninhalt bleibt dank
preserveAspectRatio unverzerrt und vollstaendig sichtbar. */
.office-svg {
max-width: 100%;
max-height: 100%;
aspect-ratio: 1920 / 1080;
display: block;
border-radius: 12px;
box-shadow: 0 10px 30px rgba(15, 23, 42, 0.25);
}
/* Fenster breiter als 16:9 -> die Hoehe ist der Engpass. */
@media (min-aspect-ratio: 16 / 9) {
.office-svg {
height: 100%;
width: auto;
}
}
/* Fenster schmaler als 16:9 -> die Breite ist der Engpass. */
@media (max-aspect-ratio: 16 / 9) {
.office-svg {
width: 100%;
height: auto;
}
}
/* Bei knappem Platz weicht zuerst der erklaerende Fliesstext - er kostet in flachen
oder schmalen Fenstern mehrere Zeilen Hoehe, die der Szene fehlen. */
@media (max-height: 640px), (max-width: 760px) {
header.office-header p {
display: none;
}
}
@media (max-height: 640px) {
header.office-header {
padding: 8px 16px;
}
header.office-header h1 {
font-size: 1.1rem;
}
}
.floor {
fill: var(--color-floor);
}
.wall {
fill: var(--color-wall);
}
.wall-side {
fill: var(--color-wall-side);
}
.door {
fill: var(--color-door);
stroke: #5f86ab;
stroke-width: 3;
}
.wall-label {
fill: #f8fafc;
font-size: 22px;
font-weight: 600;
}
/* Kanban-Board */
.board-frame {
fill: #7a5230;
stroke: var(--color-board-frame);
stroke-width: 6;
}
.board-column-label {
fill: var(--color-text-inverse);
font-size: 16px;
font-weight: 600;
}
.board-column-divider {
stroke: rgba(255, 255, 255, 0.25);
stroke-width: 2;
}
.note {
fill: var(--color-note);
stroke: var(--color-note-border);
stroke-width: 2;
}
.note-stack-badge {
fill: var(--color-note-stack-badge);
stroke: #92400e;
stroke-width: 2;
}
.note-stack-count {
fill: #ffffff;
font-size: 20px;
font-weight: 700;
}
/* Monitor-Wand */
.monitor-frame {
fill: var(--color-monitor-frame);
}
.monitor-screen {
fill: var(--color-monitor-screen);
}
.monitor-screen-placeholder {
fill: var(--color-monitor-placeholder);
}
.monitor-event-line {
font-family: "Consolas", "Courier New", monospace;
font-size: 13px;
}
.severity-warning {
fill: #facc15;
}
.severity-error {
fill: #f87171;
}
.system-tile-bg {
fill: #1e293b;
}
.system-tile-bar {
fill: #334155;
}
.system-tile-led {
fill: #64748b;
}
.status-ok .system-tile-led {
fill: #4ade80;
}
.status-error .system-tile-led {
fill: #f87171;
}
.system-tile-label {
fill: var(--color-text-inverse);
font-size: 12px;
}
.monitor-placeholder-text {
fill: #64748b;
font-size: 15px;
}
/* Schreibtische */
.desk-table {
fill: var(--color-desk-table);
stroke: #8a6238;
stroke-width: 3;
}
.desk-screen {
fill: var(--color-desk-screen-idle);
stroke: #1f2430;
stroke-width: 2;
}
.desk-screen.pose-working {
fill: #7dd3fc;
}
.desk-chair {
fill: var(--color-desk-chair);
}
.person-head {
fill: #f3d9b1;
stroke: #d8b98a;
stroke-width: 1.5;
}
.person-body {
fill: var(--role-color, #94a3b8);
}
.desk-name {
fill: #334155;
font-size: 14px;
font-weight: 600;
}
.desk-name-empty {
fill: #94a3b8;
font-style: italic;
font-weight: 400;
}
.desk-deco-star {
fill: #fbbf24;
}
.desk-deco-flower circle {
fill: #f9a8d4;
}
.desk-deco-flower-center {
fill: #fde047 !important;
}
.desk-deco-check {
fill: none;
stroke: #22c55e;
stroke-width: 4;
stroke-linecap: round;
stroke-linejoin: round;
}
.desk-empty .desk-chair {
opacity: 0.5;
}
/* Klickbare Bereiche (Phase 3/4: Board-Spalten + Monitore oeffnen ein Modal) */
.clickable {
cursor: pointer;
}
.board-column-hit {
fill: transparent;
pointer-events: all;
}
.just-updated .board-frame,
.just-updated .monitor-frame {
animation: office-flash 0.9s ease-out;
}
@keyframes office-flash {
0% {
filter: drop-shadow(0 0 0 rgba(250, 204, 21, 0));
}
25% {
filter: drop-shadow(0 0 12px rgba(250, 204, 21, 0.9));
}
100% {
filter: drop-shadow(0 0 0 rgba(250, 204, 21, 0));
}
}
/* Kaffee-Ecke (Phase 5, Raum-Prop zwischen den Schreibtischreihen) */
.coffee-table {
fill: #8a6238;
stroke: #6b4a28;
stroke-width: 2;
}
.coffee-cup {
fill: #f8fafc;
stroke: #94a3b8;
stroke-width: 1.5;
}
.coffee-icon {
font-size: 20px;
}
/* Agenten-Avatare (Phase 5: bewegliche Schicht, siehe office-render.js) */
.agent-avatar {
transition: transform 1.1s ease-in-out;
}
.agent-avatar .person-head {
fill: #f3d9b1;
stroke: #d8b98a;
stroke-width: 1.5;
}
.agent-avatar .person-body {
fill: var(--role-color, #94a3b8);
}
.agent-avatar.pose-walking .person-leg {
fill: #475569;
transform-box: fill-box;
transform-origin: top center;
animation: office-leg-swing 0.6s ease-in-out infinite alternate;
}
.agent-avatar.pose-walking .person-leg-right {
animation-delay: 0.3s;
}
@keyframes office-leg-swing {
from {
transform: rotate(-18deg);
}
to {
transform: rotate(18deg);
}
}
.person-prop-cup {
fill: #f8fafc;
stroke: #94a3b8;
}
.person-prop-newspaper {
fill: #f8fafc;
stroke: #94a3b8;
stroke-width: 1;
}
.person-prop-speech {
fill: #f8fafc;
stroke: #94a3b8;
stroke-width: 1;
}
.avatar-name {
fill: #334155;
font-size: 13px;
font-weight: 600;
text-anchor: middle;
}
/* KPI-Sparklines (Phase 4, F10: kein Chart-Lib, eigenes SVG-Zeichnen) */
.kpi-tile-label {
fill: var(--color-text-inverse);
font-size: 13px;
font-weight: 600;
}
.kpi-sparkline-bg {
fill: rgba(255, 255, 255, 0.04);
}
.kpi-sparkline-line {
fill: none;
stroke: #7dd3fc;
stroke-width: 2;
stroke-linejoin: round;
stroke-linecap: round;
}
/* Modal (Phase 3/4: Board-/Monitor-Detailansicht, Visualization.md 4.5) */
.office-modal {
border: none;
border-radius: 12px;
padding: 0;
width: min(640px, 92vw);
max-height: 80vh;
box-shadow: 0 20px 50px rgba(15, 23, 42, 0.4);
}
.office-modal::backdrop {
background: rgba(15, 23, 42, 0.55);
}
.office-modal-form {
display: flex;
flex-direction: column;
max-height: 80vh;
}
.office-modal-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 16px 20px;
border-bottom: 1px solid #e2e8f0;
}
.office-modal-title {
margin: 0;
font-size: 1.1rem;
}
.office-modal-close {
border: none;
background: transparent;
font-size: 1.4rem;
line-height: 1;
cursor: pointer;
color: #64748b;
}
.office-modal-body {
padding: 16px 20px;
overflow-y: auto;
}
.office-modal-list {
list-style: none;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
gap: 10px;
}
.office-modal-item {
border: 1px solid #e2e8f0;
border-radius: 8px;
padding: 10px 12px;
}
.office-modal-item p {
margin: 6px 0 0;
color: #475569;
font-size: 0.9rem;
}
.office-modal-item-heading {
display: flex;
align-items: center;
gap: 8px;
}
.office-modal-badge {
font-size: 0.75rem;
padding: 2px 8px;
border-radius: 999px;
background: #e2e8f0;
color: #1f2937;
}
.office-modal-item.severity-error {
border-color: #fca5a5;
background: #fef2f2;
}
.office-modal-item.severity-warning {
border-color: #fde68a;
background: #fffbeb;
}
.office-modal-item.status-error {
border-color: #fca5a5;
background: #fef2f2;
}
.office-modal-empty {
color: #64748b;
font-style: italic;
}
.kpi-modal-sparkline {
width: 100%;
height: 80px;
margin-top: 8px;
background: #10131a;
border-radius: 6px;
}