{{ selectedGuild.name }}
{{ role.toUpperCase() }}
{{ health.latency }}ms SSE {{ sseClients }} · Canvas {{ canvasSessions }} CPU {{ topMonitor.cpu }}% RAM {{ topMonitor.mem }}% Disk {{ topMonitor.disk }}% Redis {{ topMonitor.redis === true ? 'UP' : topMonitor.redis === false ? 'DOWN' : '…' }}
Owner
FrostBloom Viewer VIEWER - {{ selectedGuild.name }}
{{ error }}
{{ toast.message }}

Select a server to get started

{{ eventStatsHeader.totalEvents }}
Total Events
{{ eventStatsHeader.totalSignups }}
Total Signups
{{ eventStatsHeader.avgSignups }}
Avg Signups
{{ eventStatsHeader.uniqueParticipants }}
Unique Participants
{{ ev.title || 'Untitled' }}✎
{{ ev.type }}
{{ formatDate(ev.timestamp) }}
{{ ev.counts.main }}/{{ ev.counts.cap }} FULL {{ ev.counts.slots_left }} left
Bench: {{ ev.counts.bench }} | Absent: {{ ev.counts.absent }} | Tentative: {{ ev.counts.tentative }}
TANK {{ ev.role_breakdown.TANK }}
HEAL {{ ev.role_breakdown.HEAL }}
DPS {{ ev.role_breakdown.DPS }}
MAIN ({{ ev.main.length }})
{{ m.ign }}
BENCH ({{ ev.bench.length }}) {{ expandedBenches[ev.event_id] ? '▼' : '▶' }}
{{ b.ign }} {{ b.bench_reason === 'auto_bench' ? '🔴 Auto-bench' : '🔶 Bench' }}
{{ status }}
{{ name }}

No event data available for stats

{{ p.question }}
{{ p.active ? 'Active' : 'Closed' }}
{{ opt }} {{ p.vote_counts?.[idx] || 0 }}
Real-time collaborative drawing
Draw shapes, arrows, and freehand sketches together on a world map background. WebSocket-powered with editor/viewer roles.
Features:
Rectangles Ellipses Arrows Freehand Real-time cursor sync Editor/Viewer roles Map background

Select an event to view/create groups

No active events
Click a member to select as commander, then click a group header to assign
NOTES · {{ m.ign || m.user }}

Loading...

★ {{ m.order ? m.order + '. ' : '' }}{{ m.ign || m.user }} *Bench*
{{ cg.name || 'G' + cg.id }}
{{ m.weapon || 'No loadout' }}
{{ m.games }} {{ m.games === 1 ? 'game' : 'games' }}
Final groups posted — {{ formatDate(gwSnapshot.created_at) }} No final groups post yet
★ {{ getCommanderName(sq.leader_id) }}
{{ sq.members.length }}/5
★ {{ m.order ? m.order + '. ' : '' }}{{ m.ign || m.user }}
{{ m.weapon }}
{{ m.games }} {{ m.games === 1 ? 'game' : 'games' }}
Drop roster item here
+ free slot
{{ m.order ? m.order + '. ' : '' }}{{ m.ign || 'N/A' }}
{{ m.user }}
{{ m.weapon }}

No league roster data found

{{ (selectedMember.ign || selectedMember.user || '?').charAt(0).toUpperCase() }}
{{ selectedMember.ign || selectedMember.user }}
{{ selectedMember.weapon || 'No loadout' }}
Loading...
No notes yet
{{ note.tag }} {{ note.author_name }} · {{ timeAgo(note.created_at) }}
{{ note.content }}
{{ jungle.active ? 'Running' : 'Stopped' }}
C
{{ ch.name }}
⏱ ~{{ jungleEstimate.perCh }}s/ch · {{ jungleEstimate.n }} channels · ~{{ jungleEstimate.total }}s / {{ jungleEstimate.window }}s window
{{ formatTime(jungle.timing_session) }} session · {{ jungle.timing_windows.length }} window(s). Remaining mm:ss sets when the window triggers.
⚠ Over budget: trailing channels will be skipped.
Announce runs s into each window (0 = at window open · late values leave less room for the channel pass)
Time (remaining) Voice Line to Play Est. pass
~{{ jungleEstimate.total }}s
No windows configured — add one below.
Click a channel to toggle it on/off. Use arrows to adjust visit order.
#{{ channelSeqIndex(ch.id) + 1 }} ○ {{ ch.name }}

No voice channels available

? {{ ch.name }}
Connect Sound (First Join)
Default Announcement (Recurring)
Create unique phrases and map them to individual timing windows in the schedule.
{{ l.name }} {{ l.phrase }} {{ l.source === 'upload' ? (l.filename || 'upload') : 'TTS' }}
No custom lines yet — default announcement plays in all windows.
{{ howtoStep + 1 }} / {{ jungleHowtoSteps.length }}
{{ jungleHowtoSteps[howtoStep].t }}
{{ jungleHowtoSteps[howtoStep].d }}