personal memory agent
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Health dashboard: visual polish — observe grid, status summary, card consistency, terminology fixes

Flatten the observer status grid, keep the status summary prominent on mobile, align observer and dream terminology, and tighten card/status styling without changing the underlying dashboard data flow.

+65 -80
+65 -80
apps/health/workspace.html
··· 30 30 .status-summary { 31 31 background: #f9fafb; 32 32 border-radius: 10px; 33 - padding: 0.8em 1.5em; 34 - font-size: 0.95em; 33 + padding: 1em 1.5em; 34 + font-size: 1.1em; 35 + font-weight: 500; 35 36 color: #374151; 36 37 } 37 38 ··· 116 117 align-items: center; 117 118 gap: 0.3em; 118 119 background: rgba(255,255,255,0.15); 119 - padding: 0.2em 0.6em; 120 + padding: 0.15em 0.45em; 120 121 border-radius: 12px; 121 - font-size: 0.85em; 122 + font-size: 0.75em; 122 123 } 123 124 124 125 .service-dot.crashed { ··· 198 199 } 199 200 200 201 .observe-content { 201 - display: flex; 202 - gap: 2em; 202 + display: grid; 203 + grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); 204 + gap: 1em; 203 205 } 204 206 205 207 .observe-content.hidden { 206 208 display: none; 207 209 } 208 210 209 - .observe-group { 210 - flex: 1; 211 - } 212 - 213 - .observe-group-label { 214 - font-size: 0.75em; 215 - color: #9ca3af; 216 - text-transform: uppercase; 217 - letter-spacing: 0.5px; 218 - margin-bottom: 0.5em; 219 - font-weight: 500; 220 - } 221 - 222 - .observe-group-channels { 223 - display: grid; 224 - grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); 225 - gap: 1em; 226 - } 227 - 228 211 .observe-empty { 229 212 text-align: center; 230 213 color: #6b7280; 231 214 padding: 2em 1em; 232 215 font-size: 0.95em; 216 + } 217 + 218 + .observe-empty.hidden { 219 + display: none; 233 220 } 234 221 235 222 .observe-empty a { ··· 249 236 } 250 237 251 238 .observe-section-title { 252 - font-size: 0.85em; 239 + font-size: 0.75em; 253 240 color: #6b7280; 254 - text-transform: uppercase; 255 241 letter-spacing: 0.5px; 256 242 font-weight: 500; 257 243 } ··· 262 248 font-weight: 500; 263 249 } 264 250 251 + .observe-section-value.idle { 252 + color: #9ca3af; 253 + } 254 + 265 255 .observe-section-detail { 266 - font-size: 0.85em; 256 + font-size: 0.75em; 267 257 color: #6b7280; 268 258 padding-left: 1em; 259 + overflow: hidden; 260 + text-overflow: ellipsis; 261 + white-space: nowrap; 269 262 } 270 263 271 264 /* Observers Card */ ··· 284 277 } 285 278 286 279 .observer-host-card { 287 - background: linear-gradient(135deg, #f3f4f6 0%, #e5e7eb 100%); 280 + background: #f3f4f6; 288 281 border-radius: 8px; 289 282 padding: 1em; 290 283 display: flex; ··· 294 287 } 295 288 296 289 .observer-host-card.active { 297 - background: linear-gradient(135deg, #ede9fe 0%, #ddd6fe 100%); 298 - border-color: #8b5cf6; 290 + background: #f3f4f6; 291 + border-left: 4px solid #8b5cf6; 299 292 } 300 293 301 294 .observer-host-card.stale { 302 - background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%); 303 - border-color: #f59e0b; 295 + background: #fefce8; 296 + border-left: 4px solid #f59e0b; 304 297 } 305 298 306 299 .observer-host-name { ··· 707 700 border-radius: 8px; 708 701 } 709 702 710 - .observe-group-channels { 703 + .observe-content { 711 704 grid-template-columns: repeat(3, 1fr); 712 705 } 713 706 ··· 730 723 gap: 0.5em; 731 724 } 732 725 733 - .observe-group-channels { 726 + .observe-content { 734 727 grid-template-columns: repeat(2, 1fr); 735 728 } 736 729 ··· 751 744 } 752 745 753 746 .status-summary { 754 - font-size: 0.85em; 755 - padding: 0.6em 1em; 747 + font-size: 1em; 748 + padding: 0.8em 1.2em; 756 749 } 757 750 } 758 751 </style> ··· 820 813 <div class="dashboard-card observe-card"> 821 814 <div class="card-header"> 822 815 <div class="card-title"> 823 - Observation status 816 + Observers 824 817 </div> 825 818 <div class="health-badge idle" id="observeModeBadge"> 826 819 <span id="observeModeLabel">Waiting...</span> 827 820 </div> 828 821 </div> 829 822 <div class="observe-empty" id="observeEmpty"> 830 - No observers connected — <a href="/app/remote/">Manage remotes →</a> 823 + No observers connected — <a href="/app/remote/">Manage observers →</a> 831 824 </div> 832 825 <div class="observe-content hidden" id="observeContent"> 833 - <div class="observe-group"> 834 - <div class="observe-group-label">Capture</div> 835 - <div class="observe-group-channels"> 836 - <div class="observe-section"> 837 - <div class="observe-section-title">Screen Recording</div> 838 - <div class="observe-section-value" id="screencastStatus">Waiting...</div> 839 - <div class="observe-section-detail" id="screencastDetail"></div> 840 - </div> 841 - <div class="observe-section"> 842 - <div class="observe-section-title">Terminal Sessions</div> 843 - <div class="observe-section-value" id="tmuxStatus">Waiting...</div> 844 - <div class="observe-section-detail" id="tmuxDetail"></div> 845 - </div> 846 - <div class="observe-section"> 847 - <div class="observe-section-title">Audio Capture</div> 848 - <div class="observe-section-value" id="audioStatus">Waiting...</div> 849 - <div class="observe-section-detail" id="audioDetail"></div> 850 - </div> 851 - <div class="observe-section"> 852 - <div class="observe-section-title">System Activity</div> 853 - <div class="observe-section-value" id="activityStatus">Waiting...</div> 854 - <div class="observe-section-detail" id="activityDetail"></div> 855 - </div> 856 - </div> 826 + <div class="observe-section"> 827 + <div class="observe-section-title">Screen Recording</div> 828 + <div class="observe-section-value" id="screencastStatus">Waiting...</div> 829 + <div class="observe-section-detail" id="screencastDetail"></div> 857 830 </div> 858 - <div class="observe-group"> 859 - <div class="observe-group-label">Processing</div> 860 - <div class="observe-group-channels"> 861 - <div class="observe-section"> 862 - <div class="observe-section-title">Scene Analysis</div> 863 - <div class="observe-section-value" id="describeStatus">Idle</div> 864 - <div class="observe-section-detail" id="describeDetail"></div> 865 - </div> 866 - <div class="observe-section"> 867 - <div class="observe-section-title">Audio Transcription</div> 868 - <div class="observe-section-value" id="transcribeStatus">Idle</div> 869 - <div class="observe-section-detail" id="transcribeDetail"></div> 870 - </div> 871 - </div> 831 + <div class="observe-section"> 832 + <div class="observe-section-title">Terminal Sessions</div> 833 + <div class="observe-section-value" id="tmuxStatus">Waiting...</div> 834 + <div class="observe-section-detail" id="tmuxDetail"></div> 835 + </div> 836 + <div class="observe-section"> 837 + <div class="observe-section-title">Audio Capture</div> 838 + <div class="observe-section-value" id="audioStatus">Waiting...</div> 839 + <div class="observe-section-detail" id="audioDetail"></div> 840 + </div> 841 + <div class="observe-section"> 842 + <div class="observe-section-title">System Activity</div> 843 + <div class="observe-section-value" id="activityStatus">Waiting...</div> 844 + <div class="observe-section-detail" id="activityDetail"></div> 845 + </div> 846 + <div class="observe-section"> 847 + <div class="observe-section-title">Scene Analysis</div> 848 + <div class="observe-section-value" id="describeStatus">Idle</div> 849 + <div class="observe-section-detail" id="describeDetail"></div> 850 + </div> 851 + <div class="observe-section"> 852 + <div class="observe-section-title">Audio Transcription</div> 853 + <div class="observe-section-value" id="transcribeStatus">Idle</div> 854 + <div class="observe-section-detail" id="transcribeDetail"></div> 872 855 </div> 873 856 </div> 874 857 </div> ··· 877 860 <div class="dashboard-card observers-card hidden" id="observersCard"> 878 861 <div class="card-header"> 879 862 <div class="card-title"> 880 - Connected observers 863 + Connected 881 864 </div> 882 865 </div> 883 866 <div class="observers-grid" id="observersGrid"></div> ··· 916 899 <!-- Dream Card (hidden when idle) --> 917 900 <div class="dashboard-card dream-card hidden" id="dreamCard"> 918 901 <div class="card-header"> 919 - <div class="card-title">Overnight processing</div> 902 + <div class="card-title">Background analysis</div> 920 903 </div> 921 904 <div class="dream-info" id="dreamInfo"></div> 922 905 <div id="dreamProgress"></div> ··· 1050 1033 cortex: 'AI Engine', 1051 1034 sense: 'Media Processor', 1052 1035 observe: 'Screen & Audio', 1053 - dream: 'Overnight Processing', 1036 + dream: 'Background Analysis', 1054 1037 sync: 'Cloud Sync', 1055 1038 importer: 'File Importer', 1056 1039 schedule: 'Task Scheduler', ··· 1452 1435 if (!state.localHost || !primary) { 1453 1436 channels.forEach(ch => { 1454 1437 ch.statusEl.textContent = 'Waiting...'; 1438 + ch.statusEl.classList.remove('idle'); 1455 1439 ch.detailEl.textContent = ''; 1456 1440 }); 1457 1441 updateStatusSummary(); ··· 1486 1470 ch.statusEl.textContent = result.status; 1487 1471 ch.detailEl.textContent = result.detail || ''; 1488 1472 } 1473 + ch.statusEl.classList.toggle('idle', ch.statusEl.textContent === ch.idleText); 1489 1474 }); 1490 1475 1491 1476 updateStatusSummary();