commits
tags
<!DOCTYPE html>
<html lang="sv">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Kiosk Display</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
html, body { width: 100%; height: 100%; overflow: hidden; background: #000; cursor: none; }
* { cursor: none !important; }
.layer { position: fixed; inset: 0; display: none; }
#layer-iframe iframe { width: 100%; height: 100%; border: none; }
#layer-video { background: #000; display: flex; align-items: center; justify-content: center; }
#layer-video video { width: 100%; height: 100%; object-fit: contain; }
#layer-image { background: #000; display: flex; align-items: center; justify-content: center; }
#layer-image img { width: 100%; height: 100%; object-fit: contain; }
#layer-idle { background: #111; display: flex; align-items: center; justify-content: center; }
#layer-idle .ip { color: #fff; font-family: monospace; font-size: 4vw; opacity: 0.6; }
/* Ticker overlay */
#ticker {
display: none;
position: fixed;
left: 0; right: 0;
z-index: 9999;
overflow: hidden;
pointer-events: none;
}
#ticker.top { top: 0; }
#ticker.bottom { bottom: 0; }
#ticker-text {
display: inline-block;
white-space: nowrap;
}
@keyframes ticker-scroll {
from { transform: translateX(100vw); }
to { transform: translateX(-100%); }
}
/* === Kiosk chat overlay === */
#kiosk-chat-overlay {
font-family: 'Segoe UI', system-ui, sans-serif;
}
#kc-msgs {
position: absolute;
bottom: 0; left: 0; right: 0;
display: flex;
flex-direction: column;
gap: .55rem;
padding: .75rem;
}
.kc-msg {
display: flex;
align-items: flex-start;
gap: .55rem;
animation: kc-in .25s ease;
}
.kc-avatar {
width: 2rem; height: 2rem;
border-radius: 50%;
display: flex; align-items: center; justify-content: center;
font-size: 1rem;
flex-shrink: 0;
margin-top: .1rem;
overflow: hidden;
}
.kc-body { flex: 1; min-width: 0; }
.kc-name {
font-size: .78rem;
font-weight: 700;
margin-bottom: .15rem;
}
.kc-text {
font-size: 1.05rem;
line-height: 1.45;
word-break: break-word;
color: #e8e8e8;
text-shadow: 0 1px 4px #000c;
}
.kc-system {
font-size: .8rem;
color: #aaa;
font-style: italic;
padding: .05rem .25rem;
text-shadow: 0 1px 3px #000c;
}
@keyframes kc-in {
from { opacity: 0; transform: translateY(8px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes ticker-scroll-seamless {
from { transform: translateX(0); }
to { transform: translateX(-50%); }
}
/* kiosk chat overlay header */
#kc-header {
display: flex;
align-items: center;
gap: .5rem;
padding: .55rem .75rem .45rem;
border-bottom: 1px solid #ffffff14;
flex-shrink: 0;
}
#kc-title {
font-size: .9rem;
font-weight: 700;
color: #fff;
letter-spacing: .02em;
}
#kc-count {
font-size: .72rem;
color: #888;
background: #1a1a1a;
padding: .15rem .5rem;
border-radius: 99px;
margin-right: auto;
}
#kc-qr {
width: 48px; height: 48px;
border-radius: 5px;
background: #fff;
padding: 2px;
flex-shrink: 0;
}
#kc-msgs-wrap {
flex: 1;
overflow: hidden;
position: relative;
}
.dot-live {
width: .5rem; height: .5rem;
background: #ef4444;
border-radius: 50%;
display: inline-block;
flex-shrink: 0;
animation: kc-pulse 1.4s infinite;
}
@keyframes kc-pulse {
0%,100% { opacity: 1; }
50% { opacity: .3; }
}
/* === Layer transitions === */
.layer { will-change: transform, opacity; }
/* Fade */
@keyframes tx-fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes tx-fade-out { from { opacity: 1; } to { opacity: 0; } }
/* Slide left — ny layer kommer från höger */
@keyframes tx-slide-left-in { from { transform: translateX(100%); } to { transform: translateX(0); } }
@keyframes tx-slide-left-out { from { transform: translateX(0); } to { transform: translateX(-100%); } }
/* Slide right — ny layer kommer från vänster */
@keyframes tx-slide-right-in { from { transform: translateX(-100%); } to { transform: translateX(0); } }
@keyframes tx-slide-right-out { from { transform: translateX(0); } to { transform: translateX(100%); } }
/* Slide up — ny layer kommer underifrån */
@keyframes tx-slide-up-in { from { transform: translateY(100%); } to { transform: translateY(0); } }
@keyframes tx-slide-up-out { from { transform: translateY(0); } to { transform: translateY(-100%); } }
/* Slide down — ny layer kommer uppifrån */
@keyframes tx-slide-down-in { from { transform: translateY(-100%); } to { transform: translateY(0); } }
@keyframes tx-slide-down-out { from { transform: translateY(0); } to { transform: translateY(100%); } }
/* Zoom */
@keyframes tx-zoom-in { from { transform: scale(0.85); opacity: 0; } to { transform: scale(1); opacity: 1; } }
@keyframes tx-zoom-out { from { transform: scale(1); opacity: 1; } to { transform: scale(1.15); opacity: 0; } }
/* Wipe — vänster till höger via clip-path */
@keyframes tx-wipe-in { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0% 0 0); } }
@keyframes tx-wipe-out { from { opacity: 1; } to { opacity: 0; } }
/* Blur dissolve (pixel-liknande) */
@keyframes tx-blur-in { from { filter: blur(24px) brightness(1.3); opacity: 0; } to { filter: blur(0) brightness(1); opacity: 1; } }
@keyframes tx-blur-out { from { filter: blur(0) brightness(1); opacity: 1; } to { filter: blur(24px) brightness(0.5); opacity: 0; } }
/* Pixel canvas overlay */
#tx-pixel-canvas {
position: fixed; inset: 0; z-index: 99998;
pointer-events: none;
display: none;
}
</style>
</head>
<body>
<div id="layer-iframe" class="layer">
<iframe id="frame" src="" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
</div>
<div id="layer-video" class="layer">
<video id="video" autoplay></video>
</div>
<div id="layer-local" class="layer"></div>
<div id="layer-image" class="layer">
<img id="image" src="" alt="">
</div>
<!-- YouTube Livechat overlay -->
<div id="chat-overlay" style="display:none; position:fixed; top:0; z-index:9998; pointer-events:auto; transition:opacity .3s;">
<iframe id="chat-frame" src="" frameborder="0" style="width:100%;height:100%;border:none;"></iframe>
</div>
<!-- Kiosk Livechat overlay (inbyggd, ingen iframe) -->
<div id="kiosk-chat-overlay" style="display:none; position:fixed; top:0; z-index:9997; pointer-events:none; overflow:hidden; font-family:'Segoe UI',system-ui,sans-serif; flex-direction:column; background:#0f0f0fd0;">
<div id="kc-header">
<span class="dot-live"></span>
<span id="kc-title">Livechat</span>
<span id="kc-count">0 aktiva</span>
<img id="kc-qr" src="/api/chat-qr" alt="QR">
</div>
<div id="kc-msgs-wrap">
<div id="kc-msgs" style="position:absolute;bottom:0;left:0;right:0;display:flex;flex-direction:column;gap:.45rem;padding:.6rem .75rem;"></div>
</div>
</div>
<!-- Ticker overlay -->
<div id="ticker" class="bottom">
<span id="ticker-text"></span>
</div>
<div id="layer-idle" class="layer" style="display: block;">
<span class="ip">{{ local_ip }}:5000</span>
</div>
<!-- Clock overlay -->
<div id="clock-overlay" style="display:none; position:fixed; z-index:9990; pointer-events:none; flex-direction:column; align-items:center;">
<div id="clock-digital"></div>
<canvas id="clock-analog"></canvas>
<div id="clock-date"></div>
</div>
<!-- Transition: pixel canvas overlay -->
<canvas id="tx-pixel-canvas"></canvas>
<!-- Söv-overlay — täcker allt -->
<div id="layer-sleep" style="display:none; position:fixed; inset:0; background:#000; z-index:99999;"></div>
<!-- Musik: bakgrundsaudio (lokal MP3) -->
<audio id="music-player" preload="auto" style="display:none"></audio>
<!-- Musik: dold iframe för YouTube-spellista -->
<iframe id="music-yt-frame" src="" allow="autoplay; encrypted-media" style="position:fixed;width:320px;height:180px;left:-400px;top:0;pointer-events:none;border:none;"></iframe>
<!-- Now Playing-overlay -->
<div id="now-playing-overlay" style="display:none; position:fixed; z-index:9985; pointer-events:none; max-width:320px;">
<div id="now-playing-inner" style="
background: rgba(0,0,0,0.72);
backdrop-filter: blur(8px);
border-radius: 10px;
padding: .55rem .85rem;
display: flex;
align-items: center;
gap: .6rem;
animation: np-fadein .4s ease;
">
<span id="now-playing-icon" style="font-size:1.3rem;flex-shrink:0;">♪</span>
<div style="min-width:0;">
<div id="now-playing-title" style="color:#fff;font-size:.88rem;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;text-shadow:0 1px 4px #000c;"></div>
<div id="now-playing-artist" style="color:#bbb;font-size:.75rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;text-shadow:0 1px 4px #000c;"></div>
</div>
</div>
</div>
<style>
@keyframes np-fadein {
from { opacity:0; transform:translateY(6px); }
to { opacity:1; transform:translateY(0); }
}
</style>
<script src="/static/socket.io.min.js"></script>
<script src="/static/display.js"></script>
{% for name in active_overlays %}
<script src="/static/addons/{{ name }}/overlay.js"></script>
{% endfor %}
</body>
</html>