@font-face {
    font-family: 'Mulish';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('fonts/mulish-v18-latin-regular.woff2') format('woff2');
}
@font-face {
    font-family: 'Mulish';
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url('fonts/mulish-v18-latin-500.woff2') format('woff2');
}
@font-face {
    font-family: 'Mulish';
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url('fonts/mulish-v18-latin-600.woff2') format('woff2');
}
@font-face {
    font-family: 'Mulish';
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url('fonts/mulish-v18-latin-700.woff2') format('woff2');
}

html, body {
    font-family: 'Nunito', 'Mulish', 'Segoe UI', 'Helvetica Neue', Helvetica, Arial, sans-serif;
    margin: 0;
}

/* ============================================================
   Redesign design tokens — mirror of design_handoff_dashboard/app/theme.css.
   Dark is the default; [data-theme="light"] is set on <html> by the anti-flash
   script in App.razor and kept in sync by MainLayout's theme toggle. The key
   colours are also mirrored into MudTheme so MudBlazor components inherit them.
   ============================================================ */
:root, [data-theme="dark"] {
    /* Active nav/tab text. Lives here rather than being interpolated into a
       <style> block from Blazor so it follows the same data-theme switch as
       every other token — and applies before the circuit has even connected. */
    --streamionbot-text-purple: #c9a8ff;
    --accent: #9d6bff;
    --accent-2: #7c4dff;
    --accent-soft: rgba(157, 107, 255, 0.14);
    --accent-ring: rgba(157, 107, 255, 0.45);
    --ok: #2fd08a;
    --danger: #ff7a7a;
    --warn: #f5b544;
    --info: #6aa8ff;
    --spotify: #25d366;
    --youtube: #ff5d5d;
    --discord: #6b78ff;
    --bg: #08060f;
    --bg-2: #0c0a17;
    --glow-a: rgba(124, 77, 255, 0.22);
    --glow-b: rgba(157, 107, 255, 0.10);
    --glow-c: rgba(40, 30, 80, 0.5);
    --surface: rgba(255, 255, 255, 0.045);
    --surface-hover: rgba(255, 255, 255, 0.075);
    --surface-solid: #14111f;
    --border: rgba(255, 255, 255, 0.085);
    --border-strong: rgba(255, 255, 255, 0.15);
    --panel: rgba(20, 16, 32, 0.55);
    --panel-blur: rgba(16, 13, 26, 0.78);
    --teal: #1fb6c4;
    --pink: #e25fae;
    --text: #ece9f6;
    --text-2: #b3aecb;
    --text-3: #7e7896;
    --shadow-sm: 0 8px 24px -16px rgba(0, 0, 0, 0.8);
    --shadow: 0 18px 50px -22px rgba(0, 0, 0, 0.85), 0 2px 8px -4px rgba(0, 0, 0, 0.6);
    --radius: 14px;
    /* Pills, chips and badges: the gently rounded corner of the FOUNDER badge,
       not a full capsule. Dots, switches and avatars stay circular. */
    --radius-pill: 8px;
    --r-sm: calc(var(--radius) * 0.6);
    --r-pill: 999px;
    --font-display: "Quicksand", system-ui, sans-serif;
    --font-body: "Nunito", system-ui, sans-serif;
    --font-mono: "JetBrains Mono", ui-monospace, monospace;
}

[data-theme="light"] {
    --streamionbot-text-purple: #9147ff;
    --accent: #7c3aed;
    --accent-2: #6d28d9;
    --accent-soft: rgba(124, 58, 237, 0.10);
    --accent-ring: rgba(124, 58, 237, 0.35);
    --bg: #eceaf4;
    --bg-2: #f4f2fb;
    --glow-a: rgba(124, 77, 255, 0.16);
    --glow-b: rgba(157, 107, 255, 0.10);
    --glow-c: rgba(210, 200, 255, 0.55);
    --surface: rgba(255, 255, 255, 0.72);
    --surface-hover: rgba(255, 255, 255, 0.95);
    --surface-solid: #ffffff;
    --border: rgba(36, 24, 70, 0.09);
    --border-strong: rgba(36, 24, 70, 0.16);
    --panel: rgba(255, 255, 255, 0.7);
    --panel-blur: rgba(255, 255, 255, 0.82);
    --text: #1b1730;
    --text-2: #524c6b;
    --text-3: #8a849e;
    --shadow-sm: 0 8px 22px -16px rgba(60, 40, 120, 0.35);
    --shadow: 0 20px 48px -26px rgba(60, 40, 120, 0.45), 0 2px 6px -3px rgba(60, 40, 120, 0.18);
}

/* Background ambiance: layered radial glows behind the whole app, fixed so they
   don't scroll. Overrides MudBlazor's flat palette background (loaded after
   app.css, hence !important). */
body {
    background:
        radial-gradient(1100px 700px at 8% -8%, var(--glow-a), transparent 60%),
        radial-gradient(900px 600px at 100% 110%, var(--glow-b), transparent 55%),
        radial-gradient(700px 500px at 60% 40%, var(--glow-c), transparent 70%),
        var(--bg) !important;
    background-attachment: fixed !important;
}

/* Frosted chrome — MudBlazor doesn't set backdrop-filter, so these layer on top
   of the translucent appbar/drawer backgrounds from the palette. */
.mud-appbar {
    backdrop-filter: blur(20px) saturate(140%);
    -webkit-backdrop-filter: blur(20px) saturate(140%);
    border-bottom: 1px solid var(--border) !important;
}
.mud-drawer {
    backdrop-filter: blur(20px) saturate(140%);
    -webkit-backdrop-filter: blur(20px) saturate(140%);
    border-right: 1px solid var(--border) !important;
}

/* Primary filled buttons → 135° accent gradient with a soft glow. Skip the
   disabled state so it doesn't keep the vivid gradient while its text greys out
   (that "full colour + greyed label" combo read as a broken button). */
.mud-button-filled.mud-button-filled-primary:not(:disabled):not(.mud-disabled) {
    background: linear-gradient(135deg, var(--accent), var(--accent-2)) !important;
    box-shadow: 0 12px 28px -12px var(--accent-ring), inset 0 1px 0 rgba(255, 255, 255, 0.22) !important;
}
.mud-button-filled.mud-button-filled-primary:hover:not(:disabled):not(.mud-disabled) { filter: brightness(1.08); }
/* Disabled primary → muted fill + muted label, matching every other disabled
   button (MudBlazor's own disabled tokens). */
.mud-button-filled.mud-button-filled-primary:disabled,
.mud-button-filled.mud-button-filled-primary.mud-disabled {
    background: var(--mud-palette-action-disabled-background) !important;
    box-shadow: none !important;
}

/* Sidebar active nav item: accent-soft fill, ring border, left accent bar. */
.mud-nav-link.active, .mud-nav-link[aria-current="page"] {
    background: var(--accent-soft) !important;
    border: 1px solid var(--accent-ring) !important;
    border-radius: 11px !important;
    position: relative;
}
.mud-nav-link.active::before, .mud-nav-link[aria-current="page"]::before {
    content: "";
    position: absolute;
    left: 0;
    top: 50%;
    transform: translateY(-50%);
    width: 4px;
    height: 22px;
    border-radius: 0 4px 4px 0;
    background: linear-gradient(var(--accent), var(--accent-2));
}

/* Flat sidebar section labels (uppercase, muted) — interleaved with the nav
   links in NavMenu instead of collapsible groups. */
.streamionbot-nav-label {
    font-size: 10.5px;
    font-weight: 800;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--text-3);
    padding: 16px 16px 6px;
    white-space: nowrap;
}

/* Frosted dropdown panel for the topbar Help + User menus (applied via the
   MudMenu PopoverClass). Translucent + blurred, radius 14, soft shadow. */
.streamionbot-frosted-menu.mud-popover {
    background: var(--panel-blur) !important;
    backdrop-filter: blur(24px) saturate(150%);
    -webkit-backdrop-filter: blur(24px) saturate(150%);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius) !important;
    box-shadow: var(--shadow) !important;
}
.streamionbot-frosted-menu .mud-list { background: transparent !important; }

/* Help-menu sub-labels in teal (the design's secondary accent). */
.streamionbot-help-sub { color: var(--teal) !important; font-weight: 600; }

/* Reusable redesign primitives shared across the content pages (Commands,
   Quotes, Events, Media, admin tables, …). Frosted card + mono trigger chip +
   frosted modal panel. Pages that already ship their own page-local copies
   (Dashboard, Stats) are unaffected — those <style> blocks only exist while
   their page is mounted. */
.streamionbot-card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    backdrop-filter: blur(16px) saturate(130%);
    -webkit-backdrop-filter: blur(16px) saturate(130%);
    box-shadow: var(--shadow-sm);
}
.streamionbot-card .mud-table { background: transparent !important; }

/* Command / quote / counter trigger — mono accent chip. */
.trigger-chip {
    font-family: var(--font-mono);
    font-size: 13px;
    font-weight: 600;
    background: var(--accent-soft);
    color: var(--accent);
    padding: 3px 9px;
    border-radius: var(--radius-pill);
    border: 1px solid var(--accent-ring);
    white-space: nowrap;
}

/* Small accent icon tile used as a section-header glyph (Alerts "Alert types",
   Tools section headers, …). Mirrors the scene-card icon tile. */
.streamionbot-section-ico {
    width: 34px;
    height: 34px;
    flex: none;
    border-radius: 9px;
    display: grid;
    place-items: center;
    background: var(--accent-soft);
    color: var(--accent);
    border: 1px solid var(--accent-ring);
}

/* Friendly in-table empty state (MudTable NoRecordsContent): a muted icon over
   centred text. Reusable across the table pages. */
.streamionbot-table-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    padding: 36px 16px;
    text-align: center;
    color: var(--text-2);
    font-weight: 600;
}
.streamionbot-table-empty__ico { color: var(--text-3); opacity: 0.5; }

/* Frosted modal panels — the redesign renders every dialog as frosted glass
   (radius 14 comes from the MudTheme). */
.mud-dialog {
    background: var(--panel-blur) !important;
    backdrop-filter: blur(24px) saturate(150%);
    -webkit-backdrop-filter: blur(24px) saturate(150%);
    border: 1px solid var(--border-strong);
    box-shadow: var(--shadow) !important;
}

/* Code, command triggers and {variables} → JetBrains Mono. */
code, kbd, samp, pre { font-family: var(--font-mono); }

/* Smooth scrollbar on dark backgrounds */
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.08); border-radius: 4px; }
::-webkit-scrollbar-thumb:hover { background: rgba(255, 255, 255, 0.18); }

/* Permission level chips on the Commands page. Colour hints follow the
   visual language of the Twitch chat badges (broadcaster camera, mod
   sword, VIP diamond). Everyone uses the default outlined MudChip look.
   All role pills share a fixed width so the column lines up cleanly. */
.permission-chip {
    width: 120px !important;
    justify-content: center !important;
}
.permission-chip .mud-chip-content {
    flex-grow: 1;
    justify-content: center;
}
.permission-follower,
.permission-subscriber,
.permission-vip,
.permission-moderator,
.permission-broadcaster {
    color: white !important;
    font-weight: 500 !important;
}
.permission-follower    { background: #7d6ff0 !important; }  /* Twitch heart purple */
.permission-subscriber  { background: #4fc3f7 !important; }  /* light blue */
.permission-vip         { background: #e005b9 !important; }  /* Twitch VIP pink */
.permission-moderator   { background: #00ad03 !important; }  /* Twitch mod green */
.permission-broadcaster { background: #e71a28 !important; }  /* Twitch broadcaster red */

/* Highlighted header for StreamionBot data tables. MudTable's HeaderClass
   lands on the <thead> element, so we style its th children. */
.streamionbot-table-header {
    background: var(--mud-palette-action-default-hover) !important;
}
.streamionbot-table-header th {
    font-weight: 600 !important;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    font-size: 0.75rem;
}

/* Blazor's <FocusOnNavigate Selector="h1"> (Routes.razor) moves focus to the
   page's <h1> after every navigation so screen-reader/keyboard users land on
   the new content. That focus is programmatic — not a keyboard tab — so the
   default focus ring (e.g. the box around the Dashboard title) is just visual
   noise for mouse users. Suppress it on headings; they're never tab-reachable
   interactive controls, so keyboard usability is unaffected. */
h1:focus,
h1:focus-visible {
    outline: none;
}

/* Section header within a page (see SectionHeader.razor). The left accent
   bar visually anchors the section title without competing with the
   page-level underline. */
.streamionbot-section-header__title {
    border-left: 3px solid var(--mud-palette-primary);
    padding-left: 12px;
}

/* AlertPreview — admin-side stand-in for the OBS browser-source
   toast. The structure mirrors wwwroot/overlays/alerts/alerts.css
   (same class names, same layout modifiers) so the preview reads as
   "what OBS will paint" minus animation/sound. Everything is scoped
   under .streamionbot-alert-preview so the global selectors of the live
   overlay can't leak into the admin UI. */
.streamionbot-alert-preview__stage {
    background:
        /* Subtle vignette so the foreground text doesn't drown when
           the streamer picks a near-white accent against the dark
           preview surface. */
        radial-gradient(circle at center, rgba(255,255,255,0.04) 0%, transparent 70%),
        repeating-linear-gradient(45deg, rgba(255,255,255,0.02) 0 8px, transparent 8px 16px),
        #1a1f24;
    border-radius: 8px;
    padding: 24px;
    min-height: 160px;
    display: flex;
    align-items: center;
    justify-content: center;
}
.streamionbot-alert-preview .toast {
    display: flex;
    align-items: center;
    gap: 14px;
    font-family: var(--font-family);
    color: var(--text-color);
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
    max-width: 100%;
}
.streamionbot-alert-preview .toast.layout-left   { flex-direction: row;            text-align: left;   }
.streamionbot-alert-preview .toast.layout-right  { flex-direction: row-reverse;    text-align: right;  }
.streamionbot-alert-preview .toast.layout-top    { flex-direction: column;         text-align: center; align-items: center; }
.streamionbot-alert-preview .toast.layout-bottom { flex-direction: column-reverse; text-align: center; align-items: center; }
.streamionbot-alert-preview .toast-icon {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 56px;
    line-height: 1;
}
.streamionbot-alert-preview .toast-icon img {
    max-width: var(--image-max-size, 160px);
    max-height: var(--image-max-size, 160px);
    width: auto;
    height: auto;
    object-fit: contain;
    display: block;
}
.streamionbot-alert-preview .toast-text {
    min-width: 0;
    display: flex;
    flex-direction: column;
}
.streamionbot-alert-preview .toast-title {
    /* Title scales with the same --font-size custom prop that drives
       the subtitle, with a fixed offset so the headline stays larger.
       At the 18 px subtitle default this resolves to 28 px — matches
       the hardcoded value the old layout shipped with, so existing
       configs paint identically. */
    font-size: calc(var(--font-size, 18px) + 10px);
    font-weight: 700;
    line-height: 1.15;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.streamionbot-alert-preview .toast-subtitle {
    font-size: var(--font-size, 18px);
    font-weight: var(--font-weight, 400);
    opacity: 0.9;
    margin-top: 4px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.streamionbot-alert-preview .alert-var {
    color: var(--accent, inherit);
}
.streamionbot-alert-preview .toast-message {
    font-size: calc(var(--font-size, 18px) * 0.85);
    font-weight: var(--font-weight, 400);
    color: var(--text-color, inherit);
    opacity: 0.75;
    margin-top: 4px;
    line-height: 1.25;
    white-space: normal;
    word-break: break-word;
}

/* AppBar user menu: swap MudMenu's StartIcon SVG for the Twitch profile picture.
   Activated when the `--user-avatar-url` CSS var is set on the MudMenu root. */
.streamionbot-user-menu-avatar .mud-button-icon-start {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    overflow: hidden;
    background-image: var(--user-avatar-url);
    background-size: cover;
    background-position: center;
    margin-right: 8px;
}
.streamionbot-user-menu-avatar .mud-button-icon-start svg {
    display: none;
}

/* Drag-to-position handle inside the layout-preview rectangles
   (used by /alerts → "Alert Overlay Layout" and /media-commands →
   "Video overlay position"). cursor: grab while idle, grabbing
   while a drag is in flight. touch-action: none stops the browser
   from claiming the pointer for scroll / pinch on touch devices.
   user-select: none keeps a long-drag from accidentally selecting
   the glyph inside the box. The .is-dragging modifier is toggled
   from app.js, and disables the 120 ms position transition so the
   box stays under the cursor without visible lag. */
.media-preview-handle {
    cursor: grab;
    touch-action: none;
    user-select: none;
}
.media-preview-handle.is-dragging {
    cursor: grabbing;
    transition: none !important;
}

/* --------------------------------------------------------------------
   Overlay scene editor canvas (/overlays/scenes/{id}). Global, not a
   .razor.css scoped file — the host doesn't link the scoped-CSS bundle,
   so scoped styles never load. The class names are unique to the editor
   so there is no collision risk at global scope.
   -------------------------------------------------------------------- */
.scene-canvas {
    position: relative;
    width: 100%;
    aspect-ratio: 16 / 9;
    background: #0d1117;
    border-radius: 8px;
    overflow: hidden;
    border: 1px solid var(--mud-palette-lines-default);
}

.scene-canvas-frame {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    border: 0;
    background: transparent;
}

/* While a widget is being dragged/resized the iframe must ignore pointer
   events, otherwise it can swallow the move events and the drag gets stuck. */
.scene-canvas.editor-busy .scene-canvas-frame {
    pointer-events: none;
}

/* Transparent layer above the iframe that captures pointer events for
   selecting / dragging widgets. The iframe shows pixels; this owns input. */
.scene-interaction {
    position: absolute;
    inset: 0;
    z-index: 1;
}

.editor-hitbox {
    position: absolute;
    box-sizing: border-box;
    border: 1.5px solid rgba(124, 77, 255, 0.55);
    background: rgba(124, 77, 255, 0.07);
    border-radius: 4px;
    cursor: move;
    touch-action: none;
    transition: background 0.12s ease, border-color 0.12s ease, box-shadow 0.12s ease;
}

.editor-hitbox:hover {
    border-color: var(--mud-palette-primary);
    background: rgba(124, 77, 255, 0.18);
    box-shadow: 0 0 0 1px rgba(124, 77, 255, 0.35);
}

.editor-hitbox.selected {
    border: 2px solid var(--mud-palette-primary);
    background: rgba(124, 77, 255, 0.14);
    box-shadow: 0 0 0 2px rgba(124, 77, 255, 0.3);
}

.editor-hitbox-label {
    position: absolute;
    top: 4px;
    left: 4px;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 11px;
    font-weight: 600;
    line-height: 1.5;
    color: #fff;
    background: var(--mud-palette-primary);
    padding: 0 6px;
    border-radius: 4px;
    pointer-events: none;
    white-space: nowrap;
    opacity: 0.92;
}

.editor-handle {
    position: absolute;
    width: 14px;
    height: 14px;
    background: #fff;
    border: 2px solid var(--mud-palette-primary);
    border-radius: 3px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.45);
}

.editor-handle[data-handle="nw"] { top: -8px; left: -8px; cursor: nwse-resize; }
.editor-handle[data-handle="ne"] { top: -8px; right: -8px; cursor: nesw-resize; }
.editor-handle[data-handle="sw"] { bottom: -8px; left: -8px; cursor: nesw-resize; }
.editor-handle[data-handle="se"] { bottom: -8px; right: -8px; cursor: nwse-resize; }

/* ============================================================
   Command-center shell (Phase 1): compact accordion sidebar,
   236px, hosted in a MudDrawer (ClipMode.Never → full height).
   Everything token-driven — [data-theme="light"] restyles it
   automatically via the variables at the top of this file.
   ============================================================ */

/* The drawer palette already paints --panel; just make sure the drawer's own
   content column lets the sidenav stretch and scroll. */
.mud-drawer-content { display: flex; flex-direction: column; min-height: 0; }

.streamionbot-sidenav {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 16px 12px;
    overflow-y: auto;
    overflow-x: hidden;
}

/* Brand head: 36px logo tile + wordmark + PRO mini-pill, version below. */
.streamionbot-sidenav-brand {
    display: flex;
    align-items: center;
    gap: 13px;
    padding: 6px 6px 22px;
    text-decoration: none;
    color: var(--text);
}
/* Brand tile: pre-rendered robot PNG (plain / pro / founder variant). */
.streamionbot-sidenav-logo-img {
    width: 36px;
    height: 36px;
    flex: none;
    border-radius: 11px;
    object-fit: cover;
}
.streamionbot-sidenav-brand-text { min-width: 0; }
.streamionbot-sidenav-wordmark {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 14.5px;
    letter-spacing: -0.025em;
    color: var(--text);
    white-space: nowrap;
}
.streamionbot-sidenav-version {
    display: flex;
    align-items: center;
    gap: 9px;
    font-size: 10.5px;
    color: var(--text-3);
    margin-top: 5px;
}

/* Accent PRO mini-pill (sidebar head); the -gold variant marks Pro features
   on sub-entries (Buddies, Coworking). */
.streamionbot-mini-pro-pill {
    display: inline-block;
    font-size: 9.5px;
    font-weight: 800;
    letter-spacing: 0.04em;
    padding: 1px 6px;
    border-radius: var(--radius-pill);
    background: var(--accent-soft);
    color: var(--accent);
    border: 1px solid var(--accent-ring);
    vertical-align: 2px;
    line-height: 1.5;
}
.streamionbot-sidenav-wordmark .streamionbot-mini-pro-pill { margin-left: 9px; }

/* FOUNDER pill (replaces the PRO pill for founding members): gold outline,
   gold text, gently rounded corners — mirrors the golden brand tile. */
.streamionbot-mini-founder-pill {
    background: transparent;
    color: #F5C84B;
    border: 1.5px solid rgba(245, 200, 75, 0.65);
    border-radius: var(--radius-pill);
    padding: 1px 9px;
    letter-spacing: 0.06em;
}
[data-theme="light"] .streamionbot-mini-founder-pill {
    color: #9a7a1f;
    border-color: rgba(196, 154, 44, 0.65);
}
.streamionbot-mini-pro-pill-gold {
    background: rgba(245, 200, 75, 0.12);
    color: #F5C84B;
    border-color: rgba(245, 200, 75, 0.4);
}
[data-theme="light"] .streamionbot-mini-pro-pill-gold {
    background: rgba(196, 154, 44, 0.12);
    color: #9a7a1f;
    border-color: rgba(196, 154, 44, 0.45);
}

/* Group rows: icon + label, chevron for groups with sub-entries. */
.streamionbot-sidenav-groups {
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.streamionbot-sidenav-group {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 10px;
    border-radius: 11px;
    border: 1px solid transparent;
    color: var(--text-2);
    text-decoration: none;
    cursor: pointer;
    user-select: none;
    transition: background-color 140ms ease, color 140ms ease;
}
.streamionbot-sidenav-group:hover {
    background: var(--surface-hover);
    color: var(--text);
}
.streamionbot-sidenav-group.open {
    color: var(--text);
}
.streamionbot-sidenav-group.active {
    background: var(--accent-soft);
    border-color: var(--accent-ring);
    color: var(--text);
}
.streamionbot-sidenav-group.active .streamionbot-sidenav-group-label,
.streamionbot-sidenav-group.open .streamionbot-sidenav-group-label {
    font-weight: 800;
}
.streamionbot-sidenav-group-icon {
    flex: none;
    width: 20px !important;
    height: 20px !important;
}
.streamionbot-sidenav-group-label {
    flex: 1;
    font-size: 13.5px;
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.streamionbot-sidenav-chevron {
    flex: none;
    width: 16px !important;
    height: 16px !important;
    color: var(--text-3);
}
.streamionbot-sidenav-dot {
    flex: none;
    width: 7px;
    height: 7px;
    border-radius: 999px;
    background: var(--warn);
}

/* Expanded sub-entries: indented, thin left rule. */
.streamionbot-sidenav-items {
    margin: 2px 0 6px 22px;
    border-left: 1px solid var(--border);
    padding-left: 8px;
    display: flex;
    flex-direction: column;
    gap: 1px;
}
.streamionbot-sidenav-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 6px 10px;
    border-radius: 8px;
    font-size: 12.5px;
    font-weight: 600;
    color: var(--text-2);
    text-decoration: none;
    transition: background-color 140ms ease, color 140ms ease;
}
.streamionbot-sidenav-item:hover {
    background: var(--surface-hover);
    color: var(--text);
}
.streamionbot-sidenav-item.active {
    background: var(--accent-soft);
    color: var(--text);
    font-weight: 800;
}
.streamionbot-sidenav-count {
    font-size: 10.5px;
    color: var(--text-3);
}

/* Owner-only PRO upsell tile pinned at the foot of the sidebar (the tile's
   own look comes from the shared .streamionbot-upsell class). */
.streamionbot-sidenav-foot {
    margin-top: auto;
    padding-top: 12px;
}
.streamionbot-sidenav-foot .streamionbot-upsell { display: flex; }
.streamionbot-upsell-logo {
    width: 22px;
    height: 22px;
    flex: none;
    border-radius: 7px;
    object-fit: cover;
}

/* ============================================================
   Top bar (Phase 2): breadcrumb + status pill, ⌘K search /
   live metrics + actions, quiet icon buttons. Token-driven.
   ============================================================ */

/* The bar sits transparent on the page background (design #5x): no panel
   fill, just a hairline bottom border. Blur keeps scrolled content legible
   underneath. Overrides the palette AppbarBackground. */
.mud-appbar.mud-appbar-fixed-top {
    background: transparent !important;
    box-shadow: none !important;
}

.streamionbot-topbar {
    display: flex;
    align-items: center;
    gap: 14px;
    flex: 1 1 auto;
    min-width: 0;
}

/* Left cluster: group / title breadcrumb + status pill. */
.streamionbot-topbar-lead {
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 0;
}
.streamionbot-topbar-group {
    font-size: 13px;
    font-weight: 600;
    color: var(--text-3);
    white-space: nowrap;
}
.streamionbot-topbar-sep { color: var(--text-3); opacity: 0.6; }
.streamionbot-topbar-title {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 15px;
    letter-spacing: -0.025em;
    color: var(--text);
    white-space: nowrap;
}

/* Status pill (shared StatusPill component). */
.streamionbot-status-pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    border-radius: var(--radius-pill);
    padding: 4px 11px;
    font-size: 10.5px;
    font-weight: 800;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    white-space: nowrap;
    background: var(--surface);
    border: 1px solid var(--border);
    color: var(--text-2);
}
.streamionbot-status-pill-dot {
    width: 6px;
    height: 6px;
    border-radius: 999px;
    background: var(--text-3);
    flex: none;
}
.streamionbot-status-pill-danger {
    background: rgba(255, 122, 122, 0.12);
    border-color: rgba(255, 122, 122, 0.45);
    color: var(--danger);
}
.streamionbot-status-pill-danger .streamionbot-status-pill-dot {
    background: var(--danger);
    box-shadow: 0 0 8px var(--danger);
}
.streamionbot-status-pill-ok {
    background: rgba(47, 208, 138, 0.12);
    border-color: rgba(47, 208, 138, 0.45);
    color: var(--ok);
}
.streamionbot-status-pill-ok .streamionbot-status-pill-dot {
    background: var(--ok);
    box-shadow: 0 0 8px var(--ok);
}
.streamionbot-status-pill-warn {
    background: rgba(245, 181, 68, 0.12);
    border-color: rgba(245, 181, 68, 0.45);
    color: var(--warn);
}
.streamionbot-status-pill-warn .streamionbot-status-pill-dot { background: var(--warn); }
.streamionbot-status-pill-dot.pulse {
    animation: streamionbot-pill-pulse 2s ease-in-out infinite;
}
@keyframes streamionbot-pill-pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.4; }
}

/* ⌘K search affordance (right-aligned; the palette is a follow-up phase). */
.streamionbot-topbar-search {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 340px;
    margin-left: auto;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 7px 12px;
    font-size: 12.5px;
    color: var(--text-3);
    white-space: nowrap;
    user-select: none;
}
.streamionbot-topbar-search-label {
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
}
.streamionbot-topbar-search kbd {
    font-family: var(--font-mono);
    font-size: 10px;
    border: 1px solid var(--border-strong);
    border-radius: 5px;
    padding: 1px 6px;
}

/* Live metrics strip (centered while live). */
.streamionbot-topbar-metrics {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 22px;
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
}
.streamionbot-topbar-metric {
    display: flex;
    align-items: center;
    gap: 7px;
    font-size: 12.5px;
    color: var(--text-2);
    white-space: nowrap;
}
.streamionbot-topbar-metric b { color: var(--text); }

/* Live quick actions: neutral Clip, danger-outline Lockdown. */
.streamionbot-topbar-actions {
    display: flex;
    align-items: center;
    gap: 8px;
}
.streamionbot-topbar-btn {
    all: unset;
    box-sizing: border-box;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-pill);
    padding: 7px 13px;
    font-size: 12px;
    font-weight: 800;
    color: var(--text);
    cursor: pointer;
    white-space: nowrap;
    transition: background-color 140ms ease;
}
.streamionbot-topbar-btn:hover { background: var(--surface-hover); }
.streamionbot-topbar-btn:disabled { opacity: 0.55; cursor: default; }
.streamionbot-topbar-btn-danger {
    background: rgba(255, 122, 122, 0.12);
    border-color: rgba(255, 122, 122, 0.45);
    color: var(--danger);
}
.streamionbot-topbar-btn-danger:hover { background: rgba(255, 122, 122, 0.2); }

/* Right cluster: quiet 36px icon buttons (help, theme) + user menu. */
.streamionbot-topbar-icons {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-left: 0;
}
.streamionbot-topbar-icons .mud-icon-button {
    width: 36px;
    height: 36px;
    border-radius: 10px;
    color: var(--text-2);
}
.streamionbot-topbar-icons .mud-icon-button:hover { background: var(--surface-hover); }

/* Help + theme wrapper: a plain <span> lays its inline-block children out on
   the text baseline, which lifts the help/theme icons above the centred user
   menu next to it. Flex + center puts them back in the same row. */
.streamionbot-topbar-desktop {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

/* Metrics need room — hide them (not the actions) on narrow viewports; the
   search affordance likewise steps aside below the lg breakpoint. */
@media (max-width: 1279.98px) {
    .streamionbot-topbar-metrics { display: none; }
    .streamionbot-topbar-search { display: none; }
}

/* Dashboard chat + event feeds: fixed scroll windows. Hardened here (on top
   of the page-local rules) so nothing can ever re-grow these cards — the
   scrollbar lives INSIDE the list, the card never stretches with content.
   The away list fills its fixed-height card (flex) instead of a hard pixel
   height, so it tracks the uniform .bento-tall row height. */
.dash .chat-list { height: 380px !important; overflow-y: auto !important; }
.dash .away-list { flex: 1 1 0 !important; min-height: 0 !important; overflow-y: auto !important; }

/* ============================================================
   Phase 4 primitives: filter pills, accent toggle, tinted role
   pills and the frosted grid table (+ compact pager). All
   token-driven; reused by later phases (stats, settings).
   ============================================================ */

/* Filter pills (replaces MudTabs). */
.streamionbot-filter-pills {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
}
@media (max-width: 959.98px) {
    .streamionbot-filter-pills { flex-wrap: nowrap; overflow-x: auto; padding-bottom: 4px; }
}
.streamionbot-filter-pill {
    all: unset;
    box-sizing: border-box;
    display: inline-flex;
    align-items: center;
    gap: 7px;
    border-radius: var(--radius-pill);
    padding: 7px 15px;
    font-size: 12.5px;
    font-weight: 800;
    color: var(--text-2);
    border: 1px solid transparent;
    cursor: pointer;
    white-space: nowrap;
    transition: background-color 140ms ease, color 140ms ease;
}
.streamionbot-filter-pill:hover { background: var(--surface-hover); }
.streamionbot-filter-pill.active {
    background: var(--accent-soft);
    border-color: var(--accent-ring);
    color: var(--text);
}
.streamionbot-filter-pill-count { font-size: 10.5px; color: var(--text-3); font-weight: 700; }

/* Accent toggle (36×20, knob 16px). */
.streamionbot-accent-toggle {
    all: unset;
    box-sizing: border-box;
    width: 36px;
    height: 20px;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.12);
    position: relative;
    cursor: pointer;
    flex: none;
    transition: background 150ms ease;
}
[data-theme="light"] .streamionbot-accent-toggle { background: rgba(36, 24, 70, 0.18); }
.streamionbot-accent-toggle.on {
    background: linear-gradient(135deg, var(--accent), var(--accent-2));
}
.streamionbot-accent-toggle:disabled { opacity: 0.45; cursor: default; }
.streamionbot-accent-toggle-knob {
    position: absolute;
    top: 2px;
    left: 2px;
    width: 16px;
    height: 16px;
    border-radius: 999px;
    background: #fff;
    transition: left 150ms ease;
}
.streamionbot-accent-toggle.on .streamionbot-accent-toggle-knob { left: 18px; }

/* Tinted role pills (Commands "Berechtigung" column): tint instead of the
   full-colour chips, colours derived from the existing .permission-* hues.
   Everyone stays a neutral outline. */
.perm-pill {
    display: inline-flex;
    align-items: center;
    border-radius: var(--radius-pill);
    padding: 4px 12px;
    font-size: 11px;
    font-weight: 700;
    white-space: nowrap;
    border: 1px solid var(--border-strong);
    color: var(--text-2);
    background: transparent;
}
.perm-pill-follower    { background: rgba(125, 111, 240, 0.15); color: #a99cff; border-color: rgba(125, 111, 240, 0.45); }
.perm-pill-subscriber  { background: rgba(79, 195, 247, 0.15);  color: #7cd4ff; border-color: rgba(79, 195, 247, 0.45); }
.perm-pill-vip         { background: rgba(224, 5, 185, 0.15);   color: #ff6fdd; border-color: rgba(224, 5, 185, 0.45); }
.perm-pill-moderator   { background: rgba(0, 173, 3, 0.15);     color: #7ce38b; border-color: rgba(0, 173, 3, 0.45); }
.perm-pill-broadcaster { background: rgba(231, 26, 40, 0.15);   color: #ff8b93; border-color: rgba(231, 26, 40, 0.45); }
[data-theme="light"] .perm-pill-follower    { color: #5b46d6; }
[data-theme="light"] .perm-pill-subscriber  { color: #0b7db3; }
[data-theme="light"] .perm-pill-vip         { color: #b3038f; }
[data-theme="light"] .perm-pill-moderator   { color: #067d08; }
[data-theme="light"] .perm-pill-broadcaster { color: #c11420; }

/* Frosted grid table: header row 10.5px uppercase on a soft strip, rows with
   hairline separators, actions fade in on row hover, disabled rows dim. */
.streamionbot-grid-table {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    backdrop-filter: blur(16px) saturate(130%);
    -webkit-backdrop-filter: blur(16px) saturate(130%);
    box-shadow: var(--shadow-sm);
    overflow: hidden;
}
.streamionbot-grid-table-scroll { overflow-x: auto; }
.streamionbot-grid-head,
.streamionbot-grid-row {
    display: grid;
    gap: 12px;
    padding: 12px 20px;
    align-items: center;
}
.streamionbot-grid-head {
    font-size: 10.5px;
    font-weight: 800;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--text-3);
    background: rgba(255, 255, 255, 0.03);
    border-bottom: 1px solid var(--border);
}
[data-theme="light"] .streamionbot-grid-head { background: rgba(36, 24, 70, 0.03); }
.streamionbot-grid-row { border-bottom: 1px solid var(--border); }
.streamionbot-grid-row:last-child { border-bottom: none; }
.streamionbot-grid-row:hover { background: rgba(255, 255, 255, 0.03); }
[data-theme="light"] .streamionbot-grid-row:hover { background: rgba(36, 24, 70, 0.03); }
.streamionbot-grid-row.is-disabled > *:not(.streamionbot-grid-actions) { opacity: 0.55; }
.streamionbot-grid-mono { font-family: var(--font-mono); font-size: 12px; color: var(--text-3); }
.streamionbot-grid-text { font-size: 13px; color: var(--text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Rows whose actions are the point of the table (import, activate) keep them
   visible — hover-to-reveal hides the primary action. */
.streamionbot-grid-actions.is-sticky { opacity: 1 !important; }

/* Row actions: hidden until the row is hovered (or focused). */
.streamionbot-grid-actions {
    display: flex;
    gap: 4px;
    justify-content: flex-end;
    opacity: 0;
    transition: opacity 130ms ease;
}
.streamionbot-grid-row:hover .streamionbot-grid-actions,
.streamionbot-grid-row:focus-within .streamionbot-grid-actions { opacity: 1; }

/* Compact pager: "x–y of z" + square page buttons. */
.streamionbot-pager {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 12px 20px;
    font-size: 12px;
    color: var(--text-3);
    border-top: 1px solid var(--border);
}
.streamionbot-pager-left {
    display: flex;
    align-items: center;
    gap: 14px;
    flex-wrap: wrap;
}
/* Rows-per-page picker: a native select skinned to match the pager. */
.streamionbot-pager-size {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    white-space: nowrap;
}
.streamionbot-pager-size select {
    appearance: none;
    -webkit-appearance: none;
    font: inherit;
    color: var(--text);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 3px 22px 3px 9px;
    cursor: pointer;
    /* caret glyph, drawn so the control needs no extra markup */
    background-image: linear-gradient(45deg, transparent 50%, var(--text-3) 50%),
                      linear-gradient(135deg, var(--text-3) 50%, transparent 50%);
    background-position: calc(100% - 13px) 52%, calc(100% - 9px) 52%;
    background-size: 4px 4px, 4px 4px;
    background-repeat: no-repeat;
}
.streamionbot-pager-size select:hover { background-color: var(--surface-hover); }
.streamionbot-pager-size select option { background: var(--surface-solid); color: var(--text); }

.streamionbot-pager-buttons { display: flex; gap: 4px; align-items: center; }
.streamionbot-pager-gap { color: var(--text-3); padding: 0 2px; }
.streamionbot-pager-btn {
    all: unset;
    box-sizing: border-box;
    width: 28px;
    height: 28px;
    border-radius: var(--radius-pill);
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--border);
    color: var(--text-2);
    cursor: pointer;
    font-size: 12px;
    transition: background-color 140ms ease;
}
.streamionbot-pager-btn:hover:not(:disabled) { background: var(--surface-hover); }
.streamionbot-pager-btn:disabled { opacity: 0.4; cursor: default; }
.streamionbot-pager-btn.active {
    background: var(--accent-soft);
    border-color: var(--accent-ring);
    color: var(--accent);
    font-weight: 800;
}

/* Segmented control (top-bar range switcher, reusable). */
.streamionbot-seg {
    display: flex;
    gap: 4px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 3px;
    flex: none;
}
/* While it replaces the search (offline top bar) it takes the search's
   right-aligned slot. */
.streamionbot-topbar-seg-offline { margin-left: auto; }
.streamionbot-seg-btn {
    all: unset;
    box-sizing: border-box;
    padding: 5px 13px;
    border-radius: var(--radius-pill);
    font-size: 12px;
    font-weight: 800;
    color: var(--text-2);
    cursor: pointer;
    white-space: nowrap;
    transition: background-color 140ms ease, color 140ms ease;
}
.streamionbot-seg-btn:hover { color: var(--text); }
.streamionbot-seg-btn.active {
    background: var(--accent-soft);
    color: var(--accent);
}

/* Live variant of the top-bar search (page-driven filter, e.g. the settings
   hub): a real input inside the search shell. */
.streamionbot-topbar-search-live input {
    all: unset;
    flex: 1;
    min-width: 0;
    font: inherit;
    color: var(--text);
}
.streamionbot-topbar-search-live input::placeholder { color: var(--text-3); }
.streamionbot-topbar-search-live:focus-within { border-color: var(--accent-ring); }

/* Shared page chrome for the redesigned list pages (Commands, Counters,
   Quotes, Timers, Event responses, Auto-responses, Clips): title + count
   line with a trailing primary action, and the compact search toolbar. */
.page-header-row {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
}
.page-title {
    font-family: var(--font-display);
    font-weight: 700;
    letter-spacing: -0.025em;
    line-height: 1.05;
    font-size: 26px;
    margin: 0;
    color: var(--text);
}
.page-sub {
    color: var(--text-2);
    font-weight: 600;
    font-size: 13.5px;
    margin: 3px 0 0;
}
.page-toolbar { display: flex; justify-content: flex-end; }
/* Back link above a sub-page title (settings detail pages, configure pages). */
.page-back { align-self: flex-start; margin-bottom: 2px; text-transform: none; min-width: 0; }
/* Sub-section inside a page that stacks several tables (music playlists). */
.page-section-row { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.page-section-title {
    font-family: var(--font-display); font-weight: 700; font-size: 16px; letter-spacing: -0.01em;
    margin: 0; color: var(--text);
}
.page-section-hint { font-size: 12.5px; color: var(--text-3); }
.page-search { max-width: 280px; min-width: 200px; width: 100%; }

/* Pro badge (ProBadge.razor): gold tint pill for entitled features, muted
   with a lock glyph when the tenant isn't entitled. Mirrors the sidebar's
   PRO mini-pill so both read as the same signal. */
.streamionbot-pro-badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 10.5px;
    font-weight: 800;
    letter-spacing: 0.06em;
    padding: 2px 9px;
    border-radius: var(--radius-pill);
    line-height: 1.6;
    white-space: nowrap;
    vertical-align: middle;
    user-select: none;
    background: rgba(245, 200, 75, 0.12);
    color: #F5C84B;
    border: 1px solid rgba(245, 200, 75, 0.45);
}
.streamionbot-pro-badge.locked {
    background: var(--surface);
    color: var(--text-3);
    border-color: var(--border-strong);
}
.streamionbot-pro-badge-ico {
    font-size: 12px !important;
    width: 12px !important;
    height: 12px !important;
}
[data-theme="light"] .streamionbot-pro-badge { color: #9a7a1f; border-color: rgba(196, 154, 44, 0.5); }

/* ---------- Coworking hub (Phase 7) — shared by the timer/to-do/chat-to-do panels ---------- */
  /* Two-column shell: settings on the left, the "what OBS sees" rail on the right. */
  .cw-2col { display: grid; grid-template-columns: minmax(0, 1fr) 380px; gap: 16px; align-items: start; }
  .cw-col { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
  .cw-rail { position: sticky; top: 12px; }
  @media (max-width: 1180px) {
    .cw-2col { grid-template-columns: minmax(0, 1fr); }
    .cw-rail { position: static; }
  }

  .cw-enable { display: inline-flex; align-items: center; gap: 9px; }
  .cw-enable-label { font-size: 13px; font-weight: 700; color: var(--text-2); white-space: nowrap; }

  .cw-rail-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 12px; }

  /* Hatched stage stands in for the transparent OBS canvas. */
  .cw-stage {
    border: 1px solid var(--border-strong); border-radius: var(--radius); overflow: hidden;
    background:
      repeating-linear-gradient(45deg, rgba(255,255,255,0.035) 0 10px, transparent 10px 20px),
      rgba(10, 12, 20, 0.55);
    padding: 22px 18px; display: grid; place-items: center; container-type: inline-size;
    transition: box-shadow 160ms ease, border-color 160ms ease;
  }
  .cw-stage.is-live { border-color: var(--ok); box-shadow: 0 0 0 1px var(--ok), 0 0 26px -8px var(--ok); }
  .cw-stage-inner { text-align: center; width: 100%; font-family: var(--font-mono); }
  .cw-stage-eyebrow {
    font-size: 11px; font-weight: 800; letter-spacing: 0.12em; text-transform: uppercase;
    color: var(--cw-preview-accent, var(--accent)); margin-bottom: 6px;
  }
  /* Break phases read in the same calm hue the overlay switches to. */
  .cw-stage-inner.is-break .cw-stage-eyebrow { color: #38d39f; }
  .cw-stage-inner.is-break .cw-stage-pips span.is-on { background: #38d39f; }
  .cw-stage-inner.is-paused .cw-stage-time { opacity: 0.5; }
  /* The digits honour the configured size but never overflow the rail — the
     stage is a query container so they scale with the card, not the viewport. */
  .cw-stage-time {
    font-family: inherit; font-variant-numeric: tabular-nums; line-height: 1;
    color: var(--cw-preview-text, #fff);
    font-size: min(var(--cw-preview-size, 56px), 22cqw);
  }
  .cw-stage-time.is-long { font-size: min(var(--cw-preview-size, 56px), 15cqw); }
  .cw-stage-time.is-idle { opacity: 0.42; }

  /* Pomodoro round pips — same read as the overlay's. */
  .cw-stage-pips { display: flex; justify-content: center; gap: 6px; margin-top: 12px; }
  .cw-stage-pips span {
    width: 8px; height: 8px; border-radius: 50%;
    background: rgba(255, 255, 255, 0.22);
  }
  .cw-stage-pips span.is-on { background: var(--cw-preview-accent, var(--accent)); }

  /* Phase durations: colour dot + label + "− value +" stepper. */
  .cw-phases { display: flex; flex-direction: column; }
  .cw-phase-row { display: flex; align-items: center; gap: 10px; padding: 9px 0; border-top: 1px solid var(--border); }
  .cw-phase-row:first-child { border-top: 0; padding-top: 0; }
  .cw-phase-dot { width: 9px; height: 9px; border-radius: 50%; flex: none; }
  .cw-phase-label { flex: 1; min-width: 0; font-size: 13.5px; font-weight: 700; color: var(--text-2); }
  .cw-step { display: inline-flex; align-items: center; gap: 2px; }
  .cw-step-btn {
    width: 28px; height: 28px; display: grid; place-items: center; cursor: pointer;
    background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-pill);
    color: var(--text-2); font-size: 15px; font-weight: 700; line-height: 1; padding: 0;
    transition: border-color 120ms ease, background-color 120ms ease, color 120ms ease;
  }
  .cw-step-btn:hover:not(:disabled) { border-color: var(--accent-ring); background: var(--accent-soft); color: var(--accent); }
  .cw-step-btn:disabled { opacity: 0.45; cursor: default; }
  .cw-step-val { display: inline-flex; align-items: baseline; justify-content: center; gap: 3px; min-width: 76px; }
  .cw-step-val em { font-style: normal; font-size: 11px; color: var(--text-3); }
  /* Editable field: the ± buttons are the fast path, typing the exact path.
     The native spinners would duplicate the buttons, so they're hidden. */
  .cw-step-input {
    width: 46px; text-align: center; font-family: var(--font-mono); font-size: 14px;
    font-weight: 700; color: var(--text); background: transparent;
    border: 1px solid transparent; border-radius: 8px; padding: 2px 0;
    transition: border-color 120ms ease, background-color 120ms ease;
    -moz-appearance: textfield; appearance: textfield;
  }
  .cw-step-input::-webkit-outer-spin-button,
  .cw-step-input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
  .cw-step-input:hover:not(:disabled) { border-color: var(--border); }
  .cw-step-input:focus { outline: none; border-color: var(--accent-ring); background: var(--accent-soft); }
  .cw-step-input:disabled { opacity: 0.45; }

  .cw-url-row { display: flex; align-items: center; gap: 6px; }
  .cw-obs-hint { display: flex; align-items: flex-start; gap: 8px; margin-top: 10px; font-size: 12px; color: var(--text-3); }

  /* One grid for the whole list, rows spliced in via display:contents — that
     way every chip is sized by the LONGEST command, not by its own text. */
  .cw-cmds { display: grid; grid-template-columns: max-content 1fr; column-gap: 10px; row-gap: 7px; }
  .cw-cmd { display: contents; }
  .cw-cmd code {
    font-family: var(--font-mono); font-size: 12px; font-weight: 700; white-space: nowrap;
    background: var(--accent-soft); color: var(--accent); border: 1px solid var(--accent-ring);
    border-radius: var(--radius-pill); padding: 2px 8px; text-align: center; align-self: center;
  }
  .cw-cmd span { font-size: 12.5px; color: var(--text-3); align-self: center; }

  /* The commands driving the overlay you're currently configuring stand out —
     each tab in its own hue, matching the phase dots (accent / ok / info) —
     while the rest of the vocabulary stays readable but quiet. */
  .cw-cmd.is-own span { color: var(--text-2); }
  .cw-cmd.is-own code { font-weight: 800; }
  .cw-cmds.k-todo .cw-cmd.is-own code {
    background: rgba(47, 208, 138, 0.14); color: var(--ok); border-color: rgba(47, 208, 138, 0.45);
  }
  .cw-cmds.k-chattodo .cw-cmd.is-own code {
    background: rgba(106, 168, 255, 0.14); color: var(--info); border-color: rgba(106, 168, 255, 0.45);
  }
  .cw-cmd:not(.is-own) code {
    background: transparent; color: var(--text-3); border-color: var(--border); font-weight: 600;
  }

/* ---------- Song-request blacklists ---------- */
.bl-type {
    display: inline-block; font-size: 11px; font-weight: 800; letter-spacing: .02em;
    border-radius: var(--radius-pill); padding: 3px 10px; white-space: nowrap;
}
/* Artist / channel entries block a person, keywords block a phrase — two
   different kinds of rule, so they read differently. */
.bl-type.is-name { background: var(--accent-soft); color: var(--accent); border: 1px solid var(--accent-ring); }
.bl-type.is-keyword { background: rgba(106, 168, 255, 0.12); color: var(--info); border: 1px solid rgba(106, 168, 255, 0.4); }
.bl-value { font-size: 13px; font-weight: 700; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bl-raw { font-size: 11px; color: var(--text-3); }

/* ---------- Music playlists ---------- */
.pl-name { font-size: 13px; font-weight: 700; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pl-name-row, .pl-owner-row { display: flex; align-items: center; gap: 8px; min-width: 0; }
.pl-id, .pl-desc { font-size: 11px; color: var(--text-3); }
.pl-count { font-size: 13px; font-weight: 700; color: var(--text); font-variant-numeric: tabular-nums; }
.pl-dash { color: var(--text-3); }
/* Ownership / import markers — quieter than a full status pill. */
.pl-flag {
    display: inline-block; font-size: 11px; font-weight: 700; white-space: nowrap;
    border-radius: var(--radius-pill); padding: 2px 9px;
    background: var(--surface); color: var(--text-3); border: 1px solid var(--border);
}
.pl-flag.is-ok { background: rgba(47, 208, 138, 0.12); color: var(--ok); border-color: rgba(47, 208, 138, 0.4); }
.pl-flag.is-warn { background: rgba(245, 181, 68, 0.12); color: var(--warn); border-color: rgba(245, 181, 68, 0.4); }
/* The playlist currently feeding song requests. */
.streamionbot-grid-row.is-active { background: var(--accent-soft); }

/* ---------- Corner radius of buttons & chips ----------
   MudBlazor derives these from the theme's DefaultBorderRadius (14px), which is
   the CARD radius — on a 34px-tall button that reads as a capsule. Buttons and
   chips instead share the pill radius, so a "Save" button and a status pill have
   the same corner. Icon buttons stay circular: they're round by design, like the
   toggles and status dots. */
.mud-button-root:not(.mud-icon-button):not(.mud-fab) { border-radius: var(--radius-pill); }
.mud-chip { border-radius: var(--radius-pill); }

/* ---------- Connection cards (Channel, Custom Bot) ----------
   One account, its state and what it may do. Shared because the broadcaster
   and the custom-bot connection are the same thing twice. */
.conn-card { max-width: 720px; }
.conn-head { display: flex; align-items: center; gap: 12px; }
.conn-ico {
    width: 38px; height: 38px; flex: none; border-radius: 11px; display: grid; place-items: center;
    background: var(--surface); color: var(--text-3); border: 1px solid var(--border);
}
.conn-ico.is-ok { background: rgba(47, 208, 138, 0.12); color: var(--ok); border-color: rgba(47, 208, 138, 0.4); }
.conn-ico.is-danger { background: rgba(255, 122, 122, 0.12); color: var(--danger); border-color: rgba(255, 122, 122, 0.4); }
.conn-ico.is-warn { background: rgba(245, 181, 68, 0.12); color: var(--warn); border-color: rgba(245, 181, 68, 0.45); }
.conn-meta { flex: 1; min-width: 0; }
.conn-title { font-family: var(--font-display); font-weight: 700; font-size: 16px; color: var(--text);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.conn-sub { font-size: 12px; font-weight: 600; color: var(--text-3); margin-top: 2px; }
.conn-desc { font-size: 13.5px; color: var(--text-2); margin: 16px 0 0; }
.conn-hint { font-size: 12.5px; color: var(--text-3); }

/* Connection facts as label/value pairs — reads faster than a text block. */
.conn-facts { display: grid; grid-template-columns: max-content 1fr; gap: 6px 16px; margin: 18px 0 0; }
.conn-facts dt { font-size: 12.5px; font-weight: 700; color: var(--text-3); margin: 0; }
.conn-facts dd { font-size: 13px; color: var(--text); margin: 0; }
.conn-mono { font-family: var(--font-mono); font-size: 12px; }

/* Scopes are the reason a reconnect is ever needed, so they're listed rather
   than crammed into one comma-separated line. */
.conn-scopes { margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--border); }
.conn-scopes-head { display: flex; align-items: baseline; gap: 8px; font-size: 12.5px; font-weight: 700; color: var(--text-3); }
.conn-scope-count { font-weight: 600; color: var(--text-3); opacity: 0.8; }
.conn-scope-list { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 8px; }
.conn-scope-list code {
    font-family: var(--font-mono); font-size: 11px; font-weight: 600; white-space: nowrap;
    background: var(--surface); color: var(--text-2); border: 1px solid var(--border);
    border-radius: var(--radius-pill); padding: 2px 8px;
}
.conn-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 18px;
    padding-top: 14px; border-top: 1px solid var(--border); }

/* ==================================================================
   Phase 10 — Settings › Music (design ref #8a).
   Provider picker (selectable cards), connection status cards, and the
   song-request / channel-point / custom-app settings grid. Everything is
   token-driven, so [data-theme="light"] restyles it with no per-rule
   overrides; ok/danger tints are color-mixed from --ok/--danger so they
   flip with the theme too.
   ================================================================== */
.ms-page { display: flex; flex-direction: column; gap: 22px; }

/* Header — back-link, title, one-liner + active-provider pill. */
.ms-head { display: flex; align-items: flex-end; gap: 14px; }
.ms-head-main { flex: 1; min-width: 0; }
.ms-back { display: inline-block; font-size: 12px; font-weight: 800; color: var(--accent);
    text-decoration: none; margin-bottom: 4px; }
.ms-back:hover { filter: brightness(1.1); text-decoration: underline; }
.ms-title { font-family: var(--font-display); font-size: 26px; font-weight: 700;
    letter-spacing: -0.025em; color: var(--text); margin: 0; }
.ms-sub { color: var(--text-2); margin: 3px 0 0; font-size: 13.5px; }

/* Section eyebrow (MUSIK-PROVIDER, VERBINDUNGEN). */
.ms-section { display: flex; flex-direction: column; gap: 10px; }
.ms-eyebrow { font-size: 11px; font-weight: 800; letter-spacing: 0.08em;
    text-transform: uppercase; color: var(--text-3); }
.ms-hint { font-size: 12px; color: var(--text-3); line-height: 1.55; margin: 0; }
.ms-hint code { font-family: var(--font-mono); font-size: 11px; }

/* Mixed-case status pill (the app's uppercase StatusPill doesn't fit the
   "Spotify aktiv" / "Verbunden" wording). Tints derived from --ok. */
.ms-pill { display: inline-flex; align-items: center; gap: 7px; flex: none;
    border-radius: var(--r-pill); padding: 5px 13px; font-size: 12px; font-weight: 800;
    white-space: nowrap; border: 1px solid var(--border); background: var(--surface); color: var(--text-2); }
.ms-pill-dot { width: 7px; height: 7px; border-radius: var(--r-pill); background: var(--text-3); flex: none; }
.ms-pill-ok { background: color-mix(in srgb, var(--ok) 12%, transparent);
    border-color: color-mix(in srgb, var(--ok) 40%, transparent); color: var(--ok); }
.ms-pill-ok .ms-pill-dot { background: var(--ok); }
.ms-head-pill { align-self: center; }

/* Provider picker — three selectable cards; active = accent-soft + ring + glow. */
.ms-provider-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
.ms-provider-card { display: flex; align-items: center; gap: 13px; text-align: left; width: 100%;
    padding: 15px 17px; border-radius: var(--radius); cursor: pointer; color: inherit; font: inherit;
    background: var(--surface); border: 1px solid var(--border);
    transition: background 130ms ease, border-color 130ms ease, box-shadow 130ms ease; }
.ms-provider-card:hover:not(:disabled) { background: var(--surface-hover); }
.ms-provider-card:disabled { cursor: default; }
.ms-provider-card.is-active { background: var(--accent-soft); border-color: var(--accent-ring);
    box-shadow: 0 0 0 3px var(--accent-soft); }
.ms-provider-ico { width: 38px; height: 38px; flex: none; border-radius: 11px; display: grid; place-items: center;
    background: var(--surface); color: var(--text-2); border: 1px solid var(--border); }
.ms-provider-card.is-active .ms-provider-ico { color: var(--accent); border-color: var(--accent-ring);
    background: color-mix(in srgb, var(--accent) 16%, transparent); }
.ms-provider-ico .mud-icon-root { font-size: 20px; }
.ms-provider-text { flex: 1; min-width: 0; }
.ms-provider-title { display: block; font-weight: 800; font-size: 13.5px; color: var(--text-2); }
.ms-provider-card.is-active .ms-provider-title { color: var(--text); }
.ms-provider-desc { display: block; font-size: 11.5px; color: var(--text-3); margin-top: 1px;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ms-provider-radio { width: 18px; height: 18px; flex: none; box-sizing: border-box;
    border-radius: var(--r-pill); border: 2px solid var(--border-strong); }
.ms-provider-radio.is-active { border: 5px solid var(--accent); background: var(--surface-solid); }

/* Connection status cards. */
.ms-conn-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; align-items: stretch; }
.ms-conn-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
    padding: 18px 20px; display: flex; flex-direction: column; gap: 12px; box-shadow: var(--shadow-sm);
    backdrop-filter: blur(16px) saturate(130%); -webkit-backdrop-filter: blur(16px) saturate(130%); }
.ms-conn-head { display: flex; align-items: center; gap: 12px; }
.ms-conn-head .conn-ico { width: 40px; height: 40px; border-radius: 12px; }
.ms-conn-head .conn-ico .mud-icon-root { font-size: 22px; }
.ms-conn-headtext { flex: 1; min-width: 0; }
.ms-conn-title { font-weight: 800; font-size: 14.5px; color: var(--text);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ms-conn-account { font-size: 12px; color: var(--text-2); margin-top: 1px;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ms-conn-desc { font-size: 13px; color: var(--text-2); line-height: 1.5; margin: 0; }
.ms-conn-alert { margin: 0; }
.ms-conn-meta { background: color-mix(in srgb, var(--bg) 55%, transparent);
    border: 1px solid var(--border); border-radius: 10px; padding: 10px 13px;
    display: flex; flex-direction: column; gap: 5px; }
.ms-conn-metarow { display: flex; gap: 10px; font-size: 11.5px; }
.ms-conn-metalabel { color: var(--text-3); width: 80px; flex: none; }
.ms-conn-metaval { color: var(--text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ms-conn-actions { display: flex; align-items: center; gap: 9px; margin-top: auto; }
.ms-inline-form { display: contents; }
.ms-mono { font-family: var(--font-mono); font-size: 11px; }

/* Settings grid: left song-requests, right stacked (channel points + app). */
.ms-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; align-items: stretch; }
.ms-grid-single { grid-template-columns: 1fr; }
.ms-col { display: flex; flex-direction: column; gap: 12px; }

/* Settings card chrome (header with toggle + body). */
.ms-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
    overflow: hidden; display: flex; flex-direction: column; flex: 1 0 auto; box-shadow: var(--shadow-sm);
    backdrop-filter: blur(16px) saturate(130%); -webkit-backdrop-filter: blur(16px) saturate(130%); }
.ms-card-head { display: flex; align-items: center; gap: 12px; padding: 15px 20px;
    border-bottom: 1px solid var(--border); }
.ms-card-headtext { flex: 1; min-width: 0; }
.ms-card-title { font-family: var(--font-display); font-weight: 700; font-size: 15px; color: var(--text); }
.ms-card-title.ms-title-badge { display: flex; align-items: center; gap: 9px; }
.ms-card-sub { font-size: 12px; color: var(--text-3); margin-top: 1px; }
.ms-card-sub code { font-family: var(--font-mono); font-size: 11px; }
.ms-card-body { padding: 18px 20px; display: flex; flex-direction: column; gap: 14px; }
.ms-card-hint { font-size: 12px; color: var(--text-3); line-height: 1.55; }
.ms-card-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.ms-field-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.ms-toggle-rows { display: flex; flex-direction: column; gap: 2px; }
.ms-toggle-row { display: flex; align-items: center; gap: 12px; padding: 6px 2px; }
.ms-toggle-label { font-size: 13px; font-weight: 700; color: var(--text-2); }
.ms-cp-fields { display: flex; flex-direction: column; gap: 14px; transition: opacity 130ms ease; }
.ms-cp-fields.is-dimmed { opacity: 0.55; }

/* Custom-app redirect info box + copy chip. */
.ms-info-box { display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
    background: var(--accent-soft); border: 1px solid var(--accent-ring); border-radius: 10px;
    padding: 10px 13px; font-size: 12px; color: var(--text-2); }
.ms-info-ico { flex: none; color: var(--accent); }
.ms-info-text { line-height: 1.5; }
.ms-copy-chip { display: inline-flex; align-items: center; gap: 8px; border-radius: 6px;
    padding: 4px 6px 4px 9px; background: color-mix(in srgb, var(--bg) 40%, transparent); }
.ms-copy-btn { border: 0; background: transparent; cursor: pointer; color: var(--text-3);
    font-size: 13px; line-height: 1; padding: 2px 5px; border-radius: 5px; }
.ms-copy-btn:hover { color: var(--text); background: var(--surface-hover); }
.ms-ok-caption { font-size: 12px; color: var(--ok); }

@media (max-width: 899.98px) {
    .ms-provider-grid { grid-template-columns: 1fr; }
    .ms-conn-grid { grid-template-columns: 1fr; }
    .ms-grid { grid-template-columns: 1fr; }
    .ms-field-grid { grid-template-columns: 1fr; }
}

/* ==================================================================
   Phase 8 — mobile shell (<960px): bottom bar + "Mehr" sheet.
   Desktop keeps the sidebar; below the breakpoint the MudDrawer is
   removed entirely (design ref #6a — the drawer variant #6b was
   rejected) and the bottom bar takes over navigation.
   ================================================================== */

/* Bottom bar — hidden on desktop, fixed above the safe area on phones. */
.streamionbot-mnav { display: none; }

/* "Mehr" sheet + backdrop (only ever rendered while open). */
.streamionbot-msheet-backdrop {
    position: fixed; inset: 0; z-index: 1340;
    background: rgba(0, 0, 0, 0.55);
}
.streamionbot-msheet {
    /* Above the bottom bar (1300), below MudBlazor popovers (1400) so the
       embedded HelpMenu can open on top of the sheet. */
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 1350;
    background: var(--panel-blur, rgba(16, 13, 26, 0.97));
    backdrop-filter: blur(24px) saturate(140%);
    -webkit-backdrop-filter: blur(24px) saturate(140%);
    border-top: 1px solid var(--border-strong);
    border-radius: 22px 22px 0 0;
    padding: 10px 16px calc(22px + env(safe-area-inset-bottom));
}
.streamionbot-msheet-grabber {
    width: 38px; height: 4px; border-radius: 999px;
    background: var(--border-strong); margin: 0 auto 14px;
}
.streamionbot-msheet-grid {
    display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-bottom: 12px;
}
.streamionbot-msheet-tile {
    display: flex; align-items: center; gap: 10px;
    background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
    padding: 12px 13px; text-decoration: none;
    font-size: 12.5px; font-weight: 800; color: var(--text);
    transition: background-color 130ms ease;
}
.streamionbot-msheet-tile:hover { background: var(--surface-hover); }
.streamionbot-msheet-tile .mud-icon-root { color: var(--text-3); }
.streamionbot-msheet-foot {
    border-top: 1px solid var(--border); padding-top: 10px;
    display: flex; flex-direction: column; gap: 2px;
}
.streamionbot-msheet-row {
    display: flex; align-items: center; gap: 11px;
    padding: 6px 8px; border-radius: 10px;
}
.streamionbot-msheet-row-ico { width: 34px; display: grid; place-items: center; color: var(--text-3); }
.streamionbot-msheet-row-label { flex: 1; font-size: 13px; font-weight: 700; color: var(--text); }

/* Mobile brand tile in the top bar — desktop has the sidebar's brand head. */
.streamionbot-topbar-mlogo { display: none; }

@media (max-width: 959.98px) {
    /* The sidebar and its off-canvas remnants disappear completely. */
    .mud-drawer, .mud-drawer-overlay, .mud-overlay-drawer { display: none !important; }

    /* Content clears the fixed bottom bar (incl. iOS safe area). */
    .mud-main-content { padding-bottom: calc(72px + env(safe-area-inset-bottom)); }
    .mud-main-content > .mud-container { padding: 16px !important; }

    /* Bottom bar. */
    .streamionbot-mnav {
        display: flex; position: fixed; left: 0; right: 0; bottom: 0; z-index: 1300;
        background: var(--panel-blur, rgba(16, 13, 26, 0.92));
        backdrop-filter: blur(24px) saturate(140%);
        -webkit-backdrop-filter: blur(24px) saturate(140%);
        border-top: 1px solid var(--border);
        padding: 8px 6px calc(10px + env(safe-area-inset-bottom));
    }
    .streamionbot-mnav-tab {
        all: unset; cursor: pointer; flex: 1;
        display: flex; flex-direction: column; align-items: center; gap: 3px;
        padding: 2px 0; text-decoration: none; position: relative;
    }
    .streamionbot-mnav-ico {
        width: 44px; height: 30px; display: flex; align-items: center; justify-content: center;
        border-radius: 10px; color: var(--text-3);
        transition: background-color 140ms ease, color 140ms ease;
    }
    .streamionbot-mnav-ico .mud-icon-root { font-size: 19px; width: 19px; height: 19px; }
    .streamionbot-mnav-label { font-size: 9.5px; font-weight: 800; color: var(--text-3); }
    .streamionbot-mnav-tab.active .streamionbot-mnav-ico {
        background: rgba(157, 107, 255, 0.18); color: #c9adff;
    }
    .streamionbot-mnav-tab.active .streamionbot-mnav-label { color: #c9adff; }
    [data-theme="light"] .streamionbot-mnav-tab.active .streamionbot-mnav-ico { color: var(--accent); }
    [data-theme="light"] .streamionbot-mnav-tab.active .streamionbot-mnav-label { color: var(--accent); }

    /* Top bar goes compact: brand tile + title + status; the ⌘K search,
       breadcrumb group and help/theme buttons live elsewhere on mobile. */
    .streamionbot-topbar-mlogo {
        display: grid; place-items: center;
        width: 32px; height: 32px; flex: none; margin-right: 2px;
    }
    .streamionbot-topbar-mlogo img { width: 32px; height: 32px; object-fit: contain; }
    .streamionbot-topbar-group, .streamionbot-topbar-sep { display: none; }
    .streamionbot-topbar-search { display: none; }
    .streamionbot-topbar-desktop { display: none; }
    .streamionbot-topbar-metrics { display: none; }

    /* Touch has no hover — row actions are always visible. */
    .streamionbot-grid-actions { opacity: 1; }
}
