5dcadd1c20
Warm, friendly redesign replacing the generic cold-shadcn look. Built as a swappable token bundle so other presets can be added later; dark mode and the user-tunable accent hue are retained. Foundation - app.css: warm cream (light) + "dusk" (dark) token system; terracotta accent (default hue 16); pastel --room-* palette; vivid --status-* (dots/bars) plus AA-legible --status-*-ink (text); soft warm shadows; --radius 1rem; font tokens - Fonts: Fraunces (display) + Figtree (body), self-hosted in static/fonts (no Google CDN) so offline/LAN installs work; system-ui fallbacks kept - h1/h2/h3 render in Fraunces via base layer Chrome and surfaces - Sidebar, Header, home, AppCard/BoardCard, BoardHeader, sections, favorites - 29 widgets + integration renderers: cozy card shells, room-palette charts - Default background is a static warm "cozy" glow (mesh demoted, rAF gated on prefers-reduced-motion) System-wide - Status colors tokenized (no raw bg/text-*-500 or status hex); success/warning to status tokens, categorical to room palette, errors to destructive - Inputs rounded-xl; buttons rounded-xl; cards/dialogs rounded-[1.4rem]; soft-shadow vocabulary only; focus-visible:ring-primary/30 - Forms, admin tables (now cozy cards), dialogs, popovers, auth screens a11y: reduced-motion guards; darker status "ink" text for AA on cream. Known tradeoff: terracotta primary + white button text ~2.96:1 (signature color, user-tunable). Verified: svelte-check 0/0, build ok, 274 tests pass, eslint 0 errors. Design refs + system sheet in design-mockups/.
724 lines
18 KiB
HTML
724 lines
18 KiB
HTML
<!doctype html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="utf-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||
<title>Web App Launcher — Cozy Home</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=Fraunces:opsz,wght@9..144,500;9..144,600;9..144,700&family=Figtree:wght@400;500;600;700&display=swap"
|
||
rel="stylesheet"
|
||
/>
|
||
<style>
|
||
:root {
|
||
--bg: #fdf8f2; /* warm cream */
|
||
--bg-2: #f6efe4;
|
||
--card: #fffdfa;
|
||
--ink: #3a322b;
|
||
--ink-2: #857a6d;
|
||
--ink-faint: #b3a899;
|
||
--line: #ece2d3;
|
||
--peach: #ff9a76;
|
||
--terra: #e8754f;
|
||
--sage: #7fb069;
|
||
--sky: #6ca9d6;
|
||
--butter: #f3c969;
|
||
--lav: #b09fd6;
|
||
--ok: #5fa86c;
|
||
--warn: #d99a2b;
|
||
--bad: #e0685f;
|
||
--radius: 22px;
|
||
}
|
||
* {
|
||
box-sizing: border-box;
|
||
margin: 0;
|
||
padding: 0;
|
||
}
|
||
html,
|
||
body {
|
||
height: 100%;
|
||
}
|
||
body {
|
||
background: var(--bg);
|
||
color: var(--ink);
|
||
font-family: 'Figtree', system-ui, sans-serif;
|
||
-webkit-font-smoothing: antialiased;
|
||
overflow-x: hidden;
|
||
}
|
||
body::before {
|
||
content: '';
|
||
position: fixed;
|
||
inset: 0;
|
||
z-index: 0;
|
||
pointer-events: none;
|
||
background:
|
||
radial-gradient(50% 40% at 12% 0%, rgba(255, 154, 118, 0.16), transparent 70%),
|
||
radial-gradient(45% 40% at 95% 8%, rgba(108, 169, 214, 0.14), transparent 70%),
|
||
radial-gradient(50% 45% at 85% 100%, rgba(127, 176, 105, 0.12), transparent 70%);
|
||
}
|
||
.shell {
|
||
position: relative;
|
||
z-index: 1;
|
||
display: grid;
|
||
grid-template-columns: 236px 1fr;
|
||
min-height: 100vh;
|
||
}
|
||
|
||
/* sidebar */
|
||
.side {
|
||
padding: 24px 18px;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
.brand {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 11px;
|
||
padding: 6px 8px;
|
||
margin-bottom: 24px;
|
||
}
|
||
.brand .m {
|
||
width: 40px;
|
||
height: 40px;
|
||
border-radius: 14px;
|
||
background: linear-gradient(135deg, var(--peach), var(--terra));
|
||
display: grid;
|
||
place-items: center;
|
||
color: #fff;
|
||
box-shadow: 0 10px 22px -8px var(--terra);
|
||
}
|
||
.brand .m svg {
|
||
width: 21px;
|
||
height: 21px;
|
||
}
|
||
.brand .t {
|
||
font-family: 'Fraunces';
|
||
font-weight: 600;
|
||
font-size: 19px;
|
||
letter-spacing: -0.01em;
|
||
}
|
||
.brand .t span {
|
||
display: block;
|
||
font-family: 'Figtree';
|
||
font-weight: 500;
|
||
font-size: 11px;
|
||
color: var(--ink-faint);
|
||
}
|
||
.nlabel {
|
||
font-weight: 700;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.1em;
|
||
font-size: 10.5px;
|
||
color: var(--ink-faint);
|
||
margin: 16px 10px 8px;
|
||
}
|
||
.ni {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12px;
|
||
padding: 11px 13px;
|
||
border-radius: 14px;
|
||
color: var(--ink-2);
|
||
font-weight: 600;
|
||
font-size: 14.5px;
|
||
cursor: pointer;
|
||
transition: 0.16s;
|
||
}
|
||
.ni svg {
|
||
width: 19px;
|
||
height: 19px;
|
||
}
|
||
.ni:hover {
|
||
background: var(--bg-2);
|
||
color: var(--ink);
|
||
}
|
||
.ni.on {
|
||
background: var(--card);
|
||
color: var(--terra);
|
||
box-shadow:
|
||
0 6px 16px -8px rgba(0, 0, 0, 0.18),
|
||
inset 0 0 0 1px var(--line);
|
||
}
|
||
.ni .c {
|
||
margin-left: auto;
|
||
font-size: 11px;
|
||
background: var(--bg-2);
|
||
color: var(--ink-2);
|
||
padding: 2px 8px;
|
||
border-radius: 10px;
|
||
}
|
||
.side-card {
|
||
margin-top: auto;
|
||
background: linear-gradient(135deg, rgba(127, 176, 105, 0.16), rgba(108, 169, 214, 0.14));
|
||
border-radius: 18px;
|
||
padding: 16px;
|
||
border: 1px solid var(--line);
|
||
}
|
||
.side-card p {
|
||
font-size: 12.5px;
|
||
color: var(--ink-2);
|
||
line-height: 1.4;
|
||
}
|
||
.side-card .who {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10px;
|
||
margin-top: 12px;
|
||
}
|
||
.side-card .av {
|
||
width: 32px;
|
||
height: 32px;
|
||
border-radius: 11px;
|
||
background: linear-gradient(135deg, var(--lav), var(--sky));
|
||
color: #fff;
|
||
display: grid;
|
||
place-items: center;
|
||
font-weight: 700;
|
||
font-size: 13px;
|
||
}
|
||
|
||
/* main */
|
||
.main {
|
||
padding: 30px 36px 40px;
|
||
min-width: 0;
|
||
}
|
||
.top {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 16px;
|
||
margin-bottom: 8px;
|
||
}
|
||
.top .search {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10px;
|
||
background: var(--card);
|
||
border: 1px solid var(--line);
|
||
border-radius: 16px;
|
||
padding: 12px 16px;
|
||
color: var(--ink-faint);
|
||
font-size: 14px;
|
||
width: 320px;
|
||
cursor: text;
|
||
box-shadow: 0 4px 14px -10px rgba(0, 0, 0, 0.2);
|
||
}
|
||
.top .search svg {
|
||
width: 16px;
|
||
height: 16px;
|
||
}
|
||
.top .search .k {
|
||
margin-left: auto;
|
||
font-size: 11px;
|
||
font-weight: 700;
|
||
background: var(--bg-2);
|
||
padding: 2px 8px;
|
||
border-radius: 8px;
|
||
}
|
||
.rbtn {
|
||
margin-left: auto;
|
||
width: 44px;
|
||
height: 44px;
|
||
border-radius: 15px;
|
||
background: var(--card);
|
||
border: 1px solid var(--line);
|
||
display: grid;
|
||
place-items: center;
|
||
color: var(--ink-2);
|
||
cursor: pointer;
|
||
box-shadow: 0 4px 14px -10px rgba(0, 0, 0, 0.2);
|
||
}
|
||
.rbtn + .rbtn {
|
||
margin-left: 0;
|
||
}
|
||
.rbtn:hover {
|
||
color: var(--terra);
|
||
}
|
||
.rbtn svg {
|
||
width: 19px;
|
||
height: 19px;
|
||
}
|
||
|
||
.greet {
|
||
font-family: 'Fraunces';
|
||
font-weight: 600;
|
||
font-size: 34px;
|
||
letter-spacing: -0.02em;
|
||
margin: 18px 0 4px;
|
||
}
|
||
.greet .wave {
|
||
display: inline-block;
|
||
animation: wave 2.4s ease-in-out infinite;
|
||
transform-origin: 70% 70%;
|
||
}
|
||
@keyframes wave {
|
||
0%,
|
||
60%,
|
||
100% {
|
||
transform: rotate(0);
|
||
}
|
||
10% {
|
||
transform: rotate(16deg);
|
||
}
|
||
20% {
|
||
transform: rotate(-8deg);
|
||
}
|
||
30% {
|
||
transform: rotate(14deg);
|
||
}
|
||
40% {
|
||
transform: rotate(-4deg);
|
||
}
|
||
}
|
||
.gsub {
|
||
color: var(--ink-2);
|
||
font-size: 15px;
|
||
margin-bottom: 26px;
|
||
}
|
||
.gsub b {
|
||
color: var(--sage);
|
||
font-weight: 700;
|
||
}
|
||
|
||
/* summary chips */
|
||
.chips {
|
||
display: flex;
|
||
gap: 12px;
|
||
margin-bottom: 30px;
|
||
flex-wrap: wrap;
|
||
}
|
||
.chip {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12px;
|
||
background: var(--card);
|
||
border: 1px solid var(--line);
|
||
border-radius: 18px;
|
||
padding: 14px 18px;
|
||
box-shadow: 0 8px 20px -16px rgba(0, 0, 0, 0.3);
|
||
}
|
||
.chip .ic {
|
||
width: 38px;
|
||
height: 38px;
|
||
border-radius: 12px;
|
||
display: grid;
|
||
place-items: center;
|
||
}
|
||
.chip .ic svg {
|
||
width: 19px;
|
||
height: 19px;
|
||
color: #fff;
|
||
}
|
||
.chip .v {
|
||
font-family: 'Fraunces';
|
||
font-weight: 600;
|
||
font-size: 21px;
|
||
line-height: 1;
|
||
}
|
||
.chip .l {
|
||
font-size: 12.5px;
|
||
color: var(--ink-2);
|
||
margin-top: 2px;
|
||
}
|
||
|
||
.sec {
|
||
display: flex;
|
||
align-items: baseline;
|
||
gap: 12px;
|
||
margin: 6px 0 18px;
|
||
}
|
||
.sec h2 {
|
||
font-family: 'Fraunces';
|
||
font-weight: 600;
|
||
font-size: 22px;
|
||
letter-spacing: -0.01em;
|
||
}
|
||
.sec .more {
|
||
margin-left: auto;
|
||
font-size: 13.5px;
|
||
color: var(--terra);
|
||
font-weight: 600;
|
||
text-decoration: none;
|
||
}
|
||
|
||
.apps {
|
||
display: grid;
|
||
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
|
||
gap: 18px;
|
||
}
|
||
.card {
|
||
background: var(--card);
|
||
border: 1px solid var(--line);
|
||
border-radius: var(--radius);
|
||
padding: 20px;
|
||
cursor: pointer;
|
||
transition:
|
||
transform 0.2s cubic-bezier(0.2, 0.8, 0.2, 1),
|
||
box-shadow 0.2s;
|
||
position: relative;
|
||
overflow: hidden;
|
||
box-shadow: 0 10px 26px -20px rgba(0, 0, 0, 0.4);
|
||
}
|
||
.card:hover {
|
||
transform: translateY(-6px) rotate(-0.4deg);
|
||
box-shadow: 0 22px 40px -22px rgba(0, 0, 0, 0.4);
|
||
}
|
||
.blob {
|
||
position: absolute;
|
||
width: 120px;
|
||
height: 120px;
|
||
border-radius: 50%;
|
||
filter: blur(30px);
|
||
opacity: 0.5;
|
||
top: -50px;
|
||
right: -40px;
|
||
}
|
||
.ico {
|
||
width: 54px;
|
||
height: 54px;
|
||
border-radius: 18px;
|
||
display: grid;
|
||
place-items: center;
|
||
font-size: 26px;
|
||
position: relative;
|
||
}
|
||
.nm {
|
||
font-family: 'Fraunces';
|
||
font-weight: 600;
|
||
font-size: 17px;
|
||
margin-top: 16px;
|
||
letter-spacing: -0.01em;
|
||
}
|
||
.ct {
|
||
font-size: 13px;
|
||
color: var(--ink-2);
|
||
margin-top: 1px;
|
||
}
|
||
.foot {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
margin-top: 18px;
|
||
}
|
||
.dot {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 7px;
|
||
font-size: 12.5px;
|
||
font-weight: 600;
|
||
}
|
||
.dot .b {
|
||
width: 9px;
|
||
height: 9px;
|
||
border-radius: 50%;
|
||
}
|
||
.dot.ok {
|
||
color: var(--ok);
|
||
}
|
||
.dot.ok .b {
|
||
background: var(--ok);
|
||
box-shadow: 0 0 0 4px rgba(95, 168, 108, 0.18);
|
||
}
|
||
.dot.warn {
|
||
color: var(--warn);
|
||
}
|
||
.dot.warn .b {
|
||
background: var(--warn);
|
||
box-shadow: 0 0 0 4px rgba(217, 154, 43, 0.18);
|
||
}
|
||
.dot.bad {
|
||
color: var(--bad);
|
||
}
|
||
.dot.bad .b {
|
||
background: var(--bad);
|
||
box-shadow: 0 0 0 4px rgba(224, 104, 95, 0.18);
|
||
}
|
||
.up {
|
||
font-size: 12px;
|
||
color: var(--ink-faint);
|
||
font-weight: 600;
|
||
}
|
||
|
||
@keyframes rise {
|
||
from {
|
||
opacity: 0;
|
||
transform: translateY(16px);
|
||
}
|
||
to {
|
||
opacity: 1;
|
||
transform: none;
|
||
}
|
||
}
|
||
.card,
|
||
.chip {
|
||
animation: rise 0.55s both;
|
||
}
|
||
.chip:nth-child(2) {
|
||
animation-delay: 0.06s;
|
||
}
|
||
.chip:nth-child(3) {
|
||
animation-delay: 0.12s;
|
||
}
|
||
.chip:nth-child(4) {
|
||
animation-delay: 0.18s;
|
||
}
|
||
.apps .card:nth-child(1) {
|
||
animation-delay: 0.1s;
|
||
}
|
||
.apps .card:nth-child(2) {
|
||
animation-delay: 0.16s;
|
||
}
|
||
.apps .card:nth-child(3) {
|
||
animation-delay: 0.22s;
|
||
}
|
||
.apps .card:nth-child(4) {
|
||
animation-delay: 0.28s;
|
||
}
|
||
.apps .card:nth-child(5) {
|
||
animation-delay: 0.34s;
|
||
}
|
||
.apps .card:nth-child(6) {
|
||
animation-delay: 0.4s;
|
||
}
|
||
.apps .card:nth-child(7) {
|
||
animation-delay: 0.46s;
|
||
}
|
||
.apps .card:nth-child(8) {
|
||
animation-delay: 0.52s;
|
||
}
|
||
|
||
.note {
|
||
text-align: center;
|
||
color: var(--ink-faint);
|
||
font-family: 'Fraunces';
|
||
font-style: italic;
|
||
font-size: 14px;
|
||
margin-top: 36px;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="shell">
|
||
<!-- Sidebar -->
|
||
<aside class="side">
|
||
<div class="brand">
|
||
<div class="m">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<rect x="3" y="3" width="7" height="7" rx="2" />
|
||
<rect x="14" y="3" width="7" height="7" rx="2" />
|
||
<rect x="14" y="14" width="7" height="7" rx="2" />
|
||
<rect x="3" y="14" width="7" height="7" rx="2" />
|
||
</svg>
|
||
</div>
|
||
<div class="t">Launcher<span>our home cloud</span></div>
|
||
</div>
|
||
<div class="nlabel">Menu</div>
|
||
<div class="ni on">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9">
|
||
<path d="M3 11l9-8 9 8M5 10v10h14V10" />
|
||
</svg>
|
||
Home
|
||
</div>
|
||
<div class="ni">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9">
|
||
<circle cx="12" cy="12" r="9" />
|
||
<path d="M3 12h18M12 3a14 14 0 0 1 0 18 14 14 0 0 1 0-18" />
|
||
</svg>
|
||
All apps <span class="c">10</span>
|
||
</div>
|
||
<div class="ni">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9">
|
||
<path d="M20 6 9 17l-5-5" />
|
||
</svg>
|
||
Status
|
||
</div>
|
||
<div class="nlabel">Rooms</div>
|
||
<div class="ni">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9">
|
||
<rect x="3" y="3" width="18" height="18" rx="4" />
|
||
</svg>
|
||
Movie night
|
||
</div>
|
||
<div class="ni">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9">
|
||
<rect x="3" y="3" width="18" height="18" rx="4" />
|
||
</svg>
|
||
The basement rack
|
||
</div>
|
||
<div class="side-card">
|
||
<p>“Everything’s running smoothly today. ☕ Two apps want a peek when you get a sec.”</p>
|
||
<div class="who">
|
||
<div class="av">AD</div>
|
||
<div>
|
||
<div style="font-weight: 700; font-size: 13px">Alexei</div>
|
||
<div style="font-size: 11px; color: var(--ink-faint)">Admin</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</aside>
|
||
|
||
<!-- Main -->
|
||
<main class="main">
|
||
<div class="top">
|
||
<div class="search">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<circle cx="11" cy="11" r="7" />
|
||
<line x1="21" y1="21" x2="16.65" y2="16.65" />
|
||
</svg>
|
||
Search your apps… <span class="k">⌘K</span>
|
||
</div>
|
||
<div class="rbtn">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9">
|
||
<path d="M18 8a6 6 0 1 0-12 0c0 7-3 9-3 9h18s-3-2-3-9" />
|
||
<path d="M13.7 21a2 2 0 0 1-3.4 0" />
|
||
</svg>
|
||
</div>
|
||
<div class="rbtn">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9">
|
||
<circle cx="12" cy="12" r="4" />
|
||
<path
|
||
d="M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4"
|
||
/>
|
||
</svg>
|
||
</div>
|
||
</div>
|
||
|
||
<h1 class="greet">Hi Alexei <span class="wave">👋</span></h1>
|
||
<p class="gsub">It’s a calm evening — <b>8 of your 10 apps</b> are happy and online.</p>
|
||
|
||
<div class="chips">
|
||
<div class="chip">
|
||
<div class="ic" style="background: var(--sage)">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2">
|
||
<path d="M20 6 9 17l-5-5" />
|
||
</svg>
|
||
</div>
|
||
<div>
|
||
<div class="v">8/10</div>
|
||
<div class="l">Apps online</div>
|
||
</div>
|
||
</div>
|
||
<div class="chip">
|
||
<div class="ic" style="background: var(--sky)">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2">
|
||
<circle cx="12" cy="12" r="9" />
|
||
<path d="M12 7v5l3 2" />
|
||
</svg>
|
||
</div>
|
||
<div>
|
||
<div class="v">142ms</div>
|
||
<div class="l">Avg speed</div>
|
||
</div>
|
||
</div>
|
||
<div class="chip">
|
||
<div class="ic" style="background: var(--butter)">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2">
|
||
<path d="M3 12h4l3 8 4-16 3 8h4" />
|
||
</svg>
|
||
</div>
|
||
<div>
|
||
<div class="v">99.4%</div>
|
||
<div class="l">Uptime · 30d</div>
|
||
</div>
|
||
</div>
|
||
<div class="chip">
|
||
<div class="ic" style="background: var(--lav)">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2">
|
||
<path d="M13 2 3 14h7l-1 8 10-12h-7z" />
|
||
</svg>
|
||
</div>
|
||
<div>
|
||
<div class="v">38 min</div>
|
||
<div class="l">Battery left</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="sec">
|
||
<h2>Your favorites</h2>
|
||
<a class="more" href="#">See all →</a>
|
||
</div>
|
||
<div class="apps">
|
||
<div class="card">
|
||
<div class="blob" style="background: var(--terra)"></div>
|
||
<div class="ico" style="background: rgba(232, 117, 79, 0.16)">🎬</div>
|
||
<div class="nm">Jellyfin</div>
|
||
<div class="ct">Movies & shows</div>
|
||
<div class="foot">
|
||
<span class="dot ok"><span class="b"></span>Online</span><span class="up">99.9%</span>
|
||
</div>
|
||
</div>
|
||
<div class="card">
|
||
<div class="blob" style="background: var(--sky)"></div>
|
||
<div class="ico" style="background: rgba(108, 169, 214, 0.18)">📷</div>
|
||
<div class="nm">Immich</div>
|
||
<div class="ct">Photos</div>
|
||
<div class="foot">
|
||
<span class="dot ok"><span class="b"></span>Online</span><span class="up">100%</span>
|
||
</div>
|
||
</div>
|
||
<div class="card">
|
||
<div class="blob" style="background: var(--sage)"></div>
|
||
<div class="ico" style="background: rgba(127, 176, 105, 0.18)">🌿</div>
|
||
<div class="nm">Gitea</div>
|
||
<div class="ct">Code</div>
|
||
<div class="foot">
|
||
<span class="dot ok"><span class="b"></span>Online</span><span class="up">99.8%</span>
|
||
</div>
|
||
</div>
|
||
<div class="card">
|
||
<div class="blob" style="background: var(--butter)"></div>
|
||
<div class="ico" style="background: rgba(243, 201, 105, 0.22)">🐳</div>
|
||
<div class="nm">Portainer</div>
|
||
<div class="ct">Containers</div>
|
||
<div class="foot">
|
||
<span class="dot warn"><span class="b"></span>A bit slow</span
|
||
><span class="up">98.1%</span>
|
||
</div>
|
||
</div>
|
||
<div class="card">
|
||
<div class="blob" style="background: var(--lav)"></div>
|
||
<div class="ico" style="background: rgba(176, 159, 214, 0.2)">🛡️</div>
|
||
<div class="nm">Pi-hole</div>
|
||
<div class="ct">Ad blocker</div>
|
||
<div class="foot">
|
||
<span class="dot ok"><span class="b"></span>Online</span><span class="up">100%</span>
|
||
</div>
|
||
</div>
|
||
<div class="card">
|
||
<div class="blob" style="background: var(--peach)"></div>
|
||
<div class="ico" style="background: rgba(255, 154, 118, 0.2)">📋</div>
|
||
<div class="nm">Planka</div>
|
||
<div class="ct">To-dos</div>
|
||
<div class="foot">
|
||
<span class="dot ok"><span class="b"></span>Online</span><span class="up">99.5%</span>
|
||
</div>
|
||
</div>
|
||
<div class="card">
|
||
<div class="blob" style="background: var(--bad)"></div>
|
||
<div class="ico" style="background: rgba(224, 104, 95, 0.16)">⬇️</div>
|
||
<div class="nm">Deluge</div>
|
||
<div class="ct">Downloads</div>
|
||
<div class="foot">
|
||
<span class="dot bad"><span class="b"></span>Asleep</span><span class="up">—</span>
|
||
</div>
|
||
</div>
|
||
<div class="card">
|
||
<div class="blob" style="background: var(--sky)"></div>
|
||
<div class="ico" style="background: rgba(108, 169, 214, 0.18)">🔀</div>
|
||
<div class="nm">Proxy</div>
|
||
<div class="ct">Networking</div>
|
||
<div class="foot">
|
||
<span class="dot ok"><span class="b"></span>Online</span><span class="up">99.9%</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<p class="note">
|
||
Cozy Home — Fraunces + Figtree · warm cream · soft pastel rooms · gentle motion
|
||
</p>
|
||
</main>
|
||
</div>
|
||
</body>
|
||
</html>
|