up up and away

This commit is contained in:
thrhymes
2025-12-24 21:35:43 +01:00
parent b049dded72
commit 354e897e55
7 changed files with 508 additions and 536 deletions

View File

@@ -1,285 +1,173 @@
<!doctype html>
<html lang="de" translate="no">
<html lang="de">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover" />
<meta name="theme-color" content="#0b1020" />
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="mobile-web-app-capable" content="yes">
<link rel="manifest" href="./manifest.webmanifest">
<link rel="icon" href="./icons/icon-192.png">
<link rel="apple-touch-icon" href="./icons/icon-192.png">
<title>WFW-Aushang</title>
<link rel="manifest" href="./manifest.webmanifest">
<meta name="theme-color" content="#0b1020">
<!-- iOS / PWA -->
<meta name="apple-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="WFW-Aushang">
<link rel="apple-touch-icon" href="./icons/icon-192.png">
<style>
:root{
--bg: #f6f7fb;
--panel: rgba(255,255,255,.75);
--panelSolid: #ffffff;
--text: #0b1220;
--muted: rgba(11,18,32,.62);
--border: rgba(11,18,32,.12);
--shadow: 0 10px 30px rgba(11,18,32,.12);
--accent: #2563eb;
--btnText: #ffffff;
--glass: blur(12px);
:root,
:root[data-theme="dark"]{
--bg:#0b1020; --card:#121a33; --text:#e8eeff; --muted:#9fb0ff;
--line:rgba(255,255,255,.12); --btn:#2b60ff; --btn2:#1c254b;
--ok:#2bff9f; --warn:#ffd36b;
}
[data-theme="dark"]{
--bg: #070a12;
--panel: rgba(17,24,39,.55);
--panelSolid: #0b1020;
--text: #e5e7eb;
--muted: rgba(229,231,235,.65);
--border: rgba(229,231,235,.14);
--shadow: 0 14px 40px rgba(0,0,0,.55);
--accent: #60a5fa;
--btnText: #061022;
:root[data-theme="light"]{
--bg:#f6f7fb; --card:#ffffff; --text:#0b1020; --muted:#5060a8;
--line:rgba(0,0,0,.10); --btn:#2b60ff; --btn2:#eef1ff;
}
html, body { height:100%; }
*{ box-sizing:border-box; }
body{
margin:0;
font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif;
background:
radial-gradient(1200px 900px at 10% 0%, rgba(37,99,235,.12), transparent 55%),
radial-gradient(900px 700px at 90% 10%, rgba(99,102,241,.12), transparent 60%),
radial-gradient(900px 700px at 50% 110%, rgba(16,185,129,.10), transparent 60%),
var(--bg);
color: var(--text);
margin:0; font-family: system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Arial;
background:var(--bg); color:var(--text);
}
header{
position: sticky;
top: 0;
z-index: 5;
padding: 14px 16px 12px;
border-bottom: 1px solid var(--border);
background: color-mix(in srgb, var(--panelSolid) 70%, transparent);
backdrop-filter: var(--glass);
}
.headrow{
display:flex;
align-items:center;
justify-content:space-between;
gap: 10px;
max-width: 980px;
margin: 0 auto;
}
h1{
margin:0;
font-size: 18px;
letter-spacing: .2px;
}
.headbtns{ display:flex; gap:10px; align-items:center; }
.iconbtn{
border: 1px solid var(--border);
background: color-mix(in srgb, var(--panelSolid) 80%, transparent);
color: var(--text);
border-radius: 12px;
padding: 10px 12px;
cursor:pointer;
box-shadow: 0 6px 18px rgba(0,0,0,.06);
}
.iconbtn:active{ transform: translateY(1px); }
.wrap{
padding: 14px 12px 96px;
max-width: 980px;
margin: 0 auto;
max-width: 860px; margin: 0 auto; padding: 16px 16px 92px;
}
h1{ font-size: 20px; margin: 8px 0 14px; letter-spacing:.3px; }
.list{
display:flex; flex-direction:column; gap:10px;
}
.row{
display:flex; align-items:center; gap:12px;
background:var(--card); border:1px solid var(--line);
border-radius:16px; padding:12px 14px;
text-decoration:none; color:inherit;
}
.row:active{ transform: scale(0.995); }
.ico{
width:38px; height:38px; border-radius:12px;
display:grid; place-items:center;
background:rgba(43,96,255,.16);
border:1px solid rgba(43,96,255,.22);
flex:0 0 auto;
}
.name{ font-size: 16px; line-height:1.2; }
.sub{ font-size: 12px; color: var(--muted); margin-top:3px; }
.spacer{ flex:1; }
.badge{
font-size:12px; color:var(--muted);
border:1px solid var(--line); padding:6px 10px; border-radius:999px;
background:rgba(0,0,0,.08);
}
.footer{
position:fixed; left:0; right:0; bottom:0;
padding:12px 12px calc(12px + env(safe-area-inset-bottom));
background:linear-gradient(to top, rgba(11,16,32,.95), rgba(11,16,32,.55), rgba(11,16,32,0));
pointer-events:none;
}
@media (prefers-color-scheme: light){
.footer{ background:linear-gradient(to top, rgba(246,247,251,.95), rgba(246,247,251,.55), rgba(246,247,251,0)); }
}
.footerInner{
max-width: 860px; margin:0 auto; display:flex; gap:10px; pointer-events:auto;
}
/* BIG BUTTONS */
.btn{
border:0; border-radius:18px;
padding:18px 18px; /* bigger */
font-size:18px; /* bigger */
font-weight:800;
min-height:64px; /* bigger */
display:flex; align-items:center; justify-content:center;
cursor:pointer;
box-shadow: 0 10px 30px rgba(0,0,0,.22);
text-decoration:none;
user-select:none;
-webkit-tap-highlight-color: transparent;
}
.btnPrimary{ background:var(--btn); color:white; flex:1; }
.btnSecondary{ background:var(--btn2); color:var(--text); flex:1; border:1px solid var(--line); box-shadow:none; }
.btn:active{ transform: scale(0.995); }
.status{
margin: 12px 4px;
font-size: 13px;
color: var(--muted);
margin: 8px 0 14px; color: var(--muted); font-size: 13px;
}
.list{
border: 1px solid var(--border);
border-radius: 18px;
overflow: hidden;
background: var(--panel);
backdrop-filter: var(--glass);
box-shadow: var(--shadow);
}
.item{
display:flex;
align-items:center;
gap: 12px;
padding: 12px 12px;
border-top: 1px solid var(--border);
cursor: pointer;
}
.item:first-child{ border-top:none; }
.item:hover{ background: color-mix(in srgb, var(--panelSolid) 22%, transparent); }
.pdfIcon{
width: 38px; height: 38px;
border-radius: 12px;
display:flex; align-items:center; justify-content:center;
background: color-mix(in srgb, var(--accent) 14%, transparent);
border: 1px solid color-mix(in srgb, var(--accent) 22%, transparent);
font-size: 18px;
flex: 0 0 auto;
}
.name{
flex:1;
overflow:hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-weight: 650;
}
.meta{
font-size: 12px;
color: var(--muted);
text-align:right;
min-width: 92px;
}
.bottom{
position: fixed;
left: 0; right: 0; bottom: 0;
padding: 12px;
border-top: 1px solid var(--border);
background: color-mix(in srgb, var(--panelSolid) 70%, transparent);
backdrop-filter: var(--glass);
z-index: 6;
}
.bottom .inner{
max-width: 980px;
margin: 0 auto;
display:flex;
justify-content:center;
}
.btn{
padding: 11px 14px;
.error{
background: rgba(255,80,80,.12);
border:1px solid rgba(255,80,80,.25);
color: #ffb7b7;
padding: 10px 12px;
border-radius: 14px;
border: 1px solid var(--border);
background: var(--accent);
color: var(--btnText);
cursor: pointer;
font-size: 14px;
font-weight: 700;
}
.btn.secondary{
background: transparent;
color: var(--text);
}
.bottom .btn{
width: min(520px, 100%);
font-size: 16px;
padding: 14px 16px;
font-size: 13px;
white-space: pre-wrap;
}
/* Kioskiges Overlay */
.ov{
position: fixed;
inset: 0;
z-index: 9999;
display: grid;
place-items: center;
padding: 18px;
background: rgba(0,0,0,.62);
backdrop-filter: blur(12px);
/* INSTALL/UPDATE OVERLAY */
#installOverlay{
position:fixed; inset:0;
display:none;
z-index:2147483647;
background: rgba(0,0,0,.55);
backdrop-filter: blur(10px);
pointer-events:auto;
padding: 18px 14px;
}
#installOverlay *{ pointer-events:auto; }
.ovCard{
width: min(560px, 100%);
max-width: 560px;
margin: 10vh auto 0;
background: var(--card);
border: 1px solid var(--line);
border-radius: 22px;
border: 1px solid rgba(255,255,255,.14);
background: color-mix(in srgb, var(--panelSolid) 92%, transparent);
box-shadow: 0 18px 60px rgba(0,0,0,.45);
padding: 18px;
text-align: center;
}
.ovTitle{
font-size: 20px;
font-weight: 900;
margin: 6px 0 8px;
letter-spacing: .2px;
}
.ovText{
color: var(--muted);
font-size: 14px;
line-height: 1.35;
margin: 0 0 16px;
}
.ovPrimary{
width: 100%;
padding: 14px 16px;
font-size: 16px;
border-radius: 16px;
border: 0;
background: var(--accent);
color: var(--btnText);
font-weight: 900;
cursor: pointer;
box-shadow: 0 10px 30px rgba(0,0,0,.25);
}
.ovPrimary:active{ transform: translateY(1px); }
.ovLink{
margin-top: 12px;
display: inline-block;
background: transparent;
border: 0;
padding: 8px 10px;
color: color-mix(in srgb, var(--text) 82%, transparent);
font-size: 13px;
text-decoration: underline;
cursor: pointer;
opacity: .85;
padding: 18px 16px;
box-shadow: 0 20px 70px rgba(0,0,0,.35);
}
.ovTitle{ font-size: 18px; font-weight: 850; margin: 6px 0 6px; }
.ovText{ color: var(--muted); font-size: 14px; line-height: 1.35; margin: 0 0 14px; }
.ovBtns{ display:flex; gap:12px; margin-top: 10px; }
.ovBtns .btn{ flex:1; }
.ovHint{
margin-top: 10px;
margin-top: 12px;
font-size: 12px;
color: var(--muted);
border-top: 1px solid var(--line);
padding-top: 12px;
line-height: 1.35;
}
</style>
</head>
<body>
<!-- Kiosk Overlay -->
<div id="installOverlay" class="ov" hidden>
<div class="wrap">
<h1>WFW-Aushang</h1>
<div id="status" class="status">Lade Liste…</div>
<div id="err" class="error" style="display:none"></div>
<div id="list" class="list"></div>
</div>
<div class="footer">
<div class="footerInner">
<button id="closeBtn" class="btn btnSecondary">Aushang schließen</button>
<button id="themeBtn" class="btn btnSecondary">🌙 Dunkel</button>
<button id="refreshBtn" class="btn btnPrimary">↻ Refresh</button>
</div>
</div>
<div id="installOverlay" role="dialog" aria-modal="true">
<div class="ovCard">
<div class="ovTitle" id="ovTitle">WFW-Aushang</div>
<div class="ovText" id="ovText">Installiere die App für Kiosk-Modus und schnelle PDFs.</div>
<button id="ovPrimaryBtn" class="ovPrimary">Installieren</button>
<button id="ovContinueBtn" class="ovLink" type="button">Weiter im Browser</button>
<div class="ovHint" id="ovHint"></div>
</div>
</div>
<header>
<div class="headrow">
<h1>WFW-Aushang</h1>
<div class="headbtns">
<button class="iconbtn" id="themeBtn" title="Dark Mode">🌓</button>
<button class="iconbtn" id="refreshBtn" title="Neu laden"></button>
<p class="ovText" id="ovText">Installiere mich!</p>
<div class="ovBtns">
<button id="ovPrimaryBtn" class="btn btnPrimary">Installieren</button>
<button id="ovContinueBtn" class="btn btnSecondary">Weiter im Browser</button>
</div>
</div>
</header>
<div class="wrap">
<div class="status" id="status">Lade Liste…</div>
<div class="list" id="list"></div>
</div>
<div class="bottom">
<div class="inner">
<button class="btn" id="closeBtn">Aushang schließen</button>
<div class="ovHint" id="ovHint" style="display:none"></div>
</div>
</div>
<script src="./app.js"></script>
<script src="./app.js?v=2025.12.24.6"></script>
</body>
</html>