.playerWrap { /* Fixed + inset so it fills the actual viewport regardless of .mainContent's own padding (which used to add to 100vh and push the whole page taller than the screen, causing an outer scrollbar). Also covers the sidebar while playing, like most video players' theater mode - "Quitter" is how you get back to it. */ position: fixed; inset: 0; z-index: 20; background: #000; } .playerWrap video { width: 100%; height: 100%; object-fit: contain; } /* Toggled alongside .bottomBar.minimal (see Player.ts's scheduleControlsHide/ showControls) - a mouse cursor left sitting over the video is the same kind of clutter the bar itself was, once there's nothing left under it to interact with. Any pointermove/pointerdown anywhere in .playerWrap already calls showControls(), so the cursor reappears the instant the mouse moves again - same convention as any other video player's auto-hiding controls. */ .playerWrap.cursorHidden { cursor: none; } /* Two stacked rows, both part of the same top gradient overlay: the action bar (title/members/next/settings/leave) and, below it, the presence avatars - see .presenceOverlay in styles/presence.css. Stacking them in normal flow inside one column means the avatar row always ends up right after the action bar regardless of how tall that bar is (it wraps to two lines on narrow screens), instead of guessing a fixed pixel offset for a second absolutely-positioned block. */ .topOverlay { position: absolute; top: 0; left: 0; right: 0; display: flex; flex-direction: column; gap: 10px; padding: 12px 16px; background: linear-gradient(to bottom, rgba(0,0,0,.7), transparent); z-index: 5; } .actionBar { display: flex; align-items: center; gap: 16px; color: white; font-size: 13px; flex-wrap: wrap; } .actionBar .itemTitle { font-weight: 600; } .actionBar .members { color: var(--muted); flex: 1; } /* Settings: a small gear icon in the action bar, not a permanently-visible block of dropdowns - opens a compact popup on click. */ .settingsWrap { position: relative; } .iconBtn { background: none; padding: 4px 8px; font-size: 16px; line-height: 1; border-radius: 6px; } .iconBtn:hover { background: rgba(255, 255, 255, .12); } /* #castBtn while actively casting - see Player.ts's toggleCast. Same "clearly-on" treatment as .avatarActionRequested's orange, not just a background tint, so it reads at a glance whether the TV or this screen is the one actually playing right now. */ .iconBtn[aria-pressed="true"] { color: #ff9800; background: rgba(255, 152, 0, .18); } .settingsPanel { position: absolute; top: 100%; right: 0; margin-top: 6px; display: flex; flex-direction: column; gap: 10px; background: var(--bg-header); padding: 12px; border-radius: 10px; font-size: 12px; min-width: 180px; box-shadow: 0 8px 24px rgba(0, 0, 0, .4); z-index: 5; } .settingsPanel label { color: var(--muted); margin-bottom: 0; display: flex; flex-direction: column; gap: 4px; } .settingsPanel select { background: var(--panel); color: var(--text); border: 1px solid #3a3a3a; border-radius: 6px; padding: 4px 6px; font-size: 12px; } .settingsPanel select:disabled { opacity: .5; } /* .hint's own bottom margin (base.css) would stack with the panel's own flex `gap` below it - zeroed here so it's spaced exactly like every other row in the column, not a wider gap after this specific one. */ .burnInHint { margin: 0; max-width: 220px; } .loadingNotice { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); color: var(--muted); font-size: 14px; margin: 0; } .playerError { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); max-width: 360px; text-align: center; background: rgba(0, 0, 0, .75); padding: 20px; border-radius: 10px; } .playerError p { color: var(--danger); font-size: 14px; margin: 0 0 10px; } /* Transient toast (see showRequestBanner in Player.ts) - positioned independently near the top so it never fights the persistent .bottomBar below for space, and reads as a pop-in/fade-out notification rather than a fourth thing bolted onto a fixed layout. Centered under .topOverlay's usual (single-line) height - see Player.html's own comment. */ .requestBanner { position: absolute; top: 64px; left: 50%; transform: translateX(-50%); z-index: 7; max-width: calc(100% - 32px); text-align: center; background: rgba(0, 0, 0, .75); color: white; padding: 8px 16px; border-radius: 20px; font-size: 13px; } /* Replaces what used to be three separate floating pieces (a centered banner/notice column, a request toolbar cornered bottom-right, an "Épisode suivant" link in the top bar) AND the browser's native