/* ===================================================================
   GrooVVee — Components
   Reusable UI component styles
   =================================================================== */

/* ── Ambient Background Orbs ────────────────────────────────────── */
/* Was the branded illustration (assets/bg.jpg, with its own colorful
   icons + wordmark) — plain neutral base for now, per product direction
   (no color beyond dark grey). Drifting orbs kept for subtle texture/
   motion, recolored to grey instead of blue/green/yellow. */
.ambient-bg {
  position: fixed;
  inset: 0;
  z-index: var(--z-below);
  overflow: hidden;
  pointer-events: none;
  background: var(--bg-base);
}

.orb {
  position: absolute;
  border-radius: 50%;
  filter: blur(80px);
  animation: orb-drift linear infinite;
}

.orb--1 {
  width: 600px;
  height: 600px;
  background: radial-gradient(circle, rgba(28, 28, 30, 0.07) 0%, transparent 70%);
  top: -200px;
  left: -150px;
  animation-duration: 25s;
}

.orb--2 {
  width: 500px;
  height: 500px;
  background: radial-gradient(circle, rgba(28, 28, 30, 0.05) 0%, transparent 70%);
  bottom: -100px;
  right: -100px;
  animation-duration: 32s;
  animation-direction: reverse;
}

.orb--3 {
  width: 400px;
  height: 400px;
  background: radial-gradient(circle, rgba(28, 28, 30, 0.05) 0%, transparent 70%);
  top: 40%;
  left: 60%;
  animation-duration: 20s;
  animation-delay: -10s;
}

@keyframes orb-drift {
  0%, 100% { transform: translate(0, 0) scale(1); }
  25%       { transform: translate(40px, -30px) scale(1.05); }
  50%       { transform: translate(-20px, 50px) scale(0.95); }
  75%       { transform: translate(-50px, -20px) scale(1.03); }
}

/* ── Splash Screen ──────────────────────────────────────────────────
   Shown immediately on load (plain HTML, no JS needed for first paint),
   removed by main.js once bootstrap finishes — see initSplashScreen(). */
.splash-screen {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-4);
  background: var(--bg-base);
  transition: opacity 300ms var(--ease-out), visibility 300ms;
}

.splash-screen__icon {
  border-radius: var(--radius-lg);
}

.splash-screen__wordmark {
  font-size: 1.75rem;
}

.splash-screen--hidden {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}

/* ── Loading Spinner ────────────────────────────────────────────── */
.page-loader {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 60vh;
}

.spinner {
  width: 36px;
  height: 36px;
  border: 3px solid var(--border-default);
  border-top-color: var(--primary-500);
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

/* ── Buttons ────────────────────────────────────────────────────── */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: 0.625rem var(--space-5);
  border-radius: var(--radius-md);
  font-size: 0.9375rem;
  font-weight: 600;
  line-height: 1;
  transition: all var(--transition-base);
  white-space: nowrap;
  cursor: pointer;
  border: 1px solid transparent;
  position: relative;
  overflow: hidden;
}

.btn svg {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
}

.btn::before {
  content: '';
  position: absolute;
  inset: 0;
  background: rgba(255, 255, 255, 0);
  transition: background var(--transition-fast);
}

.btn:hover::before {
  background: rgba(255, 255, 255, 0.06);
}

.btn:active { transform: scale(0.94); transition: transform 100ms var(--ease-spring); }

/* Primary — the vivid blue→green→yellow→red brand gradient, not solid blue,
   so every primary action reads as the most colorful, "tap me" element. */
.btn--primary {
  background: var(--gradient-mixed);
  background-size: 200% 200%;
  background-position: 0% 50%;
  color: #fff;
  border-color: transparent;
  box-shadow: var(--shadow-glow-sm);
  transition: background-position var(--transition-slow), transform var(--transition-fast), box-shadow var(--transition-fast);
}
.btn--primary:hover {
  background-position: 100% 50%;
  box-shadow: var(--shadow-glow-primary), var(--shadow-glow-accent);
  transform: translateY(-1px);
}
.btn--primary:active { transform: translateY(0) scale(0.98); }

/* Accent */
.btn--accent {
  background: var(--gradient-accent);
  color: var(--text-inverse);
  border-color: transparent;
}
.btn--accent:hover {
  box-shadow: var(--shadow-glow-accent);
  transform: translateY(-1px);
}

/* Secondary / Ghost */
.btn--secondary {
  background: var(--glass-bg);
  color: var(--text-primary);
  border-color: var(--glass-border);
  backdrop-filter: var(--glass-blur);
}
.btn--secondary:hover {
  background: var(--glass-bg-hover);
  border-color: var(--glass-border-hover);
}

/* Ghost */
.btn--ghost {
  background: transparent;
  color: var(--text-secondary);
  border-color: transparent;
}
.btn--ghost:hover {
  background: var(--glass-bg);
  color: var(--text-primary);
}

/* Danger */
.btn--danger {
  background: transparent;
  color: var(--error-500);
  border-color: rgba(239, 68, 68, 0.3);
}
.btn--danger:hover {
  background: rgba(239, 68, 68, 0.1);
  border-color: var(--error-500);
}

/* Sizes */
.btn--sm {
  padding: 0.4375rem var(--space-4);
  font-size: 0.8125rem;
  border-radius: var(--radius-sm);
}
.btn--lg {
  padding: 0.875rem var(--space-7);
  font-size: 1.0625rem;
  border-radius: var(--radius-lg);
}
.btn--xl {
  padding: 1rem var(--space-8);
  font-size: 1.125rem;
  border-radius: var(--radius-lg);
}
.btn--full { width: 100%; }

/* Disabled */
.btn:disabled, .btn[aria-disabled="true"] {
  opacity: 0.4;
  pointer-events: none;
}

/* Icon-only button */
.btn-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--text-secondary);
  transition: all var(--transition-fast);
  flex-shrink: 0;
}
.btn-icon svg {
  width: 20px;
  height: 20px;
}
.btn-icon:hover {
  background: var(--glass-bg-hover);
  color: var(--text-primary);
}
.btn-icon:active { transform: scale(0.93); }

/* ── Cards ──────────────────────────────────────────────────────── */
.card {
  background: var(--glass-bg);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-xl);
  backdrop-filter: var(--glass-blur);
  padding: var(--space-6);
  transition: all var(--transition-base);
  position: relative;
  overflow: hidden;
}

.card::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(15,23,42,0.08), transparent);
  pointer-events: none;
}

.card:hover {
  border-color: var(--glass-border-hover);
  background: var(--glass-bg-hover);
  transform: translateY(-2px);
  box-shadow: var(--shadow-lg);
}

/* Snappy tap feedback on touch — subtle enough that it reads fine even on
   cards whose press event bubbled up from an inner button. */
.card:active {
  transform: scale(0.97);
  transition: transform 100ms var(--ease-spring);
}

.card--glow {
  border-color: var(--border-primary);
  box-shadow: var(--shadow-glow-sm);
}

.card--flat {
  background: var(--bg-surface);
  border-color: var(--border-subtle);
  backdrop-filter: none;
}
.card--flat:hover {
  background: var(--bg-elevated);
  transform: translateY(-1px);
}

/* ── Form Inputs ────────────────────────────────────────────────── */
.form-group {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.form-label {
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--text-secondary);
  letter-spacing: 0.01em;
}

.form-input {
  width: 100%;
  padding: 0.75rem var(--space-4);
  background: rgba(15, 23, 42, 0.03);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  color: var(--text-primary);
  font-size: 0.9375rem;
  transition: all var(--transition-fast);
  -webkit-appearance: none;
}

.form-input::placeholder {
  color: var(--text-muted);
}

.form-input:focus {
  border-color: var(--primary-500);
  background: rgba(28, 28, 30, 0.06);
  box-shadow: 0 0 0 3px rgba(28, 28, 30, 0.15);
}

/* :placeholder-shown never matches a <select> (it has no placeholder attribute
   to show), so :not(:placeholder-shown) is always true there — excluding
   select keeps a required-but-unselected dropdown from showing an error
   border before the user has touched it. */
.form-input:not(select):invalid:not(:placeholder-shown) {
  border-color: var(--error-500);
}

.form-hint {
  font-size: 0.8125rem;
  color: var(--text-muted);
}

.form-error {
  font-size: 0.8125rem;
  color: var(--error-500);
  display: flex;
  align-items: center;
  gap: var(--space-1);
}

.form-input--password {
  padding-right: 3rem;
}

.input-wrapper {
  position: relative;
}

.input-wrapper .input-icon {
  position: absolute;
  left: var(--space-4);
  top: 50%;
  transform: translateY(-50%);
  color: var(--text-muted);
  pointer-events: none;
  width: 18px;
  height: 18px;
}

.input-wrapper .form-input {
  padding-left: 2.75rem;
}

.input-wrapper .input-action {
  position: absolute;
  right: var(--space-3);
  top: 50%;
  transform: translateY(-50%);
  color: var(--text-muted);
  cursor: pointer;
  padding: var(--space-1);
  border-radius: var(--radius-sm);
  transition: color var(--transition-fast);
  background: none;
  border: none;
}
.input-wrapper .input-action:hover { color: var(--text-secondary); }
.input-wrapper .input-action svg { width: 18px; height: 18px; display: block; }

/* ── Badges ─────────────────────────────────────────────────────── */
.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: 0.2rem var(--space-2);
  border-radius: var(--radius-full);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  line-height: 1;
}

.badge svg { width: 10px; height: 10px; }

/* Text colors here are deliberately the DARK end of each scale (600/700),
   not the light 300/400 shades the original dark theme used — those were
   pastel tones meant to pop against near-black backgrounds and read as
   washed-out, low-contrast text on this app's light background. */
/* Decorative-only badges ("New", role tags) — dark grey, no color right
   now. badge--success/error/warning/live below stay color-coded since
   those convey real status, not brand decoration. */
.badge--primary   { background: rgba(28, 28, 30, 0.08); color: var(--text-primary); border: 1px solid rgba(28, 28, 30, 0.2); }
.badge--accent    { background: rgba(28, 28, 30, 0.08); color: var(--text-primary); border: 1px solid rgba(28, 28, 30, 0.2); }
.badge--success   { background: rgba(34, 197, 94, 0.14); color: var(--success-500); border: 1px solid rgba(34, 197, 94, 0.3); }
.badge--error     { background: rgba(239, 68, 68, 0.14); color: var(--error-500); border: 1px solid rgba(239, 68, 68, 0.3); }
.badge--warning   { background: rgba(234, 179, 8, 0.14); color: var(--warning-500); border: 1px solid rgba(234, 179, 8, 0.3); }
.badge--neutral   { background: var(--glass-bg); color: var(--text-secondary); border: 1px solid var(--glass-border); }
.badge--live      { background: rgba(239, 68, 68, 0.16); color: var(--error-500); border: 1px solid rgba(239, 68, 68, 0.4); animation: pulse-badge 2s ease-in-out infinite; }

@keyframes pulse-badge {
  0%, 100% { opacity: 1; }
  50%       { opacity: 0.6; }
}

/* ── Avatar ─────────────────────────────────────────────────────── */
.avatar {
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-full);
  background: var(--gradient-primary);
  font-weight: 700;
  font-size: 0.875rem;
  color: #fff;
  flex-shrink: 0;
  width: 36px;
  height: 36px;
  letter-spacing: 0.02em;
  border: 2px solid rgba(255,255,255,0.1);
}

.avatar--sm  { width: 28px; height: 28px; font-size: 0.6875rem; }
.avatar--lg  { width: 48px; height: 48px; font-size: 1rem; }
.avatar--xl  { width: 64px; height: 64px; font-size: 1.25rem; }
.avatar--2xl { width: 96px; height: 96px; font-size: 1.75rem; }

/* Gemstone avatar frames (modules/_shared/gemstoneFrame.js) — the wrapped
   img/video/initials keeps its own .avatar(--size) class for font-size
   (initials fallback) but must stretch to fill the frame's clip-path
   shape rather than sit at its class's own fixed width/height. */
.gem-frame-media > * { width: 100%; height: 100%; object-fit: cover; border-radius: 0 !important; border: none !important; background: transparent !important; }

/* Live chat panel card (DM chat, and the live chat used by Streaming,
   Concerts, Contests, Battlesphere, Watch Party — see roomWidgets.js's
   mountChatPanel). Used to be a flat inline `height:480px` (etc.) per
   caller — fine on desktop, but on a phone with the on-screen keyboard
   open that fixed height doesn't shrink, so the message input and Send
   button (at the bottom of the box) end up pushed below the visible
   viewport, invisible until you dismiss the keyboard. `--chat-height`
   (set inline per caller) keeps each screen's original desktop height;
   the mobile rule below caps it to whatever's actually left of the
   dynamic viewport, which shrinks live as the keyboard opens on browsers
   that support `dvh` (current Safari/Chrome on iOS and Android). */
.chat-panel {
  display: flex;
  flex-direction: column;
  padding: var(--space-4);
  height: var(--chat-height, 480px);
}
@media (max-width: 640px) {
  .chat-panel {
    height: min(var(--chat-height, 480px), calc(100dvh - 260px));
  }
}

/* ── Chat bubbles (WhatsApp-style shape) ──────────────────────────────
   One shared shape for every chat surface in the app — DM chat
   (modules/social/dmChatPanel.js) and every group/room chat (Battlesphere,
   Contests, Concerts, Watch Party, Streaming, Podcast — all via
   modules/_shared/roomWidgets.js's mountChatPanel). A real WhatsApp bubble
   is a rounded rectangle with ONE corner squared off and a small triangular
   tail growing out of that same corner — built here with a ::after
   pseudo-element clipped into a triangle, not a plain rectangle. Colors
   stay GrooVVee's own (blue for mine / neutral gray for theirs) rather
   than WhatsApp's literal green — this app already avoids recreating
   other platforms' exact branded visuals everywhere else, only ever
   matching the real UX shape/behavior. */
.chat-row {
  display: flex;
  align-items: flex-end;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
}
.chat-row--mine { justify-content: flex-end; }

.chat-bubble {
  position: relative;
  max-width: 75%;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-lg);
  font-size: 0.875rem;
  line-height: 1.4;
  overflow-wrap: anywhere;
  white-space: pre-wrap;
}
.chat-bubble--mine {
  background: var(--info-500);
  color: #fff;
  border-bottom-right-radius: 3px;
}
.chat-bubble--mine::after {
  content: '';
  position: absolute;
  bottom: 0;
  right: -6px;
  width: 12px;
  height: 12px;
  background: var(--info-500);
  clip-path: polygon(0 0, 0 100%, 100% 100%);
}
.chat-bubble--theirs {
  background: var(--bg-overlay);
  color: var(--text-primary);
  border-bottom-left-radius: 3px;
}
.chat-bubble--theirs::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: -6px;
  width: 12px;
  height: 12px;
  background: var(--bg-overlay);
  clip-path: polygon(100% 0, 0 100%, 100% 100%);
}
/* Group/room chat only — WhatsApp shows the sender's name in a distinct
   color at the top of the bubble, but only on messages that aren't yours
   (your own bubbles never need to say who they're from). */
.chat-bubble__sender {
  display: block;
  font-weight: 600;
  font-size: 0.75rem;
  color: var(--primary-600);
  margin-bottom: 2px;
}
.chat-bubble__time {
  display: inline-block;
  font-size: 0.6875rem;
  opacity: 0.7;
  margin-left: var(--space-2);
  float: right;
  margin-top: 3px;
}

/* ── Fullscreen Live View (YouTube/IG-Live-style) ─────────────────────
   Shared by Streaming and Concerts' live detail view: the camera/video
   fills the whole screen (not a 16:9 card in the page flow) with overlay
   controls, and chat lives behind a comment-icon toggle instead of an
   always-open docked panel. Deliberately NOT nested inside a `.page-enter`
   wrapper (that class's animation leaves a non-"none" `transform` on its
   element via its `forwards` fill-mode, which — per the CSS spec — turns
   it into a containing block for any `position:fixed` descendant, so the
   fixed overlay would end up confined to that box instead of the real
   viewport). z-index sits at --z-modal so toasts (--z-toast, higher)
   still show above it, but it still covers the app's own sidebar/bottom
   nav (--z-sidebar, lower) the same way a real fullscreen player would. */
.live-fullscreen {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
  background: #000;
  overflow: hidden;
}
/* router.js's _renderRoute unconditionally re-adds 'page-enter' to
   #main-content right after every route swap (to retrigger the fade-in
   animation), even if a module removes it — so neutralizing the class
   from inside a module (as this one briefly tried) never sticks. This
   :has() rule reacts to the CONTENT instead of fighting that class
   toggle: whenever #main-content contains a .live-fullscreen child, force
   its transform to the literal `none` (not just an identity matrix),
   which is what actually stops it from being a containing block for
   .live-fullscreen's `position:fixed`. */
#main-content:has(> .live-fullscreen) {
  transform: none !important;
  animation: none !important;
}
.live-fullscreen__media {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
.live-fullscreen__media video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.live-fullscreen__top-bar {
  position: absolute;
  top: 0; left: 0; right: 0;
  padding: var(--space-4);
  padding-top: max(var(--space-4), env(safe-area-inset-top));
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  z-index: 2;
  background: linear-gradient(rgba(0,0,0,0.55), transparent);
}
.live-fullscreen__top-bar .btn-icon,
.live-fullscreen__action-rail button,
.live-fullscreen__controls-bar .btn-icon {
  background: rgba(0,0,0,0.4);
  color: #fff;
  border-color: transparent;
}
/* One flex-column stack instead of several independently bottom:0-anchored
   blocks — .info/.controls-bar/the reaction mount used to all occupy the
   same rectangle and visually collide (title text under the End Stream
   button, reactions floating over both). Order here is visual order:
   reactions float just above the info text, which sits just above the
   owner's control bar (or the viewer's screen-frame/filter controls). */
.live-fullscreen__bottom-overlay {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  padding: var(--space-3) 76px var(--space-3) var(--space-4); /* right padding clears the action rail */
  padding-bottom: max(var(--space-3), env(safe-area-inset-bottom));
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  z-index: 2;
  background: linear-gradient(transparent, rgba(0,0,0,0.8));
}
.live-fullscreen__info h1 { color: #fff; margin: 0; }
.live-fullscreen__info .text-secondary { color: rgba(255,255,255,0.85); }
.live-fullscreen__reactions-row {
  position: relative;
  height: 0;
  align-self: flex-start;
}
.live-fullscreen__action-rail {
  position: absolute;
  right: var(--space-3);
  bottom: var(--space-4);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-4);
  z-index: 3;
}
.live-fullscreen__action-rail button {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  font-size: 0.6875rem;
  padding: var(--space-2);
  border-radius: var(--radius-full);
  min-width: 44px;
  min-height: 44px;
}
.live-fullscreen__controls-bar {
  display: flex;
  gap: var(--space-2);
  flex-wrap: wrap;
}
.live-fullscreen__chat-drawer {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  max-height: 65%;
  min-height: 40%;
  background: var(--bg-surface);
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  box-shadow: var(--shadow-xl);
  z-index: 4;
  display: flex;
  flex-direction: column;
  padding: var(--space-3) 0 0;
}
.live-fullscreen__chat-drawer[hidden] { display: none; }
.live-fullscreen__chat-drawer-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 var(--space-4) var(--space-3);
  border-bottom: 1px solid var(--border-subtle);
  flex-shrink: 0;
}

/* Rich chat input (modules/_shared/richChatInput.js) — emoji/sticker
   picker trays, and the mic button's recording state. */
.rich-chat-picker {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
  padding: var(--space-2);
  border-top: 1px solid var(--border-subtle);
  margin-bottom: var(--space-2);
}
.rci-mic-btn--recording {
  background: var(--error-500);
  color: #fff;
  animation: pulse-dot 1.2s ease-in-out infinite;
}

/* Global call overlay (modules/_shared/globalCall.js) — WhatsApp-style
   round controls. Lives on a near-black call background regardless of
   light/dark theme, so colors are hardcoded here rather than themed. */
.gc-round-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  border: none;
  background: rgba(255,255,255,0.16);
  color: #fff;
  cursor: pointer;
  flex-shrink: 0;
}
.gc-round-btn svg { width: 24px; height: 24px; }
.gc-round-btn:hover { background: rgba(255,255,255,0.26); }
.gc-round-btn--sm { width: 38px; height: 38px; }
.gc-round-btn--sm svg { width: 18px; height: 18px; }
.gc-round-btn--active { background: #fff; color: #111; }
.gc-round-btn--danger { background: var(--error-500, #ef4444); }
.gc-round-btn--danger:hover { background: var(--error-600, #dc2626); }
.gc-round-btn--accept { background: var(--success-500, #22c55e); }
.gc-round-btn--accept:hover { background: var(--success-600, #16a34a); }

/* Real presence (services/presenceService.js) — online is the one place
   this app still uses a functional color (green), same as live/error
   status elsewhere; not part of the "no color" decorative palette. */
.presence-dot {
  position: absolute;
  bottom: -1px;
  right: -1px;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--success-500);
  border: 2px solid var(--bg-surface);
}

.avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: inherit;
}

/* Avatar button (clickable) */
.avatar-btn {
  cursor: pointer;
  border: none;
  background: none;
  padding: 2px;
  border-radius: var(--radius-full);
  transition: all var(--transition-fast);
}
.avatar-btn:hover .avatar {
  box-shadow: 0 0 0 3px var(--primary-500);
}

/* ── Search Bar ─────────────────────────────────────────────────── */
.search-bar {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  background: var(--glass-bg);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-full);
  padding: 0 var(--space-4);
  transition: all var(--transition-fast);
  max-width: 400px;
  width: 100%;
}

.search-bar:focus-within {
  border-color: var(--primary-500);
  background: rgba(28, 28, 30, 0.06);
  box-shadow: 0 0 0 3px rgba(28, 28, 30, 0.12);
}

.search-bar__icon {
  width: 16px;
  height: 16px;
  color: var(--text-muted);
  flex-shrink: 0;
}

.search-bar__input {
  background: transparent;
  border: none;
  color: var(--text-primary);
  font-size: 0.875rem;
  width: 100%;
  height: 38px;
  padding: 0;
}
.search-bar__input::placeholder { color: var(--text-muted); }

.search-bar__mic {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 26px;
  height: 26px;
  margin: 0 -6px 0 0;
  border-radius: 50%;
  border: none;
  background: none;
  color: var(--text-muted);
  cursor: pointer;
  transition: color var(--transition-fast), background var(--transition-fast);
}
.search-bar__mic:hover { color: var(--text-primary); background: var(--glass-bg-hover); }
.search-bar__mic svg { width: 16px; height: 16px; }
.search-bar__mic:disabled { opacity: 0.4; cursor: not-allowed; }
.search-bar__mic--listening {
  color: var(--text-inverse);
  background: var(--text-primary);
  animation: voice-pulse 1.2s ease-in-out infinite;
}

/* ── Toasts ─────────────────────────────────────────────────────── */
.toast-container {
  position: fixed;
  top: calc(var(--topbar-height) + var(--space-4));
  right: var(--space-6);
  z-index: var(--z-toast);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  pointer-events: none;
}

.toast {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  background: var(--bg-elevated);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xl);
  min-width: 280px;
  max-width: 400px;
  pointer-events: all;
  animation: toast-slide-in var(--duration-slow) var(--ease-out) forwards;
  position: relative;
  overflow: hidden;
}

.toast::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 3px;
}

.toast--success::before { background: var(--success-500); }
.toast--error::before   { background: var(--error-500); }
.toast--warning::before { background: var(--warning-500); }
.toast--info::before    { background: var(--info-500); }

.toast__icon {
  width: 20px;
  height: 20px;
  flex-shrink: 0;
  margin-top: 1px;
}

.toast--success .toast__icon { color: var(--success-500); }
.toast--error .toast__icon   { color: var(--error-500); }
.toast--warning .toast__icon { color: var(--warning-500); }
.toast--info .toast__icon    { color: var(--info-500); }

.toast__body { flex: 1; min-width: 0; }

.toast__title {
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--text-primary);
  line-height: 1.3;
}

.toast__message {
  font-size: 0.8125rem;
  color: var(--text-secondary);
  margin-top: 2px;
  line-height: 1.5;
}

.toast__close {
  width: 24px;
  height: 24px;
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  cursor: pointer;
  transition: all var(--transition-fast);
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: none;
  padding: 0;
}
.toast__close svg { width: 14px; height: 14px; }
.toast__close:hover { color: var(--text-primary); background: var(--glass-bg); }

.toast--removing {
  animation: toast-slide-out var(--duration-base) var(--ease-in-out) forwards;
}

@keyframes toast-slide-in {
  from {
    opacity: 0;
    transform: translateX(120%) scale(0.95);
  }
  to {
    opacity: 1;
    transform: translateX(0) scale(1);
  }
}

@keyframes toast-slide-out {
  from {
    opacity: 1;
    transform: translateX(0) scale(1);
    max-height: 200px;
    margin-bottom: 0;
  }
  to {
    opacity: 0;
    transform: translateX(120%) scale(0.9);
    max-height: 0;
    margin-bottom: calc(var(--space-3) * -1);
  }
}

/* ── Notification Dot ───────────────────────────────────────────── */
.notification-dot {
  position: absolute;
  top: 5px;
  right: 5px;
  width: 8px;
  height: 8px;
  background: var(--error-500);
  border-radius: 50%;
  border: 2px solid var(--bg-base);
  animation: pulse-dot 2s ease-in-out infinite;
}

@keyframes pulse-dot {
  0%, 100% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.4); }
  50%       { box-shadow: 0 0 0 4px rgba(239, 68, 68, 0); }
}

/* Btn-icon relative positioning for dot */
.btn-icon { position: relative; }

/* Notifications bell badge — same red "count" pill as most apps put on a
   bell icon (e.g. "9+" once it's more than one digit's worth of room). */
.topbar__notif-badge {
  position: absolute;
  top: 2px;
  right: 2px;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: var(--radius-full);
  background: var(--error-500);
  color: #fff;
  font-size: 0.625rem;
  font-weight: 700;
  line-height: 16px;
  text-align: center;
}

/* ── Dropdown Menu ──────────────────────────────────────────────── */
.dropdown {
  position: fixed;
  background: var(--bg-elevated);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-xl);
  padding: var(--space-2);
  min-width: 220px;
  z-index: var(--z-dropdown);
  animation: dropdown-pop var(--duration-base) var(--ease-spring) forwards;
  backdrop-filter: var(--glass-blur);
  /* Grows to fit its content by default (fine for a couple of items), but
     the language list alone now has 10 entries — without a cap it can
     render past the bottom of the screen with no way to reach the rest.
     Capped + scrollable here so every .dropdown (notifications, account,
     language) stays fully reachable regardless of how many items it holds. */
  max-height: min(420px, 70vh);
  overflow-y: auto;
}

/* The account dropdown's trigger lives inside the sidebar now (bottom-left
   footer) — the sidebar's own z-index (200) sits above the base .dropdown
   z-index (100), so without this it opens invisibly behind the sidebar
   panel itself. */
#user-dropdown {
  z-index: var(--z-modal);
}

@keyframes dropdown-pop {
  from { opacity: 0; transform: scale(0.95) translateY(-8px); }
  to   { opacity: 1; transform: scale(1) translateY(0); }
}

.dropdown__header {
  padding: var(--space-3) var(--space-3) var(--space-2);
  position: sticky;
  top: 0;
  background: var(--bg-elevated);
  z-index: 1;
}

.dropdown__header .user-email {
  font-size: 0.75rem;
  color: var(--text-muted);
  margin-top: 2px;
}

.dropdown__header .user-role-badge {
  margin-top: var(--space-2);
}

.dropdown__divider {
  height: 1px;
  background: var(--border-subtle);
  margin: var(--space-2) 0;
}

.dropdown__item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  padding: var(--space-3) var(--space-3);
  border-radius: var(--radius-md);
  font-size: 0.9375rem;
  font-weight: 500;
  color: var(--text-secondary);
  text-align: left;
  cursor: pointer;
  transition: all var(--transition-fast);
  background: none;
  border: none;
}
.dropdown__item svg { width: 18px; height: 18px; flex-shrink: 0; }
.dropdown__item:hover {
  background: var(--glass-bg-hover);
  color: var(--text-primary);
}
.dropdown__item--danger { color: var(--error-500); }
.dropdown__item--danger:hover { background: rgba(239, 68, 68, 0.1); }

/* ── Tabs ───────────────────────────────────────────────────────── */
.tabs {
  display: flex;
  background: var(--glass-bg);
  border-radius: var(--radius-lg);
  padding: 3px;
  border: 1px solid var(--glass-border);
  width: fit-content;
}

.tab-btn {
  padding: 0.5rem var(--space-5);
  border-radius: calc(var(--radius-lg) - 3px);
  font-size: 0.9375rem;
  font-weight: 500;
  color: var(--text-muted);
  transition: all var(--transition-base);
  cursor: pointer;
  background: none;
  border: none;
  white-space: nowrap;
}

.tab-btn.active {
  background: var(--glass-bg-active);
  color: var(--text-primary);
  box-shadow: var(--shadow-sm);
}

.tab-btn:hover:not(.active) {
  color: var(--text-secondary);
}

/* ── Progress Bar ───────────────────────────────────────────────── */
.progress {
  width: 100%;
  height: 4px;
  background: var(--border-subtle);
  border-radius: var(--radius-full);
  overflow: hidden;
}

.progress__bar {
  height: 100%;
  border-radius: inherit;
  background: var(--gradient-primary);
  transition: width var(--duration-slow) var(--ease-out);
}

/* ── Divider ────────────────────────────────────────────────────── */
.divider {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  color: var(--text-muted);
  font-size: 0.8125rem;
}

.divider::before,
.divider::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--border-subtle);
}

/* ── Stat Tile ──────────────────────────────────────────────────── */
.stat-tile {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding: var(--space-5) var(--space-6);
  background: var(--glass-bg);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-xl);
  backdrop-filter: var(--glass-blur);
  transition: all var(--transition-base);
}

.stat-tile:hover {
  border-color: var(--border-primary);
  box-shadow: var(--shadow-glow-sm);
  transform: translateY(-2px);
}

.stat-tile__label {
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.stat-tile__value {
  font-family: 'Times New Roman', Times, serif;
  font-size: 1.875rem;
  font-weight: 800;
  color: var(--text-primary);
  line-height: 1;
  letter-spacing: -0.03em;
}

.stat-tile__sub {
  font-size: 0.8125rem;
  color: var(--success-500);
  display: flex;
  align-items: center;
  gap: var(--space-1);
}

/* ── Module Placeholder (Coming Soon) ───────────────────────────── */
.module-placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: calc(100vh - var(--topbar-height) - var(--space-16));
  padding: var(--space-12) var(--space-6);
  text-align: center;
  gap: var(--space-6);
}

.module-placeholder__icon {
  width: 80px;
  height: 80px;
  /* Tinted to whatever `color` each module sets inline, not a fixed glass
     tone — on the light theme a flat translucent-white box with a generic
     blue glow behind it (the old dark-theme design) washed out badly for
     non-blue icons (e.g. Shop's yellow). currentColor keeps every module's
     icon readable regardless of its accent color. */
  background: color-mix(in srgb, currentColor 14%, var(--bg-surface));
  border: 1.5px solid color-mix(in srgb, currentColor 45%, transparent);
  border-radius: var(--radius-2xl);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--primary-500);
  box-shadow: var(--shadow-sm);
  position: relative;
}

.module-placeholder__icon svg {
  width: 40px;
  height: 40px;
}

.module-placeholder__icon::before {
  content: '';
  position: absolute;
  inset: -2px;
  border-radius: calc(var(--radius-2xl) + 2px);
  background: currentColor;
  z-index: -1;
  opacity: 0.18;
  filter: blur(10px);
}

.module-placeholder__badge-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
  justify-content: center;
}

.module-placeholder__title {
  font-family: 'Times New Roman', Times, serif;
  font-size: clamp(1.75rem, 4vw, 2.5rem);
  font-weight: 800;
  letter-spacing: -0.03em;
  color: var(--text-primary);
}

.module-placeholder__desc {
  font-size: 1.0625rem;
  color: var(--text-secondary);
  max-width: 480px;
  line-height: 1.7;
}

.module-placeholder__features {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  justify-content: center;
  max-width: 560px;
}

.feature-chip {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-4);
  background: var(--glass-bg);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-full);
  font-size: 0.875rem;
  color: var(--text-secondary);
  backdrop-filter: var(--glass-blur);
  transition: all var(--transition-base);
}

.feature-chip:hover {
  border-color: var(--border-primary);
  color: var(--text-primary);
}

.feature-chip svg {
  width: 14px;
  height: 14px;
  color: var(--primary-400);
}

/* ── Page Section ───────────────────────────────────────────────── */
.section {
  padding: var(--space-8) var(--space-8);
}

.section-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: var(--space-6);
}

.section-title {
  font-family: 'Times New Roman', Times, serif;
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--text-primary);
  letter-spacing: -0.02em;
}

.section-subtitle {
  font-size: 0.875rem;
  color: var(--text-muted);
  margin-top: var(--space-1);
}

/* ── Role Badge ─────────────────────────────────────────────────── */
.role-badge--fan     { background: rgba(28, 28, 30, 0.14); color: var(--text-primary); border: 1px solid rgba(28, 28, 30, 0.3); }
.role-badge--creator { background: rgba(28, 28, 30, 0.14); color: var(--text-primary); border: 1px solid rgba(28, 28, 30, 0.3); }
.role-badge--admin   { background: rgba(28, 28, 30, 0.14); color: var(--text-primary); border: 1px solid rgba(28, 28, 30, 0.3); }

/* ── Grid Layouts ───────────────────────────────────────────────── */
.grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--space-5); }
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-5); }
.grid-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-5); }
.grid-auto { display: grid; grid-template-columns: repeat(auto-fill, minmax(var(--card-min-width), 1fr)); gap: var(--space-5); }

@media (max-width: 1024px) {
  .grid-4 { grid-template-columns: repeat(2, 1fr); }
  .grid-3 { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 640px) {
  .grid-4, .grid-3, .grid-2 { grid-template-columns: 1fr; }
}

/* Two-column detail layouts (streaming/contests/battlesphere/concerts/
   watch-party detail views: media+info beside chat) — stack on phones and
   tablets so the sidebar column never gets squeezed unreadably narrow. */
@media (max-width: 900px) {
  .detail-split-grid { grid-template-columns: 1fr !important; }
}

/* ── Utility flex ───────────────────────────────────────────────── */
.flex         { display: flex; }
.flex-col     { display: flex; flex-direction: column; }
.flex-center  { display: flex; align-items: center; justify-content: center; }
.flex-between { display: flex; align-items: center; justify-content: space-between; }
.items-center { align-items: center; }
.gap-2  { gap: var(--space-2); }
.gap-3  { gap: var(--space-3); }
.gap-4  { gap: var(--space-4); }
.gap-6  { gap: var(--space-6); }

/* ── Page Transition ────────────────────────────────────────────── */
.page-enter {
  animation: page-fade-in 260ms var(--ease-spring) forwards;
}

@keyframes page-fade-in {
  from { opacity: 0; transform: translateY(8px) scale(0.99); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

/* ── Dashboard Widget Grid ──────────────────────────────────────── */
.widget-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-5);
  align-items: start;
}
.widget-wrapper--full   { grid-column: span 4; }
.widget-wrapper--half   { grid-column: span 2; }
.widget-wrapper--third  { grid-column: span 1; }
.widget-wrapper--quarter { grid-column: span 1; }

@media (max-width: 1024px) {
  .widget-grid { grid-template-columns: repeat(2, 1fr); }
  .widget-wrapper--full  { grid-column: span 2; }
  .widget-wrapper--half  { grid-column: span 1; }
  .widget-wrapper--third,
  .widget-wrapper--quarter { grid-column: span 1; }
}
@media (max-width: 640px) {
  .widget-grid { grid-template-columns: 1fr; }
  .widget-wrapper--full,
  .widget-wrapper--half,
  .widget-wrapper--third,
  .widget-wrapper--quarter { grid-column: span 1; }
}

/* ── Widget Cards ───────────────────────────────────────────────── */
.widget-card {
  min-height: 160px;
  position: relative;
  overflow: hidden;
  transition: transform var(--transition-base);
}
.widget-card:hover { transform: translateY(-2px); }
.widget-card__icon {
  width: 40px;
  height: 40px;
  border-radius: var(--radius-md);
  border: 1px solid;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.widget-card__label {
  font-size: 0.9375rem;
  font-weight: 700;
  color: var(--text-primary);
  margin-bottom: var(--space-1);
}
.widget-card__coming-soon {
  font-size: 0.75rem;
  color: var(--text-muted);
  font-style: italic;
}
.widget-card--placeholder {
  background: var(--glass-bg);
}
.widget-loading {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 120px;
}

/* Widget shimmer effect */
.widget-shimmer {
  position: absolute;
  bottom: 0;
  right: 0;
  width: 80px;
  height: 80px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(28, 28, 30,0.06) 0%, transparent 70%);
  pointer-events: none;
}

/* ── Dashboard Banner ───────────────────────────────────────────── */
.dashboard-tier-badge {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-full);
  border: 1px solid;
  font-size: 0.8125rem;
}
.dashboard-tier-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  flex-shrink: 0;
}

/* ── Enterprise Banner ──────────────────────────────────────────── */
.enterprise-banner {
  border-left: 3px solid var(--accent-300);
}

/* ── Role badges — enterprise ───────────────────────────────────── */
.role-badge--enterprise {
  background: rgba(28, 28, 30, 0.14);
  color: var(--accent-700);
  border: 1px solid rgba(28, 28, 30, 0.3);
}

/* ── Room Reaction Float (Contests, Battlesphere, Concerts, Watch Party) ── */
@keyframes reaction-float {
  0%   { opacity: 1; transform: translate(0, 0) scale(1); }
  100% { opacity: 0; transform: translate(0, -60px) scale(1.4); }
}

/* ── AI Studio tool cards ───────────────────────────────────────── */
.tool-card--active {
  border-color: var(--primary-500) !important;
  background: rgba(28, 28, 30, 0.06) !important;
  box-shadow: 0 0 0 1px var(--primary-500), var(--shadow-glow-sm);
}

/* ── Netflix-style horizontal carousel row ─────────────────────────── */
.carousel-row {
  display: flex;
  gap: var(--space-4);
  overflow-x: auto;
  scroll-snap-type: x proximity;
  padding-bottom: var(--space-3);
  scrollbar-width: thin;
}
.carousel-row > * {
  scroll-snap-align: start;
  flex-shrink: 0;
}

/* ── Hero banner ────────────────────────────────────────────────── */
.hero-banner {
  position: relative;
  border-radius: var(--radius-2xl);
  overflow: hidden;
  min-height: 320px;
  display: flex;
  align-items: flex-end;
  padding: var(--space-8);
  background: var(--gradient-mixed);
  box-shadow: var(--shadow-xl);
}
.hero-banner::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(0deg, rgba(15,23,42,0.55) 0%, rgba(15,23,42,0.05) 60%);
}
.hero-banner__content { position: relative; z-index: 1; color: #fff; max-width: 560px; }

/* ── Voice Assistant (floating mic) ────────────────────────────────── */
/* Inline in the topbar's icon row now (next to the notification bell),
   not a separate floating button — .btn-icon.topbar__quick-icon (already
   on this element) supplies the sizing/layout, this just supplies the
   explicit orange: the rest of the app stays grey/no-color, this one
   button is a deliberate, requested exception. */
.voice-btn {
  border-radius: var(--radius-full);
  background: linear-gradient(135deg, #FFB86B, #FF922B);
  color: #fff;
  box-shadow: 0 0 12px rgba(255, 146, 43, 0.35);
  transition: transform var(--transition-fast);
}
.voice-btn:hover { transform: scale(1.08); background: linear-gradient(135deg, #FFB86B, #FF922B); }
.voice-btn:disabled { opacity: 0.4; cursor: not-allowed; }
.voice-btn--listening {
  background: var(--gradient-accent);
  animation: voice-pulse 1.2s ease-in-out infinite;
}
@keyframes voice-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(28, 28, 30,0.5); }
  50%      { box-shadow: 0 0 0 10px rgba(28, 28, 30,0); }
}

/* ── Netflix-style browse row (VOD library) ─────────────────────────
   Horizontal-scrolling poster cards that scale up on hover, like Netflix's
   own browse rows — distinct from the TikTok-style vertical feed used for
   Home; a video library suits "browse and pick," not "swipe one at a time." */
.netflix-row {
  display: flex;
  gap: var(--space-3);
  overflow-x: auto;
  padding-bottom: var(--space-2);
  scrollbar-width: thin;
}

.netflix-card {
  flex: 0 0 220px;
  cursor: pointer;
  transition: transform 200ms var(--ease-out), z-index 0s;
  transform-origin: center;
}

.netflix-card:hover {
  transform: scale(1.08);
  z-index: 2;
}

.netflix-card:active {
  transform: scale(1.03);
}

.netflix-card__poster {
  position: relative;
  aspect-ratio: 16/9;
  border-radius: var(--radius-md);
  background: linear-gradient(135deg, #18181b, #000);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  box-shadow: var(--shadow-md);
}

.netflix-card:hover .netflix-card__poster {
  box-shadow: var(--shadow-xl);
}

.netflix-card__duration {
  position: absolute;
  bottom: var(--space-2);
  right: var(--space-2);
}

.netflix-card__hover-play {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0,0,0,0.35);
  color: #fff;
  opacity: 0;
  transition: opacity 150ms var(--ease-out);
}

.netflix-card:hover .netflix-card__hover-play,
.netflix-card:focus-visible .netflix-card__hover-play {
  opacity: 1;
}

.netflix-card__meta {
  padding: var(--space-2) 2px 0;
}

/* TikTok-Live-style floating heart burst — see _burstHeart() in modules/streaming/index.js */
@keyframes live-heart-float {
  0%   { transform: translate(0, 0) scale(0.6); opacity: 0; }
  15%  { transform: translate(-6px, -20px) scale(1.1); opacity: 1; }
  100% { transform: translate(-24px, -160px) scale(0.9); opacity: 0; }
}

/* ── TikTok-style Vertical Feed (Home) ──────────────────────────────
   One item fills the available viewport height; scroll/swipe snaps to
   the next, exactly like TikTok/Reels/Shorts. Colors stay this app's
   own — only the layout is copied. .home-page is a flex column so the
   live status bar (when present) takes only the room it needs and the
   feed fills the rest — no live streams, no bar, feed still fills 100%. */

.home-page {
  display: flex;
  flex-direction: column;
  height: calc(100dvh - var(--topbar-height) - var(--bottom-nav-height));
}

.feed-scroller {
  flex: 1;
  min-height: 0;
  overflow-y: scroll;
  scroll-snap-type: y mandatory;
  scroll-behavior: smooth;
  background: #000;
}

.feed-item {
  position: relative;
  height: 100%;
  width: 100%;
  scroll-snap-align: start;
  scroll-snap-stop: always;
  overflow: hidden;
  cursor: default;
}

.feed-item--live { cursor: pointer; }

.feed-item__bg {
  position: absolute;
  inset: 0;
  background: #000;
}

.feed-item__overlay {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: var(--space-6);
  padding-right: 88px; /* keep clear of the right-side icon rail */
  padding-bottom: var(--space-10);
  background: linear-gradient(to top, rgba(0,0,0,0.65) 0%, rgba(0,0,0,0.15) 40%, transparent 70%);
  pointer-events: none;
}

.feed-item__overlay > * { pointer-events: auto; }

.feed-item__author {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
  cursor: pointer;
  width: fit-content;
}

.feed-item__caption {
  color: #fff;
  font-size: 0.9375rem;
  line-height: 1.4;
  max-width: 480px;
  text-shadow: 0 1px 3px rgba(0,0,0,0.4);
}

.feed-item__mute-btn {
  position: absolute;
  top: var(--space-4);
  right: var(--space-4);
  z-index: 2;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: none;
  background: rgba(0,0,0,0.4);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.feed-item__mute-btn svg { width: 18px; height: 18px; }

.feed-item__rail {
  position: absolute;
  right: var(--space-4);
  bottom: var(--space-10);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-5);
  z-index: 2;
}

.feed-item__rail-avatar {
  position: relative;
  margin-bottom: var(--space-2);
  cursor: pointer;
}

.feed-item__rail-avatar .avatar {
  border: 2px solid #fff;
}

.feed-item__follow-btn {
  position: absolute;
  bottom: -8px;
  left: 50%;
  transform: translateX(-50%);
  width: 20px;
  height: 20px;
  border-radius: 50%;
  border: none;
  background: var(--gradient-accent);
  color: #fff;
  font-size: 0.75rem;
  font-weight: 800;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.feed-item__follow-btn[data-following="true"] { background: var(--success-500); }

.feed-item__rail-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  background: none;
  border: none;
  cursor: pointer;
  color: #fff;
}

.feed-item__rail-icon {
  display: flex;
  filter: drop-shadow(0 1px 3px rgba(0,0,0,0.5));
  transition: transform 100ms var(--ease-spring);
}

.feed-item__rail-icon svg {
  width: 30px;
  height: 30px;
}

.post-icon {
  display: inline-flex;
  vertical-align: -5px;
}

.post-icon svg {
  width: 16px;
  height: 16px;
}

.feed-item__rail-btn:active .feed-item__rail-icon { transform: scale(1.3); }

.feed-item__rail-count {
  font-size: 0.75rem;
  font-weight: 600;
  text-shadow: 0 1px 3px rgba(0,0,0,0.5);
}

.feed-item__comments {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  max-height: 60%;
  background: var(--bg-surface);
  border-radius: var(--radius-2xl) var(--radius-2xl) 0 0;
  box-shadow: var(--shadow-xl);
  z-index: 3;
  display: flex;
  flex-direction: column;
  padding: var(--space-4);
  animation: page-fade-in 200ms var(--ease-spring) forwards;
}

.feed-item__comments-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--space-3);
}

.feed-item__comments-list {
  flex: 1;
  overflow-y: auto;
  margin-bottom: var(--space-3);
}

.feed-item__comment-form {
  display: flex;
  gap: var(--space-2);
}

@media (min-width: 768px) {
  /* width:100% is required here, not just max-width — .feed-scroller is a
     flex item (see .home-page) whose children are all position:absolute,
     so it has no normal-flow content to derive a shrink-to-fit width from;
     without an explicit width, the auto side-margins below collapse it to
     0 instead of centering it. */
  .feed-scroller { width: 100%; max-width: 480px; margin: 0 auto; }
  .live-status-bar { width: 100%; max-width: 480px; margin: 0 auto; }
}

/* ── YouTube-style category chips ────────────────────────────────────
   Sits above the live status bar / feed, same flex-shrink:0 pattern as
   .live-status-bar below so the feed still fills the rest of the column. */

.home-category-bar {
  display: flex;
  gap: var(--space-2);
  padding: 0 var(--space-4) var(--space-3);
  overflow-x: auto;
  background: var(--bg-surface);
  border-bottom: 1px solid var(--border-subtle);
  flex-shrink: 0;
  scrollbar-width: none;
}

.home-category-bar::-webkit-scrollbar { display: none; }

.home-category-chip {
  flex-shrink: 0;
  white-space: nowrap;
  padding: 0.5rem var(--space-4);
  border-radius: var(--radius-full);
  border: none;
  background: var(--bg-overlay);
  color: var(--text-primary);
  font-size: 0.8125rem;
  font-weight: 600;
  cursor: pointer;
  transition: background var(--transition-fast), color var(--transition-fast);
}

.home-category-chip:hover { background: var(--glass-bg-active); }

.home-category-chip.active {
  background: var(--text-primary);
  color: var(--text-inverse);
}

.home-category-chip--custom-feed {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.home-category-chip__icon {
  display: inline-flex;
  width: 14px;
  height: 14px;
  flex-shrink: 0;
}

/* ── "Your custom feed" builder ──────────────────────────────────────
   Takes over the #feed area (see .feed-scroller--plain below) with a
   plain scrollable panel instead of the vertical snap feed. */

.feed-scroller--plain {
  scroll-snap-type: none;
  background: var(--bg-base);
  display: flex;
  justify-content: center;
}

.custom-feed-builder {
  width: 100%;
  max-width: 480px;
  padding: var(--space-6) var(--space-4) var(--space-10);
}

.custom-feed-builder__title {
  font-family: 'Times New Roman', Times, serif;
  font-weight: 800;
  font-size: 1.75rem;
  line-height: 1.2;
  margin: var(--space-6) 0 var(--space-5);
  color: var(--text-primary);
}

.custom-feed-builder__form {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  background: var(--bg-overlay);
  border-radius: var(--radius-full);
  padding: var(--space-1) var(--space-1) var(--space-1) var(--space-4);
}

.custom-feed-builder__form input {
  flex: 1;
  min-width: 0;
  border: none;
  background: transparent;
  outline: none;
  font-size: 0.9375rem;
  color: var(--text-primary);
  padding: 0.625rem 0;
}

.custom-feed-builder__form input::placeholder { color: var(--text-muted); }

.custom-feed-builder__submit {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: none;
  background: var(--text-primary);
  color: var(--text-inverse);
  cursor: pointer;
}

.custom-feed-builder__submit svg { width: 18px; height: 18px; }

.custom-feed-builder__disclaimer {
  font-size: 0.75rem;
  color: var(--text-muted);
  margin: var(--space-3) 0 var(--space-6);
}

.custom-feed-builder__examples {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.custom-feed-builder__example {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  text-align: left;
  background: none;
  border: none;
  padding: 0;
  font-size: 0.9375rem;
  color: var(--text-primary);
  cursor: pointer;
}

.custom-feed-builder__example:hover { color: var(--text-brand); }

.custom-feed-builder__example-icon {
  display: inline-flex;
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  margin-top: 2px;
  color: var(--text-muted);
}

/* ── Live status bar (Instagram/Snapchat-Stories-style) ─────────────
   Persistent, above the scrolling feed — every current live stream as a
   clickable bubble, not something you have to scroll into the feed to
   discover. */

.live-status-bar {
  display: flex;
  gap: var(--space-4);
  padding: var(--space-3) var(--space-4);
  overflow-x: auto;
  background: var(--bg-surface);
  border-bottom: 1px solid var(--border-subtle);
  flex-shrink: 0;
}

.live-status-bar__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  background: none;
  border: none;
  cursor: pointer;
  flex-shrink: 0;
  width: 68px;
}

.live-status-bar__ring {
  display: block;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  padding: 2.5px;
  background: linear-gradient(135deg, var(--error-500), var(--warning-400));
  position: relative;
}

/* Your own "Go Live" bubble — always leads, same as your own Story bubble on IG */
.live-status-bar__ring--add {
  background: var(--border-default);
}

.live-status-bar__plus {
  position: absolute;
  bottom: -2px;
  right: -2px;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--gradient-mixed);
  color: #fff;
  font-size: 0.875rem;
  font-weight: 800;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 2px solid var(--bg-surface);
}

.live-status-bar__ring .avatar {
  width: 100%;
  height: 100%;
  border: 2px solid var(--bg-surface);
}

.live-status-bar__label {
  font-size: 0.6875rem;
  font-weight: 600;
  color: var(--text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}

