Fix grouped AVR / room card + add movie info
Deploy HEOS panel / deploy (push) Successful in 25s

This commit is contained in:
2026-09-16 20:36:29 +02:00
parent 69476134f7
commit 532b48ad37
7 changed files with 316 additions and 123 deletions
+42 -36
View File
@@ -13,6 +13,7 @@
--live: #3ddc97;
--warn: #ff7a6b;
--radius: 22px;
--gutter: 16px; /* from the screen's side to a card, and from one card to the next */
}
* { box-sizing: border-box; }
@@ -51,15 +52,20 @@ svg { width: 22px; height: 22px; fill: currentColor; }
.app {
max-width: 520px;
margin: 0 auto;
padding: max(12px, env(safe-area-inset-top)) max(16px, env(safe-area-inset-right))
max(24px, env(safe-area-inset-bottom)) max(16px, env(safe-area-inset-left));
padding: max(12px, env(safe-area-inset-top)) max(var(--gutter), env(safe-area-inset-right))
max(24px, env(safe-area-inset-bottom)) max(var(--gutter), env(safe-area-inset-left));
display: flex;
flex-direction: column;
gap: 14px;
gap: var(--gutter);
}
/* A playing card goes to the top. The rest stay in markup order (rooms as
room_keys lists them, then the AVR), because items with the same order
keep their place, so playing cards keep that order among themselves too.
Only the order changes, not the DOM, so a knob held mid-drag stays put. */
.app > .on-top { order: -1; }
/* --- header ---------------------------------------------------------- */
.top { display: flex; align-items: center; justify-content: space-between; padding: 6px 4px 0; }
.top { order: -2; display: flex; align-items: center; justify-content: space-between; padding: 6px 4px 0; }
.top h1 { margin: 0; line-height: 0; }
.top .logo { height: 34px; width: auto; display: block; }
@@ -84,8 +90,10 @@ svg { width: 22px; height: 22px; fill: currentColor; }
}
.card.offline { opacity: .5; }
/* A tint, not a repaint -- it should read at a glance without competing
with the song title right above it. */
.card.room.playing {
with the song title right above it. A group plays one thing, so it is the
host's card that lights up, not the rooms merged into it. */
.card.room.playing,
.card.source.playing {
background: linear-gradient(135deg,
color-mix(in srgb, var(--live) 25%, var(--card)) 0%,
var(--card) 70%);
@@ -118,6 +126,9 @@ svg { width: 22px; height: 22px; fill: currentColor; }
object-fit: cover;
background: var(--raised);
}
/* A film's jacket keeps its own portrait shape rather than being cropped
square like an album's. */
.cover.poster { width: 50px; height: 75px; border-radius: 9px; }
.track { display: flex; flex-direction: column; min-width: 0; }
.track span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.song { font-size: 20px; font-weight: 550; }
@@ -212,23 +223,27 @@ svg { width: 22px; height: 22px; fill: currentColor; }
.transport.playing .icon-play { display: none; }
.transport.playing .icon-pause { display: block; }
/* --- join / leave the AVR, beside the room's name ---------------------- */
/* --- join / leave the AVR, between the Spotify buttons ----------------- */
/* Styled like the .spotify buttons it sits between -- same height, corner,
type and full-strength ink -- but sized to its own label instead of
sharing the row equally. Like them, it says "not the active one" with a
plain background rather than by dimming itself, so the three read as
equal choices. */
.toggle {
flex: 0 0 auto;
padding: 7px 14px; border-radius: 999px;
height: 50px; padding: 0 14px; border-radius: 16px;
background: var(--raised);
display: flex; align-items: center; justify-content: center; gap: 8px;
font-size: 14px; font-weight: 550; white-space: nowrap;
color: var(--muted);
display: flex; align-items: center; justify-content: center; gap: 9px;
font-size: 15px; font-weight: 550; white-space: nowrap;
}
.toggle .dot { width: 8px; height: 8px; border-radius: 50%; background: currentColor; opacity: .6; }
.toggle .cinema { flex: 0 0 auto; height: 18px; width: auto; color: #fff; }
.toggle .leave { display: none; flex: 0 0 auto; color: #fff; }
.toggle[aria-pressed="true"] { background: var(--accent); color: #fff; }
.toggle[aria-pressed="true"] .dot { background: #fff; opacity: 1; }
.toggle:active { transform: scale(.985); }
.toggle:disabled { opacity: .5; }
.toggle.busy { opacity: .6; }
/* --- Spotify: one resume button per account ----------------------------- */
/* --- Spotify: one resume button per account, around the host toggle ----- */
.spotify-row { display: flex; gap: 10px; }
.spotify {
flex: 1; min-width: 0;
@@ -260,33 +275,24 @@ svg { width: 22px; height: 22px; fill: currentColor; }
.source-button .chevron { color: var(--muted); }
/* --- rooms merged into the host's card --------------------------------- */
.joined { display: flex; flex-direction: column; gap: 12px; }
.joined-title { margin: 0 2px; font-size: 11px; text-transform: uppercase; letter-spacing: .08em; color: var(--muted); }
.joined-rooms { display: flex; flex-direction: column; gap: 14px; }
.joined { display: flex; flex-direction: column; gap: 14px; }
/* The card stops being a card in here: one border around the group, not
one around every room in it. */
.joined .card.room { background: none; border: 0; border-radius: 0; padding: 0; gap: 12px; }
.joined .card.room + .card.room { border-top: 1px solid var(--edge); padding-top: 14px; }
/* Flush against the group's own card, so no radius here -- .playing has
to out-specificity the plain "background: none" above to show at all. */
.joined .card.room.playing {
background: linear-gradient(135deg,
color-mix(in srgb, var(--live) 25%, transparent) 0%,
transparent 70%);
}
/* In here a room is an outline rather than a card: its border is what says
it is playing with the AVR, and the fill -- a tint too, when it plays --
belongs to the group's card instead. Same specificity as
.card.room.playing, so being later is what wins. */
.joined .card.room { background: none; border-color: var(--ink); border-radius: 18px; padding: 14px; gap: 12px; }
.joined .card-head h2 { font-size: 15px; font-weight: 550; color: var(--muted); }
.joined .cover { width: 52px; height: 52px; border-radius: 10px; }
.joined .song { font-size: 18px; }
.joined .step { height: 54px; }
.joined .toggle,
.joined .toggle[aria-pressed="true"] {
height: 36px; font-size: 13px; font-weight: 500;
background: none; border: 1px solid var(--edge); color: var(--muted);
}
.joined .toggle .dot { display: none; }
.joined .spotify { height: 40px; font-size: 13px; font-weight: 500; }
.joined .toggle:active { background: var(--raised); color: var(--ink); }
/* In here the Spotify buttons hide and the toggle says "Detach", so it takes
their place and their look: the whole row, a plain background rather than
the pressed accent, and an exit icon where the host's would only muddle. */
.joined .toggle { flex: 1; min-width: 0; }
.joined .toggle[aria-pressed="true"] { background: var(--raised); color: inherit; }
.joined .toggle .cinema { display: none; }
.joined .toggle .leave { display: block; }
/* --- misc ------------------------------------------------------------- */
.wide { width: 100%; height: 50px; border-radius: 16px; font-size: 15px; }