diff --git a/dashboard/siro-admin/css/main.css b/dashboard/siro-admin/css/main.css index 6d156e3a..c2bbe303 100644 --- a/dashboard/siro-admin/css/main.css +++ b/dashboard/siro-admin/css/main.css @@ -1508,3 +1508,86 @@ textarea.form-input { text-align: start; } direction: ltr; text-align: start; } + +/* Build identifier, always visible in the sidebar footer */ +.build-stamp { + padding: 0.45rem 1.25rem 0.75rem; + font-size: 0.68rem; + letter-spacing: 0.04em; + color: var(--text-subtle); + font-family: ui-monospace, SFMono-Regular, Menlo, monospace; + direction: ltr; + text-align: center; + border-top: 1px solid var(--border-color); +} + +/* Long values in generated tables */ +.cell-long { + cursor: pointer; + border-bottom: 1px dotted var(--text-subtle); +} + +.cell-long:hover { color: var(--primary); } + +.cell-full { + display: block; + max-width: 460px; + white-space: pre-wrap; + word-break: break-word; + font-family: ui-monospace, SFMono-Regular, Menlo, monospace; + font-size: 0.74rem; + color: var(--text-muted); +} + +.data-table td { max-width: 420px; } + +/* ========================================================================== + Motion — used sparingly, and only where it carries meaning: + arrival of content, and the moment data is being fetched. + ========================================================================== */ +@keyframes riseIn { + from { opacity: 0; transform: translateY(10px); } + to { opacity: 1; transform: translateY(0); } +} + +.page-view.active .stat-card, +.page-view.active > .card, +.module-panels > .card { + animation: riseIn 0.34s cubic-bezier(0.22, 1, 0.36, 1) backwards; +} + +/* Stagger so a grid resolves left-to-right instead of snapping in at once */ +.page-view.active .stats-grid .stat-card:nth-child(1) { animation-delay: 0.00s; } +.page-view.active .stats-grid .stat-card:nth-child(2) { animation-delay: 0.05s; } +.page-view.active .stats-grid .stat-card:nth-child(3) { animation-delay: 0.10s; } +.page-view.active .stats-grid .stat-card:nth-child(4) { animation-delay: 0.15s; } +.module-panels > .card:nth-child(2) { animation-delay: 0.06s; } +.module-panels > .card:nth-child(3) { animation-delay: 0.12s; } + +.stat-card, .card { transition: transform 0.25s ease, border-color 0.25s ease; } +.stat-card:hover { transform: translateY(-3px); } + +/* Rows settle in rather than appearing fully formed */ +.data-table tbody tr { animation: riseIn 0.25s ease backwards; } +.data-table tbody tr:nth-child(1) { animation-delay: 0.02s; } +.data-table tbody tr:nth-child(2) { animation-delay: 0.04s; } +.data-table tbody tr:nth-child(3) { animation-delay: 0.06s; } +.data-table tbody tr:nth-child(4) { animation-delay: 0.08s; } +.data-table tbody tr:nth-child(n+5) { animation-delay: 0.10s; } + +/* The refresh control spins while a request is in flight, so a section that + returns nothing still visibly did something. */ +@keyframes spin { to { transform: rotate(360deg); } } +.btn-icon.is-busy i { animation: spin 0.8s linear infinite; } + +.live-indicator[data-state="loading"] { animation: pulseSoft 1.4s ease-in-out infinite; } +@keyframes pulseSoft { 50% { opacity: 0.55; } } + +/* Respect users who ask the system for less motion */ +@media (prefers-reduced-motion: reduce) { + *, *::before, *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + } +} diff --git a/dashboard/siro-admin/index.html b/dashboard/siro-admin/index.html index 44b9b248..690f9644 100644 --- a/dashboard/siro-admin/index.html +++ b/dashboard/siro-admin/index.html @@ -134,6 +134,10 @@ + +