game6 / client / public / index.html
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
<!doctype html>
<html lang="en" class="boot">
<head>
<meta charset="utf-8">
<title>ODEON</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover">
<meta name="theme-color" content="#120b0e">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="apple-mobile-web-app-title" content="ODEON">
<link rel="apple-touch-icon" href="./icons/apple-touch-icon.png">
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' rx='6' fill='%23120b0e'/%3E%3Cpath d='M16 5 C22 5 25 10 25 16 C25 22 22 27 16 27 C10 27 7 22 7 16 C7 10 10 5 16 5 Z' fill='none' stroke='%23ffb03a' stroke-width='2.2'/%3E%3Ccircle cx='16' cy='16' r='3.2' fill='%23ffb03a'/%3E%3C/svg%3E">
<link rel="manifest" href="./manifest.webmanifest">
<link rel="stylesheet" href="./style.css">
</head>
<body>
<div id="hud">
  <div id="logo">ODEON</div>
  <button id="copybtn" title="Copy invite link" data-i18n="hud.invite" data-i18n-attr="title:hud.invite.title">⧉ invite</button>
  <div id="status"><span id="statdot"></span><span id="stattext" data-i18n="hud.offline">offline</span></div>
</div>

<div id="stage"><canvas id="hall"></canvas></div>

<div id="controls" class="hidden">
  <div class="crow">
    <div id="transport">
      <button id="bpmdn" class="tbtn">−</button>
      <span id="bpmval">100</span><span class="bpmlbl">bpm</span>
      <button id="bpmup" class="tbtn">+</button>
      <span id="beatdots"><i></i><i></i><i></i><i></i></span>
    </div>
    <div id="recwrap">
      <button id="recbtn" class="tbtn" title="record a loop">●</button>
      <button id="lenbtn" class="tbtn">2bars</button>
      <div id="recbarwrap"><div id="recbar"></div></div>
    </div>
    <button id="metrobtn" class="tbtn" title="metronome (m)" data-i18n-attr="title:transport.metro.title">◭</button>
    <button id="hallbtn" class="tbtn" title="hall reverb" data-i18n-attr="title:transport.hall.title">≋</button>
  </div>
  <div class="crow">
    <div id="insttabs">
      <button class="itab" data-inst="0" title="grand piano" data-i18n-attr="title:tab.grand">🎹</button>
      <button class="itab" data-inst="1" title="drum pads" data-i18n-attr="title:tab.pads">🥁</button>
      <button class="itab" data-inst="2" title="theremin" data-i18n-attr="title:tab.theremin">👋</button>
      <button class="itab" data-inst="3" title="bass" data-i18n-attr="title:tab.bass">🎸</button>
      <button class="itab" data-inst="4" title="step off stage — watch from the house" data-i18n-attr="title:tab.watch">🎟</button>
    </div>
    <button id="clapbtn" class="tbtn" title="applaud" data-i18n-attr="title:transport.clap.title">👏</button>
    <div id="looprack"></div>
  </div>
</div>

<div id="instpanel" class="hidden"></div>

<!-- boot splash: shown from first paint until main.ts decides gate vs auto-join -->
<div id="ovSplash" class="overlay">
  <div class="panel">
    <div class="title">ODEON</div>
    <p id="splashmsg" class="sub"></p>
  </div>
</div>

<!-- join screen -->
<div id="ovJoin" class="overlay">
  <div class="panel">
    <div class="title">ODEON</div>
    <div class="sub" data-i18n="join.sub">a p2p concert hall — walk on stage, play together</div>
    <input id="nick" maxlength="32" placeholder="stage name" autocomplete="off" autocapitalize="off" spellcheck="false" data-i18n-attr="placeholder:join.nick">
    <div id="instpick">
      <button class="ipick on" data-inst="0"><b>🎹</b><span data-i18n="pick.grand">grand</span></button>
      <button class="ipick" data-inst="1"><b>🥁</b><span data-i18n="pick.pads">pads</span></button>
      <button class="ipick" data-inst="2"><b>👋</b><span data-i18n="pick.theremin">theremin</span></button>
      <button class="ipick" data-inst="3"><b>🎸</b><span data-i18n="pick.bass">bass</span></button>
      <button class="ipick" data-inst="4"><b>🎟</b><span data-i18n="pick.watch">watch</span></button>
    </div>
    <button id="playbtn" class="big" data-i18n="join.play">Take the stage</button>
    <button id="sharebtn" class="big ghost" data-i18n="lobby.share">📤 invite friends</button>
    <div class="hint" id="joinhint"><span data-i18n="join.hint.notes">live notes travel the wind · recorded loops lock to the shared beat</span><br>
      <span data-i18n="join.hint.record">● record 1/2/4-bar riffs — build a song together, then bow</span></div>
  </div>
</div>

<!-- fatal -->
<div id="ovMsg" class="overlay hidden" style="background:#120b0ecc">
  <div style="display:flex;flex-direction:column;gap:14px;align-items:center">
    <div id="bigmsg"></div>
    <div id="submsg"></div>
  </div>
</div>

<div id="toast"></div>

<script defer src="./assets/main.js"></script>
</body>
</html>

static mirror of HEAD · about · clone: git clone https://git.ardegazu.ro/game6.git