diff --git a/src/app.js b/src/app.js index aba96a8..87b702f 100644 --- a/src/app.js +++ b/src/app.js @@ -1587,6 +1587,28 @@ // ---------- pattern charts ---------- + // Where "now" falls in the day, 0..1 — the shared x for the charts that run + // midnight to midnight. + function nowDayFraction() { + const now = new Date(); + return (now.getTime() - startOfDay(now).getTime()) / 86_400_000; + } + + // Vertical "now" rule for those charts: ink over a surface-coloured underlay + // so it stays legible whatever bar or cell it crosses, with a caret hung + // above the track so it doesn't read as one more gridline. Append the parts + // last so the rule sits on top; it ignores pointer events, so the rows and + // cells underneath stay tappable. + function nowRuleParts(x, yTop, yBottom) { + const xs = x.toFixed(1); + return [ + ``, + ``, + ``, + ]; + } + // Actogram: one row per day (oldest at top), a midnight-to-midnight track // with the given windows shaded. Windows are clipped to each day, so one that // crosses midnight shows correctly split across two rows, and an open one @@ -1647,6 +1669,10 @@ parts.push(`${escapeText(title)}`); } + // The window always ends today, so one rule marks both the live edge of the + // bottom row and the same time of day on every row above it. + parts.push(...nowRuleParts(xOf(nowDayFraction()), MT, H - MB)); + setChartSVG(svg, parts); // wires the .bar[data-day] click → select that day } @@ -1894,7 +1920,7 @@ } parts.push(`24h`); - svg.innerHTML = parts.concat(hits).join(""); + svg.innerHTML = parts.concat(hits, nowRuleParts(ML + nowDayFraction() * innerW, MT, H - MB)).join(""); // tooltips only ever show on a pointer, which left phones with no // way to read a block's count. Tapping (or hovering) a block names it in diff --git a/src/changelog.json b/src/changelog.json index e1c4b45..70fb1df 100644 --- a/src/changelog.json +++ b/src/changelog.json @@ -1,4 +1,5 @@ [ + { "date": "2026-09-04", "text": "The three day-long charts — “By hour of day”, “When sleeping” and “When walking” — now mark the current time with a small vertical line and caret. On the sleeping and walking rows it also shows where today's row stops, and it lines the same clock position up across every day above it" }, { "date": "2026-09-01", "text": "Removed the walking goal from the Walk trend — the dashed target line, its legend chip and the ✓ that marked a day as met. It came from the “five-minute rule” (five minutes per month of age, twice a day), which is a widely repeated rule of thumb rather than veterinary guidance, and the app was stating it more confidently than it deserved. The chart is now just a record of what you walked, against yesterday and the average" }, { "date": "2026-09-01", "text": "The 7d / 14d / 30d buttons have moved out of the Sleep panel onto their own “Charts cover” row, just under the Log event buttons. They always set the window for every chart on the page — training, timing, sleep, walks, pees/poos/meals — but sitting inside the Sleep panel made them look like a sleep setting" }, { "date": "2026-09-01", "text": "Dropped the “Darker = more sessions that day” caption under the training consistency grid. Tapping a cell still opens that day" }, diff --git a/src/index.html b/src/index.html index a4c4b20..9927d24 100644 --- a/src/index.html +++ b/src/index.html @@ -251,7 +251,7 @@ <section class="patterns" data-panel="sleep-timeline"> <h2><span id="sleep-timeline-title">When sleeping</span> <span class="muted-note" data-chart-days-label>(last 7 days)</span></h2> <svg id="chart-sleep-timeline" class="chart-svg" viewBox="0 0 320 125" role="img" aria-label="Sleep periods per day"></svg> - <p class="muted-note">Each row is a day, midnight to midnight; shaded = asleep. Tap a row to open that day.</p> + <p class="muted-note">Each row is a day, midnight to midnight; shaded = asleep. The marker is now. Tap a row to open that day.</p> </section> <section class="patterns" data-panel="sleep-trend"> @@ -288,7 +288,7 @@ <div class="chart-title">By hour of day</div> <svg id="chart-hour-heatmap" class="chart-svg" viewBox="0 0 320 120" role="img" aria-label="Pee, poo and meal frequency by hour of day"></svg> <p id="hour-heatmap-info" class="muted-note hour-point-info" aria-live="polite"></p> - <p class="muted-note">Darker = happens more often at that hour.</p> + <p class="muted-note">Darker = happens more often at that hour; the marker is now.</p> </div> </section> @@ -308,7 +308,7 @@ <section class="patterns" data-panel="walk-timeline" hidden> <h2><span id="walk-timeline-title">When walking</span> <span class="muted-note" data-chart-days-label>(last 7 days)</span></h2> <svg id="chart-walk-timeline" class="chart-svg" viewBox="0 0 320 125" role="img" aria-label="Walks per day"></svg> - <p class="muted-note">Each row is a day, midnight to midnight; shaded = out on a walk. Tap a row to open that day.</p> + <p class="muted-note">Each row is a day, midnight to midnight; shaded = out on a walk. The marker is now. Tap a row to open that day.</p> </section> <section class="patterns" data-panel="walk-trend" hidden> diff --git a/src/style.css b/src/style.css index 51c2361..c3f2e93 100644 --- a/src/style.css +++ b/src/style.css @@ -1109,6 +1109,13 @@ input.switch:checked::after { transform: translateX(18px); } .chart-svg .stl-hit { fill: transparent; cursor: pointer; } .chart-svg .stl-hit:hover { fill: var(--accent); fill-opacity: 0.08; } +/* "Now" rule on the midnight-to-midnight charts (actograms + hour heatmap): + ink over a surface-coloured underlay so it reads over any shaded window or + cell, and never eats a tap meant for the row underneath. */ +.chart-svg .now-rule-ring { stroke: var(--surface); stroke-width: 3; pointer-events: none; } +.chart-svg .now-rule { stroke: var(--text); stroke-width: 1; opacity: 0.75; pointer-events: none; } +.chart-svg .now-rule-cap { fill: var(--text); opacity: 0.75; pointer-events: none; } + /* Sleep trend lines: today strongest, the reference curves lighter/dashed. */ .chart-svg .trend-today { stroke: var(--sleep);