feat(home): redesign in AMPP layout — wide preview cards on brand-blue gradient, hardhat avatar centerpiece
This commit is contained in:
parent
1c7329ef35
commit
623e38ae27
1 changed files with 336 additions and 281 deletions
|
|
@ -6,189 +6,182 @@
|
|||
<title>Home — Z-AMPP</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=Inter:wght@400;500;600&display=swap" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="css/common.css">
|
||||
<style>
|
||||
/* AMPP-style landing — wide row of preview cards on a brand-blue gradient */
|
||||
.home-main {
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
background:
|
||||
radial-gradient(ellipse 80% 60% at 50% 0%, oklch(22% 0.04 260 / 0.65), transparent 60%),
|
||||
radial-gradient(ellipse 40% 30% at 50% 100%, oklch(45% 0.20 266 / 0.10), transparent 60%),
|
||||
var(--bg-base);
|
||||
}
|
||||
.home-hero {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(300px, 1fr) minmax(300px, 460px);
|
||||
gap: 48px;
|
||||
align-items: center;
|
||||
padding: 64px 56px 56px;
|
||||
max-width: 1280px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.home-hero-text { display: flex; flex-direction: column; gap: 18px; }
|
||||
.home-eyebrow {
|
||||
display: inline-flex; align-items: center; gap: 10px;
|
||||
width: max-content;
|
||||
padding: 6px 14px 6px 12px;
|
||||
background: oklch(15% 0.020 250);
|
||||
border: 1px solid oklch(35% 0.08 260 / 0.4);
|
||||
border-radius: 999px;
|
||||
font-size: 11px; font-weight: 600; letter-spacing: 0.14em;
|
||||
text-transform: uppercase; color: var(--accent-strong);
|
||||
}
|
||||
.home-eyebrow-dot {
|
||||
width: 6px; height: 6px; background: var(--accent);
|
||||
border-radius: 50%; box-shadow: 0 0 10px var(--accent);
|
||||
}
|
||||
.home-title {
|
||||
font-size: 44px; font-weight: 600; line-height: 1.05;
|
||||
letter-spacing: -0.02em; color: var(--text-primary);
|
||||
}
|
||||
.home-title .accent { color: var(--accent-strong); }
|
||||
.home-subtitle {
|
||||
font-size: 16px; line-height: 1.55;
|
||||
color: var(--text-secondary); max-width: 52ch;
|
||||
}
|
||||
.home-meta {
|
||||
display: flex; gap: 24px; margin-top: 8px;
|
||||
font-size: 12px; color: var(--text-tertiary);
|
||||
font-family: var(--font-mono); letter-spacing: 0.04em;
|
||||
}
|
||||
.home-meta-item { display: flex; align-items: center; gap: 8px; }
|
||||
.home-meta-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--signal-good); box-shadow: 0 0 8px var(--signal-good); }
|
||||
|
||||
.home-portrait {
|
||||
position: relative;
|
||||
aspect-ratio: 3/2;
|
||||
border-radius: 16px;
|
||||
overflow: hidden;
|
||||
background:
|
||||
radial-gradient(ellipse at 40% 35%, oklch(35% 0.18 266 / 0.30), transparent 65%),
|
||||
linear-gradient(135deg, oklch(15% 0.025 250), oklch(8% 0.015 250));
|
||||
border: 1px solid oklch(28% 0.04 260 / 0.6);
|
||||
box-shadow: 0 30px 60px -20px oklch(0% 0 0 / 0.6),
|
||||
inset 0 1px 0 oklch(100% 0 0 / 0.05);
|
||||
radial-gradient(ellipse 70% 50% at 50% 0%, oklch(35% 0.16 266 / 0.55), transparent 65%),
|
||||
radial-gradient(ellipse 80% 60% at 30% 90%, oklch(40% 0.20 266 / 0.45), transparent 70%),
|
||||
radial-gradient(ellipse 60% 50% at 80% 80%, oklch(45% 0.18 240 / 0.30), transparent 65%),
|
||||
linear-gradient(135deg, oklch(20% 0.05 260), oklch(12% 0.025 250) 100%);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.home-stage {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 56px 32px 32px;
|
||||
gap: 36px;
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
.home-brandmark {
|
||||
display: flex; flex-direction: column; align-items: center; gap: 14px;
|
||||
}
|
||||
.home-portrait {
|
||||
width: 120px; height: 120px;
|
||||
border-radius: 50%;
|
||||
overflow: hidden; position: relative;
|
||||
background:
|
||||
radial-gradient(ellipse at 40% 30%, oklch(35% 0.18 266 / 0.4), transparent 65%),
|
||||
linear-gradient(135deg, oklch(20% 0.04 260), oklch(8% 0.015 250));
|
||||
border: 2px solid oklch(55% 0.20 266 / 0.5);
|
||||
box-shadow:
|
||||
0 20px 50px -10px oklch(45% 0.20 266 / 0.4),
|
||||
inset 0 1px 0 oklch(100% 0 0 / 0.08);
|
||||
}
|
||||
.home-portrait img {
|
||||
position: absolute; inset: 0;
|
||||
width: 100%; height: 100%;
|
||||
object-fit: contain;
|
||||
filter: drop-shadow(0 20px 30px oklch(0% 0 0 / 0.5));
|
||||
object-fit: cover;
|
||||
object-position: 50% 30%;
|
||||
}
|
||||
.home-portrait::after {
|
||||
content: ''; position: absolute; inset: 0;
|
||||
background: radial-gradient(ellipse at 50% 100%, oklch(0% 0 0 / 0.3), transparent 50%);
|
||||
pointer-events: none;
|
||||
.home-portrait-dot {
|
||||
position: absolute; bottom: 4px; right: 4px;
|
||||
width: 18px; height: 18px;
|
||||
background: oklch(62% 0.22 25);
|
||||
border: 3px solid oklch(15% 0.025 250);
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 0 12px oklch(62% 0.22 25);
|
||||
animation: live-pulse 1.6s ease-in-out infinite;
|
||||
}
|
||||
.home-portrait-stamp {
|
||||
position: absolute; bottom: 16px; left: 16px;
|
||||
display: inline-flex; align-items: center; gap: 8px;
|
||||
background: oklch(8% 0.015 250 / 0.75);
|
||||
backdrop-filter: blur(8px);
|
||||
padding: 6px 12px;
|
||||
border-radius: 999px;
|
||||
border: 1px solid oklch(35% 0.08 260 / 0.3);
|
||||
font-size: 10px; font-weight: 700; letter-spacing: 0.14em;
|
||||
color: var(--text-primary); text-transform: uppercase;
|
||||
@keyframes live-pulse {
|
||||
0%, 100% { opacity: 0.85; transform: scale(1); }
|
||||
50% { opacity: 1; transform: scale(1.1); }
|
||||
}
|
||||
.home-portrait-stamp .dot {
|
||||
width: 6px; height: 6px; border-radius: 50%;
|
||||
background: var(--accent); box-shadow: 0 0 8px var(--accent);
|
||||
animation: pulse 1.6s ease-in-out infinite;
|
||||
.home-wordmark {
|
||||
font-size: 36px; font-weight: 700;
|
||||
letter-spacing: -0.02em;
|
||||
color: var(--text-primary);
|
||||
line-height: 1;
|
||||
}
|
||||
@keyframes pulse { 0%,100% { opacity: 0.7 } 50% { opacity: 1 } }
|
||||
.home-wordmark .accent { color: oklch(70% 0.18 266); }
|
||||
|
||||
.home-tiles-wrap {
|
||||
max-width: 1280px;
|
||||
margin: 0 auto;
|
||||
padding: 8px 56px 64px;
|
||||
.home-tagline {
|
||||
display: flex; align-items: center; gap: 12px;
|
||||
font-size: 17px; font-weight: 500;
|
||||
color: oklch(75% 0.10 240);
|
||||
letter-spacing: 0.005em;
|
||||
}
|
||||
.home-tiles-header {
|
||||
display: flex; align-items: baseline; justify-content: space-between;
|
||||
margin-bottom: 18px;
|
||||
padding: 0 4px;
|
||||
.home-tagline::before {
|
||||
content: ''; width: 3px; height: 18px;
|
||||
background: oklch(70% 0.18 266);
|
||||
border-radius: 2px;
|
||||
}
|
||||
.home-tiles-title {
|
||||
font-size: 11px; font-weight: 600;
|
||||
letter-spacing: 0.18em; text-transform: uppercase;
|
||||
color: var(--text-tertiary);
|
||||
|
||||
.home-cards {
|
||||
display: flex;
|
||||
gap: 18px;
|
||||
width: 100%;
|
||||
max-width: 1680px;
|
||||
padding: 0 24px;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
}
|
||||
.home-tiles-hint {
|
||||
font-size: 11px; color: var(--text-tertiary);
|
||||
font-family: var(--font-mono);
|
||||
}
|
||||
.home-tiles {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
||||
gap: 16px;
|
||||
}
|
||||
.home-tile {
|
||||
position: relative;
|
||||
display: flex; flex-direction: column; gap: 14px;
|
||||
padding: 24px 22px;
|
||||
background: oklch(13% 0.018 250 / 0.6);
|
||||
border: 1px solid oklch(28% 0.04 260 / 0.5);
|
||||
border-radius: 14px;
|
||||
.home-card {
|
||||
flex: 1 1 0;
|
||||
min-width: 200px;
|
||||
max-width: 220px;
|
||||
background: oklch(12% 0.020 250 / 0.85);
|
||||
border: 1px solid oklch(30% 0.04 260 / 0.5);
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
text-decoration: none;
|
||||
color: var(--text-primary);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
cursor: pointer;
|
||||
transition: transform 160ms ease, border-color 160ms ease, background 160ms ease;
|
||||
backdrop-filter: blur(6px);
|
||||
transition: transform 200ms ease, border-color 200ms ease, box-shadow 200ms ease;
|
||||
}
|
||||
.home-card:hover {
|
||||
transform: translateY(-4px);
|
||||
border-color: oklch(55% 0.20 266 / 0.6);
|
||||
box-shadow: 0 24px 50px -16px oklch(45% 0.20 266 / 0.4);
|
||||
}
|
||||
.home-card-title {
|
||||
padding: 12px 16px 10px;
|
||||
font-size: 15px; font-weight: 500;
|
||||
letter-spacing: 0.005em;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
.home-card-preview {
|
||||
position: relative;
|
||||
aspect-ratio: 16/10;
|
||||
background: linear-gradient(135deg, oklch(18% 0.030 260), oklch(10% 0.015 250));
|
||||
overflow: hidden;
|
||||
border-top: 1px solid oklch(28% 0.04 260 / 0.4);
|
||||
border-bottom: 1px solid oklch(28% 0.04 260 / 0.4);
|
||||
}
|
||||
.home-tile::before {
|
||||
content: ''; position: absolute; inset: 0;
|
||||
background: linear-gradient(135deg, oklch(45% 0.20 266 / 0.05), transparent 50%);
|
||||
opacity: 0; transition: opacity 200ms ease;
|
||||
pointer-events: none;
|
||||
.home-card-preview svg.preview-art {
|
||||
position: absolute; inset: 0;
|
||||
width: 100%; height: 100%;
|
||||
}
|
||||
.home-tile:hover {
|
||||
transform: translateY(-2px);
|
||||
border-color: oklch(45% 0.20 266 / 0.5);
|
||||
background: oklch(15% 0.025 250 / 0.8);
|
||||
}
|
||||
.home-tile:hover::before { opacity: 1; }
|
||||
.home-tile-icon {
|
||||
width: 40px; height: 40px;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
background: oklch(20% 0.04 260);
|
||||
border: 1px solid oklch(35% 0.08 260 / 0.4);
|
||||
border-radius: 10px;
|
||||
color: var(--accent-strong);
|
||||
}
|
||||
.home-tile-icon svg { width: 20px; height: 20px; }
|
||||
.home-tile-title {
|
||||
font-size: 16px; font-weight: 600;
|
||||
letter-spacing: -0.005em;
|
||||
}
|
||||
.home-tile-desc {
|
||||
font-size: 12px; line-height: 1.5;
|
||||
.home-card-stats {
|
||||
position: absolute; bottom: 8px; left: 10px;
|
||||
display: inline-flex; align-items: center; gap: 6px;
|
||||
background: oklch(10% 0.015 250 / 0.8);
|
||||
backdrop-filter: blur(6px);
|
||||
padding: 3px 8px;
|
||||
border-radius: 999px;
|
||||
border: 1px solid oklch(28% 0.04 260 / 0.4);
|
||||
font-size: 10px; font-family: var(--font-mono);
|
||||
letter-spacing: 0.04em;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
.home-tile-meta {
|
||||
display: flex; align-items: center; gap: 6px;
|
||||
margin-top: auto;
|
||||
font-size: 11px; font-family: var(--font-mono);
|
||||
letter-spacing: 0.04em;
|
||||
.home-card-stats b { color: var(--text-primary); font-weight: 600; }
|
||||
.home-card-stats-dot {
|
||||
width: 6px; height: 6px; border-radius: 50%;
|
||||
background: var(--signal-good); box-shadow: 0 0 6px var(--signal-good);
|
||||
}
|
||||
.home-card-desc {
|
||||
padding: 12px 16px 16px;
|
||||
font-size: 11.5px; line-height: 1.5;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.home-footer {
|
||||
padding: 24px;
|
||||
display: flex; align-items: center; gap: 10px;
|
||||
justify-content: center;
|
||||
color: var(--text-tertiary);
|
||||
font-size: 11px; letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.home-tile-meta-num {
|
||||
color: var(--text-primary); font-weight: 600;
|
||||
.home-footer-mark {
|
||||
display: inline-flex; align-items: center; gap: 8px;
|
||||
font-weight: 700; color: var(--text-secondary);
|
||||
}
|
||||
.home-tile-arrow {
|
||||
position: absolute; top: 22px; right: 22px;
|
||||
color: var(--text-tertiary);
|
||||
transition: transform 160ms ease, color 160ms ease;
|
||||
}
|
||||
.home-tile:hover .home-tile-arrow {
|
||||
color: var(--accent-strong);
|
||||
transform: translateX(3px);
|
||||
.home-footer-mark-dot {
|
||||
width: 6px; height: 6px; border-radius: 50%;
|
||||
background: oklch(70% 0.18 266);
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.home-hero { grid-template-columns: 1fr; padding: 40px 24px; gap: 32px; }
|
||||
.home-tiles-wrap { padding: 8px 24px 48px; }
|
||||
.home-title { font-size: 32px; }
|
||||
.home-stage { padding: 32px 16px; gap: 24px; }
|
||||
.home-wordmark { font-size: 28px; }
|
||||
.home-portrait { width: 96px; height: 96px; }
|
||||
.home-cards { gap: 12px; padding: 0 12px; }
|
||||
.home-card { min-width: 150px; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
|
@ -197,139 +190,204 @@
|
|||
<div class="shell">
|
||||
<nav class="sidebar" aria-label="Main navigation">
|
||||
<div class="sidebar-brand">
|
||||
<img src="img/ampp-safe.png?v=hardhat2" alt="Z-AMPP" class="sidebar-logo">
|
||||
<img src="img/ampp-safe.png?v=hardhat3" alt="Z-AMPP" class="sidebar-logo">
|
||||
<span class="sidebar-brand-name">Z-AMPP</span>
|
||||
</div>
|
||||
<nav class="sidebar-nav">
|
||||
<a href="home.html" class="nav-item active">
|
||||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M2 7l6-5 6 5v7a1 1 0 0 1-1 1h-3v-5H6v5H3a1 1 0 0 1-1-1z"/></svg>
|
||||
Home
|
||||
</a>
|
||||
<a href="index.html" class="nav-item">
|
||||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="1" y="1" width="6" height="6" rx="1"/><rect x="9" y="1" width="6" height="6" rx="1"/><rect x="1" y="9" width="6" height="6" rx="1"/><rect x="9" y="9" width="6" height="6" rx="1"/></svg>
|
||||
Library
|
||||
</a>
|
||||
<a href="projects.html" class="nav-item">
|
||||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M1 4a1 1 0 0 1 1-1h4l2 2h5a1 1 0 0 1 1 1v6a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1z"/></svg>
|
||||
Projects
|
||||
</a>
|
||||
<a href="upload.html" class="nav-item">
|
||||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M8 11V3M5 6l3-3 3 3"/><path d="M2 13h12"/></svg>
|
||||
Ingest
|
||||
</a>
|
||||
<a href="recorders.html" class="nav-item">
|
||||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="1" y="4" width="10" height="8" rx="1"/><path d="M11 7l4-2v6l-4-2"/></svg>
|
||||
Recorders
|
||||
</a>
|
||||
<a href="capture.html" class="nav-item">
|
||||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="8" cy="8" r="3"/><circle cx="8" cy="8" r="6.5"/></svg>
|
||||
Capture
|
||||
</a>
|
||||
<a href="jobs.html" class="nav-item">
|
||||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M2 4h12M2 8h8M2 12h5"/></svg>
|
||||
Jobs
|
||||
</a>
|
||||
<a href="#" class="nav-item" onclick="window.open(location.protocol + '//' + location.hostname + ':47435/', '_blank'); return false;">
|
||||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M2 13l1.5-3.5L11 2l3 3-7.5 7.5L3 14zM10 3l3 3"/></svg>
|
||||
Editor
|
||||
</a>
|
||||
<a href="home.html" class="nav-item active"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M2 7l6-5 6 5v7a1 1 0 0 1-1 1h-3v-5H6v5H3a1 1 0 0 1-1-1z"/></svg>Home</a>
|
||||
<a href="index.html" class="nav-item"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="1" y="1" width="6" height="6" rx="1"/><rect x="9" y="1" width="6" height="6" rx="1"/><rect x="1" y="9" width="6" height="6" rx="1"/><rect x="9" y="9" width="6" height="6" rx="1"/></svg>Library</a>
|
||||
<a href="projects.html" class="nav-item"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M1 4a1 1 0 0 1 1-1h4l2 2h5a1 1 0 0 1 1 1v6a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1z"/></svg>Projects</a>
|
||||
<a href="upload.html" class="nav-item"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M8 11V3M5 6l3-3 3 3"/><path d="M2 13h12"/></svg>Ingest</a>
|
||||
<a href="recorders.html" class="nav-item"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="1" y="4" width="10" height="8" rx="1"/><path d="M11 7l4-2v6l-4-2"/></svg>Recorders</a>
|
||||
<a href="capture.html" class="nav-item"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="8" cy="8" r="3"/><circle cx="8" cy="8" r="6.5"/></svg>Capture</a>
|
||||
<a href="jobs.html" class="nav-item"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M2 4h12M2 8h8M2 12h5"/></svg>Jobs</a>
|
||||
<a href="#" class="nav-item" onclick="window.open(location.protocol + '//' + location.hostname + ':47435/', '_blank'); return false;"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M2 13l1.5-3.5L11 2l3 3-7.5 7.5L3 14zM10 3l3 3"/></svg>Editor</a>
|
||||
</nav>
|
||||
</nav>
|
||||
|
||||
<div class="main home-main">
|
||||
<header class="topbar">
|
||||
<div class="topbar-left"><span class="page-title">Home</span></div>
|
||||
<div class="topbar-right">
|
||||
<button class="btn btn-ghost btn-sm" onclick="location.href='settings.html'" title="Settings">
|
||||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" width="14" height="14"><circle cx="8" cy="8" r="2.5"/><path d="M8 1v2M8 13v2M15 8h-2M3 8H1M12.5 3.5L11 5M5 11l-1.5 1.5M12.5 12.5L11 11M5 5L3.5 3.5"/></svg>
|
||||
Settings
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<section class="home-hero">
|
||||
<div class="home-hero-text">
|
||||
<span class="home-eyebrow"><span class="home-eyebrow-dot"></span>AMPP Safe</span>
|
||||
<h1 class="home-title">Z<span class="accent">-</span>AMPP<br><span style="color:var(--text-secondary);font-weight:500">Operator Console</span></h1>
|
||||
<p class="home-subtitle">Self-hosted media asset management for broadcast operations. Pull a feed, monitor the queue, edit on the web, hand off to Premiere. All from one place.</p>
|
||||
<div class="home-meta">
|
||||
<span class="home-meta-item"><span class="home-meta-dot"></span><span id="systemStatus">All systems nominal</span></span>
|
||||
<span class="home-meta-item" id="liveCount" style="display:none"><span class="home-meta-dot" style="background:oklch(62% 0.22 25);box-shadow:0 0 8px oklch(62% 0.22 25)"></span><span id="liveCountText">0 live</span></span>
|
||||
<div class="home-stage">
|
||||
<div class="home-brandmark">
|
||||
<div class="home-portrait">
|
||||
<img src="img/ampp-safe.png?v=hardhat3" alt="Zac in hardhat">
|
||||
<span class="home-portrait-dot" title="On duty"></span>
|
||||
</div>
|
||||
<h1 class="home-wordmark">Z<span class="accent">-</span>AMPP</h1>
|
||||
</div>
|
||||
<div class="home-portrait">
|
||||
<img src="img/ampp-safe.png?v=hardhat2" alt="Zac in hardhat">
|
||||
<div class="home-portrait-stamp"><span class="dot"></span>On Duty</div>
|
||||
|
||||
<div class="home-tagline">Please select an option below to get started</div>
|
||||
|
||||
<div class="home-cards">
|
||||
|
||||
<a href="index.html" class="home-card">
|
||||
<div class="home-card-title">Library</div>
|
||||
<div class="home-card-preview">
|
||||
<svg class="preview-art" viewBox="0 0 200 125" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="0" y="0" width="200" height="125" fill="oklch(13% 0.02 250)"/>
|
||||
<g fill="oklch(25% 0.05 260)" stroke="oklch(45% 0.10 266 / 0.4)" stroke-width="0.5">
|
||||
<rect x="12" y="14" width="40" height="28" rx="2"/>
|
||||
<rect x="58" y="14" width="40" height="28" rx="2"/>
|
||||
<rect x="104" y="14" width="40" height="28" rx="2"/>
|
||||
<rect x="150" y="14" width="40" height="28" rx="2"/>
|
||||
<rect x="12" y="48" width="40" height="28" rx="2"/>
|
||||
<rect x="58" y="48" width="40" height="28" rx="2"/>
|
||||
<rect x="104" y="48" width="40" height="28" rx="2"/>
|
||||
<rect x="150" y="48" width="40" height="28" rx="2"/>
|
||||
<rect x="12" y="82" width="40" height="28" rx="2"/>
|
||||
<rect x="58" y="82" width="40" height="28" rx="2"/>
|
||||
<rect x="104" y="82" width="40" height="28" rx="2"/>
|
||||
<rect x="150" y="82" width="40" height="28" rx="2"/>
|
||||
</g>
|
||||
<g fill="oklch(45% 0.20 266 / 0.8)"><circle cx="32" cy="28" r="3"/><circle cx="124" cy="62" r="3"/><circle cx="170" cy="96" r="3"/></g>
|
||||
</svg>
|
||||
<span class="home-card-stats"><span class="home-card-stats-dot"></span><b id="assetCount">--</b> assets</span>
|
||||
</div>
|
||||
<div class="home-card-desc">Browse, organize, and preview every asset across all projects.</div>
|
||||
</a>
|
||||
|
||||
<a href="projects.html" class="home-card">
|
||||
<div class="home-card-title">Projects</div>
|
||||
<div class="home-card-preview">
|
||||
<svg class="preview-art" viewBox="0 0 200 125" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="0" y="0" width="200" height="125" fill="oklch(13% 0.02 250)"/>
|
||||
<g fill="oklch(20% 0.04 260)" stroke="oklch(45% 0.10 266 / 0.4)" stroke-width="0.5">
|
||||
<path d="M12 24 L12 100 L188 100 L188 36 L92 36 L80 24 Z" />
|
||||
<path d="M28 56 L184 56" stroke-dasharray="2,3"/>
|
||||
<path d="M28 76 L184 76" stroke-dasharray="2,3"/>
|
||||
</g>
|
||||
<g fill="oklch(45% 0.20 266 / 0.6)">
|
||||
<rect x="32" y="46" width="6" height="6" rx="1"/>
|
||||
<rect x="32" y="66" width="6" height="6" rx="1"/>
|
||||
<rect x="32" y="86" width="6" height="6" rx="1"/>
|
||||
</g>
|
||||
</svg>
|
||||
<span class="home-card-stats"><span class="home-card-stats-dot"></span><b id="projectCount">--</b> projects</span>
|
||||
</div>
|
||||
<div class="home-card-desc">Create projects, organize bins, and manage who owns what footage.</div>
|
||||
</a>
|
||||
|
||||
<a href="upload.html" class="home-card">
|
||||
<div class="home-card-title">Ingest</div>
|
||||
<div class="home-card-preview">
|
||||
<svg class="preview-art" viewBox="0 0 200 125" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="0" y="0" width="200" height="125" fill="oklch(13% 0.02 250)"/>
|
||||
<g stroke="oklch(45% 0.20 266 / 0.6)" stroke-width="2" fill="none">
|
||||
<path d="M100 80 V 30 M85 45 L 100 30 L 115 45" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<line x1="30" y1="100" x2="170" y2="100" stroke-dasharray="3,3" stroke-width="1"/>
|
||||
</g>
|
||||
<rect x="40" y="92" width="120" height="6" rx="3" fill="oklch(25% 0.05 260)"/>
|
||||
<rect x="40" y="92" width="68" height="6" rx="3" fill="oklch(55% 0.20 266 / 0.9)"/>
|
||||
</svg>
|
||||
<span class="home-card-stats"><span class="home-card-stats-dot"></span><b id="ingestCount">--</b> processing</span>
|
||||
</div>
|
||||
<div class="home-card-desc">Upload finished files. MOV, MP4, MXF, ProRes — drop them, we proxy them.</div>
|
||||
</a>
|
||||
|
||||
<a href="recorders.html" class="home-card">
|
||||
<div class="home-card-title">Recorders</div>
|
||||
<div class="home-card-preview">
|
||||
<svg class="preview-art" viewBox="0 0 200 125" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="0" y="0" width="200" height="125" fill="oklch(13% 0.02 250)"/>
|
||||
<rect x="20" y="22" width="120" height="80" rx="4" fill="oklch(8% 0.01 250)" stroke="oklch(45% 0.10 266 / 0.4)" stroke-width="0.5"/>
|
||||
<g opacity="0.5"><path d="M30 50 q15 -12 30 0 t30 0 t30 0 t30 0" stroke="oklch(55% 0.20 266)" stroke-width="1" fill="none"/><path d="M30 70 q15 -8 30 0 t30 0 t30 0 t30 0" stroke="oklch(55% 0.20 266)" stroke-width="1" fill="none"/></g>
|
||||
<path d="M140 62 L182 42 L182 82 Z" fill="oklch(20% 0.04 260)" stroke="oklch(45% 0.10 266 / 0.4)" stroke-width="0.5"/>
|
||||
<circle cx="160" cy="62" r="6" fill="oklch(62% 0.22 25)"><animate attributeName="opacity" values="1;0.5;1" dur="1.6s" repeatCount="indefinite"/></circle>
|
||||
</svg>
|
||||
<span class="home-card-stats"><span class="home-card-stats-dot" style="background:oklch(62% 0.22 25);box-shadow:0 0 6px oklch(62% 0.22 25)"></span><b id="recorderCount">--</b> live</span>
|
||||
</div>
|
||||
<div class="home-card-desc">Pull SRT, RTMP, and SDI feeds straight to ProRes with a live HLS preview.</div>
|
||||
</a>
|
||||
|
||||
<a href="capture.html" class="home-card">
|
||||
<div class="home-card-title">Capture</div>
|
||||
<div class="home-card-preview">
|
||||
<svg class="preview-art" viewBox="0 0 200 125" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="0" y="0" width="200" height="125" fill="oklch(13% 0.02 250)"/>
|
||||
<circle cx="100" cy="62" r="34" fill="none" stroke="oklch(45% 0.10 266 / 0.3)" stroke-width="0.5"/>
|
||||
<circle cx="100" cy="62" r="22" fill="none" stroke="oklch(45% 0.10 266 / 0.5)" stroke-width="0.5"/>
|
||||
<circle cx="100" cy="62" r="12" fill="oklch(20% 0.04 260)" stroke="oklch(55% 0.20 266 / 0.7)" stroke-width="1"/>
|
||||
<circle cx="100" cy="62" r="4" fill="oklch(70% 0.18 266)"/>
|
||||
</svg>
|
||||
<span class="home-card-stats"><span class="home-card-stats-dot"></span><b id="captureStatus">Idle</b></span>
|
||||
</div>
|
||||
<div class="home-card-desc">DeckLink SDI capture with manual scene control and per-device routing.</div>
|
||||
</a>
|
||||
|
||||
<a href="#" onclick="window.open(location.protocol + '//' + location.hostname + ':47435/', '_blank'); return false;" class="home-card">
|
||||
<div class="home-card-title">Editor</div>
|
||||
<div class="home-card-preview">
|
||||
<svg class="preview-art" viewBox="0 0 200 125" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="0" y="0" width="200" height="125" fill="oklch(13% 0.02 250)"/>
|
||||
<rect x="14" y="14" width="172" height="44" rx="3" fill="oklch(8% 0.01 250)" stroke="oklch(45% 0.10 266 / 0.4)" stroke-width="0.5"/>
|
||||
<g stroke="oklch(45% 0.10 266 / 0.4)" stroke-width="0.5">
|
||||
<line x1="14" y1="74" x2="186" y2="74"/>
|
||||
<line x1="14" y1="92" x2="186" y2="92"/>
|
||||
<line x1="14" y1="110" x2="186" y2="110"/>
|
||||
</g>
|
||||
<rect x="22" y="68" width="60" height="12" rx="2" fill="oklch(55% 0.20 266 / 0.8)"/>
|
||||
<rect x="90" y="68" width="38" height="12" rx="2" fill="oklch(55% 0.20 266 / 0.5)"/>
|
||||
<rect x="40" y="86" width="90" height="12" rx="2" fill="oklch(70% 0.18 266 / 0.6)"/>
|
||||
<rect x="30" y="104" width="80" height="12" rx="2" fill="oklch(55% 0.20 266 / 0.7)"/>
|
||||
</svg>
|
||||
<span class="home-card-stats"><span class="home-card-stats-dot"></span>Web editor ↗</span>
|
||||
</div>
|
||||
<div class="home-card-desc">Pull a clip from the library into the in-browser editor. Trim, cut, export.</div>
|
||||
</a>
|
||||
|
||||
<a href="jobs.html" class="home-card">
|
||||
<div class="home-card-title">Jobs</div>
|
||||
<div class="home-card-preview">
|
||||
<svg class="preview-art" viewBox="0 0 200 125" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="0" y="0" width="200" height="125" fill="oklch(13% 0.02 250)"/>
|
||||
<g stroke="oklch(45% 0.10 266 / 0.4)" stroke-width="0.5">
|
||||
<line x1="14" y1="28" x2="186" y2="28"/>
|
||||
<line x1="14" y1="46" x2="186" y2="46"/>
|
||||
<line x1="14" y1="64" x2="186" y2="64"/>
|
||||
<line x1="14" y1="82" x2="186" y2="82"/>
|
||||
<line x1="14" y1="100" x2="186" y2="100"/>
|
||||
</g>
|
||||
<rect x="22" y="20" width="38" height="6" rx="3" fill="oklch(45% 0.16 145 / 0.8)"/>
|
||||
<rect x="22" y="38" width="80" height="6" rx="3" fill="oklch(45% 0.16 145 / 0.6)"/>
|
||||
<rect x="22" y="56" width="120" height="6" rx="3" fill="oklch(70% 0.18 80 / 0.8)"/>
|
||||
<rect x="22" y="74" width="60" height="6" rx="3" fill="oklch(45% 0.16 145 / 0.7)"/>
|
||||
<rect x="22" y="92" width="100" height="6" rx="3" fill="oklch(45% 0.16 145 / 0.5)"/>
|
||||
</svg>
|
||||
<span class="home-card-stats"><span class="home-card-stats-dot"></span><b id="jobCount">--</b> active</span>
|
||||
</div>
|
||||
<div class="home-card-desc">Track proxy generation, thumbnails, and AMPP folder sync as they run.</div>
|
||||
</a>
|
||||
|
||||
<a href="settings.html" class="home-card">
|
||||
<div class="home-card-title">Settings</div>
|
||||
<div class="home-card-preview">
|
||||
<svg class="preview-art" viewBox="0 0 200 125" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="0" y="0" width="200" height="125" fill="oklch(13% 0.02 250)"/>
|
||||
<circle cx="100" cy="62" r="22" fill="none" stroke="oklch(55% 0.20 266 / 0.7)" stroke-width="1.5"/>
|
||||
<g stroke="oklch(55% 0.20 266 / 0.7)" stroke-width="2" stroke-linecap="round">
|
||||
<line x1="100" y1="32" x2="100" y2="38"/>
|
||||
<line x1="100" y1="86" x2="100" y2="92"/>
|
||||
<line x1="70" y1="62" x2="76" y2="62"/>
|
||||
<line x1="124" y1="62" x2="130" y2="62"/>
|
||||
<line x1="79" y1="41" x2="84" y2="46"/>
|
||||
<line x1="116" y1="78" x2="121" y2="83"/>
|
||||
<line x1="121" y1="41" x2="116" y2="46"/>
|
||||
<line x1="84" y1="78" x2="79" y2="83"/>
|
||||
</g>
|
||||
<circle cx="100" cy="62" r="7" fill="oklch(20% 0.04 260)" stroke="oklch(70% 0.18 266)" stroke-width="1"/>
|
||||
</svg>
|
||||
<span class="home-card-stats"><span class="home-card-stats-dot"></span>System</span>
|
||||
</div>
|
||||
<div class="home-card-desc">Storage, AMPP sync, recorder defaults, and infrastructure connections.</div>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<section class="home-tiles-wrap">
|
||||
<div class="home-tiles-header">
|
||||
<span class="home-tiles-title">Workspaces</span>
|
||||
<span class="home-tiles-hint" id="updateTime">--</span>
|
||||
</div>
|
||||
<div class="home-tiles">
|
||||
<a href="index.html" class="home-tile">
|
||||
<div class="home-tile-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="2" y="2" width="9" height="9" rx="1"/><rect x="13" y="2" width="9" height="9" rx="1"/><rect x="2" y="13" width="9" height="9" rx="1"/><rect x="13" y="13" width="9" height="9" rx="1"/></svg></div>
|
||||
<div>
|
||||
<div class="home-tile-title">Library</div>
|
||||
<div class="home-tile-desc">Browse, organize, and preview every asset across all projects.</div>
|
||||
</div>
|
||||
<div class="home-tile-meta"><span class="home-tile-meta-num" id="assetCount">--</span><span>assets</span></div>
|
||||
<svg class="home-tile-arrow" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" width="14" height="14"><path d="M5 3l5 5-5 5"/></svg>
|
||||
</a>
|
||||
|
||||
<a href="projects.html" class="home-tile">
|
||||
<div class="home-tile-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M2 5a1 1 0 0 1 1-1h6l3 3h8a1 1 0 0 1 1 1v10a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1z"/></svg></div>
|
||||
<div>
|
||||
<div class="home-tile-title">Projects</div>
|
||||
<div class="home-tile-desc">Create projects, organize bins, and manage who owns what footage.</div>
|
||||
</div>
|
||||
<div class="home-tile-meta"><span class="home-tile-meta-num" id="projectCount">--</span><span>projects</span></div>
|
||||
<svg class="home-tile-arrow" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" width="14" height="14"><path d="M5 3l5 5-5 5"/></svg>
|
||||
</a>
|
||||
|
||||
<a href="upload.html" class="home-tile">
|
||||
<div class="home-tile-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M12 16V4M7 9l5-5 5 5"/><path d="M3 20h18"/></svg></div>
|
||||
<div>
|
||||
<div class="home-tile-title">Ingest</div>
|
||||
<div class="home-tile-desc">Upload finished files. MOV, MP4, MXF, ProRes — drop them, we proxy them.</div>
|
||||
</div>
|
||||
<div class="home-tile-meta"><span class="home-tile-meta-num" id="ingestCount">--</span><span>processing</span></div>
|
||||
<svg class="home-tile-arrow" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" width="14" height="14"><path d="M5 3l5 5-5 5"/></svg>
|
||||
</a>
|
||||
|
||||
<a href="recorders.html" class="home-tile">
|
||||
<div class="home-tile-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="2" y="6" width="15" height="12" rx="1"/><path d="M17 10l5-3v10l-5-3"/></svg></div>
|
||||
<div>
|
||||
<div class="home-tile-title">Recorders</div>
|
||||
<div class="home-tile-desc">Pull SRT, RTMP, and SDI feeds straight to ProRes with a live HLS preview.</div>
|
||||
</div>
|
||||
<div class="home-tile-meta"><span class="home-tile-meta-num" id="recorderCount">--</span><span>recording</span></div>
|
||||
<svg class="home-tile-arrow" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" width="14" height="14"><path d="M5 3l5 5-5 5"/></svg>
|
||||
</a>
|
||||
|
||||
<a href="capture.html" class="home-tile">
|
||||
<div class="home-tile-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="12" cy="12" r="4"/><circle cx="12" cy="12" r="9.5"/></svg></div>
|
||||
<div>
|
||||
<div class="home-tile-title">Capture</div>
|
||||
<div class="home-tile-desc">DeckLink SDI capture with manual scene control and per-device routing.</div>
|
||||
</div>
|
||||
<div class="home-tile-meta"><span id="captureStatus">Idle</span></div>
|
||||
<svg class="home-tile-arrow" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" width="14" height="14"><path d="M5 3l5 5-5 5"/></svg>
|
||||
</a>
|
||||
|
||||
<a href="#" onclick="window.open(location.protocol + '//' + location.hostname + ':47435/', '_blank'); return false;" class="home-tile">
|
||||
<div class="home-tile-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M3 19l2-5L16 3l5 5L10 19l-5 2zM15 5l4 4"/></svg></div>
|
||||
<div>
|
||||
<div class="home-tile-title">Editor</div>
|
||||
<div class="home-tile-desc">Pull a clip from the library into the in-browser editor. Trim, cut, export.</div>
|
||||
</div>
|
||||
<div class="home-tile-meta"><span>Web editor</span><span style="margin-left:auto;color:var(--accent-strong);font-weight:600">↗</span></div>
|
||||
<svg class="home-tile-arrow" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" width="14" height="14"><path d="M5 3l5 5-5 5"/></svg>
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
<div class="home-footer">
|
||||
<span class="home-footer-mark"><span class="home-footer-mark-dot"></span>Wild Dragon</span>
|
||||
<span>·</span>
|
||||
<span id="systemBuild">Z-AMPP Operator Console</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -337,6 +395,7 @@
|
|||
<script src="js/topbar-strip.js"></script>
|
||||
<script>
|
||||
async function loadStats() {
|
||||
const setText = (id, val) => { const el = document.getElementById(id); if (el) el.textContent = val; };
|
||||
try {
|
||||
const [aRes, pRes, rRes, jRes] = await Promise.allSettled([
|
||||
fetch('/api/v1/assets?limit=1', { credentials: 'include' }),
|
||||
|
|
@ -347,30 +406,26 @@
|
|||
|
||||
if (aRes.status === 'fulfilled' && aRes.value.ok) {
|
||||
const j = await aRes.value.json();
|
||||
document.getElementById('assetCount').textContent = j.total ?? (j.assets?.length ?? '--');
|
||||
setText('assetCount', j.total ?? (j.assets?.length ?? '--'));
|
||||
}
|
||||
if (pRes.status === 'fulfilled' && pRes.value.ok) {
|
||||
const j = await pRes.value.json();
|
||||
const arr = Array.isArray(j) ? j : (j.projects ?? []);
|
||||
document.getElementById('projectCount').textContent = arr.length;
|
||||
setText('projectCount', arr.length);
|
||||
}
|
||||
if (rRes.status === 'fulfilled' && rRes.value.ok) {
|
||||
const j = await rRes.value.json();
|
||||
const arr = Array.isArray(j) ? j : [];
|
||||
const recording = arr.filter(r => r.status === 'recording').length;
|
||||
document.getElementById('recorderCount').textContent = recording;
|
||||
if (recording > 0) {
|
||||
document.getElementById('liveCount').style.display = 'flex';
|
||||
document.getElementById('liveCountText').textContent = recording + ' live';
|
||||
}
|
||||
setText('recorderCount', recording);
|
||||
}
|
||||
if (jRes.status === 'fulfilled' && jRes.value.ok) {
|
||||
const j = await jRes.value.json();
|
||||
const arr = Array.isArray(j) ? j : (j.jobs ?? []);
|
||||
document.getElementById('ingestCount').textContent = arr.length;
|
||||
setText('jobCount', arr.length);
|
||||
setText('ingestCount', arr.filter(x => (x.type || '').toLowerCase().includes('proxy')).length || arr.length);
|
||||
}
|
||||
} catch (_) { /* leave dashes */ }
|
||||
document.getElementById('updateTime').textContent = 'Updated ' + new Date().toLocaleTimeString();
|
||||
}
|
||||
loadStats();
|
||||
setInterval(loadStats, 15000);
|
||||
|
|
|
|||
Loading…
Reference in a new issue