/** * 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