next-ep popup: design A (Cinematic Strip) shipped to dev + designs A/B/C archived
Adds web-overrides/popup-designs/ with the 4-up preview (preview.html) and three standalone candidate designs (a-strip.html / b-terminal.html / c-minimal.html) so we can revisit the alternates later without re-running the design generator. Owner picked A. Design A is wired into Jellyfin's stock .upNextDialog by overriding its CSS to a full-bleed bottom 26 % strip with white 'Start Now' CTA and a custom SVG countdown ring that mirrors .upNextDialog-countdownText. The DOM stays intact so Jellyfin's own countdown timer and click handlers on .btnStartNow / .btnHide keep working untouched. Shim is bracketed by NEXT-EP-POPUP-BEGIN / NEXT-EP-POPUP-END markers inside the existing ARRFLIX-SHIM block in web-overrides/index-dev.html. Only deployed to dev (dev.arrflix.s8n.ru) for spot-check; promote to prod once verified by editing prod's index.html the same way and redeploying via the nsenter trick. Adds bin/revert-next-ep-popup.sh — sed-deletes between markers, defaults to dev with --prod flag for prod target. Saves a timestamped backup and prints the redeploy command.
This commit is contained in:
parent
24a9497e7d
commit
508fc42a1e
7 changed files with 1704 additions and 0 deletions
54
bin/revert-next-ep-popup.sh
Executable file
54
bin/revert-next-ep-popup.sh
Executable file
|
|
@ -0,0 +1,54 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Revert the NEXT-EP-POPUP shim injected into dev's index-dev.html on 2026-05-10.
|
||||||
|
#
|
||||||
|
# What it removes:
|
||||||
|
# /* NEXT-EP-POPUP-BEGIN ... */ ... /* NEXT-EP-POPUP-END */
|
||||||
|
#
|
||||||
|
# Defaults to dev. Pass --prod to remove from prod's index.html instead.
|
||||||
|
# Idempotent: safe to re-run.
|
||||||
|
#
|
||||||
|
# After local edit, redeploy to nullstone via the same nsenter cp trick used
|
||||||
|
# for sub-label-shim revert (see comment at end).
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||||
|
TARGET_DEV="$REPO_ROOT/web-overrides/index-dev.html"
|
||||||
|
TARGET_PROD="$REPO_ROOT/web-overrides/index.html"
|
||||||
|
|
||||||
|
TARGET="$TARGET_DEV"
|
||||||
|
ENV="dev"
|
||||||
|
if [[ "${1:-}" == "--prod" ]]; then
|
||||||
|
TARGET="$TARGET_PROD"
|
||||||
|
ENV="prod"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -f "$TARGET" ]]; then
|
||||||
|
echo "ERROR: $TARGET not found" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! grep -q "NEXT-EP-POPUP-BEGIN" "$TARGET"; then
|
||||||
|
echo "shim already absent in $ENV — nothing to do"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
cp "$TARGET" "$TARGET.bak.$(date -u +%Y%m%dT%H%M%SZ)"
|
||||||
|
sed -i '/NEXT-EP-POPUP-BEGIN/,/NEXT-EP-POPUP-END/d' "$TARGET"
|
||||||
|
|
||||||
|
if grep -q "NEXT-EP-POPUP" "$TARGET"; then
|
||||||
|
echo "ERROR: revert left orphan markers in $TARGET" >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "reverted ($ENV). backup at $TARGET.bak.*"
|
||||||
|
echo
|
||||||
|
echo "Now redeploy to nullstone:"
|
||||||
|
if [[ "$ENV" == "dev" ]]; then
|
||||||
|
echo " scp $TARGET user@192.168.0.100:/tmp/index-dev-new.html"
|
||||||
|
echo " ssh user@192.168.0.100 'docker run --rm --privileged --pid=host --userns=host -v /opt:/opt -v /tmp:/tmp alpine nsenter -t 1 -m -u -i -n cp /tmp/index-dev-new.html /opt/docker/jellyfin-dev/web-overrides/index-dev.html'"
|
||||||
|
else
|
||||||
|
echo " scp $TARGET user@192.168.0.100:/tmp/arrflix-index.html"
|
||||||
|
echo " ssh user@192.168.0.100 'docker run --rm --privileged --pid=host --userns=host -v /opt:/opt -v /tmp:/tmp alpine nsenter -t 1 -m -u -i -n cp /tmp/arrflix-index.html /opt/docker/jellyfin/web-overrides/index.html'"
|
||||||
|
fi
|
||||||
|
echo "Then hard-refresh the browser (Ctrl+Shift+R)."
|
||||||
735
web-overrides/index-dev.html
Normal file
735
web-overrides/index-dev.html
Normal file
File diff suppressed because one or more lines are too long
37
web-overrides/popup-designs/README.md
Normal file
37
web-overrides/popup-designs/README.md
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
# Next-episode popup designs
|
||||||
|
|
||||||
|
Side-by-side preview of the 4 candidate popup designs evaluated 2026-05-10.
|
||||||
|
Owner picked **A · Cinematic Strip** for prod-bound shim. **B · Terminal**
|
||||||
|
and **C · Minimal Bar** archived as standalone files for future re-evaluation
|
||||||
|
(e.g. when ARRFLIX visual direction shifts or owner gets bored of A).
|
||||||
|
|
||||||
|
## Files
|
||||||
|
|
||||||
|
- `preview.html` — full 4-up preview page (drop into `python3 -m http.server`
|
||||||
|
to compare). Designed at 1920×1080 in a faux Star-Wars-credits backdrop.
|
||||||
|
- `a-strip.html` — standalone A. Full-bleed bottom strip, big countdown
|
||||||
|
ring, white "Start Now" CTA, "Hide" secondary. Netflix-grade muscle
|
||||||
|
memory. **Currently shipped to dev.**
|
||||||
|
- `b-terminal.html` — standalone B. Bottom-right card with JetBrains
|
||||||
|
Mono, dashed dividers, red accent line. Edgy, ARRFLIX-distinct.
|
||||||
|
- `c-minimal.html` — standalone C. Thin progress bar across bottom + small
|
||||||
|
text strip, no card. Disappears into UX. Power-user.
|
||||||
|
|
||||||
|
D · Poster Card was discarded — too similar to Jellyfin stock to justify
|
||||||
|
shipping.
|
||||||
|
|
||||||
|
## Wiring (current state)
|
||||||
|
|
||||||
|
Design A is shipped to **dev only** (`dev.arrflix.s8n.ru`) as a CSS+JS
|
||||||
|
shim bracketed in `/opt/docker/jellyfin-dev/web-overrides/index-dev.html`
|
||||||
|
between `NEXT-EP-POPUP-BEGIN` and `NEXT-EP-POPUP-END` markers. The shim
|
||||||
|
keeps Jellyfin's `.upNextDialog` DOM intact (so its countdown timer keeps
|
||||||
|
ticking and clicking the underlying buttons stays wired) and overlays
|
||||||
|
Design A's visual via CSS + a small countdown-ring SVG that mirrors
|
||||||
|
`.upNextDialog-countdownText`.
|
||||||
|
|
||||||
|
Promote to prod when satisfied: copy the shim block into prod's
|
||||||
|
`web-overrides/index.html` between the same markers, then deploy via
|
||||||
|
the same nsenter trick documented in `bin/revert-sub-label-shim.sh`.
|
||||||
|
|
||||||
|
Revert (dev): `bin/revert-next-ep-popup.sh`.
|
||||||
42
web-overrides/popup-designs/a-strip.html
Normal file
42
web-overrides/popup-designs/a-strip.html
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en"><head><meta charset="UTF-8"><title>ARRFLIX popup — A · Cinematic Strip</title>
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Geist:wght@400;500;600;700&family=JetBrains+Mono:wght@500&display=swap" rel="stylesheet">
|
||||||
|
<style>
|
||||||
|
:root { --arrflix-red:#E50914; --ink:#fff; --ink-dim:rgba(255,255,255,0.55); --ink-faint:rgba(255,255,255,0.3); }
|
||||||
|
*{box-sizing:border-box;margin:0;padding:0;}
|
||||||
|
body{background:#000;color:#fff;font-family:'Geist',system-ui,sans-serif;height:100vh;overflow:hidden;position:relative;}
|
||||||
|
.bg{position:absolute;inset:0;background:radial-gradient(ellipse 60% 40% at 50% 50%,rgba(20,20,40,0.4) 0%,transparent 70%),black;}
|
||||||
|
.popup{position:absolute;bottom:0;left:0;right:0;height:26%;background:linear-gradient(to top,rgba(0,0,0,0.95) 50%,rgba(0,0,0,0.7) 80%,transparent);padding:28px 56px 32px;display:flex;align-items:center;gap:36px;}
|
||||||
|
.ring{position:relative;width:88px;height:88px;flex-shrink:0;}
|
||||||
|
.ring svg{transform:rotate(-90deg);}
|
||||||
|
.ring circle{fill:none;stroke-width:3;}
|
||||||
|
.ring .track{stroke:rgba(255,255,255,0.1);}
|
||||||
|
.ring .progress{stroke:var(--arrflix-red);stroke-dasharray:264;stroke-dashoffset:67;stroke-linecap:round;filter:drop-shadow(0 0 8px rgba(229,9,20,0.5));}
|
||||||
|
.ring .num{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-family:'JetBrains Mono',monospace;font-size:28px;font-weight:500;}
|
||||||
|
.info{flex:1;min-width:0;}
|
||||||
|
.label{font-size:10px;letter-spacing:0.32em;text-transform:uppercase;color:var(--arrflix-red);margin-bottom:8px;font-weight:600;}
|
||||||
|
.title{font-size:28px;font-weight:600;letter-spacing:-0.02em;margin-bottom:6px;line-height:1.1;}
|
||||||
|
.episode-title{font-size:16px;color:var(--ink-dim);margin-bottom:4px;}
|
||||||
|
.meta{font-size:12px;color:var(--ink-faint);letter-spacing:0.04em;}
|
||||||
|
.actions{display:flex;gap:10px;flex-shrink:0;}
|
||||||
|
.btn{border:none;background:white;color:black;padding:14px 28px;font-family:inherit;font-size:13px;font-weight:600;cursor:pointer;display:flex;align-items:center;gap:10px;}
|
||||||
|
.btn:hover{background:rgba(255,255,255,0.85);}
|
||||||
|
.btn-secondary{background:rgba(255,255,255,0.08);color:white;backdrop-filter:blur(10px);}
|
||||||
|
.btn-secondary:hover{background:rgba(255,255,255,0.16);}
|
||||||
|
</style></head><body>
|
||||||
|
<div class="bg"></div>
|
||||||
|
<div class="popup">
|
||||||
|
<div class="ring"><svg width="88" height="88" viewBox="0 0 88 88"><circle class="track" cx="44" cy="44" r="42"/><circle class="progress" cx="44" cy="44" r="42"/></svg><div class="num">17</div></div>
|
||||||
|
<div class="info">
|
||||||
|
<div class="label">Up Next</div>
|
||||||
|
<div class="title">Star Wars: Maul · Shadow Lord</div>
|
||||||
|
<div class="episode-title">S1·E3 — Chapter 3: The Crucible</div>
|
||||||
|
<div class="meta">22 min · Ends at 2:49 AM</div>
|
||||||
|
</div>
|
||||||
|
<div class="actions">
|
||||||
|
<button class="btn">▶ Start Now</button>
|
||||||
|
<button class="btn btn-secondary">Hide</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body></html>
|
||||||
40
web-overrides/popup-designs/b-terminal.html
Normal file
40
web-overrides/popup-designs/b-terminal.html
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en"><head><meta charset="UTF-8"><title>ARRFLIX popup — B · Terminal Card</title>
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Geist:wght@400;500&family=JetBrains+Mono:wght@400;500;700&display=swap" rel="stylesheet">
|
||||||
|
<style>
|
||||||
|
:root{--arrflix-red:#E50914;--arrflix-red-dark:#B00710;--ink:#fff;--ink-dim:rgba(255,255,255,0.55);--ink-faint:rgba(255,255,255,0.3);}
|
||||||
|
*{box-sizing:border-box;margin:0;padding:0;}
|
||||||
|
body{background:#000;color:#fff;font-family:'JetBrains Mono',monospace;height:100vh;overflow:hidden;position:relative;}
|
||||||
|
.bg{position:absolute;inset:0;background:radial-gradient(ellipse 60% 40% at 50% 50%,rgba(20,20,40,0.4) 0%,transparent 70%),black;}
|
||||||
|
.popup{position:absolute;bottom:32px;right:32px;width:380px;background:rgba(5,5,5,0.92);backdrop-filter:blur(14px);border:1px solid rgba(255,255,255,0.12);border-left:2px solid var(--arrflix-red);padding:20px 22px;}
|
||||||
|
.top-row{display:flex;justify-content:space-between;align-items:center;margin-bottom:14px;font-size:10px;letter-spacing:0.18em;text-transform:uppercase;}
|
||||||
|
.tag{color:var(--arrflix-red);font-weight:700;}
|
||||||
|
.countdown{color:var(--ink-dim);}
|
||||||
|
.countdown strong{color:var(--ink);font-weight:700;}
|
||||||
|
hr{border:none;border-top:1px dashed rgba(255,255,255,0.1);margin:12px 0;}
|
||||||
|
.show{font-family:'Geist',sans-serif;font-size:11px;letter-spacing:0.18em;text-transform:uppercase;color:var(--ink-faint);margin-bottom:4px;}
|
||||||
|
.ep{font-family:'Geist',sans-serif;font-size:15px;font-weight:500;margin-bottom:4px;color:var(--ink);}
|
||||||
|
.ep-meta{font-size:11px;color:var(--ink-faint);letter-spacing:0.06em;margin-bottom:16px;}
|
||||||
|
.progress-bar{height:2px;background:rgba(255,255,255,0.08);margin-bottom:18px;position:relative;}
|
||||||
|
.progress-bar::after{content:'';position:absolute;top:0;left:0;height:100%;width:75%;background:var(--arrflix-red);box-shadow:0 0 8px rgba(229,9,20,0.6);}
|
||||||
|
.actions{display:flex;gap:8px;}
|
||||||
|
.btn{flex:1;background:transparent;border:1px solid rgba(255,255,255,0.18);color:white;padding:9px 14px;font-family:inherit;font-size:11px;letter-spacing:0.18em;text-transform:uppercase;cursor:pointer;}
|
||||||
|
.btn-primary{background:var(--arrflix-red);border-color:var(--arrflix-red);}
|
||||||
|
.btn-primary:hover{background:var(--arrflix-red-dark);}
|
||||||
|
.btn:hover{background:rgba(255,255,255,0.06);border-color:rgba(255,255,255,0.3);}
|
||||||
|
</style></head><body>
|
||||||
|
<div class="bg"></div>
|
||||||
|
<div class="popup">
|
||||||
|
<div class="top-row"><span class="tag">▎ Up Next</span><span class="countdown"><strong>17</strong>s</span></div>
|
||||||
|
<hr>
|
||||||
|
<div class="show">Star Wars: Maul · Shadow Lord · S1E3</div>
|
||||||
|
<div class="ep">Chapter 3: The Crucible</div>
|
||||||
|
<div class="ep-meta">22m / ends 02:49</div>
|
||||||
|
<div class="progress-bar"></div>
|
||||||
|
<div class="actions">
|
||||||
|
<button class="btn btn-primary">▶ Start now</button>
|
||||||
|
<button class="btn">Hide</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body></html>
|
||||||
36
web-overrides/popup-designs/c-minimal.html
Normal file
36
web-overrides/popup-designs/c-minimal.html
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en"><head><meta charset="UTF-8"><title>ARRFLIX popup — C · Minimal Bar</title>
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Geist:wght@400;500;600;700&family=JetBrains+Mono:wght@500&family=Bebas+Neue&display=swap" rel="stylesheet">
|
||||||
|
<style>
|
||||||
|
:root{--arrflix-red:#E50914;--ink:#fff;--ink-dim:rgba(255,255,255,0.55);}
|
||||||
|
*{box-sizing:border-box;margin:0;padding:0;}
|
||||||
|
body{background:#000;color:#fff;font-family:'Geist',system-ui,sans-serif;height:100vh;overflow:hidden;position:relative;}
|
||||||
|
.bg{position:absolute;inset:0;background:radial-gradient(ellipse 60% 40% at 50% 50%,rgba(20,20,40,0.4) 0%,transparent 70%),black;}
|
||||||
|
.popup{position:absolute;bottom:0;left:0;right:0;}
|
||||||
|
.progress-line{height:3px;background:rgba(255,255,255,0.1);position:relative;}
|
||||||
|
.progress-line::after{content:'';position:absolute;top:0;left:0;height:100%;width:75%;background:var(--arrflix-red);}
|
||||||
|
.row{background:linear-gradient(to bottom,transparent,rgba(0,0,0,0.85) 30%);padding:24px 56px 22px;display:flex;align-items:center;gap:24px;}
|
||||||
|
.label{font-family:'Bebas Neue',sans-serif;font-size:13px;letter-spacing:0.32em;color:var(--arrflix-red);flex-shrink:0;}
|
||||||
|
.text{flex:1;font-size:14px;color:var(--ink-dim);letter-spacing:0.02em;}
|
||||||
|
.text strong{color:var(--ink);font-weight:500;margin-right:8px;}
|
||||||
|
.text .countdown{color:var(--arrflix-red);font-family:'JetBrains Mono',monospace;font-weight:500;margin-left:8px;}
|
||||||
|
.actions{display:flex;gap:16px;}
|
||||||
|
.btn{background:transparent;border:none;color:white;font-family:inherit;font-size:12px;letter-spacing:0.2em;text-transform:uppercase;font-weight:600;cursor:pointer;padding:8px 0;position:relative;}
|
||||||
|
.btn::after{content:'';position:absolute;left:0;bottom:0;height:1px;width:100%;background:currentColor;opacity:0.3;}
|
||||||
|
.btn:hover::after{opacity:1;}
|
||||||
|
.btn-primary{color:var(--arrflix-red);}
|
||||||
|
</style></head><body>
|
||||||
|
<div class="bg"></div>
|
||||||
|
<div class="popup">
|
||||||
|
<div class="progress-line"></div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="label">UP NEXT</div>
|
||||||
|
<div class="text"><strong>Star Wars: Maul · Shadow Lord</strong>S1·E3 — Chapter 3: The Crucible<span class="countdown">00:17</span></div>
|
||||||
|
<div class="actions">
|
||||||
|
<button class="btn btn-primary">Start now ▶</button>
|
||||||
|
<button class="btn">Hide</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body></html>
|
||||||
760
web-overrides/popup-designs/preview.html
Normal file
760
web-overrides/popup-designs/preview.html
Normal file
|
|
@ -0,0 +1,760 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>ARRFLIX — Next-Episode popup designs</title>
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Geist:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;700&family=Bebas+Neue&family=Anton&display=swap" rel="stylesheet">
|
||||||
|
<style>
|
||||||
|
:root {
|
||||||
|
--arrflix-red: #E50914;
|
||||||
|
--arrflix-red-dark: #B00710;
|
||||||
|
--arrflix-bg: #0a0a0a;
|
||||||
|
--ink: #fff;
|
||||||
|
--ink-dim: rgba(255,255,255,0.55);
|
||||||
|
--ink-faint: rgba(255,255,255,0.3);
|
||||||
|
}
|
||||||
|
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||||
|
html, body {
|
||||||
|
background: #050505;
|
||||||
|
color: var(--ink);
|
||||||
|
font-family: 'Geist', system-ui, sans-serif;
|
||||||
|
font-feature-settings: "ss01", "ss02";
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
.header {
|
||||||
|
position: sticky; top: 0; z-index: 100;
|
||||||
|
background: rgba(5,5,5,0.85);
|
||||||
|
backdrop-filter: blur(12px);
|
||||||
|
border-bottom: 1px solid rgba(255,255,255,0.08);
|
||||||
|
padding: 18px 28px;
|
||||||
|
display: flex; align-items: center; justify-content: space-between;
|
||||||
|
}
|
||||||
|
.header h1 {
|
||||||
|
font-family: 'Bebas Neue', sans-serif;
|
||||||
|
letter-spacing: 0.1em;
|
||||||
|
font-size: 20px;
|
||||||
|
color: var(--arrflix-red);
|
||||||
|
}
|
||||||
|
.header .meta {
|
||||||
|
font-size: 11px;
|
||||||
|
letter-spacing: 0.18em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--ink-dim);
|
||||||
|
}
|
||||||
|
.picker {
|
||||||
|
display: flex; gap: 10px;
|
||||||
|
}
|
||||||
|
.picker button {
|
||||||
|
background: transparent;
|
||||||
|
border: 1px solid rgba(255,255,255,0.15);
|
||||||
|
color: var(--ink-dim);
|
||||||
|
padding: 8px 14px;
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: 11px;
|
||||||
|
letter-spacing: 0.15em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.15s ease;
|
||||||
|
}
|
||||||
|
.picker button:hover {
|
||||||
|
border-color: var(--arrflix-red);
|
||||||
|
color: var(--ink);
|
||||||
|
}
|
||||||
|
.picker button.active {
|
||||||
|
background: var(--arrflix-red);
|
||||||
|
border-color: var(--arrflix-red);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stage {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
aspect-ratio: 16/9;
|
||||||
|
max-height: calc(100vh - 80px);
|
||||||
|
background: black;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.stage::before {
|
||||||
|
/* Star Wars credits backdrop */
|
||||||
|
content: '';
|
||||||
|
position: absolute; inset: 0;
|
||||||
|
background:
|
||||||
|
radial-gradient(ellipse 60% 40% at 50% 50%, rgba(20,20,40,0.4) 0%, transparent 70%),
|
||||||
|
black;
|
||||||
|
}
|
||||||
|
.stars {
|
||||||
|
position: absolute; inset: 0;
|
||||||
|
background-image:
|
||||||
|
radial-gradient(1px 1px at 20% 30%, white, transparent),
|
||||||
|
radial-gradient(1px 1px at 65% 50%, white, transparent),
|
||||||
|
radial-gradient(1px 1px at 80% 20%, rgba(255,255,255,0.7), transparent),
|
||||||
|
radial-gradient(2px 2px at 10% 70%, white, transparent),
|
||||||
|
radial-gradient(1px 1px at 85% 80%, rgba(255,255,255,0.8), transparent),
|
||||||
|
radial-gradient(1px 1px at 45% 90%, white, transparent),
|
||||||
|
radial-gradient(1px 1px at 30% 15%, rgba(255,255,255,0.5), transparent),
|
||||||
|
radial-gradient(1.5px 1.5px at 70% 75%, white, transparent),
|
||||||
|
radial-gradient(1px 1px at 5% 45%, white, transparent),
|
||||||
|
radial-gradient(1px 1px at 95% 60%, rgba(255,255,255,0.6), transparent),
|
||||||
|
radial-gradient(1px 1px at 25% 85%, white, transparent),
|
||||||
|
radial-gradient(1px 1px at 55% 25%, white, transparent),
|
||||||
|
radial-gradient(2px 2px at 50% 50%, rgba(255,255,255,0.4), transparent),
|
||||||
|
radial-gradient(1px 1px at 15% 92%, white, transparent),
|
||||||
|
radial-gradient(1px 1px at 88% 35%, white, transparent);
|
||||||
|
background-size: 100% 100%;
|
||||||
|
}
|
||||||
|
.credits {
|
||||||
|
position: absolute;
|
||||||
|
top: 18%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
color: #4488dd;
|
||||||
|
font-family: 'Geist', sans-serif;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 14px;
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 1.7;
|
||||||
|
opacity: 0.55;
|
||||||
|
text-shadow: 0 0 4px rgba(68,136,221,0.2);
|
||||||
|
}
|
||||||
|
.credits .row {
|
||||||
|
display: grid; grid-template-columns: 1fr 1fr; gap: 32px;
|
||||||
|
text-align: left;
|
||||||
|
margin-bottom: 18px;
|
||||||
|
}
|
||||||
|
.credits .row .role { text-align: right; opacity: 0.85; }
|
||||||
|
.credits .row .name { text-transform: uppercase; }
|
||||||
|
.credits .title-block { text-align: center; margin-bottom: 18px; }
|
||||||
|
|
||||||
|
/* Stop the star backdrop from comUSER-Eing */
|
||||||
|
.stage .popup-host {
|
||||||
|
position: absolute; inset: 0; z-index: 50;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
.stage .popup-host > * { pointer-events: auto; }
|
||||||
|
|
||||||
|
/* === DESIGN A — CINEMATIC STRIP === */
|
||||||
|
.design-a {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0; left: 0; right: 0;
|
||||||
|
height: 26%;
|
||||||
|
background: linear-gradient(to top, rgba(0,0,0,0.95) 50%, rgba(0,0,0,0.7) 80%, transparent);
|
||||||
|
padding: 28px 56px 32px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 36px;
|
||||||
|
transform: translateY(0);
|
||||||
|
animation: slideUp 0.5s cubic-bezier(0.16, 1, 0.3, 1);
|
||||||
|
}
|
||||||
|
@keyframes slideUp {
|
||||||
|
from { transform: translateY(100%); opacity: 0; }
|
||||||
|
to { transform: translateY(0); opacity: 1; }
|
||||||
|
}
|
||||||
|
.design-a .ring {
|
||||||
|
position: relative;
|
||||||
|
width: 88px; height: 88px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
.design-a .ring svg { transform: rotate(-90deg); }
|
||||||
|
.design-a .ring circle {
|
||||||
|
fill: none;
|
||||||
|
stroke-width: 3;
|
||||||
|
}
|
||||||
|
.design-a .ring .track { stroke: rgba(255,255,255,0.1); }
|
||||||
|
.design-a .ring .progress {
|
||||||
|
stroke: var(--arrflix-red);
|
||||||
|
stroke-dasharray: 264;
|
||||||
|
stroke-dashoffset: 67;
|
||||||
|
stroke-linecap: round;
|
||||||
|
transition: stroke-dashoffset 1s linear;
|
||||||
|
filter: drop-shadow(0 0 8px rgba(229, 9, 20, 0.5));
|
||||||
|
}
|
||||||
|
.design-a .ring .num {
|
||||||
|
position: absolute; inset: 0;
|
||||||
|
display: flex; align-items: center; justify-content: center;
|
||||||
|
font-family: 'JetBrains Mono', monospace;
|
||||||
|
font-size: 28px;
|
||||||
|
font-weight: 500;
|
||||||
|
letter-spacing: -0.02em;
|
||||||
|
}
|
||||||
|
.design-a .info { flex: 1; min-width: 0; }
|
||||||
|
.design-a .label {
|
||||||
|
font-size: 10px;
|
||||||
|
letter-spacing: 0.32em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--arrflix-red);
|
||||||
|
margin-bottom: 8px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
.design-a .title {
|
||||||
|
font-size: 28px;
|
||||||
|
font-weight: 600;
|
||||||
|
letter-spacing: -0.02em;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
line-height: 1.1;
|
||||||
|
}
|
||||||
|
.design-a .episode-title {
|
||||||
|
font-size: 16px;
|
||||||
|
color: var(--ink-dim);
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
.design-a .meta {
|
||||||
|
font-size: 12px;
|
||||||
|
color: var(--ink-faint);
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
}
|
||||||
|
.design-a .actions {
|
||||||
|
display: flex; gap: 10px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
.design-a .btn {
|
||||||
|
border: none;
|
||||||
|
background: white;
|
||||||
|
color: black;
|
||||||
|
padding: 14px 28px;
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 600;
|
||||||
|
letter-spacing: 0.02em;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
transition: all 0.15s ease;
|
||||||
|
}
|
||||||
|
.design-a .btn:hover { background: rgba(255,255,255,0.85); }
|
||||||
|
.design-a .btn-secondary {
|
||||||
|
background: rgba(255,255,255,0.08);
|
||||||
|
color: white;
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
}
|
||||||
|
.design-a .btn-secondary:hover { background: rgba(255,255,255,0.16); }
|
||||||
|
|
||||||
|
/* === DESIGN B — TERMINAL CARD === */
|
||||||
|
.design-b {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 32px; right: 32px;
|
||||||
|
width: 380px;
|
||||||
|
background: rgba(5,5,5,0.92);
|
||||||
|
backdrop-filter: blur(14px);
|
||||||
|
border: 1px solid rgba(255,255,255,0.12);
|
||||||
|
border-left: 2px solid var(--arrflix-red);
|
||||||
|
padding: 20px 22px;
|
||||||
|
font-family: 'JetBrains Mono', monospace;
|
||||||
|
animation: slideRight 0.4s cubic-bezier(0.16, 1, 0.3, 1);
|
||||||
|
}
|
||||||
|
@keyframes slideRight {
|
||||||
|
from { transform: translateX(20px); opacity: 0; }
|
||||||
|
to { transform: translateX(0); opacity: 1; }
|
||||||
|
}
|
||||||
|
.design-b .top-row {
|
||||||
|
display: flex; justify-content: space-between; align-items: center;
|
||||||
|
margin-bottom: 14px;
|
||||||
|
font-size: 10px;
|
||||||
|
letter-spacing: 0.18em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
.design-b .tag {
|
||||||
|
color: var(--arrflix-red);
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
.design-b .countdown {
|
||||||
|
color: var(--ink-dim);
|
||||||
|
}
|
||||||
|
.design-b .countdown strong {
|
||||||
|
color: var(--ink);
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
.design-b hr {
|
||||||
|
border: none;
|
||||||
|
border-top: 1px dashed rgba(255,255,255,0.1);
|
||||||
|
margin: 12px 0;
|
||||||
|
}
|
||||||
|
.design-b .ep {
|
||||||
|
font-family: 'Geist', sans-serif;
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
color: var(--ink);
|
||||||
|
letter-spacing: -0.01em;
|
||||||
|
}
|
||||||
|
.design-b .ep-meta {
|
||||||
|
font-size: 11px;
|
||||||
|
color: var(--ink-faint);
|
||||||
|
letter-spacing: 0.06em;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
.design-b .progress-bar {
|
||||||
|
height: 2px;
|
||||||
|
background: rgba(255,255,255,0.08);
|
||||||
|
margin-bottom: 18px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.design-b .progress-bar::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0; left: 0;
|
||||||
|
height: 100%;
|
||||||
|
width: 75%;
|
||||||
|
background: var(--arrflix-red);
|
||||||
|
box-shadow: 0 0 8px rgba(229,9,20,0.6);
|
||||||
|
animation: fillBar 17s linear forwards;
|
||||||
|
}
|
||||||
|
@keyframes fillBar {
|
||||||
|
to { width: 100%; }
|
||||||
|
}
|
||||||
|
.design-b .actions {
|
||||||
|
display: flex; gap: 8px;
|
||||||
|
}
|
||||||
|
.design-b .btn {
|
||||||
|
flex: 1;
|
||||||
|
background: transparent;
|
||||||
|
border: 1px solid rgba(255,255,255,0.18);
|
||||||
|
color: white;
|
||||||
|
padding: 9px 14px;
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: 11px;
|
||||||
|
letter-spacing: 0.18em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.15s ease;
|
||||||
|
}
|
||||||
|
.design-b .btn-primary {
|
||||||
|
background: var(--arrflix-red);
|
||||||
|
border-color: var(--arrflix-red);
|
||||||
|
}
|
||||||
|
.design-b .btn-primary:hover { background: var(--arrflix-red-dark); }
|
||||||
|
.design-b .btn-secondary:hover {
|
||||||
|
background: rgba(255,255,255,0.06);
|
||||||
|
border-color: rgba(255,255,255,0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* === DESIGN C — MINIMAL BAR === */
|
||||||
|
.design-c {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0; left: 0; right: 0;
|
||||||
|
pointer-events: auto;
|
||||||
|
animation: fadeUp 0.4s ease;
|
||||||
|
}
|
||||||
|
@keyframes fadeUp {
|
||||||
|
from { transform: translateY(20px); opacity: 0; }
|
||||||
|
to { transform: translateY(0); opacity: 1; }
|
||||||
|
}
|
||||||
|
.design-c .progress-line {
|
||||||
|
height: 3px;
|
||||||
|
background: rgba(255,255,255,0.1);
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.design-c .progress-line::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0; left: 0;
|
||||||
|
height: 100%;
|
||||||
|
width: 75%;
|
||||||
|
background: var(--arrflix-red);
|
||||||
|
animation: fillBar 17s linear forwards;
|
||||||
|
}
|
||||||
|
.design-c .row {
|
||||||
|
background: linear-gradient(to bottom, transparent, rgba(0,0,0,0.85) 30%);
|
||||||
|
padding: 24px 56px 22px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 24px;
|
||||||
|
}
|
||||||
|
.design-c .label {
|
||||||
|
font-family: 'Bebas Neue', sans-serif;
|
||||||
|
font-size: 13px;
|
||||||
|
letter-spacing: 0.32em;
|
||||||
|
color: var(--arrflix-red);
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
.design-c .text {
|
||||||
|
flex: 1;
|
||||||
|
font-size: 14px;
|
||||||
|
color: var(--ink-dim);
|
||||||
|
letter-spacing: 0.02em;
|
||||||
|
}
|
||||||
|
.design-c .text strong {
|
||||||
|
color: var(--ink);
|
||||||
|
font-weight: 500;
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
.design-c .text .countdown {
|
||||||
|
color: var(--arrflix-red);
|
||||||
|
font-family: 'JetBrains Mono', monospace;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
.design-c .actions {
|
||||||
|
display: flex; gap: 16px;
|
||||||
|
}
|
||||||
|
.design-c .btn {
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
color: white;
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: 12px;
|
||||||
|
letter-spacing: 0.2em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-weight: 600;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 8px 0;
|
||||||
|
position: relative;
|
||||||
|
transition: color 0.15s ease;
|
||||||
|
}
|
||||||
|
.design-c .btn::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: 0; bottom: 0;
|
||||||
|
height: 1px; width: 100%;
|
||||||
|
background: currentColor;
|
||||||
|
opacity: 0.3;
|
||||||
|
transition: opacity 0.15s ease;
|
||||||
|
}
|
||||||
|
.design-c .btn:hover::after { opacity: 1; }
|
||||||
|
.design-c .btn-primary { color: var(--arrflix-red); }
|
||||||
|
|
||||||
|
/* === DESIGN D — POSTER CARD === */
|
||||||
|
.design-d {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 28px; right: 28px;
|
||||||
|
width: 460px;
|
||||||
|
background: linear-gradient(135deg, rgba(15,15,15,0.95), rgba(5,5,5,0.95));
|
||||||
|
backdrop-filter: blur(20px);
|
||||||
|
border: 1px solid rgba(255,255,255,0.08);
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
box-shadow: 0 20px 60px rgba(0,0,0,0.6),
|
||||||
|
0 0 0 1px rgba(229,9,20,0.15);
|
||||||
|
animation: slideRight 0.4s cubic-bezier(0.16, 1, 0.3, 1);
|
||||||
|
}
|
||||||
|
.design-d .poster {
|
||||||
|
width: 160px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
background:
|
||||||
|
linear-gradient(135deg, rgba(229,9,20,0.3), transparent 60%),
|
||||||
|
radial-gradient(circle at 30% 30%, #2a1a1a, #050505);
|
||||||
|
position: relative;
|
||||||
|
display: flex; align-items: flex-end;
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
.design-d .poster::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute; inset: 0;
|
||||||
|
background-image:
|
||||||
|
radial-gradient(1px 1px at 20% 30%, white, transparent),
|
||||||
|
radial-gradient(1px 1px at 70% 50%, white, transparent),
|
||||||
|
radial-gradient(1px 1px at 40% 70%, white, transparent),
|
||||||
|
radial-gradient(1px 1px at 80% 80%, white, transparent),
|
||||||
|
radial-gradient(1px 1px at 50% 20%, white, transparent),
|
||||||
|
radial-gradient(1.5px 1.5px at 60% 60%, white, transparent);
|
||||||
|
opacity: 0.4;
|
||||||
|
}
|
||||||
|
.design-d .poster .ep-num {
|
||||||
|
position: relative;
|
||||||
|
font-family: 'Anton', sans-serif;
|
||||||
|
font-size: 64px;
|
||||||
|
line-height: 0.9;
|
||||||
|
color: var(--arrflix-red);
|
||||||
|
letter-spacing: -0.04em;
|
||||||
|
text-shadow: 0 4px 20px rgba(229,9,20,0.5);
|
||||||
|
}
|
||||||
|
.design-d .body {
|
||||||
|
flex: 1;
|
||||||
|
padding: 18px 20px 16px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
.design-d .top {
|
||||||
|
display: flex; justify-content: space-between; align-items: center;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
.design-d .label {
|
||||||
|
font-size: 9.5px;
|
||||||
|
letter-spacing: 0.32em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--arrflix-red);
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
.design-d .timer {
|
||||||
|
font-family: 'JetBrains Mono', monospace;
|
||||||
|
font-size: 11px;
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
color: var(--ink-dim);
|
||||||
|
}
|
||||||
|
.design-d .timer strong {
|
||||||
|
color: var(--ink);
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
.design-d .show {
|
||||||
|
font-size: 13px;
|
||||||
|
color: var(--ink-faint);
|
||||||
|
margin-bottom: 4px;
|
||||||
|
letter-spacing: 0.02em;
|
||||||
|
}
|
||||||
|
.design-d .ep-title {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
letter-spacing: -0.02em;
|
||||||
|
line-height: 1.2;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
.design-d .meta {
|
||||||
|
font-size: 11px;
|
||||||
|
color: var(--ink-faint);
|
||||||
|
letter-spacing: 0.06em;
|
||||||
|
margin-bottom: 14px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
.design-d .meta .dot { margin: 0 8px; opacity: 0.5; }
|
||||||
|
.design-d .actions {
|
||||||
|
display: flex; gap: 8px;
|
||||||
|
margin-top: auto;
|
||||||
|
}
|
||||||
|
.design-d .btn {
|
||||||
|
flex: 1;
|
||||||
|
border: none;
|
||||||
|
padding: 11px 12px;
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: 11.5px;
|
||||||
|
font-weight: 600;
|
||||||
|
letter-spacing: 0.08em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.15s ease;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
.design-d .btn-primary {
|
||||||
|
background: var(--arrflix-red);
|
||||||
|
color: white;
|
||||||
|
box-shadow: 0 4px 14px rgba(229,9,20,0.3);
|
||||||
|
}
|
||||||
|
.design-d .btn-primary:hover { background: var(--arrflix-red-dark); }
|
||||||
|
.design-d .btn-secondary {
|
||||||
|
background: transparent;
|
||||||
|
color: var(--ink-dim);
|
||||||
|
border: 1px solid rgba(255,255,255,0.15);
|
||||||
|
}
|
||||||
|
.design-d .btn-secondary:hover {
|
||||||
|
color: var(--ink);
|
||||||
|
border-color: rgba(255,255,255,0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* hidden helper */
|
||||||
|
.hidden { display: none !important; }
|
||||||
|
|
||||||
|
/* design label */
|
||||||
|
.design-label {
|
||||||
|
position: absolute;
|
||||||
|
top: 24px; left: 28px;
|
||||||
|
z-index: 60;
|
||||||
|
font-family: 'Bebas Neue', sans-serif;
|
||||||
|
letter-spacing: 0.18em;
|
||||||
|
font-size: 13px;
|
||||||
|
color: rgba(255,255,255,0.5);
|
||||||
|
border-left: 2px solid var(--arrflix-red);
|
||||||
|
padding-left: 12px;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
.design-label strong {
|
||||||
|
display: block;
|
||||||
|
color: white;
|
||||||
|
font-size: 18px;
|
||||||
|
letter-spacing: 0.1em;
|
||||||
|
}
|
||||||
|
.design-label .desc {
|
||||||
|
font-family: 'Geist', sans-serif;
|
||||||
|
font-size: 11px;
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
text-transform: none;
|
||||||
|
color: var(--ink-dim);
|
||||||
|
margin-top: 4px;
|
||||||
|
max-width: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
padding: 28px 56px 36px;
|
||||||
|
font-size: 12px;
|
||||||
|
color: var(--ink-faint);
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
line-height: 1.7;
|
||||||
|
border-top: 1px solid rgba(255,255,255,0.06);
|
||||||
|
}
|
||||||
|
.footer strong { color: var(--ink-dim); font-weight: 500; }
|
||||||
|
.footer kbd {
|
||||||
|
background: rgba(255,255,255,0.08);
|
||||||
|
border: 1px solid rgba(255,255,255,0.12);
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 2px 6px;
|
||||||
|
font-family: 'JetBrains Mono', monospace;
|
||||||
|
font-size: 11px;
|
||||||
|
color: var(--ink-dim);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<header class="header">
|
||||||
|
<h1>ARRFLIX · NEXT-EPISODE POPUP</h1>
|
||||||
|
<div class="picker">
|
||||||
|
<button data-d="a" class="active">A · STRIP</button>
|
||||||
|
<button data-d="b">B · TERMINAL</button>
|
||||||
|
<button data-d="c">C · MINIMAL</button>
|
||||||
|
<button data-d="d">D · POSTER</button>
|
||||||
|
</div>
|
||||||
|
<div class="meta">PICK ONE · 2026-05-10</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="stage">
|
||||||
|
<div class="stars"></div>
|
||||||
|
<div class="credits">
|
||||||
|
<div class="title-block" style="color:#4488dd; font-weight:600;">
|
||||||
|
Production Services Provided by CGCG, Inc.
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="role">Lighting Director<br>Lighting Lead<br>Lighting Artists</div>
|
||||||
|
<div class="name">Chung-Kai Hsueh<br>Yin-Jung Huang<br>Jung-Tzu Chang · Po-Jui Chiu<br>Char Ho · Luna Jiang<br>Chuan-Sheng Lan · Po-Yu Li</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="role">Special Effects Director<br>Special Effects Artists</div>
|
||||||
|
<div class="name">Chia-Hung Chu<br>Jia-You Cai · Lin-Chi Chen<br>Cai-Jhu Li · Zhi-Hao Liu</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="role">Production Technology</div>
|
||||||
|
<div class="name">Indigo Tang · Joe Chang<br>I Chiang · Chih-Chiang Tsai</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="design-label" id="dlabel">
|
||||||
|
<strong>A · CINEMATIC STRIP</strong>
|
||||||
|
<div class="desc">Full-bleed bottom strip. Big countdown ring. White CTA = Netflix muscle memory. Grand.</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="popup-host">
|
||||||
|
|
||||||
|
<!-- DESIGN A -->
|
||||||
|
<div class="design-a" data-design="a">
|
||||||
|
<div class="ring">
|
||||||
|
<svg width="88" height="88" viewBox="0 0 88 88">
|
||||||
|
<circle class="track" cx="44" cy="44" r="42"/>
|
||||||
|
<circle class="progress" cx="44" cy="44" r="42"/>
|
||||||
|
</svg>
|
||||||
|
<div class="num">17</div>
|
||||||
|
</div>
|
||||||
|
<div class="info">
|
||||||
|
<div class="label">Up Next</div>
|
||||||
|
<div class="title">Star Wars: Maul · Shadow Lord</div>
|
||||||
|
<div class="episode-title">S1·E3 — Chapter 3: The Crucible</div>
|
||||||
|
<div class="meta">22 min · Ends at 2:49 AM</div>
|
||||||
|
</div>
|
||||||
|
<div class="actions">
|
||||||
|
<button class="btn">▶ Start Now</button>
|
||||||
|
<button class="btn btn-secondary">Hide</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- DESIGN B -->
|
||||||
|
<div class="design-b hidden" data-design="b">
|
||||||
|
<div class="top-row">
|
||||||
|
<span class="tag">▎ Up Next</span>
|
||||||
|
<span class="countdown"><strong>17</strong>s</span>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
<div style="font-family:'Geist',sans-serif; font-size: 11px; letter-spacing: 0.18em; text-transform: uppercase; color: var(--ink-faint); margin-bottom: 4px;">Star Wars: Maul · Shadow Lord · S1E3</div>
|
||||||
|
<div class="ep">Chapter 3: The Crucible</div>
|
||||||
|
<div class="ep-meta">22m / ends 02:49</div>
|
||||||
|
<div class="progress-bar"></div>
|
||||||
|
<div class="actions">
|
||||||
|
<button class="btn btn-primary">▶ Start now</button>
|
||||||
|
<button class="btn btn-secondary">Hide</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- DESIGN C -->
|
||||||
|
<div class="design-c hidden" data-design="c">
|
||||||
|
<div class="progress-line"></div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="label">UP NEXT</div>
|
||||||
|
<div class="text">
|
||||||
|
<strong>Star Wars: Maul · Shadow Lord</strong>S1·E3 — Chapter 3: The Crucible
|
||||||
|
<span class="countdown">00:17</span>
|
||||||
|
</div>
|
||||||
|
<div class="actions">
|
||||||
|
<button class="btn btn-primary">Start now ▶</button>
|
||||||
|
<button class="btn">Hide</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- DESIGN D -->
|
||||||
|
<div class="design-d hidden" data-design="d">
|
||||||
|
<div class="poster"><div class="ep-num">E3</div></div>
|
||||||
|
<div class="body">
|
||||||
|
<div class="top">
|
||||||
|
<div class="label">Up Next</div>
|
||||||
|
<div class="timer">in <strong>17</strong>s</div>
|
||||||
|
</div>
|
||||||
|
<div class="show">Star Wars: Maul · Shadow Lord</div>
|
||||||
|
<div class="ep-title">Chapter 3: The Crucible</div>
|
||||||
|
<div class="meta">Season 1 <span class="dot">·</span> 22 min <span class="dot">·</span> Ends 02:49</div>
|
||||||
|
<div class="actions">
|
||||||
|
<button class="btn btn-primary">▶ Start now</button>
|
||||||
|
<button class="btn btn-secondary">Hide</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer">
|
||||||
|
Pick one (<kbd>1</kbd>–<kbd>4</kbd> or click). When approved, design ships as a JS shim into <strong>web-overrides/index.html</strong> bracketed by <strong>NEXT-EP-POPUP-BEGIN/END</strong> markers, with one-shot revert via <strong>bin/revert-next-ep-popup.sh</strong> (matching the sub-label-shim pattern). The shim hides Jellyfin's stock card and renders the chosen design in its place when Jellyfin signals an upcoming episode.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const labels = {
|
||||||
|
a: ['A · CINEMATIC STRIP', 'Full-bleed bottom strip. Big countdown ring. White CTA = Netflix muscle memory. Grand.'],
|
||||||
|
b: ['B · TERMINAL CARD', 'Bottom-right card with monospace, dashed dividers, red accent line. Edgy, ARRFLIX-distinct.'],
|
||||||
|
c: ['C · MINIMAL BAR', 'Thin progress line + small text strip across bottom. Disappears into UX. Power-user.'],
|
||||||
|
d: ['D · POSTER CARD', 'Bottom-right card with episode-number tile + show + ep title + dual buttons. Polished, pragmatic.'],
|
||||||
|
};
|
||||||
|
const buttons = document.querySelectorAll('.picker button');
|
||||||
|
const designs = document.querySelectorAll('[data-design]');
|
||||||
|
const lbl = document.getElementById('dlabel');
|
||||||
|
function show(d) {
|
||||||
|
buttons.forEach(b => b.classList.toggle('active', b.dataset.d === d));
|
||||||
|
designs.forEach(el => el.classList.toggle('hidden', el.dataset.design !== d));
|
||||||
|
lbl.querySelector('strong').textContent = labels[d][0];
|
||||||
|
lbl.querySelector('.desc').textContent = labels[d][1];
|
||||||
|
// restart fillBar animations on switch (recreate elements)
|
||||||
|
designs.forEach(el => {
|
||||||
|
if (el.dataset.design === d) {
|
||||||
|
el.style.animation = 'none';
|
||||||
|
void el.offsetHeight;
|
||||||
|
el.style.animation = '';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
buttons.forEach(b => b.addEventListener('click', () => show(b.dataset.d)));
|
||||||
|
document.addEventListener('keydown', (e) => {
|
||||||
|
const map = { '1':'a', '2':'b', '3':'c', '4':'d' };
|
||||||
|
if (map[e.key]) show(map[e.key]);
|
||||||
|
});
|
||||||
|
|
||||||
|
// animated countdown
|
||||||
|
let t = 17;
|
||||||
|
setInterval(() => {
|
||||||
|
t--;
|
||||||
|
if (t < 0) t = 17;
|
||||||
|
document.querySelector('.design-a .num').textContent = t;
|
||||||
|
document.querySelector('.design-a .ring .progress').style.strokeDashoffset = 67 + (264 - 67) * (1 - t/17);
|
||||||
|
document.querySelector('.design-b .top-row strong').textContent = t;
|
||||||
|
document.querySelector('.design-c .countdown').textContent = '00:' + String(t).padStart(2,'0');
|
||||||
|
document.querySelector('.design-d .timer strong').textContent = t;
|
||||||
|
}, 1000);
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Loading…
Reference in a new issue