**Sitzungszimmer statisch.** Die Kamera folgte dem Zeiger um bis zu 7,5 Zentimeter — als Belebung gedacht, als Wackeln wahrgenommen. Entfernt ist nur der Aufruf der Parallaxe samt der nun unbenutzten Methode; Kameraposition, Blickziel, Sitzordnung, Bilder und Beschriftungen sind unverändert. Das Erkennen des Agenten unter dem Zeiger und der Klick auf seinen Platz bleiben — das ist keine Bewegung. **«Meine Objekte» ohne Querscrollen.** Bei automatischer Spaltenbreite richtet sich jede Spalte nach ihrem längsten Inhalt; bei elf Spalten summierte sich das über die Fensterbreite hinaus. Jetzt feste Anteile, die zusammen 100 % ergeben, schmaleres Zellenpolster und Wortumbruch statt `nowrap` beim Mieter. Keine Spalte entfernt, kein Wert gekürzt. **Chats antworten.** Bisher meldete das Absenden nur, der Chat sei nicht angebunden. Jetzt beantwortet jeder Agent — Thomas eingeschlossen — drei Fragetypen aus dem Bearbeitungsverlauf seiner eigenen Seite: Rolle, Anzahl Vorgänge im Log, Vorgänge im Vormonat. Schlüsselwortlogik statt Sprachmodell, wie gefordert. Die Zeitfrage wird vor der Mengenfrage geprüft: «Wie viele Aufträge wurden letzten Monat bearbeitet?» enthält auch das Wort «Aufträge» und würde sonst als Frage nach dem Log gelesen. Findet sich im Zeitraum nichts, sagt der Agent das und nennt zum Vergleich den Gesamtbestand — statt eine plausible Zahl zu erfinden. Eine erfundene Zahl im Chat ist schlimmer als keine Antwort: sie sieht aus wie eine Auskunft. Der Verlauf lebt nur, solange die Seite offen ist. Ein Verlauf, der Tage überdauert, weckte die Erwartung, der Agent erinnere sich. **KI-Hinweis überall gleich.** «KI kann Fehler machen, bitte überprüfen Sie sämtliche Angaben» steht als eine Konstante und eine Komponente in allen sechs Detailansichten. Bei Livia ersetzt er den Quellenvermerk und den Block «Empfohlene nächste Handlung»; die Herkunft steht ohnehin oben bei der Quelle. Geprüft im Browser gegen den Produktionsbau: Szene reagiert nicht mehr auf Mausbewegung (Pixelvergleich), Tabelle 11 Spalten ohne Querscrollen (scrollWidth = clientWidth), alle sechs Chats antworten agentenspezifisch mit Zahlen, die den Mockdaten entsprechen, unbekannte Fragen werden sauber abgewiesen, Hinweis in allen sechs Detailansichten vorhanden, 0 Laufzeitfehler. 423/423 Tests grün, tsc und eslint sauber. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
104 lines
3.7 KiB
TypeScript
104 lines
3.7 KiB
TypeScript
/**
|
||
* Farben und Maße des 3D-Meetingraums (Runde 6, §3/§5).
|
||
*
|
||
* Die Farben stehen als Zahlen und nicht als Hexzeichenketten, weil three.js
|
||
* Zahlen erwartet — `new Color(0x…)` ist der direkte Weg, jede Umwandlung
|
||
* dazwischen wäre nur Umweg. Sie liegen hier statt in der Szene, damit sich die
|
||
* Materialstimmung an einer Stelle ändern lässt (CLAUDE.md §8).
|
||
*
|
||
* Der Raum ist «modern, hochwertig, zurückhaltend, nicht futuristisch»: warmes
|
||
* Eichenholz, heller Putz, Anthrazitteppich, mattgraue Fensterprofile. Als
|
||
* einziger Markenbezug trägt die geschlossene Wand einen schmalen Streifen im
|
||
* Property-Match-Blau (§3 «darf subtil aufgenommen werden»).
|
||
*/
|
||
|
||
export const ROOM_COLORS = {
|
||
floor: 0x4b4741,
|
||
floorSheen: 0x5d5852,
|
||
ceiling: 0xf6f5f2,
|
||
ceilingRail: 0xeeebe5,
|
||
/** Geschlossene Wand rechts: heller Putz mit Eichenpaneel im unteren Drittel. */
|
||
wall: 0xe8e4dc,
|
||
wallPanel: 0x9c7b52,
|
||
wallSkirting: 0xd6d1c7,
|
||
/** Schmaler Markenstreifen auf der geschlossenen Wand. */
|
||
brandStripe: 0x152642,
|
||
/** Fensterprofile und Pfosten. */
|
||
mullion: 0x6b7079,
|
||
frame: 0x585d65,
|
||
/** Glasscheibe: sehr schwacher Blauschleier, sonst wäre sie unsichtbar. */
|
||
glass: 0xd8e8f0,
|
||
/** Tischplatte in Eiche, Kante etwas dunkler. */
|
||
tableTop: 0x8f7350,
|
||
tableEdge: 0x6f5637,
|
||
tableBase: 0x35322f,
|
||
/** Ring um das Porträt — hebt den Kopf vom Hintergrund ab. */
|
||
headRing: 0xffffff,
|
||
/** Ring bei Hover: Gold aus dem Designsystem. */
|
||
headRingHover: 0xb8975a,
|
||
/** Himmel hinter der Kulisse, falls doch ein Rand sichtbar wird. */
|
||
sky: 0xbcd7e6,
|
||
} as const
|
||
|
||
/**
|
||
* Raumgeometrie in Metern. Der Betrachter sitzt am Kopfende bei z ≈ 0 und
|
||
* schaut in Richtung −z; die Fensterfront gegenüber liegt bei z = −ROOM.depth.
|
||
*/
|
||
export const ROOM = {
|
||
width: 7.4,
|
||
height: 3.05,
|
||
depth: 9.2,
|
||
} as const
|
||
|
||
/** Kamera: Augenhöhe einer sitzenden Person am Kopfende (§2). */
|
||
export const CAMERA = {
|
||
/** Sitzende Augenhöhe über dem Boden. */
|
||
eyeHeight: 1.19,
|
||
/** Knapp hinter der vorderen Tischkante. */
|
||
z: 1.9,
|
||
fov: 48,
|
||
/**
|
||
* Obergrenze des waagrechten Bildwinkels in Grad. Greift nur bei sehr breiten
|
||
* und gleichzeitig flachen Fenstern; bei üblichen Seitenverhältnissen liegt
|
||
* der waagrechte Winkel darunter und die Ansicht bleibt unverändert.
|
||
*/
|
||
maxHFov: 84,
|
||
/** Blickziel: leicht unter Augenhöhe, damit die Tischplatte Tiefe zeigt. */
|
||
lookAt: [0, 1.24, -5.2] as const,
|
||
/*
|
||
* Die Parallaxe ist mit Runde 9 (§1) entfallen: Die Kamera folgte dem Zeiger
|
||
* um bis zu 7,5 Zentimeter, was den Raum beleben sollte und stattdessen als
|
||
* Wackeln wahrgenommen wurde. Kameraposition und Blickziel bleiben exakt
|
||
* dieselben — nur bewegt sich nichts mehr.
|
||
*/
|
||
} as const
|
||
|
||
/** Meetingtisch (§5): längliche Form, führt vom Betrachter weg. */
|
||
export const TABLE = {
|
||
width: 1.70,
|
||
/** Höhe der Plattenoberseite über dem Boden. */
|
||
top: 0.745,
|
||
thickness: 0.06,
|
||
/** Vordere Kante, knapp vor der Kamera. */
|
||
zNear: 0.15,
|
||
/** Hintere Kante, vor dem Platz von Thomas. */
|
||
zFar: -5.75,
|
||
} as const
|
||
|
||
/** Sitzende Personen: Höhe der Porträtkreise. */
|
||
export const SEATED = {
|
||
/**
|
||
* Luft zwischen Tischplatte und Unterkante des Porträtkreises (Runde 7, §2).
|
||
*
|
||
* Daraus ergibt sich die Kopfhöhe: `TABLE.top + radius + headGap`. Die Kreise
|
||
* schweben damit nur knapp über der Tischkante statt weit darüber. Vorher
|
||
* hingen sie fest auf 1.52 m — bei den jetzt deutlich grösseren Kreisen sähe
|
||
* das aus, als schwebten Köpfe frei im Raum.
|
||
*
|
||
* Getrennt gehalten werden die Plätze in der Tiefe nicht über die Höhe,
|
||
* sondern seitlich: die Werte in `meetingRoomSeats` sind so gewählt, dass sich
|
||
* im Bild keine zwei Kreise überschneiden.
|
||
*/
|
||
headGap: 0.05,
|
||
} as const
|