Add batched status endpoint and optimize frontend performance
Server-side batched /api/v1/services/status endpoint replaces N individual browser probes with a single API call (HEAD-first with GET fallback, concurrency-limited, CA-aware HTTPS agent). Frontend: clock reuses DOM instead of rebuilding innerHTML every second with drift-correcting timer that pauses on hidden tabs. Card animations use CSS transitionDelay + requestAnimationFrame. Internet dot blink moved from JS intervals to CSS keyframes with prefers-reduced-motion support. Service worker rewritten with network-first navigation, stale-while-revalidate assets, and navigation preload. Font faces drop TTF fallbacks, use font-display swap. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,75 +1,67 @@
|
||||
/* Sami Grotesk Custom Font Family */
|
||||
@font-face {
|
||||
font-family: 'Sami Grotesk';
|
||||
src: url('/assets/fonts/sami-grotesk/SamiGrotesk-Light.woff2') format('woff2'),
|
||||
url('/assets/fonts/sami-grotesk/SamiGrotesk-Light.ttf') format('truetype');
|
||||
src: url('/assets/fonts/sami-grotesk/SamiGrotesk-Light.woff2') format('woff2');
|
||||
font-weight: 300;
|
||||
font-style: normal;
|
||||
font-display: block;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Sami Grotesk';
|
||||
src: url('/assets/fonts/sami-grotesk/SamiGrotesk-Regular.woff2') format('woff2'),
|
||||
url('/assets/fonts/sami-grotesk/SamiGrotesk-Regular.ttf') format('truetype');
|
||||
src: url('/assets/fonts/sami-grotesk/SamiGrotesk-Regular.woff2') format('woff2');
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
font-display: block;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Sami Grotesk';
|
||||
src: url('/assets/fonts/sami-grotesk/SamiGrotesk-Medium.woff2') format('woff2'),
|
||||
url('/assets/fonts/sami-grotesk/SamiGrotesk-Medium.ttf') format('truetype');
|
||||
src: url('/assets/fonts/sami-grotesk/SamiGrotesk-Medium.woff2') format('woff2');
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
font-display: block;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Sami Grotesk';
|
||||
src: url('/assets/fonts/sami-grotesk/SamiGrotesk-Bold.woff2') format('woff2'),
|
||||
url('/assets/fonts/sami-grotesk/SamiGrotesk-Bold.ttf') format('truetype');
|
||||
src: url('/assets/fonts/sami-grotesk/SamiGrotesk-Bold.woff2') format('woff2');
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
font-display: block;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Sami Grotesk';
|
||||
src: url('/assets/fonts/sami-grotesk/SamiGrotesk-Black.woff2') format('woff2'),
|
||||
url('/assets/fonts/sami-grotesk/SamiGrotesk-Black.ttf') format('truetype');
|
||||
src: url('/assets/fonts/sami-grotesk/SamiGrotesk-Black.woff2') format('woff2');
|
||||
font-weight: 900;
|
||||
font-style: normal;
|
||||
font-display: block;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
/* Italic variants */
|
||||
@font-face {
|
||||
font-family: 'Sami Grotesk';
|
||||
src: url('/assets/fonts/sami-grotesk/SamiGrotesk-RegularItalic.woff2') format('woff2'),
|
||||
url('/assets/fonts/sami-grotesk/SamiGrotesk-RegularItalic.ttf') format('truetype');
|
||||
src: url('/assets/fonts/sami-grotesk/SamiGrotesk-RegularItalic.woff2') format('woff2');
|
||||
font-weight: 400;
|
||||
font-style: italic;
|
||||
font-display: block;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Sami Grotesk';
|
||||
src: url('/assets/fonts/sami-grotesk/SamiGrotesk-MediumItalic.woff2') format('woff2'),
|
||||
url('/assets/fonts/sami-grotesk/SamiGrotesk-MediumItalic.ttf') format('truetype');
|
||||
src: url('/assets/fonts/sami-grotesk/SamiGrotesk-MediumItalic.woff2') format('woff2');
|
||||
font-weight: 500;
|
||||
font-style: italic;
|
||||
font-display: block;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Sami Grotesk';
|
||||
src: url('/assets/fonts/sami-grotesk/SamiGrotesk-BoldItalic.woff2') format('woff2'),
|
||||
url('/assets/fonts/sami-grotesk/SamiGrotesk-BoldItalic.ttf') format('truetype');
|
||||
src: url('/assets/fonts/sami-grotesk/SamiGrotesk-BoldItalic.woff2') format('woff2');
|
||||
font-weight: 700;
|
||||
font-style: italic;
|
||||
font-display: block;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
/* Theme variables and transitions are in themes.css */
|
||||
@@ -2018,15 +2010,37 @@ button:focus-visible {
|
||||
|
||||
/* Internet card packet blink */
|
||||
.card[data-app="internet"] .dot {
|
||||
transition: all 0.1s ease;
|
||||
transition: background-color 0.18s ease, box-shadow 0.18s ease, transform 0.18s ease;
|
||||
}
|
||||
.card[data-app="internet"] .dot.packet-rx {
|
||||
box-shadow: 0 0 8px 2px #4caf50;
|
||||
background: #4caf50;
|
||||
|
||||
.card[data-app="internet"][data-status="on"] .dot {
|
||||
animation: internet-traffic 1.35s ease-in-out infinite;
|
||||
}
|
||||
.card[data-app="internet"] .dot.packet-tx {
|
||||
box-shadow: 0 0 8px 2px #2196f3;
|
||||
background: #2196f3;
|
||||
|
||||
@keyframes internet-traffic {
|
||||
0%, 100% {
|
||||
transform: scale(1);
|
||||
background: var(--dot-ok);
|
||||
box-shadow: 0 0 0 rgba(39, 174, 96, 0);
|
||||
}
|
||||
|
||||
38% {
|
||||
transform: scale(1.06);
|
||||
background: #4caf50;
|
||||
box-shadow: 0 0 10px 2px rgba(76, 175, 80, 0.55);
|
||||
}
|
||||
|
||||
68% {
|
||||
transform: scale(0.98);
|
||||
background: #2196f3;
|
||||
box-shadow: 0 0 10px 2px rgba(33, 150, 243, 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.card[data-app="internet"][data-status="on"] .dot {
|
||||
animation: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Restart button styling */
|
||||
|
||||
Reference in New Issue
Block a user