Add "Mein Zimmer" room-control page (Home Assistant, proxied through the backend)

Implements the room-control page from the design mockup: a scenes row above cards
for shutters, color lamps, and brightness-only lamps, all driven by a new
`general.ha` config section (server URL, token, ordered device/scene lists).

The backend proxies every Home Assistant call server-side (GET/POST /api/ha/...)
rather than the browser calling Home Assistant directly, so the long-lived token
never leaves the LAN device and Home Assistant's own CORS settings don't need to
know about musicmouse at all. Card kind (shutter/color/brightness-only) is
inferred at runtime from what Home Assistant reports about each entity, not
configured explicitly.

Also stops tracking python-backend/config.yml, which had drifted into the repo
despite its own header saying it shouldn't be - it now carries real credentials
locally and needs to stay untracked.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-27 23:45:29 +02:00
parent edb6e5e027
commit a8ed350aec
27 changed files with 1437 additions and 163 deletions

54
web/src/styles/room.css Normal file
View File

@@ -0,0 +1,54 @@
/* "Mein Zimmer" (room control). Ported from claude-design/Mein Zimmer.dc.html - the
same oklch-everywhere approach as app.css, but its own violet hue (~298-310) rather
than app.css's teal (~210), so the two pages read as siblings, not one bleeding into
the other. */
:root {
--room-ink: oklch(20% 0.03 300);
--room-paper: oklch(97% 0.01 302);
--room-accent: oklch(62% 0.15 302);
--room-card-bg: oklch(96% 0.012 300 / 0.55);
--room-shadow: oklch(15% 0.05 300 / 0.35);
}
.room-stage {
background: linear-gradient(
180deg,
oklch(56% 0.14 305) 0%,
oklch(38% 0.12 300) 45%,
oklch(21% 0.08 298) 100%
);
}
.room-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 20px;
}
.room-card {
background: var(--room-card-bg);
backdrop-filter: blur(6px);
border-radius: 22px;
padding: 18px 20px 20px;
box-shadow: 0 8px 24px var(--room-shadow);
}
.room-pill {
border: none;
cursor: pointer;
font-size: 15px;
font-weight: 800;
min-height: 52px;
padding: 12px 20px;
border-radius: 999px;
white-space: nowrap;
background: oklch(97% 0.01 302 / 0.18);
color: var(--room-paper);
}
.room-pill[data-active="true"] {
background: var(--room-paper);
color: oklch(26% 0.05 300);
box-shadow: 0 6px 18px oklch(15% 0.05 300 / 0.4);
}