/* dashboard-bot.css — verify-bot config subpage.
   Everything visual that already exists in dashboard.css (inputs, buttons,
   typography, modal styles) is REUSED. This file only adds the few layout
   bits that don't have an equivalent on /dashboard:
     - greeting back-chip + license/status pills
     - the tabs strip (uses store-tabs base + tweaks)
     - the content panel container
     - blacklist row layout
     - paywall card for locked branding
     - toast host position
*/

/* ─── Greeting block ────────────────────────────────────────────────────── */
/* Two-column header layout: greeting text on the left, server-stats panel
   pinned to the right. Stacks vertically on tablet and narrower.
   `dashboard-greeting` (from dashboard.css) sets max-width: 720px which
   would force the stats panel to wrap. We override max-width so the
   panel can sit on the right at full container width. */
.vb-greeting {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 24px;
  flex-wrap: wrap;
  max-width: none;
}
.vb-greeting .dashboard-greeting-text {
  flex: 1 1 320px;
  min-width: 0;
}

/* Middle-row promoted actions ("Branding" + "White-Label"). They sit
   centered horizontally between the title block and the stats panel,
   bottom-aligned to the license-key row so they read as a clean
   inline pair instead of a separate stacked column. */
/* Header-side quick-actions: default = flex (handles 1 or 2 buttons).
   The dashboard-bot page has 3 buttons and opts into the 2x2 grid below
   via the inline-style-free vbQuickActions wrapper. Restore-bot has only
   one button (Bot Personalisieren) and stays on the simple flex layout. */
.vb-quick-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  flex: 0 0 auto;
  align-self: flex-end;
  margin: 0 auto 2px;
}
/* Single-button variant on restore-bot: don't stretch to fill, just
   right-align it with a sensible width so the lone button doesn't look
   orphaned. */
.vb-quick-actions--single {
  min-width: 220px;
  justify-content: flex-end;
}
.vb-quick-actions[hidden] { display: none; }

/* Dashboard-bot 3-button layout: 2x2 grid with one empty cell.
     ┌──────────────┬──────────────┐
     │   (empty)    │  Einstellungen│  ← Settings sits above Restore only
     ├──────────────┼──────────────┤
     │Personalisieren│ Restore Opt. │  ← the two per-instance actions side by side
     └──────────────┴──────────────┘
   Scoped to #vbQuickActions so it doesn't bleed onto restore-bot's
   #rbHeaderActions, which uses the flex default above. */
#vbQuickActions.vb-quick-actions {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: auto auto;
  min-width: 360px;
}
#vbQuickActions .vb-qa-btn--settings { grid-column: 2; grid-row: 1; }
#vbQuickActions .vb-qa-btn--paid     { grid-column: 1; grid-row: 2; }
#vbQuickActions .vb-qa-btn--restore  { grid-column: 2; grid-row: 2; }
.vb-qa-btn {
  display: inline-flex;
  align-items: center;
  justify-content: flex-start;
  gap: 10px;
  padding: 9px 14px;
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  color: var(--text-muted);
  background: rgba(255, 255, 255, 0.04);
  border: 1px dashed rgba(255, 255, 255, 0.35);
  border-radius: 10px;
  cursor: pointer;
  text-decoration: none;
  width: 100%;
  transition: background .15s, border-color .15s, color .15s, transform .1s;
}
.vb-qa-btn:active { transform: translateY(1px); }
.vb-qa-btn .vb-paid-diamond { display: inline-flex; }

/* External-link arrow on buttons that navigate AWAY from the current
   page (e.g. Bot Personalisieren on restore-bot → goes to /dashboard-bot).
   Subtle by default, stronger on hover. */
.vb-qa-extern {
  margin-left: 6px;
  opacity: 0.75;
  transition: opacity .15s, transform .15s;
  flex-shrink: 0;
}
.vb-qa-btn:hover .vb-qa-extern {
  opacity: 1;
  transform: translate(1px, -1px);
}

/* All three variants share the same orange chrome — only the icon colors
   the button. Kept as separate selectors so future per-button tweaks (e.g.
   adding an external-link arrow on Restore) can attach cleanly. */
.vb-qa-btn--paid     .vb-qa-icon,
.vb-qa-btn--settings .vb-qa-icon,
.vb-qa-btn--restore  .vb-qa-icon,
.vb-qa-btn--restore  .vb-qa-extern { color: var(--orange); }
.vb-qa-btn--paid:hover,
.vb-qa-btn--settings:hover,
.vb-qa-btn--restore:hover {
  background: rgba(255, 130, 40, 0.12);
  border-color: rgba(255, 130, 40, 0.55);
}
.vb-qa-btn--paid.active,
.vb-qa-btn--settings.active,
.vb-qa-btn--restore.active {
  background: rgba(255, 130, 40, 0.14);
  border-style: solid;
  border-color: var(--orange);
}

@media (max-width: 900px) {
  .vb-quick-actions,
  #vbQuickActions.vb-quick-actions {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-self: stretch;
    min-width: 0;
    margin: 4px 0 0;
  }
  .vb-qa-btn { flex: 1 1 auto; width: auto; justify-content: center; }
  /* Reset grid placements for mobile so flex order applies (HTML order:
     Settings → Personalisieren → Restore). */
  #vbQuickActions .vb-qa-btn--settings,
  #vbQuickActions .vb-qa-btn--paid,
  #vbQuickActions .vb-qa-btn--restore { grid-column: auto; grid-row: auto; }
}
.vb-greeting .dashboard-subtitle {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

/* Right-side guild stats panel — six tiles in a 3×2 grid on desktop,
   2×3 on tablet, 2 cols on mobile. Devcon-style: subtle card chrome,
   large value, dim label. Accent variants tint the value: green for
   online, orange-pink gradient for boosts. */
.vb-guild-stats {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
  flex: 0 0 auto;
  width: 380px;
  max-width: 100%;
}
@media (max-width: 1100px) {
  .vb-guild-stats { width: 100%; grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 640px) {
  .vb-guild-stats { grid-template-columns: repeat(2, 1fr); }
}

.vb-gs-tile {
  position: relative;
  overflow: hidden;
  background: rgba(255,255,255,.025);
  border: 1px solid rgba(255,255,255,.06);
  border-radius: 10px;
  padding: 12px 14px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  transition: border-color .15s, background .15s;
}
.vb-gs-tile:hover {
  border-color: rgba(255,255,255,.12);
  background: rgba(255,255,255,.04);
}

/* Background icon — mirrors the `/dashboard` stat cards: large, dim,
   pinned to the right edge of the tile. Hover bumps opacity and shifts
   the accent to orange (overridden by accent variants below). */
.vb-gs-tile-icon {
  position: absolute;
  right: -8px;
  top: 50%;
  transform: translateY(-50%);
  width: 64px;
  height: 64px;
  color: var(--text-muted);
  opacity: 0.10;
  pointer-events: none;
  z-index: 0;
  transition: opacity .25s ease, color .25s ease;
}
.vb-gs-tile-icon svg { width: 100%; height: 100%; display: block; }
.vb-gs-tile:hover .vb-gs-tile-icon {
  opacity: 0.18;
  color: var(--orange);
}

.vb-gs-tile-value,
.vb-gs-tile-label {
  position: relative;
  z-index: 1;
}
.vb-gs-tile-value {
  font-family: var(--font-display, 'Geist', system-ui, sans-serif);
  font-size: 22px;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--text);
  line-height: 1.1;
}
.vb-gs-tile-label {
  font-size: 10.5px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--text-dim);
}
.vb-gs-tile--online .vb-gs-tile-value {
  color: #22c55e;
}
.vb-gs-tile--online {
  border-color: rgba(34,197,94,.18);
  background: rgba(34,197,94,.04);
}
.vb-gs-tile--online:hover { border-color: rgba(34,197,94,.35); }
.vb-gs-tile--online .vb-gs-tile-icon { color: #22c55e; opacity: 0.14; }
.vb-gs-tile--online:hover .vb-gs-tile-icon { color: #22c55e; opacity: 0.22; }

.vb-gs-tile--boost .vb-gs-tile-value {
  background: linear-gradient(135deg, #f47fff 0%, #c084fc 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.vb-gs-tile--boost {
  border-color: rgba(192,132,252,.22);
  background: rgba(192,132,252,.04);
}
.vb-gs-tile--boost:hover { border-color: rgba(192,132,252,.4); }
.vb-gs-tile--boost .vb-gs-tile-icon { color: #c084fc; opacity: 0.14; }
.vb-gs-tile--boost:hover .vb-gs-tile-icon { color: #c084fc; opacity: 0.22; }
/* License holder — populated with the dashboard.css .dash-license-dot
   + .dash-spoiler pair so it visually matches /dashboard exactly. */
.vb-license-holder {
  display: inline-flex;
  align-items: center;
}

/* Title: "<username>'s Bot" — username + possessive stay white (default),
   "Bot" becomes the italic orange accent like /dashboard's <em>. */
.vb-greeting .dashboard-title .vb-poss {
  color: var(--text);
  font-style: normal;
  font-weight: 700;
}
.vb-greeting .dashboard-title .vb-bot-accent {
  color: var(--orange);
  font-style: italic;
}
/* Match the gap below the title to the eyebrow→title gap (14px) so the
   title sits visually centered between the eyebrow above and the license
   line below. */
.vb-greeting .dashboard-title {
  margin-bottom: 14px;
}

/* Inline title editor: a flat pencil icon (no chrome) next to "Bot", and
   the prefix span itself becomes contenteditable on click so the caret
   lands directly after the last character — no separate input field. */
.vb-title-edit-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-left: 8px;
  padding: 0;
  vertical-align: middle;
  background: transparent;
  border: 0;
  color: var(--text);
  opacity: 0.55;
  cursor: pointer;
  transition: opacity .15s, color .15s;
}
.vb-title-edit-btn:hover { opacity: 1; color: var(--orange); }
.vb-title-edit-btn:focus-visible { outline: none; opacity: 1; color: var(--orange); }
/* While editing the icon is a checkmark — show it green at full opacity
   so the user sees "click to save" instead of "click to edit". */
.vb-title-edit-btn.is-saving { opacity: 1; color: #4ade80; }
.vb-title-edit-btn.is-saving:hover { color: #22c55e; }

/* When editing: render exactly like the surrounding text. No box, no
   width — caret + characters only. */
.vb-title-text[contenteditable="true"] {
  outline: none;
  caret-color: var(--orange);
  white-space: pre;
}

/* Tiny grey "Server-ID: 1234…" line sitting between the title and the
   license row. Mono digits so the numeric block reads cleanly. */
.vb-guild-id-line {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--text-dim, rgba(255, 255, 255, 0.5));
  margin: -6px 0 10px;
}
/* Specificity above beats the [hidden] default; restore it explicitly so
   the line never shows on the server-picker view (no guild bound yet). */
.vb-guild-id-line[hidden] { display: none; }
.vb-guild-id-line .vb-guild-id-label { opacity: 0.85; }
.vb-guild-id-line .vb-guild-id-value {
  font-variant-numeric: tabular-nums;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  letter-spacing: 0.2px;
}

/* ─── Module tabs (top strip) ───────────────────────────────────────────── */
.vb-tabs { margin-top: 20px; }
/* Module-tab icon (Lucide-style stroke SVG sitting before the label).
   Inherits the tab's text color so it dims/orange-tints in sync with
   the active/hover/disabled states. */
.vb-tabs .store-tab .vb-tab-icon {
  width: 16px;
  height: 16px;
  flex: 0 0 auto;
  margin-right: 2px;
  opacity: 0.85;
  transition: opacity .15s, color .15s;
}
.vb-tabs .store-tab:hover .vb-tab-icon,
.vb-tabs .store-tab.active .vb-tab-icon { opacity: 1; }
.vb-tabs .store-tab .vb-lock {
  font-size: 11px;
  margin-left: 4px;
  opacity: .8;
}
.vb-tabs .store-tab .vb-lock.unlocked { display: none; }

/* "bald" / "soon" pill next to disabled modules */
.vb-soon-pill {
  display: inline-block;
  margin-left: 6px;
  padding: 2px 8px;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  border-radius: 999px;
  background: rgba(255,255,255,.06);
  color: var(--text-dim);
}
.vb-tabs .store-tab.active .vb-soon-pill {
  background: rgba(255,138,34,.18);
  color: var(--orange);
}

/* Premium-feature diamond shown before paid module names.
   Subtle — just a very mild glow + tiny breathing scale. No big halo. */
.vb-paid-diamond {
  display: inline-flex;
  align-items: center;
  width: 18px;
  height: 16px;
  margin-right: 7px;
  vertical-align: -3px;
  flex: 0 0 auto;
  filter: drop-shadow(0 0 1.5px rgba(180, 225, 245, 0.45));
  animation: vbDiamondBreathe 3.6s ease-in-out infinite;
}
.vb-paid-diamond svg { width: 100%; height: 100%; display: block; }
@keyframes vbDiamondBreathe {
  0%, 100% { transform: scale(1);    opacity: 0.95; }
  50%      { transform: scale(1.04); opacity: 1;    }
}

/* Mini on/off switch embedded inside a module tab pill.
   Green = active, Red = inactive. Distinct from the orange active-tab
   highlight so you can read the state at a glance even on the selected tab. */
.vb-tab-switch {
  display: inline-flex;
  align-items: center;
  width: 28px;
  height: 16px;
  background: rgba(240, 71, 71, 0.55);            /* red-off */
  border: 1px solid rgba(240, 71, 71, 0.45);
  border-radius: 999px;
  position: relative;
  margin-left: 6px;
  cursor: pointer;
  transition: background .15s, border-color .15s, box-shadow .15s;
  flex: 0 0 auto;
  vertical-align: middle;
}
.vb-tab-switch:hover {
  background: rgba(240, 71, 71, 0.75);
  box-shadow: 0 0 0 2px rgba(240, 71, 71, 0.18);
}
.vb-tab-switch-slider {
  position: absolute;
  top: 1px;
  left: 1px;
  width: 12px;
  height: 12px;
  background: #f2f3f5;
  border-radius: 50%;
  transition: left .15s, background .15s;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.4);
}
.vb-tab-switch.is-on {
  background: rgba(67, 181, 129, 0.7);            /* green-on */
  border-color: rgba(67, 181, 129, 0.55);
}
.vb-tab-switch.is-on:hover {
  background: rgba(67, 181, 129, 0.9);
  box-shadow: 0 0 0 2px rgba(67, 181, 129, 0.2);
}
.vb-tab-switch.is-on .vb-tab-switch-slider { left: 13px; background: #fff; }

/* Section-title switch (next to the H2 inside each module page). Larger
   variant of the tab pill so it reads as a primary "module on/off"
   control, not a tiny tab adornment. */
.vb-section-switch-wrap {
  display: inline-flex;
  align-items: center;
  margin-left: 14px;
  vertical-align: middle;
}
.vb-section-switch {
  width: 40px;
  height: 22px;
  margin: 0;
}
.vb-section-switch .vb-tab-switch-slider {
  width: 16px;
  height: 16px;
  top: 2px;
  left: 2px;
}
.vb-section-switch.is-on .vb-tab-switch-slider { left: 21px; }

/* When the module switch is off, give the tab pill itself a slightly
   dimmer feel so the user sees "not active yet". */
.store-tab:not(.is-mod-on)[data-module="verify"],
.store-tab:not(.is-mod-on)[data-module="ticket"],
.store-tab:not(.is-mod-on)[data-module="giveaway"] {
  opacity: 0.85;
}

/* Vertical separator between feature modules and shared modules */
.vb-module-divider {
  display: inline-block;
  width: 1px;
  align-self: stretch;
  background: rgba(255,255,255,.08);
  margin: 6px 4px;
}
@media (max-width: 640px) { .vb-module-divider { display: none; } }

/* ─── Sub-tabs (secondary nav inside content panel) ──────────────────────── */
.vb-subtabs {
  display: flex;
  gap: 2px;
  margin: -8px -8px 20px;
  padding: 4px;
  background: rgba(0,0,0,.18);
  border: 1px solid rgba(255,255,255,.04);
  border-radius: 10px;
  overflow-x: auto;
  scrollbar-width: thin;
}
.vb-subtab {
  appearance: none;
  background: transparent;
  border: 0;
  color: var(--text-dim);
  font-family: inherit;
  font-size: 13px;
  font-weight: 500;
  padding: 8px 14px;
  border-radius: 8px;
  cursor: pointer;
  white-space: nowrap;
  transition: background .12s, color .12s;
}
.vb-subtab:hover { color: var(--text-bright); background: rgba(255,255,255,.03); }
.vb-subtab.is-active {
  background: rgba(255,138,34,.12);
  color: var(--orange);
}
@media (max-width: 640px) { .vb-subtabs { margin: 0 0 20px; } }

/* "Coming soon" placeholder for stubbed modules */
.vb-coming-soon {
  text-align: center;
  padding: 48px 24px;
  border: 1px dashed rgba(255,255,255,.08);
  border-radius: 12px;
  background: rgba(255,255,255,.015);
}
.vb-coming-soon h2 {
  font-size: 18px;
  margin: 0 0 8px;
  color: var(--text-bright);
}
.vb-coming-soon p {
  color: var(--text-dim);
  margin: 0 0 18px;
  font-size: 14px;
  line-height: 1.55;
  max-width: 420px;
  margin-left: auto;
  margin-right: auto;
}
.vb-coming-soon-preview {
  display: inline-flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px;
  margin-top: 8px;
}
.vb-coming-soon-preview span {
  font-size: 12px;
  padding: 4px 10px;
  border-radius: 999px;
  background: rgba(255,255,255,.04);
  color: var(--text-dim);
  border: 1px solid rgba(255,255,255,.06);
}

/* ─── Content panel ─────────────────────────────────────────────────────── */
.vb-panel {
  margin-top: 20px;
  background: var(--bg-card);
  border: 1px solid var(--border, rgba(255,255,255,.06));
  border-radius: var(--radius, 14px);
  padding: 28px 30px;
  min-height: 380px;
}
@media (max-width: 640px) {
  .vb-panel { padding: 20px; }
}
.vb-loading {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 80px 0;
  color: var(--text-dim);
}

/* Empty-state placeholder — used by category list, giveaway list, embed
   list. Same visual language as a section, just centered + dimmed. */
.vb-empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 40px 24px;
  text-align: center;
  color: var(--text-dim);
  font-size: 14px;
  line-height: 1.55;
  border: 1px dashed rgba(255,255,255,.10);
  border-radius: 12px;
  background: rgba(255,255,255,.015);
}
/* Mark: Lupe mit X drin (search-x). Sauberer als das vorherige ?-Glyph,
   universell als „gesucht, nichts gefunden" lesbar. Wird auch von
   .vb-ec-table-empty unten geteilt — selbe Image-URL halten. */
.vb-empty-state::before {
  content: '';
  width: 60px;
  height: 60px;
  background-color: var(--text-muted);
  opacity: 0.32;
  -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'><path d='M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z'/><polyline points='14 2 14 8 20 8'/><line x1='9.5' y1='12.5' x2='14.5' y2='17.5'/><line x1='14.5' y1='12.5' x2='9.5' y2='17.5'/></svg>");
          mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'><path d='M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z'/><polyline points='14 2 14 8 20 8'/><line x1='9.5' y1='12.5' x2='14.5' y2='17.5'/><line x1='14.5' y1='12.5' x2='9.5' y2='17.5'/></svg>");
  -webkit-mask-size: contain;          mask-size: contain;
  -webkit-mask-repeat: no-repeat;       mask-repeat: no-repeat;
  -webkit-mask-position: center;        mask-position: center;
}
@media (max-width: 640px) {
  .vb-empty-state { padding: 28px 16px; font-size: 13px; }
  .vb-empty-state::before { width: 50px; height: 50px; }
}

/* Async-disabled buttons (during save / post / delete). */
.dash-btn[disabled],
.dash-btn.is-loading {
  opacity: 0.6;
  pointer-events: none;
}

.vb-section + .vb-section { margin-top: 28px; padding-top: 24px; border-top: 1px solid rgba(255,255,255,.06); }

/* ─── Item-list rows ────────────────────────────────────────────────────────
   Shared by: ticket categories, giveaway list, embed-creator list.
   One row = compact text on the left, icon-only actions pinned right.
   Class name kept as .vb-blacklist-* for legacy reasons; the styles below
   are the canonical implementation for ALL row lists in the bot dashboard. */

.vb-blacklist-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.vb-blacklist-row {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 12px 14px;
  background: rgba(255,255,255,.02);
  border: 1px solid rgba(255,255,255,.06);
  border-radius: 10px;
  transition: border-color .15s, background .15s;
}
.vb-blacklist-row:hover {
  border-color: rgba(255,138,34,.25);
  background: rgba(255,138,34,.03);
}

.vb-blacklist-row-text {
  flex: 1 1 auto;
  min-width: 0;     /* lets the children truncate cleanly */
}
.vb-blacklist-row-title {
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
  margin-bottom: 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  display: flex;
  align-items: center;
  gap: 6px;
}
.vb-blacklist-row-title code {
  background: rgba(255,255,255,.05);
  padding: 1px 6px;
  border-radius: 4px;
  font-size: 11px;
  color: var(--text-dim);
}
.vb-blacklist-row-sub {
  font-size: 12px;
  color: var(--text-dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  line-height: 1.4;
}
.vb-blacklist-row-actions {
  display: flex;
  gap: 4px;
  flex-shrink: 0;
}

/* Tiny color dot used in front of an embed/category name. */
.vb-row-color-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  flex-shrink: 0;
  border: 1px solid rgba(255,255,255,.15);
}

/* Icon-only row actions (edit / clone / delete). Globale Regel:
   - kein Background, keine Border, keine Pill — nur das Icon
   - Hover/Focus: Icon wird leicht größer + Farbe ändert sich (orange für
     edit/clone, rot für [data-danger])
   - Active: kurzer Press-Effekt
   Memory: feedback_row_icon_btn_global. */
.vb-row-icon-btn {
  width: 28px;
  height: 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  background: transparent;
  border: 0;
  color: var(--text-dim);
  cursor: pointer;
  transition: color .15s ease, transform .15s ease;
}
.vb-row-icon-btn:hover,
.vb-row-icon-btn:focus-visible {
  color: var(--orange);
  background: transparent;
  outline: none;
  transform: scale(1.18);
}
.vb-row-icon-btn:active { transform: scale(.92); }
.vb-row-icon-btn[data-danger]:hover,
.vb-row-icon-btn[data-danger]:focus-visible {
  color: #ef4444;
  background: transparent;
}
.vb-row-icon-btn svg { width: 16px; height: 16px; pointer-events: none; transition: transform .15s ease; }

/* Aktionen-Zelle in jeder list-table: Icons nebeneinander, rechtsbündig
   ans Ende des Grid-Cells gepinnt — damit die `Aktionen`-Legende (via
   .vb-sg-actions-head min-width + text-align:left) BÜNDIG mit dem ersten
   Icon der Zeile beginnt. Memory: feedback_actions_cell_alignment. */
.vb-sg-actions-cell {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: 4px;
}

@media (max-width: 540px) {
  .vb-blacklist-row     { padding: 10px; gap: 10px; }
  .vb-row-icon-btn      { width: 30px; height: 30px; }
}

/* ─── Server picker (Mee6-style /dashboard-bot landing) ──────────────────
   Three columns on desktop, two on tablet, one on mobile. Cards are now
   vertical (icon on top, stats in the middle, CTA pinned to the bottom).
   Installed guilds get a green border + orange CTA; the rest stay subtle
   until hover. */
.vb-server-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 18px;
}
@media (max-width: 1024px) { .vb-server-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 640px)  { .vb-server-grid { grid-template-columns: 1fr; gap: 12px; } }

.vb-server-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 12px;
  padding: 20px;
  background: var(--bg-card, #0e0e10);
  border: 1px solid rgba(255,255,255,.06);
  border-radius: 16px;
  transition: border-color .15s, background .15s, transform .15s;
}
.vb-server-card:hover {
  border-color: rgba(255,138,34,.4);
  background: rgba(255,138,34,.03);
  transform: translateY(-2px);
}

.vb-server-card-icon {
  position: relative;
  width: 64px;
  height: 64px;
  border-radius: 50%;
  overflow: visible;
  flex-shrink: 0;
}
.vb-server-card-icon img {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  object-fit: cover;
  background: rgba(255,255,255,.04);
}
.vb-server-card-fallback {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--orange-deep), var(--orange-bright));
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 20px;
  color: #0a0a0a;
  letter-spacing: -0.02em;
}
.vb-server-owner-badge {
  position: absolute;
  bottom: -2px;
  right: -2px;
  background: linear-gradient(135deg, #fbbf24, #f59e0b);
  border: 2px solid var(--bg-card);
  border-radius: 50%;
  width: 22px;
  height: 22px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #0a0a0a;
  box-shadow: 0 2px 6px rgba(0,0,0,.4);
}
/* Botmaster/Admin Badge — gleiche Größe + Hintergrund wie der Owner-Crown,
   nur mit Wrench-Icon statt Krone. Stroke-Icon braucht ein bisschen mehr
   Kontrast, daher leicht dunklere Color. */
.vb-server-admin-badge {
  color: #1a1a1e;
}

.vb-server-card-name {
  font-size: 15px;
  font-weight: 600;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  letter-spacing: -0.005em;
  width: 100%;
}
/* Mit Sub-Tier Marken hinter dem Namen: Name + Crown(s) in einer Zeile.
   Der Name shrinkt auf die freie Breite, die Marks sitzen fix rechts. */
.vb-server-card-name--with-marks {
  display: flex;
  align-items: center;
  gap: 6px;
  overflow: visible;          /* ellipsis greift jetzt am Name-Span */
}
.vb-server-card-name-text {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex: 0 1 auto;
}
.vb-server-card-marks {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  flex: 0 0 auto;
}
.vb-server-card-marks .vb-premium-mark { margin-right: 0; }
/* Marker im Server-Picker werden kompakter rendered — keine permanente
   Wobble-Animation, kein dauerhafter Glow. */
.vb-server-card-marks .vb-premium-mark:hover { animation: none; }

.vb-server-card-stats {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  color: var(--text-dim);
  flex-wrap: wrap;
}
.vb-server-card-stats strong { color: var(--text); font-weight: 600; }
.vb-server-card-stats svg { color: var(--text-dim); flex-shrink: 0; }

/* Server-ID under the name — same font as the rest of the card, just
   dimmer + kleiner. */
.vb-server-card-id {
  font-family: inherit;
  font-size: 11px;
  color: var(--text-dim);
  letter-spacing: 0.2px;
  margin-top: -2px;
  margin-bottom: 6px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.vb-server-card-id-label { font-weight: 600; }

/* Boost + vanity rows. Same horizontal layout as the member/online
   stats row but color-tinted so the extra info catches the eye. */
.vb-server-card-meta {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 11.5px;
  color: var(--text-dim);
  margin-top: 4px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}
.vb-server-card-meta strong { color: var(--text); font-weight: 600; }
.vb-server-card-meta em { font-style: normal; opacity: 0.7; }

/* Inline boost stat inside .vb-server-card-stats - sits right after
   the online count (no separator dot). Discord-boost-pink to match
   their official boost branding. */
.vb-server-card-meta--vanity { color: var(--text-muted); }
.vb-server-card-meta--vanity svg { color: var(--orange); }
.vb-server-card-meta--vanity code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px;
  color: var(--text);
  background: rgba(255, 130, 40, 0.08);
  padding: 1px 5px;
  border-radius: 4px;
}
.vb-server-card-dot {
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: var(--text-dim);
  opacity: .6;
}
/* Discord-style green presence dot next to the online count. */
.vb-server-online-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #22c55e;
  box-shadow: 0 0 6px rgba(34,197,94,.5);
  flex-shrink: 0;
}
.vb-server-online { color: #22c55e; }
.vb-server-online strong { color: #22c55e; }

/* CTA button — neutral (grey) by default for "needs setup", orange for
   "already installed, continue". No card-level highlighting; the button
   state is the only differentiator. */
.vb-server-card-cta {
  font-size: 13px;
  font-weight: 600;
  padding: 10px 18px;
  border-radius: 10px;
  background: rgba(255,255,255,.04);
  border: 1px solid rgba(255,255,255,.10);
  color: var(--text-muted);
  text-decoration: none;
  text-align: center;
  white-space: nowrap;
  transition: all .15s;
  margin-top: auto;
  align-self: stretch;
}
.vb-server-card-cta:hover {
  border-color: rgba(255,255,255,.20);
  color: var(--text);
  background: rgba(255,255,255,.06);
}
.vb-server-card-cta.is-installed {
  background: var(--orange);
  border-color: var(--orange);
  color: #0a0a0a;
}
.vb-server-card-cta.is-installed:hover {
  background: var(--orange-bright);
  border-color: var(--orange-bright);
  color: #0a0a0a;
}

/* Pill-style segmented mode switcher used by the Welcome tab to pick
   between text / stored-embed. Two pills side by side, active one filled.
   The active state mirrors the .dash-pill orange-on-black pattern from
   the dashboard. */
.vb-mode-pills {
  display: inline-flex;
  gap: 4px;
  padding: 4px;
  background: rgba(255,255,255,.04);
  border: 1px solid rgba(255,255,255,.08);
  border-radius: 999px;
  margin: 6px 0 14px;
}
.vb-mode-pill {
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--text-dim);
  font-size: 12px;
  font-weight: 600;
  padding: 7px 16px;
  border-radius: 999px;
  cursor: pointer;
  transition: color .15s, background .15s;
}
.vb-mode-pill:hover {
  color: var(--text);
}
.vb-mode-pill.is-active {
  background: var(--orange);
  color: #0a0a0a;
}
/* "+ Neuer Embed" creator pill — dashed-orange outline, signals
   "this opens a builder" instead of "this picks an existing one". */
.vb-mode-pill.vb-mode-pill--create {
  color: var(--orange);
  background: rgba(255, 130, 40, 0.06);
  border: 1px dashed rgba(255, 130, 40, 0.40);
  padding: 6px 14px;
}
.vb-mode-pill.vb-mode-pill--create:hover {
  background: rgba(255, 130, 40, 0.14);
  border-color: var(--orange);
  border-style: solid;
}

/* Embed-Creator two-column grid for paired fields. Collapses on mobile. */
.vb-ec-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
  margin-top: 6px;
}
@media (max-width: 640px) {
  .vb-ec-grid { grid-template-columns: 1fr; gap: 8px; }
}
.vb-ec-field-row textarea { min-height: 56px; }
.vb-section h2 {
  font-size: 16px;
  font-weight: 600;
  margin: 0 0 6px;
  letter-spacing: -.005em;
  color: var(--text-bright);
}
.vb-section-desc {
  font-size: 13px;
  color: var(--text-dim);
  margin: 0 0 18px;
  line-height: 1.55;
}

/* ─── Global: kill the default textarea resize handle ───────────────────── */
.dash-modal-input,
textarea.dash-modal-input { resize: none !important; }

/* ─── VS-Code-style HTML editor ─────────────────────────────────────────── */
.vb-codeed {
  background: #1e1e1e;
  border: 1px solid #303034;
  border-radius: 10px;
  overflow: hidden;
  box-shadow: 0 4px 12px rgba(0,0,0,.4);
}
.vb-codeed-tabs {
  display: flex;
  background: #2d2d30;
  border-bottom: 1px solid #1c1c1c;
}
.vb-codeed-tab {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 16px;
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 12px;
  color: #888;
  background: #2d2d30;
  border: 0;
  border-right: 1px solid #1c1c1c;
  border-bottom: 1px solid transparent;
  cursor: pointer;
  transition: background .12s, color .12s;
}
.vb-codeed-tab:hover { background: #383838; color: #d4d4d4; }
.vb-codeed-tab.is-active {
  background: #1e1e1e;
  color: #ffffff;
  border-bottom-color: #1e1e1e;
}
.vb-codeed-dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: #888;
  flex: 0 0 auto;
}
.vb-codeed-dot--html { background: #e44d26; } /* HTML5 orange */
.vb-codeed-dot--css  { background: #2965f1; } /* CSS3 blue */
.vb-codeed-body[hidden] { display: none; }
.vb-codeed-body {
  display: flex;
  background: #1e1e1e;
  position: relative;
}
.vb-codeed-gutter {
  flex: 0 0 auto;
  width: 44px;
  padding: 12px 8px;
  background: #1e1e1e;
  color: #858585;
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 13px;
  line-height: 1.55;
  text-align: right;
  white-space: pre;
  user-select: none;
  border-right: 1px solid #2a2a2a;
  overflow: hidden;
}
.vb-codeed-area {
  flex: 1 1 auto;
  min-height: 180px;
  padding: 12px 14px;
  background: #1e1e1e;
  color: #d4d4d4;
  border: 0;
  outline: none;
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 13px;
  line-height: 1.55;
  resize: none !important;
  white-space: pre;
  overflow-x: auto;
  overflow-y: auto;
  tab-size: 2;
  /* Firefox custom scrollbar */
  scrollbar-width: thin;
  scrollbar-color: #424242 #1e1e1e;
}
.vb-codeed-area:focus { outline: none; }
.vb-codeed-area::selection { background: rgba(255,138,34,.3); }

/* WebKit/Blink custom scrollbars for the code editor — VS Code style */
.vb-codeed-area::-webkit-scrollbar         { width: 12px; height: 12px; }
.vb-codeed-area::-webkit-scrollbar-track   { background: #1e1e1e; }
.vb-codeed-area::-webkit-scrollbar-thumb   { background: #3e3e42; border: 3px solid #1e1e1e; border-radius: 8px; }
.vb-codeed-area::-webkit-scrollbar-thumb:hover  { background: #5a5a5e; }
.vb-codeed-area::-webkit-scrollbar-corner  { background: #1e1e1e; }
/* The gutter never scrolls horizontally, just kill its scrollbar entirely */
.vb-codeed-gutter::-webkit-scrollbar { display: none; }
.vb-codeed-gutter { scrollbar-width: none; }

/* ─── Color picker (DEVCON_COLOR_PICKER_v2) ────────────────────────────────
   Same compact-button language as the emoji picker. The popup holds an HSV
   square + hue slider + hex input + recent/preset chips. Three colors only:
   white, dim-white, orange.                                                */
.vb-color-btn {
  position: relative;
  width: 48px;
  height: 48px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: rgba(255,255,255,.02);
  border: 1px solid var(--border, #1a1a1e);
  border-radius: 8px;
  cursor: pointer;
  padding: 0;
  transition: border-color .15s ease, background .15s ease;
}
.vb-color-btn:hover { background: rgba(255,255,255,.035); border-color: rgba(255,255,255,.14); }
.vb-picker-color.is-open .vb-color-btn,
.vb-color-btn:focus-visible {
  outline: none;
  border-color: var(--orange);
  background: rgba(255,255,255,.035);
}
.vb-color-swatch {
  display: inline-block;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 1px solid rgba(255,255,255,.14);
  box-shadow: 0 1px 3px rgba(0,0,0,.3) inset;
  flex: 0 0 auto;
}

/* Popup. Overrides .vb-picker-dropdown's default width via the modifier. */
.vb-picker-color-dd {
  width: 260px !important;
  padding: 10px !important;
  gap: 10px !important;
}

/* 2D Saturation × Value square. JS builds the full background as ONE
   stack on this element: black→transparent-black (value),
   white→transparent-white (saturation), pure-hue base. Keeping it on a
   single element + using explicit zero-alpha colors prevents both the
   subpixel border-radius leak and the "transparent-black" gradient bug. */
.vb-color-sv {
  position: relative;
  width: 100%;
  height: 140px;
  border-radius: 8px;
  cursor: crosshair;
  touch-action: none;
  user-select: none;
  /* JS sets `background:` per current hue. Initial paint avoids a flash. */
  background:
    linear-gradient(to top,   #000, rgba(0,0,0,0)),
    linear-gradient(to right, #fff, rgba(255,255,255,0)),
    #f00;
}
.vb-color-sv-handle {
  position: absolute;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 2px solid #fff;
  box-shadow: 0 0 0 1px rgba(0,0,0,.6), 0 1px 4px rgba(0,0,0,.45);
  transform: translate(-50%, -50%);
  pointer-events: none;
  background: transparent;
}

/* Hue slider — horizontal rainbow strip with a circular handle. */
.vb-color-hue {
  position: relative;
  width: 100%;
  height: 14px;
  border-radius: 999px;
  cursor: ew-resize;
  background: linear-gradient(to right,
    #f00 0%, #ff0 16.6%, #0f0 33.3%, #0ff 50%, #00f 66.6%, #f0f 83.3%, #f00 100%);
  touch-action: none;
  user-select: none;
}
.vb-color-hue-handle {
  position: absolute;
  top: 50%;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  border: 2px solid #fff;
  box-shadow: 0 0 0 1px rgba(0,0,0,.55);
  transform: translate(-50%, -50%);
  pointer-events: none;
  background: #f00;
}

/* Format row — toggle (HEX/RGB/HSL) + dynamic inputs to its right. */
.vb-color-formatrow {
  display: flex;
  align-items: stretch;
  gap: 4px;
}
.vb-color-format-toggle {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0 10px;
  background: rgba(255,255,255,.02);
  border: 1px solid var(--border, #1a1a1e);
  border-radius: 6px;
  color: var(--text-dim, var(--text-muted));
  font-family: var(--font-mono, 'Geist Mono', ui-monospace, monospace);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .08em;
  cursor: pointer;
  transition: background .12s ease, color .12s ease, border-color .12s ease;
  user-select: none;
}
.vb-color-format-toggle:hover { background: rgba(255,138,34,.08); color: var(--orange); border-color: rgba(255,138,34,.3); }
.vb-color-format-toggle:focus-visible { outline: none; border-color: var(--orange); }
.vb-color-format-inputs {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  gap: 4px;
  background: rgba(255,255,255,.02);
  border: 1px solid var(--border, #1a1a1e);
  border-radius: 6px;
  padding: 0 10px;
  transition: border-color .12s ease;
  min-width: 0;
}
.vb-color-format-inputs:focus-within { border-color: var(--orange); }
.vb-color-hex-prefix {
  color: var(--text-dim, var(--text-muted));
  font-family: var(--font-mono, 'Geist Mono', ui-monospace, monospace);
  font-size: 13px;
  flex: 0 0 auto;
}
.vb-color-hex,
.vb-color-num {
  flex: 1 1 auto;
  background: transparent;
  border: 0;
  color: var(--text, var(--text-bright));
  padding: 8px 0;
  font-family: var(--font-mono, 'Geist Mono', ui-monospace, monospace);
  font-size: 13px;
  letter-spacing: .04em;
  outline: none;
  min-width: 0;
  width: 100%;
}
.vb-color-hex { text-transform: uppercase; }
.vb-color-num {
  text-align: center;
  -moz-appearance: textfield;
  appearance: textfield;
}
.vb-color-num::-webkit-outer-spin-button,
.vb-color-num::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

.vb-color-section { display: flex; flex-direction: column; gap: 6px; }
.vb-color-section-title {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--text-dim, var(--text-muted));
  font-weight: 600;
}
.vb-color-swatches {
  display: grid;
  grid-template-columns: repeat(9, 1fr);
  gap: 4px;
}
.vb-color-chip {
  aspect-ratio: 1 / 1;
  border: 1px solid rgba(255,255,255,.1);
  border-radius: 50%;
  cursor: pointer;
  padding: 0;
  transition: transform .12s ease, border-color .12s ease;
}
.vb-color-chip:hover { transform: scale(1.15); border-color: rgba(255,255,255,.35); }
.vb-color-chip:focus-visible { outline: none; border-color: var(--orange); transform: scale(1.15); }

/* ─── Channel/Role pickers (DEVCON_PICKER_MEE6_v2) ─────────────────────────
   Trigger matches dash-modal-input exactly: same subtle background, same
   border, same focus treatment. Two-line layout (name + dim mono ID) inside
   the same shell. Only three colors in play: white text, dimmed-white,
   orange accent. No bespoke grey tones.                                    */
.vb-picker { position: relative; }
.vb-picker-trigger {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  /* same as .dash-modal-input */
  background: rgba(255,255,255,.02);
  border: 1px solid var(--border, #1a1a1e);
  border-radius: 8px;
  padding: 10px 14px;
  min-height: 48px;
  color: var(--text, var(--text-bright));
  font-size: 14px;
  font-family: inherit;
  cursor: pointer;
  text-align: left;
  transition: border-color .15s ease, background .15s ease;
}
.vb-picker-trigger:hover { background: rgba(255,255,255,.035); border-color: rgba(255,255,255,.14); }
.vb-picker.is-open .vb-picker-trigger,
.vb-picker-trigger:focus-visible {
  outline: none;
  border-color: var(--orange);
  background: rgba(255,255,255,.035);
}
.vb-picker-trigger.is-empty .vb-picker-current { color: var(--text-dim, var(--text-muted)); font-weight: 400; }
.vb-picker-trigger.is-empty .vb-picker-id     { display: none; }
.vb-picker-current-wrap {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1px;
  min-width: 0;
  flex: 1 1 auto;
}
.vb-picker-current-row {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  max-width: 100%;
}
.vb-picker-current { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 500; }
.vb-picker-id {
  font-family: var(--font-mono, 'Geist Mono', ui-monospace, monospace);
  font-size: 11px;
  color: var(--text-dim, var(--text-muted));
  letter-spacing: .02em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
  opacity: .65;
}

/* Chevron (SVG, currentColor). Bigger, clearer, animates on open. */
.vb-picker-chevron {
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
  color: var(--text-dim, var(--text-muted));
  transition: transform .15s ease, color .15s ease;
}
.vb-picker:hover .vb-picker-chevron { color: var(--text, var(--text-bright)); }
.vb-picker.is-open .vb-picker-chevron { color: var(--orange); transform: rotate(180deg); }

/* Dropdown — uses --bg-card so it floats over content as the exact same
   surface tone the panel itself is rendered on. */
.vb-picker-dropdown {
  position: fixed;
  z-index: 9999;
  max-height: 360px;
  background: var(--bg-card, #0e0e10);
  border: 1px solid var(--border, #1a1a1e);
  border-radius: 8px;
  box-shadow: 0 16px 40px rgba(0,0,0,.55);
  padding: 8px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  width: 280px;
  animation: vbPickerDropIn .12s ease-out;
}
@keyframes vbPickerDropIn {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: translateY(0); }
}
.vb-picker-dropdown[hidden] { display: none; }
.vb-picker-portal { /* marker class for the body-attached dropdowns */ }

.vb-picker-search {
  background: rgba(255,255,255,.02);
  border: 1px solid var(--border, #1a1a1e);
  border-radius: 6px;
  padding: 8px 12px;
  font-size: 13px;
  font-family: inherit;
  color: var(--text, var(--text-bright));
  width: 100%;
  box-sizing: border-box;
  transition: border-color .12s ease;
}
.vb-picker-search::placeholder { color: var(--text-dim, var(--text-muted)); }
.vb-picker-search:focus { outline: none; border-color: var(--orange); }

.vb-picker-list {
  overflow-y: auto;
  max-height: 260px;
  display: flex;
  flex-direction: column;
  gap: 1px;
  scrollbar-width: thin;
  scrollbar-color: rgba(255,255,255,.12) transparent;
}
.vb-picker-list::-webkit-scrollbar { width: 6px; }
.vb-picker-list::-webkit-scrollbar-track { background: transparent; }
.vb-picker-list::-webkit-scrollbar-thumb { background: rgba(255,255,255,.12); border-radius: 3px; }
.vb-picker-list::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,.22); }

.vb-picker-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  background: transparent;
  border: 0;
  color: var(--text, var(--text-bright));
  border-radius: 6px;
  font-family: inherit;
  font-size: 13px;
  cursor: pointer;
  text-align: left;
  width: 100%;
  box-sizing: border-box;
  transition: background .1s ease;
}
.vb-picker-item:hover,
.vb-picker-item:focus-visible { background: rgba(255,138,34,.1); outline: none; }
.vb-picker-item-text {
  display: flex;
  flex-direction: column;
  gap: 0;
  min-width: 0;
  flex: 1 1 auto;
}
.vb-picker-glyph {
  color: var(--text-dim, var(--text-muted));
  font-weight: 500;
  flex: 0 0 auto;
  width: 16px;
  text-align: center;
  font-size: 14px;
}
.vb-picker-dot {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  flex: 0 0 auto;
}
.vb-picker-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 500; }
.vb-picker-sub {
  font-family: var(--font-mono, 'Geist Mono', ui-monospace, monospace);
  font-size: 11px;
  color: var(--text-dim, var(--text-muted));
  letter-spacing: .02em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  opacity: .6;
}
.vb-picker-empty {
  color: var(--text-dim, var(--text-muted));
  padding: 16px 12px;
  text-align: center;
  font-size: 12.5px;
}
/* Multi-picker chip wrapper — same input shell, chips inside. */
.vb-picker-multi .vb-chip-list {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 8px 10px;
  background: rgba(255,255,255,.02);
  border: 1px solid var(--border, #1a1a1e);
  border-radius: 8px;
  min-height: 48px;
  align-items: center;
  transition: border-color .15s ease, background .15s ease;
}
.vb-picker-multi:hover .vb-chip-list { background: rgba(255,255,255,.035); border-color: rgba(255,255,255,.14); }
.vb-picker-multi.is-open .vb-chip-list {
  border-color: var(--orange);
  background: rgba(255,255,255,.035);
}
.vb-chip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 4px 4px 4px 10px;
  background: rgba(255,255,255,.04);
  border: 1px solid rgba(255,255,255,.08);
  border-radius: 999px;
  font-size: 12.5px;
  color: var(--text, var(--text-bright));
  transition: background .12s ease, border-color .12s ease;
}
.vb-chip:hover { background: rgba(255,138,34,.08); border-color: rgba(255,138,34,.3); }
/* Role chips render a two-line label: name on top, role-ID directly
   below in monospace grey. Chip stays inline-flex so the dot + remove
   button still flank the text block. */
.vb-chip--role { padding: 5px 5px 5px 10px; }
.vb-chip--role .vb-chip-text {
  display: inline-flex;
  flex-direction: column;
  line-height: 1.15;
  gap: 1px;
}
.vb-chip--role .vb-chip-name { font-size: 12.5px; }
.vb-chip--role .vb-chip-rid {
  font-family: ui-monospace, monospace;
  font-size: 10px;
  color: var(--text-dim);
  letter-spacing: -0.01em;
}
/* Naked × — no bg / border / circle. Hover = red + 90° rotate. Matches
   the global close-x convention used throughout the dashboard. */
.vb-chip-rm {
  background: transparent;
  border: 0;
  border-radius: 0;
  color: var(--text-dim, var(--text-muted));
  cursor: pointer;
  width: 18px;
  height: 18px;
  line-height: 1;
  font-size: 16px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: color .15s ease, transform .15s ease;
}
.vb-chip-rm:hover {
  background: transparent;
  color: #ed4245;
  transform: rotate(90deg);
}
.vb-chip-add {
  background: transparent;
  border: 1px dashed rgba(255,138,34,.4);
  color: var(--orange);
  border-radius: 999px;
  padding: 5px 12px;
  font-size: 12px;
  font-weight: 500;
  cursor: pointer;
  font-family: inherit;
  transition: background .12s ease, border-style .12s ease;
}
.vb-chip-add:hover { background: rgba(255,138,34,.1); border-style: solid; }
.vb-picker-multi.is-open .vb-chip-add { background: rgba(255,138,34,.1); border-style: solid; }

/* ─── Emoji picker (DEVCON_EMOJI_PICKER_v1) ────────────────────────────────
   Compact "+" button that becomes the chosen emoji once set. Same three-
   color palette: white, dim-white, orange. Dropdown uses --bg-card to
   match the panel surface like the channel/role picker does.              */
.vb-emoji-picker { position: relative; display: inline-block; }
.vb-emoji-btn {
  position: relative;
  width: 48px;
  height: 48px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: rgba(255,255,255,.02);
  border: 1px solid var(--border, #1a1a1e);
  border-radius: 8px;
  cursor: pointer;
  color: var(--text-dim, var(--text-muted));
  font-family: inherit;
  padding: 0;
  transition: border-color .15s ease, background .15s ease, color .15s ease;
}
.vb-emoji-btn:hover { background: rgba(255,255,255,.035); border-color: rgba(255,255,255,.14); color: var(--text, var(--text-bright)); }
.vb-emoji-picker.is-open .vb-emoji-btn,
.vb-emoji-btn:focus-visible {
  outline: none;
  border-color: var(--orange);
  background: rgba(255,255,255,.035);
}
.vb-emoji-btn.is-empty .vb-emoji-icon::before {
  content: '+';
  font-size: 22px;
  font-weight: 300;
  line-height: 1;
  color: var(--text-dim, var(--text-muted));
}
.vb-emoji-btn:hover.is-empty .vb-emoji-icon::before { color: var(--orange); }
.vb-emoji-btn.is-set .vb-emoji-icon { font-size: 22px; line-height: 1; }
.vb-emoji-icon { display: inline-flex; align-items: center; justify-content: center; }
.vb-emoji-icon .vb-emoji-img {
  width: 28px;
  height: 28px;
  object-fit: contain;
  display: block;
}

/* Tiny × at top-right of a filled emoji button. Shown on hover/focus.
   Canonical naked-× Style ([[close-x-style]]): kein Background, keine
   Border, kein Kreis. Hover = rot + 90° Rotation, nichts anderes. */
.vb-emoji-clear {
  position: absolute;
  top: -8px;
  right: -6px;
  width: auto;
  height: auto;
  background: transparent;
  border: 0;
  border-radius: 0;
  color: var(--text-muted);
  font-size: 18px;
  line-height: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  opacity: 0;
  transition: opacity .12s ease, color .15s ease, transform .15s ease;
}
.vb-emoji-btn:hover .vb-emoji-clear,
.vb-emoji-btn:focus-visible .vb-emoji-clear,
.vb-emoji-clear:hover { opacity: 1; }
.vb-emoji-clear:hover {
  background: transparent;
  border: 0;
  color: #ed4245;
  transform: rotate(90deg);
}

/* Dropdown — same surface tone as the channel/role picker. */
.vb-emoji-dropdown {
  position: fixed;
  z-index: 9999;
  width: 320px;
  background: var(--bg-card, #0e0e10);
  border: 1px solid var(--border, #1a1a1e);
  border-radius: 8px;
  box-shadow: 0 16px 40px rgba(0,0,0,.55);
  padding: 8px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  animation: vbPickerDropIn .12s ease-out;
}
.vb-emoji-dropdown[hidden] { display: none; }
.vb-emoji-portal { /* marker class for body-attached emoji dropdowns */ }
.vb-emoji-search {
  background: rgba(255,255,255,.02);
  border: 1px solid var(--border, #1a1a1e);
  border-radius: 6px;
  padding: 8px 12px;
  font-size: 13px;
  font-family: inherit;
  color: var(--text, var(--text-bright));
  width: 100%;
  box-sizing: border-box;
  transition: border-color .12s ease;
}
.vb-emoji-search::placeholder { color: var(--text-dim, var(--text-muted)); }
.vb-emoji-search:focus { outline: none; border-color: var(--orange); }
.vb-emoji-tabs {
  display: flex;
  align-items: center;
  gap: 2px;
  padding-bottom: 6px;
  border-bottom: 1px solid rgba(255,255,255,.06);
  overflow-x: auto;
  flex: 0 0 auto;
  scrollbar-width: none;
}
.vb-emoji-tabs::-webkit-scrollbar { display: none; }
.vb-emoji-tab {
  flex: 0 0 auto;
  width: 32px;
  height: 32px;
  background: transparent;
  border: 0;
  border-radius: 6px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--text-dim, var(--text-muted));
  opacity: .65;
  transition: opacity .12s ease, background .12s ease, color .12s ease;
  font-family: inherit;
  padding: 0;
}
.vb-emoji-tab svg { width: 16px; height: 16px; display: block; }
.vb-emoji-tab:hover { opacity: 1; background: rgba(255,255,255,.04); color: var(--text, var(--text-bright)); }
.vb-emoji-tab.is-active {
  opacity: 1;
  background: rgba(255,138,34,.12);
  color: var(--orange);
}
.vb-emoji-grid {
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  gap: 2px;
  max-height: 240px;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: rgba(255,255,255,.12) transparent;
}
.vb-emoji-grid::-webkit-scrollbar { width: 6px; }
.vb-emoji-grid::-webkit-scrollbar-track { background: transparent; }
.vb-emoji-grid::-webkit-scrollbar-thumb { background: rgba(255,255,255,.12); border-radius: 3px; }
.vb-emoji-grid::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,.22); }
.vb-emoji-cell {
  background: transparent;
  border: 0;
  border-radius: 6px;
  width: 100%;
  aspect-ratio: 1 / 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
  font-family: inherit;
  transition: background .1s ease;
  padding: 0;
  color: var(--text, var(--text-bright));
}
.vb-emoji-cell:hover,
.vb-emoji-cell:focus-visible { background: rgba(255,138,34,.12); outline: none; }
.vb-emoji-cell--img img {
  width: 22px;
  height: 22px;
  object-fit: contain;
  display: block;
}
.vb-emoji-empty {
  grid-column: 1 / -1;
  color: var(--text-dim, var(--text-muted));
  font-size: 12.5px;
  text-align: center;
  padding: 24px 12px;
}

/* Messages sub-tab: each reply pairs a textarea with its own ephemeral switch */
.vb-msg-row {
  padding: 12px 14px;
  background: rgba(255,255,255,.02);
  border: 1px solid rgba(255,255,255,.06);
  border-radius: 10px;
  margin-bottom: 12px;
}
.vb-msg-row .dash-modal-label { margin-bottom: 6px; }
.vb-msg-row .dash-modal-input { margin-bottom: 8px; }
.vb-msg-row .vb-msg-eph { margin-top: 4px; }
.vb-msg-row .vb-msg-eph .vb-switch-label { font-size: 12px; color: var(--text-dim); }

/* Render-mode segmented control at the top of embed-dependent sub-tabs */
.vb-mode-section { padding: 14px 16px; background: rgba(0,0,0,.18); border: 1px solid rgba(255,255,255,.06); border-radius: 12px; }
.vb-mode-section h3 { margin: 0 0 4px; font-size: 13px; font-weight: 600; color: var(--text-bright); }
.vb-mode-section .vb-section-desc { margin: 0 0 12px; font-size: 12px; }
.vb-mode-switch {
  display: inline-flex;
  background: rgba(0,0,0,.35);
  border: 1px solid rgba(255,255,255,.08);
  border-radius: 10px;
  padding: 3px;
  gap: 2px;
}
.vb-mode-opt {
  position: relative;
  cursor: pointer;
  user-select: none;
}
.vb-mode-opt input { position: absolute; opacity: 0; pointer-events: none; }
.vb-mode-opt span {
  display: inline-block;
  padding: 7px 14px;
  font-size: 13px;
  font-weight: 500;
  color: var(--text-dim);
  border-radius: 8px;
  transition: background .12s, color .12s;
}
.vb-mode-opt:hover span { color: var(--text-bright); }
.vb-mode-opt.is-active span {
  background: rgba(255,138,34,.18);
  color: var(--orange);
}

/* Sub-section headings inside a sub-tab (smaller than vb-section h2) */
.vb-subsection-head { margin: 0 0 14px; }
.vb-subsection-head h3 {
  font-size: 14px;
  font-weight: 600;
  margin: 0 0 4px;
  letter-spacing: -.005em;
  color: var(--text-bright);
  text-transform: uppercase;
  letter-spacing: .04em;
  font-size: 12px;
  opacity: .85;
}
.vb-subsection-head .vb-section-desc { margin-bottom: 0; font-size: 12px; }

/* Branding-locked field treatment */
.vb-brand-badge {
  display: inline-block;
  margin-left: 6px;
  font-size: 11px;
  opacity: .9;
  cursor: help;
}
.vb-branding.vb-locked .dash-modal-input,
.vb-branding.vb-locked input[type=color],
.vb-branding.vb-locked .vb-switch input {
  opacity: .5;
  cursor: not-allowed;
}
.vb-branding.vb-locked .dash-modal-label,
.vb-branding.vb-locked .vb-switch-label {
  color: var(--text-dim);
}
.vb-branding.vb-locked .vb-switch { cursor: not-allowed; }

/* ─── Form rows (reuse dash-modal-input / -label / -help under the hood) ──── */
.vb-field { margin-bottom: 16px; }
.vb-field .dash-modal-input { margin-bottom: 0; }
.vb-field .dash-modal-help  { margin-top: 6px; margin-bottom: 0; }
.vb-row { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
@media (max-width: 640px) { .vb-row { grid-template-columns: 1fr; } }

/* Color pickers (color input + hex twin) */
.vb-color { display: inline-flex; align-items: center; gap: 8px; width: 100%; }
.vb-color input[type=color] {
  flex: 0 0 auto;
  width: 42px; height: 38px;
  padding: 0;
  border: 1px solid rgba(255,255,255,.1);
  border-radius: 8px;
  background: var(--bg-card);
  cursor: pointer;
}

/* Toggle switch (re-uses dc-switch from dashboard.css if you want; here is a
   bot-page variant that matches its size + uses --orange) */
.vb-switch { display: inline-flex; align-items: center; gap: 12px; cursor: pointer; user-select: none; }
.vb-switch input { display: none; }
/* DEVCON_TOGGLE_GREEN_RED_v1 — every toggle in the bot dashboard reads
   red when off, green when on. White thumb shifts on toggle. */
.vb-switch-slider {
  width: 36px; height: 20px;
  background: rgba(237,66,69,0.55);        /* off → red */
  border-radius: 999px;
  position: relative;
  transition: background .15s;
  flex: 0 0 auto;
}
.vb-switch-slider::after {
  content: ""; position: absolute;
  top: 2px; left: 2px;
  width: 16px; height: 16px;
  border-radius: 50%;
  background: #fff;
  transition: left .15s;
}
.vb-switch input:checked + .vb-switch-slider { background: rgba(67,181,129,0.85); }   /* on → green */
.vb-switch input:checked + .vb-switch-slider::after { left: 18px; }
.vb-switch-label {
  font-size: 13px;
  color: var(--text-bright);
}

/* Actions row at bottom of each tab — no top divider, button just floats
   below the last section with breathing room. */
.vb-actions {
  margin-top: 24px;
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}

/* ─── MEE6-style row builder (DEVCON_MEE6_ROW_v1) ───────────────────────
   Generic flat-row pattern used for repeating list items (embed fields,
   embed buttons, automation rules, etc.). Left rail is a vertical stack
   of icon-only action buttons (delete + move up + move down). Content
   sits to the right and breathes naturally.                              */
.vb-mee6-row {
  display: flex;
  align-items: stretch;
  gap: 12px;
  padding: 14px;
  background: rgba(255,255,255,.02);
  border: 1px solid var(--border, #1a1a1e);
  border-radius: 10px;
  margin-top: 10px;
  transition: border-color .15s ease, background .15s ease;
}
.vb-mee6-row:hover { border-color: rgba(255,255,255,.12); background: rgba(255,255,255,.03); }
.vb-mee6-row__rail {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}
.vb-mee6-row__rail .vb-row-icon-btn { width: 26px; height: 26px; }
.vb-mee6-row__rail .vb-row-icon-btn svg { width: 13px; height: 13px; }
.vb-mee6-row__rail .vb-row-icon-btn:disabled,
.vb-mee6-row__rail .vb-row-icon-btn[disabled] {
  opacity: .3;
  cursor: not-allowed;
  pointer-events: none;
}
.vb-mee6-row__body {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.vb-mee6-row__body .dash-modal-label { margin: 0 0 4px; font-size: 11px; }
.vb-mee6-row__body .dash-modal-input { margin: 0; }
.vb-mee6-row__body .vb-ec-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }

/* "+ Add X" pill — wide subtle grey button with + icon. */
.vb-mee6-add {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 16px;
  background: rgba(255,255,255,.04);
  border: 1px solid rgba(255,255,255,.08);
  border-radius: 8px;
  color: var(--text, var(--text-bright));
  font-family: inherit;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  margin-top: 10px;
  transition: background .15s ease, border-color .15s ease, color .15s ease;
}
.vb-mee6-add:hover {
  background: rgba(255,138,34,.08);
  border-color: rgba(255,138,34,.3);
  color: var(--orange);
}
.vb-mee6-add::before {
  content: '+';
  font-size: 16px;
  font-weight: 400;
  line-height: 1;
  display: inline-block;
  width: 14px;
  text-align: center;
}

/* Dashed empty-state when a repeating list has zero items. */
.vb-mee6-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 28px 16px;
  border: 1px dashed rgba(255,255,255,.12);
  border-radius: 10px;
  color: var(--text-dim, var(--text-muted));
  font-size: 13px;
  text-align: center;
  margin-top: 10px;
}

/* ─── Embed editor: two-column layout + Discord live preview ───────────────
   Left column: the form (everything that mutates the draft).
   Right column: a sticky pane that mirrors what the embed will look like
   when actually posted to Discord. The preview is a faithful copy of
   Discord's dark-theme message rendering — colour bar, author row,
   title, description (markdown), inline fields, image, thumbnail,
   footer, components (buttons). Stacks to one column < 980px wide.       */
.vb-ec-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 460px;
  gap: 28px;
  align-items: start;
}
@media (max-width: 980px) {
  .vb-ec-layout { grid-template-columns: 1fr; }
}
.vb-ec-form { min-width: 0; }
.vb-ec-preview-wrap {
  position: sticky;
  top: 24px;
  align-self: start;
  min-width: 0;
}
@media (max-width: 980px) {
  .vb-ec-preview-wrap { position: static; }
}
.vb-ec-preview-label {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: .12em;
  font-weight: 600;
  color: var(--text-dim, var(--text-muted));
  margin-bottom: 10px;
}

/* Discord-faithful preview surface. Hex values are intentionally
   hard-coded to match Discord's dark theme exactly — they don't follow
   the dashboard's --bg-card etc. because the goal is "looks like
   Discord", not "looks like the dashboard". */
.vb-ec-discord-msg {
  background: #313338;
  color: #dbdee1;
  padding: 16px 16px 14px;
  border-radius: 10px;
  font-family: 'gg sans', 'Noto Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: 14px;
  line-height: 1.4;
  word-wrap: break-word;
  overflow-wrap: anywhere;
}
.vb-ec-discord-empty {
  color: #80848e;
  font-style: italic;
  text-align: center;
  padding: 30px 8px;
  font-size: 13px;
}

/* Message content (above the embed). */
.vb-ec-discord-content {
  margin-bottom: 8px;
  white-space: pre-wrap;
  color: #dbdee1;
}

/* The actual embed card. CSS grid lays out: title/desc/fields on the
   left, thumbnail spanning multiple rows on the right. Image goes full
   width at the bottom, footer below that. */
.vb-ec-discord-embed {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 8px 16px;
  align-items: start;
  background: #2b2d31;
  border-left: 4px solid var(--embed-color, #5865F2);
  border-radius: 4px;
  padding: 8px 16px 16px 12px;
  max-width: 416px;
}
.vb-ec-discord-embed-author {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  font-weight: 600;
  color: #fff;
  margin-top: 8px;
}
.vb-ec-discord-embed-author-icon {
  width: 24px; height: 24px;
  border-radius: 50%;
  object-fit: cover;
}
.vb-ec-discord-embed-author-link {
  color: inherit;
  text-decoration: none;
}
.vb-ec-discord-embed-author-link:hover { text-decoration: underline; }
.vb-ec-discord-embed-title {
  grid-column: 1 / 2;
  font-size: 16px;
  font-weight: 600;
  color: #fff;
  margin-top: 8px;
}
.vb-ec-discord-embed-desc {
  grid-column: 1 / 2;
  font-size: 14px;
  color: #dbdee1;
  white-space: pre-wrap;
  margin-top: 8px;
}
/* Thumbnail: spans starting at row 2 (below author) and occupies the
   right column. 80×80 max, rounded. */
.vb-ec-discord-embed-thumb {
  grid-column: 2 / 3;
  grid-row: 1 / span 5;
  width: 80px;
  height: 80px;
  object-fit: cover;
  border-radius: 4px;
  justify-self: end;
  margin-top: 8px;
}
.vb-ec-discord-embed-fields {
  grid-column: 1 / 2;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
  margin-top: 8px;
}
.vb-ec-discord-embed-field {
  grid-column: span 3;
  min-width: 0;
}
.vb-ec-discord-embed-field.is-inline { grid-column: span 1; }
.vb-ec-discord-embed-field-name {
  font-size: 14px;
  font-weight: 600;
  color: #fff;
  margin-bottom: 2px;
}
.vb-ec-discord-embed-field-value {
  font-size: 14px;
  color: #dbdee1;
  white-space: pre-wrap;
}
.vb-ec-discord-embed-image {
  grid-column: 1 / -1;
  max-width: 100%;
  border-radius: 4px;
  margin-top: 8px;
  display: block;
}
.vb-ec-discord-embed-footer {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  color: #949ba4;
  margin-top: 8px;
}
.vb-ec-discord-embed-footer-icon {
  width: 20px; height: 20px;
  border-radius: 50%;
  object-fit: cover;
}

/* Component buttons below the embed. */
.vb-ec-discord-btns {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 8px;
  max-width: 432px;
}
.vb-ec-discord-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 14px;
  height: 32px;
  border: 0;
  border-radius: 3px;
  font-family: inherit;
  font-size: 14px;
  font-weight: 500;
  color: #fff;
  cursor: default; /* preview-only */
  transition: background .1s ease;
}
.vb-ec-discord-btn-emoji { display: inline-flex; font-size: 16px; line-height: 1; }
.vb-ec-discord-btn-emoji img { width: 18px; height: 18px; display: block; }
.vb-ec-discord-btn-linkicon { width: 12px; height: 12px; opacity: .85; }
.vb-ec-discord-btn--primary   { background: #5865f2; }
.vb-ec-discord-btn--primary:hover   { background: #4752c4; }
.vb-ec-discord-btn--secondary { background: #4e5058; }
.vb-ec-discord-btn--secondary:hover { background: #6d6f78; }
.vb-ec-discord-btn--success   { background: #248046; }
.vb-ec-discord-btn--success:hover   { background: #1a6334; }
.vb-ec-discord-btn--danger    { background: #da373c; }
.vb-ec-discord-btn--danger:hover    { background: #a12d2f; }
.vb-ec-discord-btn--link      { background: #4e5058; }
.vb-ec-discord-btn--link:hover { background: #6d6f78; }

/* Markdown inside preview text. */
.vb-ec-md-pre {
  background: #1e1f22;
  border-radius: 4px;
  padding: 8px 10px;
  margin: 6px 0;
  font-family: 'Consolas', 'Menlo', monospace;
  font-size: 13px;
  overflow-x: auto;
  white-space: pre;
  color: #dbdee1;
}
.vb-ec-md-code {
  background: #1e1f22;
  border-radius: 3px;
  padding: 1px 4px;
  font-family: 'Consolas', 'Menlo', monospace;
  font-size: 13px;
}
.vb-ec-md-link  { color: #00a8fc; text-decoration: none; }
.vb-ec-md-link:hover { text-decoration: underline; }
.vb-ec-md-h1 { font-size: 24px; font-weight: 700; color: #fff; margin: 6px 0 2px; }
.vb-ec-md-h2 { font-size: 20px; font-weight: 700; color: #fff; margin: 6px 0 2px; }
.vb-ec-md-h3 { font-size: 16px; font-weight: 700; color: #fff; margin: 6px 0 2px; }
.vb-ec-md-quote {
  border-left: 4px solid #4e5058;
  padding-left: 10px;
  margin: 4px 0;
  color: #dbdee1;
}
.vb-ec-md-spoiler {
  background: #202225;
  color: #202225;
  border-radius: 3px;
  padding: 0 2px;
  cursor: pointer;
}
.vb-ec-md-spoiler:hover { color: #dbdee1; }

/* ============================================================
   Global Component System — single source of truth for buttons,
   selects, inputs across every module tab. Components use the
   `.dc-` prefix; legacy `.dash-btn-*` classes (from dashboard.css)
   are normalised below so existing markup picks up the modern
   styling without any markup churn.
   ============================================================ */

/* ── Buttons ─────────────────────────────────────────────────── */
.dc-btn,
.vb-panel .dash-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 9px 18px;
  border-radius: 10px;
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.005em;
  border: 1px solid transparent;
  background: transparent;
  color: var(--text);
  cursor: pointer;
  white-space: nowrap;
  user-select: none;
  text-decoration: none;
  transition: background .12s ease, border-color .12s ease, color .12s ease, transform .08s ease, box-shadow .12s ease;
  flex: 0 0 auto;            /* override .dash-btn { flex:1 } so action rows align right */
}
.dc-btn:active,
.vb-panel .dash-btn:active { transform: translateY(1px); }
.dc-btn:focus-visible,
.vb-panel .dash-btn:focus-visible { outline: 2px solid var(--orange); outline-offset: 2px; }
.dc-btn[disabled],
.vb-panel .dash-btn[disabled] { opacity: 0.5; cursor: not-allowed; }
.dc-btn svg,
.vb-panel .dash-btn svg { flex: 0 0 auto; }

/* Primary — filled orange, used for "Speichern", "Aktivieren". */
.dc-btn--primary,
.vb-panel .dash-btn-primary {
  background: var(--orange);
  color: #0a0a0a;
  border-color: var(--orange);
}
.dc-btn--primary:hover,
.vb-panel .dash-btn-primary:hover {
  background: #ffa338;
  border-color: #ffa338;
  box-shadow: 0 6px 18px -6px rgba(255, 130, 40, 0.5);
}

/* Secondary — neutral outline, used for "Abbrechen", side actions. */
.dc-btn--secondary,
.vb-panel .dash-btn-secondary {
  background: rgba(255, 255, 255, 0.04);
  color: var(--text);
  border-color: rgba(255, 255, 255, 0.10);
}
.dc-btn--secondary:hover,
.vb-panel .dash-btn-secondary:hover {
  background: rgba(255, 255, 255, 0.06);
  border-color: rgba(255, 255, 255, 0.20);
  color: var(--text);
}

/* Danger — destructive actions ("Löschen", "Deaktivieren"). */
.dc-btn--danger,
.vb-panel .dash-btn-danger {
  background: rgba(237, 66, 69, 0.10);
  color: #ff8e91;
  border-color: rgba(237, 66, 69, 0.40);
}
.dc-btn--danger:hover,
.vb-panel .dash-btn-danger:hover {
  background: rgba(237, 66, 69, 0.18);
  border-color: #ed4245;
  color: #ffc6c7;
}

/* Ghost — text-only, for inline actions inside cards. */
.dc-btn--ghost {
  background: transparent;
  color: var(--text-muted);
  border-color: transparent;
}
.dc-btn--ghost:hover {
  background: rgba(255, 255, 255, 0.06);
  color: var(--text);
}

/* "+ Neu" / "+ Add" — outlined orange-tinted variant that signals
   "open the creator form", separate from the filled primary "Save" CTA.
   Labels already include "+ ..." so no pseudo-element prefix needed. */
.dc-btn--add {
  background: rgba(255, 130, 40, 0.06);
  color: var(--orange);
  border: 1px dashed rgba(255, 130, 40, 0.40);
}
.dc-btn--add:hover {
  background: rgba(255, 130, 40, 0.14);
  border-color: var(--orange);
  border-style: solid;
}

/* Size modifiers */
.dc-btn--sm { padding: 6px 12px; font-size: 12px; border-radius: 8px; gap: 6px; }
.dc-btn--lg { padding: 12px 22px; font-size: 14px; border-radius: 12px; }

/* Icon-only square */
.dc-btn--icon { padding: 8px; width: 34px; height: 34px; }
.dc-btn--icon.dc-btn--sm { width: 28px; height: 28px; padding: 6px; }

/* ── Form Controls ───────────────────────────────────────────── */
/* Canonical input + select look. Legacy `.dash-modal-input` adopts
   the same chrome so existing forms inherit the upgrade. */
.dc-input,
.vb-panel .dash-modal-input,
.dash-modal-input,
.vb-panel input[type="text"]:not(.vb-tab-switch input):not(.vb-pers-title-input),
.vb-panel input[type="number"],
.vb-panel input[type="url"],
.vb-panel input[type="email"],
.vb-panel textarea,
.vb-panel select:not(.vb-tab-switch select),
.dash-modal-body input[type="text"],
.dash-modal-body input[type="number"],
.dash-modal-body textarea,
.dash-modal-body select {
  width: 100%;
  padding: 10px 14px;
  font: inherit;
  font-size: 14px;
  color: var(--text);
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 10px;
  outline: none;
  transition: border-color .12s ease, background .12s ease, box-shadow .12s ease;
  box-sizing: border-box;
}
.dc-input:focus,
.vb-panel .dash-modal-input:focus,
.dash-modal-input:focus,
.vb-panel input:not(.vb-tab-switch input):focus,
.vb-panel textarea:focus,
.vb-panel select:focus,
.dash-modal-body input:focus,
.dash-modal-body textarea:focus,
.dash-modal-body select:focus {
  border-color: var(--orange);
  background: rgba(255, 130, 40, 0.04);
  box-shadow: 0 0 0 3px rgba(255, 130, 40, 0.15);
}
.dc-input::placeholder,
.vb-panel input::placeholder,
.vb-panel textarea::placeholder { color: rgba(255, 255, 255, 0.30); }

/* ── Custom DevCon dropdown ─────────────────────────────────
   Replaces every native <select> in the bot panel. The native element
   stays in the DOM (hidden) so form values + existing change-handler
   wiring still works. JS lives in dashboard-bot.js (enhanceSelects). */
.dc-select-native {
  position: absolute !important;
  width: 1px !important;
  height: 1px !important;
  padding: 0 !important;
  margin: 0 !important;
  border: 0 !important;
  opacity: 0 !important;
  pointer-events: none !important;
  clip: rect(0,0,0,0);
  overflow: hidden;
}
.dc-select-wrap { position: relative; display: block; }

.dc-select-trigger {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 14px;
  font: inherit;
  font-size: 14px;
  color: var(--text);
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 10px;
  cursor: pointer;
  text-align: left;
  transition: border-color .12s, background .12s, box-shadow .12s;
}
.dc-select-trigger:hover { border-color: rgba(255, 255, 255, 0.20); }
.dc-select-trigger:focus-visible,
.dc-select-trigger[aria-expanded="true"] {
  outline: none;
  border-color: var(--orange);
  background: rgba(255, 130, 40, 0.04);
  box-shadow: 0 0 0 3px rgba(255, 130, 40, 0.15);
}
.dc-select-trigger[disabled] { opacity: 0.5; cursor: not-allowed; }
.dc-select-value {
  flex: 1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.dc-select-caret {
  flex: 0 0 auto;
  opacity: 0.55;
  transition: transform .15s, opacity .15s;
}
.dc-select-trigger[aria-expanded="true"] .dc-select-caret {
  transform: rotate(180deg);
  opacity: 1;
}

.dc-select-menu {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  z-index: 100;
  max-height: 280px;
  overflow-y: auto;
  background: var(--bg-card, #14161b);
  border: 1px solid rgba(255, 255, 255, 0.10);
  border-radius: 10px;
  box-shadow:
    0 18px 40px -16px rgba(0, 0, 0, 0.65),
    0 6px 14px -8px rgba(0, 0, 0, 0.4),
    inset 0 1px 0 rgba(255, 255, 255, 0.04);
  padding: 6px;
  display: none;
  animation: dcModalFade .12s ease-out;
}
.dc-select-menu.is-open { display: block; }
/* Custom scrollbar inside menu */
.dc-select-menu::-webkit-scrollbar { width: 8px; }
.dc-select-menu::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.10); border-radius: 4px; }
.dc-select-menu::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,0.18); }

.dc-select-option {
  padding: 9px 12px;
  font-size: 13.5px;
  color: var(--text);
  border-radius: 7px;
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: background .08s, color .08s;
}
.dc-select-option:hover { background: rgba(255, 255, 255, 0.06); }
.dc-select-option.is-selected {
  background: rgba(255, 130, 40, 0.12);
  color: var(--orange);
  font-weight: 600;
}
.dc-select-option.is-selected:hover { background: rgba(255, 130, 40, 0.18); }
.dc-select-option.is-disabled { opacity: 0.4; cursor: not-allowed; }
.dc-select-option.is-disabled:hover { background: transparent; }

/* "+ Neuer Embed" creator affordance — sticky at the top of every
   embed-picker dropdown so the customer can create-and-pick inline. */
.dc-select-option--create {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--orange);
  font-weight: 600;
}
.dc-select-option--create:hover { background: rgba(255, 130, 40, 0.10); color: var(--orange); }
.dc-select-option--create svg { flex: 0 0 auto; opacity: 0.85; }
.dc-select-sep {
  height: 1px;
  margin: 6px 4px;
  background: rgba(255, 255, 255, 0.06);
}

/* Labels + help text — force the modern sans look everywhere in the
   bot panel. dashboard.css's .dash-modal-label declares UPPERCASE + a
   mono font; both are explicitly reset here so labels read in clean
   sentence case across module pages AND modals. */
.dc-label,
.vb-panel .dash-modal-label,
.dash-modal-body .dash-modal-label {
  display: block;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.2px;
  text-transform: none;
  font-family: inherit;
  color: var(--text-muted);
  margin-bottom: 6px;
}

/* Page-wide normalisation — strip the legacy "uppercase + mono"
   decoration from every label-style element inside the bot dashboard.
   Affects field labels, section eyebrows, stat-tile labels, dropdown
   menus etc. so the whole panel reads in one clean sans-serif voice. */
.dashboard-content .dash-modal-label,
.dashboard-content .dashboard-greeting-eyebrow,
.dashboard-content .dashboard-stat-label,
.dashboard-content .vb-section-subhead,
.dashboard-content .vb-pers-eyebrow {
  font-family: inherit !important;
  text-transform: none !important;
  letter-spacing: 0.2px !important;
}
/* Inputs themselves — dashboard.css forces mono on .dash-modal-input
   and other field types; the bot panel always wants the body font. */
.vb-panel .dash-modal-input,
.dashboard-content .dash-modal-input,
.dash-modal-body .dash-modal-input,
.dash-modal-body input,
.dash-modal-body textarea,
.dash-modal-body select { font-family: inherit !important; }
.dc-help,
.vb-panel .dash-modal-help,
.dash-modal-body .dash-modal-help {
  font-size: 12px;
  color: var(--text-muted);
  margin-top: 6px;
  line-height: 1.5;
}

/* ── Layout helpers ──────────────────────────────────────────── */
/* Two-column form grid; collapses to one column under 720px. */
.dc-form-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
}
@media (max-width: 720px) {
  .dc-form-grid { grid-template-columns: 1fr; }
}

/* "+ Neu" row — full-width dashed button at the bottom of a list. */
.dc-add-row { margin-top: 14px; }
.dc-add-row .dc-btn--add { width: 100%; padding: 12px 18px; }

/* ── Section breathing — DEVCON_CARD_CONSISTENCY_v1.
   Every "card-style" container in the bot dashboard shares the same
   background + border + radius so adjacent sections, list-panels and
   new-card buttons read as the same visual family. Adjacency in any
   combination gets a uniform 18px gap. ── */
.vb-section,
.vb-ec-list-panel,
.vb-ec-new-card {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 12px;
}
.vb-section { padding: 22px 24px; }
/* Universal sibling-spacing — every card-container gets an 18px gap to ANY
   preceding sibling (not just other cards). Catches wrapper rows like the
   embed-creator's "Neue Embed-Nachricht + Import (JSON)" flex-row that sits
   between the hero and the list-panel. Never set margin-bottom on the cards
   themselves — push from the next sibling instead. */
* + .vb-section,
* + .vb-ec-list-panel,
* + .vb-ec-new-card { margin-top: 18px; }
.vb-section > h2 {
  margin: 0 0 6px;
  font-size: 16px;
  font-weight: 700;
  letter-spacing: -0.005em;
  color: var(--text);
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}
.vb-section > .vb-section-desc { margin: 0 0 14px; color: var(--text-muted); font-size: 13px; line-height: 1.55; }
.vb-section .vb-field + .vb-field { margin-top: 14px; }
.vb-section .vb-actions { margin-top: 22px; }

/* ── Modals ─────────────────────────────────────────────────── */
/* Canonical .dc-modal component + page-wide overrides for every legacy
   .dash-modal popup so all 18 existing popups (Neuer Hub, Neuer Command,
   Stats-Channel etc.) pick up the wider, breezier, modern look without
   markup churn. Modals are injected at document.body level, so the
   selectors are unscoped — safe because dashboard-bot.css only loads
   on /dashboard-bot. */
@keyframes dcModalIn {
  from { opacity: 0; transform: translateY(8px) scale(0.98); }
  to   { opacity: 1; transform: none; }
}
@keyframes dcModalFade {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.dc-modal-overlay,
.dash-modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: grid;
  place-items: center;
  padding: 24px;
  background: rgba(6, 7, 10, 0.72);
  backdrop-filter: blur(10px) saturate(140%);
  -webkit-backdrop-filter: blur(10px) saturate(140%);
  animation: dcModalFade .14s ease-out;
}

.dc-modal,
.dash-modal {
  width: 100%;
  max-width: 720px;
  max-height: calc(100vh - 48px);
  background: linear-gradient(180deg, rgba(255,255,255,0.025), rgba(255,255,255,0.005)), var(--bg-card, #14161b);
  border: 1px solid rgba(255, 255, 255, 0.10);
  border-radius: 16px;
  box-shadow:
    0 30px 80px -20px rgba(0, 0, 0, 0.6),
    0 8px 24px -12px rgba(0, 0, 0, 0.4),
    inset 0 1px 0 rgba(255, 255, 255, 0.04);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  animation: dcModalIn .18s cubic-bezier(.2, .8, .2, 1);
}

.dc-modal--sm,   .dash-modal--sm   { max-width: 460px; }
.dc-modal--wide, .dash-modal--wide { max-width: 860px; }
.dc-modal--full, .dash-modal--full { max-width: 1080px; }

.dc-modal-header,
.dash-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 20px 26px 14px;
  /* divider removed — title + body sit flush. Must be explicit because
     dashboard.css declares its own border-bottom on this selector. */
  border-bottom: 0 !important;
}
.dc-modal-header h3,
.dash-modal-header h3 {
  margin: 0;
  font-size: 18px;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--text);
}
/* Unified close-button look (DEVCON_GLOBAL_CLOSE_v1). No box — just the
   plain X icon. Hover: red + 90° rotation. Active: scale-down. */
.dc-modal-close,
.dash-modal-close,
.vb-vars-modal-close,
.vb-pers-modal-close {
  width: 32px;
  height: 32px;
  padding: 0;
  display: inline-grid;
  place-items: center;
  background: transparent;
  border: 0;
  color: var(--text-muted);
  font-size: 25px;         /* ~20% larger than vb217's 21px */
  line-height: 1;
  cursor: pointer;
  transition: color .15s, transform .25s;
}
.dc-modal-close:hover,
.dash-modal-close:hover,
.vb-vars-modal-close:hover,
.vb-pers-modal-close:hover {
  background: transparent;          /* explicit — overrides dashboard.css */
  border-color: transparent;
  color: #ed4245;
  transform: rotate(90deg);
}
.dc-modal-close:active,
.dash-modal-close:active,
.vb-vars-modal-close:active,
.vb-pers-modal-close:active { transform: rotate(90deg) scale(0.94); }

.dc-modal-body,
.dash-modal-body {
  padding: 22px 26px;
  overflow-y: auto;
  flex: 1 1 auto;
  min-height: 0;
  scrollbar-width: thin;
  scrollbar-color: rgba(255,255,255,.18) transparent;
}
.dc-modal-body::-webkit-scrollbar,
.dash-modal-body::-webkit-scrollbar { width: 8px; }
.dc-modal-body::-webkit-scrollbar-track,
.dash-modal-body::-webkit-scrollbar-track { background: transparent; }
.dc-modal-body::-webkit-scrollbar-thumb,
.dash-modal-body::-webkit-scrollbar-thumb {
  background: rgba(255,255,255,.14);
  border-radius: 4px;
  border: 2px solid transparent;
  background-clip: padding-box;
}
.dc-modal-body::-webkit-scrollbar-thumb:hover,
.dash-modal-body::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,.26); background-clip: padding-box; }

/* Required + optional markers on modal labels (used in ticket category modal,
   pattern is generic so other modals can adopt it) */
.dash-modal-label .vb-req       { color: var(--orange); margin-left: 2px; }
.dash-modal-label .vb-optional  { color: var(--text-dim, var(--text-muted)); font-weight: 400; margin-left: 4px; font-size: 11px; }
.dash-modal-body .dash-modal-input.is-invalid,
.dash-modal-body input.is-invalid,
.dash-modal-body textarea.is-invalid {
  border-color: rgba(237,66,69,.7) !important;
  box-shadow: 0 0 0 2px rgba(237,66,69,.18);
}
/* Modern label style — sentence case, sans. margin-bottom: 0 because the
   uniform gap to the field below is set by `.dash-modal-label + *` rule
   right after this block. Without that approach, block fields (select)
   collapse margins with the label but inline-flex fields (mode-pills,
   number-stepper) don't, producing visibly inconsistent gaps. */
.dash-modal-body .dash-modal-label,
.dc-modal-body .dc-label {
  text-transform: none;
  font-family: inherit;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.2px;
  color: var(--text-muted);
  margin-bottom: 0;
}
/* Uniform label-to-field gap, regardless of field type — 10px global
   standard for every popup. See [[modal-density]]. */
.dash-modal-body .dash-modal-label + *,
.dc-modal-body .dc-label + * {
  margin-top: 10px;
}
.dash-modal-body .dash-modal-input,
.dash-modal-body input,
.dash-modal-body textarea,
.dash-modal-body select { font-family: inherit; }

/* Field stacking — every immediate child gets a gap from its neighbour
   so no two fields ever touch. */
.dash-modal-body > * + *,
.dc-modal-body > * + * { margin-top: 14px; }
.dash-modal-body .dash-modal-help,
.dc-modal-body .dc-help { margin: 6px 0 0; }

/* Footer — soft divider, right-aligned action buttons. Both legacy
   class names are supported (.dash-modal-actions and .dash-modal-footer). */
.dc-modal-actions,
.dash-modal-actions,
.dash-modal-footer {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  padding: 16px 26px 22px;
}
/* The default .dash-btn from dashboard.css has `flex:1` which makes the
   two footer buttons stretch + bunch to the left. Reset them inside any
   modal footer so they sit naturally on the right. */
.dc-modal-actions .dc-btn,
.dc-modal-actions .dash-btn,
.dash-modal-actions .dash-btn,
.dash-modal-actions .dc-btn,
.dash-modal-footer .dash-btn,
.dash-modal-footer .dc-btn {
  flex: 0 0 auto;
  min-width: 100px;
}
/* DEVCON_GLOBAL_CANCEL_BTN_v1 — every plain .dash-btn / .dc-btn inside a
   modal footer or actions row gets a visible neutral border, so cancel-
   style buttons aren't borderless ghosts on the dark modal body. Excludes
   the primary + danger variants which already have their own fills. */
.dc-modal-actions .dash-btn:not(.dash-btn-primary):not(.dash-btn-danger),
.dc-modal-actions .dc-btn:not(.dc-btn-primary):not(.dash-btn-danger),
.dash-modal-actions .dash-btn:not(.dash-btn-primary):not(.dash-btn-danger),
.dash-modal-actions .dc-btn:not(.dc-btn-primary):not(.dash-btn-danger),
.dash-modal-footer .dash-btn:not(.dash-btn-primary):not(.dash-btn-danger),
.dash-modal-footer .dc-btn:not(.dc-btn-primary):not(.dash-btn-danger) {
  background: transparent;
  color: var(--text, #dbdee1);
  border: 1px solid rgba(255,255,255,0.18);
}
.dc-modal-actions .dash-btn:not(.dash-btn-primary):not(.dash-btn-danger):hover,
.dc-modal-actions .dc-btn:not(.dc-btn-primary):not(.dash-btn-danger):hover,
.dash-modal-actions .dash-btn:not(.dash-btn-primary):not(.dash-btn-danger):hover,
.dash-modal-actions .dc-btn:not(.dc-btn-primary):not(.dash-btn-danger):hover,
.dash-modal-footer .dash-btn:not(.dash-btn-primary):not(.dash-btn-danger):hover,
.dash-modal-footer .dc-btn:not(.dc-btn-primary):not(.dash-btn-danger):hover {
  background: rgba(255,255,255,0.05);
  border-color: rgba(255,255,255,0.35);
  color: #fff;
}

.dash-modal-error { color: #ff8e91; font-size: 12px; margin: 6px 0 0; }

/* Featured top-of-modal switch ("Command aktiv", "Hub aktiv", etc.).
   Sits in its own framed strip so the on/off state is the first thing
   the user sees when the modal opens. */
.dash-modal-body .vb-switch.vb-switch--top {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  background: rgba(255, 130, 40, 0.05);
  border: 1px solid rgba(255, 130, 40, 0.20);
  border-radius: 10px;
  margin-bottom: 18px;
}
.dash-modal-body .vb-switch.vb-switch--top .vb-switch-label {
  font-weight: 600;
  font-size: 14px;
  color: var(--text);
}

/* Field-label + inline-switch on the same row — used for the Matches
   textarea where "Groß/Klein egal" belongs visually next to the label,
   not below the textarea. */
.vb-keyword-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 8px;
  flex-wrap: wrap;
}
.vb-switch.vb-switch--inline {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  font-size: 12px;
  color: var(--text-muted);
}

/* Inline prefix editor inside the Custom Commands modal — shows the
   global custom_commands_prefix with a live preview of the trigger. */
.vb-prefix-inline {
  margin-top: 10px;
  padding: 12px 14px;
  background: rgba(255, 130, 40, 0.04);
  border: 1px dashed rgba(255, 130, 40, 0.30);
  border-radius: 10px;
}
.vb-prefix-row {
  display: flex;
  align-items: center;
  gap: 12px;
}
.vb-prefix-input {
  width: 80px !important;
  text-align: center;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace !important;
  font-size: 15px !important;
  letter-spacing: 1px;
}
.vb-prefix-preview {
  flex: 1;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 13px;
  color: var(--orange);
  background: rgba(0, 0, 0, 0.30);
  border: 1px solid rgba(255, 130, 40, 0.25);
  border-radius: 8px;
  padding: 8px 12px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Mobile — modal goes (almost) full-screen on small viewports */
@media (max-width: 640px) {
  .dc-modal-overlay,
  .dash-modal-overlay { padding: 0; }
  .dc-modal,
  .dash-modal {
    max-width: 100%;
    max-height: 100vh;
    border-radius: 0;
    border-left: 0;
    border-right: 0;
  }
}

/* ─── Paywall card (Branding tab when locked) ───────────────────────────── */
.vb-paywall {
  background: linear-gradient(135deg, rgba(255,138,34,.08), rgba(255,138,34,.02));
  border: 1px solid rgba(255,138,34,.25);
  border-radius: 12px;
  padding: 28px;
}
.vb-paywall h3 { margin: 0 0 8px; font-size: 17px; color: var(--orange); }
.vb-paywall p  { margin: 0 0 14px; color: var(--text-dim); line-height: 1.55; font-size: 14px; }

/* ─── Blacklist row layout ──────────────────────────────────────────────── */
.vb-bl-list { margin: 12px 0; }
.vb-bl-row {
  display: grid;
  grid-template-columns: 1fr 1.6fr auto;
  gap: 12px;
  padding: 10px 14px;
  background: rgba(255,255,255,.02);
  border: 1px solid rgba(255,255,255,.06);
  border-radius: 10px;
  margin-bottom: 8px;
  align-items: center;
}
.vb-bl-id { font-family: ui-monospace, monospace; font-size: 13px; color: var(--text-bright); }
.vb-bl-meta {
  font-size: 13px;
  color: var(--text-dim);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.vb-bl-add {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr auto;
  gap: 8px;
  margin-top: 12px;
}
.vb-bl-add-users { grid-template-columns: 1fr 2fr auto; }
@media (max-width: 720px) {
  .vb-bl-row    { grid-template-columns: 1fr auto; }
  .vb-bl-meta   { grid-column: 1 / -1; }
  .vb-bl-add,
  .vb-bl-add-users { grid-template-columns: 1fr; }
}

/* Tighten label/input spacing inside the blacklist-edit modal — the
   default modal layout has a generous gap that feels too airy for a tiny
   2-field form. */
.vb-bl-edit-overlay .dash-modal-body .dash-modal-label {
  margin-bottom: 0;
  font-size: 11px;
  line-height: 1.2;
}
.vb-bl-edit-overlay .dash-modal-body .dash-modal-label[style] {
  margin-top: 12px !important;
}
.vb-bl-edit-overlay .dash-modal-body .dash-modal-input {
  padding: 6px 12px;
  font-size: 13px;
}

/* Rich variant with id / name / reason / time + actions ── DEVCON_BL_RICH_v1 */
.vb-bl-row--rich {
  grid-template-columns: minmax(170px, 1.1fr) minmax(120px, 1fr) minmax(140px, 1.4fr) minmax(110px, 0.9fr) auto;
  gap: 14px;
}
.vb-bl-row--rich .vb-bl-cell {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.vb-bl-row--rich .vb-bl-cell code,
.vb-bl-row--rich .vb-bl-cell span {
  font-size: 13px;
  color: var(--text-bright);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.vb-bl-row--rich .vb-bl-cell code {
  font-family: ui-monospace, monospace;
}
.vb-bl-id-label,
.vb-bl-cell-label {
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-muted);
}
.vb-bl-actions {
  display: flex;
  align-items: center;
  gap: 6px;
  justify-self: end;
}
/* Stack the cells vertically on narrow screens so the action icons stay
   reachable without horizontal overflow. */
@media (max-width: 880px) {
  .vb-bl-row--rich {
    grid-template-columns: 1fr auto;
  }
  .vb-bl-row--rich .vb-bl-cell { grid-column: 1; }
  .vb-bl-actions { grid-column: 2; grid-row: 1 / span 4; align-self: start; flex-direction: column; }
}
.vb-bl-empty {
  color: var(--text-dim);
  font-size: 13px;
  padding: 14px;
  text-align: center;
  border: 1px dashed rgba(255,255,255,.08);
  border-radius: 10px;
}

/* Danger button (used for blacklist remove + whitelabel disable) */
.dash-btn-danger {
  background: rgba(240,71,71,.12);
  color: #ff8585;
  border: 1px solid rgba(240,71,71,.3);
  padding: 8px 14px;
  border-radius: 8px;
  font-size: 13px;
  cursor: pointer;
  font-family: inherit;
}
.dash-btn-danger:hover { background: rgba(240,71,71,.2); }

/* Log pre */
.vb-log-pre {
  background: rgba(0,0,0,.35);
  border: 1px solid rgba(255,255,255,.06);
  border-radius: 10px;
  padding: 14px;
  max-height: 60vh;
  overflow: auto;
  font-family: ui-monospace, "JetBrains Mono", monospace;
  font-size: 12px;
  color: #c9ccd0;
  white-space: pre-wrap;
  line-height: 1.5;
}

/* ─── Toast (success/error feedback) ────────────────────────────────────── */
.vb-toast-host {
  position: fixed;
  bottom: 24px;
  right: 24px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  z-index: 100;
}
.vb-toast {
  padding: 12px 18px;
  background: var(--bg-card);
  border: 1px solid rgba(255,255,255,.08);
  color: var(--text-bright);
  border-radius: 10px;
  font-size: 14px;
  font-weight: 500;
  box-shadow: 0 8px 24px rgba(0,0,0,.45);
  animation: vbToastIn .18s ease-out, vbToastOut .35s ease-in 1.9s forwards;
}
.vb-toast.is-success { border-color: rgba(74,222,128,.4);  color: #d1fadf; }
.vb-toast.is-error   { border-color: rgba(252,165,165,.4); color: #ffd0d0; }
@keyframes vbToastIn  { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }
@keyframes vbToastOut { to   { opacity: 0; transform: translateY(8px); } }

/* Error state */
.vb-error-state {
  text-align: center;
  padding: 60px 24px;
  color: var(--text-dim);
}
.vb-error-state h2 { font-size: 18px; margin: 0 0 12px; color: var(--text-bright); }
.vb-error-state .btn { margin-top: 18px; }

/* Closed-beta "bald verfügbar" screen. Centered card with clock icon,
   matches the homepage greeting tone so the page never looks broken. */
.vb-coming-soon {
  max-width: 560px;
  margin: 60px auto 80px;
  padding: 48px 40px;
  text-align: center;
  background: var(--bg-card);
  border: 1px solid rgba(255, 130, 40, 0.20);
  border-radius: 18px;
  position: relative;
  overflow: hidden;
}
.vb-coming-soon::before {
  content: '';
  position: absolute;
  top: -40%;
  left: 50%;
  transform: translateX(-50%);
  width: 480px;
  height: 320px;
  background: radial-gradient(ellipse 50% 50% at 50% 0%, rgba(255, 140, 26, 0.12), transparent 70%);
  pointer-events: none;
}
.vb-coming-soon-icon {
  position: relative;
  width: 88px;
  height: 88px;
  margin: 0 auto 22px;
  display: grid;
  place-items: center;
  background: rgba(255, 130, 40, 0.10);
  color: var(--orange);
  border-radius: 24px;
}
.vb-coming-soon h2 {
  position: relative;
  font-size: 22px;
  font-weight: 700;
  letter-spacing: -0.01em;
  margin: 0 0 10px;
  color: var(--text);
}
.vb-coming-soon p {
  position: relative;
  font-size: 14px;
  line-height: 1.6;
  color: var(--text-muted);
  margin: 0 0 26px;
}
.vb-coming-soon-actions {
  position: relative;
  display: flex;
  justify-content: center;
  gap: 10px;
  flex-wrap: wrap;
}

/* ─── Bot Personalisieren (locked teaser) ───────────────────────────── */
/* Global Premium marker (DEVCON_PREMIUM_MARK_v1) — orange-gradient icon
   that sits inline before any title gating a premium-only feature. */
.vb-premium-mark {
  display: inline-flex;
  align-items: center;
  vertical-align: -3px;
  margin-right: 8px;
  flex: 0 0 auto;
  filter: drop-shadow(0 2px 6px rgba(255, 107, 26, 0.32));
  transition: transform .35s cubic-bezier(.34, 1.56, .64, 1),
              filter .25s ease;
  transform-origin: 50% 60%;       /* leichte Drehung um die Basis statt der Mitte */
  cursor: default;
}
.vb-premium-mark svg { display: block; }
.vb-premium-mark:hover {
  transform: scale(1.22) rotate(-8deg);
  filter: drop-shadow(0 4px 14px rgba(255, 107, 26, 0.55));
  animation: vbPremiumWobble 1.4s ease-in-out infinite;
}
@keyframes vbPremiumWobble {
  0%, 100% { transform: scale(1.22) rotate(-8deg); }
  50%      { transform: scale(1.26) rotate(8deg); }
}

/* Paid-Feature Marker — gleiche Form wie Premium-Crown, aber Glow in
   Diamant-Hellblau zur Unterscheidung. */
.vb-paid-mark {
  filter: drop-shadow(0 2px 6px rgba(86, 184, 230, 0.42));
}
.vb-paid-mark:hover {
  filter: drop-shadow(0 4px 14px rgba(207, 241, 255, 0.70));
}

/* Gesperrtes Bot-Token Feld — visuell editierbar aussehend, aber Klick
   öffnet das Kauf-Modal. cursor:pointer signalisiert das. */
.vb-paid-locked-input {
  cursor: pointer !important;
  caret-color: transparent;
}
.vb-paid-locked-input:focus {
  outline: none;
  border-color: var(--orange);
}

/* Whitelabel-Kauf Modal */
.vb-paid-modal[hidden] { display: none; }
.vb-paid-modal {
  position: fixed; inset: 0;
  z-index: 10000;
  display: flex;
  align-items: center;
  justify-content: center;
}
.vb-paid-modal-backdrop {
  position: absolute; inset: 0;
  background: rgba(0, 0, 0, 0.65);
  backdrop-filter: blur(6px);
}
.vb-paid-modal-card {
  position: relative;
  max-width: 460px;
  width: calc(100% - 32px);
  background: var(--bg-card, #14151a);
  border: 1px solid var(--border, rgba(255, 255, 255, 0.08));
  border-radius: 14px;
  padding: 28px 28px 22px;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.6);
  text-align: center;
}
.vb-paid-modal-close {
  position: absolute;
  top: 10px; right: 14px;
  background: transparent;
  border: 0;
  color: var(--text-muted);
  font-size: 24px;
  line-height: 1;
  cursor: pointer;
  padding: 4px 8px;
  transition: color .15s, transform .15s;
}
.vb-paid-modal-close:hover { color: #ed4245; transform: rotate(90deg); }
.vb-paid-modal-icon {
  display: flex;
  justify-content: center;
  margin: 8px 0 18px;
}
/* Modal-Crown läuft permanent in der Wobble-Animation — gleicher Effekt
   wie sonst beim Hover, hier dauerhaft sichtbar als visuelles Highlight.
   Paid-Variante: Diamant-Hellblau Glow. Premium-Variante: Orange Glow. */
.vb-paid-modal-icon .vb-premium-mark {
  filter: drop-shadow(0 6px 18px rgba(207, 241, 255, 0.55));
  transform-origin: 50% 60%;
  animation: vbPremiumWobble 2s ease-in-out infinite;
}
.vb-paid-modal-icon--premium .vb-premium-mark {
  filter: drop-shadow(0 6px 18px rgba(255, 138, 34, 0.55));
}
.vb-paid-modal-card h3 {
  margin: 0 0 8px;
  font-size: 18px;
  font-weight: 700;
  color: var(--text-bright);
}
.vb-paid-modal-desc {
  margin: 0 0 14px;
  font-size: 13px;
  color: var(--text-muted);
  line-height: 1.5;
}
.vb-paid-modal-list {
  margin: 0 0 18px;
  padding: 0;
  list-style: none;
  text-align: left;
  display: grid;
  gap: 8px;
}
.vb-paid-modal-list li {
  position: relative;
  padding-left: 28px;
  font-size: 13px;
  color: var(--text);
  line-height: 1.45;
}
.vb-paid-modal-list li::before {
  content: "";
  position: absolute;
  left: 2px;
  top: 2px;
  width: 18px;
  height: 18px;
  /* Verzierter "Verified-Seal" Check — scalloped Badge in Grün mit
     weißem Haken in der Mitte. Twitter-Verified-Style. */
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path fill='%233ba55d' d='M22.5 12.5c0-1.58-.875-2.95-2.148-3.6.154-.435.238-.905.238-1.4 0-2.21-1.71-3.998-3.818-3.998-.47 0-.92.084-1.336.25C14.818 2.415 13.51 1.5 12 1.5s-2.818.916-3.437 2.25c-.415-.165-.866-.25-1.336-.25-2.11 0-3.818 1.79-3.818 4 0 .494.083.964.237 1.4-1.272.65-2.147 2.018-2.147 3.6 0 1.495.782 2.798 1.942 3.486-.02.17-.032.34-.032.514 0 2.21 1.708 4 3.818 4 .47 0 .92-.086 1.335-.25.618 1.334 1.926 2.25 3.437 2.25s2.818-.916 3.437-2.25c.415.163.866.25 1.336.25 2.11 0 3.818-1.79 3.818-4 0-.174-.012-.344-.033-.513 1.158-.687 1.943-1.99 1.943-3.484z'/><path fill='none' stroke='white' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round' d='M8.5 12.5 L11 15 L16 9.5'/></svg>");
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
  transition: transform .3s cubic-bezier(.34, 1.56, .64, 1);
  transform-origin: 50% 55%;
}
.vb-paid-modal-list li:hover::before {
  transform: rotate(-14deg) scale(1.18);
}

/* Body-Scroll-Lock solange irgendein modal offen ist. */
body.vb-modal-open { overflow: hidden; }
.vb-paid-modal-actions {
  display: flex;
  gap: 10px;
  justify-content: flex-end;
  align-items: stretch;
  margin-top: 4px;
}

/* Combined CTA — Label links, Preis-Pille rechts. Button erbt vom
   globalen .dash-btn-primary (devcon orange). */
.vb-paid-cta {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  padding-right: 8px;        /* Pille hat eigenes Padding, kein doppeltes */
}
.vb-paid-cta-price {
  display: inline-flex;
  align-items: baseline;
  gap: 2px;
  padding: 4px 10px;
  background: rgba(0, 0, 0, 0.22);
  border-radius: 999px;
  font-weight: 800;
  font-size: 13px;
  letter-spacing: -0.01em;
}
.vb-paid-cta-period {
  font-weight: 500;
  font-size: 11px;
  opacity: 0.85;
}

/* The outer .vb-section already provides the framing box; this wrap is
   just a positioning context for the click-overlay. */
.vb-pers-wrap { position: relative; }
.vb-pers-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  margin-bottom: 18px;
}
.vb-pers-lock-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 14px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.2px;
  text-transform: uppercase;
  color: #fff;
  background: linear-gradient(135deg, #ff9a3c, #ff6b1a);
  border: 0;
  border-radius: 999px;
  box-shadow: 0 4px 14px rgba(255, 107, 26, 0.32);
  cursor: pointer;
  white-space: nowrap;
}
.vb-pers-lock-pill:hover { transform: translateY(-1px); box-shadow: 0 6px 18px rgba(255, 107, 26, 0.42); }
.vb-pers-lock-pill:focus-visible { outline: 2px solid var(--orange); outline-offset: 2px; }

/* Two-column layout: editor left, previews right. Only the editor is
   visually dimmed (it's the locked control); the previews render at
   full brightness so they read as a real glimpse of the bot. */
.vb-pers-grid {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 380px);
  gap: 20px;
  pointer-events: none;       /* clicks fall through to the overlay (locked teaser) */
  user-select: none;
}
/* When premium is active, the editor is fully interactive — re-enable
   pointer events and selection on the grid. */
.vb-pers-wrap.is-unlocked .vb-pers-grid {
  pointer-events: auto;
  user-select: auto;
}
@media (max-width: 960px) {
  .vb-pers-grid { grid-template-columns: 1fr; }
}
.vb-pers-overlay {
  position: absolute;
  inset: 0;
  top: 80px;
  cursor: pointer;
  z-index: 2;
  background: transparent;
}

/* ── Editor (left) — the surrounding chrome (banner, avatar, labels)
   renders at full brightness so the editor looks like a real Discord
   profile editor. Only the actual interactive controls get the locked
   "muted" treatment — see .vb-pers-field input/select + .vb-pers-status
   rules further down. ── */
.vb-pers-editor {
  position: relative;
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 12px;
  overflow: hidden;
}
/* Click-Catcher über der ganzen Editor-Karte solange !premium — jeder
   Click auf Banner / Avatar / Name / Status / Aktivität öffnet das
   Upsell-Modal statt direkt etwas zu ändern. */
.vb-pers-editor-overlay {
  position: absolute;
  inset: 0;
  z-index: 4;
  cursor: pointer;
  background: transparent;
  pointer-events: auto;     /* parent .vb-pers-grid sets pointer-events:none — explicit auto re-enables for the catcher */
}
.vb-pers-banner {
  position: relative;
  height: 130px;
  background: linear-gradient(135deg, #5865f2 0%, #3b45c4 50%, #1e2147 100%);
  transition: filter .15s ease;
}
.vb-pers-banner.is-clickable { cursor: pointer; }
.vb-pers-banner.is-clickable:hover { filter: brightness(1.08); }
.vb-pers-avatar.is-clickable { cursor: pointer; }
.vb-pers-avatar.is-clickable:hover { filter: brightness(1.08); }
.vb-pers-avatar-wrap { cursor: pointer; }
.vb-pers-edit-chip {
  position: absolute;
  top: 12px;
  right: 12px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 10px;
  font-size: 11px;
  font-weight: 600;
  color: #fff;
  background: rgba(0, 0, 0, 0.45);
  border: 1px dashed rgba(255, 255, 255, 0.35);
  border-radius: 999px;
  backdrop-filter: blur(4px);
}
.vb-pers-avatar-wrap {
  position: absolute;
  left: 24px;
  bottom: -36px;
  width: 88px;
  height: 88px;
}
.vb-pers-avatar {
  width: 88px;
  height: 88px;
  border-radius: 50%;
  background: #2a2d34;
  display: grid;
  place-items: center;
  font-size: 36px;
  font-weight: 700;
  color: #fff;
  overflow: hidden;
  box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.10);
}
.vb-pers-avatar:has(img) { background: transparent; }
.vb-pers-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.vb-pers-member-avatar { overflow: hidden; }
.vb-pers-member-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.vb-pers-profile-avatar { overflow: hidden; }
.vb-pers-profile-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.vb-pers-edit-dot {
  position: absolute;
  right: -2px;
  bottom: 4px;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.45);
  border: 1px dashed rgba(255, 255, 255, 0.35);
  display: grid;
  place-items: center;
  color: #fff;
  backdrop-filter: blur(4px);
}
.vb-pers-fields {
  padding: 56px 22px 22px;
  display: flex;
  flex-direction: column;
  gap: 18px;
}
.vb-pers-save-row {
  display: none;                            /* hidden until the editor is dirty */
  justify-content: flex-end;
  margin-top: 4px;
}
.vb-pers-editor.is-dirty .vb-pers-save-row { display: flex; }
.vb-pers-status-line {
  margin: 0;
  font-size: 12px;
}
.vb-pers-status-line.is-err { color: #fca5a5; }
.vb-pers-field label {
  display: block;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--text-dim, rgba(255, 255, 255, 0.55));
  margin-bottom: 6px;
}
.vb-pers-field input,
.vb-pers-field select {
  width: 100%;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 8px;
  color: var(--text);
  font: inherit;
  font-size: 14px;
  padding: 10px 12px;
  /* Locked controls — dim so it's clear they're not interactive yet. */
  opacity: 0.55;
  filter: grayscale(0.3);
}
/* Unlocked (premium): full brightness + interactive look. */
.vb-pers-wrap.is-unlocked .vb-pers-field input,
.vb-pers-wrap.is-unlocked .vb-pers-field select {
  opacity: 1;
  filter: none;
}
/* Devcon-Standard Focus-Look auf allen interaktiven Pers-Felder:
   orangener Rand + dezenter orange Glow, kein native outline. Gilt für:
     • Bot-Name Input  (.vb-pers-field input)
     • Aktivitäts-Status-Text Input (.vb-pers-statact-row input)
     • Custom-Dropdown Trigger (.vb-pers-statact-row .vb-picker-trigger)
   So sieht's identisch aus zu den dash-modal-inputs überall sonst. */
.vb-pers-wrap.is-unlocked .vb-pers-field input:focus,
.vb-pers-wrap.is-unlocked .vb-pers-field select:focus,
.vb-pers-statact-row input:focus,
.vb-pers-statact-row select:focus,
.vb-pers-statact-row .vb-picker-trigger:focus,
.vb-pers-statact-row .vb-picker-trigger:focus-visible {
  border-color: var(--orange) !important;
  background: rgba(255, 130, 40, 0.04);
  box-shadow: 0 0 0 3px rgba(255, 130, 40, 0.15);
  outline: none;
}
/* Custom chevron so the arrow sits tight against the right edge instead
   of the browser's default (which often pushes it half-out of the box). */
.vb-pers-field select {
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  padding-right: 32px;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-opacity='0.55' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-size: 12px 12px;
}
.vb-pers-field--row {
  display: grid;
  grid-template-columns: 200px 1fr;
  gap: 14px;
}
@media (max-width: 600px) { .vb-pers-field--row { grid-template-columns: 1fr; } }
/* Status + Aktivität in einer Karte. Label→Selector entspricht dem
   label→input Abstand der anderen Felder (6px). Selector→Aktivitätszeile
   ist größer (≈ inter-field Abstand wie zwischen Bot-Name und Status). */
.vb-pers-statact { display: flex; flex-direction: column; gap: 6px; }
.vb-pers-statact > label { margin-bottom: 0; }
.vb-pers-statact > .vb-pers-statact-row { margin-top: 12px; }
.vb-pers-statact-row {
  display: grid;
  grid-template-columns: 160px 1fr;
  gap: 8px;
}
@media (max-width: 600px) { .vb-pers-statact-row { grid-template-columns: 1fr; } }
/* Status-Bar — segmentierter vb-mode-pills Slider (Nachricht/Embed/V2-
   Pattern). Inline-flex damit der Bar nur so breit wird wie nötig, nicht
   full-width. Statt eines Farb-Punkts vor dem Label nimmt die aktive
   Pill die Discord-Statusfarbe als Hintergrund an. */
.vb-pers-status-bar {
  margin: 0;
  display: inline-flex;
  align-self: flex-start;   /* parent .vb-pers-statact is column flex → stretch is default; this stops the bar at "Unsichtbar". */
  width: fit-content;
  max-width: 100%;
}
.vb-pers-status-bar .vb-mode-pill[data-status="online"].is-active    { background: #3ba55d; color: #0a0a0a; }
.vb-pers-status-bar .vb-mode-pill[data-status="idle"].is-active      { background: #faa61a; color: #0a0a0a; }
.vb-pers-status-bar .vb-mode-pill[data-status="dnd"].is-active       { background: #ed4245; color: #fff;    }
.vb-pers-status-bar .vb-mode-pill[data-status="invisible"].is-active { background: #747f8d; color: #fff;    }

/* Tier-2 lock: dimmt sowohl Status-Slider als auch Aktivitäts-Zeile,
   solange kein eigener Bot-Token aktiv ist. Status & Aktivität sind
   beide gateway-only — der Shared-Bot kann sie nicht pro Server setzen. */
.vb-pers-statact-row.is-locked,
.vb-pers-status-bar.is-locked { opacity: 0.55; pointer-events: none; cursor: not-allowed; }
.vb-pers-statact-row .vb-picker { width: 100%; }
.vb-pers-statact-row .vb-picker-trigger { width: 100%; }

/* ── Previews (right) — column stretches to the editor's height (grid
   default). Cards keep their natural content size; the larger profile
   card grows to soak up any leftover space so the bottom edge of the
   column meets the editor's bottom edge. ── */
.vb-pers-previews {
  display: flex;
  flex-direction: column;
  gap: 14px;
  height: 100%;
}
.vb-pers-preview-card {
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 12px;
  padding: 14px;
}
.vb-pers-preview-card:last-child {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
}
/* Label sticks at the top; the profile mock floats to the vertical
   center of the leftover space via twin auto margins. */
.vb-pers-preview-card:last-child .vb-pers-profile {
  margin-top: auto;
  margin-bottom: auto;
}
.vb-pers-preview-label {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--text-dim, rgba(255, 255, 255, 0.55));
  margin-bottom: 10px;
}
/* Single bot row — matches Discord's member-list entry: 36px avatar
   with the green presence dot in the bottom-right corner, then a
   two-line text block (name + APP inline, custom status below). */
.vb-pers-member {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 8px;
  border-radius: 6px;
}
.vb-pers-member-avatar-wrap {
  position: relative;
  width: 36px;
  height: 36px;
  flex: 0 0 auto;
}
.vb-pers-member-avatar {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-size: 14px;
  font-weight: 700;
  color: #fff;
  overflow: hidden;
}
.vb-pers-member-avatar:has(img) { background: transparent !important; }
.vb-pers-member-presence {
  position: absolute;
  right: -3px;
  bottom: -3px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  border: 4px solid #1e2026;
}
.vb-pers-member-text {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  line-height: 1.2;
}
.vb-pers-member-row1 {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}
.vb-pers-member-name {
  color: var(--text);
  font-weight: 600;
  font-size: 15px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.vb-pers-member-bot {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.3px;
  background: #5865f2;
  color: #fff;
  padding: 2px 6px;
  border-radius: 4px;
  flex: 0 0 auto;
}
.vb-pers-member-status {
  font-size: 12px;
  color: rgba(255, 255, 255, 0.55);
  margin-top: 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Profile preview — clean Discord-style card: banner → overlapping avatar
   with green presence dot → name + APP tag → custom-status line. No
   horizontal divider, no "STATUS" label — Discord doesn't render those. */
.vb-pers-profile {
  border-radius: 10px;
  overflow: hidden;
  background: #1e2026;
}
.vb-pers-profile-banner {
  height: 60px;
  background: linear-gradient(135deg, #5865f2, #1e2147);
}
.vb-pers-profile-avatar-wrap {
  position: relative;
  width: 64px;
  height: 64px;
  margin: -32px 0 0 14px;
}
.vb-pers-profile-avatar {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  background: #2a2d34;
  display: grid;
  place-items: center;
  font-size: 26px;
  font-weight: 700;
  color: #fff;
  overflow: hidden;
  box-shadow: 0 0 0 4px #1e2026;
}
/* Once the real avatar img is injected, hide any residual background so
   transparent corners / PNG fringes don't show a coloured halo. */
.vb-pers-profile-avatar:has(img) { background: transparent; }
.vb-pers-profile-presence {
  position: absolute;
  right: 0;
  bottom: 0;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  border: 5px solid #1e2026;
}
.vb-pers-profile-body { padding: 8px 14px 14px; }
.vb-pers-profile-name {
  font-size: 16px;
  font-weight: 700;
  color: var(--text);
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.vb-pers-profile-bot {
  font-size: 10px;
  font-weight: 700;
  background: #5865f2;
  color: #fff;
  padding: 2px 6px;
  border-radius: 4px;
}
/* Discriminator / username under the display name (e.g. "devCon#4124"). */
.vb-pers-profile-tag {
  font-size: 13px;
  color: rgba(255, 255, 255, 0.55);
  margin-top: 2px;
}

/* Discord activity box: rounded grey card under the name, two lines
   stacked — "Spielt"/"Hört … zu"/"Schaut" verb on top, activity text
   below. Same chrome Discord uses for game/listening/watching status. */
.vb-pers-activity-box {
  margin-top: 10px;
  padding: 10px 12px;
  background: rgba(255, 255, 255, 0.05);
  border-radius: 8px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.vb-pers-activity-verb {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.3px;
  color: rgba(255, 255, 255, 0.55);
  text-transform: none;
}
.vb-pers-activity-text {
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
}

/* ── Upsell modal ── */
.vb-pers-modal {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: grid;
  place-items: center;
  padding: 20px;
}
.vb-pers-modal[hidden] { display: none; }
.vb-pers-modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
  backdrop-filter: blur(4px);
}
.vb-pers-modal-card {
  position: relative;
  max-width: 480px;
  width: 100%;
  background: var(--bg-card, #16181d);
  border: 1px solid rgba(255, 255, 255, 0.10);
  border-radius: 14px;
  padding: 28px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
}
.vb-pers-modal-close {
  position: absolute;
  top: 12px;
  right: 14px;
  /* dimensional + hover behaviour now inherited from the unified
     .dash-modal-close rule above (DEVCON_GLOBAL_CLOSE_v1). */
}
.vb-pers-modal-icon {
  width: 56px;
  height: 56px;
  border-radius: 14px;
  background: linear-gradient(135deg, #ff9a3c, #ff6b1a);
  color: #fff;
  display: grid;
  place-items: center;
  margin-bottom: 14px;
}
.vb-pers-modal h3 { font-size: 18px; margin: 0 0 8px; color: var(--text); }
.vb-pers-modal-desc { font-size: 13px; color: var(--text-dim); margin: 0 0 14px; line-height: 1.55; }
.vb-pers-modal-list {
  margin: 0 0 18px;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 13px;
  color: var(--text);
}
.vb-pers-modal-list li::before { content: "✓"; color: var(--orange); margin-right: 8px; font-weight: 700; }
.vb-pers-modal-token { margin-bottom: 16px; }
.vb-pers-modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}


/* === Embed Creator MEE6 redesign v1 ===
   List-view: hero card "New embed message" + table with status badges + search.
   Editor: header with back/delete/discard/save/publish + collapsible sections.
   Reuses devCon design tokens (--bg-card, --orange, --border, --radius) and
   matches the rest of dashboard-bot.css conventions. */

/* ─── List view ─── */

.vb-ec-hero {
  margin-bottom: 24px;
}
.vb-ec-hero h2 { margin: 0 0 6px; font-size: 22px; font-weight: 700; }
.vb-ec-hero p {
  margin: 0;
  color: var(--text-dim);
  font-size: 13px;
  line-height: 1.55;
}

.vb-ec-hero-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}

/* Big "+ New embed message" card-button. Full-width, orange outline on hover.
   Height matched to .vb-ec-import-card by taking the optional plus-icon out
   of the flex flow (position:absolute) so only the text drives the height. */
.vb-ec-new-card {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  width: 100%;
  box-sizing: border-box;
  height: 68px !important;
  padding: 0 24px;
  /* background/border/radius/spacing handled by DEVCON_CARD_CONSISTENCY_v1
     so they stay in sync with .vb-section + .vb-ec-list-panel. */
  color: var(--text);
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
  transition: border-color .15s, background .15s, transform .15s;
  font-family: inherit;
}
.vb-ec-new-card:hover {
  border-color: var(--orange);
  background: rgba(255, 140, 26, 0.04);
}
.vb-ec-new-card:active { transform: scale(0.998); }
.vb-ec-new-card-plus {
  position: absolute;
  right: 24px;
  top: 50%;
  transform: translateY(-50%);
  width: 20px;
  height: 20px;
  color: var(--text-dim);
  transition: color .15s, transform .2s;
}
.vb-ec-new-card:hover .vb-ec-new-card-plus {
  color: var(--orange);
  transform: translateY(-50%) rotate(90deg);
}

/* Import button — sibling to .vb-ec-new-card in the same flex row. Same
   height (matched padding + font-size), narrower fixed width, with a big
   faded download icon as right-side background art. */
.vb-ec-import-card {
  position: relative;
  display: flex;
  align-items: center;
  flex: 0 0 280px;
  box-sizing: border-box;
  height: 68px;
  padding: 0 24px;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 12px;
  color: var(--text);
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
  overflow: hidden;
  font-family: inherit;
  transition: border-color .15s, background .15s, transform .15s;
}
.vb-ec-import-card:hover {
  border-color: var(--orange);
  background: rgba(255, 140, 26, 0.04);
}
.vb-ec-import-card:active { transform: scale(0.998); }
.vb-ec-import-label {
  position: relative;
  z-index: 1;
  text-align: left;
}
/* Big faded download icon sticking out on the right — pure visual flavor.
   Uses opacity (not low-alpha color) so overlapping strokes stay uniform
   gray instead of double-darkening where they cross. */
.vb-ie-bg-art {}
.vb-ec-import-bg {
  position: absolute;
  right: -14px;
  top: 50%;
  width: 88px;
  height: 88px;
  transform: translateY(-50%);
  color: #fff;
  opacity: 0.08;
  pointer-events: none;
  transition: opacity .15s, color .15s, transform .25s;
}
.vb-ec-import-card:hover .vb-ec-import-bg {
  color: var(--orange, #ff8c1a);
  opacity: 0.35;
  transform: translateY(-50%) translateX(-4px);
}

/* List panel (Your embed messages) */
.vb-ec-list-panel {
  /* background/border/radius handled by DEVCON_CARD_CONSISTENCY_v1. */
  padding: 22px 24px;
}
.vb-ec-list-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 16px;
  flex-wrap: wrap;
  gap: 12px;
}
.vb-ec-list-head h3 {
  margin: 0;
  font-size: 16px;
  font-weight: 600;
}
.vb-ec-counter {
  font-size: 13px;
  color: var(--text-dim);
}
.vb-ec-counter strong { color: var(--text); font-weight: 600; }

/* Search input. The global `.vb-panel input[type="text"]:not(…):not(…)`
   reset down at line ~2225 has specificity (0,4,2) — higher than any
   reasonable scoped selector we can write here. The padding/border/
   background overrides use !important defensively to break out of that
   reset, otherwise the input ends up at 14px left-padding and the
   magnifier icon overlaps the placeholder text. */
.vb-ec-list-panel .vb-ec-search {
  position: relative;
  margin-bottom: 8px;
}
.vb-ec-list-panel .vb-ec-search input[type="text"] {
  width: 100%;
  box-sizing: border-box;
  padding: 12px 14px 12px 42px !important;
  background: rgba(255,255,255,.02) !important;
  border: 1px solid var(--border) !important;
  border-radius: 8px !important;
  color: var(--text);
  font-size: 14px;
  font-family: inherit;
  transition: border-color .15s ease, background .15s ease;
}
.vb-ec-list-panel .vb-ec-search input[type="text"]::placeholder { color: var(--text-dim); }
.vb-ec-list-panel .vb-ec-search input[type="text"]:hover {
  border-color: rgba(255,255,255,.14) !important;
}
.vb-ec-list-panel .vb-ec-search input[type="text"]:focus {
  outline: none;
  border-color: var(--orange) !important;
  background: rgba(255,255,255,.035) !important;
  box-shadow: none !important;
}
.vb-ec-list-panel .vb-ec-search-icon {
  position: absolute;
  left: 14px;
  top: 50%;
  transform: translateY(-50%);
  width: 16px;
  height: 16px;
  color: var(--text-dim);
  pointer-events: none;
  transition: color .15s ease;
  z-index: 1;
}
.vb-ec-list-panel .vb-ec-search:hover .vb-ec-search-icon,
.vb-ec-list-panel .vb-ec-search:focus-within .vb-ec-search-icon { color: var(--orange); }

/* Table — no top divider under the search anymore; no bottom divider on
   the header row either. Row borders carry enough structure on their own. */
.vb-ec-table { /* container only */ }
.vb-ec-table-head {
  display: grid;
  grid-template-columns: 1fr 160px 200px 50px;
  gap: 12px;
  padding: 12px 0;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--text-dim);
}
.vb-ec-table-row {
  display: grid;
  grid-template-columns: 1fr 160px 200px 50px;
  gap: 12px;
  align-items: center;
  padding: 14px 0;
  border-bottom: 1px solid rgba(255,255,255,.04);
  transition: background .12s ease;
  cursor: pointer;
  position: relative;
}
/* 6-Spalten Variante (Invite-Tracking → Erstellte Einladungen).
   Code | Erstellt von | Channel | Nutzungen | Erstellt | Läuft ab */
.vb-ec-list-table--6 .vb-ec-table-head,
.vb-ec-list-table--6 .vb-ec-table-row {
  grid-template-columns: 1.1fr 1fr 1fr 0.7fr 1fr 1fr;
}

/* Social Overview list — 6 cols: Plattform | Account | Link | Channel | Zuletzt live | Aktionen */
.vb-soc-list-table .vb-ec-table-head,
.vb-soc-list-table .vb-ec-table-row {
  grid-template-columns: 140px 1fr 1.4fr 160px 130px 92px;
}
.vb-soc-row-link {
  color: var(--text-dim);
  text-decoration: none;
  font-size: 12px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 100%;
  transition: color .12s ease;
}
.vb-soc-row-link:hover {
  color: var(--orange);
  text-decoration: underline;
}

/* Giveaway-Liste — 6 cols: Gewinnspiel | Host | Channel | Teilnehmer | Gestartet | Endet */
.vb-gw-list-table .vb-ec-table-head,
.vb-gw-list-table .vb-ec-table-row {
  grid-template-columns: 1.2fr 200px 140px 100px 160px 1.2fr;
}
.vb-gw-list-table .vb-ec-table-row > div { display: flex; align-items: center; min-width: 0; }

/* Embed Creator list — 5 cols: Embed | Autor | Status | Zeit | Aktionen */
.vb-ec-author-table .vb-ec-table-head,
.vb-ec-author-table .vb-ec-table-row {
  grid-template-columns: 1.4fr 200px 140px 140px 92px;
}
.vb-ec-author-table .vb-ec-table-row > div { display: flex; align-items: center; min-width: 0; }
.vb-ec-author-table .vb-sg-actions-head > span { min-width: 92px; }

/* Role-Reactions list — 5 cols: Name | Typ | Rollen | Nutzungen | Aktionen */
.vb-rr-list-table .vb-ec-table-head,
.vb-rr-list-table .vb-ec-table-row {
  grid-template-columns: 1.4fr 140px 200px 100px 60px;
}
.vb-rr-list-table .vb-ec-table-row > div { display: flex; align-items: center; min-width: 0; }
.vb-rr-list-table .vb-sg-actions-head > span { min-width: 60px; }

/* Birthdays list — 5 cols: Mitglied | Datum | Nächster | Ersteller | Aktionen */
.vb-bt-list-table .vb-ec-table-head,
.vb-bt-list-table .vb-ec-table-row {
  grid-template-columns: 1.4fr 100px 160px 200px 60px;
}
.vb-bt-list-table .vb-ec-table-row > div { display: flex; align-items: center; min-width: 0; }
.vb-bt-list-table .vb-sg-actions-head > span { min-width: 60px; }

/* Suggestions Panels list — 5 cols: Panel | Status | Zeit | Letzter Vorschlag | Aktionen */
.vb-sg-panels-table .vb-ec-table-head,
.vb-sg-panels-table .vb-ec-table-row {
  grid-template-columns: 1.4fr 140px 160px 160px 124px;
}
.vb-sg-panels-table .vb-ec-table-row > div { display: flex; align-items: center; min-width: 0; }

/* Highlights Mod-Highlights list — 5 cols: Keyword | Empfänger | Ersteller | Erstellt | Aktionen */
.vb-hlmod-list-table .vb-ec-table-head,
.vb-hlmod-list-table .vb-ec-table-row {
  grid-template-columns: 1fr 1.4fr 200px 140px 60px;
}
.vb-hlmod-list-table .vb-ec-table-row > div { display: flex; align-items: center; min-width: 0; }
/* Hover wash: use a ::before pseudo so the orange tint can extend slightly
   beyond the row's text content without changing the row's own width.
   This keeps the row strictly aligned with the search input and table
   header above it (all three span the panel's content area, x=0..W). */
.vb-ec-table-row::before {
  content: '';
  position: absolute;
  inset: 4px -8px;
  border-radius: 10px;
  background: transparent;
  transition: background .12s ease;
  pointer-events: none;
  z-index: 0;
}
.vb-ec-table-row > * { position: relative; z-index: 1; }
.vb-ec-table-row:hover::before { background: rgba(255,138,34,.05); }
.vb-ec-table-row:hover .vb-ec-row-embed-name { color: var(--orange); }
.vb-ec-table-row:last-child { border-bottom: none; }

.vb-ec-row-embed-name {
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
  margin-bottom: 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.vb-ec-row-channel {
  font-size: 12px;
  color: var(--text-dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.vb-ec-row-channel.is-deleted { color: #ef4444; }
.vb-ec-row-channel-id {
  margin-left: 4px;
  font-size: 11px;
  color: var(--text-muted, #707481);
  font-variant-numeric: tabular-nums;
}

/* Status badges */
.vb-ec-status {
  display: inline-flex;
  align-items: center;
  padding: 4px 10px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .01em;
}
.vb-ec-status.is-draft {
  background: rgba(255,255,255,.06);
  color: var(--text-dim);
}
.vb-ec-status.is-published {
  background: rgba(34, 197, 94, 0.12);
  color: #22c55e;
}
.vb-ec-status.is-channel-deleted {
  background: rgba(239, 68, 68, 0.12);
  color: #ef4444;
}

.vb-ec-row-time {
  font-size: 12px;
  color: var(--text-dim);
}
.vb-ec-row-time-error {
  font-size: 12px;
  color: #ef4444;
  margin-top: 2px;
}

/* Inline row actions — duplicate + delete buttons at the right of each row.
   Replaces the old 3-dot menu for one-click access to the two common ops. */
.vb-ec-row-actions {
  display: flex;
  align-items: center;
  gap: 4px;
  justify-self: end;
}
/* DEVCON_ROW_ACT_v1 — minimal icon-only row action button used globally
   wherever a list has inline delete / duplicate / etc. controls (embed
   creator, backups, audit-log, …). No border, transparent background,
   hover scales + colors. */
.dash-row-act,
.vb-ec-row-act {
  width: 28px;
  height: 28px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 0;
  border-radius: 4px;
  color: var(--text-dim);
  cursor: pointer;
  transition: color .12s, transform .1s;
}
.dash-row-act svg,
.vb-ec-row-act svg { display: block; }
.dash-row-act:hover,
.vb-ec-row-act:hover { transform: scale(1.15); }
.dash-row-act--dup:hover,
.vb-ec-row-act--dup:hover { color: var(--orange, #ff8c1a); }
.dash-row-act--del:hover,
.vb-ec-row-act--del:hover { color: #ed4245; }

/* 3-dot menu (legacy — kept for any other module still using the pattern) */
.vb-ec-row-menu {
  position: relative;
  justify-self: end;
}
.vb-ec-row-menu-btn {
  width: 32px;
  height: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 6px;
  color: var(--text-dim);
  cursor: pointer;
  transition: background .12s, color .12s, border-color .12s;
}
.vb-ec-row-menu-btn:hover {
  background: rgba(255,255,255,.05);
  color: var(--text);
  border-color: var(--border);
}
.vb-ec-row-menu-dropdown {
  position: absolute;
  right: 0;
  top: calc(100% + 4px);
  min-width: 160px;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 8px 24px rgba(0,0,0,.5);
  padding: 4px;
  z-index: 100;
}
.vb-ec-row-menu-dropdown[hidden] { display: none; }
.vb-ec-row-menu-item {
  display: block;
  width: 100%;
  padding: 8px 12px;
  background: transparent;
  border: none;
  border-radius: 4px;
  color: var(--text);
  font-size: 13px;
  text-align: left;
  cursor: pointer;
  transition: background .12s;
  font-family: inherit;
}
.vb-ec-row-menu-item:hover { background: rgba(255,255,255,.05); }
.vb-ec-row-menu-item.is-danger { color: #ef4444; }
.vb-ec-row-menu-item.is-danger:hover { background: rgba(239,68,68,.08); }

/* Empty state for table */
.vb-ec-table-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 48px 20px;
  text-align: center;
  color: var(--text-dim);
  font-size: 13px;
}
.vb-ec-table-empty::before {
  content: '';
  width: 60px;
  height: 60px;
  background-color: var(--text-muted);
  opacity: 0.32;
  -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'><path d='M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z'/><polyline points='14 2 14 8 20 8'/><line x1='9.5' y1='12.5' x2='14.5' y2='17.5'/><line x1='14.5' y1='12.5' x2='9.5' y2='17.5'/></svg>");
          mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'><path d='M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z'/><polyline points='14 2 14 8 20 8'/><line x1='9.5' y1='12.5' x2='14.5' y2='17.5'/><line x1='14.5' y1='12.5' x2='9.5' y2='17.5'/></svg>");
  -webkit-mask-size: contain;          mask-size: contain;
  -webkit-mask-repeat: no-repeat;       mask-repeat: no-repeat;
  -webkit-mask-position: center;        mask-position: center;
}

/* ─── Editor view ─── */

.vb-ec-editor-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  margin-bottom: 22px;
  padding-bottom: 4px;
}
.vb-ec-editor-head-left {
  display: flex;
  align-items: center;
  gap: 12px;
  flex: 1 1 auto;
  min-width: 0;
}
.vb-ec-back {
  width: 36px;
  height: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text-dim);
  cursor: pointer;
  flex-shrink: 0;
  transition: background .12s, color .12s, border-color .12s;
}
.vb-ec-back:hover {
  background: rgba(255,255,255,.04);
  color: var(--text);
  border-color: rgba(255,255,255,.12);
}
.vb-ec-name-wrap {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1 1 auto;
  min-width: 0;
}
.vb-ec-name-input {
  font-size: 20px;
  font-weight: 700;
  background: transparent;
  border: 1px solid transparent;
  color: var(--text);
  padding: 6px 10px;
  border-radius: 6px;
  outline: none;
  font-family: inherit;
  flex: 1 1 auto;
  min-width: 0;
  max-width: 480px;
  transition: background .12s, border-color .12s;
}
.vb-ec-name-input:hover { background: rgba(255,255,255,.03); }
.vb-ec-name-input:focus {
  background: rgba(255,255,255,.04);
  border-color: var(--border);
}
.vb-ec-name-pencil {
  width: 16px;
  height: 16px;
  color: var(--text-dim);
  flex-shrink: 0;
  pointer-events: none;
}

.vb-ec-editor-actions {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap;
}
.vb-ec-action {
  padding: 9px 16px;
  border-radius: 8px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  border: 1px solid var(--border);
  background: transparent;
  color: var(--text);
  transition: background .12s, border-color .12s, color .12s;
  font-family: inherit;
}
.vb-ec-action:hover { background: rgba(255,255,255,.04); }
.vb-ec-action.is-danger {
  color: #ef4444;
  border-color: rgba(239,68,68,.3);
}
.vb-ec-action.is-danger:hover {
  background: rgba(239,68,68,.08);
  border-color: rgba(239,68,68,.5);
}
.vb-ec-action.is-primary {
  background: var(--orange);
  border-color: var(--orange);
  color: #000;
}
.vb-ec-action.is-primary:hover {
  background: #ff9a33;
  border-color: #ff9a33;
}
.vb-ec-action[disabled] {
  opacity: 0.45;
  cursor: not-allowed;
}

/* Collapsible sections */
.vb-ec-block {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 12px;
  margin-bottom: 14px;
  overflow: hidden;
}
.vb-ec-block-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 20px;
  cursor: pointer;
  user-select: none;
  transition: background .12s;
}
.vb-ec-block-head:hover { background: rgba(255,255,255,.02); }
.vb-ec-block-head h3 {
  margin: 0;
  font-size: 15px;
  font-weight: 600;
}
.vb-ec-block-chevron {
  width: 18px;
  height: 18px;
  color: var(--text-dim);
  transition: transform .2s;
}
.vb-ec-block.is-collapsed .vb-ec-block-chevron { transform: rotate(-90deg); }
.vb-ec-block-body {
  padding: 4px 20px 20px;
  border-top: 1px solid var(--border);
}
.vb-ec-block.is-collapsed .vb-ec-block-body { display: none; }
.vb-ec-block-desc {
  margin: 0 0 14px;
  color: var(--text-dim);
  font-size: 12px;
  line-height: 1.55;
}

/* Discord-style bot preview header (used in Message section) */
.vb-ec-bot-header {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 0 16px;
}
.vb-ec-bot-avatar {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--orange);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
  font-weight: 700;
  color: #000;
  flex-shrink: 0;
}
.vb-ec-bot-avatar img { width: 100%; height: 100%; border-radius: 50%; object-fit: cover; }
.vb-ec-bot-meta {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 14px;
  flex-wrap: wrap;
}
.vb-ec-bot-name { font-weight: 600; color: var(--text); }
.vb-ec-bot-badge {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 1px 5px;
  font-size: 10px;
  font-weight: 700;
  background: #5865F2;
  color: #fff;
  border-radius: 3px;
  letter-spacing: .02em;
}
.vb-ec-bot-time {
  color: var(--text-dim);
  font-size: 12px;
  margin-left: 4px;
}

/* Add buttons (Add embed / Add link button) */
.vb-ec-add-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  padding: 12px 16px;
  background: transparent;
  border: 1px dashed rgba(255,255,255,.12);
  border-radius: 10px;
  color: var(--text-dim);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition: border-color .15s, color .15s, background .15s;
  margin-top: 12px;
  font-family: inherit;
}
.vb-ec-add-btn:hover {
  border-color: var(--orange);
  color: var(--orange);
  background: rgba(255,140,26,.03);
}
.vb-ec-add-btn[disabled] {
  opacity: 0.4;
  cursor: not-allowed;
  border-color: rgba(255,255,255,.06);
  color: var(--text-dim);
  background: transparent;
}
.vb-ec-add-btn-icon { width: 16px; height: 16px; }

/* Save state indicator */
.vb-ec-savestate {
  font-size: 12px;
  color: var(--text-dim);
  margin-right: 8px;
  white-space: nowrap;
}
.vb-ec-savestate.is-saving { color: #f59e0b; }
.vb-ec-savestate.is-saved { color: #22c55e; }
.vb-ec-savestate.is-error { color: #ef4444; }

/* Mobile */
@media (max-width: 640px) {
  .vb-ec-table-head,
  .vb-ec-table-row {
    grid-template-columns: 1fr 80px 40px;
  }
  .vb-ec-table-head > :nth-child(3),
  .vb-ec-table-row > :nth-child(3) {
    display: none;
  }
  .vb-ec-editor-head { gap: 10px; padding-bottom: 14px; margin-bottom: 16px; }
  .vb-ec-name-input { font-size: 17px; }
  .vb-ec-block-head { padding: 14px 16px; }
  .vb-ec-block-body { padding: 4px 16px 18px; }
  .vb-ec-editor-actions { width: 100%; justify-content: flex-end; }
}

/* Back-to-server-list link above the KONFIGURATION header on dashboard-bot,
   and the matching "Zurück zum Bot-Dashboard" on restore-bot. Both pages
   load this stylesheet, so the rule is shared.
   Kept deliberately subtle: small font, muted color, no chevron emphasis —
   it's a navigational hint, not a CTA. The margin-bottom matches the
   rhythm of subtitle→next-module (~28px) so the back-link reads as its
   own row in the vertical spacing, not as glued to the eyebrow below. */
.vb-back-link,
.rb-back {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  color: var(--text-muted);
  text-decoration: none;
  font-size: 12.5px;
  font-weight: 500;
  letter-spacing: 0.01em;
  line-height: 1.2;
  margin: 0 0 28px;
  opacity: 0.78;
  transition: color .15s, opacity .15s, transform .15s;
}
.vb-back-link[hidden] { display: none; }
.vb-back-link:hover,
.rb-back:hover {
  color: var(--orange);
  opacity: 1;
  transform: translateX(-2px);
}
.vb-back-link svg,
.rb-back svg {
  flex-shrink: 0;
  width: 11px;
  height: 11px;
  opacity: 0.9;
}

/* ───── DEVCON_VB_MODE_v1 — picker/detail-mode visibility ─────
   Inline <head> script sets html.vb-picker-mode or html.vb-detail-mode
   before first paint. CSS controls which UI pieces show on which mode
   so the user never sees the wrong layout flash. */
html.vb-picker-mode #vbModuleBar,
html.vb-picker-mode #vbQuickActions,
html.vb-picker-mode #vbGuildStats,
html.vb-picker-mode #vbBackLink {
  display: none !important;
}
/* Picker-mode greeting is invisible until renderServerPicker() rewrites
   the title from "-'s Bot" to "Wähle einen Server" (avoids text flash).
   JS adds `vb-picker-ready` to <html> after the rewrite. */
html.vb-picker-mode .vb-greeting { visibility: hidden; }
html.vb-picker-mode.vb-picker-ready .vb-greeting { visibility: visible; }

/* Skeleton-Tile pulse on Guild-Stats values while body.dc-loading is set */
body.dc-loading .vb-gs-tile-value { animation: dc-skel-pulse 1.6s ease-in-out infinite; }

/* ───── DEVCON_VB_VARS_v1 — "Verfügbare Variablen" link + modal ─────
   Renders a small top-right link above text inputs that, when clicked,
   opens a centered popup with the available {token} placeholders. */
/* The label-row is a plain block whose height is whatever the
   .dash-modal-label naturally is — the "Verfügbare Variablen" pill
   floats over the top-right and does not contribute to the row's
   height. Without this the flex container would grow to fit the pill's
   own font/line-height and the gap below the row would be visibly
   bigger than a bare label's. */
/* Match `.dash-modal-label` rendering exactly: the inner label inherits
   the body's line-height so it has the same height and bottom-gap as a
   bare label elsewhere in the modal. The pill is absolutely positioned
   so it can't push the row taller. */
.vb-field-label-row {
  display: block;
  position: relative;
}
.vb-field-label-row .dash-modal-label { margin: 0 0 6px; }
.vb-vars-btn {
  position: absolute; top: 0; right: 0;
  background: transparent;
  border: 0;
  color: var(--text-muted);
  font: inherit; font-size: 11px; font-weight: 500;
  line-height: 1;
  padding: 0;
  cursor: pointer; transition: color .15s;
  white-space: nowrap;
}
.vb-vars-btn:hover { color: var(--orange); }

.vb-vars-modal-bg {
  position: fixed; inset: 0; z-index: 2000;
  background: rgba(0,0,0,0.55); backdrop-filter: blur(2px);
  display: none; align-items: center; justify-content: center;
  padding: 24px;
}
.vb-vars-modal-bg.rb-open { display: flex; }
.vb-vars-modal {
  background: #15161a; border: 1px solid var(--border);
  border-radius: 14px; max-width: 540px; width: 100%;
  max-height: 80vh; display: flex; flex-direction: column;
  box-shadow: 0 24px 60px rgba(0,0,0,0.5);
}
.vb-vars-modal-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 18px 22px 8px;
}
.vb-vars-modal-head h3 { margin: 0; font-size: 16px; }
/* .vb-vars-modal-close dimensional + hover behaviour inherited from the
   unified .dash-modal-close rule above (DEVCON_GLOBAL_CLOSE_v1). */
.vb-vars-modal-hint {
  margin: 12px 22px 8px; font-size: 12px; color: var(--text-muted);
}
.vb-vars-modal-body {
  padding: 4px 22px 22px; overflow-y: auto;
}
.vb-vars-row {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 12px; margin: 4px 0;
  border: 1px solid var(--border); border-radius: 10px;
  cursor: pointer; transition: all .15s;
  background: rgba(255,255,255,0.015);
}
.vb-vars-row:hover { border-color: var(--orange); background: rgba(255,138,34,0.04); }
.vb-vars-row--copied { background: rgba(74,222,128,0.12); border-color: #4ade80; }
.vb-vars-token {
  background: rgba(255,138,34,0.12); color: var(--orange);
  padding: 4px 10px; border-radius: 6px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12px; font-weight: 600; line-height: 1.4;
  flex-shrink: 0;
  display: inline-flex; align-items: center;
}
.vb-vars-desc {
  font-size: 13px; color: var(--text); line-height: 1.4;
  flex: 1; min-width: 0;
}

/* ───── DEVCON_MOD_EXPANSION_v1 — AutoMod cards + Restricted channels ───── */
.vb-am-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(380px, 1fr)); gap: 14px; margin-top: 14px; }
.vb-am-rule { background: rgba(255,255,255,0.02); border: 1px solid var(--border); border-radius: 12px; padding: 14px 16px; }
.vb-am-rule-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 8px; }
.vb-am-rule-title { margin: 0 0 4px; font-size: 14px; font-weight: 600; color: var(--text); }
.vb-am-rule-desc { margin: 0; font-size: 12px; color: var(--text-muted); line-height: 1.5; }
.vb-am-rule-cfg { display: grid; grid-template-columns: 1fr 1fr; gap: 10px 12px; padding-top: 10px; border-top: 1px solid var(--border); }
.vb-am-rule-cfg--disabled { opacity: 0.35; pointer-events: none; }
.vb-am-rule-cfg-row { display: flex; flex-direction: column; gap: 4px; }
.vb-am-rule-cfg-row .dash-modal-label { margin: 0; font-size: 11px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-muted); }
.vb-am-rule-cfg-row .dash-modal-input { padding: 6px 10px; font-size: 13px; }

/* Anti-nuke rules: same look but full-width since they have more config */
.vb-am-rule .vb-am-rule-cfg { grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); }

/* Slash-command reference grid */
.vb-cmd-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 10px; margin-top: 12px; }
.vb-cmd-card { display: flex; align-items: center; gap: 12px; padding: 10px 14px; background: rgba(255,255,255,0.02); border: 1px solid var(--border); border-radius: 10px; transition: border-color .15s; }
.vb-cmd-card:hover { border-color: var(--orange); }
.vb-cmd-name { background: rgba(255,138,34,0.12); color: var(--orange); padding: 3px 9px; border-radius: 5px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; font-weight: 600; flex-shrink: 0; }
.vb-cmd-desc { font-size: 12px; color: var(--text); line-height: 1.4; }

/* Modal backdrop for restricted-channel popup */
.vb-modal-backdrop { position: fixed; inset: 0; background: rgba(0,0,0,0.55); z-index: 2000; display: flex; align-items: center; justify-content: center; padding: 24px; backdrop-filter: blur(2px); }
.vb-modal { background: #15161a; border: 1px solid var(--border); border-radius: 14px; width: 100%; padding: 22px; box-shadow: 0 24px 60px rgba(0,0,0,0.5); }

/* ───── DEVCON_LEVELS_EXPANSION_v1 — XP-Rate + Pills + Rank-Card ───── */
.vb-xp-rate-bar { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; }
.vb-xp-rate-btn {
  background: rgba(255,255,255,0.03); border: 1px solid var(--border);
  color: var(--text); padding: 8px 18px; border-radius: 999px;
  font-weight: 600; font-size: 13px; cursor: pointer; transition: all .15s;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}
.vb-xp-rate-btn:hover { border-color: var(--orange); color: var(--orange); }
.vb-xp-rate-btn.is-active { background: var(--orange); color: #0a0a0a; border-color: var(--orange); }

.vb-pills-bar { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.vb-pill {
  background: rgba(255,255,255,0.03); border: 1px solid var(--border);
  color: var(--text-muted); padding: 7px 16px; border-radius: 999px;
  font-size: 12.5px; font-weight: 500; cursor: pointer; transition: all .15s;
}
.vb-pill:hover { border-color: var(--text-muted); color: var(--text); }
.vb-pill.is-active { background: rgba(255,138,34,0.12); border-color: var(--orange); color: var(--orange); }

/* Rank-card preview */
.vb-rankcard-preview {
  --rc-accent: #F58A20;
  display: flex; align-items: center; gap: 18px;
  background: linear-gradient(135deg, #1a1c20 0%, #15171a 100%);
  border: 1px solid var(--border); border-radius: 14px;
  padding: 20px 24px; margin-top: 12px;
  position: relative; overflow: hidden;
}
.vb-rankcard-preview::before {
  content: ''; position: absolute; inset: 0;
  background: radial-gradient(circle at top right, var(--rc-accent) 0%, transparent 40%);
  opacity: 0.18; pointer-events: none;
}
.vb-rankcard-avatar {
  width: 64px; height: 64px; border-radius: 50%;
  background: linear-gradient(135deg, var(--rc-accent), #ff6a00);
  display: flex; align-items: center; justify-content: center;
  font-size: 28px; font-weight: 700; color: #0a0a0a;
  flex-shrink: 0; border: 3px solid var(--rc-accent);
}
.vb-rankcard-body { flex: 1; min-width: 0; position: relative; z-index: 1; }
.vb-rankcard-name { font-size: 18px; font-weight: 600; color: var(--text); }
.vb-rankcard-rank { font-size: 11px; color: var(--text-muted); letter-spacing: 0.04em; margin: 2px 0 8px; }
.vb-rankcard-rank strong { color: var(--rc-accent); font-size: 13px; }
.vb-rankcard-xp { font-size: 12px; color: var(--text-muted); margin-bottom: 4px; font-variant-numeric: tabular-nums; }
.vb-rankcard-bar { height: 6px; background: rgba(255,255,255,0.06); border-radius: 3px; overflow: hidden; }
.vb-rankcard-bar span { display: block; height: 100%; background: var(--rc-accent); transition: width .3s ease; }

/* ───── DEVCON_CC_ACTIONS_v1 — Multi-action editor in custom-commands modal ───── */
.vb-cc-actions-list { display: flex; flex-direction: column; gap: 10px; }
.vb-cc-act-card { background: rgba(255,255,255,0.025); border: 1px solid var(--border); border-radius: 10px; padding: 12px 14px; }
.vb-cc-act-head { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.vb-cc-act-head strong { font-size: 12px; color: var(--text-muted); white-space: nowrap; }
.vb-cc-act-type { flex: 1; min-width: 0; }
.vb-cc-act-del { background: transparent; border: 1px solid var(--border); color: var(--text-muted); width: 28px; height: 28px; border-radius: 6px; cursor: pointer; font-size: 16px; line-height: 1; padding: 0; flex-shrink: 0; }
.vb-cc-act-del:hover { border-color: #f87171; color: #f87171; }
.vb-cc-act-body label { font-size: 11px; }
.vb-cc-advanced summary::-webkit-details-marker { display: none; }
.vb-cc-advanced summary::before { content: '▸ '; color: var(--orange); margin-right: 4px; }
.vb-cc-advanced[open] summary::before { content: '▾ '; }

/* ───── DEVCON_STARBOARDS_v1 + AUDIT_LOG_v1 ───── */
.vb-al-events { display: grid; grid-template-columns: 1fr; gap: 6px; margin-top: 8px; }
.vb-al-event-row { display: grid; grid-template-columns: 200px 1fr; gap: 12px; align-items: center; padding: 6px 0; }
.vb-al-event-label { font-size: 13px; color: var(--text); }
.vb-al-event-channel { font-size: 12px; padding: 6px 10px; }

/* ───── Extended command cards with usage examples (DEVCON_MOD_CMDS_v2) ───── */
.vb-cmd-grid--rich { grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); }
.vb-cmd-card--rich { flex-direction: column; align-items: stretch; gap: 8px; padding: 12px 14px; }
.vb-cmd-card--rich .vb-cmd-row { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.vb-cmd-card--rich .vb-cmd-name { background: rgba(255,138,34,0.15); color: var(--orange); }
.vb-cmd-card--rich .vb-cmd-desc { font-size: 12.5px; line-height: 1.4; }
.vb-cmd-usages { display: flex; flex-direction: column; gap: 4px; margin-top: 4px; padding-top: 8px; border-top: 1px dashed var(--border); }
.vb-cmd-usages code { font-size: 11px; color: var(--text-muted); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; padding: 2px 6px; background: rgba(255,255,255,0.02); border-radius: 4px; word-break: break-all; }

/* Built-in command cards in Custom Commands tab — highlight when enabled */
.vb-builtin-card { transition: border-color .15s, background .15s; }
.vb-builtin-card.is-on { border-color: rgba(74,222,128,0.4); background: rgba(74,222,128,0.04); }
.vb-builtin-card.is-on .vb-cmd-name { background: rgba(74,222,128,0.18); color: #4ade80; }

/* Permission badges on command cards (DEVCON_CMD_PERMS_v1) */
.vb-cmd-perm {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  flex-shrink: 0;
  margin-left: auto;
}
.vb-cmd-perm--mod    { background: rgba(255,138,34,0.15); color: var(--orange); border: 1px solid rgba(255,138,34,0.3); }
.vb-cmd-perm--admin  { background: rgba(248,113,113,0.15); color: #f87171; border: 1px solid rgba(248,113,113,0.3); }
.vb-cmd-perm--public { background: rgba(74,222,128,0.15); color: #4ade80; border: 1px solid rgba(74,222,128,0.3); }

/* ─── Global Bot Settings tab (DEVCON_BOT_SETTINGS_v1) ─────────────── */
/* (The Einstellungen entry-point lives in the header quick-actions stack,
   not in the module-bar — see .vb-qa-btn--settings.) */

/* Discord-style embed preview */
.vb-embed-preview {
  --ec: #F58A20;
  display: flex;
  background: #2b2d31;
  border-radius: 6px;
  overflow: hidden;
  min-height: 72px;
  max-width: 480px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.18);
}
.vb-embed-preview-bar {
  background: var(--ec);
  width: 4px;
  flex-shrink: 0;
  transition: background 0.18s ease;
}
.vb-embed-preview-body {
  padding: 10px 14px;
  flex: 1;
  min-width: 0;
}
.vb-embed-preview-title {
  color: #fff;
  font-size: 14px;
  font-weight: 600;
  margin-bottom: 4px;
}
.vb-embed-preview-desc {
  color: #d2d5db;
  font-size: 13px;
  line-height: 1.4;
}

/* Settings section optgroup styling */
.dash-modal-input optgroup {
  background: #1f2024;
  color: var(--text-muted);
  font-weight: 600;
}
.dash-modal-input optgroup option {
  color: var(--text);
  font-weight: 400;
}

/* ─── Social Notifications module (DEVCON_SOCIAL_v1) ─────────────── */

/* Platform-subtab row — grid that wraps over multiple lines */
.vb-subtabs--social {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 14px 0 20px;
}
.vb-subtabs--social .vb-subtab {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px;
}
.vb-social-tab-icon {
  font-size: 18px;
  line-height: 1;
  width: 18px;
  height: 18px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
}
.vb-social-tab-icon svg {
  width: 100%;
  height: 100%;
  display: block;
}

/* Plattform-Zelle in der Social-Übersicht-Tabelle: Icon + Label nebeneinander. */
.vb-soc-row-platform {
  display: flex;
  align-items: center;
  gap: 8px;
}

/* Stream/Post-Historie im View-Modal (Auge-Icon Aktion). */
.vb-soc-hist-row {
  display: flex;
  gap: 12px;
  padding: 10px 0;
  border-bottom: 1px solid rgba(255,255,255,.06);
}
.vb-soc-hist-row:last-child { border-bottom: none; }
.vb-soc-hist-thumb {
  width: 80px;
  height: 45px;
  object-fit: cover;
  border-radius: 4px;
  flex-shrink: 0;
}
.vb-soc-hist-body { flex: 1; min-width: 0; }
.vb-soc-hist-title {
  font-weight: 600;
  font-size: 13px;
  color: var(--text-bright);
  margin-bottom: 4px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.vb-soc-hist-row-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  font-size: 12px;
  color: var(--text-muted);
}
.vb-soc-hist-meta { white-space: nowrap; }
.vb-soc-hist-link {
  display: inline-block;
  margin-top: 6px;
  font-size: 12px;
  color: var(--orange);
  text-decoration: none;
}
.vb-soc-hist-link:hover { text-decoration: underline; }

/* Notify-Typ-Picker im Benachrichtigungen-Subtab (zwischen Channel + Nachricht). */
.vb-soc-type-pills {
  display: inline-flex;
  gap: 4px;
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: 8px;
  padding: 3px;
  margin-top: 4px;
}
.vb-soc-type-pill {
  appearance: none;
  background: transparent;
  border: 0;
  padding: 6px 14px;
  border-radius: 6px;
  font-size: 12px;
  font-weight: 500;
  color: var(--text-dim);
  cursor: pointer;
  transition: background 0.12s ease, color 0.12s ease;
}
.vb-soc-type-pill:hover:not(.is-active):not(:disabled) {
  color: var(--text-bright);
  background: rgba(255,255,255,0.04);
}
.vb-soc-type-pill.is-active {
  background: rgba(255,138,34,0.12);
  color: var(--orange);
}
.vb-soc-type-pills.is-readonly .vb-soc-type-pill {
  cursor: default;
  opacity: 0.75;
}
.vb-soc-type-pill:disabled { cursor: default; }

/* Per-Plattform Card-Head im Benachrichtigungen-Subtab. */
.vb-soc-notif-head {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 12px;
}
.vb-soc-notif-head h3 {
  margin: 0;
  font-size: 16px;
  font-weight: 600;
}
.vb-soc-notif-head .vb-social-tab-icon {
  font-size: 22px;
  width: 22px;
  height: 22px;
}

/* Plattform-Picker (Step 1 vom Create-Modal): 3-Spalten-Grid mit großen,
   anklickbaren Karten. Reuses .dash-modal styling. */
.vb-soc-picker-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
  margin-top: 12px;
}
.vb-soc-picker-card {
  --soc-color: var(--orange);  /* Fallback; per-card via inline style override */
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 18px 8px;
  background: rgba(255,255,255,0.025);
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: 10px;
  color: var(--text-bright);
  cursor: pointer;
  transition: background 0.12s ease, border-color 0.12s ease, transform 0.12s ease, color 0.12s ease;
}
.vb-soc-picker-card:hover {
  background: color-mix(in srgb, var(--soc-color) 8%, transparent);
  border-color: color-mix(in srgb, var(--soc-color) 55%, transparent);
  color: var(--soc-color);
  transform: translateY(-1px);
}
.vb-soc-picker-icon {
  font-size: 28px;
  width: 28px;
  height: 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.vb-soc-picker-icon svg { width: 100%; height: 100%; display: block; }
.vb-soc-picker-label {
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.2px;
}
/* Subscription-Count pro Plattform — ersetzt den alten enabled-Dot. */
.vb-social-tab-count {
  font-size: 12px;
  opacity: 0.55;
  font-variant-numeric: tabular-nums;
  margin-left: 2px;
}
.vb-subtab.is-active .vb-social-tab-count {
  opacity: 0.85;
}
/* Card-Icon ebenfalls auf feste Box damit alle gleich groß rendern. */
.vb-social-card-icon svg {
  width: 24px;
  height: 24px;
  display: block;
}

/* Section-header with title + action button on one row */
.vb-section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 8px;
}

/* Subscription card */
.vb-social-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 12px;
}
.vb-social-card {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  background: rgba(255,255,255,0.025);
  border: 1px solid rgba(255,255,255,0.06);
  border-radius: 8px;
  transition: background 0.12s ease, border-color 0.12s ease;
}
.vb-social-card:hover {
  background: rgba(255,255,255,0.04);
  border-color: rgba(255,255,255,0.12);
}
.vb-social-card.is-off {
  opacity: 0.55;
}
.vb-social-card-icon {
  font-size: 24px;
  width: 36px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
  background: rgba(255,255,255,0.04);
  flex-shrink: 0;
}
.vb-social-card-body {
  flex: 1;
  min-width: 0;
}
.vb-social-card-title {
  font-weight: 600;
  font-size: 14px;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.vb-social-card-meta {
  font-size: 12px;
  color: var(--text-muted);
  margin-top: 2px;
}
.vb-social-card-meta code {
  background: rgba(255,255,255,0.06);
  padding: 1px 5px;
  border-radius: 4px;
  font-size: 11px;
  font-family: ui-monospace, monospace;
}

/* Live-stream options block inside the modal */
.vb-social-opts {
  margin-top: 16px;
  padding: 14px;
  background: rgba(255,138,34,0.05);
  border-radius: 8px;
  border-left: 3px solid var(--orange);
}
.vb-social-opts > h3 {
  margin: 0 0 12px;
  font-size: 14px;
  font-weight: 600;
  color: var(--text-bright);
}

/* Small icon-only button (edit/delete on cards) */
.vb-icon-btn {
  width: 32px;
  height: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 6px;
  background: transparent;
  border: 1px solid rgba(255,255,255,0.08);
  color: var(--text-muted);
  cursor: pointer;
  transition: background 0.12s ease, color 0.12s ease, border-color 0.12s ease;
  font-size: 14px;
}
.vb-icon-btn:hover {
  background: rgba(255,255,255,0.06);
  color: var(--text-bright);
  border-color: rgba(255,255,255,0.18);
}
.vb-icon-btn--danger:hover {
  background: rgba(240,71,71,0.12);
  color: #f87171;
  border-color: rgba(240,71,71,0.3);
}

/* Size variants for vb-switch */
.vb-switch--lg .vb-switch-slider {
  width: 44px;
  height: 24px;
}
.vb-switch--lg .vb-switch-label {
  font-size: 13px;
  font-weight: 600;
}
.vb-switch--sm .vb-switch-slider {
  width: 28px;
  height: 16px;
}
.vb-switch--sm .vb-switch-slider::after {
  width: 12px;
  height: 12px;
  top: 2px;
  left: 2px;
}
.vb-switch--sm input:checked + .vb-switch-slider::after { left: 14px; }
.vb-switch--sm .vb-switch-label { font-size: 11px; }

/* Variable-chips bar shown under message templates */
.vb-vars-hint {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
  margin-top: 6px;
  font-size: 11px;
  color: var(--text-muted);
}
.vb-var-chip {
  background: rgba(255,138,34,0.1);
  color: var(--orange);
  padding: 2px 8px;
  border-radius: 4px;
  font-family: ui-monospace, monospace;
  font-size: 11px;
  cursor: pointer;
  border: 1px solid rgba(255,138,34,0.2);
  transition: background 0.12s ease;
}
.vb-var-chip:hover {
  background: rgba(255,138,34,0.2);
}

/* Inline mention-chip row */
.vb-mention-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 6px;
}
.vb-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: 999px;
  font-size: 12px;
  color: var(--text-muted);
  cursor: pointer;
  transition: background 0.12s ease, color 0.12s ease;
}
.vb-chip:has(input:checked) {
  background: rgba(255,138,34,0.12);
  border-color: rgba(255,138,34,0.4);
  color: var(--orange);
}
.vb-chip input {
  margin: 0;
  width: 12px;
  height: 12px;
}

/* ─── Highlights + Sticky Roles modules (DEVCON_HIGHLIGHTS_STICKYROLES_v1) */

/* Compact stat-tile grid used on Highlights / Sticky-Roles stats blocks.
   Three tiles in a row, collapses to one column on mobile. */
.vb-stat-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
  margin-top: 8px;
}
.vb-stat-tile {
  background: rgba(255,255,255,0.035);
  border: 1px solid rgba(255,255,255,0.06);
  border-radius: 8px;
  padding: 14px 16px;
  text-align: center;
}
.vb-stat-num {
  font-size: 28px;
  font-weight: 700;
  color: var(--orange);
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.vb-stat-lbl {
  margin-top: 4px;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text-muted);
}
@media (max-width: 720px) {
  .vb-stat-grid { grid-template-columns: 1fr; }
}

/* ─── Suggestion stats — reuse the header `.vb-gs-tile` look 1:1 ───────
   Same neutral base, same right-side ghosted icon, same value+label.
   Per-status variants follow the `--online` / `--boost` recipe (subtle
   bg + border tint, value coloured, icon hue + bumped opacity on hover). */
/* Stat-Tile Row: spannt die volle Breite egal wie viele Tiles drin sind.
   grid-auto-flow:column + grid-auto-columns:1fr → jedes Tile teilt sich
   die volle Container-Breite gleichmäßig, kein „repeat(5)" mit leerer
   letzter Spalte wenn nur 4 Tiles. Mobile-Stages switchen via grid-
   template-columns + grid-auto-flow:row zurück auf wrap. */
.vb-stat-cards {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 8px;
  margin-top: 8px;
}
@media (max-width: 1100px) {
  .vb-stat-cards { grid-auto-flow: row; grid-auto-columns: auto; grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 720px) {
  .vb-stat-cards { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 480px) {
  .vb-stat-cards { grid-template-columns: 1fr; }
}

/* Semantic palette — Offen=grau, In Bearbeitung=gelb, Genehmigt=grün,
   Umgesetzt=orange (Brand), Abgelehnt=rot. */
.vb-gs-tile--sgopen        .vb-gs-tile-value { color: #9ca3af; }
.vb-gs-tile--sgopen        { border-color: rgba(156,163,175,.18); background: rgba(156,163,175,.04); }
.vb-gs-tile--sgopen:hover  { border-color: rgba(156,163,175,.35); }
.vb-gs-tile--sgopen        .vb-gs-tile-icon { color: #9ca3af; opacity: 0.14; }
.vb-gs-tile--sgopen:hover  .vb-gs-tile-icon { color: #9ca3af; opacity: 0.22; }

.vb-gs-tile--sgconsidered        .vb-gs-tile-value { color: #fbbf24; }
.vb-gs-tile--sgconsidered        { border-color: rgba(251,191,36,.18); background: rgba(251,191,36,.04); }
.vb-gs-tile--sgconsidered:hover  { border-color: rgba(251,191,36,.35); }
.vb-gs-tile--sgconsidered        .vb-gs-tile-icon { color: #fbbf24; opacity: 0.14; }
.vb-gs-tile--sgconsidered:hover  .vb-gs-tile-icon { color: #fbbf24; opacity: 0.22; }

.vb-gs-tile--sgapproved        .vb-gs-tile-value { color: #4ade80; }
.vb-gs-tile--sgapproved        { border-color: rgba(74,222,128,.18); background: rgba(74,222,128,.04); }
.vb-gs-tile--sgapproved:hover  { border-color: rgba(74,222,128,.35); }
.vb-gs-tile--sgapproved        .vb-gs-tile-icon { color: #4ade80; opacity: 0.14; }
.vb-gs-tile--sgapproved:hover  .vb-gs-tile-icon { color: #4ade80; opacity: 0.22; }

.vb-gs-tile--sgimplemented        .vb-gs-tile-value { color: var(--orange); }
.vb-gs-tile--sgimplemented        { border-color: rgba(255,138,34,.18); background: rgba(255,138,34,.04); }
.vb-gs-tile--sgimplemented:hover  { border-color: rgba(255,138,34,.35); }
.vb-gs-tile--sgimplemented        .vb-gs-tile-icon { color: var(--orange); opacity: 0.14; }
.vb-gs-tile--sgimplemented:hover  .vb-gs-tile-icon { color: var(--orange); opacity: 0.22; }

/* Invite-Tracking Stat-Tile Varianten (5 Stück). */
.vb-gs-tile--ittotal        .vb-gs-tile-value { color: #60a5fa; }
.vb-gs-tile--ittotal        { border-color: rgba(96,165,250,.18); background: rgba(96,165,250,.04); }
.vb-gs-tile--ittotal:hover  { border-color: rgba(96,165,250,.35); }
.vb-gs-tile--ittotal        .vb-gs-tile-icon { color: #60a5fa; opacity: 0.14; }
.vb-gs-tile--ittotal:hover  .vb-gs-tile-icon { color: #60a5fa; opacity: 0.22; }

.vb-gs-tile--itactive        .vb-gs-tile-value { color: #22c55e; }
.vb-gs-tile--itactive        { border-color: rgba(34,197,94,.18); background: rgba(34,197,94,.04); }
.vb-gs-tile--itactive:hover  { border-color: rgba(34,197,94,.35); }
.vb-gs-tile--itactive        .vb-gs-tile-icon { color: #22c55e; opacity: 0.14; }
.vb-gs-tile--itactive:hover  .vb-gs-tile-icon { color: #22c55e; opacity: 0.22; }

.vb-gs-tile--itleft        .vb-gs-tile-value { color: #ef4444; }
.vb-gs-tile--itleft        { border-color: rgba(239,68,68,.18); background: rgba(239,68,68,.04); }
.vb-gs-tile--itleft:hover  { border-color: rgba(239,68,68,.35); }
.vb-gs-tile--itleft        .vb-gs-tile-icon { color: #ef4444; opacity: 0.14; }
.vb-gs-tile--itleft:hover  .vb-gs-tile-icon { color: #ef4444; opacity: 0.22; }

.vb-gs-tile--itcodes        .vb-gs-tile-value { color: var(--orange); }
.vb-gs-tile--itcodes        { border-color: rgba(255,138,34,.18); background: rgba(255,138,34,.04); }
.vb-gs-tile--itcodes:hover  { border-color: rgba(255,138,34,.35); }
.vb-gs-tile--itcodes        .vb-gs-tile-icon { color: var(--orange); opacity: 0.14; }
.vb-gs-tile--itcodes:hover  .vb-gs-tile-icon { color: var(--orange); opacity: 0.22; }

.vb-gs-tile--itinviters        .vb-gs-tile-value { color: #c084fc; }
.vb-gs-tile--itinviters        { border-color: rgba(192,132,252,.18); background: rgba(192,132,252,.04); }
.vb-gs-tile--itinviters:hover  { border-color: rgba(192,132,252,.35); }
.vb-gs-tile--itinviters        .vb-gs-tile-icon { color: #c084fc; opacity: 0.14; }
.vb-gs-tile--itinviters:hover  .vb-gs-tile-icon { color: #c084fc; opacity: 0.22; }

/* Birthdays Stat-Tile Varianten (4 Stück). */
.vb-gs-tile--bttotal         .vb-gs-tile-value { color: #60a5fa; }
.vb-gs-tile--bttotal         { border-color: rgba(96,165,250,.18); background: rgba(96,165,250,.04); }
.vb-gs-tile--bttotal:hover   { border-color: rgba(96,165,250,.35); }
.vb-gs-tile--bttotal         .vb-gs-tile-icon { color: #60a5fa; opacity: 0.14; }
.vb-gs-tile--bttotal:hover   .vb-gs-tile-icon { color: #60a5fa; opacity: 0.22; }

.vb-gs-tile--bttoday         .vb-gs-tile-value { color: #fbbf24; }
.vb-gs-tile--bttoday         { border-color: rgba(251,191,36,.18); background: rgba(251,191,36,.04); }
.vb-gs-tile--bttoday:hover   { border-color: rgba(251,191,36,.35); }
.vb-gs-tile--bttoday         .vb-gs-tile-icon { color: #fbbf24; opacity: 0.14; }
.vb-gs-tile--bttoday:hover   .vb-gs-tile-icon { color: #fbbf24; opacity: 0.22; }

.vb-gs-tile--btmonth         .vb-gs-tile-value { color: #c084fc; }
.vb-gs-tile--btmonth         { border-color: rgba(192,132,252,.18); background: rgba(192,132,252,.04); }
.vb-gs-tile--btmonth:hover   { border-color: rgba(192,132,252,.35); }
.vb-gs-tile--btmonth         .vb-gs-tile-icon { color: #c084fc; opacity: 0.14; }
.vb-gs-tile--btmonth:hover   .vb-gs-tile-icon { color: #c084fc; opacity: 0.22; }

.vb-gs-tile--btupcoming        .vb-gs-tile-value { color: #22c55e; }
.vb-gs-tile--btupcoming        { border-color: rgba(34,197,94,.18); background: rgba(34,197,94,.04); }
.vb-gs-tile--btupcoming:hover  { border-color: rgba(34,197,94,.35); }
.vb-gs-tile--btupcoming        .vb-gs-tile-icon { color: #22c55e; opacity: 0.14; }
.vb-gs-tile--btupcoming:hover  .vb-gs-tile-icon { color: #22c55e; opacity: 0.22; }

/* Highlights Stat-Tile Varianten — aktive Mitglieder=blau, Keywords=Brand
   orange, Ø Keywords/Member=violett. Follows [[stat-tiles-pattern]]. */
.vb-gs-tile--hlusers        .vb-gs-tile-value { color: #60a5fa; }
.vb-gs-tile--hlusers        { border-color: rgba(96,165,250,.18); background: rgba(96,165,250,.04); }
.vb-gs-tile--hlusers:hover  { border-color: rgba(96,165,250,.35); }
.vb-gs-tile--hlusers        .vb-gs-tile-icon { color: #60a5fa; opacity: 0.14; }
.vb-gs-tile--hlusers:hover  .vb-gs-tile-icon { color: #60a5fa; opacity: 0.22; }

.vb-gs-tile--hlkeywords        .vb-gs-tile-value { color: var(--orange); }
.vb-gs-tile--hlkeywords        { border-color: rgba(255,138,34,.18); background: rgba(255,138,34,.04); }
.vb-gs-tile--hlkeywords:hover  { border-color: rgba(255,138,34,.35); }
.vb-gs-tile--hlkeywords        .vb-gs-tile-icon { color: var(--orange); opacity: 0.14; }
.vb-gs-tile--hlkeywords:hover  .vb-gs-tile-icon { color: var(--orange); opacity: 0.22; }

.vb-gs-tile--hlavg        .vb-gs-tile-value { color: #a78bfa; }
.vb-gs-tile--hlavg        { border-color: rgba(167,139,250,.18); background: rgba(167,139,250,.04); }
.vb-gs-tile--hlavg:hover  { border-color: rgba(167,139,250,.35); }
.vb-gs-tile--hlavg        .vb-gs-tile-icon { color: #a78bfa; opacity: 0.14; }
.vb-gs-tile--hlavg:hover  .vb-gs-tile-icon { color: #a78bfa; opacity: 0.22; }

.vb-gs-tile--hlmod        .vb-gs-tile-value { color: #f472b6; }
.vb-gs-tile--hlmod        { border-color: rgba(244,114,182,.18); background: rgba(244,114,182,.04); }
.vb-gs-tile--hlmod:hover  { border-color: rgba(244,114,182,.35); }
.vb-gs-tile--hlmod        .vb-gs-tile-icon { color: #f472b6; opacity: 0.14; }
.vb-gs-tile--hlmod:hover  .vb-gs-tile-icon { color: #f472b6; opacity: 0.22; }

.vb-gs-tile--sgdenied        .vb-gs-tile-value { color: #ef4444; }
.vb-gs-tile--sgdenied        { border-color: rgba(239,68,68,.18); background: rgba(239,68,68,.04); }
.vb-gs-tile--sgdenied:hover  { border-color: rgba(239,68,68,.35); }
.vb-gs-tile--sgdenied        .vb-gs-tile-icon { color: #ef4444; opacity: 0.14; }
.vb-gs-tile--sgdenied:hover  .vb-gs-tile-icon { color: #ef4444; opacity: 0.22; }

/* Sticky-Roles stat tiles — getrackte Mitglieder=grau, Snapshots=Brand orange,
   Restores=grün. Follows [[stat-tiles-pattern]]. */
.vb-gs-tile--srtracked        .vb-gs-tile-value { color: #9ca3af; }
.vb-gs-tile--srtracked        { border-color: rgba(156,163,175,.18); background: rgba(156,163,175,.04); }
.vb-gs-tile--srtracked:hover  { border-color: rgba(156,163,175,.35); }
.vb-gs-tile--srtracked        .vb-gs-tile-icon { color: #9ca3af; opacity: 0.14; }
.vb-gs-tile--srtracked:hover  .vb-gs-tile-icon { color: #9ca3af; opacity: 0.22; }

.vb-gs-tile--srsnapshots        .vb-gs-tile-value { color: var(--orange); }
.vb-gs-tile--srsnapshots        { border-color: rgba(255,138,34,.18); background: rgba(255,138,34,.04); }
.vb-gs-tile--srsnapshots:hover  { border-color: rgba(255,138,34,.35); }
.vb-gs-tile--srsnapshots        .vb-gs-tile-icon { color: var(--orange); opacity: 0.14; }
.vb-gs-tile--srsnapshots:hover  .vb-gs-tile-icon { color: var(--orange); opacity: 0.22; }

.vb-gs-tile--srrestores        .vb-gs-tile-value { color: #4ade80; }
.vb-gs-tile--srrestores        { border-color: rgba(74,222,128,.18); background: rgba(74,222,128,.04); }
.vb-gs-tile--srrestores:hover  { border-color: rgba(74,222,128,.35); }
.vb-gs-tile--srrestores        .vb-gs-tile-icon { color: #4ade80; opacity: 0.14; }
.vb-gs-tile--srrestores:hover  .vb-gs-tile-icon { color: #4ade80; opacity: 0.22; }

/* Filter-dropdown bei "Letzte Vorschläge" — `width: 100%` aus
   .dash-modal-input würde es auf Container-Breite ziehen. Auf max-content
   begrenzen → so breit wie das längste Option-Label. */
.vb-sg-filter {
  width: max-content !important;
  flex: 0 0 auto !important;
}

/* Generic vertical command-list (used by Highlights to show available
   member-side slash commands). Each card is rendered by cmdCard(). */
.vb-cmd-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 8px;
}

/* ─── Sprint 1 quickwins (DEVCON_SPRINT1_v1) ───────────────────────── */

/* Prefix-chip strip for Settings → multi-prefix UI */
.vb-prefix-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 4px;
  min-height: 32px;
  padding: 4px;
  background: rgba(255,255,255,0.02);
  border: 1px dashed rgba(255,255,255,0.08);
  border-radius: 6px;
}
.vb-prefix-row:empty::before {
  content: 'Noch keine zusätzlichen Präfixe.';
  color: var(--text-dim);
  font-size: 12px;
  padding: 4px 8px;
}
/* Global override — `.dash-btn` sets display:inline-flex which beats the
   UA's `[hidden] { display: none }` rule on specificity. Force hidden
   wins so `el.hidden = true` actually hides .dash-btn elements. */
.dash-btn[hidden] { display: none !important; }

/* DEVCON_SR_GDPR_v1 — per-user snapshot deletion row in Sticky Roles.
   Input + two buttons all the same height, no flex:1 stretching from
   the global .dash-btn default. "Alle löschen" zone is visually
   separated with a top border and uses secondary styling so it's less
   loud than the per-user (red) action. */
.vb-sr-userrow {
  display: flex;
  gap: 8px;
  align-items: stretch;
  flex-wrap: wrap;
  margin-top: 6px;
}
.vb-sr-userrow .dash-modal-input {
  flex: 1 1 240px;
  max-width: 320px;
  margin: 0;
  font-family: ui-monospace, monospace;
}
.vb-sr-userrow .dash-btn {
  flex: 0 0 auto;
  padding: 0 18px;
  min-height: 42px;
}
.vb-sr-purgeall {
  display: flex;
  margin-top: 6px;
}
.vb-sr-purgeall .dash-btn {
  flex: 0 0 auto;
  padding: 0 18px;
  min-height: 42px;
}
/* Red dashed outline — signals "danger but rarely needed" without the
   solid-red shout of a primary destructive action. Mirrors the dashed
   accent pattern used elsewhere for opt-in heavy actions. */
.vb-sr-purgeall .dash-btn.dash-btn-danger {
  background: transparent;
  border: 1px dashed rgba(248, 113, 113, 0.55);
  color: #f87171;
}
.vb-sr-purgeall .dash-btn.dash-btn-danger:hover {
  background: rgba(248, 113, 113, 0.08);
  border-color: rgba(248, 113, 113, 0.85);
  color: #fca5a5;
}
.vb-sr-purgeall .dash-modal-help { margin-top: 8px; }

/* DEVCON_BS_PREFIX_TOG_v1 — six toggleable boxes for picking which
   command prefixes the bot listens to. Replaces the old free-form
   input + chip list since 99% of guilds just want one of {!, ?, ., $,
   ;, >}. Active state is solid orange to match other "on" affordances. */
.vb-prefix-toggles {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 6px;
}
.vb-prefix-tog {
  display: inline-flex;
  align-items: center; justify-content: center;
  width: 44px; height: 40px;
  padding: 0;
  background: rgba(255,255,255,0.03);
  border: 1px solid rgba(255,255,255,0.10);
  border-radius: 8px;
  cursor: pointer;
  transition: background .12s, border-color .12s, color .12s;
}
.vb-prefix-tog code {
  font-family: ui-monospace, monospace;
  font-size: 16px;
  font-weight: 600;
  color: var(--text-dim);
  background: transparent;
}
.vb-prefix-tog:hover {
  background: rgba(255,255,255,0.06);
  border-color: rgba(255,140,26,0.35);
}
.vb-prefix-tog:hover code { color: var(--text); }
.vb-prefix-tog.is-on {
  background: rgba(255,138,34,0.16);
  border-color: rgba(255,138,34,0.55);
}
.vb-prefix-tog.is-on code { color: var(--orange); }

.vb-prefix-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 4px 4px 10px;
  background: rgba(255,138,34,0.12);
  border: 1px solid rgba(255,138,34,0.3);
  border-radius: 6px;
  font-family: ui-monospace, monospace;
}
.vb-prefix-chip code {
  background: transparent;
  color: var(--orange);
  font-weight: 600;
}
.vb-prefix-chip button {
  background: rgba(255,255,255,0.08);
  border: 0;
  color: var(--text-muted);
  width: 20px;
  height: 20px;
  border-radius: 4px;
  cursor: pointer;
  font-size: 14px;
  line-height: 1;
}
.vb-prefix-chip button:hover { background: rgba(248,113,113,0.2); color: #f87171; }

/* Mod-Activity Highscores table */
.vb-highscores {
  width: 100%;
  border-collapse: collapse;
  font-size: 12px;
}
.vb-highscores th,
.vb-highscores td {
  text-align: left;
  padding: 8px 10px;
  border-bottom: 1px solid rgba(255,255,255,0.05);
}
.vb-highscores th {
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted);
  background: rgba(255,255,255,0.02);
}
.vb-highscores tbody tr:hover {
  background: rgba(255,138,34,0.04);
}
.vb-highscores td code {
  background: rgba(255,255,255,0.06);
  padding: 2px 6px;
  border-radius: 3px;
  font-size: 11px;
  font-family: ui-monospace, monospace;
}
.vb-highscores td:nth-child(3) {
  color: var(--orange);
  font-variant-numeric: tabular-nums;
}

/* Embed-Creator "Import" tile sits next to the "New embed" tile */
.vb-ec-import-card:hover {
  background: rgba(255,138,34,0.08) !important;
  border-color: rgba(255,138,34,0.4) !important;
  color: var(--orange) !important;
}

/* ─── WYSIWYG Inline Embed Editor (DEVCON_INLINE_EMBED_v1) ─────────── */
/* Flex-column with bounded height so the body scrolls when the embed list
   grows tall — header + footer stay pinned, body has its own scrollbar. */
.vb-ie-overlay .vb-ie-modal {
  max-width: 1100px;
  width: 95vw;
  max-height: 92vh;
  display: flex;
  flex-direction: column;
}
/* Generous padding on all sides + scrollable body so tall multi-embed
   stacks don't get clipped by the modal's overflow:hidden. */
.vb-ie-body {
  padding: 24px 28px;
  overflow-y: auto;
  flex: 1 1 auto;
  min-height: 0;
}
.vb-ie-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 10px;
}
.vb-ie-mode { margin: 0; flex-shrink: 0; }

/* Inline editable name — matches the main dashboard title pencil pattern */
.vb-ie-title {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  flex: 1 1 auto;
  min-width: 0;
  font-size: 18px;
  font-weight: 700;
  color: var(--text, #f2f3f5);
  line-height: 1.3;
}
.vb-ie-title-text {
  outline: none;
  border-radius: 4px;
  padding: 2px 6px;
  margin: 0 -6px;
  transition: background .12s, box-shadow .12s;
  cursor: text;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* When draft._name is empty, the visible text is the "Unbenannte Einbettung"
   placeholder — render it muted/italic to signal it's a stand-in. */
.vb-ie-title-text:not([contenteditable="true"]) {
  font-style: italic;
  color: var(--text-muted, #b5bac1);
  font-weight: 600;
}
.vb-ie-title-text[contenteditable="true"] {
  background: rgba(255,140,26,0.06);
  box-shadow: inset 0 0 0 1px rgba(255,140,26,0.45);
  font-style: normal;
  font-weight: 700;
  color: var(--text, #f2f3f5);
  white-space: normal;
  overflow: visible;
}
.vb-ie-title-text:hover:not([contenteditable="true"]) {
  background: rgba(255,255,255,0.04);
}
/* Naked pencil → naked green check. No border, no bg, no padding box.
   Hover: pencil = orange + 90° rotate; check = brighter green + rotate.
   Mirrors the global close-x / chip-rm conventions. */
.vb-ie-title-edit {
  flex: 0 0 auto;
  width: 22px; height: 22px;
  padding: 0;
  background: transparent !important;
  border: 0 !important;
  border-radius: 0;
  color: var(--text-muted, #b5bac1);
  cursor: pointer;
  display: inline-flex;
  align-items: center; justify-content: center;
  opacity: 0.7;
  transition: color .15s ease, transform .15s ease, opacity .15s ease;
}
.vb-ie-title-edit:hover {
  background: transparent !important;
  opacity: 1;
  color: var(--orange, #ff8c1a);
  transform: rotate(90deg);
}
/* Edit-mode swap: the pencil becomes a green check (commit). Same
   semantics on every editable modal title — see [[editable-modal-title]]. */
.vb-ie-title-edit.is-saving {
  opacity: 1;
  color: #4ade80;
}
.vb-ie-title-edit.is-saving:hover {
  color: #22c55e;
  transform: rotate(90deg);
}
.vb-ie-hint {
  font-size: 11px;
  color: var(--text-muted);
  margin: 0 0 14px;
  font-style: italic;
}

/* Canvas renders a Discord-style message: avatar + header + content + embed.
   Transparent background — inherits the modal's body color for visual unity.
   No inner padding — the body already provides generous left/right margin. */
.vb-ie-canvas {
  padding: 4px 0;
  background: transparent;
  border-radius: 0;
  min-height: 120px;
}
/* Discord message row — avatar left, body right */
.vb-ie-msg {
  display: grid;
  grid-template-columns: 40px 1fr;
  gap: 14px;
  align-items: flex-start;
}
.vb-ie-msg-avatar {
  width: 40px; height: 40px;
  border-radius: 50%;
  background: linear-gradient(135deg, #5865F2 0%, #7289DA 100%);
  display: flex; align-items: center; justify-content: center;
  font-weight: 700; color: #fff; font-size: 18px;
  overflow: hidden;
  flex: 0 0 40px;
}
.vb-ie-msg-avatar img { width: 100%; height: 100%; object-fit: cover; }
.vb-ie-msg-body {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;             /* uniform vertical rhythm between head / text / embed */
}
.vb-ie-msg-head {
  display: flex; align-items: center; gap: 8px;
  flex-wrap: wrap;
  width: 100%;
  max-width: 576px;        /* same cap as .vb-ie-msg-content below — keeps the
                              "Verfügbare Variablen" pill aligned with the
                              textarea's right edge, not the modal's right edge */
}
.vb-ie-msg-vars {
  margin-left: auto;
  flex: 0 0 auto;
}
.vb-ie-msg-name {
  font-weight: 600; font-size: 15px; color: #f2f3f5;
}
.vb-ie-msg-badge {
  display: inline-flex; align-items: center; gap: 3px;
  background: #5865F2; color: #fff;
  font-size: 9px; font-weight: 700; text-transform: uppercase;
  padding: 1px 5px; border-radius: 3px;
  letter-spacing: 0.04em;
}
.vb-ie-msg-time {
  font-size: 11px; color: #949ba4;
}
.vb-ie-msg-content {
  display: block;              /* prevent inline siblings from sitting beside */
  box-sizing: border-box;
  width: 100%;
  max-width: 576px;            /* ~20% shorter than the embed below (720px) */
  min-height: 26px;
  height: 26px;                /* compact by default — grows on input via JS */
  font-size: 14px; color: #dbdee1;
  background: rgba(0,0,0,0.18);
  border: 1px dashed rgba(255,255,255,0.06);
  border-radius: 6px;
  padding: 4px 10px;
  margin: 0;
  font-family: inherit;
  line-height: 1.4;
  resize: none;
  outline: none;
  overflow: hidden;
  transition: border-color .12s, background .12s;
}
.vb-ie-msg-content:focus,
.vb-ie-msg-content:hover {
  border-color: rgba(88,101,242,0.5);
  background: rgba(0,0,0,0.28);
}
.vb-ie-msg-content::placeholder {
  color: #6d7079; font-style: italic;
}
/* "+ Einbettung hinzufügen" CTA — only when no embed yet.
   display:flex (block-level) so it always sits BELOW the textarea, not
   beside it. width: fit-content keeps it small but min-width gives presence. */
.vb-ie-add-embed {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  width: fit-content;
  min-width: 240px;
  margin: 0;
  background: rgba(88,101,242,0.1);
  color: #c9cdfb;
  border: 1px dashed rgba(88,101,242,0.4);
  border-radius: 6px;
  padding: 9px 14px;
  font-size: 13px; font-weight: 500;
  cursor: pointer;
  transition: background .12s, color .12s, border-color .12s;
}
.vb-ie-add-embed:hover {
  background: rgba(88,101,242,0.18);
  border-color: rgba(88,101,242,0.7);
  color: #fff;
}
/* Wrapper around each embed in the canvas. Block-level so multi-embeds
   stack vertically; max-width matches the embed itself. */
.vb-ie-embed-wrap {
  display: block;
  position: relative;
  margin: 0;
  width: 100%;
  max-width: 576px;
}
/* ─── V2 Insert Panel ────────────────────────────────────────────────
   Right column ONLY visible when the embed is in Components-V2 mode.
   Sits OUTSIDE the trash/dup stack with a clear gap (mirrors the gap
   between the embed and the trash column on the same row). */
.vb-ie-v2-panel {
  position: absolute;
  top: 0;
  right: -194px;          /* trash ends at +42 → ~12px gap → matches embed↔trash distance */
  width: 130px;
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.1);
  border-radius: 8px;
  padding: 8px 8px 10px;
  z-index: 2;
  display: none;          /* hidden by default — only the active embed shows it */
}
.vb-ie-v2-panel.is-active { display: block; }
.vb-ie-v2-panel-title {
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted, #b5bac1);
  padding: 0 2px 6px;
  margin-bottom: 4px;
}
.vb-ie-v2-insert {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  padding: 6px 8px;
  background: transparent;
  border: 1px solid rgba(255,255,255,0.12);
  border-radius: 4px;
  color: var(--text, #f2f3f5);
  font-size: 12px;
  font-weight: 500;
  cursor: pointer;
  margin-bottom: 4px;
  text-align: left;
  transition: background .12s, border-color .12s, color .12s;
}
.vb-ie-v2-insert:last-child { margin-bottom: 0; }
.vb-ie-v2-insert:hover {
  background: rgba(255,140,26,0.08);
  border-color: rgba(255,140,26,0.5);
  color: var(--orange, #ff8c1a);
}
.vb-ie-v2-insert svg { flex: 0 0 auto; width: 12px; height: 12px; }

/* ─── V2 block types ─────────────────────────────────────────────────
   Text-only blocks and Section (text+button) blocks. */
.vb-ie-v2-block {
  position: relative;
  background: rgba(255,255,255,0.02);
  border-radius: 4px;
  padding: 8px 10px;
  transition: box-shadow .12s, opacity .12s;
}
/* While being dragged — reduce opacity, faint outline so user sees source */
.vb-ie-v2-block.is-dragging,
.vb-ie-embed-v2-section.is-dragging,
.vb-ie-v2-sep.is-dragging {
  opacity: 0.4;
}
/* Drop indicator — a thin orange line above/below the target block */
.vb-ie-v2-block.is-drop-above,
.vb-ie-embed-v2-section.is-drop-above,
.vb-ie-v2-sep.is-drop-above {
  box-shadow: 0 -2px 0 0 var(--orange, #ff8c1a);
}
.vb-ie-v2-block.is-drop-below,
.vb-ie-embed-v2-section.is-drop-below,
.vb-ie-v2-sep.is-drop-below {
  box-shadow: 0 2px 0 0 var(--orange, #ff8c1a);
}

/* Drag-handle (grip) — straddles the LEFT edge of the block, vertically
   centered. Half sticks outside, half inside; visible against any backdrop
   thanks to the dark chip background. */
/* Drag handle — no box, just the icon. Same minimalist style as the X
   on the right (delete button). Centered on the left edge of the block. */
.vb-ie-v2-grip {
  position: absolute;
  left: -10px;
  top: 50%;
  transform: translateY(-50%);
  width: 18px;
  height: 18px;
  padding: 0;
  background: transparent;
  border: 0;
  color: #b5bac1;
  cursor: grab;
  display: flex;
  align-items: center; justify-content: center;
  opacity: 0;
  transition: opacity .12s, color .12s, transform .1s;
  z-index: 3;
}
.vb-ie-v2-grip:active { cursor: grabbing; }
.vb-ie-v2-block:hover > .vb-ie-v2-grip,
.vb-ie-embed-v2-section:hover > .vb-ie-v2-grip,
.vb-ie-v2-sep:hover > .vb-ie-v2-grip,
.vb-ie-v2-grip:focus-visible { opacity: 1; }
.vb-ie-v2-grip:hover {
  color: var(--orange, #ff8c1a);
  transform: translateY(-50%) scale(1.15);
}
.vb-ie-v2-grip svg { display: block; }

/* Separator-specific: the visual divider line sits at the TOP edge of the
   element (border-top), not in the middle. Pin the grip there too so it
   visually sits ON the line, matching the X position on the right side. */
.vb-ie-v2-sep > .vb-ie-v2-grip {
  top: 0;
  transform: translateY(-50%);
}
.vb-ie-v2-sep:hover > .vb-ie-v2-grip:hover {
  transform: translateY(-50%) scale(1.15);
}
.vb-ie-v2-text {
  /* nothing special — just a padded contenteditable */
}
.vb-ie-v2-sect {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  justify-content: space-between;
}
.vb-ie-v2-sect-text {
  flex: 1 1 auto;
  min-width: 0;
}
/* Button accessory on the right of a Section block. Styled to look like
   an actual Discord button so the preview feels accurate. */
.vb-ie-v2-sect-btn {
  flex: 0 0 auto;
  align-self: center;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 80px;
  padding: 6px 12px;
  border-radius: 4px;
  border: 0;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  color: #fff;
  transition: filter .12s;
}
.vb-ie-v2-sect-btn:hover { filter: brightness(1.12); }
.vb-ie-v2-sect-btn-label {
  outline: none;
  padding: 0 2px;
}
.vb-ie-btn-style--primary   { background: #5865F2; }
.vb-ie-btn-style--secondary { background: #4e5058; }
.vb-ie-btn-style--success   { background: #248046; }
.vb-ie-btn-style--danger    { background: #da373c; }
.vb-ie-btn-style--link      { background: #4e5058; }
/* ─── V2 Media block (single image + gallery) ──────────────────────── */
.vb-ie-v2-media {
  padding: 4px;
}
.vb-ie-v2-media-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 4px;
}
.vb-ie-v2-media.is-gallery .vb-ie-v2-media-grid {
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
}
.vb-ie-v2-media-tile {
  position: relative;
  display: flex;
  align-items: center; justify-content: center;
  min-height: 120px;
  background: rgba(255,255,255,0.025);
  border: 1px dashed rgba(255,255,255,0.18);
  border-radius: 6px;
  cursor: pointer;
  padding: 0;
  overflow: hidden;
  transition: background .12s, border-color .12s;
}
.vb-ie-v2-media-tile:hover {
  background: rgba(255,140,26,0.06);
  border-color: rgba(255,140,26,0.45);
}
.vb-ie-v2-media-tile.is-set {
  border-style: solid;
  border-color: rgba(255,255,255,0.06);
  background: transparent;
  min-height: 0;
}
.vb-ie-v2-media.is-gallery .vb-ie-v2-media-tile.is-set { min-height: 120px; }
.vb-ie-v2-media-tile img {
  width: 100%; height: 100%;
  max-height: 320px;
  object-fit: cover;
  display: block;
}
.vb-ie-v2-media-rm {
  position: absolute;
  top: 4px; right: 4px;
  width: 22px; height: 22px;
  background: rgba(0,0,0,0.55);
  color: #fff;
  border: 0;
  border-radius: 50%;
  cursor: pointer;
  display: flex;
  align-items: center; justify-content: center;
  opacity: 0;
  transition: opacity .12s, background .12s;
}
.vb-ie-v2-media-tile:hover .vb-ie-v2-media-rm { opacity: 1; }
.vb-ie-v2-media-rm:hover { background: #ed4245; }
.vb-ie-v2-media-rm svg { display: block; }
.vb-ie-v2-media-add {
  flex: 0 0 60px;
  min-height: 60px;
  color: var(--text-muted, #b5bac1);
}
.vb-ie-v2-media-add:hover { color: var(--orange, #ff8c1a); }
.vb-ie-v2-media-add svg { width: 20px; height: 20px; }

/* ─── V2 File block ─────────────────────────────────────────────────── */
.vb-ie-v2-file {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  background: rgba(255,255,255,0.03);
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: 6px;
  cursor: pointer;
  transition: background .12s, border-color .12s;
}
.vb-ie-v2-file:hover {
  background: rgba(255,140,26,0.05);
  border-color: rgba(255,140,26,0.35);
}
.vb-ie-v2-file-icon {
  flex: 0 0 32px;
  width: 32px; height: 32px;
  display: flex;
  align-items: center; justify-content: center;
  background: rgba(255,255,255,0.05);
  border-radius: 6px;
  color: var(--text-muted, #b5bac1);
}
.vb-ie-v2-file-icon svg { width: 20px; height: 20px; }
.vb-ie-v2-file-meta {
  flex: 1 1 auto;
  min-width: 0;
}
.vb-ie-v2-file-name {
  font-size: 13px;
  font-weight: 600;
  color: var(--text, #f2f3f5);
  text-decoration: none;
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.vb-ie-v2-file-url {
  font-size: 11px;
  color: var(--text-muted, #b5bac1);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.vb-ie-btn-style--link::after {
  content: '';
  display: inline-block;
  width: 10px; height: 10px;
  margin-left: 6px;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http%3A//www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6'/><polyline points='15 3 21 3 21 9'/><line x1='10' y1='14' x2='21' y2='3'/></svg>") center/contain no-repeat;
          mask: url("data:image/svg+xml;utf8,<svg xmlns='http%3A//www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6'/><polyline points='15 3 21 3 21 9'/><line x1='10' y1='14' x2='21' y2='3'/></svg>") center/contain no-repeat;
  opacity: 0.85;
}

/* "+ Weitere Einbettung" variant — slightly smaller, neutral color so the
   first big CTA stays visually distinct. */
.vb-ie-add-embed--more {
  background: rgba(255,255,255,0.04);
  border-color: rgba(255,255,255,0.16);
  color: var(--text-muted, #b5bac1);
  font-weight: 400;
}
.vb-ie-add-embed--more:hover {
  background: rgba(255,140,26,0.1);
  border-color: rgba(255,140,26,0.45);
  color: var(--orange, #ff8c1a);
}
/* Vertical action stack to the RIGHT of each embed — trash + duplicate.
   Always visible, permanently rendered so the user sees the controls at all
   times across the multi-embed stack. */
.vb-ie-embed-actions {
  position: absolute;
  top: 0;
  right: -42px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  z-index: 2;
}
.vb-ie-embed-rm,
.vb-ie-embed-dup {
  width: 32px; height: 32px;
  border-radius: 6px;
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  padding: 0;
  transition: background .12s, border-color .12s, color .12s;
}
/* Red trash */
.vb-ie-embed-rm {
  background: rgba(237,66,69,0.12);
  color: #ed4245;
  border: 1px solid rgba(237,66,69,0.35);
}
.vb-ie-embed-rm:hover {
  background: rgba(237,66,69,0.28);
  border-color: rgba(237,66,69,0.7);
  color: #ff7176;
}
/* Neutral gray duplicate */
.vb-ie-embed-dup {
  background: rgba(255,255,255,0.05);
  color: #b5bac1;
  border: 1px solid rgba(255,255,255,0.18);
}
.vb-ie-embed-dup:hover {
  background: rgba(255,255,255,0.1);
  border-color: rgba(255,255,255,0.35);
  color: #fff;
}
.vb-ie-embed-rm svg,
.vb-ie-embed-dup svg { display: block; }

/* Discord-style embed card — same width as the textarea above. Height
   follows content; no forced min-height (Discord embeds shrink-to-fit). */
.vb-ie-embed {
  display: grid;
  grid-template-columns: 4px 1fr auto;
  background: #2b2d31;
  border-radius: 4px;
  width: 100%;
  max-width: 576px;
  overflow: hidden;
}
.vb-ie-embed-bar {
  background: var(--ie-color, #5865F2);
  cursor: pointer;
  transition: filter .12s;
}
.vb-ie-embed-bar:hover { filter: brightness(1.3); }
.vb-ie-embed-body {
  padding: 12px 16px 18px;    /* extra bottom breathing room below footer */
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.vb-ie-embed-author {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  font-weight: 600;
  color: #f2f3f5;
  margin: 6px 0;
}
.vb-ie-embed-author img {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  object-fit: cover;
}
.vb-ie-embed-title {
  font-size: 16px;
  font-weight: 600;
  color: #fff;
  margin: 2px 0;
}
.vb-ie-embed-desc {
  font-size: 14px;
  color: #dbdee1;
  margin: 2px 0;
  line-height: 1.4;
  white-space: pre-wrap;
  word-wrap: break-word;
}
.vb-ie-embed-fields {
  display: grid;
  grid-template-columns: 1fr;
  gap: 6px;
  margin-top: 8px;
}
.vb-ie-embed-field {
  position: relative;
  font-size: 14px;
}
.vb-ie-embed-field.is-inline { grid-column: span 1; }
@media (min-width: 600px) {
  .vb-ie-embed-fields { grid-template-columns: repeat(3, 1fr); }
  .vb-ie-embed-field { grid-column: span 3; }
  .vb-ie-embed-field.is-inline { grid-column: span 1; }
}
.vb-ie-embed-field-name {
  font-weight: 600;
  color: #fff;
  margin-bottom: 2px;
}
.vb-ie-embed-field-value {
  color: #dbdee1;
  white-space: pre-wrap;
}
/* Field/section/separator delete — small red X, no box. Hidden until the
   parent field is hovered so the embed-body stays uncluttered. */
.vb-ie-field-del {
  position: absolute;
  top: -8px;
  right: -8px;
  width: 18px;
  height: 18px;
  padding: 0;
  background: transparent;
  border: 0;
  border-radius: 50%;
  color: #ed4245;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 2;
  opacity: 0;
  pointer-events: none;
  transition: opacity .12s, color .12s, transform .1s;
}
/* X icon ~20% larger than the default 12px IE_ICONS.x */
.vb-ie-field-del svg { display: block; width: 15px; height: 15px; }
.vb-ie-embed-field:hover .vb-ie-field-del,
.vb-ie-embed-v2-section:hover .vb-ie-field-del,
.vb-ie-v2-sep:hover .vb-ie-field-del,
.vb-ie-v2-block:hover > .vb-ie-field-del,
.vb-ie-field-del:focus-visible {
  opacity: 1;
  pointer-events: auto;
}
.vb-ie-field-del:hover {
  color: #ff7176;
  transform: scale(1.15);
}

/* ─── Inline-editable text zones ────────────────────────────────────── */
.vb-ie-text {
  outline: none;
  border-radius: 3px;
  padding: 1px 3px;
  margin: 0 -3px;
  transition: background .1s, box-shadow .1s;
  cursor: text;
  min-height: 1.2em;
  white-space: pre-wrap;
  word-break: break-word;
}
.vb-ie-text:hover { background: rgba(255,255,255,0.04); }
.vb-ie-text:focus {
  background: rgba(88,101,242,0.1);
  box-shadow: inset 0 0 0 1px rgba(88,101,242,0.5);
}
.vb-ie-text:empty::before {
  content: attr(data-ph);
  color: #6d7079;
  font-style: italic;
  font-weight: normal;
  pointer-events: none;
}

/* ─── Embed row layout — color trigger sits OUTSIDE on the left ─────── */
.vb-ie-embed-row {
  position: relative;
  display: block;
  max-width: 576px;
  width: 100%;
}
/* Left-side control stack: palette (color picker) + eye (preview toggle).
   Mirrors the right-side action stack (trash + duplicate). */
.vb-ie-embed-controls-left {
  position: absolute;
  top: 0;
  left: -44px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  z-index: 3;
}
.vb-ie-embed-color-slot { display: inline-block; }
.vb-ie-embed-color-slot .vb-picker { display: inline-block; }

/* Gray rounded button with the palette icon. The colored swatch from the
   shared picker is hidden — accent color lives in the embed's left bar. */
.vb-ie-embed-color-slot .vb-color-btn {
  position: relative;
  width: 32px; height: 32px;
  padding: 0;
  background: rgba(255,255,255,0.05);
  border: 1px solid rgba(255,255,255,0.18);
  border-radius: 6px;
  cursor: pointer;
  display: flex;
  align-items: center; justify-content: center;
  color: #b5bac1;
  transition: background .12s, border-color .12s, color .12s;
}
.vb-ie-embed-color-slot .vb-color-btn:hover {
  background: rgba(255,255,255,0.1);
  border-color: rgba(255,255,255,0.35);
  color: #fff;
}

/* Eye / preview toggle — always neutral gray. In preview mode the icon
   changes to a pencil ("zurück zum Bearbeiten"); no color shift. */
.vb-ie-embed-eye {
  width: 32px; height: 32px;
  padding: 0;
  background: rgba(255,255,255,0.05);
  color: #b5bac1;
  border: 1px solid rgba(255,255,255,0.18);
  border-radius: 6px;
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: background .12s, border-color .12s, color .12s;
}
.vb-ie-embed-eye:hover {
  background: rgba(255,255,255,0.1);
  border-color: rgba(255,255,255,0.35);
  color: #fff;
}
.vb-ie-embed-eye svg { display: block; }
.vb-ie-embed-color-slot .vb-color-swatch { display: none; }
/* Palette icon injected via mask (svg inlined as data URI). */
.vb-ie-embed-color-slot .vb-color-btn::after {
  content: '';
  width: 16px; height: 16px;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http%3A//www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='13.5' cy='6.5' r='.5'/><circle cx='17.5' cy='10.5' r='.5'/><circle cx='8.5' cy='7.5' r='.5'/><circle cx='6.5' cy='12.5' r='.5'/><path d='M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10c.926 0 1.648-.746 1.648-1.688 0-.437-.18-.835-.437-1.125-.29-.289-.438-.652-.438-1.125a1.64 1.64 0 0 1 1.668-1.668h1.996c3.051 0 5.555-2.503 5.555-5.554C21.965 6.012 17.461 2 12 2z'/></svg>") center/contain no-repeat;
          mask: url("data:image/svg+xml;utf8,<svg xmlns='http%3A//www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='13.5' cy='6.5' r='.5'/><circle cx='17.5' cy='10.5' r='.5'/><circle cx='8.5' cy='7.5' r='.5'/><circle cx='6.5' cy='12.5' r='.5'/><path d='M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10c.926 0 1.648-.746 1.648-1.688 0-.437-.18-.835-.437-1.125-.29-.289-.438-.652-.438-1.125a1.64 1.64 0 0 1 1.668-1.668h1.996c3.051 0 5.555-2.503 5.555-5.554C21.965 6.012 17.461 2 12 2z'/></svg>") center/contain no-repeat;
}

/* ─── Placeholders for thumbnail + image — dashed RECTANGLES with a
   round + circle centered inside. The rectangle makes the drop-zone
   clearly visible, the circle is the actual click target visual. ─── */
.vb-ie-thumb-ph,
.vb-ie-image-ph {
  display: flex;
  align-items: center; justify-content: center;
  padding: 0;
  background: rgba(255,255,255,0.025);
  border: 1px dashed rgba(255,255,255,0.22);
  border-radius: 4px;
  cursor: pointer;
  transition: background .12s, border-color .12s;
}
.vb-ie-thumb-ph:hover,
.vb-ie-image-ph:hover {
  background: rgba(255,140,26,0.06);
  border-color: rgba(255,140,26,0.5);
}
/* Inner circle with the + icon, centered inside the dashed box */
.vb-ie-ph-plus {
  display: flex;
  align-items: center; justify-content: center;
  width: 36px; height: 36px;
  border-radius: 50%;
  background: rgba(255,255,255,0.05);
  border: 1px solid rgba(255,255,255,0.18);
  color: #b5bac1;
  transition: background .12s, border-color .12s, color .12s, transform .1s;
}
.vb-ie-thumb-ph:hover .vb-ie-ph-plus,
.vb-ie-image-ph:hover .vb-ie-ph-plus {
  background: rgba(255,140,26,0.12);
  border-color: rgba(255,140,26,0.5);
  color: var(--orange, #ff8c1a);
  transform: scale(1.08);
}
.vb-ie-ph-plus svg { width: 14px; height: 14px; }

/* Thumbnail box dimensions — 80×80 (matches Discord's actual thumb size). */
.vb-ie-thumb-ph,
.vb-ie-embed-thumb.is-set {
  width: 80px;
  height: 80px;
  margin: 10px 14px 0 8px;
  align-self: flex-start;
  flex: 0 0 80px;
}
.vb-ie-embed-thumb.is-set {
  padding: 0;
  background: transparent;
  border: 0;
  cursor: pointer;
  border-radius: 4px;
}
.vb-ie-embed-thumb.is-set img {
  width: 100%; height: 100%;
  border-radius: 4px;
  object-fit: cover;
  display: block;
}
/* Image placeholder dimensions — full-width inside the embed body. */
.vb-ie-image-ph {
  width: 100%;
  height: 120px;
  margin: 8px 0 0;
}

/* ─── Small/extra-small circle icon placeholders (author + footer) ──── */
.vb-ie-icon-ph {
  flex: 0 0 auto;
  border-radius: 50%;
  background: rgba(255,255,255,0.04);
  border: 1px dashed rgba(255,255,255,0.22);
  color: #80848e;
  display: inline-flex;
  align-items: center; justify-content: center;
  cursor: pointer;
  padding: 0;
  overflow: hidden;
  transition: background .12s, border-color .12s, color .12s;
}
.vb-ie-icon-ph:hover {
  background: rgba(88,101,242,0.1);
  border-color: rgba(88,101,242,0.6);
  color: #c9cdfb;
}
.vb-ie-icon-ph svg { width: 12px; height: 12px; }
.vb-ie-icon-ph--xs svg { width: 10px; height: 10px; }
.vb-ie-icon-ph img { width: 100%; height: 100%; object-fit: cover; border-radius: 50%; }
.vb-ie-icon-ph--sm { width: 24px; height: 24px; }
.vb-ie-icon-ph--xs { width: 20px; height: 20px; }

/* ─── "+ Feld hinzufügen" inline button ──────────────────────────── */
.vb-ie-inline-add {
  display: inline-flex;
  align-self: flex-start;       /* don't stretch across the column-flex parent */
  width: fit-content;
  align-items: center; gap: 4px;
  margin: 6px 0 4px;
  padding: 2px 8px;
  background: transparent;
  border: 1px dashed rgba(255,255,255,0.18);
  border-radius: 4px;
  color: var(--text-muted, #b5bac1);
  font-size: 11px;
  font-weight: 500;
  cursor: pointer;
  transition: background .12s, color .12s, border-color .12s;
}
.vb-ie-inline-add:hover {
  background: rgba(255,255,255,0.05);
  border-color: rgba(255,255,255,0.35);
  color: #fff;
}
.vb-ie-ts-pill {
  font-size: 11px;
  color: #b5bac1;
  cursor: default;
  pointer-events: none;        /* purely display — toggle via slider only */
}

/* Soft hint inside the preview embed when title or description is still
   empty — italic muted text so it reads as "this slot needs content"
   rather than as actual embed content. */
.vb-ie-preview-hint {
  font-style: italic;
  color: #80848e;
  font-weight: normal;
  opacity: 0.9;
}
.vb-ie-embed-title.vb-ie-preview-hint {
  font-size: 16px;
  font-weight: normal;
}
/* Components-V2 visual treatment — boxier, no orange bar, sections stack */
.vb-ie-embed--v2 {
  grid-template-columns: 1fr;          /* no left color-bar in V2 */
  border-left: 4px solid var(--ie-color, #5865F2);
  background: linear-gradient(180deg, rgba(255,255,255,0.025), transparent), #2b2d31;
}
.vb-ie-embed--v2 .vb-ie-embed-bar { display: none; }

/* V2 stacked blocks (each block is one section) */
.vb-ie-embed-v2-blocks {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 8px;
}
.vb-ie-embed-v2-section {
  position: relative;
  padding: 8px 10px;
  background: rgba(255,255,255,0.025);
  border-radius: 4px;
  font-size: 14px;
}

/* V2 separator — visible horizontal divider */
.vb-ie-v2-sep {
  position: relative;
  height: 14px;
  border-top: 1px solid transparent;
  margin: 4px 0;
}
.vb-ie-v2-sep.has-divider {
  border-top-color: rgba(255,255,255,0.12);
}
/* Separator no longer changes color on hover — grip + delete handle the
   interaction visually, consistent with the other V2 block types. */

/* Big image (full-width) when SET — just the <img>, no border decoration. */
.vb-ie-embed-image.is-set {
  display: block;
  width: 100%;
  margin-top: 8px;
  border-radius: 4px;
  cursor: pointer;
  border: 0;
  padding: 0;
  background: transparent;
}
.vb-ie-embed-image.is-set img {
  max-width: 100%;
  border-radius: 4px;
  display: block;
}
/* Big-image placeholder — small + circle aligned left, just like Discord's
   "add attachment" hint. Sits on its own line below the description. */
.vb-ie-image-ph {
  margin: 8px 0 0;
}
.vb-ie-embed-footer {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 8px;
  font-size: 12px;
  color: #b5bac1;
}
.vb-ie-embed-footer img {
  width: 20px;
  height: 20px;
  border-radius: 50%;
}

/* (vb-ie-zone hover styles removed — all V2 blocks use the global grip +
   delete pattern instead of a per-zone blue outline.) */
.vb-ie-empty {
  opacity: 0.5;
}
.vb-ie-empty .vb-ie-ph,
.vb-ie-ph {
  font-style: italic;
  color: #80848e;
  font-size: 13px;
  font-weight: normal !important;
}

/* Bottom toolbar — currently unused (timestamp moved to per-embed slider) */
.vb-ie-toolbar-bottom {
  display: none;
}

/* Per-embed toggle row — sits between the embed and the "+ Weitere
   Einbettung" button. Small slider with label, brand orange when active. */
.vb-ie-embed-toggles {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 8px 0 0;
  padding: 0 2px;
  font-size: 12px;
  color: var(--text-muted, #b5bac1);
}
.vb-ie-toggle {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  user-select: none;
}
.vb-ie-toggle input[type="checkbox"] {
  position: absolute;
  opacity: 0;
  width: 0; height: 0;
  pointer-events: none;
}
.vb-ie-toggle-track {
  position: relative;
  width: 30px; height: 16px;
  background: rgba(237,66,69,0.55);        /* off → red */
  border-radius: 999px;
  transition: background .15s;
  flex: 0 0 30px;
}
.vb-ie-toggle-track::after {
  content: '';
  position: absolute;
  top: 2px; left: 2px;
  width: 12px; height: 12px;
  background: #fff;
  border-radius: 50%;
  transition: transform .15s, background .15s;
}
.vb-ie-toggle input:checked + .vb-ie-toggle-track {
  background: rgba(67,181,129,0.85);      /* on → green */
}
.vb-ie-toggle input:checked + .vb-ie-toggle-track::after {
  transform: translateX(14px);
  background: #fff;
}
.vb-ie-toggle input:focus-visible + .vb-ie-toggle-track {
  outline: 2px solid #4ade80;
  outline-offset: 2px;
}
.vb-ie-toggle-label {
  font-size: 12px;
  font-weight: 500;
  color: var(--text-muted, #b5bac1);
  transition: color .15s;
}
.vb-ie-toggle:hover .vb-ie-toggle-label { color: var(--text, #f2f3f5); }

/* Popover for one zone */
.vb-ie-popover {
  background: var(--bg-elevated, #1f2024);
  border: 1px solid var(--border, #2c2d31);
  border-radius: 8px;
  padding: 12px;
  min-width: 320px;
  max-width: 360px;
  box-shadow: 0 12px 32px rgba(0,0,0,0.6);
  z-index: 10000;
}
.vb-ie-popover label {
  display: block;
  font-size: 11px;
  color: var(--text-muted);
  margin: 4px 0 2px;
  font-weight: 600;
}
.vb-ie-popover input,
.vb-ie-popover textarea {
  width: 100%;
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.1);
  border-radius: 4px;
  color: var(--text);
  padding: 6px 8px;
  font-family: inherit;
  font-size: 13px;
}
.vb-ie-popover input[type="color"] {
  height: 36px;
  padding: 2px;
}
.vb-ie-popover-actions {
  display: flex;
  justify-content: flex-end;
  gap: 6px;
  margin-top: 10px;
}

/* Button-Style picker — used inside the section-accessory popover. Each
   option is a radio styled as a mini Discord-button so the user picks the
   visual style they want without reading style names. */
.vb-ie-btn-style-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px;
  margin: 4px 0 12px;
}
.vb-ie-btn-style-opt {
  position: relative;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 10px;
  border-radius: 4px;
  cursor: pointer;
  color: #fff;
  font-size: 12px;
  font-weight: 600;
  opacity: 0.55;
  transition: opacity .12s, transform .1s;
  margin: 0;
}
.vb-ie-btn-style-opt:hover { opacity: 0.8; }
.vb-ie-btn-style-opt.is-active {
  opacity: 1;
  box-shadow: 0 0 0 2px rgba(255,255,255,0.4);
}
.vb-ie-btn-style-opt input[type="radio"] {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

/* ─── Bot-Texts editor (DEVCON_BOT_STRINGS_v1) ─────────────────────── */
.vb-btx-cat {
  margin-bottom: 28px;
}
.vb-btx-cat-title {
  font-size: 14px;
  font-weight: 700;
  color: var(--text);
  letter-spacing: 0.03em;
  margin: 0 0 10px;
  padding-bottom: 6px;
  border-bottom: 1px solid rgba(255,255,255,0.08);
}
.vb-btx-row {
  padding: 12px;
  margin-bottom: 10px;
  background: rgba(255,255,255,0.025);
  border: 1px solid rgba(255,255,255,0.06);
  border-radius: 8px;
  transition: border-color .12s;
}
.vb-btx-row.is-overridden {
  border-color: rgba(255,138,34,0.4);
  background: rgba(255,138,34,0.04);
}
.vb-btx-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 12px;
  margin-bottom: 6px;
}
.vb-btx-name {
  font-weight: 600;
  font-size: 13px;
  color: var(--text);
}
.vb-btx-tag {
  display: inline-block;
  padding: 2px 6px;
  margin-left: 6px;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.05em;
  border-radius: 3px;
  background: rgba(255,138,34,0.15);
  color: var(--orange);
}
.vb-btx-tag--default {
  background: rgba(255,255,255,0.05);
  color: var(--text-muted);
}
.vb-btx-key {
  font-size: 11px;
  color: var(--text-muted);
  margin-top: 2px;
}
.vb-btx-key code {
  background: transparent;
  font-family: ui-monospace, monospace;
}
.vb-btx-desc {
  margin: 4px 0 8px;
  font-size: 12px;
  color: var(--text-muted);
}
.vb-btx-textarea {
  font-family: inherit;
  font-size: 13px;
  width: 100%;
}
.vb-btx-vars {
  margin-top: 6px;
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}
.vb-btx-var {
  background: rgba(255,138,34,0.08);
  color: var(--orange);
  padding: 2px 7px;
  border-radius: 4px;
  font-family: ui-monospace, monospace;
  font-size: 11px;
  cursor: pointer;
  border: 1px solid rgba(255,138,34,0.2);
}
.vb-btx-var:hover { background: rgba(255,138,34,0.2); }
.vb-btx-embed-pick {
  margin-top: 8px;
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 8px;
  align-items: center;
}
.vb-btx-embed-pick label { font-size: 11px; color: var(--text-muted); }
.vb-btx-actions {
  display: flex;
  gap: 4px;
  flex-shrink: 0;
}
.dash-btn-small {
  font-size: 11px !important;
  padding: 4px 10px !important;
}

/* ─── Birthdays bar chart (DEVCON_BIRTHDAYS_v1) ────────────────────── */
.vb-bday-bars {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 4px;
  height: 120px;
  align-items: end;
  padding: 8px;
  background: rgba(255,255,255,0.02);
  border-radius: 8px;
}
.vb-bday-bar {
  display: flex;
  flex-direction: column;
  align-items: center;
  position: relative;
  height: 100%;
  cursor: default;
}
.vb-bday-bar-fill {
  width: 60%;
  background: linear-gradient(180deg, var(--orange), rgba(255,138,34,0.3));
  border-radius: 3px 3px 0 0;
  min-height: 4px;
}
.vb-bday-bar:hover .vb-bday-bar-fill {
  background: var(--orange);
}
.vb-bday-bar-lbl {
  position: absolute;
  bottom: -18px;
  font-size: 10px;
  color: var(--text-muted);
}
.vb-bday-bar-cnt {
  position: absolute;
  top: -14px;
  font-size: 11px;
  font-weight: 600;
  color: var(--orange);
  font-variant-numeric: tabular-nums;
}

/* ─── Ticket Category Question-Builder (DEVCON_TICKETS_PRO_v1) ──────── */
.vb-tk-q-row {
  position: relative;
  padding: 10px 12px;
  margin-top: 8px;
  background: rgba(255,255,255,0.025);
  border: 1px solid rgba(255,255,255,0.06);
  border-radius: 8px;
}
.vb-tk-q-head {
  display: grid;
  grid-template-columns: 1fr auto auto;
  gap: 8px;
  align-items: center;
}
.vb-tk-q-type-bar { margin-top: 0; gap: 4px; }
.vb-tk-q-type-bar .vb-pill { padding: 4px 10px; font-size: 11px; }

/* Priority row at the bottom of each question — stepper on the left with the
   inline explanation text right of it. Stepper matches the standard
   .dash-modal-input height so the row reads as just another field. */
.vb-tk-q-prio-row {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid rgba(255,255,255,0.06);
}
.vb-tk-q-prio-row .vb-num-stepper { flex: 0 0 110px; width: 110px; height: 40px; }
.vb-tk-q-prio-desc {
  margin: 0 !important;
  flex: 1 1 auto;
  font-size: 12px;
  color: var(--text-muted);
}

/* "Frage hinzufügen" button — dashed-orange add card, full width, signals
   "this opens an inline editor". No `+` per the new-card-no-plus rule. */
.vb-tk-q-addbtn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  margin-top: 10px;
  padding: 10px 14px;
  background: rgba(255, 130, 40, 0.06);
  color: var(--orange);
  font-family: inherit;
  font-size: 13px;
  font-weight: 600;
  border: 1px dashed rgba(255, 130, 40, 0.40);
  border-radius: 8px;
  cursor: pointer;
  transition: background .15s, border-color .15s;
}
.vb-tk-q-addbtn:hover {
  background: rgba(255, 130, 40, 0.14);
  border-color: var(--orange);
  border-style: solid;
}
.vb-tk-q-addbtn:active { transform: scale(0.998); }

/* Day-of-week pill strip (Office-Hours days mask) */
.vb-day-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 4px;
}
.vb-day-pills .vb-pill {
  min-width: 44px;
  padding: 6px 0;
  text-align: center;
}

/* Static picker (timezones, languages, …) — group header inside dropdown */
.vb-static-picker-group-label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--text-dim, var(--text-muted));
  padding: 8px 10px 4px;
  margin-top: 2px;
  user-select: none;
}
.vb-static-picker-group-label:first-child { margin-top: 0; }
.vb-picker-item.is-active {
  background: rgba(255,138,34,.12);
  color: var(--text-bright);
}
.vb-picker-item.is-active::before {
  content: "•";
  color: var(--orange);
  font-size: 18px;
  line-height: 0;
  margin-right: 4px;
}

/* Ticket-Hubs — 7-col list table: hub | status | created | open | closed | categories | actions.
   Status pill chrome stripped per [[column-header-alignment]]. All data
   columns are proportional flex so they collectively fill the container
   width — Actions stays right-aligned via `auto` which sizes to its
   content. Gap between every column is the inherited uniform 12px. */
.vb-tkhubs-table .vb-ec-table-head,
.vb-tkhubs-table .vb-ec-table-row {
  grid-template-columns: 1.5fr 1fr 1fr 0.7fr 1fr 1fr auto;
}
.vb-tkhubs-table .vb-sg-actions-head > span { min-width: 92px; }
.vb-tkhubs-table .vb-ec-table-row .vb-ec-status {
  padding: 0;
  background: transparent;
  border-radius: 0;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
}
.vb-tkhubs-table .vb-ec-table-row .vb-ec-status.is-published { color: #4ade80; }
.vb-tkhubs-table .vb-ec-table-row .vb-ec-status.is-draft     { color: var(--text-dim); }

/* Verify-Panels list — 5 Spalten (Panel / Status / Channel / Format / Aktionen). */
.vb-vp-table .vb-ec-table-head,
.vb-vp-table .vb-ec-table-row {
  grid-template-columns: 1.6fr 0.9fr 1.4fr 1.1fr 0.9fr 92px;
}
/* Flex-cells in jeder Zelle damit Header-Text und Cell-Inhalt an exakt
   derselben x-Position starten (Memory: feedback_actions_cell_alignment). */
.vb-vp-table .vb-ec-table-row > div { display: flex; align-items: center; min-width: 0; }
.vb-vp-table .vb-sg-actions-head > span { min-width: 92px; }
.vb-vp-table .vb-ec-table-row .vb-ec-status {
  padding: 0;
  background: transparent;
  border-radius: 0;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
}
.vb-vp-table .vb-ec-table-row .vb-ec-status.is-published { color: #4ade80; }
.vb-vp-table .vb-ec-table-row .vb-ec-status.is-draft     { color: var(--text-dim); }

/* Verify-Flow Picker — 3 Karten nebeneinander (Title fett oben + kurze
   Beschreibung drunter). Aktive Karte bekommt den orange devcon-Akzent. */
.vb-vp-flow-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px;
  margin-top: 6px;
}
@media (max-width: 720px) { .vb-vp-flow-grid { grid-template-columns: 1fr; } }
.vb-vp-flow-card {
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 16px 18px;
  text-align: left;
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.10);
  border-radius: 10px;
  cursor: pointer;
  font-family: inherit;
  transition: background .12s ease, border-color .12s ease, transform .08s ease;
}
.vb-vp-flow-card:hover {
  background: rgba(255, 255, 255, 0.05);
  border-color: rgba(255, 255, 255, 0.18);
}
.vb-vp-flow-card.is-active {
  border-color: var(--orange);
  background: rgba(255, 138, 34, 0.08);
  box-shadow: 0 0 0 2px rgba(255, 138, 34, 0.18);
}
.vb-vp-flow-card-title {
  position: relative;          /* über dem Ghost-Icon */
  z-index: 1;
  font-size: 14px;
  font-weight: 700;
  color: var(--text-bright);
}
.vb-vp-flow-card.is-active .vb-vp-flow-card-title { color: var(--orange); }
.vb-vp-flow-card-desc {
  position: relative;
  z-index: 1;
  font-size: 12px;
  color: var(--text-muted);
  line-height: 1.45;
}
/* Ghost-Icon mittig-rechts in jeder Karte — identisch zum .vb-gs-tile
   Pattern (Stat-Tiles). Halb aus der Karte rausragend für den dezenten
   Akzent. Bei is-active wechselt die Farbe auf Orange. */
.vb-vp-flow-card::after {
  content: "";
  position: absolute;
  right: -8px;
  top: 50%;
  transform: translateY(-50%);
  width: 72px;
  height: 72px;
  background-color: var(--text-muted, #b5bac1);
  opacity: 0.10;
  pointer-events: none;
  -webkit-mask-size: contain;
          mask-size: contain;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  -webkit-mask-position: center;
          mask-position: center;
  transition: opacity .15s ease, background-color .15s ease;
}
.vb-vp-flow-card:hover::after { opacity: 0.18; }
.vb-vp-flow-card.is-active::after {
  opacity: 0.22;
  background-color: var(--orange);
}
/* OAuth → Shield + Check */
.vb-vp-flow-card--oauth::after {
  -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'><path d='M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z'/><polyline points='9 12 11 14 15 10'/></svg>");
          mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'><path d='M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z'/><polyline points='9 12 11 14 15 10'/></svg>");
}
/* Direkt → Lightning Bolt */
.vb-vp-flow-card--direct::after {
  -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'><polygon points='13 2 3 14 12 14 11 22 21 10 12 10 13 2'/></svg>");
          mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'><polygon points='13 2 3 14 12 14 11 22 21 10 12 10 13 2'/></svg>");
}
/* Mathe-Aufgabe → Calculator */
.vb-vp-flow-card--math::after {
  -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'><rect x='4' y='2' width='16' height='20' rx='2'/><line x1='8' y1='6' x2='16' y2='6'/><line x1='8' y1='10' x2='10' y2='10'/><line x1='12' y1='10' x2='14' y2='10'/><line x1='16' y1='10' x2='16' y2='10'/><line x1='8' y1='14' x2='10' y2='14'/><line x1='12' y1='14' x2='14' y2='14'/><line x1='8' y1='18' x2='14' y2='18'/></svg>");
          mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'><rect x='4' y='2' width='16' height='20' rx='2'/><line x1='8' y1='6' x2='16' y2='6'/><line x1='8' y1='10' x2='10' y2='10'/><line x1='12' y1='10' x2='14' y2='10'/><line x1='16' y1='10' x2='16' y2='10'/><line x1='8' y1='14' x2='10' y2='14'/><line x1='12' y1='14' x2='14' y2='14'/><line x1='8' y1='18' x2='14' y2='18'/></svg>");
}
/* Role-Reactions Type-Karten (mig 109). Selbe Ghost-Icon-Pattern wie die
   Verify-Flow-Karten oben. Bewusst nur EINE Form pro Icon (keine
   überlappenden Sub-Pfade) — bei 72px Größe + mask-rendering werden
   verschachtelte Lucide-Outlines sonst zu Knubbeln. */
/* Button → Bullseye / Klick-Target: 3 konzentrische Ringe via evenodd-
   fill, ein einziger Path. „Hier klicken" mit punch. */
.vb-vp-flow-card--button::after {
  -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill-rule='evenodd' clip-rule='evenodd' fill='black' stroke='none'><path d='M12 2a10 10 0 1 0 0 20 10 10 0 0 0 0-20zm0 4a6 6 0 1 0 0 12 6 6 0 0 0 0-12zm0 4a2 2 0 1 0 0 4 2 2 0 0 0 0-4z'/></svg>");
          mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill-rule='evenodd' clip-rule='evenodd' fill='black' stroke='none'><path d='M12 2a10 10 0 1 0 0 20 10 10 0 0 0 0-20zm0 4a6 6 0 1 0 0 12 6 6 0 0 0 0-12zm0 4a2 2 0 1 0 0 4 2 2 0 0 0 0-4z'/></svg>");
}
/* Dropdown → Double-Chevron-Down (chevrons-down). Peppier als Single-
   Chevron, klar „aufklappen". */
.vb-vp-flow-card--select::after {
  -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'><polyline points='7 6 12 11 17 6'/><polyline points='7 13 12 18 17 13'/></svg>");
          mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'><polyline points='7 6 12 11 17 6'/><polyline points='7 13 12 18 17 13'/></svg>");
}
/* Reaction → Filled 5-Point-Star. Single Path, klassisches Reaction-
   Gefühl ohne die Smiley-Augen-Knubbel-Falle. */
.vb-vp-flow-card--reaction::after {
  -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='black' stroke='none'><path d='M12 2l3.09 6.26L22 9.27l-5 4.87L18.18 22 12 18.27 5.82 22 7 14.14l-5-4.87 6.91-1.01z'/></svg>");
          mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='black' stroke='none'><path d='M12 2l3.09 6.26L22 9.27l-5 4.87L18.18 22 12 18.27 5.82 22 7 14.14l-5-4.87 6.91-1.01z'/></svg>");
}

/* Min-Account-Age Stepper im Verify-Builder — Breite bleibt natürlich
   (Default 120px). Die Höhe wird per JS zur Laufzeit auf die rendered
   Höhe der Role-Picker Chip-List nebenan gesetzt (siehe
   renderVerifyMessage). CSS-Override hier nur als Fallback. */
.vb-vp-minage-wrap .vb-num-stepper { box-sizing: border-box; }

/* Dezenter "Flow ist nicht OAuth" Hinweis — komplett ohne Box, nur
   Info-Icon + Inline-Text. Wirkt wie ein normaler Hilfetext, fällt
   nicht aus dem Seiten-Flow raus. */
.vb-noauth-hint {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding: 0;
  margin-bottom: 14px;
  background: transparent;
  border: 0;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--text-muted);
}
.vb-noauth-hint-icon {
  flex: 0 0 auto;
  color: rgba(250, 166, 26, 0.85);
  margin-top: 2px;
}
.vb-noauth-hint-body strong {
  color: var(--text);
  font-weight: 600;
}

/* Verify-Panel "Verify-Nachricht" Subtab — Toggles untereinander
   (sonst legt .vb-switch inline-flex sie nebeneinander). */
.vb-vp-toggle-stack {
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-items: flex-start;
}

/* Button-Style Picker — fünf Discord-style Buttons in einer Reihe,
   jede in der Farbe des entsprechenden ButtonStyle Enum. Aktive Choice
   bekommt einen orange Ring drumrum damit die Wahl klar sichtbar ist. */
.vb-vp-btn-styles {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 6px;
}
.vb-vp-btn-choice {
  display: inline-flex;
  align-items: center;
  padding: 8px 16px;
  font-size: 13px;
  font-weight: 600;
  color: #fff;
  background: #4f545c;
  border: 0;
  border-radius: 4px;
  cursor: pointer;
  font-family: inherit;
  transition: filter .12s ease, box-shadow .12s ease, transform .08s ease;
  box-shadow: inset 0 -1px 0 rgba(0,0,0,0.18);
}
.vb-vp-btn-choice:hover  { filter: brightness(1.1); }
.vb-vp-btn-choice:active { transform: translateY(1px); }
.vb-vp-btn-choice.is-active {
  box-shadow: inset 0 -1px 0 rgba(0,0,0,0.18), 0 0 0 2px var(--orange);
}
/* Discord Button-Style Farben — 1:1 wie sie posted aussehen werden. */
.vb-vp-btn--link      { background: #4f545c; color: #fff; }     /* Link = Secondary chrome + Link-Icon */
.vb-vp-btn--primary   { background: #5865f2; }                  /* Blurple */
.vb-vp-btn--secondary { background: #4f545c; }
.vb-vp-btn--success   { background: #248046; }
.vb-vp-btn--danger    { background: #da373c; }
/* Live Button-Preview innerhalb des Embed-Editors. Wird vor dem
   Zeitstempel-Toggle injected; layout-mäßig wie Discord eine ActionRow
   die direkt unter dem Embed-Body sitzt. Bei mehreren Buttons würde
   flex-wrap eine zweite Zeile öffnen. */
.vb-vp-btn-preview-mount {
  margin: 8px 0 4px;
  padding-left: 0;   /* flush mit der Embed-Color-Bar */
}

/* Role-Reactions Live-Preview Komponenten. Werden in dieselbe
   .vb-vp-btn-preview-mount Stelle injected — je nach trigger_mode
   entweder Buttons (siehe oben), Dropdown-Mock oder Reaction-Pill-Reihe. */
.vb-rr-select-mock {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 10px 12px;
  background: #1e1f22;
  border: 1px solid #3a3c43;
  border-radius: 4px;
  color: #b5bac1;
  font-size: 14px;
  max-width: 400px;
}
.vb-rr-select-mock-label { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vb-rr-reactions-row {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}
.vb-rr-reaction-pill {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 8px;
  background: rgba(78, 80, 88, 0.32);
  border: 1px solid rgba(78, 80, 88, 0.6);
  border-radius: 8px;
  font-size: 13px;
  color: #dbdee1;
  line-height: 1.6;
}
.vb-rr-reaction-count { font-size: 12px; color: #b5bac1; font-variant-numeric: tabular-nums; }
.vb-vp-btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.vb-vp-btn-preview {
  display: inline-flex;
  align-items: center;
  padding: 6px 14px;
  font-size: 13px;
  font-weight: 500;
  color: #fff;
  border-radius: 4px;
  font-family: inherit;
  box-shadow: inset 0 -1px 0 rgba(0,0,0,0.18);
  user-select: none;
  pointer-events: none;
}

/* Discord Link-Button hat das External-Link Icon RECHTS vom Label
   (kleines Quadrat mit Pfeil oben-rechts raus), nicht das Chain-Icon. */
.vb-vp-btn--link::after {
  content: "";
  width: 14px; height: 14px;
  margin-left: 6px;
  background-color: currentColor;
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'><path d='M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6'/><polyline points='15 3 21 3 21 9'/><line x1='10' y1='14' x2='21' y2='3'/></svg>") center/contain no-repeat;
          mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'><path d='M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6'/><polyline points='15 3 21 3 21 9'/><line x1='10' y1='14' x2='21' y2='3'/></svg>") center/contain no-repeat;
}

/* Ticket-System / Bans — 7-col list table:
   user-id | reason | banned-at | banned-by | duration | status | actions.
   Status pill chrome stripped per [[column-header-alignment]] so the
   header text aligns flush with cell content. */
.vb-tkbans-table .vb-ec-table-head,
.vb-tkbans-table .vb-ec-table-row {
  grid-template-columns: 220px 1fr 140px 220px 110px 90px 92px;
  /* User cells (col 1 + col 4) use the canonical avatar+@name+ID stack
     from [[user-display-avatar-name-id]] — 220px gives the avatar 32px
     plus name+ID column room to breathe without truncation. */
}
.vb-tkbans-table .vb-sg-actions-head > span { min-width: 60px; }
.vb-tkbans-table .vb-ec-table-row .vb-ec-status {
  padding: 0;
  background: transparent;
  border-radius: 0;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
}
.vb-tkbans-table .vb-ec-table-row .vb-ec-status.is-published { color: #4ade80; }
.vb-tkbans-table .vb-ec-table-row .vb-ec-status.is-draft     { color: var(--text-dim); }

/* DEVCON_BACK_LINK_v1 — global "← Zurück zu …" navigation link.
   Used at the top of any drill-down view (ticket subtabs inside a hub,
   future per-server drilldowns, etc.). Naked text-only chrome with a
   small chevron icon, orange on hover. Reusable across modules. */
.vb-back-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: transparent;
  border: 0;
  padding: 0;
  /* Parent layout already provides the top breathing room (page chrome
     gap above the content area). Mirror that visually below the link
     with a generous 28px so the next element doesn't crowd the link. */
  margin: 0 0 28px;
  color: var(--text-dim, var(--text-muted));
  font-family: inherit;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition: color .12s ease;
}
.vb-back-link:hover { color: var(--orange); }
.vb-back-link svg { transition: transform .12s ease; }
.vb-back-link:hover svg { transform: translateX(-2px); }

/* DEVCON_MODAL_TIGHT_v1 — uniform spacing for create/edit popups.
   Drop this class on the .dash-modal-body and every direct child gets
   the same 10px gap from its sibling. h3 → p (subhead title → desc)
   stays tight at 2px. h3 (section header) starts a new section with
   18px lead-in. First child has no top margin. Inputs/pickers/switches/
   mode-pills/steppers all reset their built-in margins to play nice.
   See [[modal-create-edit-pattern]]. */
.vb-modal-tight-body {
  padding-top: 16px;
}
.vb-modal-tight-body > * { margin: 0; }
.vb-modal-tight-body > * + * { margin-top: 10px; }
.vb-modal-tight-body > h3 {
  font-size: 14px;
  font-weight: 600;
  color: var(--text-bright);
  line-height: 1.3;
  margin-top: 18px;
}
.vb-modal-tight-body > h3:first-child { margin-top: 0; }
.vb-modal-tight-body > h3 + p {
  margin-top: 2px;
  font-size: 12px;
  color: var(--text-dim, var(--text-muted));
  line-height: 1.45;
}
/* Suppress defaults from reusable widgets so they don't double-pad. */
.vb-modal-tight-body > .vb-mode-pills { margin: 10px 0 0; }
.vb-modal-tight-body > .vb-num-stepper { margin-top: 10px; }
.vb-modal-tight-body > .vb-switch { margin: 10px 0 0; }

/* Ticket-System / Auto-Triage — 5-col list table:
   name | match-pattern | actions | status | actions. Status pill chrome
   stripped per [[column-header-alignment]]. */
.vb-tktrg-table .vb-ec-table-head,
.vb-tktrg-table .vb-ec-table-row {
  grid-template-columns: 200px 1.2fr 1.5fr 90px 92px;
}
.vb-tktrg-table .vb-sg-actions-head > span { min-width: 60px; }

.vb-tktrg-table .vb-ec-table-row .vb-ec-status {
  padding: 0;
  background: transparent;
  border-radius: 0;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
}
.vb-tktrg-table .vb-ec-table-row .vb-ec-status.is-published { color: #4ade80; }
.vb-tktrg-table .vb-ec-table-row .vb-ec-status.is-draft     { color: var(--text-dim); }

/* Ban-Modal: 3-column duration row (Tage / Stunden / Minuten). Each
   stepper hugs its label, no stretching, consistent gap. */
.vb-tk-dur-row {
  display: flex;
  gap: 14px;
  flex-wrap: wrap;
  margin-top: 6px;
}
.vb-tk-dur-field {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.vb-tk-dur-field .vb-tk-dur-label {
  font-size: 11px;
  font-weight: 600;
  color: var(--text-dim, var(--text-muted));
  text-transform: uppercase;
  letter-spacing: .04em;
}
.vb-tk-dur-field .vb-num-stepper { width: 110px; }

/* Ticket-System / Commands — 3-col list table (command / description / chevron).
   The chevron slot holds the expand-collapse arrow per row. Header has an
   empty 3rd cell so head + rows stay grid-aligned. */
.vb-tkcmds-table .vb-ec-table-head,
.vb-tkcmds-table .vb-ec-table-row {
  grid-template-columns: 180px 1fr 32px;
}
/* Default commands stay clickable (to expand) — they're "locked" in the
   sense that name/description aren't editable, NOT in the sense that the
   row is dead. Keep the hover styling. */
.vb-ec-table-row--locked { cursor: pointer; }

/* ─── Generic expandable-row pattern (DEVCON_ROW_EXPAND_v1) ────────────
   Drops a settings panel below any .vb-ec-table-row. Other modules reuse:
   wrap the row in .vb-ec-row-expand-host, emit a sibling .vb-ec-row-expand
   block, toggle .is-expanded on host + row. When expanded the host
   reads as ONE card — row + panel share background + box-shadow outline,
   no internal divider, no enter-animation, no layout shift on toggle. */
.vb-ec-row-expand-host {
  border-bottom: 1px solid rgba(255,255,255,.04);
}
.vb-ec-row-expand-host:last-child { border-bottom: 0; }
/* Row inside the host owns no separator — host handles it. */
.vb-ec-row-expand-host .vb-ec-table-row { border-bottom: 0; }
.vb-ec-row-chevron {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--text-dim, var(--text-muted));
  transition: transform .15s ease, color .15s ease;
  pointer-events: none;
}
.vb-ec-table-row:hover .vb-ec-row-chevron { color: var(--text); }
.vb-ec-table-row.is-expanded .vb-ec-row-chevron {
  transform: rotate(180deg);
  color: var(--orange);
}
.vb-ec-row-expand {
  padding: 4px 14px 16px;
}
.vb-ec-row-expand[hidden] { display: none; }
.vb-ec-row-expand-actions {
  display: flex;
  justify-content: flex-end;
  margin-top: 14px;
}
/* Expanded state — host becomes one unified card. box-shadow outline
   instead of a real border so toggling on/off doesn't shift surrounding
   rows by 1px or flash a half-painted border. Background tint stays
   subtle so nothing reads as "loud". */
.vb-ec-row-expand-host.is-expanded {
  background: rgba(255,255,255,.02);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.08);
  border-radius: 10px;
  border-bottom: 0;
}
/* Suppress the separator owned by the host IMMEDIATELY above an open
   card — otherwise you see a thin divider clipping the card's top edge. */
.vb-ec-row-expand-host:has(+ .vb-ec-row-expand-host.is-expanded) {
  border-bottom-color: transparent;
}
/* Row inside an open card hugs the card padding + drops its hover wash */
.vb-ec-row-expand-host.is-expanded .vb-ec-table-row {
  padding-left: 14px;
  padding-right: 14px;
}
.vb-ec-row-expand-host.is-expanded .vb-ec-table-row::before { background: transparent; }
.vb-ec-row-expand-host.is-expanded .vb-ec-table-row:hover .vb-ec-row-embed-name { color: var(--text); }
/* Command modal: "/" prefix slot — same body font as everywhere else, no mono. */
.vb-tkcmd-modal .vb-tkcmd-name-row {
  display: flex;
  align-items: stretch;
  gap: 0;
  border: 1px solid var(--border, #1a1a1e);
  border-radius: 8px;
  background: rgba(255,255,255,.02);
  overflow: hidden;
}
.vb-tkcmd-modal .vb-tkcmd-slash {
  display: inline-flex;
  align-items: center;
  padding: 0 10px;
  background: rgba(255,255,255,.04);
  color: var(--text-dim, var(--text-muted));
  font-weight: 600;
  border-right: 1px solid var(--border, #1a1a1e);
}
.vb-tkcmd-modal .vb-tkcmd-name-row .dash-modal-input {
  border: 0;
  border-radius: 0;
  background: transparent;
  flex: 1 1 auto;
}

/* Ticket-System / Auto-Close bei Inaktivität — tight row for
   inactive-threshold / warn-hours / warn-target. Three fields side-by-side
   with a small gap, vs the wider .vb-ec-grid that paired fields use. */
.vb-tk-tight-row {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  align-items: flex-end;
  margin-top: 14px;
}
.vb-tk-tight-field {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}
.vb-tk-tight-field .dash-modal-label { margin-bottom: 0; }
.vb-tk-tight-field .vb-num-stepper { width: 110px; }

/* Warn-target row: label + pill-toggle sit between the enable switch
   and the threshold steppers. Pills hug their content (no stretch). */
.vb-tk-warn-target-label { margin-top: 14px; }
.vb-tk-warn-target-label + .vb-mode-pills { margin: 4px 0 0; }

/* Ticket-System: per-day office-hours schedule */
.vb-tk-schedule {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 6px;
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 8px;
  background: var(--bg-soft, rgba(255,255,255,0.02));
}
.vb-tk-schedule-row {
  display: grid;
  grid-template-columns: 200px 1fr;
  align-items: center;
  gap: 16px;
  padding: 6px 8px;
  border-radius: 8px;
}
.vb-tk-schedule-row:hover {
  background: rgba(255,255,255,0.02);
}
.vb-tk-schedule-day {
  /* uses .vb-switch base — just tighten gap + ensure label sits beside slider */
  gap: 10px;
}
.vb-tk-schedule-dayname {
  font-size: 13px;
  font-weight: 500;
  color: var(--text-bright);
}
.vb-tk-schedule-times {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.vb-tk-schedule-times[hidden] { display: none; }
/* Compact stepper variant for hour pickers in office-hours schedule */
.vb-num-stepper--hour {
  width: 72px;
  height: 32px;
}
.vb-num-stepper--hour input[type="number"] {
  font-size: 13px;
  padding: 0 4px;
}
.vb-tk-schedule-sep {
  color: var(--text-muted);
  font-weight: 600;
  padding: 0 2px;
}
.vb-tk-schedule-unit {
  font-size: 12px;
  color: var(--text-muted);
}
.vb-tk-schedule-closed {
  font-size: 12px;
  color: var(--text-muted);
  font-style: italic;
}
.vb-tk-schedule-closed[hidden] { display: none; }
@media (max-width: 540px) {
  .vb-tk-schedule-row {
    grid-template-columns: 1fr;
    gap: 4px;
  }
}

/* Sub-label under mode-pill main text (used in transcript format pills) */
.vb-pill-sub {
  font-size: 10px;
  font-weight: 500;
  color: var(--text-muted);
  margin-left: 4px;
  text-transform: none;
  letter-spacing: 0;
}
/* When the parent pill is active (orange bg + near-black text), the
   grey muted sub-label drops to ~0 contrast against orange. Bump it to
   a darker neutral so it stays legible inside the active state. */
.vb-mode-pill.is-active .vb-pill-sub {
  color: rgba(10, 10, 10, .65);
}

/* Vertical switch stack — used wherever multiple .vb-switch toggles
   need to render below each other instead of as inline-flex siblings.
   The base .vb-switch is inline-flex, so we override the child
   display + collapse any leftover top-margins on stacked rows. */
.vb-switch-stack {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 10px;
}
.vb-switch-stack > .vb-switch {
  display: flex;
  margin-top: 0;
}

/* ─── Games-Overview tiles ──────────────────────────────────────────── */
.vb-game-tiles {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 12px;
  margin-top: 10px;
}
@media (max-width: 720px) {
  .vb-game-tiles { grid-template-columns: 1fr; }
}
.vb-game-tile {
  display: grid;
  grid-template-columns: 64px 1fr;
  gap: 12px;
  padding: 14px;
  background: rgba(255,255,255,0.03);
  border: 1px solid rgba(255,255,255,0.06);
  border-radius: 10px;
  cursor: pointer;
  text-decoration: none;
  color: var(--text);
  transition: background .15s, border-color .15s, transform .1s;
}
.vb-game-tile:hover {
  background: rgba(255,138,34,0.06);
  border-color: rgba(255,138,34,0.4);
}
.vb-game-tile:active { transform: translateY(1px); }
.vb-game-tile.is-on {
  border-color: rgba(74,222,128,0.35);
  background: rgba(74,222,128,0.04);
}
.vb-game-tile-icon {
  font-size: 36px;
  width: 64px;
  height: 64px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(255,255,255,0.04);
  border-radius: 8px;
}
.vb-game-tile-title {
  font-weight: 600;
  font-size: 15px;
  color: var(--text);
}
.vb-game-tile-status {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin: 2px 0 6px;
}
.vb-game-tile.is-on .vb-game-tile-status { color: #4ade80; }
.vb-game-tile p {
  margin: 0;
  font-size: 12.5px;
  color: var(--text-muted);
  line-height: 1.45;
}

/* ─── Sprint 4: TagScript editor + Triggers (DEVCON_TAGSCRIPT_v1) ─── */

/* Code-style textarea used for TagScript bodies */
.vb-tagscript-editor {
  font-family: ui-monospace, 'Menlo', 'Consolas', monospace;
  font-size: 12.5px;
  line-height: 1.45;
  background: #0e0e10;
  color: #e8e8ed;
  white-space: pre;
  overflow-x: auto;
  tab-size: 2;
}

/* Variable-cheatsheet chip strip below the editor */
.vb-tagscript-cheatsheet {
  margin-top: 8px;
}
.vb-tagscript-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}
.vb-tagscript-chip {
  background: rgba(255,138,34,0.08);
  border: 1px solid rgba(255,138,34,0.2);
  color: var(--orange);
  padding: 2px 7px;
  border-radius: 4px;
  font-family: ui-monospace, monospace;
  font-size: 10.5px;
  cursor: pointer;
  transition: background .12s;
}
.vb-tagscript-chip:hover {
  background: rgba(255,138,34,0.2);
}

/* Render-Preview output */
.vb-tagscript-preview {
  margin-top: 10px;
  padding: 12px 14px;
  background: rgba(255,255,255,0.02);
  border: 1px solid rgba(255,255,255,0.06);
  border-radius: 6px;
}
.vb-tagscript-preview-out {
  white-space: pre-wrap;
  font-size: 13px;
  line-height: 1.5;
  color: var(--text);
}
.vb-tagscript-preview-errs {
  margin-top: 8px;
  font-size: 11px;
  color: #fbbf24;
  background: rgba(251,191,36,0.06);
  padding: 6px 8px;
  border-radius: 4px;
}

/* Custom Command Modal: Simple ↔ Advanced mode pill row */
.vb-cc-mode {
  margin-top: 8px;
}

/* Built-in cmd permission row */
.vb-builtin-perm-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.vb-builtin-perm-row {
  display: grid;
  grid-template-columns: 120px auto auto 1fr;
  gap: 12px;
  align-items: center;
  padding: 6px 10px;
  background: rgba(255,255,255,0.025);
  border-radius: 6px;
  border: 1px solid transparent;
}
.vb-builtin-perm-row:hover {
  border-color: rgba(255,255,255,0.06);
}
.vb-builtin-perm-row code {
  background: transparent;
  font-weight: 600;
  color: var(--text);
}
.vb-bp-ch { font-family: ui-monospace, monospace; }

/* Gaming-platform pill selector inside the Social modal */
.vb-gaming-platforms {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 4px;
}
.vb-gaming-platform-pill {
  display: inline-flex;
  align-items: center;
  padding: 6px 14px;
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: 999px;
  cursor: pointer;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-muted);
  transition: background .12s, color .12s, border-color .12s;
}
.vb-gaming-platform-pill:hover { background: rgba(34,211,238,0.08); color: #67e8f9; }
.vb-gaming-platform-pill.is-active {
  background: rgba(34,211,238,0.14);
  border-color: rgba(34,211,238,0.5);
  color: #22d3ee;
}

/* 5-tile variant of the stat grid (Suggestions has 5 status buckets) */
.vb-stat-grid.vb-stat-grid--5 {
  grid-template-columns: repeat(5, 1fr);
}
@media (max-width: 900px) {
  .vb-stat-grid.vb-stat-grid--5 { grid-template-columns: repeat(2, 1fr); }
}

/* ─── Suggestions module cards (DEVCON_SUGGESTIONS_v1) ─────────────── */
.vb-suggestion-card {
  display: grid;
  grid-template-columns: 64px 1fr auto;
  gap: 12px;
  padding: 12px 14px;
  margin-top: 8px;
  background: rgba(255,255,255,0.025);
  border: 1px solid rgba(255,255,255,0.06);
  border-radius: 8px;
  transition: background .12s, border-color .12s;
}
.vb-suggestion-card:hover {
  background: rgba(255,255,255,0.04);
  border-color: rgba(255,255,255,0.12);
}
.vb-suggestion-vote {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 4px;
  background: rgba(255,255,255,0.04);
  border-radius: 8px;
  font-variant-numeric: tabular-nums;
  font-size: 11px;
  color: var(--text-muted);
}
.vb-suggestion-diff {
  font-size: 14px;
  font-weight: 700;
  margin: 2px 0;
}
.vb-suggestion-body { min-width: 0; }
.vb-suggestion-actions {
  display: flex;
  flex-direction: column;
  gap: 6px;
  align-items: stretch;
  align-self: center;
}
@media (max-width: 720px) {
  .vb-suggestion-card { grid-template-columns: 1fr; }
  .vb-suggestion-vote { flex-direction: row; gap: 14px; padding: 6px 10px; }
  .vb-suggestion-actions { flex-direction: row; }
}

/* ─── Suggestion Panels (DEVCON_SUGGESTION_PANELS_v1) ─────────────────── */
.vb-sg-panel-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  background: rgba(255,255,255,0.025);
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: 10px;
  margin-bottom: 8px;
  transition: background .15s, border-color .15s;
}
.vb-sg-panel-row:hover { background: rgba(255,255,255,0.045); border-color: rgba(255,255,255,0.14); }
.vb-sg-panel-row.is-disabled { opacity: 0.55; }
.vb-sg-panel-main { flex: 1 1 auto; min-width: 0; }
.vb-sg-panel-name {
  font-size: 14px;
  font-weight: 600;
  color: var(--text-bright);
  margin-bottom: 3px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.vb-sg-panel-sub {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 12px;
  color: var(--text-muted);
  min-width: 0;
}
.vb-sg-panel-ch {
  color: var(--text-bright);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex: 0 1 auto;
}
.vb-sg-panel-id {
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: 11px;
  color: var(--text-muted);
  opacity: 0.7;
}
.vb-sg-panel-actions { display: flex; gap: 6px; flex: 0 0 auto; }
.vb-sg-panel-row { cursor: pointer; }
.vb-sg-panel-row:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Editable title in the panel-settings modal header — reuses .vb-ie-title
   classes from the embed editor but un-italicizes the non-editing state
   (panel names are always set, so there's no placeholder). */
.vb-sg-panel-head .vb-ie-title-text:not([contenteditable="true"]) {
  font-style: normal;
  color: var(--text-bright);
  font-weight: 700;
}
.vb-sg-panel-head .vb-ie-title-text.is-placeholder {
  color: var(--text-muted);
  font-style: italic;
  font-weight: 500;
}

/* Feature blocks with progressive disclosure */
.vb-sg-feature {
  margin-top: 16px;
  padding: 12px 14px;
  background: rgba(255,255,255,0.02);
  border: 1px solid rgba(255,255,255,0.07);
  border-radius: 8px;
}
.vb-sg-feature--top { margin-top: 18px; }
.vb-sg-feature-title {
  font-size: 14px;
  color: var(--text-bright);
  font-weight: 500;
}
.vb-sg-feature .vb-switch-label {
  font-weight: 500;
  color: var(--text-bright);
  font-size: 14px;
}
.vb-sg-feature-desc {
  margin: 4px 0 0;
  padding-left: 0;             /* aligns with the slider's left edge above */
  font-size: 12px;
  line-height: 1.5;
  color: var(--text-muted);
}
.vb-sg-feature-body {
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px dashed rgba(255,255,255,0.08);
}
.vb-sg-subfeature {
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px dashed rgba(255,255,255,0.05);
}
.vb-sg-subfeature .vb-switch-label { font-size: 13px; font-weight: 400; }
.vb-sg-subfeature .vb-sg-feature-desc { padding-left: 0; }

/* Clean number stepper — replaces browser-default spinner arrows */
.vb-num-stepper {
  display: inline-flex;
  align-items: stretch;
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.12);
  border-radius: 6px;
  overflow: hidden;
  height: 36px;
  width: 120px;
}
.vb-num-stepper input[type="number"] {
  flex: 1 1 auto;
  background: transparent;
  border: 0;
  outline: none;
  padding: 0 8px;
  color: var(--text-bright);
  font-size: 14px;
  font-family: inherit;
  text-align: center;
  -moz-appearance: textfield;
  min-width: 0;
}
.vb-num-stepper input[type="number"]::-webkit-outer-spin-button,
.vb-num-stepper input[type="number"]::-webkit-inner-spin-button {
  -webkit-appearance: none;
  appearance: none;
  margin: 0;
}
.vb-num-stepper-btns {
  display: flex;
  flex-direction: column;
  border-left: 1px solid rgba(255,255,255,0.08);
  flex: 0 0 22px;
}
.vb-num-stepper button {
  flex: 1 1 50%;
  background: transparent;
  border: 0;
  color: var(--text-muted);
  cursor: pointer;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: color .12s, background .12s;
}
.vb-num-stepper button:hover { color: var(--text-bright); background: rgba(255,255,255,0.05); }
.vb-num-stepper button + button { border-top: 1px solid rgba(255,255,255,0.08); }
.vb-num-stepper button svg { width: 10px; height: 10px; display: block; }
.vb-num-stepper:focus-within { border-color: var(--orange); }

/* Horizontal stepper variant — left chevron / input / right chevron.
   Used for "order/rank" fields where left/right maps to up/down in
   a list. Same chrome as the vertical stepper, layout reversed. */
.vb-num-stepper--horiz {
  display: inline-flex;
  align-items: stretch;
  width: auto;
  height: 36px;
}
.vb-num-stepper--horiz > .vb-num-stepper-btns { display: none; }
.vb-num-stepper--horiz > button {
  flex: 0 0 32px;
  background: transparent;
  border: 0;
  color: var(--text-dim, var(--text-muted));
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: color .12s, background .12s;
}
.vb-num-stepper--horiz > button:hover {
  color: var(--text-bright);
  background: rgba(255,255,255,.05);
}
.vb-num-stepper--horiz > input[type="number"] {
  width: 70px;
  flex: 0 0 70px;
  border-left:  1px solid rgba(255,255,255,.08);
  border-right: 1px solid rgba(255,255,255,.08);
  text-align: center;
  padding: 0 4px;
}

/* Embed-template tile inside the panel modal */
.vb-sg-embed-tile {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  background: rgba(255,255,255,0.03);
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: 8px;
  margin-top: 6px;
}
.vb-sg-embed-tile-info { flex: 1 1 auto; min-width: 0; }
.vb-sg-embed-tile-name {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-bright);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.vb-sg-embed-tile-mode {
  font-size: 11px;
  color: var(--text-muted);
  margin-top: 2px;
}

/* Emoji chip-row inside the panel-settings modal */
.vb-sg-emoji-row {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 6px;
  padding: 2px 6px 6px 2px;   /* room for the absolute-positioned × badges */
}
.vb-sg-emoji-row .vb-emoji-clear {
  opacity: 1;                 /* always visible on chips */
  background: transparent;
  border: 0;
  border-radius: 0;
  width: auto;
  height: auto;
  top: -10px;
  right: -6px;
  font-size: 21px;            /* 30% bigger than previous 16px */
  line-height: 1;
  transition: color .15s ease, transform .15s ease;
}
.vb-sg-emoji-row .vb-emoji-clear:hover {
  background: transparent;
  border: 0;
  color: #ed4245;             /* Discord red */
  transform: rotate(90deg);
}

/* Mod-Panel sub-tab — inline editor host */
.vb-sg-lastupd {
  margin-top: 8px;
  font-size: 11px;
  color: var(--text-muted);
  text-align: right;
}

/* "Letzte Vorschläge" table — mirrors the embed-list table but with custom
   columns. 6 columns: Ersteller, Vorschlag, Reaktionen, Status, Zeit, Actions. */
.vb-sg-table .vb-ec-table-head,
.vb-sg-table .vb-ec-table-row {
  grid-template-columns: 180px 140px 1fr 110px 140px 130px 200px;
  align-items: center;            /* all cells centered on a single baseline */
}
/* Every grid cell is a flex container so inline content (like the panel-tag
   span) sits at the same vertical baseline as the block-level cells (author,
   time, content). Without this, inline-only cells anchor to the text-baseline
   of an empty line-box and appear higher than the rest of the row. */
.vb-sg-table .vb-ec-table-row > div {
  display: flex;
  align-items: center;
  min-width: 0;
}
.vb-sg-panel-tag {
  color: var(--orange);
  font-size: 13px;                /* same as author name + content */
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  display: inline-block;
  max-width: 100%;
  line-height: 1.3;
}
.vb-sg-panel-tag.is-empty { color: var(--text-muted); font-weight: 400; }
/* Content can wrap up to 2 lines — when it does, the cell still stays
   centered because of align-items: center on the row. */
.vb-sg-content { line-height: 1.4; }

/* Header cell for the "Aktionen" column — the label sits over the icon
   cluster, not the empty left side. We push it to the right of the cell
   (`justify-content: flex-end`) and pin the inner span to the same width
   as the cluster (5 buttons × 28px + 4 × 4px gap = 156px), text-aligned
   left so "Aktionen" starts exactly where the leftmost icon starts. */
.vb-sg-actions-head {
  display: flex;
  justify-content: flex-end;
}
.vb-sg-actions-head > span {
  display: inline-block;
  /* Default = 5-icon cluster (suggestions list + panel-view modal):
     5 buttons × 28px + 4 gaps × 4px = 156px. Per-table overrides below
     adjust for 3-icon (sticky) and 2-icon (custom-commands) clusters so
     the "Aktionen" label always starts where the leftmost icon starts. */
  min-width: 156px;
  text-align: left;
}
.vb-st-table        .vb-sg-actions-head > span { min-width: 92px;  }   /* sticky:           3 icons (28*3 + 4*2) */
.vb-cc-table        .vb-sg-actions-head > span { min-width: 60px;  }   /* custom-cmds:      2 icons (28*2 + 4*1) */
.vb-ec-list-table   .vb-sg-actions-head > span { min-width: 92px;  }   /* embeds list:      3 icons (28*3 + 4*2) */
.vb-soc-list-table  .vb-sg-actions-head > span { min-width: 92px;  }   /* social list:      3 icons (28*3 + 4*2) */
.vb-hlmod-list-table .vb-sg-actions-head > span { min-width: 60px;  }  /* hl-mod list:      2 icons (28*2 + 4) */
.vb-sg-panels-table .vb-sg-actions-head > span { min-width: 124px; }   /* suggestion list:  4 icons (28*4 + 4*3) */
.vb-sc-table        .vb-sg-actions-head > span { min-width: 92px;  }   /* stats-hubs list:  3 icons (28*3 + 4*2) */
.vb-tkcats-table    .vb-sg-actions-head > span { min-width: 92px;  }   /* ticket cats list: 3 icons (28*3 + 4*2) */

/* 8-column ticket-categories table: Emoji | Name | Label | Status | Offen | Geschlossen | Details | Aktionen */
.vb-tkcats-table .vb-ec-table-head,
.vb-tkcats-table .vb-ec-table-row {
  grid-template-columns: 56px 140px 1fr 110px 70px 110px 1fr auto;
}
.vb-tkcats-table .vb-ec-table-row .vb-ec-status {
  padding: 0;
  background: transparent;
  border-radius: 0;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
}
.vb-tkcats-table .vb-ec-table-row .vb-ec-status.is-published { color: #4ade80; }
.vb-tkcats-table .vb-ec-table-row .vb-ec-status.is-draft     { color: var(--text-dim); }
/* Name (intern) — matches sibling row text, no monospace, no dim. */
.vb-tkcats-table .vb-tkcats-key {
  font-size: 13px;
  color: var(--text);
  letter-spacing: 0;
  text-transform: none;
}
.vb-tkcats-table .vb-tkcats-emoji {
  font-size: 22px;
  line-height: 1;
  display: flex;
  align-items: center;
}
.vb-tkcats-table .vb-tkcats-count {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  font-size: 13px;
}
.vb-tkcats-table .vb-tkcats-count--open   { color: #4ade80; }
.vb-tkcats-table .vb-tkcats-count--closed { color: var(--text-dim); }
.vb-tkcats-table .vb-ec-table-head > div { padding-left: 0; }

/* 5-column stats-hubs table: Name | Typ | Status | Letztes Update | Aktionen */
.vb-sc-table .vb-ec-table-head,
.vb-sc-table .vb-ec-table-row {
  grid-template-columns: 1fr 140px 110px 160px 50px;
}
/* Strip pill chrome for Stats-Hubs rows — column header is plain text at
   the column edge, so the value below must also start there. Status
   color comes from the `is-published` / `is-draft` modifier (keeps the
   semantic "active vs pending" color cue), no rounded box. */
.vb-sc-table .vb-ec-table-row .vb-ec-status {
  padding: 0;
  background: transparent;
  border-radius: 0;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
}
.vb-sc-table .vb-ec-table-row .vb-ec-status.is-published { color: #4ade80; }
.vb-sc-table .vb-ec-table-row .vb-ec-status.is-draft     { color: var(--text-dim); }

/* Sortable header (Reaktionen) — click cycles default → desc → asc → default.
   Hover orange; active state stays orange + shows the chevron. */
.vb-sg-sortable {
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  user-select: none;
  transition: color .12s ease;
}
.vb-sg-sortable:hover { color: var(--orange); }
.vb-sg-sortable.is-sort-active { color: var(--orange); }
.vb-sg-sortable svg { flex: 0 0 auto; }

/* Panel-view modal — same table layout as "Letzte Vorschläge" + filter bar
   + pager. Tall enough that the filter dropdown's portaled menu always
   has room without overlapping the table or pager. */
.vb-sg-pv-modal {
  max-width: 1140px;
  width: 96vw;
  min-height: 640px;             /* enough vertical real estate for 10 rows + filter + pager */
  max-height: 90vh;
  display: flex;
  flex-direction: column;
}
.vb-sg-pv-modal .dash-modal-body { flex: 1 1 auto; overflow-y: auto; }
.vb-sg-pv-filterbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 14px;
}
.vb-sg-pv-total {
  font-size: 12px;
  color: var(--text-muted);
}
.vb-sg-table--pv .vb-ec-table-head,
.vb-sg-table--pv .vb-ec-table-row {
  grid-template-columns: 180px 130px 1fr 140px 130px 110px 200px;
}

/* Pager — naked icon chevrons + numeric buttons, current page in orange. */
.vb-sg-pv-pager {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  margin-top: 16px;
  flex-wrap: wrap;
}
.vb-sg-pv-pg {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 28px;
  height: 28px;
  padding: 0 8px;
  background: transparent;
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: 6px;
  color: var(--text-muted);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
  transition: color .12s, border-color .12s, background .12s;
}
.vb-sg-pv-pg:hover:not(:disabled) {
  color: var(--text-bright);
  border-color: rgba(255,255,255,0.18);
  background: rgba(255,255,255,0.03);
}
.vb-sg-pv-pg.is-active {
  color: var(--orange);
  border-color: var(--orange);
  background: rgba(255,138,34,0.06);
}
.vb-sg-pv-pg:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}
.vb-sg-pv-pg--gap {
  border: 0;
  background: transparent;
  cursor: default;
}
.vb-sg-pv-pg--nav { color: var(--text-bright); }
.vb-sg-content {
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  color: var(--text);
  font-size: 13px;
  line-height: 1.45;
}
.vb-sg-author {
  font-size: 11px;
  color: var(--text-muted);
}
.vb-sg-anon {
  font-style: italic;
  color: var(--text-muted);
  font-size: 12px;
}
.vb-sg-reactions {
  display: inline-flex;
  gap: 10px;
  flex-wrap: wrap;
  font-size: 13px;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
  line-height: 1.2;
}
.vb-sg-reaction {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.vb-sg-reaction em {
  font-style: normal;
  font-size: 12px;
  color: var(--text-bright);
}
.vb-sg-status-pill {
  display: inline-flex;
  align-items: center;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
}
.vb-sg-status-pill.is-open        { background: rgba(156,163,175,.12); color: #d4d8de; }
.vb-sg-status-pill.is-considered  { background: rgba(251,191,36,.14);  color: #fbbf24; }
.vb-sg-status-pill.is-approved    { background: rgba(74,222,128,.14);  color: #4ade80; }
.vb-sg-status-pill.is-implemented { background: rgba(255,138,34,.14);  color: var(--orange); }
.vb-sg-status-pill.is-denied      { background: rgba(239,68,68,.14);   color: #ef4444; }

/* Status-action color modifiers for the global .dash-row-act buttons.
   Match the semantic palette used in the stat-tile variants. The base
   scale-up hover (1.15) comes from .dash-row-act itself — no rotate. */
.dash-row-act--approve:hover   { color: #4ade80; }
.dash-row-act--deny:hover      { color: #ef4444; }
.dash-row-act--consider:hover  { color: #fbbf24; }
.dash-row-act--implement:hover { color: var(--orange); }

/* Author cell — avatar (left) + name on top, discord-id muted underneath. */
.vb-sg-author-cell {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}
.vb-sg-avatar {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  flex: 0 0 28px;
  object-fit: cover;
  background: rgba(255,255,255,0.04);
}
.vb-sg-author-info { min-width: 0; }
.vb-sg-author-name {
  font-size: 13px;
  font-weight: 500;
  color: var(--text-bright);
  line-height: 1.1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.vb-sg-author-id {
  font-size: 10.5px;
  color: var(--text-muted);
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  margin-top: 2px;
}

@media (max-width: 980px) {
  .vb-sg-table .vb-ec-table-head { display: none; }
  .vb-sg-table .vb-ec-table-row {
    grid-template-columns: 1fr;
    gap: 6px;
    padding: 12px;
  }
}

.vb-sg-modbtn-actions {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 12px;
  margin-top: 10px;
}
@media (max-width: 720px) { .vb-sg-modbtn-actions { grid-template-columns: 1fr; } }
.vb-sg-modbtn-card {
  background: rgba(255,255,255,0.025);
  border: 1px solid rgba(255,255,255,0.07);
  border-radius: 10px;
  padding: 12px 14px;
}
.vb-sg-modbtn-card-head {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 4px;
}
/* Status icons — same Feather glyphs as the row-action icons in "Letzte
   Vorschläge". One color per action so the meaning is recognisable at a
   glance and consistent across the whole module. */
.vb-sg-modbtn-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 18px;
  width: 18px;
  height: 18px;
}
.vb-sg-modbtn-icon--approve   { color: #4ade80; }
.vb-sg-modbtn-icon--deny      { color: #ef4444; }
.vb-sg-modbtn-icon--consider  { color: #fbbf24; }
.vb-sg-modbtn-icon--implement { color: var(--orange); }
.vb-sg-modbtn-card-title {
  font-size: 14px;
  font-weight: 600;
  color: var(--text-bright);
  flex: 1 1 auto;
}
/* "Add-On Embed posten" row — toggle on the left, pencil-edit on the right. */
.vb-sg-modbtn-embedrow {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px dashed rgba(255,255,255,0.08);
}
/* Pencil → status-embed editor. Naked icon, hover-orange + rotate, per
   project [[close-x-style]] generalization. */
.vb-sg-modbtn-edit {
  background: transparent;
  border: 0;
  padding: 0;
  margin: 0;
  color: var(--text-muted);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  transition: color .15s ease, transform .15s ease;
  flex: 0 0 22px;
}
.vb-sg-modbtn-edit:hover {
  color: var(--orange);
  transform: rotate(90deg);
}

.vb-sg-modpanel-host {
  background: rgba(255,255,255,0.02);
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: 10px;
  padding: 18px;
}

/* Inline embed-editor variant — no modal wrapper, just toolbar + canvas. */
.vb-ie-inline { display: block; }
.vb-ie-inline .vb-ie-toolbar { margin-bottom: 16px; }

/* Single-embed editor mode — hides per-embed dup/del + add-more controls.
   Applied for the mod-panel editor and for the action-status embed editors. */
.vb-ie-canvas--single .vb-ie-embed-actions,
.vb-ie-canvas--single .vb-ie-add-embed { display: none !important; }
/* Static "Mod-Panel" title — un-italic, no pencil, no hover effect */
.vb-ie-title-text--static {
  font-style: normal !important;
  cursor: default !important;
  background: transparent !important;
  box-shadow: none !important;
}
/* Give the V2-components picker enough room — it's absolutely-positioned
   right of the embed and grows downward as items are added. Without a
   min-height the host clips the picker's bottom. */
.vb-ie-canvas--modpanel .vb-ie-embed-wrap.is-v2 { min-height: 320px; }
/* In mod-panel mode there's no trash+dup action stack on the right, so the
   V2 picker can sit closer to the embed (default -194px accounts for that
   stack). */
.vb-ie-canvas--modpanel .vb-ie-v2-panel { right: -150px; }
/* singleEmbed canvas (used by Ticket Create-Embed + Default-Embed in
   Settings) has no trash / duplicate icons on the right, so the v2
   panel can sit much tighter — just a small gap from the embed edge
   instead of the 194px gap that accommodates the action icons. */
.vb-ie-canvas--single .vb-ie-v2-panel { right: -144px; }

/* ─── GLOBAL icon-button cleanup (DEVCON_EMBED_ICONS_NAKED_v1) ────────
   Color picker, eye (preview), delete, duplicate — strip box/border so
   they're just glyphs. Hover: rotate 90° + color shift (red for delete,
   orange for everything else). Applies to the entire embed editor. */
.vb-ie-embed-controls-left .vb-color-btn,
.vb-ie-embed-eye,
.vb-ie-embed-rm,
.vb-ie-embed-dup {
  background: transparent !important;
  border: 0 !important;
  border-radius: 0 !important;
  box-shadow: none !important;
  transition: color .15s ease, transform .15s ease !important;
}
.vb-ie-embed-controls-left .vb-color-btn:hover,
.vb-ie-embed-eye:hover,
.vb-ie-embed-rm:hover,
.vb-ie-embed-dup:hover {
  background: transparent !important;
  border: 0 !important;
  transform: rotate(90deg);
}
.vb-ie-embed-rm:hover  { color: #ed4245; }            /* destructive → red */
.vb-ie-embed-dup:hover,
.vb-ie-embed-eye:hover,
.vb-ie-embed-controls-left .vb-color-btn:hover { color: var(--orange); }

/* Mod-panel action-row inside the embed preview — sits below the embed body,
   above the timestamp toggle. Each button is clickable to edit label + style. */
.vb-ie-modpanel-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 8px 0 4px;
  padding-left: 0;             /* flush with the embed's color bar (Discord-style action row) */
}
.vb-ie-modpanel-btn {
  display: inline-flex;
  align-items: center;
  padding: 6px 14px;
  border: 0;
  border-radius: 4px;
  font-size: 13px;
  font-weight: 500;
  color: #fff;
  cursor: pointer;
  font-family: inherit;
  box-shadow: inset 0 -1px 0 rgba(0,0,0,0.18);
  transition: filter .12s, transform .08s;
}
.vb-ie-modpanel-btn:hover { filter: brightness(1.1); }
.vb-ie-modpanel-btn:active { transform: translateY(1px); }
.vb-ie-modpanel-btn.vb-ie-btn-style--secondary { color: #fff; }

/* Mod-button popover (label + style, no URL field) — leans on .vb-ie-popover */
.vb-modbtn-popover input[type="text"],
.vb-modbtn-popover #modBtnLabel {
  width: 100%;
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.12);
  border-radius: 6px;
  padding: 6px 10px;
  color: var(--text-bright);
  font-size: 13px;
  font-family: inherit;
  outline: none;
}
.vb-modbtn-popover #modBtnLabel:focus { border-color: var(--orange); }

/* Permissions tab — role-chip picker dropdown */
.vb-sg-roledd {
  z-index: 4000;
  width: 260px;
  max-height: 320px;
  display: flex;
  flex-direction: column;
  background: var(--bg-card, #15161a);
  border: 1px solid var(--border, #1a1a1e);
  border-radius: 8px;
  box-shadow: 0 12px 40px rgba(0,0,0,0.5);
  overflow: hidden;
}
.vb-sg-roledd .vb-picker-search {
  border: 0;
  border-bottom: 1px solid var(--border);
  background: rgba(255,255,255,0.03);
  padding: 8px 12px;
  color: var(--text-bright);
  outline: none;
  font-size: 13px;
}
.vb-sg-roledd .vb-picker-list { overflow-y: auto; max-height: 268px; }
.vb-sg-roledd .vb-picker-row {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  background: transparent;
  border: 0;
  padding: 8px 12px;
  color: var(--text-bright);
  cursor: pointer;
  font-size: 13px;
  text-align: left;
}
.vb-sg-roledd .vb-picker-row:hover { background: rgba(255,255,255,0.05); }
.vb-sg-roledd .vb-picker-dot {
  width: 10px; height: 10px; border-radius: 50%;
  flex: 0 0 10px;
}

/* ─── Sticky Messages table — embed-list pattern, custom columns ──── */
.vb-st-table .vb-ec-table-head,
.vb-st-table .vb-ec-table-row {
  grid-template-columns: 200px 180px 1fr 100px 130px 200px;
  align-items: center;
}
.vb-st-table .vb-ec-table-row > div { display: flex; align-items: center; min-width: 0; }
.vb-st-preview {
  font-size: 12px;
  color: var(--text-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  line-height: 1.4;
}
.vb-st-mode-pill {
  display: inline-flex;
  align-items: center;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
}
.vb-st-mode-pill.is-text  { background: rgba(156,163,175,.14); color: #d4d8de; }
.vb-st-mode-pill.is-embed { background: rgba(78,194,126,.14);  color: #4ec27e; }

/* Sticky modal — mode pills + dashed "+ Neue Einbettung" sitting on the
   same row. Pill wraps below on narrow modals. The create-pill is sized
   to match the height of the .dash-modal-input select that appears in
   embed-mode below it, so the two controls visually balance. */
.vb-st-mode-row {
  display: flex;
  align-items: stretch;
  gap: 8px;
  flex-wrap: wrap;
}
.vb-st-mode-row .vb-mode-pills { margin: 0; }
.vb-st-mode-row .vb-mode-pill--create {
  margin-left: auto;
  padding: 11px 18px;             /* matches .dash-modal-input padding ≈ height */
  font-size: 13px;
  border-radius: 999px;           /* full pill — matches the mode-pills selector next to it */
}

/* Embed picker — search bar + 3-cards grid (most recent / search matches) */
.vb-st-embed-search {
  position: relative;
  display: block;
}
.vb-st-embed-search-icon {
  position: absolute;
  left: 12px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--text-muted);
  pointer-events: none;
}
.vb-st-embed-search input.dash-modal-input {
  padding-left: 36px;
}
.vb-st-embed-grid {
  margin-top: 10px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.vb-st-embed-card {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px 10px 18px;       /* 18px left to clear the absolute color stripe */
  background: rgba(255,255,255,0.025);
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: 8px;
  cursor: pointer;
  text-align: left;
  width: 100%;
  transition: border-color .12s, background .12s;
  min-width: 0;
  position: relative;
  overflow: hidden;
}
.vb-st-embed-card:hover {
  border-color: rgba(255,138,34,0.4);
  background: rgba(255,138,34,0.04);
}
.vb-st-embed-card.is-selected {
  border-color: var(--orange);
  background: rgba(255,138,34,0.08);
}
/* Color stripe — absolute so it spans the full card height (top edge to
   bottom edge, no padding gap). Sits behind the border via the parent's
   overflow:hidden. */
.vb-st-embed-card-color {
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 4px;
}
.vb-st-embed-card-body {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}
.vb-st-embed-card-name {
  font-size: 13px;
  font-weight: 500;
  color: var(--text-bright);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.vb-st-embed-card.is-selected .vb-st-embed-card-name { color: var(--orange); }
.vb-st-embed-card-meta {
  font-size: 11px;
  color: var(--text-muted);
}
.vb-st-embed-card-id {
  font-size: 11px;
  color: var(--text-muted);
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  flex: 0 0 auto;
}
/* Eye-preview button — naked icon (per [[close-x-style]]), hover-orange. */
.vb-st-embed-card-eye {
  background: transparent;
  border: 0;
  padding: 0;
  width: 26px;
  height: 26px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--text-muted);
  cursor: pointer;
  transition: color .12s, transform .1s;
  flex: 0 0 26px;
}
.vb-st-embed-card-eye:hover {
  color: var(--orange);
  transform: scale(1.15);
}
.vb-st-embed-empty {
  padding: 14px;
  background: rgba(255,255,255,0.02);
  border: 1px dashed rgba(255,255,255,0.08);
  border-radius: 8px;
  color: var(--text-muted);
  font-size: 13px;
  text-align: center;
}

/* ─── Custom Commands table — embed-list pattern, custom columns ──── */
.vb-cc-table .vb-ec-table-head,
.vb-cc-table .vb-ec-table-row {
  grid-template-columns: 180px 200px 1fr 130px 100px 130px 130px;
  align-items: center;
}
.vb-cc-table .vb-ec-table-row > div { display: flex; align-items: center; min-width: 0; }
.vb-cc-trigger-cell {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}
.vb-cc-trig {
  display: inline-block;
  padding: 2px 7px;
  background: rgba(255,138,34,0.08);
  color: var(--orange);
  border-radius: 4px;
  font-size: 12px;
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
}
.vb-cc-desc {
  font-size: 12px;
  color: var(--text-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ─── Page transitions (DEVCON_PAGE_TRANSITIONS_v1) ───────────────────
   Cross-fade content swaps so tab clicks don't feel jumpy. opacity +
   transform are GPU-composited and don't trigger layout. */
#vbContent {
  transition: opacity .14s ease-out, transform .18s ease-out;
  will-change: opacity;
}
#vbContent.vb-fading-out {
  opacity: 0;
  transform: translateY(2px);
}
#vbContent.vb-fading-in {
  opacity: 0;
  transform: translateY(4px);
}
@media (prefers-reduced-motion: reduce) {
  #vbContent, #vbContent.vb-fading-out, #vbContent.vb-fading-in {
    transition: none !important;
    transform: none !important;
    opacity: 1 !important;
  }
}

/* Spinner is still used as a fallback but the new pattern is shimmer skeletons.
   Anything with .vb-skel-block fades through a moving highlight to imply
   loading without spinning, which feels heavier on smaller cards. */
.vb-skel-block {
  background: linear-gradient(90deg,
    rgba(255,255,255,0.025) 0%,
    rgba(255,255,255,0.06)  50%,
    rgba(255,255,255,0.025) 100%);
  background-size: 200% 100%;
  animation: vb-skel-pulse 1.4s ease-in-out infinite;
  border-radius: 6px;
}
@keyframes vb-skel-pulse {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
@media (prefers-reduced-motion: reduce) {
  .vb-skel-block { animation: none; }
}

/* DEVCON_BS_EMBED_v1 — mini default-embed editor for Bot Settings.
   Reuses the editor's own .vb-ie-embed-controls-left + .vb-color-btn +
   .vb-ie-embed-eye classes so the left icons are visually identical to
   the global embed editor. Layout is simple flex (no absolute -44px
   offset). Only the author + footer are editable; title/desc are muted
   hints; no thumbnail / image / fields / timestamp. */
.vb-bsembed {
  display: flex;
  gap: 4px;                     /* matches the visual rhythm of the editor (12px between button-edge and embed-edge after the -44px offset becomes inline) */
  align-items: flex-start;
  max-width: 480px;             /* ~20% narrower than the editor's 576px since this preview has no thumbnail/image */
}
/* When the controls-left stack sits inside our wrapper, override the
   absolute -44px offset so it flows in the flex layout. */
.vb-bsembed .vb-ie-embed-controls-left {
  position: static;
  left: auto;
  top: auto;
  flex: 0 0 auto;
}
.vb-bsembed-body { flex: 1 1 auto; min-width: 0; }
/* Editable spans: faint dotted outline on hover so users can tell they
   can click in. Goes flush when they actually focus. */
.vb-bsembed-edit {
  outline: none;
  border-radius: 4px;
  padding: 1px 4px;
  margin: -1px -4px;
  transition: background .12s;
}
.vb-bsembed-edit:hover { background: rgba(255,255,255,0.04); }
.vb-bsembed-edit:focus { background: rgba(255,140,26,0.08); }
/* Placeholder via data-ph when empty. */
.vb-bsembed-edit:empty::before {
  content: attr(data-ph);
  color: var(--text-muted);
  opacity: 0.55;
}
/* Preview-mode: hide edit affordances, hide placeholder hints. */
.vb-bsembed-body.is-preview .vb-bsembed-edit { background: transparent !important; }
.vb-bsembed-body.is-preview .vb-bsembed-edit:empty::before { content: ''; }
.vb-bsembed-body.is-preview .vb-ie-preview-hint { display: none; }
/* Empty author/footer rows in preview mode → hide entirely if their text + icon are both unset */
.vb-bsembed-body.is-preview .vb-bsembed-author:has(.vb-bsembed-edit:empty):has(.vb-ie-icon-ph svg) { display: none; }
.vb-bsembed-body.is-preview .vb-bsembed-footer:has(.vb-bsembed-edit:empty):has(.vb-ie-icon-ph svg) { display: none; }

/* DEVCON_BOT_FLAG_PICKER_v1 — round flag buttons for the bot-language
   picker in Settings → Sprache & Zeitzone. Mirrors the header's
   .lang-flag-btn look but uses a distinct class so it doesn't share the
   global click handler that switches the dashboard UI language. */
.vb-bot-flag-row { display: flex; gap: 12px; margin-top: 6px; }
.vb-bot-flag-btn {
  width: 38px; height: 38px;
  padding: 0;
  border-radius: 50%;
  background: transparent;
  border: 2px solid transparent;
  cursor: pointer;
  display: grid; place-items: center;
  transition: all 200ms ease;
  opacity: 0.55;
}
.vb-bot-flag-btn svg {
  display: block;
  width: 30px; height: 30px;
  border-radius: 50%;
  transition: transform 200ms ease;
}
.vb-bot-flag-btn:hover { opacity: 0.9; }
.vb-bot-flag-btn:hover svg { transform: scale(1.08); }
.vb-bot-flag-btn.active {
  opacity: 1;
  border-color: rgba(255, 140, 26, 0.7);
  box-shadow: 0 0 0 1px rgba(255, 140, 26, 0.1);
}

/* DEVCON_TK_PICKER_MOUNT_v1 — injected inside `.vb-ie-embed-wrap` right
   before `.vb-ie-embed-toggles` (the Zeitstempel checkbox), so the
   picker sits between the embed body and the toggle — matching the
   real Discord position of action-row components right under the
   embed. No extra indent: the wrap already aligns with the color bar. */
.vb-tk-picker-mount {
  margin-top: 8px;
}

/* DEVCON_IE_NO_EMBED_v3 — "Nachricht"-only mode for the inline-embed-
   editor. Hides ONLY the embed card + the add-another CTAs. The
   .vb-mode-pills bar STAYS visible (otherwise the user has no way
   back to embed mode). Bot-avatar header + content textarea also stay
   visible so the admin sees the real Discord-style message preview.
   See [[text-mode-real-preview]]. */
.vb-ie-embed-host-wrap.is-no-embed .vb-ie-embed-wrap,
.vb-ie-embed-host-wrap.is-no-embed [data-ie-add-first],
.vb-ie-embed-host-wrap.is-no-embed [data-ie-add-another],
/* Back-compat with the original create-embed selector. */
#tkCreateEmbedWrap.is-no-embed .vb-ie-embed-wrap,
#tkCreateEmbedWrap.is-no-embed [data-ie-add-first],
#tkCreateEmbedWrap.is-no-embed [data-ie-add-another] {
  display: none !important;
}

/* DEVCON_TK_PICKER_PREVIEW_v2 — pixel-honest mock of Discord's three
   message-component flavours. Each preview is constrained to the
   embed's 520px max width so the admin sees exactly what the user will
   see in their server. Pointer-events disabled — pure presentation. */
.vb-tk-prev-dropdown,
.vb-tk-prev-buttons,
.vb-tk-prev-emojis { pointer-events: none; user-select: none; }
/* Bot-Personalisieren — small status pill next to each tier title.
   Default = grey (locked / needs token). is-unlocked = orange-on-dim
   (premium active for tier 1). */
.vb-pers-tier-tag {
  display: inline-block;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .04em;
  padding: 3px 8px;
  border-radius: 999px;
  background: rgba(255,255,255,.06);
  color: var(--text-dim, var(--text-muted));
  margin-left: 8px;
  vertical-align: middle;
  text-transform: uppercase;
}
.vb-pers-tier-tag.is-unlocked {
  background: rgba(255,138,34,.14);
  color: var(--orange);
}

/* Staff action row in the Created-Embed preview IS editable — re-enable
   pointer events for those specific buttons so the click-to-edit modal
   can open. Hover ring signals interactivity. */
#tkCreatedActionsPreview .vb-tk-prev-buttons,
#tkCreatedActionsPreview .vb-tk-prev-btn {
  pointer-events: auto;
}
#tkCreatedActionsPreview .vb-tk-prev-btn {
  cursor: pointer;
  transition: box-shadow .12s ease, transform .12s ease;
}
#tkCreatedActionsPreview .vb-tk-prev-btn:hover {
  box-shadow: 0 0 0 2px rgba(255,138,34,.45);
}

/* Ticket action-button edit modal — 4 Discord-button previews as the
   style picker. Each shows the live label+emoji so the user sees exactly
   what they're choosing. Orange ring marks the active style. */
.vb-tk-actbtn-modal { max-width: 520px; }
.vb-tk-actbtn-emoji-row {
  margin-top: 4px;
}
.vb-tk-style-picker {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 6px;
}
.vb-tk-style-opt {
  cursor: pointer;
  border: 0;
  /* Inherit .vb-tk-prev-btn dimensions (32px tall, 16px h-pad) but allow
     wider content so a long button label fits comfortably. */
  min-width: 96px;
  justify-content: center;
  transition: box-shadow .12s ease, transform .08s ease;
}
.vb-tk-style-opt:hover {
  box-shadow: 0 0 0 2px rgba(255,138,34,.35);
}
.vb-tk-style-opt.is-active {
  box-shadow: 0 0 0 2px var(--orange);
}
.vb-tk-style-opt:active { transform: scale(0.98); }
.vb-tk-style-opt [data-tkact-emoji]:empty { display: none; }
.vb-tk-style-opt [data-tkact-emoji] {
  display: inline-flex;
  align-items: center;
}
.vb-tk-style-opt [data-tkact-emoji] img {
  width: 18px; height: 18px;
}

/* Dropdown — Discord select-menu styling. Real Discord uses #2b2d31 bg
   with a 1px #1e1f22 border, font 16px, height ~44px. */
.vb-tk-prev-dropdown {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  height: 40px;
  background: #2b2d31;
  border: 1px solid #1e1f22;
  border-radius: 4px;
  padding: 0 16px;
  font-size: 15px;
  font-family: "gg sans","Inter",sans-serif;
  color: #dbdee1;
}
.vb-tk-prev-dropdown svg { color: #b5bac1; }

/* Buttons — Discord action-row buttons. Default gray = #4e5058, white
   text, 3px corners, 32px tall, 16px h-padding, 14px font. */
.vb-tk-prev-buttons {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.vb-tk-prev-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 32px;
  padding: 0 16px;
  background: #4e5058;   /* secondary — Discord gray */
  color: #fff;
  border: 0;
  border-radius: 3px;
  font-family: "gg sans","Inter",sans-serif;
  font-size: 14px;
  font-weight: 500;
  cursor: default;
  white-space: nowrap;
}
.vb-tk-prev-btn.is-danger  { background: #da373c; }   /* Discord destructive red */
.vb-tk-prev-btn.is-success { background: #248046; }   /* Discord success green */
.vb-tk-prev-btn.is-primary { background: #5865f2; }   /* Discord blurple */

/* Reactions row — message-level reactions sit RIGHT under the embed in
   real Discord, each in a rounded pill with a hover-orange ring. */
.vb-tk-prev-emojis {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 4px;
}
.vb-tk-prev-emoji {
  display: inline-flex;
  align-items: center;
  height: 22px;
  padding: 0 8px;
  background: rgba(88, 101, 242, 0.15);
  border: 1px solid rgba(88, 101, 242, 0.30);
  border-radius: 8px;
  font-size: 14px;
  line-height: 1;
}
