feat(startseite): echter 3D-Meetingraum, Navigation in die Topbar
Anpassungsrunde 6. Die Kartendarstellung aus Runde 5 ist ersetzt: die Startseite zeigt oben einen räumlichen Meetingraum aus der Sicht des Betrachters, der selbst am Kopfende des Tisches sitzt. **3D statt Kulisse.** Zwei Versuche mit CSS-Flächen sind daran gescheitert, dass gezeichnete Wände neben fotografierten Porträts erkennbar gezeichnet bleiben. Diese Runde nutzt three.js — die einzige neue Abhängigkeit, und §19 lässt sie ausdrücklich zu, wenn eine schlanke 3D-Lösung die Anforderung trägt. Keine Engine darüber hinaus: kein React-Three-Fiber, keine Physik, keine Shader, keine Post-Processing-Kette, keine Orbit-Steuerung. Der Raum: Boden, Decke, rechts eine geschlossene Wand mit Eichenpaneel und einem schmalen Streifen im Markenblau, links und gegenüber bodentiefe Glasfassaden mit Pfosten. Draussen tragen die beiden Referenzfotos aus dem Auftrag die Basler Aussicht — vorne Rhein, Altstadt und Münster, links der Rheinverlauf mit der Wettsteinbrücke. Die Wasserlinie beider Kulissen liegt auf derselben Welthöhe, damit der Blick nach vorne und nach links zusammengehört und nicht wie zwei zusammengesetzte Bilder wirkt (§4). Am Tisch sitzen alle fünf bestehenden Agenten mit ihren bestehenden Porträts, Namen, Funktionen und Zielseiten — alles aus `AGENT_WORKSPACES`, damit nichts doppelt gepflegt wird (§24, Schritt 7). Neu ist Thomas, Personalverwalter, vis-à-vis am gegenüberliegenden Kopfende; sein Klick führt in die bestehende Ansicht «Meine Agenten». Gerendert wird nur bei Anlass — Grösse, Maus, Hover. Ein Dauerloop wäre für eine feste Szene verschwendete Rechenzeit (§21). Die Kamera folgt der Maus um wenige Zentimeter, mehr nicht (§20). Die Beschriftungen sind HTML über dem Bild, nicht Textur in der Szene: als Textur wären sie bei Tiefe unlesbar. Ein Entzerrungsdurchgang nach der Projektion hebt Plaketten so weit an, bis keine mehr überlappt — gerechnet und nicht handverlesen, damit es auf jeder Fenstergrösse hält. Bei Hover kommt eine Zeile mit der aktuellen Auslastung dazu; ruhend bleiben es Name und Funktion. **Navigation.** Die linke Seitenleiste ist gelöscht, nicht ausgeblendet: samt Breitenreservierung, Einklapplogik und mobilem Drawer. Der Inhalt beginnt überall bei x=0. An der Stelle des früheren Profilsymbols steht neben der Glocke ein Menüsymbol; das Klappmenü öffnet rechts an der Kopfzeile nach unten und führt Startseite, Meine Agenten samt aller Agenten als eingerückte, rechtsbündige Unterpunkte, und Profil mit Profil, Einstellungen, Produkttour und Abmelden. Alle Aktionen und Routen sind die bestehenden. Entfallen sind die Kartenkomponenten aus Runde 5 samt Präsenzschicht. Geprüft (§25): 422 Tests, Typecheck, Build, ESLint, Token-Schwelle (884/925). Im Browser 430–2560 px: keine alte Sidebar, kein leerer Streifen links, sechs Beschriftungen ohne Überlappung, alle sechs Agenten per Maus und per Tastatur erreichbar und auf der richtigen Subpage, Menü öffnet und schliesst per Klick und Escape, alle Menürouten korrekt, alle bestehenden Seiten laden, kein horizontaler Overflow, keine Konsolenfehler. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
e55be64aeb
commit
bf453d2b69
30 files changed
+1408
-1412
No files matched your search
@@ -0,0 +1,96 @@
|
||||
/**
|
||||
* 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,
|
||||
/** Stuhlschalen. */
|
||||
chair: 0x2f343c,
|
||||
/** Anzüge der Agenten, leicht variiert, damit die Reihe nicht uniform wirkt. */
|
||||
suits: [0x2c3444, 0x36302c, 0x2a3a3c, 0x3a2f36, 0x24303a, 0x1f2836],
|
||||
/** 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: 10.6,
|
||||
} as const
|
||||
|
||||
/** Kamera: Augenhöhe einer sitzenden Person am Kopfende (§2). */
|
||||
export const CAMERA = {
|
||||
/** Sitzende Augenhöhe über dem Boden. */
|
||||
eyeHeight: 1.38,
|
||||
/** Knapp hinter der vorderen Tischkante. */
|
||||
z: 1.9,
|
||||
fov: 48,
|
||||
/** Blickziel: leicht unter Augenhöhe, damit die Tischplatte Tiefe zeigt. */
|
||||
lookAt: [0, 1.06, -6.2] as const,
|
||||
/**
|
||||
* Maximaler Kameraversatz der Parallaxe in Metern. Bewusst winzig: die
|
||||
* Perspektive ist verbindlich, die Bewegung darf sie nur beleben (§20).
|
||||
*/
|
||||
parallax: 0.075,
|
||||
} as const
|
||||
|
||||
/** Meetingtisch (§5): längliche Form, führt vom Betrachter weg. */
|
||||
export const TABLE = {
|
||||
width: 1.62,
|
||||
/** 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: -7.35,
|
||||
} as const
|
||||
|
||||
/** Sitzende Personen: Kopfhöhe und Grössen. */
|
||||
export const SEATED = {
|
||||
/** Kopfmitte über dem Boden — deutlich über der Tischplatte. */
|
||||
headY: 1.30,
|
||||
headRadius: 0.155,
|
||||
/** Torso vom Stuhl bis zum Hals. */
|
||||
torsoTop: 1.12,
|
||||
torsoBottom: 0.42,
|
||||
torsoRadiusTop: 0.19,
|
||||
torsoRadiusBottom: 0.25,
|
||||
shoulderWidth: 0.46,
|
||||
} as const
|
||||
Reference in new issue
Block a user