Files
alexei.dolgolyov 1e357244e1 chore(design): add aurora redesign mockups + chooser
Three full-fidelity dashboard mockups (Bridge/Console, Aurora/Glass,
Bento/Modular) plus a chooser index and a tracker-detail page in
the chosen Aurora language. Self-contained HTML, no build needed.
2026-04-25 01:11:42 +03:00

1460 lines
56 KiB
HTML

<!doctype html>
<html lang="en" data-theme="dark">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Aurora — Tracker · family-photos</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..700&family=Geist+Mono:wght@300..600&family=Newsreader:ital,opsz,wght@0,6..72,300..700;1,6..72,300..700&display=swap" rel="stylesheet">
<style>
/* ============================================================
AURORA — Tracker Detail
Second view in the Aurora language. Stress-tests forms,
tabs, code preview, switches, and an event log — the four
surfaces a glass aesthetic can fail on if not carefully
handled.
============================================================ */
:root[data-theme="dark"] {
--bg: #050613;
--bg-deep: #02030a;
--fg: #f3f1ff;
--fg-dim: #b6b2d4;
--mute: #6f6c92;
--rule: rgba(255, 255, 255, 0.08);
--rule-strong: rgba(255, 255, 255, 0.16);
--glass: rgba(255, 255, 255, 0.04);
--glass-strong: rgba(255, 255, 255, 0.07);
--glass-elev: rgba(255, 255, 255, 0.10);
--highlight: rgba(255, 255, 255, 0.14);
--input-bg: rgba(255, 255, 255, 0.04);
--input-focus: rgba(184, 167, 255, 0.5);
--lavender: #b8a7ff;
--orchid: #ff9ec4;
--mint: #7ee8c4;
--citrus: #f0e16a;
--coral: #ff8a78;
--sky: #8ec9ff;
--shadow-card: 0 1px 0 rgba(255,255,255,0.07) inset, 0 30px 60px -20px rgba(0,0,0,0.6);
}
:root[data-theme="pearl"] {
--bg: #f5f3ff;
--bg-deep: #ede9fe;
--fg: #1a1530;
--fg-dim: #4a4670;
--mute: #7c789c;
--rule: rgba(20, 15, 60, 0.08);
--rule-strong: rgba(20, 15, 60, 0.16);
--glass: rgba(255, 255, 255, 0.55);
--glass-strong: rgba(255, 255, 255, 0.65);
--glass-elev: rgba(255, 255, 255, 0.80);
--highlight: rgba(255, 255, 255, 0.9);
--input-bg: rgba(255, 255, 255, 0.85);
--input-focus: rgba(109, 76, 224, 0.4);
--lavender: #6d4ce0;
--orchid: #d63384;
--mint: #008a64;
--citrus: #a07a00;
--coral: #e0512f;
--sky: #1f6fcc;
--shadow-card: 0 1px 0 rgba(255,255,255,0.5) inset, 0 20px 40px -16px rgba(80, 50, 180, 0.18);
}
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
background: var(--bg);
color: var(--fg);
font-family: 'Geist', ui-sans-serif, system-ui, sans-serif;
-webkit-font-smoothing: antialiased;
min-height: 100vh;
overflow-x: hidden;
font-size: 14px;
line-height: 1.5;
letter-spacing: -0.005em;
}
body::before {
content: '';
position: fixed; inset: -20vh -10vw;
background:
radial-gradient(40vw 40vw at 12% 18%, rgba(184, 167, 255, 0.55), transparent 60%),
radial-gradient(35vw 35vw at 88% 22%, rgba(255, 158, 196, 0.45), transparent 60%),
radial-gradient(50vw 35vw at 78% 88%, rgba(126, 232, 196, 0.40), transparent 60%),
radial-gradient(40vw 30vw at 6% 92%, rgba(142, 201, 255, 0.42), transparent 60%);
filter: blur(60px) saturate(140%);
pointer-events: none;
z-index: 0;
animation: drift 28s ease-in-out infinite alternate;
}
body::after {
content: '';
position: fixed; inset: 0;
background: radial-gradient(circle at 50% 50%, transparent 30%, var(--bg-deep) 100%);
pointer-events: none; z-index: 0; opacity: 0.7;
}
@keyframes drift {
from { transform: translate(0, 0) scale(1); }
to { transform: translate(-2%, 1%) scale(1.05); }
}
.grain {
position: fixed; inset: 0; z-index: 1; pointer-events: none;
opacity: 0.05; mix-blend-mode: overlay;
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
}
::selection { background: var(--lavender); color: var(--bg-deep); }
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-thumb { background: var(--rule-strong); border-radius: 999px; }
/* ============================================================
SHELL
============================================================ */
.shell {
position: relative; z-index: 2;
display: grid;
grid-template-columns: 240px 1fr;
min-height: 100vh;
padding: 18px;
gap: 18px;
}
/* RAIL — same as dashboard */
.rail {
background: var(--glass);
backdrop-filter: blur(28px) saturate(160%);
-webkit-backdrop-filter: blur(28px) saturate(160%);
border: 1px solid var(--rule);
border-radius: 22px;
box-shadow: var(--shadow-card);
position: sticky; top: 18px;
height: calc(100vh - 36px);
display: flex; flex-direction: column;
overflow: hidden;
}
.rail::after {
content: ''; position: absolute; inset: 0;
border-radius: inherit; pointer-events: none;
background: linear-gradient(180deg, var(--highlight), transparent 30%);
opacity: 0.4;
}
.rail__brand {
padding: 22px 22px 18px;
display: flex; align-items: center; gap: 12px;
position: relative; z-index: 1;
}
.rail__logo {
width: 36px; height: 36px;
border-radius: 12px;
background: conic-gradient(from 220deg, var(--lavender), var(--orchid), var(--mint), var(--lavender));
display: grid; place-items: center;
box-shadow: 0 4px 14px rgba(184, 167, 255, 0.35);
position: relative;
}
.rail__logo::after {
content: ''; position: absolute; inset: 4px;
border-radius: 8px;
background: radial-gradient(circle at 30% 25%, rgba(255,255,255,0.6), transparent 50%);
}
.rail__brand-text { line-height: 1.1; }
.rail__brand-text b { font-weight: 600; font-size: 16px; letter-spacing: -0.01em; }
.rail__brand-text small { color: var(--mute); font-size: 11px; font-family: 'Geist Mono', monospace; }
.rail__group { padding: 8px 12px; position: relative; z-index: 1; }
.rail__label {
font-size: 10px; text-transform: uppercase; letter-spacing: 0.13em;
color: var(--mute); padding: 12px 10px 8px; font-weight: 500;
}
.rail__nav { display: flex; flex-direction: column; gap: 2px; }
.rail__link {
display: flex; align-items: center; gap: 12px;
padding: 9px 12px;
color: var(--fg-dim); text-decoration: none;
font-size: 13.5px; border-radius: 12px;
transition: all .2s cubic-bezier(.4,.4,0,1);
position: relative; font-weight: 450;
}
.rail__link:hover { color: var(--fg); background: var(--glass-strong); }
.rail__link.is-active {
color: var(--fg);
background: var(--glass-elev);
box-shadow: inset 0 1px 0 var(--highlight), 0 4px 18px -8px rgba(184,167,255,0.35);
}
.rail__link.is-active::before {
content: ''; position: absolute; left: 6px; top: 50%; transform: translateY(-50%);
width: 3px; height: 14px; border-radius: 2px;
background: linear-gradient(var(--lavender), var(--orchid));
}
.rail__link svg { width: 17px; height: 17px; flex-shrink: 0; opacity: 0.85; }
.rail__link .count {
margin-left: auto;
font-family: 'Geist Mono', monospace; font-size: 10.5px; color: var(--mute);
background: var(--glass); padding: 2px 7px; border-radius: 999px;
font-variant-numeric: tabular-nums;
}
.rail__link.is-active .count { color: var(--fg); background: var(--glass-elev); }
.rail__foot { margin-top: auto; padding: 16px; position: relative; z-index: 1; }
.rail__op {
background: var(--glass-strong);
border: 1px solid var(--rule);
border-radius: 14px;
padding: 10px 12px;
display: flex; align-items: center; gap: 12px;
}
.rail__avatar {
width: 34px; height: 34px; border-radius: 50%;
background: linear-gradient(135deg, var(--orchid), var(--lavender));
display: grid; place-items: center;
color: white; font-weight: 600; font-size: 14px;
box-shadow: 0 0 0 2px var(--glass) inset;
}
.rail__op-name { font-size: 13px; font-weight: 500; }
.rail__op-role { font-size: 10.5px; color: var(--mute); margin-top: 1px; }
.rail__chip {
margin-left: auto; width: 8px; height: 8px; border-radius: 50%;
background: var(--mint); box-shadow: 0 0 8px var(--mint);
}
/* ============================================================
MAIN
============================================================ */
.main { display: flex; flex-direction: column; gap: 18px; min-width: 0; }
/* TOP CRUMB BAR */
.topbar {
background: var(--glass);
backdrop-filter: blur(28px) saturate(160%);
-webkit-backdrop-filter: blur(28px) saturate(160%);
border: 1px solid var(--rule);
border-radius: 22px;
padding: 12px 18px;
display: flex; align-items: center; gap: 14px;
position: relative;
}
.topbar::after {
content: ''; position: absolute; inset: 0;
border-radius: inherit; pointer-events: none;
background: linear-gradient(180deg, var(--highlight), transparent 30%);
opacity: 0.4;
}
.crumbs {
flex: 1;
display: flex; align-items: center; gap: 10px;
font-size: 13px; color: var(--fg-dim);
font-weight: 500;
position: relative; z-index: 1;
}
.crumbs a { color: var(--fg-dim); text-decoration: none; transition: color .15s; }
.crumbs a:hover { color: var(--fg); }
.crumbs .sep { color: var(--mute); }
.crumbs .here { color: var(--fg); font-weight: 600; }
.icon-btn {
width: 36px; height: 36px;
border-radius: 12px;
border: 1px solid var(--rule);
background: var(--glass-strong);
color: var(--fg-dim);
display: grid; place-items: center;
cursor: pointer;
transition: all .2s;
position: relative; z-index: 1;
}
.icon-btn:hover { background: var(--glass-elev); color: var(--fg); }
.icon-btn svg { width: 16px; height: 16px; }
/* HERO — tracker name + status + key actions */
.hero {
background: var(--glass);
backdrop-filter: blur(28px) saturate(160%);
-webkit-backdrop-filter: blur(28px) saturate(160%);
border: 1px solid var(--rule);
border-radius: 22px;
padding: 30px 36px 32px;
position: relative;
overflow: hidden;
}
.hero::after {
content: ''; position: absolute; inset: 0;
border-radius: inherit; pointer-events: none;
background: linear-gradient(180deg, var(--highlight), transparent 30%);
opacity: 0.4;
}
.hero__row {
position: relative; z-index: 1;
display: grid; grid-template-columns: 1fr auto;
align-items: center; gap: 28px;
}
.hero__chip {
display: inline-flex; align-items: center; gap: 8px;
padding: 5px 12px;
border-radius: 999px;
background: var(--glass-strong);
border: 1px solid var(--rule);
font-size: 11.5px;
color: var(--fg-dim);
margin-bottom: 12px;
font-weight: 500;
}
.hero__chip svg { width: 14px; height: 14px; }
.hero__chip b { color: var(--fg); font-weight: 600; }
.hero__title {
font-family: 'Newsreader', serif; font-weight: 400;
font-size: 48px; line-height: 1; letter-spacing: -0.025em;
margin: 0 0 14px;
color: var(--fg);
display: flex; align-items: baseline; gap: 14px; flex-wrap: wrap;
}
.hero__title em {
font-style: italic;
background: linear-gradient(135deg, var(--orchid), var(--lavender));
-webkit-background-clip: text; background-clip: text; color: transparent;
}
.hero__pill-live {
display: inline-flex; align-items: center; gap: 6px;
padding: 4px 12px;
border-radius: 999px;
background: rgba(126, 232, 196, 0.15);
border: 1px solid rgba(126, 232, 196, 0.3);
color: var(--mint);
font-size: 11.5px;
font-weight: 600;
font-family: 'Geist', sans-serif;
text-transform: uppercase; letter-spacing: 0.1em;
vertical-align: middle;
}
.hero__pill-live::before {
content: ''; width: 7px; height: 7px;
border-radius: 50%;
background: var(--mint);
box-shadow: 0 0 8px var(--mint);
animation: ping 1.4s ease-in-out infinite;
}
@keyframes ping {
0%, 100% { transform: scale(1); opacity: 1; }
50% { transform: scale(1.5); opacity: 0.6; }
}
.hero__sub {
font-size: 14.5px; color: var(--fg-dim);
line-height: 1.55; max-width: 680px;
font-weight: 400;
}
.hero__sub b { color: var(--fg); font-weight: 500; }
.hero__actions { display: flex; gap: 8px; align-items: center; }
.toggle {
display: inline-flex; align-items: center; gap: 10px;
background: var(--glass-strong);
border: 1px solid var(--rule);
border-radius: 999px;
padding: 6px 14px 6px 6px;
cursor: pointer;
transition: all .2s;
}
.toggle:hover { border-color: var(--rule-strong); }
.toggle__sw {
width: 36px; height: 22px;
border-radius: 999px;
background: linear-gradient(135deg, var(--mint), var(--sky));
position: relative;
box-shadow: 0 0 12px -2px var(--mint);
}
.toggle__sw::after {
content: ''; position: absolute;
top: 2px; left: 16px;
width: 18px; height: 18px;
border-radius: 50%;
background: white;
box-shadow: 0 2px 4px rgba(0,0,0,0.2);
transition: left .2s;
}
.toggle.is-off .toggle__sw {
background: var(--glass-elev);
box-shadow: none;
}
.toggle.is-off .toggle__sw::after { left: 2px; background: var(--mute); }
.toggle__label {
font-size: 12px; font-weight: 600;
color: var(--fg);
}
.ghost-btn {
display: inline-flex; align-items: center; gap: 8px;
padding: 0 14px; height: 36px;
border-radius: 12px;
border: 1px solid var(--rule-strong);
background: var(--glass-strong);
color: var(--fg);
font-family: inherit;
font-size: 12.5px; font-weight: 500;
cursor: pointer;
transition: all .15s;
}
.ghost-btn:hover { background: var(--glass-elev); }
.ghost-btn svg { width: 14px; height: 14px; }
.danger-btn {
color: var(--coral);
border-color: rgba(255, 138, 120, 0.3);
}
.danger-btn:hover { background: rgba(255, 138, 120, 0.12); }
/* ROUTING TRAIL — the killer visual */
.trail {
margin-top: 28px;
position: relative; z-index: 1;
display: grid;
grid-template-columns: 1fr 60px 1fr 60px 1fr 60px 1fr;
gap: 0;
align-items: stretch;
background: var(--glass-strong);
border: 1px solid var(--rule);
border-radius: 18px;
padding: 4px;
}
.trail__node {
padding: 16px 18px;
border-radius: 14px;
background: transparent;
text-align: center;
transition: background .15s;
cursor: pointer;
display: flex; flex-direction: column; justify-content: center; gap: 6px;
position: relative;
}
.trail__node:hover { background: var(--glass); }
.trail__node-icon {
width: 36px; height: 36px;
margin: 0 auto;
border-radius: 12px;
display: grid; place-items: center;
background: var(--glass-elev);
border: 1px solid var(--rule);
color: var(--node-color, var(--lavender));
box-shadow: inset 0 1px 0 var(--highlight);
}
.trail__node-icon svg { width: 18px; height: 18px; }
.trail__node-label {
font-size: 10px; text-transform: uppercase; letter-spacing: 0.15em;
color: var(--mute); font-weight: 600;
margin-top: 2px;
}
.trail__node-name {
font-size: 14px; font-weight: 600; color: var(--fg);
line-height: 1.3;
}
.trail__node-name em {
font-family: 'Newsreader', serif;
font-style: italic;
color: var(--node-color, var(--lavender));
font-weight: 500;
-webkit-background-clip: text; background-clip: text;
}
.trail__node-meta {
font-family: 'Geist Mono', monospace;
font-size: 10.5px;
color: var(--mute);
}
.trail__wire {
display: flex; align-items: center; justify-content: center;
position: relative;
}
.trail__wire::before {
content: ''; position: absolute;
left: 0; right: 0; top: 50%;
height: 2px;
background: linear-gradient(90deg,
transparent,
var(--lavender) 30%,
var(--orchid) 70%,
transparent
);
border-radius: 2px;
opacity: 0.6;
}
.trail__wire::after {
content: '→';
position: relative;
background: var(--bg-deep);
color: var(--lavender);
font-size: 14px;
padding: 0 6px;
font-weight: 700;
}
/* ============================================================
MAIN GRID — tabs (left) + side panels (right)
============================================================ */
.grid {
display: grid;
grid-template-columns: 1.6fr 1fr;
gap: 18px;
}
.panel {
background: var(--glass);
backdrop-filter: blur(28px) saturate(160%);
-webkit-backdrop-filter: blur(28px) saturate(160%);
border: 1px solid var(--rule);
border-radius: 22px;
box-shadow: var(--shadow-card);
overflow: hidden;
position: relative;
display: flex; flex-direction: column;
}
.panel::after {
content: ''; position: absolute; inset: 0;
border-radius: inherit; pointer-events: none;
background: linear-gradient(180deg, var(--highlight), transparent 30%);
opacity: 0.4;
}
/* TABS */
.tabs {
display: flex;
padding: 4px;
margin: 18px 18px 0;
background: var(--glass-strong);
border: 1px solid var(--rule);
border-radius: 14px;
gap: 2px;
position: relative; z-index: 1;
}
.tabs button {
flex: 1;
padding: 9px 12px;
border: 0; background: transparent;
color: var(--fg-dim);
font-family: inherit;
font-size: 13px; font-weight: 600;
border-radius: 11px;
cursor: pointer;
transition: all .15s;
display: inline-flex; align-items: center; justify-content: center; gap: 8px;
}
.tabs button:hover { color: var(--fg); }
.tabs button.is-active {
background: var(--glass-elev);
color: var(--fg);
box-shadow: inset 0 1px 0 var(--highlight), 0 2px 8px rgba(0,0,0,0.15);
}
.tabs button svg { width: 14px; height: 14px; }
.tabs button .badge {
background: var(--rule);
color: var(--fg);
font-size: 10px;
font-family: 'Geist Mono', monospace;
padding: 1px 6px;
border-radius: 999px;
font-weight: 500;
}
.tabs button.is-active .badge {
background: var(--lavender);
color: var(--bg-deep);
}
.tab-panel {
padding: 24px 28px 28px;
position: relative; z-index: 1;
}
.tab-panel__head {
display: flex; justify-content: space-between; align-items: end;
margin-bottom: 20px;
padding-bottom: 16px;
border-bottom: 1px solid var(--rule);
}
.tab-panel__title {
font-family: 'Newsreader', serif; font-weight: 400;
font-size: 22px; letter-spacing: -0.02em;
margin: 0;
}
.tab-panel__title em {
font-style: italic;
background: linear-gradient(135deg, var(--orchid), var(--lavender));
-webkit-background-clip: text; background-clip: text; color: transparent;
}
.tab-panel__hint {
font-size: 12.5px; color: var(--mute);
margin-top: 4px;
font-weight: 400;
}
/* FORM */
.field { margin-bottom: 20px; }
.field__label {
display: flex; align-items: center; gap: 8px;
font-size: 12.5px; font-weight: 600;
color: var(--fg);
margin-bottom: 8px;
}
.field__hint {
font-weight: 400; color: var(--mute);
font-size: 11px;
margin-left: auto;
}
.field__sub {
font-size: 12px; color: var(--mute);
margin-top: 6px;
line-height: 1.45;
}
.input, .select, .textarea {
width: 100%;
background: var(--input-bg);
border: 1px solid var(--rule-strong);
border-radius: 12px;
padding: 11px 14px;
color: var(--fg);
font-family: inherit;
font-size: 13.5px;
transition: all .15s;
}
.input:focus, .select:focus, .textarea:focus {
outline: none;
border-color: var(--lavender);
box-shadow: 0 0 0 3px var(--input-focus);
}
.input::placeholder, .textarea::placeholder { color: var(--mute); }
.textarea { font-family: 'Geist Mono', monospace; font-size: 12.5px; line-height: 1.5; resize: vertical; }
.field--mono .input { font-family: 'Geist Mono', monospace; font-size: 12.5px; }
.row-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.row-3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 14px; }
/* CHECKBOXES — event types */
.checkboxes {
display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px;
}
.check-item {
display: flex; align-items: center; gap: 10px;
padding: 12px 14px;
border-radius: 12px;
background: var(--input-bg);
border: 1px solid var(--rule-strong);
cursor: pointer;
transition: all .15s;
}
.check-item:hover { background: var(--glass-elev); }
.check-item.is-on {
border-color: var(--lavender);
background: rgba(184, 167, 255, 0.10);
}
.check-item__box {
width: 18px; height: 18px;
border-radius: 6px;
border: 1.5px solid var(--rule-strong);
display: grid; place-items: center;
flex-shrink: 0;
background: var(--input-bg);
transition: all .15s;
}
.check-item.is-on .check-item__box {
background: linear-gradient(135deg, var(--lavender), var(--orchid));
border-color: transparent;
box-shadow: 0 0 8px -2px var(--lavender);
}
.check-item__box svg { width: 12px; height: 12px; color: white; opacity: 0; transition: opacity .15s; }
.check-item.is-on .check-item__box svg { opacity: 1; }
.check-item__icon {
width: 28px; height: 28px;
border-radius: 8px;
background: var(--glass-elev);
display: grid; place-items: center;
flex-shrink: 0;
color: var(--ev-color, var(--fg-dim));
}
.check-item__icon svg { width: 16px; height: 16px; }
.check-item__main { flex: 1; min-width: 0; }
.check-item__name { font-size: 13px; font-weight: 600; color: var(--fg); }
.check-item__sub { font-size: 11px; color: var(--mute); margin-top: 1px; }
/* TARGET ASSIGNMENTS — pill row */
.targets-pills {
display: flex; flex-wrap: wrap; gap: 8px;
}
.tgt-pill {
display: inline-flex; align-items: center; gap: 8px;
padding: 8px 12px 8px 8px;
border-radius: 999px;
background: var(--glass-strong);
border: 1px solid var(--rule-strong);
font-size: 12.5px;
color: var(--fg);
font-weight: 500;
transition: all .15s;
cursor: pointer;
}
.tgt-pill:hover { background: var(--glass-elev); }
.tgt-pill__icon {
width: 22px; height: 22px;
border-radius: 50%;
background: linear-gradient(135deg, var(--pill-from, var(--lavender)), var(--pill-to, var(--orchid)));
display: grid; place-items: center;
color: white;
flex-shrink: 0;
}
.tgt-pill__icon svg { width: 12px; height: 12px; }
.tgt-pill__remove {
color: var(--mute);
cursor: pointer;
width: 16px; height: 16px;
display: grid; place-items: center;
border-radius: 50%;
transition: all .15s;
}
.tgt-pill__remove:hover { background: rgba(255,138,120,0.2); color: var(--coral); }
.tgt-pill--add {
background: transparent;
border-style: dashed;
color: var(--fg-dim);
}
/* SAVE BAR */
.savebar {
display: flex; justify-content: space-between; align-items: center;
padding: 18px 28px;
background: var(--glass-strong);
border-top: 1px solid var(--rule);
margin-top: auto;
position: relative; z-index: 1;
}
.savebar__status {
display: flex; align-items: center; gap: 8px;
font-size: 12.5px; color: var(--fg-dim);
}
.savebar__status .dot {
width: 8px; height: 8px; border-radius: 50%;
background: var(--citrus);
box-shadow: 0 0 6px var(--citrus);
}
.savebar__actions { display: flex; gap: 8px; }
.primary-btn {
display: inline-flex; align-items: center; gap: 8px;
padding: 0 18px; height: 38px;
border-radius: 12px;
border: 0;
background: linear-gradient(135deg, var(--lavender), var(--orchid));
color: white;
font-family: inherit;
font-size: 13px; font-weight: 600;
cursor: pointer;
box-shadow: 0 6px 20px -8px rgba(184,167,255,0.6), inset 0 1px 0 rgba(255,255,255,0.4);
transition: transform .15s;
}
.primary-btn:hover { transform: translateY(-1px); }
.primary-btn svg { width: 14px; height: 14px; }
/* ============================================================
RIGHT COLUMN — preview + recent events
============================================================ */
.side { display: flex; flex-direction: column; gap: 18px; }
.panel__head {
display: flex; align-items: center; justify-content: space-between;
padding: 22px 24px 14px;
position: relative; z-index: 1;
}
.panel__title {
font-family: 'Newsreader', serif; font-weight: 400;
font-size: 20px; letter-spacing: -0.02em;
margin: 0;
}
.panel__title em {
font-style: italic;
background: linear-gradient(135deg, var(--mint), var(--sky));
-webkit-background-clip: text; background-clip: text; color: transparent;
}
.panel__title.acc-orchid em {
background: linear-gradient(135deg, var(--orchid), var(--lavender));
-webkit-background-clip: text; background-clip: text;
}
.panel__meta { font-size: 11.5px; color: var(--mute); display: flex; gap: 12px; align-items: center; }
.panel__meta b { color: var(--fg); font-weight: 500; font-variant-numeric: tabular-nums; }
/* PREVIEW pane — chat-style mock */
.preview {
padding: 6px 24px 22px;
position: relative; z-index: 1;
}
.preview__device {
background: var(--glass-elev);
border: 1px solid var(--rule-strong);
border-radius: 18px;
padding: 14px;
box-shadow: 0 1px 0 var(--highlight) inset, 0 12px 30px -16px rgba(0,0,0,0.4);
}
.preview__head {
display: flex; align-items: center; gap: 10px;
margin-bottom: 10px;
}
.preview__head-icon {
width: 28px; height: 28px;
border-radius: 50%;
background: linear-gradient(135deg, #29b6f6, #0288d1);
display: grid; place-items: center;
color: white;
}
.preview__head-icon svg { width: 14px; height: 14px; }
.preview__head-name { font-size: 13px; font-weight: 600; }
.preview__head-sub { font-size: 11px; color: var(--mute); margin-top: 1px; }
.preview__head-time {
margin-left: auto;
font-family: 'Geist Mono', monospace;
font-size: 10.5px; color: var(--mute);
}
.preview__bubble {
background: rgba(135, 206, 250, 0.08);
border: 1px solid rgba(135, 206, 250, 0.2);
border-radius: 16px 16px 16px 4px;
padding: 12px 14px;
font-size: 13.5px;
line-height: 1.55;
}
.preview__bubble b { font-weight: 700; }
.preview__bubble a { color: var(--sky); text-decoration: none; }
.preview__bubble a:hover { text-decoration: underline; }
.preview__bubble .muted { color: var(--mute); }
.preview__media {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 4px;
margin-top: 10px;
border-radius: 10px;
overflow: hidden;
}
.preview__media-cell {
aspect-ratio: 1; border-radius: 6px;
background-size: cover; background-position: center;
}
/* Six cells, varied palette gradients to fake images */
.pmc-1 { background: linear-gradient(135deg, #ffb56a, #ff8a78); }
.pmc-2 { background: linear-gradient(135deg, #a0e8c4, #6db5fa); }
.pmc-3 { background: linear-gradient(135deg, #b8a7ff, #ff9ec4); }
.pmc-4 { background: linear-gradient(135deg, #f0e16a, #e8a050); }
.pmc-5 { background: linear-gradient(135deg, #8ec9ff, #b8a7ff); }
.pmc-6 { background: linear-gradient(135deg, #ff9ec4, #ffb56a); }
.preview__footer {
margin-top: 12px;
padding-top: 10px;
border-top: 1px solid var(--rule);
font-size: 11px; color: var(--mute);
display: flex; justify-content: space-between;
}
.preview__refresh {
cursor: pointer; color: var(--fg-dim);
display: inline-flex; align-items: center; gap: 4px;
transition: color .15s;
}
.preview__refresh:hover { color: var(--lavender); }
.preview__refresh svg { width: 12px; height: 12px; }
/* EVENT LOG */
.events { padding: 6px 0 14px; position: relative; z-index: 1; }
.event {
display: grid;
grid-template-columns: 38px 1fr auto;
gap: 14px;
padding: 12px 24px;
align-items: center;
cursor: pointer;
transition: background .15s;
}
.event + .event { border-top: 1px solid var(--rule); }
.event:hover { background: var(--glass-strong); }
.event__avatar {
width: 38px; height: 38px;
border-radius: 12px;
display: grid; place-items: center;
background: linear-gradient(135deg, var(--ev-from, var(--lavender)), var(--ev-to, var(--orchid)));
color: white;
box-shadow: 0 4px 14px -4px var(--ev-from, rgba(184,167,255,0.4)), inset 0 1px 0 rgba(255,255,255,0.3);
}
.event__avatar svg { width: 17px; height: 17px; }
.event__head {
font-size: 13.5px; line-height: 1.4;
}
.event__head b { font-weight: 600; color: var(--fg); }
.event__head .v { color: var(--fg-dim); font-weight: 400; }
.event__sub {
margin-top: 3px;
font-size: 11.5px; color: var(--mute);
}
.event__sub .ch {
color: var(--fg-dim); font-family: 'Geist Mono', monospace;
font-size: 10.5px;
background: var(--glass-strong); padding: 1px 6px; border-radius: 5px;
}
.event__when {
text-align: right;
font-family: 'Geist Mono', monospace;
font-size: 10.5px; color: var(--mute);
}
.event__when b { display: block; color: var(--fg-dim); font-size: 12px; font-weight: 500; font-variant-numeric: tabular-nums; }
/* SCHEDULE preview (mini calendar bars) */
.sched-row {
display: grid;
grid-template-columns: 38px repeat(24, 1fr);
gap: 2px;
margin-bottom: 4px;
}
.sched-day {
font-family: 'Geist Mono', monospace;
font-size: 9.5px; color: var(--mute);
text-align: right; padding-right: 6px;
line-height: 12px;
text-transform: uppercase;
letter-spacing: 0.08em;
}
.sched-cell {
height: 12px; border-radius: 3px;
background: var(--glass-strong);
}
.sched-cell.on {
background: linear-gradient(180deg, var(--lavender), var(--orchid));
box-shadow: 0 0 6px -2px var(--lavender);
}
/* THEME TOGGLE */
.theme-toggle {
position: fixed; right: 22px; top: 22px; z-index: 50;
background: var(--glass);
backdrop-filter: blur(28px) saturate(160%);
border: 1px solid var(--rule-strong);
border-radius: 999px;
padding: 4px;
display: inline-flex;
box-shadow: var(--shadow-card);
}
.theme-toggle button {
padding: 7px 14px;
border: 0; background: transparent;
color: var(--fg-dim);
font-family: inherit;
font-size: 11.5px; font-weight: 500;
border-radius: 999px; cursor: pointer;
}
.theme-toggle button.is-active { background: var(--fg); color: var(--bg); }
@keyframes rise {
from { opacity: 0; transform: translateY(14px); }
to { opacity: 1; transform: translateY(0); }
}
.stagger > * { animation: rise .6s cubic-bezier(.2,.7,.2,1) both; }
.stagger > *:nth-child(1){animation-delay:.05s}
.stagger > *:nth-child(2){animation-delay:.13s}
.stagger > *:nth-child(3){animation-delay:.21s}
.stagger > *:nth-child(4){animation-delay:.29s}
.stagger > *:nth-child(5){animation-delay:.37s}
@media (max-width: 1100px) {
.grid { grid-template-columns: 1fr; }
.trail { grid-template-columns: 1fr 1fr; }
.trail__wire { display: none; }
}
@media (max-width: 820px) {
.shell { grid-template-columns: 1fr; padding: 12px; }
.rail { position: static; height: auto; }
.hero { padding: 22px 20px; }
.hero__row { grid-template-columns: 1fr; }
.hero__title { font-size: 32px; }
.checkboxes { grid-template-columns: 1fr; }
}
</style>
</head>
<body>
<div class="grain"></div>
<div class="theme-toggle">
<button id="t-dark" class="is-active" onclick="setTheme('dark')">Aurora</button>
<button id="t-pearl" onclick="setTheme('pearl')">Pearl</button>
</div>
<div class="shell">
<!-- RAIL -->
<aside class="rail">
<div class="rail__brand">
<div class="rail__logo"></div>
<div class="rail__brand-text">
<b>Notify Bridge</b><br>
<small>v0.5.2</small>
</div>
</div>
<div class="rail__group">
<div class="rail__label">Overview</div>
<nav class="rail__nav">
<a href="dashboard-aurora.html" class="rail__link">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6"><path d="M3 12h4l3-9 4 18 3-9h4"/></svg>
Signal
<span class="count">live</span>
</a>
<a href="#" class="rail__link">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6"><rect x="3" y="3" width="7" height="7" rx="1.5"/><rect x="14" y="3" width="7" height="7" rx="1.5"/><rect x="3" y="14" width="7" height="7" rx="1.5"/><rect x="14" y="14" width="7" height="7" rx="1.5"/></svg>
Providers
<span class="count">04</span>
</a>
</nav>
</div>
<div class="rail__group">
<div class="rail__label">Routing</div>
<nav class="rail__nav">
<a href="#" class="rail__link is-active">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6"><circle cx="12" cy="12" r="3"/><circle cx="12" cy="12" r="8"/><path d="M12 4v3M12 17v3M4 12h3M17 12h3"/></svg>
Trackers <span class="count">12</span>
</a>
<a href="#" class="rail__link">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6"><path d="M4 6h16M4 12h16M4 18h10"/></svg>
Templates <span class="count">28</span>
</a>
<a href="#" class="rail__link">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6"><circle cx="12" cy="12" r="9"/><path d="M3 12h18M12 3a14 14 0 0 1 0 18M12 3a14 14 0 0 0 0 18"/></svg>
Targets <span class="count">19</span>
</a>
<a href="#" class="rail__link">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6"><path d="M5 12l3 3 6-6 6 6"/></svg>
Actions <span class="count">07</span>
</a>
</nav>
</div>
<div class="rail__group">
<div class="rail__label">Operators</div>
<nav class="rail__nav">
<a href="#" class="rail__link">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6"><rect x="4" y="4" width="16" height="16" rx="3"/><circle cx="9" cy="10" r="1.2"/><circle cx="15" cy="10" r="1.2"/><path d="M8 16c1.5 1 6.5 1 8 0"/></svg>
Bots <span class="count">06</span>
</a>
<a href="#" class="rail__link">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6"><path d="M4 18l5-5 5 5 5-9"/></svg>
Commands <span class="count">14</span>
</a>
</nav>
</div>
<div class="rail__foot">
<div class="rail__op">
<div class="rail__avatar">A</div>
<div>
<div class="rail__op-name">alexei</div>
<div class="rail__op-role">administrator</div>
</div>
<div class="rail__chip"></div>
</div>
</div>
</aside>
<!-- MAIN -->
<main class="main stagger">
<!-- TOP BAR -->
<div class="topbar">
<div class="crumbs">
<a href="dashboard-aurora.html">Signal</a>
<span class="sep">/</span>
<a href="#">Trackers</a>
<span class="sep">/</span>
<span class="here">family-photos</span>
</div>
<button class="icon-btn" title="Duplicate">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>
</button>
<button class="icon-btn" title="Notifications">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7"><path d="M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9"/><path d="M10 21a2 2 0 0 0 4 0"/></svg>
</button>
</div>
<!-- HERO -->
<section class="hero">
<div class="hero__row">
<div>
<div class="hero__chip">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><rect x="3" y="5" width="18" height="14" rx="2.5"/><circle cx="9" cy="11" r="2"/><path d="M3 17l5-5 4 4 3-3 6 6"/></svg>
<b>Immich</b> · photos.dolgolyov.dev
</div>
<h1 class="hero__title">family<em>-photos</em><span class="hero__pill-live">live</span></h1>
<p class="hero__sub">
Watches three albums (<b>«Семейный 2025»</b>, <b>«Прага 24»</b>, <b>«Лето на даче»</b>) for added or removed assets,
collection renames, and shared-link changes. Currently routing <b>1 942 events</b> across the last 24 hours
into <b>three targets</b>.
</p>
</div>
<div class="hero__actions">
<div class="toggle">
<div class="toggle__sw"></div>
<span class="toggle__label">Armed</span>
</div>
<button class="ghost-btn">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.1 2.1 0 1 1 3 3L12 15l-4 1 1-4z"/></svg>
Edit
</button>
<button class="ghost-btn danger-btn" title="Delete tracker">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M3 6h18M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/></svg>
</button>
</div>
</div>
<!-- ROUTING TRAIL -->
<div class="trail">
<div class="trail__node" style="--node-color: var(--lavender)">
<div class="trail__node-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7"><rect x="3" y="5" width="18" height="14" rx="2"/><circle cx="9" cy="11" r="2"/><path d="M3 17l5-5 4 4 3-3 6 6"/></svg>
</div>
<div class="trail__node-label">Provider</div>
<div class="trail__node-name">Immich</div>
<div class="trail__node-meta">8 trackers</div>
</div>
<div class="trail__wire"></div>
<div class="trail__node" style="--node-color: var(--orchid)">
<div class="trail__node-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7"><circle cx="12" cy="12" r="3"/><circle cx="12" cy="12" r="8"/></svg>
</div>
<div class="trail__node-label">Tracker</div>
<div class="trail__node-name"><em>family-photos</em></div>
<div class="trail__node-meta">5 events armed</div>
</div>
<div class="trail__wire"></div>
<div class="trail__node" style="--node-color: var(--mint)">
<div class="trail__node-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7"><path d="M4 6h16M4 12h16M4 18h10"/></svg>
</div>
<div class="trail__node-label">Templates</div>
<div class="trail__node-name">5 Jinja2</div>
<div class="trail__node-meta">en + ru</div>
</div>
<div class="trail__wire"></div>
<div class="trail__node" style="--node-color: var(--sky)">
<div class="trail__node-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7"><circle cx="12" cy="12" r="9"/><path d="M3 12h18"/></svg>
</div>
<div class="trail__node-label">Targets</div>
<div class="trail__node-name">3 channels</div>
<div class="trail__node-meta">tg · matrix · email</div>
</div>
</div>
</section>
<!-- GRID — config (left) + preview & events (right) -->
<section class="grid">
<!-- LEFT: tabs + form -->
<div class="panel">
<div class="tabs">
<button class="is-active">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.7 1.7 0 0 0 .3 1.8M4.3 8a1.7 1.7 0 0 0 .3 1.8"/></svg>
Configuration
</button>
<button>
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M4 6h16M4 12h16M4 18h10"/></svg>
Templates <span class="badge">5</span>
</button>
<button>
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="12" r="9"/><path d="M3 12h18"/></svg>
Targets <span class="badge">3</span>
</button>
<button>
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>
Schedule
</button>
</div>
<div class="tab-panel">
<div class="tab-panel__head">
<div>
<h2 class="tab-panel__title">Watch <em>configuration</em></h2>
<div class="tab-panel__hint">What this tracker listens for, and where to find it</div>
</div>
</div>
<div class="field">
<label class="field__label">Tracker name</label>
<input class="input" type="text" value="family-photos" />
<div class="field__sub">Used internally for routing and event logs.</div>
</div>
<div class="row-2">
<div class="field">
<label class="field__label">Provider</label>
<select class="select">
<option>Immich · photos.dolgolyov.dev</option>
<option>Gitea · git.dolgolyov-family.by</option>
<option>GitHub · anthropics/claude-code</option>
</select>
</div>
<div class="field">
<label class="field__label">Poll interval <span class="field__hint">seconds</span></label>
<input class="input" type="text" value="30" />
</div>
</div>
<div class="field">
<label class="field__label">Albums to watch <span class="field__hint">3 selected</span></label>
<div class="targets-pills">
<span class="tgt-pill" style="--pill-from: var(--lavender); --pill-to: var(--orchid)">
<span class="tgt-pill__icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="5" width="18" height="14" rx="2"/></svg>
</span>
Семейный 2025
<span class="tgt-pill__remove"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4"><path d="M6 6l12 12M6 18L18 6"/></svg></span>
</span>
<span class="tgt-pill" style="--pill-from: var(--mint); --pill-to: var(--sky)">
<span class="tgt-pill__icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="5" width="18" height="14" rx="2"/></svg>
</span>
Прага 24
<span class="tgt-pill__remove"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4"><path d="M6 6l12 12M6 18L18 6"/></svg></span>
</span>
<span class="tgt-pill" style="--pill-from: var(--citrus); --pill-to: var(--coral)">
<span class="tgt-pill__icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="5" width="18" height="14" rx="2"/></svg>
</span>
Лето на даче
<span class="tgt-pill__remove"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4"><path d="M6 6l12 12M6 18L18 6"/></svg></span>
</span>
<span class="tgt-pill tgt-pill--add">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="width:14px;height:14px"><path d="M12 5v14M5 12h14"/></svg>
Add album
</span>
</div>
</div>
<div class="field">
<label class="field__label">Event types to dispatch <span class="field__hint">choose any</span></label>
<div class="checkboxes">
<label class="check-item is-on" style="--ev-color: var(--mint)">
<span class="check-item__box"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3"><path d="M4 12l5 5 11-12"/></svg></span>
<span class="check-item__icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><rect x="3" y="5" width="18" height="14" rx="2"/><path d="M9 11h6M12 8v6"/></svg></span>
<span class="check-item__main">
<div class="check-item__name">Assets added</div>
<div class="check-item__sub">When new photos appear in album</div>
</span>
</label>
<label class="check-item is-on" style="--ev-color: var(--coral)">
<span class="check-item__box"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3"><path d="M4 12l5 5 11-12"/></svg></span>
<span class="check-item__icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><rect x="3" y="5" width="18" height="14" rx="2"/><path d="M9 12h6"/></svg></span>
<span class="check-item__main">
<div class="check-item__name">Assets removed</div>
<div class="check-item__sub">When photos disappear</div>
</span>
</label>
<label class="check-item is-on" style="--ev-color: var(--lavender)">
<span class="check-item__box"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3"><path d="M4 12l5 5 11-12"/></svg></span>
<span class="check-item__icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.1 2.1 0 1 1 3 3L12 15l-4 1 1-4z"/></svg></span>
<span class="check-item__main">
<div class="check-item__name">Album renamed</div>
<div class="check-item__sub">When the title changes</div>
</span>
</label>
<label class="check-item" style="--ev-color: var(--citrus)">
<span class="check-item__box"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3"><path d="M4 12l5 5 11-12"/></svg></span>
<span class="check-item__icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/><path d="M8.5 13.5l7 4M8.5 10.5l7-4"/></svg></span>
<span class="check-item__main">
<div class="check-item__name">Sharing changed</div>
<div class="check-item__sub">Link created, expired, removed</div>
</span>
</label>
<label class="check-item is-on" style="--ev-color: var(--sky)">
<span class="check-item__box"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3"><path d="M4 12l5 5 11-12"/></svg></span>
<span class="check-item__icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg></span>
<span class="check-item__main">
<div class="check-item__name">Memory dispatch</div>
<div class="check-item__sub">«One year ago today» weekly</div>
</span>
</label>
<label class="check-item" style="--ev-color: var(--orchid)">
<span class="check-item__box"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3"><path d="M4 12l5 5 11-12"/></svg></span>
<span class="check-item__icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M3 12c2-5 6-7 9-7s7 2 9 7c-2 5-6 7-9 7s-7-2-9-7z"/><circle cx="12" cy="12" r="3"/></svg></span>
<span class="check-item__main">
<div class="check-item__name">Favorited</div>
<div class="check-item__sub">When an asset is starred</div>
</span>
</label>
</div>
</div>
<div class="row-2">
<div class="field field--mono">
<label class="field__label">Min batch size</label>
<input class="input" type="text" value="1" />
<div class="field__sub">Hold notifications until N items collected.</div>
</div>
<div class="field field--mono">
<label class="field__label">Coalesce window</label>
<input class="input" type="text" value="120s" />
<div class="field__sub">Group events within this window into one message.</div>
</div>
</div>
</div>
<div class="savebar">
<div class="savebar__status">
<span class="dot"></span>
<span>Unsaved changes — <b style="color:var(--fg)">2 fields</b> modified</span>
</div>
<div class="savebar__actions">
<button class="ghost-btn">Discard</button>
<button class="primary-btn">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><path d="M5 13l4 4L19 7"/></svg>
Save changes
</button>
</div>
</div>
</div>
<!-- RIGHT: preview + events -->
<div class="side">
<!-- LIVE PREVIEW -->
<div class="panel">
<div class="panel__head">
<div>
<h2 class="panel__title acc-orchid">Live <em>preview</em></h2>
<div class="tab-panel__hint">Rendered with sample data — assets_added.ru</div>
</div>
<button class="icon-btn" title="Refresh">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7"><path d="M21 12a9 9 0 1 1-3-6.7"/><path d="M21 4v5h-5"/></svg>
</button>
</div>
<div class="preview">
<div class="preview__device">
<div class="preview__head">
<div class="preview__head-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 2L11 13M22 2l-7 20-4-9-9-4z"/></svg>
</div>
<div>
<div class="preview__head-name">Notify Bridge</div>
<div class="preview__head-sub">@notifybridge_bot · @family</div>
</div>
<div class="preview__head-time">02:14</div>
</div>
<div class="preview__bubble">
📸 <b>14 новых фото в «Семейный 2025»</b><br>
<span class="muted">Прага · 13 апреля · добавил <b>alexei</b></span><br>
<a href="#">Смотреть в Immich →</a>
<div class="preview__media">
<div class="preview__media-cell pmc-1"></div>
<div class="preview__media-cell pmc-2"></div>
<div class="preview__media-cell pmc-3"></div>
<div class="preview__media-cell pmc-4"></div>
<div class="preview__media-cell pmc-5"></div>
<div class="preview__media-cell pmc-6"></div>
</div>
</div>
<div class="preview__footer">
<span>Length · 184 chars · 6 attachments</span>
<a class="preview__refresh" href="#">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 12a9 9 0 1 1-3-6.7"/><path d="M21 4v5h-5"/></svg>
Re-render
</a>
</div>
</div>
</div>
</div>
<!-- RECENT EVENTS for THIS tracker -->
<div class="panel">
<div class="panel__head">
<div>
<h2 class="panel__title">Recent <em>events</em></h2>
<div class="tab-panel__hint">For this tracker only · last 24h</div>
</div>
<div class="panel__meta"><b>14</b>events</div>
</div>
<div class="events">
<div class="event" style="--ev-from: var(--mint); --ev-to: var(--sky)">
<div class="event__avatar">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9"><rect x="3" y="5" width="18" height="14" rx="2.5"/><path d="M9 11h6M12 8v6"/></svg>
</div>
<div>
<div class="event__head"><span class="v">Added</span> <b>14 assets</b></div>
<div class="event__sub">to <span class="ch">Семейный 2025</span></div>
</div>
<div class="event__when"><b>02:14</b>just now</div>
</div>
<div class="event" style="--ev-from: var(--mint); --ev-to: var(--lavender)">
<div class="event__avatar">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9"><rect x="3" y="5" width="18" height="14" rx="2.5"/><path d="M9 11h6M12 8v6"/></svg>
</div>
<div>
<div class="event__head"><span class="v">Added</span> <b>3 assets</b></div>
<div class="event__sub">to <span class="ch">Лето на даче</span></div>
</div>
<div class="event__when"><b>01:48</b>26m ago</div>
</div>
<div class="event" style="--ev-from: var(--citrus); --ev-to: var(--coral)">
<div class="event__avatar">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9"><circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/><path d="M8.5 13.5l7 4M8.5 10.5l7-4"/></svg>
</div>
<div>
<div class="event__head"><span class="v">Shared link</span> <b>expired</b></div>
<div class="event__sub">for <span class="ch">Прага 24</span></div>
</div>
<div class="event__when"><b>00:22</b>2h ago</div>
</div>
<div class="event" style="--ev-from: var(--lavender); --ev-to: var(--orchid)">
<div class="event__avatar">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.1 2.1 0 1 1 3 3L12 15l-4 1 1-4z"/></svg>
</div>
<div>
<div class="event__head"><span class="v">Renamed</span> <b>«Прага 2024» → «Прага 24»</b></div>
<div class="event__sub">at <span class="ch">photos.dolgolyov.dev</span></div>
</div>
<div class="event__when"><b>Apr 24</b>1d ago</div>
</div>
<div class="event" style="--ev-from: var(--sky); --ev-to: var(--mint)">
<div class="event__avatar">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>
</div>
<div>
<div class="event__head"><span class="v">Memory dispatched</span> <b>«Один год назад»</b></div>
<div class="event__sub">6 photos · Apr 24, 2025</div>
</div>
<div class="event__when"><b>Apr 24</b>1d ago</div>
</div>
</div>
</div>
</div>
</section>
</main>
</div>
<script>
function setTheme(t) {
document.documentElement.setAttribute('data-theme', t);
document.getElementById('t-dark').classList.toggle('is-active', t === 'dark');
document.getElementById('t-pearl').classList.toggle('is-active', t === 'pearl');
}
// Toggle the on/off switch
document.querySelectorAll('.toggle').forEach(el => {
el.addEventListener('click', () => {
el.classList.toggle('is-off');
el.querySelector('.toggle__label').textContent = el.classList.contains('is-off') ? 'Paused' : 'Armed';
});
});
// Toggle checkboxes
document.querySelectorAll('.check-item').forEach(el => {
el.addEventListener('click', e => { e.preventDefault(); el.classList.toggle('is-on'); });
});
</script>
</body>
</html>