ntdservices commited on
Commit
c9942c1
·
verified ·
1 Parent(s): e39cce9

Update static/index.html

Browse files
Files changed (1) hide show
  1. static/index.html +70 -34
static/index.html CHANGED
@@ -9,14 +9,32 @@
9
  --bg:#0b1220; --panel:#121a2e; --muted:#9fb0cf; --text:#e6edf7;
10
  --accent:#3a8dde; --accent2:#6ea8ff; --ok:#2ecc71; --warn:#ffb020; --danger:#ff6b6b;
11
  --radius:16px; --shadow:0 12px 30px rgba(0,0,0,.35);
 
12
  }
13
  *{box-sizing:border-box}
14
  html,body{height:100%; margin:0; background:var(--bg); color:var(--text); font-family:system-ui,-apple-system,Segoe UI,Roboto,Helvetica,Arial,sans-serif}
15
- #app{display:grid; grid-template-columns: 360px 1fr; height:100%}
16
 
17
- /* Sidebar */
18
- #panel{background:linear-gradient(180deg,#121a2e,#0e162b); border-right:1px solid #1e2844; padding:16px; overflow:auto; position:relative; transition:transform .28s ease; box-shadow:var(--shadow); z-index:5;}
19
- #panel.min{transform:translateX(-100%)}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  #panel h2{margin:.3rem 0 1rem; font-size:1.05rem; color:#cfe0ff}
21
  fieldset{border:1px solid #2a395f; border-radius:12px; padding:12px; margin:10px 0}
22
  legend{font-size:.9rem; color:#bcd0ff; padding:0 6px}
@@ -35,28 +53,44 @@
35
  .badge{display:inline-block; padding:2px 8px; border-radius:999px; font-size:.75rem; background:#1b2b54; color:#cfe0ff}
36
  .hr{height:1px; background:#203059; margin:12px 0}
37
 
38
- /* Panel toggle */
39
- #toggle{position:absolute; left:355px; top:12px; z-index:6; width:36px; height:36px; border-radius:10px; display:grid; place-items:center; background:#0d1a36; border:1px solid #2a395f;}
40
- #panel.min + #toggle{left:8px}
41
- #saveState{position:absolute; bottom:10px; right:12px; font-size:.8rem; border-radius:999px; padding:6px 10px; opacity:.9}
 
 
 
 
42
 
43
- /* Stage */
44
- #stage{position:relative; height:100%; width:100%; overflow:hidden; background:#000; user-select:none}
45
- .bgmedia{position:absolute; inset:0; width:100%; height:100%; object-fit:cover; z-index:0}
46
- #overlay{position:absolute; inset:0; z-index:2}
47
- #stageMsg{position:absolute; top:12px; right:12px; background:rgba(10,14,30,.55); border:1px solid #2a3a63; padding:8px 12px; border-radius:12px; z-index:4; backdrop-filter: blur(4px); font-size:.9rem}
48
 
49
- /* Pins and popups */
50
- .pin{position:absolute; width:18px; height:18px; border-radius:50%; background:rgba(255,255,255,.25); border:2px solid rgba(255,255,255,.5); box-shadow:0 2px 10px rgba(0,0,0,.45); transform:translate(-50%, -50%); z-index:3}
51
- .pin:hover{background:rgba(255,255,255,.35)}
52
- .popup{position:absolute; z-index:4; transform: translate(-50%, calc(-100% - 12px)); background:rgba(13,20,40,.92); border:1px solid #2a395f; border-radius:16px; box-shadow:var(--shadow); padding:10px; min-width:200px; max-width:min(40vw, 520px); backdrop-filter: blur(6px)}
53
- .popup header{display:flex; align-items:center; justify-content:space-between; gap:8px; margin-bottom:6px}
54
- .popup h4{margin:0; font-size:.95rem; color:#d9e6ff}
55
- .x{background:transparent; border:none; color:#cfe0ff; font-size:18px; padding:4px 8px}
56
- .media{width:100%; height:auto; border-radius:12px; overflow:hidden; display:block; background:#000}
57
- .media video{width:100%; height:auto; display:block}
58
- .media img{width:100%; height:auto; display:block}
 
 
 
 
 
 
 
 
 
 
 
 
59
 
 
 
 
60
  /* Items list */
61
  .item{display:grid; grid-template-columns:auto 1fr auto; gap:8px; align-items:center; padding:8px; border:1px solid #21345d; border-radius:10px; margin:8px 0; background:#0e1834}
62
  .item .name{font-size:.9rem}
@@ -139,8 +173,9 @@
139
  <video id="bgVid" class="bgmedia" autoplay muted loop playsinline style="display:none"></video>
140
  <div id="overlay" title="Click to place when in placement mode"></div>
141
  <div id="stageMsg" style="display:none"></div>
142
- <button id="saveState" class="btn-ghost">Saved</button>
143
  </main>
 
 
144
  </div>
145
 
146
  <script>
@@ -279,13 +314,14 @@
279
  }
280
 
281
  function adjustPopupPosition(el){
 
282
  const rect = el.getBoundingClientRect();
283
  const margin = 8; let dx=0, dy=0;
284
  if (rect.left < margin) dx = margin - rect.left;
285
  if (rect.right > innerWidth - margin) dx = (innerWidth - margin) - rect.right;
286
  if (rect.top < margin) dy = margin - rect.top;
287
  if (rect.bottom > innerHeight - margin) dy = (innerHeight - margin) - rect.bottom;
288
- if (dx || dy) el.style.transform += ` translate(${dx}px, ${dy}px)`;
289
  }
290
 
291
  function renderItems(){
@@ -302,15 +338,19 @@
302
  if (it.open){
303
  const pop = document.createElement('div'); pop.className='popup';
304
  pop.style.left = it.x+'%'; pop.style.top = it.y+'%'; pop.style.width = it.widthPct+'vw';
 
305
  const header = document.createElement('header');
306
  const h4 = document.createElement('h4'); h4.textContent = it.title || (it.type==='image'?'Image':'Video');
307
  const close = document.createElement('button'); close.className='x'; close.innerHTML='&times;';
308
  close.addEventListener('click', e=>{ e.stopPropagation(); it.open=false; renderItems(); });
309
  header.append(h4, close); pop.appendChild(header);
 
310
  const wrap = document.createElement('div'); wrap.className='media';
311
  if (it.type==='video'){ const v = document.createElement('video'); v.src=it.src; v.controls=true; v.playsInline=true; wrap.appendChild(v); }
312
  else { const img = document.createElement('img'); img.src=it.src; img.alt=it.title||'Image'; wrap.appendChild(img); }
313
- pop.appendChild(wrap); overlay.appendChild(pop);
 
 
314
  requestAnimationFrame(()=>adjustPopupPosition(pop));
315
  }
316
  }
@@ -390,15 +430,11 @@
390
  });
391
 
392
  // Misc
393
- function flash(msg){
394
- stageMsg.textContent = msg;
395
- stageMsg.style.display='block'; stageMsg.style.opacity='1';
396
- setTimeout(()=>{ stageMsg.style.transition='opacity .4s'; stageMsg.style.opacity='0';
397
- setTimeout(()=>{ stageMsg.style.display='none'; stageMsg.style.transition=''; }, 450);
398
- }, 900);
399
- }
400
  window.addEventListener('resize', ()=>{
401
- $$('.popup').forEach(el => { el.style.transform='translate(-50%, calc(-100% - 12px))'; requestAnimationFrame(()=>adjustPopupPosition(el)); });
 
 
 
402
  });
403
  stage.addEventListener('click', e => {
404
  if (state.placingId) return; // placement handled on overlay
 
9
  --bg:#0b1220; --panel:#121a2e; --muted:#9fb0cf; --text:#e6edf7;
10
  --accent:#3a8dde; --accent2:#6ea8ff; --ok:#2ecc71; --warn:#ffb020; --danger:#ff6b6b;
11
  --radius:16px; --shadow:0 12px 30px rgba(0,0,0,.35);
12
+ --panelW:360px; --panelPeek:14px;
13
  }
14
  *{box-sizing:border-box}
15
  html,body{height:100%; margin:0; background:var(--bg); color:var(--text); font-family:system-ui,-apple-system,Segoe UI,Roboto,Helvetica,Arial,sans-serif}
 
16
 
17
+ /* App container just hosts overlays; stage lives full-screen behind */
18
+ #app{position:relative; height:100vh; width:100vw; overflow:hidden}
19
+
20
+ /* Stage is full-viewport, underlays everything (so BG truly covers screen) */
21
+ #stage{position:fixed; inset:0; width:100vw; height:100vh; overflow:hidden; background:#000; user-select:none; z-index:0}
22
+ .bgmedia{position:absolute; inset:0; width:100%; height:100%; object-fit:cover; z-index:0}
23
+ #overlay{position:absolute; inset:0; z-index:2}
24
+ #stageMsg{position:absolute; top:12px; right:12px; background:rgba(10,14,30,.55); border:1px solid #2a3a63; padding:8px 12px; border-radius:12px; z-index:4; backdrop-filter: blur(4px); font-size:.9rem}
25
+
26
+ /* Sidebar overlays the stage */
27
+ #panel{
28
+ position:fixed; top:0; left:0; height:100vh; width:var(--panelW);
29
+ background:linear-gradient(180deg,#121a2e,#0e162b);
30
+ border-right:1px solid #1e2844; padding:16px; overflow:auto;
31
+ transition:transform .28s ease; box-shadow:var(--shadow); z-index:5;
32
+ transform:translateX(0);
33
+ }
34
+ #panel.min{
35
+ /* Collapse so only a tiny sliver remains visible */
36
+ transform:translateX(calc(-100% + var(--panelPeek)));
37
+ }
38
  #panel h2{margin:.3rem 0 1rem; font-size:1.05rem; color:#cfe0ff}
39
  fieldset{border:1px solid #2a395f; border-radius:12px; padding:12px; margin:10px 0}
40
  legend{font-size:.9rem; color:#bcd0ff; padding:0 6px}
 
53
  .badge{display:inline-block; padding:2px 8px; border-radius:999px; font-size:.75rem; background:#1b2b54; color:#cfe0ff}
54
  .hr{height:1px; background:#203059; margin:12px 0}
55
 
56
+ /* Panel toggle sits near the left edge whether expanded or collapsed */
57
+ #toggle{
58
+ position:fixed; top:12px; left:calc(var(--panelW) + 8px);
59
+ z-index:6; width:36px; height:36px; border-radius:10px; display:grid; place-items:center;
60
+ background:#0d1a36; border:1px solid #2a395f;
61
+ transition:left .28s ease;
62
+ }
63
+ #panel.min + #toggle{ left:16px; }
64
 
65
+ #saveState{position:fixed; bottom:12px; left:calc(var(--panelW) + 12px); font-size:.8rem; border-radius:999px; padding:6px 10px; opacity:.9; z-index:4; transition:left .28s ease}
66
+ #panel.min ~ #stage #saveState, #panel.min ~ #saveState { left:28px; }
 
 
 
67
 
68
+ /* Pins (bigger + more transparent) */
69
+ .pin{
70
+ position:absolute; width:26px; height:26px; border-radius:50%;
71
+ background:rgba(255,255,255,.18); border:2px solid rgba(255,255,255,.45);
72
+ box-shadow:0 2px 10px rgba(0,0,0,.45); transform:translate(-50%, -50%); z-index:3;
73
+ }
74
+ .pin:hover{background:rgba(255,255,255,.26)}
75
+
76
+ /* Popups: centered exactly on the pin midpoint */
77
+ .popup{
78
+ position:absolute; z-index:4;
79
+ transform: translate(-50%, -50%); /* center on pin */
80
+ background:rgba(13,20,40,.92); border:1px solid #2a395f; border-radius:16px; box-shadow:var(--shadow);
81
+ padding:0; min-width:200px; max-width:min(40vw, 520px); backdrop-filter: blur(6px);
82
+ }
83
+ /* Make header overlay so media stays geometrically centered */
84
+ .popup header{
85
+ position:absolute; top:6px; right:6px; left:auto;
86
+ display:flex; align-items:center; gap:8px; margin:0; padding:0;
87
+ }
88
+ .popup h4{margin:0; font-size:.95rem; color:#d9e6ff; background:rgba(0,0,0,.35); padding:6px 10px; border-radius:10px}
89
+ .x{background:rgba(0,0,0,.35); border:1px solid #2a395f; color:#cfe0ff; font-size:16px; padding:6px 8px; border-radius:10px}
90
 
91
+ .media{display:block; width:100%; height:auto; border-radius:16px; overflow:hidden; background:#000}
92
+ .media video, .media img{display:block; width:100%; height:auto}
93
+
94
  /* Items list */
95
  .item{display:grid; grid-template-columns:auto 1fr auto; gap:8px; align-items:center; padding:8px; border:1px solid #21345d; border-radius:10px; margin:8px 0; background:#0e1834}
96
  .item .name{font-size:.9rem}
 
173
  <video id="bgVid" class="bgmedia" autoplay muted loop playsinline style="display:none"></video>
174
  <div id="overlay" title="Click to place when in placement mode"></div>
175
  <div id="stageMsg" style="display:none"></div>
 
176
  </main>
177
+
178
+ <button id="saveState" class="btn-ghost">Saved</button>
179
  </div>
180
 
181
  <script>
 
314
  }
315
 
316
  function adjustPopupPosition(el){
317
+ // Keep centered popup fully within viewport by nudging
318
  const rect = el.getBoundingClientRect();
319
  const margin = 8; let dx=0, dy=0;
320
  if (rect.left < margin) dx = margin - rect.left;
321
  if (rect.right > innerWidth - margin) dx = (innerWidth - margin) - rect.right;
322
  if (rect.top < margin) dy = margin - rect.top;
323
  if (rect.bottom > innerHeight - margin) dy = (innerHeight - margin) - rect.bottom;
324
+ if (dx || dy) el.style.transform = `translate(calc(-50% + ${dx}px), calc(-50% + ${dy}px))`;
325
  }
326
 
327
  function renderItems(){
 
338
  if (it.open){
339
  const pop = document.createElement('div'); pop.className='popup';
340
  pop.style.left = it.x+'%'; pop.style.top = it.y+'%'; pop.style.width = it.widthPct+'vw';
341
+
342
  const header = document.createElement('header');
343
  const h4 = document.createElement('h4'); h4.textContent = it.title || (it.type==='image'?'Image':'Video');
344
  const close = document.createElement('button'); close.className='x'; close.innerHTML='&times;';
345
  close.addEventListener('click', e=>{ e.stopPropagation(); it.open=false; renderItems(); });
346
  header.append(h4, close); pop.appendChild(header);
347
+
348
  const wrap = document.createElement('div'); wrap.className='media';
349
  if (it.type==='video'){ const v = document.createElement('video'); v.src=it.src; v.controls=true; v.playsInline=true; wrap.appendChild(v); }
350
  else { const img = document.createElement('img'); img.src=it.src; img.alt=it.title||'Image'; wrap.appendChild(img); }
351
+ pop.appendChild(wrap);
352
+
353
+ overlay.appendChild(pop);
354
  requestAnimationFrame(()=>adjustPopupPosition(pop));
355
  }
356
  }
 
430
  });
431
 
432
  // Misc
 
 
 
 
 
 
 
433
  window.addEventListener('resize', ()=>{
434
+ $$('.popup').forEach(el => {
435
+ el.style.transform='translate(-50%, -50%)';
436
+ requestAnimationFrame(()=>adjustPopupPosition(el));
437
+ });
438
  });
439
  stage.addEventListener('click', e => {
440
  if (state.placingId) return; // placement handled on overlay