twitch-byte-bot / dashboard /studio.html
JuanCS-Dev's picture
feat: O6 the duo (Mah + Byte)
9a67c60 verified
Raw History Blame Contribute Delete
12.3 kB
<!doctype html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="theme-color" content="#fff4ec" />
<title>Byte Studio · Painel do Streamer</title>
<link rel="manifest" href="/studio.webmanifest" />
<link rel="apple-touch-icon" href="/dashboard/icon-192.png" />
<link rel="stylesheet" href="/dashboard/styles/studio.css" />
<link rel="stylesheet" href="/dashboard/styles/tokens-studio.css" />
<link rel="stylesheet" href="/dashboard/styles/mascot.css" />
</head>
<body class="studio">
<div class="studio-shell">
<!-- Brand -->
<div class="studio-brand">
<div id="mahAvatar" class="mah-avatar studio-mah is-unseen" title="Mah"></div>
<div id="byteMascot" class="byte-mascot studio-byte" title="Byte"></div>
<span class="brand-mark">BYTE</span>
<span class="brand-tag">STUDIO</span>
<button id="customizeBtn" class="theme-toggle" type="button" aria-label="Customizar painel">
layout
</button>
<button id="themeToggle" class="theme-toggle" type="button" aria-label="Trocar tema">
tema: auto
</button>
</div>
<!-- Status (orb halo + health chip = one-glance operational truth) -->
<header id="studioStatus" class="studio-status">
<span id="statusOrb" class="status-orb"></span>
<div class="status-main">
<h1 id="statusTitle" class="status-title">Conectando…</h1>
<p id="statusSub" class="status-sub">carregando estado do Byte</p>
</div>
<div class="status-right">
<span id="healthChip" class="health-chip">—</span>
<div class="status-uptime">
<span>uptime</span>
<strong id="statusUptime">—</strong>
</div>
</div>
</header>
<!-- Byte copilot hint (optional, dismissible) -->
<div id="byteHint" class="byte-hint is-hidden" role="status">
<span class="byte-hint-icon" data-icon="zap"></span>
<span id="byteHintText" class="byte-hint-text"></span>
<button id="byteHintClose" class="byte-hint-close" type="button" aria-label="Dispensar">×</button>
</div>
<!-- Chat mood -->
<section class="studio-mood" aria-label="Humor do chat">
<div class="mood-row">
<span id="moodFace" class="mood-face" data-icon="faceNeutral"></span>
<div class="mood-text">
<span id="moodLabel" class="mood-label">lendo o chat</span>
<span class="mood-caption">humor do chat</span>
</div>
<span id="moodScore" class="mood-score">—</span>
</div>
<div class="mood-track">
<div id="moodFill" class="mood-fill" style="width: 0%"></div>
</div>
</section>
<!-- Vitals: live trends (sparklines) -->
<section class="studio-vitals" aria-label="Tendências">
<div class="vital">
<div class="vital-head"><span class="vital-label">humor</span><span id="vitalMoodVal" class="vital-val">—</span></div>
<svg class="vital-spark" viewBox="0 0 100 24" preserveAspectRatio="none" aria-hidden="true"><path id="sparkMood" class="spark-path" d="" /></svg>
</div>
<div class="vital">
<div class="vital-head"><span class="vital-label">atividade</span><span id="vitalActVal" class="vital-val">—</span></div>
<svg class="vital-spark" viewBox="0 0 100 24" preserveAspectRatio="none" aria-hidden="true"><path id="sparkActivity" class="spark-path" d="" /></svg>
</div>
<div class="vital">
<div class="vital-head"><span class="vital-label">saúde</span><span id="vitalHealthVal" class="vital-val">—</span></div>
<svg class="vital-spark" viewBox="0 0 100 24" preserveAspectRatio="none" aria-hidden="true"><path id="sparkHealth" class="spark-path" d="" /></svg>
</div>
</section>
<!-- Retention coach (shows when churn risk rises) -->
<section id="retentionBanner" class="retention is-hidden" aria-label="Risco de retenção">
<div class="retention-head">
<span id="retentionBand" class="retention-band">—</span>
<span id="retentionTitle" class="retention-title"></span>
</div>
<p id="retentionTactic" class="retention-tactic"></p>
</section>
<!-- Tiles -->
<section id="studioGrid" class="studio-grid" aria-label="Controles">
<button id="tilePause" class="tile tile-primary" type="button">
<span class="tile-ico" data-icon="pause"></span>
<span class="tile-label">PAUSAR</span>
<span class="tile-sub">Byte ativo agora</span>
</button>
<button id="tileSpeak" class="tile" type="button">
<span class="tile-ico" data-icon="message"></span>
<span class="tile-label">FALAR</span>
<span class="tile-sub">mande o Byte dizer algo</span>
</button>
<button id="tileHype" class="tile tile-live" type="button">
<span class="tile-ico" data-icon="zap"></span>
<span class="tile-label">HYPE</span>
<span class="tile-sub">solta energia no chat</span>
</button>
<button id="tileApprove" class="tile" type="button" disabled>
<span id="approveBadge" class="tile-badge is-hidden">0</span>
<span class="tile-ico" data-icon="check"></span>
<span class="tile-label">APROVAR</span>
<span class="tile-sub">nada pendente</span>
</button>
<button id="tileVision" class="tile" type="button">
<span class="tile-ico" data-icon="eye"></span>
<span class="tile-label">VISÃO</span>
<span class="tile-sub">—</span>
</button>
<button id="tileClips" class="tile" type="button">
<span class="tile-ico" data-icon="scissors"></span>
<span class="tile-label">CLIPES</span>
<span class="tile-sub">—</span>
</button>
<button id="tileChannels" class="tile" type="button">
<span class="tile-ico" data-icon="broadcast"></span>
<span class="tile-label">CANAIS</span>
<span class="tile-sub">entrar / sair</span>
</button>
<button id="tileAct" class="tile tile-primary" type="button">
<span class="tile-ico" data-icon="target"></span>
<span class="tile-label">AGIR</span>
<span class="tile-sub">Byte toma atitude agora</span>
</button>
<button id="tileRecap" class="tile" type="button">
<span class="tile-ico" data-icon="chart"></span>
<span class="tile-label">RECAP</span>
<span class="tile-sub">resumo da live</span>
</button>
</section>
<!-- Live ticker -->
<section class="studio-ticker" aria-label="Atividade ao vivo">
<div class="ticker-head">
<span class="ticker-pulse" data-icon="pulse"></span>
O que o Byte está fazendo
</div>
<ul id="tickerList" class="ticker-list">
<li class="ticker-empty">Carregando atividade…</li>
</ul>
</section>
<p class="studio-foot">
Modo simples para streamers ·
<a href="/">abrir painel ops avançado →</a>
</p>
</div>
<!-- Toast -->
<div id="studioToast" class="studio-toast" role="status" aria-live="polite"></div>
<!-- Command palette (Cmd/Ctrl+K) -->
<div id="commandPalette" class="cmd-palette" role="dialog" aria-modal="true" aria-label="Paleta de comandos">
<div class="cmd-box">
<input
id="cmdInput"
class="cmd-input"
type="text"
autocomplete="off"
placeholder="Buscar ação… (atalhos: P F H A V C G R T)"
aria-label="Buscar comando"
/>
<ul id="cmdList" class="cmd-list" role="listbox"></ul>
</div>
</div>
<!-- Speak modal -->
<div id="speakModal" class="studio-modal" role="dialog" aria-modal="true">
<div class="modal-card">
<h2>O que o Byte deve dizer?</h2>
<textarea
id="speakInput"
placeholder="Ex: Bem-vindos, galera! Curtam a live."
></textarea>
<div class="modal-actions">
<button id="speakCancel" class="btn-cancel" type="button">
Cancelar
</button>
<button id="speakSend" class="btn-send" type="button">Enviar</button>
</div>
</div>
</div>
<!-- Channels modal -->
<div id="channelsModal" class="studio-modal" role="dialog" aria-modal="true">
<div class="modal-card">
<h2>Conexão de canais</h2>
<p id="channelsStatus" class="modal-hint">Carregando canais…</p>
<input
id="channelInput"
type="text"
autocomplete="off"
placeholder="login do canal (sem @)"
/>
<div class="modal-actions">
<button id="channelPart" class="btn-cancel" type="button">Sair</button>
<button id="channelJoin" class="btn-send" type="button">Entrar</button>
</div>
<button id="channelsClose" class="btn-ghost" type="button">Fechar</button>
</div>
</div>
<!-- Approvals modal -->
<div id="approveModal" class="studio-modal" role="dialog" aria-modal="true">
<div class="modal-card">
<h2>Ações aguardando aprovação</h2>
<div id="approveList" class="approve-list">Carregando…</div>
<div class="modal-actions">
<button id="approveClose" class="btn-send" type="button">Fechar</button>
</div>
</div>
</div>
<!-- Recap modal -->
<div id="recapModal" class="studio-modal" role="dialog" aria-modal="true">
<div class="modal-card">
<h2>Resumo da live</h2>
<div id="recapBody" class="recap-body">Gerando…</div>
<div class="modal-actions">
<button id="recapClose" class="btn-send" type="button">Fechar</button>
</div>
</div>
</div>
<!-- Layout customization -->
<div id="layoutModal" class="studio-modal" role="dialog" aria-modal="true">
<div class="modal-card">
<h2>Customizar painel</h2>
<div class="layout-section">
<span class="layout-sub">Perfil</span>
<div class="layout-row">
<button class="layout-chip" data-profile="full" type="button">Completo</button>
<button class="layout-chip" data-profile="fps" type="button">FPS</button>
<button class="layout-chip" data-profile="chatting" type="button">Just Chatting</button>
</div>
</div>
<div class="layout-section">
<span class="layout-sub">Densidade</span>
<div class="layout-row">
<button class="layout-chip" data-density="comfortable" type="button">Confortável</button>
<button class="layout-chip" data-density="compact" type="button">Compacto</button>
</div>
</div>
<div class="layout-section">
<span class="layout-sub">Tiles (mostrar / reordenar)</span>
<ul id="layoutTiles" class="layout-tiles"></ul>
</div>
<div class="modal-actions">
<button id="layoutReset" class="btn-cancel" type="button">Resetar</button>
<button id="layoutClose" class="btn-send" type="button">Fechar</button>
</div>
</div>
</div>
<!-- Token gate -->
<div id="studioGate" class="studio-gate" role="dialog" aria-modal="true">
<div class="gate-card">
<span class="gate-ico" data-icon="key"></span>
<h2>Quase lá</h2>
<p>Cole seu token de acesso para liberar o painel.</p>
<input
id="gateInput"
type="password"
autocomplete="off"
placeholder="Token de admin"
/>
<button id="gateSave" type="button">Entrar</button>
<ol class="gate-steps">
<li><b>1.</b> Cole o token de admin acima</li>
<li><b>2.</b> Conecte seu canal no tile <b>CANAIS</b></li>
<li><b>3.</b> No OBS, adicione <code>/voice</code> e <code>/avatar</code></li>
</ol>
</div>
</div>
<script type="module" src="/dashboard/features/studio/main.js"></script>
</body>
</html>