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 @@ + +
+
+
πŸ“‹
+

Install Commands

+
+ +
@@ -233,6 +274,20 @@

+ +
+
+
πŸ’Ύ
+

Backup Downloads

+
+ +
+
@@ -240,7 +295,7 @@

Home Automation

@@ -427,8 +485,8 @@ Inframyronblair/infraβ†— - - MediaStackmyronblair/mediastackβ†— + + StreamHoardmyronblair/kino-appβ†— DO Server Configmyronblair/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 = ''; + } + } + loadBackupDownloads(); + // ── Notes β€” server-backed so they sync across all devices ───────────── const API = '/notes.php';