diff --git a/assets/css/app.css b/assets/css/app.css
index ed79229..30d4617 100644
--- a/assets/css/app.css
+++ b/assets/css/app.css
@@ -943,6 +943,12 @@ body.page-dashboard .content {
background: linear-gradient(135deg, rgba(54, 147, 173, 0.92), rgba(38, 106, 135, 0.92));
}
+.sleep-phase-bar__segment--rest {
+ min-width: 0;
+ padding: 0;
+ background: rgba(255, 255, 255, 0.1);
+}
+
.media-lightbox[hidden] {
display: none;
}
@@ -990,13 +996,24 @@ body.page-dashboard .content {
.media-lightbox__content .timeline-route-map {
width: 100%;
max-width: none;
- height: min(72vh, 42rem);
border-radius: 1.4rem;
object-fit: contain;
}
+.media-lightbox__content img {
+ height: auto;
+ max-height: 82vh;
+}
+
+.media-lightbox__content .timeline-route-map {
+ aspect-ratio: 16 / 9;
+ height: auto;
+ max-height: 76vh;
+}
+
.media-lightbox__content .timeline-route-map {
cursor: default;
+ pointer-events: none;
}
.timeline-card__meta strong {
@@ -2168,8 +2185,9 @@ body.page-dashboard .content {
}
.dashboard-shell__background {
- inset: 0;
+ inset: calc(-1 * env(safe-area-inset-top)) 0 calc(-1 * env(safe-area-inset-bottom)) 0;
width: 100%;
+ height: calc(100dvh + env(safe-area-inset-top) + env(safe-area-inset-bottom));
transform: none;
}
@@ -2235,10 +2253,22 @@ body.page-dashboard .content {
.timeline-card__image {
width: 100%;
max-width: none;
- margin: -2.65rem 0 0.7rem;
+ margin: 0;
border-radius: 1.25rem;
}
+ .timeline-media-button {
+ min-height: 0;
+ height: auto;
+ max-height: none;
+ margin: 0 0 0.7rem;
+ }
+
+ .timeline-media-button .timeline-card__image {
+ height: auto;
+ max-height: 24rem;
+ }
+
.timeline-card__time-chip {
position: absolute;
top: 0.75rem;
@@ -2298,8 +2328,8 @@ body.page-dashboard .content {
}
.timeline-card--with-image .signal-row {
- top: 2.05rem;
- left: 2.05rem;
+ top: 0.75rem;
+ left: 0.75rem;
}
.timeline-card .signal-pill {
diff --git a/assets/js/app.js b/assets/js/app.js
index 82760f6..bcbd9d8 100644
--- a/assets/js/app.js
+++ b/assets/js/app.js
@@ -1693,7 +1693,7 @@
const clone = trigger.cloneNode(true);
clone.removeAttribute("data-lightbox-kind");
clone.removeAttribute("aria-label");
- clone.disabled = true;
+ clone.classList.add("is-lightbox-clone");
content.appendChild(clone);
}
diff --git a/src/App.php b/src/App.php
index 9140505..28e7e26 100644
--- a/src/App.php
+++ b/src/App.php
@@ -2050,7 +2050,7 @@ final class App
$mime = mime_content_type($path) ?: 'application/octet-stream';
header('Content-Type: ' . $mime);
header('Content-Length: ' . (string) filesize($path));
- header('Cache-Control: private, max-age=3600');
+ header('Cache-Control: private, max-age=604800');
readfile($path);
exit;
}
@@ -2081,7 +2081,7 @@ final class App
$mime = mime_content_type($path) ?: 'application/octet-stream';
header('Content-Type: ' . $mime);
header('Content-Length: ' . (string) filesize($path));
- header('Cache-Control: private, max-age=3600');
+ header('Cache-Control: private, max-age=604800');
readfile($path);
exit;
}
diff --git a/templates/pages/dashboard.php b/templates/pages/dashboard.php
index 2ddcb81..b45e5f3 100644
--- a/templates/pages/dashboard.php
+++ b/templates/pages/dashboard.php
@@ -115,6 +115,7 @@ $optimalSleepHours = max(1.0, min(16.0, (float) ($settings['sleep']['optimal_hou
}
$sleepPhaseTotal = max(0.0, array_sum($sleepPhases));
$sleepBarTotal = $eventType === 'sleep' ? max((float) ($item['value'] ?? 0), $sleepPhaseTotal, $optimalSleepHours) : 0.0;
+ $sleepPhaseRemainder = max(0.0, $sleepBarTotal - $sleepPhaseTotal);
$sleepOptimalPercent = $sleepBarTotal > 0 ? max(0, min(100, ($optimalSleepHours / $sleepBarTotal) * 100)) : 0;
?>
= e($label) ?> = e(format_points($phaseHours)) ?> h
+ 0): ?>
+
+
= e(format_points($optimalSleepHours)) ?> h