diff --git a/index.html b/index.html
index 9d2ef2d..cdbb142 100644
--- a/index.html
+++ b/index.html
@@ -54,11 +54,9 @@
}
.grid {
- display: grid;
- grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
- gap: 1.25rem;
- max-width: 1400px;
- margin: 0 auto;
+ columns: 320px;
+ column-gap: 1.25rem;
+ width: 100%;
}
.card {
@@ -67,6 +65,8 @@
border-radius: var(--radius);
overflow: hidden;
transition: border-color 0.2s, transform 0.2s;
+ break-inside: avoid;
+ margin-bottom: 1.25rem;
}
.card:hover { border-color: var(--accent); transform: translateY(-2px); }
@@ -89,11 +89,11 @@
flex-shrink: 0;
}
.card-header h2 {
- font-size: 0.8rem;
- font-weight: 600;
+ font-size: 1rem;
+ font-weight: 700;
text-transform: uppercase;
letter-spacing: 1px;
- color: var(--muted);
+ color: var(--text);
}
.links { padding: 0.5rem 0; }
@@ -115,7 +115,7 @@
border-radius: 50%;
flex-shrink: 0;
}
- .link-item .name { flex: 1; font-weight: 500; }
+ .link-item .name { flex: 1; font-weight: 500; font-size: 0.85rem; }
.link-item .sub {
font-size: 0.75rem;
color: var(--muted);
@@ -128,6 +128,32 @@
}
.link-item:hover .arrow { opacity: 1; }
+ .copy-item {
+ display: flex;
+ align-items: center;
+ gap: 0.75rem;
+ padding: 0.6rem 1rem;
+ color: var(--text);
+ font-size: 0.9rem;
+ transition: background 0.15s;
+ cursor: pointer;
+ border: none;
+ background: none;
+ width: 100%;
+ text-align: left;
+ font-family: inherit;
+ }
+ .copy-item:hover { background: var(--surface2); }
+ .copy-item .name { font-size: 0.85rem; }
+ .copy-item .copy-icon {
+ color: var(--muted);
+ font-size: 0.7rem;
+ opacity: 0;
+ transition: opacity 0.15s;
+ flex-shrink: 0;
+ }
+ .copy-item:hover .copy-icon { opacity: 1; }
+
.dot-blue { background: var(--accent); }
.dot-purple { background: var(--accent2); }
.dot-green { background: var(--green); }
@@ -155,7 +181,7 @@
@media (max-width: 600px) {
body { padding: 1rem; }
- .grid { grid-template-columns: 1fr; }
+ .grid { columns: 1; }
}
@@ -220,6 +246,21 @@
+
+
+
+
+
+ JARVIS Agent Linux install one-liner — prompts for registration key, run as root copy
+
+
+ FusionPBX Full Installer Official latest-version install script — Debian 12, run as root copy
+
+
+
+
+
+
@@ -427,8 +485,8 @@
Infra myronblair/infra β
-
- MediaStack myronblair/mediastack β
+
+ StreamHoard myronblair/kino-app β
DO Server Config myronblair/do-server-config β
@@ -688,6 +746,18 @@
}
tick(); setInterval(tick, 1000);
+ // ββ Install Commands card: copy-to-clipboard, never auto-navigates ββ
+ function copyCmd(btn, text) {
+ navigator.clipboard.writeText(text).then(() => {
+ const iconEl = btn.querySelector('.copy-icon');
+ const prev = iconEl.textContent;
+ iconEl.textContent = 'copied!';
+ iconEl.style.opacity = '1';
+ setTimeout(() => { iconEl.textContent = prev; iconEl.style.opacity = ''; }, 1500);
+ });
+ }
+
+
// ββ Backup Status card β reads daily-refreshed JSON from MSP360 collector ββ
async function loadBackupStatus() {
const el = document.getElementById('backup-status-list');
@@ -726,6 +796,31 @@
}
loadBackupStatus();
+ // ββ Backup Downloads card β added 2026-07-07 βββββββββββββββββββββββββββ
+ async function loadBackupDownloads() {
+ const el = document.getElementById('backup-downloads-list');
+ try {
+ const r = await fetch('/downloads/backup-files-status.json', { cache: 'no-store' });
+ const data = await r.json();
+ const fmt = (iso) => {
+ if (!iso) return 'No backup found';
+ const d = new Date(iso);
+ return d.toLocaleString('en-US', {month:'short', day:'numeric', hour:'2-digit', minute:'2-digit'});
+ };
+ const row = (label, entry) => `
+
+
+ ${label}
+ ${entry.source} β ${fmt(entry.timestamp)}${entry.size ? ' Β· ' + entry.size : ''}
+ β
+ `;
+ el.innerHTML = row('JARVIS Backup', data.jarvis) + row('DO Server Backup', data.do_server);
+ } catch (e) {
+ el.innerHTML = 'Status unavailable
';
+ }
+ }
+ loadBackupDownloads();
+
// ββ Notes β server-backed so they sync across all devices βββββββββββββ
const API = '/notes.php';