feat: the redesigned Event Clock
The new reader app replaces the old UI: Checklist with a rail (focus pills, Next to expire, today's dailies, pinned routines), Timeline in a new and a classic look, Routines, Archive and a Settings area, in a Structured (default) and a Relaxed interface. It follows the approved Round 6 B and Round 7 mockups, corrected screen by screen with the owner. Reader data moves to a v2 store (gacha-tracker:v2:*). Existing v1 data is migrated on first load, a recovery copy is written first, and the v1 keys are never removed, so a rollback finds them unchanged. Redeem codes for Genshin arrive as their own feed. Also: live's urgency ramp, editable per theme; completion and section-complete fireworks; a returning-user tour; the design mockups, specs, plans, reviews and handoff record. Co-Authored-By: Claude Opus 5.5 <[email protected]>
@@ -364,3 +364,56 @@ other, so `test/update.test.tsx` pins both ends of the `skip-waiting` handshake
|
||||
cleanly because state is in SQLite.
|
||||
- **No server-side rendering.** The feed is small and cacheable; a static SPA is enough.
|
||||
- **No websockets.** Events change on a scale of hours; a 5-minute cache is more than adequate.
|
||||
|
||||
## Reader application (2026-10-16 redesign)
|
||||
|
||||
`App.tsx` exports `ReaderApp`; only the v2 reader store writes production progress. Legacy hooks
|
||||
remain as compatibility helpers, validators and tests, not mounted writers. ReaderContent coordinates
|
||||
shared Checklist/Timeline/Routines/Archive/Settings, account-aware detail adapters and timed archive
|
||||
transitions. `components/redesign/` contains the feature pages. `redesign.css` scopes Relaxed and
|
||||
Structured via data-interface, with one application tree and independent theme/density.
|
||||
|
||||
`state/reader/` owns migration, schema, reducer, store, clocks, accounts, archive, backups, restore,
|
||||
imports, routines and event selectors. Operations re-read the persisted envelope under Web Locks;
|
||||
an IndexedDB readwrite transaction serializes browsers without Web Locks. Failed locking/storage
|
||||
never publishes an optimistic success. Storage events update other tabs. Field timestamps protect
|
||||
newer edits and tombstones; account writes rebase changed routine choices. Legacy deltas reconcile
|
||||
on startup into the original migrated accounts; raw keys remain preserved.
|
||||
|
||||
Clock revisions freeze automatic metadata and overrides. Imported historical clocks are excluded
|
||||
from active clock resolution; history resolves each explicit revision. Display timezone lives in
|
||||
DisplayTimeContext and never changes the feed.
|
||||
|
||||
Events and redeem codes use separate validated static feeds. `build-codes.ts` reads pinned snapshots
|
||||
or fixtures offline and preserves firstObservedAt in snapshots/codes-first-seen.json. The refresh
|
||||
runner combines event adapters and count-only code sources while sharing robots, floors, per-host
|
||||
spacing and snapshot gates. No fake GachaEvents represent codes. Both feeds are network-first in
|
||||
the worker; manual refresh bypasses the browser cache. Shell update waiting/activation is unchanged.
|
||||
|
||||
Backups are outside the reader envelope. Restore validates first, writes a recovery export, prepares
|
||||
a pending transaction, then replaces live state. Startup finishes an interrupted transaction before
|
||||
opening the reader. Browser UI restore uses the same cross-tab lock as ordinary edits.
|
||||
|
||||
|
||||
### Ordinary HTTP / WireGuard hosts
|
||||
|
||||
Reader identity minting uses `state/reader/ids.ts`: 128-bit `crypto.getRandomValues` tokens for
|
||||
accounts, operations, reset revisions and backups. The redesign's initial `randomUUID` calls were a
|
||||
startup bug on ordinary HTTP network hosts; unlike localhost, these are not browser secure contexts,
|
||||
even when reached through a WireGuard tunnel. Existing IDs are unchanged and valid. Initialization
|
||||
preserves migration recovery before minting, so the failed first visit did not discard legacy bytes.
|
||||
|
||||
Regression verification uses a Chrome test hostname mapped to loopback with isSecureContext false,
|
||||
randomUUID unavailable and actual getRandomValues/IndexedDB available. Existing-save migration,
|
||||
new setup, editing, additional servers, reset override/revert, backup and reload all pass there.
|
||||
|
||||
|
||||
### Presentation correction (2026-10-17)
|
||||
|
||||
`ChecklistEvent`/`NextDeadline` render the approved list hierarchy; `TimelinePage` owns the shared
|
||||
axis for event spans and routine periods. `RoutinesPage` groups by reset or account, with native
|
||||
`RoutineEditor` dialogs. `ArchiveDetail` reads saved archive snapshots and never routes historical
|
||||
progress through the live event editor. Settings keeps one shared tree for both interfaces, with
|
||||
separate default-view/custom-content pages and direct game profiles. Structured is the absent-value
|
||||
default at prepaint, preference normalization, setup and appearance application. No state keys,
|
||||
event identities or stored clock revisions changed for this presentation correction.
|
||||
|
||||
@@ -244,7 +244,10 @@ CREATE TABLE snapshots (
|
||||
`region_ends` and `payload` hold JSON as TEXT; parse them through the Zod schema on read so a
|
||||
malformed row surfaces at the boundary rather than deep in the UI.
|
||||
|
||||
## Client-side storage
|
||||
## Legacy client-side storage (v1 compatibility)
|
||||
|
||||
Production uses the [active v2 reader envelope](#active-reader-state-v2-2026-10-16). The keys and
|
||||
merge rules in this section describe migration input and retained compatibility helpers.
|
||||
|
||||
Namespaced, versioned, and small. Nothing here ever goes to the server.
|
||||
|
||||
@@ -772,3 +775,48 @@ Two timestamp fields distinguish crawler activity from site updates: `lastConfir
|
||||
the crawler last successfully contacted and verified the source (HTTP 200 or 304 Not Modified), and
|
||||
`contentChangedAt` records when the served bytes last changed. Both default to `null` so feeds built
|
||||
before their introduction continue to validate.
|
||||
|
||||
## Active reader state (v2, 2026-10-16)
|
||||
|
||||
The localStorage/export descriptions above document legacy v1 compatibility. Production mounts
|
||||
only `ReaderApp` and persists `gacha-tracker:v2:reader`, validated by state/reader/schema.ts.
|
||||
One stable `account:<id>` represents one tracked game/server; it is browser-local, not a login.
|
||||
Original event/task/daily IDs remain unchanged inside account data. Account data contains progress,
|
||||
ignored, and daily/amount maps nested by clock revision. A revision freezes effectiveAt, region,
|
||||
reset override and automaticBase (offset/hour/minute). Changes append revisions; imported clocks
|
||||
can be historicalOnly and never replace the local active reset.
|
||||
|
||||
The envelope includes accounts, data, archive, seenEvents, prefs, customGames/customEvents/tasks,
|
||||
codeSeen (per game), codeRedeemed (per account), and eventSeen (per account). Archive/seen keys are
|
||||
JSON.stringify([accountId,eventId]); archive snapshots retain event, outcome/time, resolved end,
|
||||
clockRevision, progress, days and amounts. Account/revision cross-references are validated before
|
||||
restore. Field timestamps and operation IDs rebase writes and preserve deletion tombstones. Unknown
|
||||
fields pass through exports; progress imports retain opaque root/account extensions in
|
||||
importedExtensions as well as mergeable known fields. Existing same-server settings remain local.
|
||||
|
||||
Migration preserves raw v1 keys in place and in migration recovery, creates one account per game at
|
||||
the saved region and maps old follows/pins/logs. Newly offered games remain off. Startup compares
|
||||
legacyRaw with surviving v1 keys to carry older-tab deltas into the original account without
|
||||
resurrecting newer v2 deletions. Parser aliases carry progress, ticks, amounts and archive/seen IDs.
|
||||
|
||||
Keys outside the envelope:
|
||||
|
||||
- gacha-tracker:v2:migration-recovery — raw pre-migration bytes.
|
||||
- gacha-tracker:v2:backups — at most 7 daily + 4 weekly + 6 monthly UTC bucket snapshots.
|
||||
- gacha-tracker:v2:restore-recovery — the complete pre-restore export.
|
||||
- gacha-tracker:v2:restore-pending — prepared replacement, resumed before mounting on startup.
|
||||
|
||||
Exports use format gacha-tracker-export, version 2, exportedAt, reader and legacy. Progress exports
|
||||
mark scope progress; full imports preview replacement, progress imports preview a merge. Backups
|
||||
are never recursively included. Original v1 export envelopes remain convertible.
|
||||
|
||||
Prefs add interface (structured/default or relaxed), density (standard/default or compact), scheme
|
||||
(slate/warm/plum/custom), separate light/dark customPalette, per-game gameColors, timezone
|
||||
(null/Automatic or IANA), checklist daily placement/expansion and redesignTourSeen. Main view remains
|
||||
soon or timeline; utility navigation is transient. Future/unreadable records remain exportable even
|
||||
when this build cannot offer editing controls.
|
||||
|
||||
|
||||
The fidelity correction adds `prefs.routineGroup` (`reset`, the absent-value default, or `game`)
|
||||
for the Routines page's grouping. It changes no routine IDs or placement keys. Structured is the
|
||||
interface default as of the owner's 2026-10-17 instruction; explicit saved Relaxed is preserved.
|
||||
|
||||
@@ -2,84 +2,84 @@
|
||||
name: Event Clock
|
||||
description: Live and upcoming gacha events, sorted by what expires next.
|
||||
colors:
|
||||
ground: "#12141c"
|
||||
surface: "#1b1e2a"
|
||||
raised: "#232739"
|
||||
hairline: "#2c3145"
|
||||
ink: "#e9ebf3"
|
||||
ground: "#1a1c24"
|
||||
surface: "#22252f"
|
||||
raised: "#30333c"
|
||||
hairline: "#43454c"
|
||||
ink: "#eeeae3"
|
||||
ink-strong: "#ffffff"
|
||||
muted: "#888fa6"
|
||||
faint: "#5a6178"
|
||||
muted: "#b1afad"
|
||||
faint: "#9c9b9b"
|
||||
scrim: "rgb(18 20 28 / 0.8)"
|
||||
glow: "#1a1e2c"
|
||||
calm: "#55607f"
|
||||
near: "#5b8def"
|
||||
soon: "#e8b33c"
|
||||
critical: "#ff4d6a"
|
||||
ground-light: "#edf0f7"
|
||||
surface-light: "#ffffff"
|
||||
raised-light: "#dfe4f0"
|
||||
hairline-light: "#c9d1e2"
|
||||
ink-light: "#151824"
|
||||
near: "#8eb3f4"
|
||||
soon: "#e9b95b"
|
||||
critical: "#ff8598"
|
||||
ground-light: "#f3f1ec"
|
||||
surface-light: "#fffdf8"
|
||||
raised-light: "#f0eeea"
|
||||
hairline-light: "#dddbd8"
|
||||
ink-light: "#28272d"
|
||||
ink-strong-light: "#000000"
|
||||
muted-light: "#535b73"
|
||||
faint-light: "#767e94"
|
||||
muted-light: "#69676a"
|
||||
faint-light: "#6e6d6e"
|
||||
scrim-light: "rgb(26 31 48 / 0.42)"
|
||||
glow-light: "#ffffff"
|
||||
calm-light: "#8a92a8"
|
||||
near-light: "#2b62c6"
|
||||
soon-light: "#8a6008"
|
||||
critical-light: "#c81e3c"
|
||||
near-light: "#315fa5"
|
||||
soon-light: "#805a12"
|
||||
critical-light: "#b12947"
|
||||
typography:
|
||||
numeral:
|
||||
fontFamily: "Chakra Petch, ui-sans-serif, system-ui, sans-serif"
|
||||
fontFamily: "Bricolage Grotesque, ui-sans-serif, system-ui, sans-serif"
|
||||
fontSize: "2.75rem"
|
||||
fontWeight: 700
|
||||
lineHeight: 1
|
||||
letterSpacing: "-0.025em"
|
||||
fontFeature: "\"tnum\" 1"
|
||||
display:
|
||||
fontFamily: "Chakra Petch, ui-sans-serif, system-ui, sans-serif"
|
||||
fontFamily: "Bricolage Grotesque, ui-sans-serif, system-ui, sans-serif"
|
||||
fontSize: "1.75rem"
|
||||
fontWeight: 600
|
||||
lineHeight: 1.15
|
||||
letterSpacing: "-0.025em"
|
||||
wordmark:
|
||||
fontFamily: "Chakra Petch, ui-sans-serif, system-ui, sans-serif"
|
||||
fontFamily: "Bricolage Grotesque, ui-sans-serif, system-ui, sans-serif"
|
||||
fontSize: "0.9375rem"
|
||||
fontWeight: 700
|
||||
letterSpacing: "0.02em"
|
||||
reading:
|
||||
fontFamily: "Chakra Petch, ui-sans-serif, system-ui, sans-serif"
|
||||
fontFamily: "Bricolage Grotesque, ui-sans-serif, system-ui, sans-serif"
|
||||
fontSize: "0.875rem"
|
||||
fontWeight: 600
|
||||
fontFeature: "\"tnum\" 1"
|
||||
title:
|
||||
fontFamily: "Public Sans, ui-sans-serif, system-ui, sans-serif"
|
||||
fontFamily: "Figtree, ui-sans-serif, system-ui, sans-serif"
|
||||
fontSize: "0.9375rem"
|
||||
fontWeight: 500
|
||||
lineHeight: 1.375
|
||||
body:
|
||||
fontFamily: "Public Sans, ui-sans-serif, system-ui, sans-serif"
|
||||
fontFamily: "Figtree, ui-sans-serif, system-ui, sans-serif"
|
||||
fontSize: "0.875rem"
|
||||
fontWeight: 400
|
||||
lineHeight: 1.625
|
||||
summary:
|
||||
fontFamily: "Public Sans, ui-sans-serif, system-ui, sans-serif"
|
||||
fontFamily: "Figtree, ui-sans-serif, system-ui, sans-serif"
|
||||
fontSize: "0.8125rem"
|
||||
fontWeight: 400
|
||||
lineHeight: 1.375
|
||||
control:
|
||||
fontFamily: "Public Sans, ui-sans-serif, system-ui, sans-serif"
|
||||
fontFamily: "Figtree, ui-sans-serif, system-ui, sans-serif"
|
||||
fontSize: "0.75rem"
|
||||
fontWeight: 500
|
||||
label:
|
||||
fontFamily: "Chakra Petch, ui-sans-serif, system-ui, sans-serif"
|
||||
fontFamily: "Bricolage Grotesque, ui-sans-serif, system-ui, sans-serif"
|
||||
fontSize: "0.6875rem"
|
||||
fontWeight: 600
|
||||
letterSpacing: "0.14em"
|
||||
tag:
|
||||
fontFamily: "Public Sans, ui-sans-serif, system-ui, sans-serif"
|
||||
fontFamily: "Figtree, ui-sans-serif, system-ui, sans-serif"
|
||||
fontSize: "0.625rem"
|
||||
fontWeight: 500
|
||||
rounded:
|
||||
@@ -170,7 +170,11 @@ components:
|
||||
|
||||
# Design System: Event Clock
|
||||
|
||||
## Overview
|
||||
The active Relaxed/Structured layout and palette contract is recorded in
|
||||
[Active redesign system](#active-redesign-system-2026-10-16). The component rationale below describes
|
||||
the preceding instrument-panel system; use the active section and live token resolver for new work.
|
||||
|
||||
## Original component rationale
|
||||
|
||||
**Creative North Star: "The Lit Instrument Panel"**
|
||||
|
||||
@@ -528,3 +532,105 @@ rather than being toned down.
|
||||
chooses.
|
||||
- **Don't** put a second control inside a row, or a drag target on the focus bar or the dailies
|
||||
strip.
|
||||
|
||||
## Shipped redesign system (2026-10-18)
|
||||
|
||||
The owner accepted this build as the initial redesign on 2026-10-18, after screen-by-screen review
|
||||
against the approved mockups (`design/mockups/round6/b-rail.html` for Structured,
|
||||
`design/mockups/round7/converged.html` for Relaxed) and the corrections recorded round by round in
|
||||
`docs/handoffs/2026-10-17-redesign-second-rejection-handoff.md`. This section supersedes the original
|
||||
shell/type/palette/layout descriptions above. Those older sections remain the rationale for the detail,
|
||||
timeline and uncertainty components that carried over. Overrides live in `src/client/redesign.css`
|
||||
and `src/client/state/appearance.ts`.
|
||||
|
||||
### Shell and layout
|
||||
|
||||
- **Interfaces.** Settings → Appearance offers Structured (the Round 6 B rail; the default for new
|
||||
installs and missing preferences) and Relaxed (Round 7). A saved Relaxed choice stays Relaxed.
|
||||
Structured uses Barlow Condensed/Barlow and adjoining ruled sections. Relaxed uses Bricolage
|
||||
Grotesque/Figtree with separated panels. Fonts keep system fallbacks offline.
|
||||
- **Navigation.** The tabs are Checklist, Timeline, Routines and Archive, with Settings on the right.
|
||||
The EVENTCLOCK logo returns to the default view. Each page is in the address bar (`#checklist`,
|
||||
`#settings/games/genshin`, …), and changing tab starts at the top of the page.
|
||||
- **Width.** The page fills up to 1920px (Relaxed 1840px) and centres beyond that.
|
||||
- **Two insets on `.reader-ui`.** `--edge` (16px) between content and the page's outer edges.
|
||||
`--gutter` (24px) where a side column (Checklist rail, Settings nav, Archive sidebar) meets the main
|
||||
content. At ≤700px, where everything stacks, both are the edge.
|
||||
- **Checklist rail.** 360px wide (Relaxed 380px; 280/300px at medium widths). Top to bottom: the
|
||||
focus pills, Next to expire (headline, meter and the next three), Today's dailies, then pinned
|
||||
routines grouped by game.
|
||||
|
||||
### Urgency and colour
|
||||
|
||||
- **Two axes, never crossed.** Game hue answers whose event: the 3px strip on the left of each
|
||||
Standard row, the Compact game cell, the pills. The urgency ramp answers how long: countdowns and
|
||||
meter ticks.
|
||||
- **The urgency ramp is live's.** Grey for a week or more, blue under a week, yellow under 3 days, red
|
||||
under a day: `--color-urgency-{calm,near,soon,critical}`, set by `urgencyTokens`. It is separate
|
||||
from the accent, so a chosen accent never changes urgency.
|
||||
- **Reader-editable.** Settings → Appearance → Urgency colours sets each step per theme
|
||||
(`prefs.urgencyPalette`), with any scheme. Values are nudged only as far as 3:1 contrast, the
|
||||
large-text bar.
|
||||
- **Fallback for the live UI.** `URGENCY_COLOR` falls back to the old `--color-*` tokens, so the
|
||||
live UI is unchanged.
|
||||
- **Schemes.** Slate, Warm, Plum and Custom shift surfaces. Custom stores ground/surface/text/accent
|
||||
per theme. Text and accent derive at least 4.5:1 contrast on ground and surface. Game colours are
|
||||
set per game in Your games.
|
||||
|
||||
Default Slate tokens:
|
||||
|
||||
| Role | Structured dark | Structured light | Relaxed dark | Relaxed light |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| Ground | #0e1117 | #eef0f5 | #1a1c24 | #f3f1ec |
|
||||
| Surface | #141923 | #ffffff | #22252f | #fffdf8 |
|
||||
| Primary text | #eeeae3 | #28272d | #eeeae3 | #28272d |
|
||||
| Accent | #8eb3f4 | #315fa5 | #8eb3f4 | #315fa5 |
|
||||
|
||||
### Checklist
|
||||
|
||||
- **Heading.** "Running now" sits with the sort and density buttons on one row. Under them is one
|
||||
line: the count on the left and live's legend on the right ("bars = time left · colour = ends in a
|
||||
week+ / under a week / under 3 days / under a day").
|
||||
- **Standard rows.** Game, title, optional description, then the countdown, date and meter, with the
|
||||
chevron 10px from the date. Every row has a meter, with or without a description; the mockup hid
|
||||
it on rows without one, and the owner chose consistency.
|
||||
- **Compact rows.** A ledger with Game / Event / Time left / Ends in columns.
|
||||
- **"Not started yet."** It opens a second section: a 48px gap, a 2px accent rule and a raised band
|
||||
with a "Coming up" eyebrow. In Compact its columns read Duration / Starts in.
|
||||
|
||||
### Focus pills
|
||||
|
||||
They have live's chip feel: 30px tall, 12px text, a 30% hue border unpressed, the full hue with a 14%
|
||||
wash when pressed. State changes ease over 130ms. Hover adds a hue ring and a 1px lift, a press
|
||||
scales to 0.96, and games with nothing outstanding dim to 50%. The "Focus" label is a 12px body-face
|
||||
legend on the same baseline as "Next: …".
|
||||
|
||||
### Ticking things off
|
||||
|
||||
- **Today's dailies.** The whole row is the target. A tick washes the row in its game's hue, pops the
|
||||
box and draws the check. A pip bar and "N of M done" sit under the heading. A check-in goal (for
|
||||
example "5/5 wk") counts as done once met, with a dotted check, and shows its goal count instead of
|
||||
a streak.
|
||||
- **Pinned routines** use the same card language. A box ticks a check-in routine, or completes an
|
||||
amount routine in one click. "+1" steps an amount, and the count opens an editor. Typing a value at
|
||||
or over the target completes it after a 450ms pause.
|
||||
- **Completion animation.** The bar fills, the row warms, then the box pops. Unticking undoes it:
|
||||
the amount from before goes back, or the editor opens when that value isn't known.
|
||||
- **Celebration.** A single completion fires live's small `Fireworks` in the row. Finishing a whole
|
||||
section (every daily, or every routine in a game's group) fires `Fireworks grand`: seven bursts in
|
||||
two waves with the game's hue mixed in, a light sweep, and the "All done" line popping.
|
||||
- **When it fires.** Only an action taken now that completes the item or section, never arriving
|
||||
complete. Reduced motion removes all of it.
|
||||
|
||||
### Other pages
|
||||
|
||||
- **Routines.** Bands by reset (Dailies, Weeklies, Monthlies, Cycles) or by game. The table has tick
|
||||
and click-to-edit amount cells. The library and create/edit drawers are shelves.
|
||||
- **Timeline.** Two looks (new and classic) chosen in Appearance. Dailies are not on the timeline.
|
||||
- **Settings.** About, Changelog, Data & sources (list options first), Region & time, Appearance
|
||||
(interface, theme, scheme, urgency colours, default view, game order, timeline design, focus bar,
|
||||
checklist group), Your own events and games, Backup (tiers plus a manual "Your backups" list), and
|
||||
per-game Setup / Codes / About.
|
||||
- **Returning-user tour.** Routines → Checklist → Timeline → Redeem codes → Archive → Settings.
|
||||
Continue stays in a fixed place, Back sits beside it, and Skip is apart. "Replay the introduction"
|
||||
starts it at step 1.
|
||||
|
||||
@@ -640,3 +640,22 @@ fixture is the regression test proving the parser still handles the previous for
|
||||
guessing, impossible calendar dates are rejected, ranges crossing New Year roll the start year back,
|
||||
and abbreviated months parse. `test/merge.test.ts` covers cross-source agreement, disagreement, and
|
||||
rerun disambiguation. These are the last line of defense before a wrong date reaches a user.
|
||||
|
||||
|
||||
## Redeem codes source (2026-10-16)
|
||||
|
||||
Genshin codes use https://game8.co/games/Genshin-Impact/archives/304759, separately from events.
|
||||
One descriptive-agent robots request and one page request returned HTTP 200 during capture; no
|
||||
access workaround or repeated source fetch was used. The raw page and capture metadata are pinned
|
||||
as fixtures/genshin/game8-codes-2026-10-16.*, with ten independently counted current codes. The
|
||||
parser reads actual code inputs/current reward rows and excludes expired programme sections; a
|
||||
future-dated programme fixture variant verifies that still-current programmes are admitted.
|
||||
Unannounced expiry remains null. A printed calendar date is expiresOn, never a fabricated exact
|
||||
expiresAt instant. Attribution is retained on every code.
|
||||
|
||||
src/ingest/codes/registry.ts registers a count-only refresh source. The existing runner shares robots,
|
||||
six-hour floors, conditional requests, per-host spacing and snapshot gates across event/code sources.
|
||||
Event adapter schemas are unchanged. scripts/build-codes.ts builds data/codes.v1.json offline from
|
||||
snapshots or fixtures and preserves observation timestamps in snapshots/codes-first-seen.json.
|
||||
Code newness is per game; redemption is per local game/server account and never clears newness by
|
||||
itself. No code row is synthesized into the event feed.
|
||||
|
||||
@@ -111,14 +111,9 @@ few pixels apart the board is being asked the one question it exists to answer a
|
||||
reader to squint. It also gives a one-day event a bar to read and to tap rather than the 34px
|
||||
minimum every short bar collapses to.
|
||||
|
||||
**What has not started yet is shown to a new reader, and either can switch it** — `prefs.showUpcoming`,
|
||||
which governs **both views**: the board plots them, and the checklist keeps its "Not started yet"
|
||||
section (F2). One question, asked once, because they are the same events. It was off by default,
|
||||
because this app answers *what expires next* and a reader with fourteen lanes has a next patch queued
|
||||
behind every one of them. Since 2026-10-13 (repository owner) first-run setup turns it **on**: a new
|
||||
reader should see what is coming before deciding they do not want it. The stored default is still
|
||||
`false`, so an existing install whose saved prefs predate the field keeps today's answer rather than
|
||||
having it switched on underneath its reader.
|
||||
**Upcoming events are optional and off initially.** New setup asks “Show events that haven't
|
||||
started” under “What do you want to track?”. The same saved answer governs Checklist and Timeline;
|
||||
Checklist separates them under “Upcoming events”. Existing saved choices survive migration.
|
||||
|
||||
On the board that is structural as well as editorial: the window is drawn from what is plotted, so
|
||||
showing the future stretches the right edge weeks past today and squeezes the running bars the
|
||||
@@ -129,10 +124,8 @@ quiet fortnight, and this app does not leave a reader to infer what it is not sh
|
||||
page header states `N live · N upcoming` whatever the setting says, and either view left with
|
||||
nothing to show says so in words and names the setting rather than rendering an empty column.
|
||||
|
||||
The switch is in settings (F4), with the two other answers to *what am I allowed to look at* —
|
||||
`showCompleted` and `showIgnored` — and **not** in the board's own header beside the stacking and
|
||||
scale controls. That is the line those two draw: they reshape what is already on the board, which is
|
||||
why they are reached for while reading it, and this one decides what is on it at all.
|
||||
The switch lives in Settings → Lists, because it decides which events enter both main views.
|
||||
Done and ignored events live in Archive; Lists has no redundant Archive link or reveal switches.
|
||||
|
||||
**Switched on, the board says in words where they begin.** A bar drawn to the right of the "now"
|
||||
rule is only *implicitly* in the future, and implicitly is not a standard this product holds itself
|
||||
@@ -198,42 +191,17 @@ an explicit "show all N". This truncates the *view* only: the order is untouched
|
||||
the cut are still counted in the header, still on the timeline, and one tap away.
|
||||
|
||||
**F3 — Mark completed.**
|
||||
A toggle on every event, in both views. State is written to `localStorage` immediately and
|
||||
optimistically — there is no server round trip and no failure case. Completed events stay visible
|
||||
but de-emphasized; a filter toggles them out entirely.
|
||||
Done writes durable progress and a metadata snapshot immediately. A confirmation remains for about
|
||||
1.5 seconds before the row fades/collapses into Archive. Undo is available for eight seconds;
|
||||
Archive Restore remains available afterwards. A failed write is disclosed and never presented as
|
||||
saved. Reduced motion removes the fade.
|
||||
|
||||
**F4 — Filters.**
|
||||
Filter by game (multi-select, persisted) and by event type. Hiding a game hides it from both views.
|
||||
Preferences persist in `localStorage`.
|
||||
|
||||
The panel holding them is **six collapsed groups, each stating its own answer on the summary line**
|
||||
— games, server region, appearance, what you see, your own games and events, your progress. It was
|
||||
one open block of everything, laid out in two columns on a wide screen, which read fine at four games
|
||||
and stopped working at eighteen: the game list alone is eighteen rows of four controls, and it sat
|
||||
above the checkbox a reader had come down here to tick. Collapsing on its own would only trade that
|
||||
friction for another, though — a group that shows nothing but its name turns *what is my region set
|
||||
to?* into a click — so each summary answers its group's question, and the closed panel is a six-line
|
||||
report of how the app is configured. Opening one is for changing an answer, not for reading it.
|
||||
|
||||
Three things follow. **The groups ship closed**, including the one holding the filters that other
|
||||
copy points at: the empty states name both the switch and the group it is in, which is more findable
|
||||
than a checkbox in a wall was. **The summary states are derived, never stored** — they are a reading
|
||||
of `prefs`, so they cannot disagree with the controls inside. And **a group answers one question**.
|
||||
The region and the theme began as one group called *Reading*, on the argument that both are "how do I
|
||||
read this?" — which summarised as `Europe · Dark`, two unrelated answers joined by a dot, under a
|
||||
name for neither. The region is not a reading preference: it is which server the reader's account is
|
||||
on, and region-scoped ends, undated deadlines and every daily streak are read off that server's
|
||||
clock, so it is the one control in this panel that can make a countdown wrong. It gets its own line,
|
||||
and says as much when opened.
|
||||
|
||||
**The panel uses the page's width**, like every other block on it. The rows were held to a narrower
|
||||
measure on the argument that a name and its state stop reading as one line across a wide screen, but
|
||||
the panel's own rule spans the shell, so the rules inside it stopped a third of the column short and
|
||||
the panel became the one thing on a desktop page not using the width — sitting between a two-column
|
||||
checklist and a three-column footer that both do. A title at one end of a full-width row and its
|
||||
countdown at the other is what "running now" does directly above it. Prose inside a group keeps a
|
||||
readable measure, and the game list takes two columns of its own on a wide screen once there are nine
|
||||
or more games, because eighteen rows in one column is a thousand pixels of ribbon down the left.
|
||||
**F4 — Settings and visibility.**
|
||||
Settings has named pages: General, Your games, Appearance, Lists, Region & time, Data & sources,
|
||||
Backup, About Event Clock, and Changelog. Your games controls visibility/order, tracking choices,
|
||||
servers, reset overrides and colours; Lists controls upcoming events and timeline grouping.
|
||||
Routines owns follows and independent Checklist/Timeline pins. Utility navigation does not replace
|
||||
the saved default main view. Empty states name where to change the relevant choice.
|
||||
|
||||
**F4a — Focus one game at a time.**
|
||||
Switching games on and off says *which games the reader plays*, and is set once. It is the wrong
|
||||
@@ -253,15 +221,26 @@ has left the feed is ignored rather than obeyed, so it can never strand the read
|
||||
whose cause is elsewhere. Each chip carries that game's outstanding count, so a game with nothing
|
||||
waiting says so before it is visited.
|
||||
|
||||
**F5 — Region selection.**
|
||||
A user picks Asia / America / Europe once. For events where `regionScoped` is true, all displayed
|
||||
end times resolve to that region's server reset. This is stored in `localStorage` and defaults to a
|
||||
guess from the browser timezone, shown as a dismissible "showing America server times — change".
|
||||
**F5 — Servers and display timezone.**
|
||||
Default server is chosen in setup and Region & time. Each locally tracked game/server has its own
|
||||
stable account identity and progress. “Add another server” is for simultaneously playing multiple
|
||||
servers: it starts fresh tracking choices and never clones marks. Server/reset changes append clock
|
||||
revisions so history stays on its original clock. Overrides can revert to Automatic. Display timezone
|
||||
is Automatic by default or a searchable IANA zone; it changes printed dates and manual date entry,
|
||||
never a source's exact timestamps or game-day keys.
|
||||
|
||||
**F6 — Export / import.**
|
||||
Because there are no accounts, moving between devices is manual: download a JSON file of completed
|
||||
IDs and preferences, upload it elsewhere. Import merges rather than replaces, and never removes a
|
||||
completion the user already has.
|
||||
**F6 — Export / import and backup.**
|
||||
No login is involved. Export progress / Import progress merges per game/server, retaining local
|
||||
preferences and active reset configuration. Day logs union; newer records/amounts win conflicts.
|
||||
Imported clock revisions remain accessible as historical clocks. Unknown extensions are retained in
|
||||
the envelope. Export all / Import all restores the complete validated envelope through a preview,
|
||||
with a recovery copy before replacement. Undo last restore reverses it. Version-1 exports remain
|
||||
convertible; original v1 browser keys are retained after migration.
|
||||
|
||||
Local backup history keeps seven daily, four weekly and six monthly snapshots while the app is
|
||||
used. UTC buckets keep their latest snapshot; backups never contain other backups. View backup
|
||||
opens the preview; Restore this backup is the separate committing action. Storage failures are
|
||||
visible. Browser deletion removes local history; export is the way to keep an external copy.
|
||||
|
||||
**F12 — Record your own progress and effort.**
|
||||
Three states, not two: untouched, doing it, done. Plus an optional effort estimate — quick, short,
|
||||
@@ -418,15 +397,16 @@ the one after it — because they answer "what ends soonest". The timeline draws
|
||||
every occurrence in view, because it answers "what is the rhythm".
|
||||
|
||||
**F8 — First-run setup.**
|
||||
Before any events are shown, the reader picks which games they play, and how they want to read
|
||||
them. A calendar full of games they
|
||||
don't play is worse than an empty one — it buries the thing they came for. Nothing is preselected
|
||||
and the button stays disabled until something is chosen; guessing on their behalf and hoping they
|
||||
notice is worse than asking. **The games are listed alphabetically by name**, not in feed order:
|
||||
everywhere else a lane's position carries meaning, but here the reader is scanning for the two or
|
||||
three names they already know, and a list ordered by which game happened to hold the first event row
|
||||
gives them nothing to scan by. The choice is stored as *hidden* games, the inverse — which is a storage
|
||||
shape, not a policy: what happens to a game added later is decided separately, below.
|
||||
Before events are shown, a four-step wizard asks for games, default server and preferred appearance,
|
||||
tracking kinds, and the default main view. Games are alphabetical, nothing selected. Events are the
|
||||
only initially selected tracking kind. Dailies, weekly/monthly and cycles have short descriptions;
|
||||
unavailable kinds remain selectable and say nothing is currently detected. Upcoming visibility
|
||||
belongs to that tracking step and starts off. Server and appearance can be changed later.
|
||||
|
||||
Returning readers get a one-time introduction and optional four-step tour. Skipping or finishing
|
||||
preserves progress and the saved main view; General can replay it.
|
||||
|
||||
|
||||
|
||||
**A game added later arrives switched off.** Adding a source is our decision, not the reader's, and
|
||||
someone who plays two games did not ask for the other twelve; a calendar that fills itself up is the
|
||||
@@ -447,10 +427,13 @@ The view question (F2) sits under it, with each option drawn rather than only de
|
||||
it arrives already answered, and the screen says where to change it afterwards: the tabs are small
|
||||
text in a corner, which is the one control a first-time reader will not find on their own.
|
||||
|
||||
**F9 — Ignore an event.**
|
||||
Distinct from completing one. "Done" keeps an event visible and counted; "not interested" removes it
|
||||
from both views entirely. Ignored events stay recoverable: a count and a reveal toggle appear in
|
||||
settings once there is something to reveal.
|
||||
**F9 — Ignore and Archive.**
|
||||
Ignore saves immediately and follows the same confirmation/Undo transition as Done. Both move to
|
||||
Archive with event metadata, notes, goals, logs, resolved end and clock revision. Previously seen
|
||||
followed events that expire unfinished also enter Archive; unknown-end events never expire by a
|
||||
guessed date. Per-game history is default, with an alternate chronological history. Story statistics
|
||||
include completion, check-ins and shortfalls where known; ignored events are excluded from success
|
||||
rates. Restore recovers saved progress without pretending an expired event is live.
|
||||
|
||||
**F10 — Works offline.**
|
||||
The reader's question is answered entirely by data already on the device, and countdowns run off the
|
||||
@@ -459,9 +442,9 @@ the last feed it downloaded. Offline is disclosed in the header and above the fo
|
||||
data must never be presented as current.
|
||||
|
||||
**F11 — Credit and disclaimer.**
|
||||
The sources that compile these calendars, and the studios that make the games, are named on the same
|
||||
screen as the data rather than one navigation step away. The page states plainly that it is
|
||||
unofficial and unaffiliated, and that the source page is the authority when the two disagree.
|
||||
Settings → About Event Clock preserves the full colophon, source credits, unofficial/unaffiliated
|
||||
disclaimer and feedback links. The footer links About. Each game's About lists the real data sources,
|
||||
links and thanks; event detail links its authoritative source.
|
||||
|
||||
**F14 — Say when a new version of the app is ready.**
|
||||
F10 caches the shell so the app survives losing signal, and the same cache is why a reader who never
|
||||
@@ -483,42 +466,29 @@ arrive without a reload, and calling that a new version would train readers to d
|
||||
unread.
|
||||
|
||||
**F7 — Freshness disclosure.**
|
||||
The footer shows when the feed was last updated, per game. If a game's data is more than 48 hours
|
||||
stale, its lane carries a warning badge. Never present stale data as current — the whole value
|
||||
proposition is trust in the dates.
|
||||
The footer always states data age, never build age. Only tracked games with stale data produce a
|
||||
compact “Event data may be out of date” row in the shared updates area. New events and new codes
|
||||
remain distinct notices. Data & sources and event detail expose the last successful check, last
|
||||
content change, source links and recorded reasons. A successful 304 confirms a check without
|
||||
claiming the wiki changed.
|
||||
|
||||
**The reader can ask for the newest data.** A reload is not enough — the browser may keep the feed
|
||||
for minutes — so *Check for new data* beside the age asks the server past that copy and swaps a newer
|
||||
feed in without a reload. It says what happened: updated, nothing newer published yet (sources are
|
||||
read about twice a day, and the button cannot make that sooner), or the server could not be reached.
|
||||
"Newer" is judged on events and source health, never on the build stamp. Disabled offline; nothing
|
||||
polls on its own.
|
||||
Check for new data revalidates event and code feeds, compares their content rather than generatedAt,
|
||||
and reports updated, unchanged or failure. It does not scrape source sites from the browser.
|
||||
|
||||
**The staleness notice names only the games the reader has switched on, and says that it does.**
|
||||
The headline age is about the feed and stays whole; the notice under it is an *instruction*, and the
|
||||
only remedy it offers is "go and check that game's source page" — which a reader cannot act on for a
|
||||
game they turned off and cannot see a single row of. With nineteen lanes and two switched on, naming
|
||||
eleven they do not play buries the one they do, and a warning about games nobody reads is a warning
|
||||
nobody reads (F8: a game we add is a game they never asked for, and arrives switched off, so an
|
||||
untouched install would be warned about the whole catalogue).
|
||||
**F15 — Appearance.**
|
||||
Relaxed (Round 7) and Structured (Round 6 B rail) share one component/state tree. Structured is the default (owner decision, 2026-10-17); an explicitly saved Relaxed preference is preserved.
|
||||
Interface choice, Standard/Compact density, Dark/Light/System theme and Slate/Warm/Plum/Custom
|
||||
scheme are independent. Custom stores ground/surface/text/accent separately for light and dark;
|
||||
rendered colours derive readable contrast without overwriting the saved choices. Per-game colours
|
||||
have a picker, hex field, preview and reset. Checklist dailies can occupy a separate direct-tick panel
|
||||
or grouped routines, with collapsed/expanded/always-expanded policies; these controls also live in
|
||||
Routines. Numeric routines use native step-one inputs.
|
||||
|
||||
Both halves of that are load-bearing. Scoping it silently would be the worse half: "nothing has
|
||||
refreshed" is a claim about the whole calendar, so a reader with fourteen of eighteen lanes off would
|
||||
read a sentence about four as one about all of them. The notice therefore states whose games it
|
||||
counted, in the same words the empty list uses — *the games you have switched on*. Credit in the
|
||||
column beside it is owed to every source we read and is not scoped; nor is the "last refreshed" line,
|
||||
which reports the feed and feeds the bug form.
|
||||
|
||||
**The staleness notice differentiates crawler checks from site updates.** If our crawler successfully
|
||||
checked the wiki recently (e.g. confirming HTTP 304) but the site's content has not changed in over
|
||||
two days, the notice explicitly distinguishes the two: "data pulled X ago, site updated Y ago", with
|
||||
an expandable breakdown detailing each source's check and content update times.
|
||||
|
||||
**F15 — Light mode, with dark still the default.**
|
||||
The earlier theme rationale below still applies to both interfaces.
|
||||
The app is a lit instrument panel and that is what it should be on first sight, but it is also read
|
||||
on a train in daylight and by people who find a dark UI harder rather than moodier. A public fork
|
||||
worked a theme toggle out first and is credited for the idea in the colophon. So the ground is
|
||||
the reader's choice: **Dark**, **Light**, or **System** to follow the device, in settings next to the
|
||||
the reader's choice: **Dark**, **Light**, or **System** to follow the device, in Settings → Appearance, separately from the
|
||||
region — both are "how do I read this?" and neither changes what the page knows.
|
||||
|
||||
Dark is what it ships as, and deliberately not `System`. A reader whose laptop is in light mode has
|
||||
@@ -571,7 +541,15 @@ placed. It also arrives switched off (F8), so settings is where they meet it, wh
|
||||
would move it anyway. **A game's dailies stay together** — a repeating event the reader marked sits
|
||||
with the standing chore of the game it came from, because the reader thinks in games and not in kinds.
|
||||
|
||||
**F17 — Weekly and monthly tasks.**
|
||||
**F17 — Routines.**
|
||||
Routines is the library and management page for daily, weekly, monthly and cycle tasks. Follow each
|
||||
per server; pin independently to Checklist and Timeline. Built-ins offer Make it mine, copying only
|
||||
that account's logs; custom routines remain editable. Catch up & recorded history exposes logs on
|
||||
their original reset revisions. A separate Timeline reset strip sits directly after its game's events;
|
||||
with strips off, Ending soonest remains a single cross-game deadline queue.
|
||||
|
||||
The cadence and goal semantics below remain the domain contract; the redesign moves their controls
|
||||
from the former Your own section to Routines.
|
||||
Some chores roll weekly or monthly rather than daily — earning ZZZ's weekly activity points,
|
||||
finishing Endfield's weekly routine — and no source publishes them, so they were nowhere in the app.
|
||||
A reader can now set them up per game in *Your own*: a title, every week (from a weekday they pick),
|
||||
@@ -624,7 +602,7 @@ instant on every server rolls on that server's reset for every reader.
|
||||
The app now says what changed, in two tiers, both tied to git. **Short entries** — one line each,
|
||||
tagged New, Fixed, or Games & sources — appear once as *What's new*, above the lists, after a new
|
||||
version loads; *Got it* dismisses them. **Release notes** — a few paragraphs per feature or
|
||||
milestone, summarised from the history and the design specs — are in the footer's *Changelog*, each
|
||||
milestone, summarised from the history and the design specs — are in Settings → *Changelog*, each
|
||||
linked to the commits it covers and the specs it draws on. Data refreshes are not changes in this
|
||||
sense; the footer already states the data's age.
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ away for more coverage (see Product Principles).
|
||||
|
||||
## Capabilities and Constraints
|
||||
|
||||
**Capabilities.** The full feature set is specified as F1–F16 in `docs/PRD.md`:
|
||||
**Capabilities.** The full feature set is specified as F1–F18 in `docs/PRD.md`:
|
||||
|
||||
- A timeline: one lane per game, or a single queue sorted by soonest end.
|
||||
- A checklist of everything running, sorted by soonest end.
|
||||
@@ -79,16 +79,17 @@ away for more coverage (see Product Principles).
|
||||
- Daily checklists, with past days that can still be filled in.
|
||||
- Ignoring an event, and filters by game or type.
|
||||
- Focusing on one game at a time.
|
||||
- Region selection.
|
||||
- JSON export and import.
|
||||
- Separate game/server tracking, reset corrections and Automatic or named display timezone.
|
||||
- JSON export/import, recoverable restore and 7 daily / 4 weekly / 6 monthly local backups.
|
||||
- The reader's own games and events, one-off or repeating.
|
||||
- First-run setup.
|
||||
- Events-first new setup and a one-time returning-reader introduction.
|
||||
- Offline use.
|
||||
- A notice when a new version of the app is ready.
|
||||
- Dark or light mode, plus a "follow the system" option.
|
||||
- The reader's own game order.
|
||||
- The reader's own game order, per-game colours, Relaxed/Structured interfaces and custom schemes.
|
||||
- A Routines library with independent view pins, an Archive with story statistics, and sourced redeem codes.
|
||||
|
||||
The app currently covers twenty games from twenty-two sources.
|
||||
The app covers twenty games; source registries are the authoritative current count.
|
||||
|
||||
**Hard constraints** (`AGENTS.md` § Three constraints):
|
||||
|
||||
@@ -112,7 +113,7 @@ The app currently covers twenty games from twenty-two sources.
|
||||
**Terminology:**
|
||||
|
||||
- The user is a **reader**.
|
||||
- The two views are **Checklist** (stored id `"soon"`) and **Timeline**.
|
||||
- The main views are **Checklist** (stored id `"soon"`) and **Timeline**; Routines, Archive and Settings are utility pages.
|
||||
- An event's states are **untouched**, **doing it** and **done**.
|
||||
- **Ignore** is not the same as done.
|
||||
- A **lane** is one game's row or source.
|
||||
|
||||
@@ -976,3 +976,22 @@ Facts stated above that a future reader may want to re-check, with how they were
|
||||
| `marisaimpact.com` states no year on any calendar | stripped tags from `/calendar89` and `/calendar90` and grepped the text for `20\d\d` — zero matches on either |
|
||||
| Its calendar URL is per-version, with no stable alias | `/calendar90` is `200` and covers `Aug 20 - Oct 22`; `/valk/calendar90` — the scheme its own `og:url` uses — is `404`; the nav links only `/calendar88` and `/calendar89` |
|
||||
| Its schedule is not behind an API | `GET /calendar90/__data.json` returns 144 bytes: an `ogImage` URL and nothing else |
|
||||
|
||||
|
||||
## Redeem codes source (2026-10-16)
|
||||
|
||||
Genshin codes use https://game8.co/games/Genshin-Impact/archives/304759, separately from events.
|
||||
One descriptive-agent robots request and one page request returned HTTP 200 during capture; no
|
||||
access workaround or repeated source fetch was used. The raw page and capture metadata are pinned
|
||||
as fixtures/genshin/game8-codes-2026-10-16.*, with ten independently counted current codes. The
|
||||
parser reads actual code inputs/current reward rows and excludes expired programme sections; a
|
||||
future-dated programme fixture variant verifies that still-current programmes are admitted.
|
||||
Unannounced expiry remains null. A printed calendar date is expiresOn, never a fabricated exact
|
||||
expiresAt instant. Attribution is retained on every code.
|
||||
|
||||
src/ingest/codes/registry.ts registers a count-only refresh source. The existing runner shares robots,
|
||||
six-hour floors, conditional requests, per-host spacing and snapshot gates across event/code sources.
|
||||
Event adapter schemas are unchanged. scripts/build-codes.ts builds data/codes.v1.json offline from
|
||||
snapshots or fixtures and preserves observation timestamps in snapshots/codes-first-seen.json.
|
||||
Code newness is per game; redemption is per local game/server account and never clears newness by
|
||||
itself. No code row is synthesized into the event feed.
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
# Approved redesign — implementation review, 2026-10-16
|
||||
|
||||
**Status: rejected by the owner for substantial divergence from the approved Round 7 markup.**
|
||||
The completion claims below describe the earlier implementation report and are withdrawn as
|
||||
evidence of design acceptance. Functional tests and overflow checks did not establish visual or
|
||||
interaction fidelity. A faithful markup-to-component correction is still required.
|
||||
|
||||
The approved [spec](../superpowers/specs/2026-10-16-ui-redesign-design.md) and
|
||||
[16-task plan](../superpowers/plans/2026-10-16-ui-redesign.md) are implemented in the working tree.
|
||||
Execution was Native. Nothing has been committed, pushed or published.
|
||||
|
||||
## Delivered
|
||||
|
||||
Relaxed (Round 7, default) and Structured (Round 6 B rail) share one reader/component tree; Appearance
|
||||
switches between them independently of theme, palette and Standard/Compact density. The redesign
|
||||
includes Routines and view pins, direct daily ticks, configurable grouping, multi-server progress,
|
||||
reset override/revert with accessible clock history, game colours/source credits, custom palettes,
|
||||
Automatic/IANA timezone, new and returning onboarding, compact source/new-event/code notices,
|
||||
Archive/story statistics, timed Done/Ignore/Undo, local rolling backups and recoverable restore.
|
||||
Settings About preserves the colophon; Changelog has its own page and no footer link.
|
||||
|
||||
The codes feed contains ten real Genshin codes from the pinned Game8 capture. Source fetching remains
|
||||
deterministic and shares the existing conduct gates; no additional community requests were needed
|
||||
while implementing or reviewing. Unstated expiry stays unknown. Codes newness and per-server
|
||||
redemption are separate. Manual refresh checks both feeds and discloses partial code-feed failure.
|
||||
|
||||
## Verification
|
||||
|
||||
- **1,587 tests pass**, zero failures, across 74 files. Strict TypeScript and whitespace checks pass.
|
||||
- The suite also runs without `public/` or `docs/` in the Docker COPY layout: 1,586 pass, one
|
||||
intentional README-only skip, zero failures. No tests depend on a preceding build.
|
||||
- Full offline build passes: 209 events across 20 games, ten codes, production JS/CSS/static shell.
|
||||
Final shell build `f5b25675010f` was loaded on a fresh origin (port 41880).
|
||||
- Chrome checks cover both interfaces, both themes, 1440/390 widths, Standard/Compact, reduced motion
|
||||
and an effective 200% CSS viewport. No horizontal page overflow or page errors in that matrix.
|
||||
- Browser journeys pass for migration, saved preferred Timeline, events-only setup, selectable empty
|
||||
tracking kinds, upcoming placement, isolation from unselected games, extra server with fresh state,
|
||||
direct ticks, reset override/revert/history, per-server redemption, Done/Ignore/Undo, unknown-end
|
||||
custom creation, real export download/upload/restore, backup preview/restore/Undo, custom palette,
|
||||
timezone selection/search, offline reload and the real service-worker update/reload handshake.
|
||||
- Two real browser tabs save concurrently with Web Locks explicitly disabled: IndexedDB serialization
|
||||
preserves both edits. Unit regressions cover stale progress fields and independent routine pins.
|
||||
- A fresh independent reviewer completed whole-change review and focused re-reviews. All important
|
||||
findings were fixed with reproductions; final review reports no remaining important findings.
|
||||
|
||||
## Review fixes and durable decisions
|
||||
|
||||
Deleted custom definitions no longer reappear from seen snapshots. Progress imports preserve local
|
||||
active reset configuration, retain imported clocks as history, and reuse those revisions on repeated
|
||||
imports. Opaque extensions survive subsequent transfers without duplicate accumulation. Timeline
|
||||
focus applies to routines as well as events; Ending soonest uses one global queue when reset strips
|
||||
are off. The browser fallback uses an IndexedDB transaction rather than unlocked whole-envelope
|
||||
writes. Account rebase preserves independent routine/pin edits and explicit retirement removal.
|
||||
|
||||
Original v1 bytes remain available after migration. Restore validates account/clock references and
|
||||
saves recovery before replacement. Setup completes before seen-history capture. Source diagnostics
|
||||
state what the feed records; absent failure reasons are described as unavailable, never guessed.
|
||||
|
||||
## Practical limits
|
||||
|
||||
Backups are browser-local and created while the app is used; they cannot recover storage a reader
|
||||
clears. Older completion IDs whose metadata was never retained remain recoverable raw data, but
|
||||
cannot produce invented archive descriptions or historical statistics. Codes currently have one
|
||||
registered game/source. External fonts have system fallbacks offline. Calendar-date code expiry is
|
||||
shown as a date without an invented instant. No accounts, remote sync or push notifications added.
|
||||
|
||||
## Captures inspected
|
||||
|
||||
[Relaxed, light, desktop](assets/2026-10-16-redesign/relaxed-light-1440.png) ·
|
||||
[Structured, dark, desktop](assets/2026-10-16-redesign/structured-dark-1440.png) ·
|
||||
[Structured, dark, phone](assets/2026-10-16-redesign/structured-dark-390.png)
|
||||
|
||||
Additional transient browser logs and captures are in `/tmp/redesign-browser-*` and
|
||||
`/tmp/redesign-final-*`; the facts above and representative images are recorded here for handoff.
|
||||
|
||||
|
||||
## Follow-up: first-visit HTTP/WireGuard startup failure
|
||||
|
||||
The owner reported the recovery screen on first visit through WireGuard `10.20.20.2`. The precise
|
||||
failure reproduced in Chrome at an ordinary HTTP hostname: `crypto.randomUUID` was undefined,
|
||||
initial account minting threw, and initialization returned the generic unavailable/saved-data error.
|
||||
Localhost-only verification had missed this because localhost is a browser secure context.
|
||||
|
||||
All reader ID consumers now use 128-bit `crypto.getRandomValues` through `state/reader/ids.ts`.
|
||||
Three new regressions failed before the fix and pass afterwards. Browser verification on an actual
|
||||
insecure HTTP origin passes both existing-save migration and fresh setup, ordinary edits, adding a
|
||||
server, reset override/revert, backups and reload; the original v1 bytes remain unchanged. Focused
|
||||
independent review found no important issues. The full suite now passes **1,590 tests** across 75
|
||||
files. Typecheck, production rebuild and whitespace checks pass. Rebuilt shell: `9752bd6bf1d2`.
|
||||
|
||||
The existing preview serves the rebuilt files; hard-refreshing bypasses the browser's cached JS.
|
||||
No storage deletion or identity remapping was performed.
|
||||
|
||||
|
||||
## Owner rejection: markup fidelity
|
||||
|
||||
Direct comparison confirms substantial divergence despite matching outer gutters/panels/fonts:
|
||||
|
||||
- Round 7's event-entry structure separates event content, a large deadline with supporting text,
|
||||
and chevron. Production reused EventRow's prior internal structure and decorated it with CSS.
|
||||
- Round 7's Routines uses game bands and aligned columns for progress, cycle/reset, pins and menus.
|
||||
Production renders a flattened library with checkbox options and no equivalent table structure.
|
||||
- Round 7's settings sidebar includes individual game entries with descriptions, leading into their
|
||||
profiles. Production substitutes a generic Your games page and game selector.
|
||||
- Round 7's Timeline places routine periods/progress/reset markers on the shared time axis.
|
||||
Production appends ordinary routine controls below event timelines and uses textual reset strips.
|
||||
- Round 7's Archive story includes interactive per-game outcome breakdowns. Production substitutes
|
||||
per-game text totals.
|
||||
- The approved header has navigation counts and a dedicated Settings placement. Production uses
|
||||
the simpler generic navigation and a different header summary.
|
||||
|
||||
References: design/mockups/round7/converged.html (final CSS from line 1003 onward and final renderer
|
||||
overrides); production ReaderApp.tsx, EventRow.tsx, TimelinePage.tsx, RoutinesPage.tsx,
|
||||
SettingsLayout.tsx, GameSettings.tsx, ArchiveStory.tsx. Earlier render functions/CSS in the mockup
|
||||
are superseded by later overrides and must not be used in isolation.
|
||||
|
||||
Root delivery error: the implementation preserved/reused existing presentation components and
|
||||
added selected reference styling instead of faithfully translating the approved rendered markup.
|
||||
Verification checked functionality and overflow without comparing equivalent reference/production
|
||||
screens and interactions. The final review concentrated on data preservation and did not close that
|
||||
design-fidelity gap. The owner should not have had to identify it after a completion claim.
|
||||
|
||||
No implementation edits or data resets were made during this rejection audit. Existing storage and
|
||||
HTTP fixes remain in place. Required correction: use the approved rendered markup, hierarchy and
|
||||
interactions as the presentation contract, then connect real reader data and compare matching states.
|
||||
@@ -0,0 +1,167 @@
|
||||
# Routine redesign: Round 4 review
|
||||
|
||||
This records the owner's decisions from three mockup rounds and the subsequent review on
|
||||
2026-10-16. These are proposed product changes, **not shipped behaviour**. The implementation spec
|
||||
and migration plan come after review of this combined prototype.
|
||||
|
||||
## Review artifact
|
||||
|
||||
Open [the standalone Round 4 prototype](../../design/mockups/round4/converged.html) in a browser.
|
||||
The review copy is also placed in `~/gacha-mockups/round4/converged.html`, linked from the existing
|
||||
Samba index. Earlier rounds remain intact there.
|
||||
|
||||
The prototype extends the Round 3 archive variant, keeping its ruled timetable visual language and
|
||||
routine library. It is deliberately separate from the production app. Its storage namespace is
|
||||
`event-clock:mockup:round4:v1`, never a production `gacha-tracker` key. Reset demo restores sample
|
||||
state; reloading otherwise keeps density, choices and progress where browser storage is available.
|
||||
|
||||
## Decisions to preserve
|
||||
|
||||
- Checklist and Timeline retain their names. Routines and Archive have their own tabs, as does
|
||||
Settings. Settings uses a sidebar with General first.
|
||||
- Routines owns follows, individual editing and independent Checklist/Timeline pins. Built-ins do
|
||||
not appear under Your own events and games. The library puts Create your own routine first.
|
||||
- Checklist keeps compact per-game routine summaries in its rail. Focusing a game expands its
|
||||
routines; All collapses them. Remove the unrelated Your own events callout from the rail.
|
||||
- The main event list has two densities: Standard by default, with wrapping titles, breathing room
|
||||
and supporting copy, and Compact using the dense table. Density is remembered and independent of
|
||||
routine pins, filters, sort order and Timeline. Both densities open the same event detail.
|
||||
- Game setup offers composable Events / Dailies / Weeklies & monthlies / Cycles shortcuts; individual
|
||||
follows remain editable in Routines. Events is a visibility choice, rather than a routine.
|
||||
- Each game can have multiple servers, with separate routine and daily progress. An additional
|
||||
server starts with events only and fresh routine choices; it does not copy the first server's
|
||||
follows, pins or ticks.
|
||||
- Onboarding begins with events only. Explain each type in plain language, especially cycles:
|
||||
routines following the game's own cadence, such as a mode resetting every fourteen days. Ask
|
||||
whether Checklist or Timeline should open first. Defer pin placement until readers have seen the
|
||||
views.
|
||||
- Returning readers receive an introduction to the new layout in either main view, with existing
|
||||
choices and progress preserved. Changelog remains accessible afterward.
|
||||
- Codes and About live beside Setup in the game's settings area. In-app notices appear in both
|
||||
main views. New means discovered since the reader last viewed that game's codes, not unredeemed.
|
||||
Viewing clears the new indicator without marking redemption. Redemption is separate per server.
|
||||
- Archive defaults to per-game groups, with the ledger's story panel and small statistics above
|
||||
them. History timeline is an additional view. Records remain in the save, with description,
|
||||
source and progress available after the live source changes.
|
||||
- Done and Ignore immediately save an archive record, then retain the active row for about 1.5
|
||||
seconds with Completed/Ignored · Moved to Archive before fading and closing the gap. Undo remains
|
||||
available afterward; Restore also lives in Archive. Reduced motion keeps the confirmation delay
|
||||
and removes the fade. Unknown end dates stay unknown in archived records.
|
||||
- Expired unfinished events belong in Archive as unfinished, rather than silently disappearing.
|
||||
- Timeline uses full rows for routines. It offers Ending soonest and By game. Separate reset strips
|
||||
are optional and sit directly below their own game's events on the same axis. In separate-strip
|
||||
mode, Ending soonest orders game groups by their next deadline to preserve this adjacency.
|
||||
|
||||
## What to review
|
||||
|
||||
1. Compare the same 21 events in Standard and Compact; focus Genshin and inspect its routine rail.
|
||||
2. Complete or ignore an event, observe confirmation/fade, Undo, then open its saved Archive detail
|
||||
and Restore it. Try an event with no announced end.
|
||||
3. Follow/unfollow a routine from the library and pin it independently to each view.
|
||||
4. Add a server in game settings and confirm the other server's choices and ticks stay separate.
|
||||
5. Open Codes, mark one redeemed on a single server, and simulate a new arrival from the demo bar.
|
||||
6. Compare the per-game Archive with History timeline, and check both timeline reset layouts.
|
||||
7. Walk through New user, then Returning user with Timeline as the default.
|
||||
|
||||
## Owner's feedback after Round 4
|
||||
|
||||
The combined prototype was received positively. Further requirements:
|
||||
|
||||
- Restore the richer statistics from Round 3 H's Ledger with a story. Round 4 reduced that panel
|
||||
to completed/ignored/unfinished counts, which lost what the owner liked. Keep the per-game
|
||||
archive as the default body, but restore the completion percentage for the current month with
|
||||
an overall comparison, current/best completion run, logged event check-in days, and unfinished
|
||||
events with near-miss detail. Retain the compact per-game outcome breakdown from that panel.
|
||||
Ignored events must not be counted as failures in the completion percentage. Definitions and
|
||||
scope labels must be explicit: recorded archive history is not all play history, event check-in
|
||||
totals are not unique calendar days, and incomplete/unknown progress cannot support a fabricated
|
||||
near-miss claim. These statistics should use saved progress and dates, not invented telemetry.
|
||||
|
||||
- Keep the colophon, potentially in Settings, and add an app-level About section distinct from a
|
||||
game's About tab. Preserve source/studio credits, author and contributor acknowledgements and
|
||||
useful project links. Moving credits must not hide the feed-age and stale-source disclosures
|
||||
that readers need while looking at deadlines.
|
||||
- The grouped routine summaries are easier to scan but add friction to ticking daily chores.
|
||||
Explore a separate daily panel with directly available one-click ticks, selectable as an
|
||||
alternative to grouping dailies with the other routines. Keep server progress separate and
|
||||
avoid showing the same tick in both panels. Placement and default are not yet settled.
|
||||
- Appearance should support colour schemes in addition to dark/light/system. The choice between
|
||||
curated palettes and reader-edited colours remains open. Any scheme must preserve game identity,
|
||||
urgency meanings, and readable contrast in both modes.
|
||||
- Each game's Settings → Setup includes a custom game-colour control, a preview and Reset to
|
||||
default. Remember the override and apply it consistently wherever that game appears, including
|
||||
Checklist, Timeline, Routines and Archive. It belongs to the game, shared across its servers,
|
||||
separately from the global interface colour scheme. Use the existing readable-hue approach to
|
||||
preserve legibility in dark and light appearances without changing the reader's saved base
|
||||
colour. Game colour expresses identity; urgency colours retain their meaning. Export/import
|
||||
must retain these overrides in the eventual implementation.
|
||||
- Clarify the additional-server action as simultaneous account tracking. Use “Track another
|
||||
server” with helper text: “Play on more than one server? Add your other server to track both
|
||||
accounts separately.” Keep changing the existing server as a distinct control. The added-server
|
||||
setup still starts with fresh routine choices and separate progress, as previously agreed.
|
||||
- Standard event rows without descriptions currently feel too empty. Size rows to their actual
|
||||
content: reserve no description line when absent, reduce vertical padding for title-only rows,
|
||||
and keep the countdown/meter stack from imposing a description-sized minimum height. Preserve
|
||||
wrapping titles and comfortable tap targets; Standard remains roomier than Compact without
|
||||
forcing every event to the same tall height. Do not invent fallback description text to fill
|
||||
the space.
|
||||
- Region & time must let the reader select their display timezone. Automatic, using the browser's
|
||||
timezone, is the default; a manual selection is remembered and can be returned to Automatic.
|
||||
Display named IANA zones with their current UTC offsets, so daylight-saving changes follow the
|
||||
selected zone rather than a fixed offset. This affects displayed dates/times, not the server
|
||||
clocks that determine deadlines, reset boundaries and stored game-day keys. Reader-authored
|
||||
event entry must explicitly identify the timezone used to interpret its input.
|
||||
- In onboarding's What do you want to track step, all type choices stay selectable even when a
|
||||
game has no current matching routines or windows. Explain the empty state beside the choice;
|
||||
distinguish no current active window from no supported built-in routine. An empty result is not
|
||||
a disabled control. Retain the reader's selected tracking intent rather than deriving it solely
|
||||
from which routines happen to exist today. The implementation spec must reconcile this intent
|
||||
with the earlier shortcut-only composition model and define how newly supported routines are
|
||||
offered without silently expanding what existing readers track.
|
||||
- Initial setup also asks for default game server, preferred appearance and whether to show
|
||||
events that have not started. The selected server initializes game setup and individual games
|
||||
can override it. Appearance includes Dark / Light / System and the agreed colour-scheme choices
|
||||
once those are settled. Upcoming events remain off initially, consistent with the existing
|
||||
default, until the reader selects otherwise. The previously agreed Checklist/Timeline default
|
||||
question remains. Present these as a short preferences step rather than crowding the tracking
|
||||
matrix with unrelated controls.
|
||||
|
||||
## Prototype boundaries and implementation work still ahead
|
||||
|
||||
- “Now” and reset clocks are fixed for review. The final app must use the existing per-game reset
|
||||
rules and actual region-specific end times.
|
||||
- Most event content was carried over from the earlier prototypes. Codes, historical archive
|
||||
records, version groups and some descriptions are illustrative. No new source fetch runs here.
|
||||
Live-list source links are matched by title against the existing local feed; unmatched sample
|
||||
events receive no invented source URL.
|
||||
Game8's supplied Genshin code page is a source-shape reference, not an implemented adapter.
|
||||
- Only in-app code notices are proposed. Push, email and background notifications remain outside
|
||||
the product scope.
|
||||
- Some inherited controls remain placeholders: backup and portions of own-event/routine editing.
|
||||
- The archive snapshot works within this prototype's save. Production needs an explicit snapshot
|
||||
retention/export format and a policy for capturing events before they drop from the feed.
|
||||
- Production needs a reviewed migration for existing progress into per-server storage; no existing
|
||||
event ID, daily ID or day key may be changed casually. The archive and code state also need a
|
||||
documented export/import contract. This artifact is not a storage implementation to copy.
|
||||
- `docs/PRD.md`, `docs/DATA-MODEL.md`, `docs/ARCHITECTURE.md`, `docs/DESIGN.md` and the matching
|
||||
AGENTS guidance must be updated with the eventual implementation. They describe the shipped app
|
||||
today, so this review record does not rewrite them as though the redesign had landed.
|
||||
|
||||
## Verification
|
||||
|
||||
Browser verification and screenshots are performed with scratch-installed puppeteer-core and
|
||||
Chrome, at 1440px and 390px. The prototype needs no Bun build or production feed changes. The test
|
||||
journeys cover density parity, navigation, completion/ignore delay and Undo, archived detail and
|
||||
Restore, separate code visibility/redemption, server setup, reset-strip adjacency, onboarding,
|
||||
returning users, persistence, reduced motion and unknown end dates.
|
||||
|
||||
Both width passes completed with no JavaScript errors and no page-level horizontal overflow in
|
||||
the checked screens. The initial mobile pass caught a confirmation notice intercepting Archive
|
||||
row taps; informational notice surfaces now let pointer events through while Undo remains a real
|
||||
button. An early verification-script failure also tried to open a Star Rail event after onboarding
|
||||
had selected only Genshin; the scenario now resets sample state before testing an unknown end.
|
||||
|
||||
Impeccable's mechanical detector reports palette, typography and size differences against the
|
||||
**shipped** DESIGN.md, plus inherited stripe treatments. The new Barlow timetable appearance is
|
||||
intentional and selected in earlier rounds; this prototype does not rewrite the shipped design
|
||||
reference or add detector suppressions. Its visual language remains subject to this review.
|
||||
@@ -0,0 +1,112 @@
|
||||
# Routine redesign: Round 5 review
|
||||
|
||||
This is a review prototype, not a production release or an approved implementation spec. It
|
||||
combines the owner's feedback after Round 4, recorded in
|
||||
[the preceding review](2026-10-16-redesign-round4.md), and the subsequent freshness, backup and
|
||||
focus-bar requests.
|
||||
|
||||
Open [Round 5](../../design/mockups/round5/converged.html), or its copy at
|
||||
`~/gacha-mockups/round5/converged.html` through the shared index. Earlier rounds remain unchanged.
|
||||
|
||||
## What changed
|
||||
|
||||
- **One-click dailies:** an optional panel exposes daily ticks directly, separately per server.
|
||||
The alternative groups dailies with the routine summaries. A daily appears in only one place;
|
||||
pins still decide which dailies appear. The separate panel is the prototype's starting choice,
|
||||
to test the owner's request for immediate access; this default remains reviewable.
|
||||
- **Focus alternatives:** a labelled game toolbar is the starting choice. The review bar's Focus
|
||||
selector also offers a compact game switcher and a picker at the top of the Checklist rail.
|
||||
Each changes the same focus state and counts, and preserves auto-expanding focused routines.
|
||||
Timeline retains a visible toolbar/switcher rather than acquiring a Checklist rail.
|
||||
- **Content-sized Standard rows:** events lacking descriptions use less vertical padding and
|
||||
omit the segmented meter. They retain a wrapping title, countdown and tap target. No filler
|
||||
descriptions are added.
|
||||
- **About and colophon:** Settings → About Event Clock retains the author, source communities,
|
||||
studio credits, acknowledgements, reset-clock reference, disclaimer and project links. The
|
||||
footer links there. Source credits come from the existing local feed, not the selected games.
|
||||
- **Freshness:** Checklist and Timeline visibly state data age and warn about older schedules for
|
||||
the games switched on. Source breakdown distinguishes last successful check from last content
|
||||
change and explains unchanged pages, overdue pulls and never-fetched data. Unknown causes are
|
||||
described as unreported, not invented. Settings → Data & sources exposes the same information.
|
||||
The review bar offers Current / Some stale / All stale / Never fetched / Offline. These are
|
||||
labelled illustrative states; no real fetch runs. Check for new data demonstrates a no-newer-feed
|
||||
result and is disabled offline. The headline data timestamp covers the demo feed as a whole;
|
||||
warnings and named source rows cover selected games. No build timestamp is used.
|
||||
- **Appearance:** Dark / Light / System plus three curated scheme previews, Slate / Warm / Plum.
|
||||
This answers the palette request for review, not the unresolved possibility of a fully editable
|
||||
interface palette. Semantic deadline colours remain separate from game identity.
|
||||
- **Game colour:** Setup adds a colour picker, hex input, preview and Reset to default. An override
|
||||
applies to all the game's servers and all its views. The stored base colour remains unchanged
|
||||
while its rendered colour is adjusted for contrast in the chosen appearance.
|
||||
- **Timezone:** Automatic is the default; named zones can be selected and searched in Region &
|
||||
time. Dates use the selected zone, including daylight saving, without changing server reset
|
||||
boundaries. The prototype's per-game reset clocks remain simplified.
|
||||
- **Additional servers:** “Track another server” explains simultaneous separate account tracking.
|
||||
Added servers still start with fresh routine choices and progress.
|
||||
- **Onboarding:** initial preferences now ask default server, mode/scheme, timezone and whether
|
||||
upcoming events should appear. Game selection, tracking types and Checklist/Timeline default
|
||||
follow. All tracking types remain selectable even if no matching built-in exists. Availability
|
||||
is explained, and selected intent is saved separately from actual follows. The no-matching-types
|
||||
message does not incorrectly call that selection events only. New supported built-ins are
|
||||
described as offers for review rather than automatic extra work for existing readers.
|
||||
- **Archive story:** restores monthly/overall completion percentages, current/best completion
|
||||
run, logged event check-ins and unfinished/near-miss counts, plus per-game outcome bars, above
|
||||
the default per-game archive. Ignored events are excluded from completion-rate denominators.
|
||||
Progress and statistics derive from illustrative saved archive records, and scope is labelled.
|
||||
History timeline remains an alternate view.
|
||||
- **Automatic backup history:** Backup shows seven daily, four weekly and six monthly snapshots,
|
||||
with latest-per-period compression. The retained historical examples are labelled sample; today's
|
||||
snapshot updates from the demo's own state. Restore previews game/routine/archive/progress counts
|
||||
and preserves current data as a recovery copy first. Undo last restore is available. Manual
|
||||
Back up now and demo JSON export/import live alongside the automatic history.
|
||||
|
||||
## Backup semantics used for this review
|
||||
|
||||
The most recent seven days retain one latest snapshot per day. Older snapshots fold into four
|
||||
consecutive seven-day windows. Older records then fold into six calendar-month buckets, keeping
|
||||
the latest snapshot in each. This is up to seventeen retained snapshots, plus a recovery copy from
|
||||
the last restore. No snapshot is invented for a day the reader never opened the app.
|
||||
|
||||
The demo clock is fixed and its bucket calculations use UTC. Production needs to settle and
|
||||
document the stable calendar basis independently of display-timezone changes, handle storage
|
||||
capacity/failures, validate restore files, and use the real export contract. Backups are browser
|
||||
local and are created while the app is used; they cannot be promised for days when it stays closed.
|
||||
Export remains the way to keep a copy outside that browser or move to another device.
|
||||
|
||||
## How to inspect
|
||||
|
||||
1. Compare focus options in the review bar. Focus Genshin; tick EU and Asia dailies separately.
|
||||
2. Compare Standard/Compact, especially rows without descriptions, and switch the daily layout.
|
||||
3. Use the Data selector to inspect every freshness state, then expand Why the data is older.
|
||||
4. Open About, Data & sources, Region & time and Appearance. Change timezone, scheme and game colour.
|
||||
5. Open Archive to inspect richer stats and History timeline.
|
||||
6. Open Backups, review a monthly sample, restore it, then Undo last restore. Demo export files are
|
||||
separate from the production app's format and storage.
|
||||
7. Open New user. Choose preferences and Genshin, then select Cycles despite no matching built-in.
|
||||
8. Set Timeline as the default and use Returning user to check the introduction appears there.
|
||||
|
||||
## Verification and boundaries
|
||||
|
||||
Chrome journeys at 1440px and 390px exercised direct daily ticks, layout choices, focus alternatives,
|
||||
freshness variants, credits, timezone persistence, light/dark/system and schemes, game-colour reset,
|
||||
fresh server setup, Archive stats, backup restore/recovery, onboarding with an empty type,
|
||||
returning-reader introduction and completion/Undo. Both passes had no JavaScript errors and no
|
||||
page-level horizontal overflow in the checked screens. A follow-up checked latest-per-period
|
||||
retention across 400 simulated days, all-games empty-type toggles, and desktop sticky toolbar/rail
|
||||
separation.
|
||||
|
||||
The mechanical design detector reports 30 findings, chiefly differences from the shipped palette,
|
||||
Barlow typography and size/radius ramp, plus inherited archive stripe treatments. These are review
|
||||
artifacts in the owner-selected replacement visual direction; no production design reference or
|
||||
detector suppression was changed to make the prototype appear to match the shipped app.
|
||||
|
||||
An inherited Round 4 Reset handler initially discarded the new state fields. Round 5 now owns
|
||||
reset initialization and its browser check passes. The active prototype data namespace is
|
||||
`event-clock:mockup:round5:v1`; production localStorage keys and progress are untouched.
|
||||
|
||||
The existing demo library/create form, independent pins, completion confirmation/fade/Undo,
|
||||
Archive restore and code-newness/redemption distinctions remain. Some inherited own-event editors
|
||||
are still placeholders. Codes, old Archive history, backup history and source health are sample
|
||||
content. Real parsers, source refreshes, app storage migrations and production backup machinery are
|
||||
not implemented by this artifact. The shipped specification and design documents remain about the
|
||||
shipped app until the redesign's spec and implementation are reviewed.
|
||||
@@ -0,0 +1,105 @@
|
||||
# Routine redesign: three quieter layouts
|
||||
|
||||
Review artifacts, not a production release. This round responds to the owner's concern that
|
||||
Round 5's focus toolbar and stale-data notice occupied too much space, and incorporates the
|
||||
additional feedback received while building the alternatives.
|
||||
|
||||
Open [the comparison index](../../design/mockups/round6/index.html). The shared copy lives at
|
||||
`~/gacha-mockups/round6/index.html`; earlier rounds stay available. Each design is a complete
|
||||
standalone HTML prototype with the same sample event data and the shared features below.
|
||||
|
||||
## The alternatives
|
||||
|
||||
- **A — Inline desk:** retains the left routine/daily rail. Game focus is a small selector beside
|
||||
the event heading, and freshness is a single understated line. Source reasons are one click away.
|
||||
- **B — Game desk:** puts game focus, daily ticks and a short source-status report in the rail.
|
||||
There is no full-width freshness or focus band above the event list. It reserves more attention
|
||||
for the list; its tradeoff is a more populated rail that stacks before events on mobile.
|
||||
- **C — Open ledger:** replaces the rail with a full-width event list, a brief next-deadline row,
|
||||
direct daily ticks in a horizontal strip, and a disclosure for other pinned routines. Game focus
|
||||
and a short freshness report sit with the event heading. It gives titles the most width; the
|
||||
routine controls scroll with the list.
|
||||
|
||||
The chosen timetable appearance is preserved. These compare structure and interaction rather than
|
||||
asking the owner to pick a new visual identity again.
|
||||
|
||||
## Shared decisions implemented for review
|
||||
|
||||
- **Changelog is its own Settings page.** The owner explicitly chose this over a main app tab,
|
||||
and explicitly declined a footer link. Remove the awkward Changelog button from About, remove
|
||||
it from the footer, and render release notes in the page rather than the old overlay. Existing
|
||||
returning-reader news links lead to that Settings page.
|
||||
- **Freshness remains honest and available.** Keep the full data timestamp and age in the footer,
|
||||
scope warnings to selected games, and expose successful-check/content-change times and reasons
|
||||
in Data & sources. Older source data is also explained in the event's detail. Unknown causes
|
||||
remain unreported, not invented. The review bar's Data selector tests the illustrative scenarios.
|
||||
- **Dailies on Checklist belongs in Routines as well.** Routines → Checklist display controls the
|
||||
same preference as the daily panel shortcut and Appearance. Choose Separate panel or Grouped
|
||||
with routines. Independent pins still govern whether a routine appears.
|
||||
- **Checklist routine groups have three behaviours:** Collapsed by default, Expanded by default
|
||||
(still collapsible), and Always expanded (no collapse buttons). Focusing a game expands its
|
||||
routines. The wide layout also honours this for its enclosing routine section.
|
||||
- **Numeric fields show the native stepper.** Browser increase/decrease controls remain visible
|
||||
and use step one, as requested. They are not replaced by a separate custom spinner.
|
||||
- **Appearance includes Custom.** Edit background, surface, text and interface accent separately
|
||||
for light and dark. Stored choices are retained while preview text/surfaces are adjusted for
|
||||
contrast. Game identities and deadline urgency remain separate from the custom interface accent.
|
||||
Individual game colours retain their own control and reset.
|
||||
- **Reset timing can be overridden per game/server.** Game Setup and Region & time expose Automatic
|
||||
versus a custom server-local hour/minute, with Revert to Automatic. The prototype applies the
|
||||
override consistently to daily/routine periods and reset summaries. Reader-authored routines
|
||||
with their own explicit reset retain it. The automatic source clocks remain simplified here;
|
||||
this is not a production reset migration.
|
||||
- **A game's About names its sources.** Links come from that game's entries in the existing local
|
||||
feed, including separate event/banner/pass sources. Use readable schedule labels and thank the
|
||||
editors. This differs from the global About's full, unfiltered colophon.
|
||||
- **Remove Done and ignored events from Lists.** That row only linked to Archive and was not a
|
||||
setting. Archive keeps its own main navigation tab.
|
||||
- **Backup rows say View backup.** They open a preview headed Backup from [date], showing the
|
||||
snapshot's contents. Restore this backup is the explicit action there; the current state is
|
||||
preserved as a recovery copy. The seven-day/four-week/six-month history is retained.
|
||||
- **Returning readers get a guided introduction.** The review bar's Returning user control opens
|
||||
a short welcome in whichever view is preferred, with Take the quick tour and Keep browsing.
|
||||
Four steps visit Routines, Checklist, Archive and Settings. Back and Skip are available; finishing
|
||||
returns to the preferred view. Games, follows and progress remain intact. Production will bind
|
||||
this to a saved release marker, so it is offered once rather than every load.
|
||||
- **Upcoming events moves to What do you want to track?** It is no longer in the initial preference
|
||||
step. The initial preferences retain default server, appearance and timezone; all type choices
|
||||
remain selectable and explained even when no matching built-in exists.
|
||||
|
||||
Standard/Compact density, richer Archive statistics and the history timeline, separate server
|
||||
progress, code-newness versus redemption, completion confirmation/fade/Undo, timezone and the
|
||||
existing routine library/create form remain available in every alternative.
|
||||
|
||||
## Boundaries
|
||||
|
||||
Each alternative uses its own `event-clock:mockup:round6:<letter>:v1` browser namespace. No production
|
||||
keys, parsers or feed data are changed. Source-health states, codes, archived history and historical
|
||||
backups are illustrative. Clock overrides affect the demo's period calculations, not any real stored
|
||||
game-day keys. Production must review migration and the preservation of historical ticks before
|
||||
introducing reader overrides. These are disposable prototypes, not code to transplant into the app.
|
||||
|
||||
## Verification record
|
||||
|
||||
The browser pass checks all three designs at 1440px and 390px: focus and daily controls, native
|
||||
numeric stepping, all disclosure modes, source reasons in event detail, the Changelog page and its
|
||||
absence from About/footer, custom-palette contrast, reset override/revert, per-game source credits,
|
||||
Lists cleanup, backup labels, the moved upcoming option, and the returning-user tour preserving
|
||||
progress. Screenshots cover each main layout plus the new shared pages.
|
||||
|
||||
The first mobile pass found a backup-preview smooth scroll continuing after navigation, allowing a
|
||||
subsequent automated tap to hit the fixed review bar. The preview now scrolls instantly, avoiding a
|
||||
pending animation against a different screen.
|
||||
|
||||
The confirming pass completed all six combinations of design and viewport with no JavaScript
|
||||
errors or page-level horizontal overflow in the checked screens. Custom-palette checks included
|
||||
equal chosen background/text colours and confirmed the rendered text was adjusted to at least
|
||||
4.5:1. Per-server override checks exercised 05:30, verified the 90-minute change from 04:00, then
|
||||
returned to Automatic. The tour returned a Timeline-default reader to Timeline with saved games,
|
||||
follows and progress unchanged.
|
||||
|
||||
Design-hook triage: retain the owner-selected Barlow typography. Narrow value exceptions for that
|
||||
font are scoped to `design/mockups/round6/index.html` only, with evidence in `.impeccable/config.json`.
|
||||
No whole-file or whole-rule exclusions are added. The shipped DESIGN.md remains the production
|
||||
reference; prototype differences in palette/size and inherited archive treatments remain review
|
||||
findings rather than being suppressed broadly.
|
||||
@@ -0,0 +1,80 @@
|
||||
# Routine redesign: one airier design
|
||||
|
||||
**Later owner decision:** retain two interfaces after all: Round 7 and Round 6 **B**, selected
|
||||
in Settings. The earlier single-interface direction below records the mockup review, not the
|
||||
final implementation decision. Replace “Older schedules” with “Event data may be out of date”.
|
||||
See the [production redesign specification](../superpowers/specs/2026-10-16-ui-redesign-design.md).
|
||||
|
||||
Review prototype, not shipped behaviour. Open
|
||||
[the unified mockup](../../design/mockups/round7/converged.html), also copied to
|
||||
`~/gacha-mockups/round7/converged.html` through the shared index.
|
||||
|
||||
## The owner's correction
|
||||
|
||||
Round 6's three alternatives were rejected. The owner asked for:
|
||||
|
||||
- Older-data notices in the same structure as New since you last looked, appearing only when
|
||||
games have older data.
|
||||
- The current production game's focus-pill structure, placed at the top of the left rail as in B.
|
||||
- A more airy, easy-to-read design informed by the original
|
||||
`~/gacha-mockups/c-one-due-list.html`.
|
||||
|
||||
The initial idea of a Simple mode or a spacing toggle was then explicitly reconsidered: the owner
|
||||
does not want two distinct UIs. Carry the spirit of C into one unified interface instead.
|
||||
|
||||
## What this mockup does
|
||||
|
||||
**A shared updates area.** New code notices and Older schedules use two compact rows in one
|
||||
component above the Checklist's event list and above Timeline. The older row lists affected games
|
||||
and links to Details & reasons; no full-width health banner or rail status panel remains. It is
|
||||
absent when the selected games have current sources. If there are no new codes either, the whole
|
||||
updates area disappears. Source reasons remain available in Data & sources and event detail; the
|
||||
full feed timestamp stays in the footer on every load. Scope is the games the reader has switched
|
||||
on, rather than only the temporary focus. Repetitive older-data labels on individual list rows are
|
||||
removed because the updates row already names those games.
|
||||
|
||||
**The existing focus behaviour.** `src/client/components/GameFocus.tsx` is the reference: All and
|
||||
game pills, game hues, outstanding counts, and Next progressing through games and then back to All.
|
||||
Tapping the focused pill returns to All. Pills wrap in their own panel at the top of the Checklist
|
||||
rail; they are absent for a single-game setup. Timeline uses the same pills above its lanes. Focus
|
||||
never changes which games are followed.
|
||||
|
||||
**One visual world.** The original C informs separated panels, quieter rules, softened surfaces,
|
||||
more room around controls and a warmer reading rhythm. Bricolage Grotesque and Figtree replace the
|
||||
compressed timetable typography consistently across the prototype, including settings and forms.
|
||||
The rail and event list have a real gutter; focus, deadline, dailies and routines have separated
|
||||
surfaces. Light mode uses warm paper and dark mode a softer charcoal. No Simple/Detailed mode or
|
||||
global spacing toggle is added. Standard/Compact remain two row densities of this same appearance.
|
||||
Rows with no description remain shorter; comfortable layout is not a fixed tall event height.
|
||||
|
||||
Direct daily ticks, routine disclosure choices, independent pins, custom palettes, per-game colours
|
||||
and reset overrides, source links and thanks, Changelog in Settings, Archive statistics and history,
|
||||
backup history/recovery, timezone and both onboarding flows remain available. The daily-panel layout
|
||||
shortcut is removed from the Checklist rail to reduce controls there; its Routines and Appearance
|
||||
settings continue to edit the same preference.
|
||||
|
||||
## Validation
|
||||
|
||||
Chrome journeys at 1440px and 390px passed with no JavaScript errors and no page-level horizontal
|
||||
overflow in the checked views. They cover conditional/scope-aware notices, empty updates, focus
|
||||
toggle/advance, spacing, routine expansion, reset override/revert, source credit links, custom
|
||||
scheme controls, light-theme game-colour contrast on ground and panel, Changelog location, backup
|
||||
history, Archive stats, Timeline, completion/fade/Undo and onboarding. Contrast adjustment now
|
||||
considers both panel and page grounds, while retaining saved base game colours.
|
||||
|
||||
Screenshots were inspected for Checklist in both appearances, Routines, Data & sources, Archive
|
||||
and Timeline. The first verification script used a nonexistent review-bar Settings shortcut; it
|
||||
was corrected to use the actual Settings tab. No product change was needed for that script error.
|
||||
|
||||
The mechanical design check flags differences from the **shipped** DESIGN.md in palette, type
|
||||
size, radius and inherited archive treatments. Those remain review findings, not broad suppressions.
|
||||
The intentional Bricolage font exception is scoped to this one prototype file, with rationale in
|
||||
`.impeccable/config.json`. The production visual reference is not rewritten before implementation.
|
||||
|
||||
## Boundaries
|
||||
|
||||
The namespace is `event-clock:mockup:round7:v1`. Earlier mockups and production progress remain
|
||||
unchanged. Historical records, codes and source health are illustrative; clocks are fixed and
|
||||
automatic reset defaults simplified. No source requests or production parser/storage changes run
|
||||
here. This is a disposable visual review artifact; the redesign still needs a reviewed production
|
||||
specification and migration plan.
|
||||
@@ -0,0 +1,101 @@
|
||||
# Redesign fidelity correction — 2026-10-17
|
||||
|
||||
> **Owner rejected this implementation after browsing it:** “This is still not even close to the
|
||||
> mockup.” The completion claim is withdrawn. Screenshots and review verdicts below are historical
|
||||
> evidence of the rejected attempt, not acceptance. Continue from
|
||||
> [the second-rejection handoff](../handoffs/2026-10-17-redesign-second-rejection-handoff.md):
|
||||
> launch the current server, then ask the owner for the biggest differences before further UI edits.
|
||||
|
||||
The owner asked to repair the rejected implementation against Round 7 Relaxed and Round 6 B
|
||||
Structured, then explicitly made **Structured the default**. Existing saved Relaxed choices remain
|
||||
valid. This correction is uncommitted in the existing checkout; no branch, publication or data-source
|
||||
refresh was performed.
|
||||
|
||||
## What changed
|
||||
|
||||
- Checklist uses dedicated reference-shaped event rows and next-deadline panel, with separate copy,
|
||||
countdown, supporting date, segmented meter and detail chevron. Header counts and Settings placement
|
||||
follow the reference. Both interfaces retain the owner-approved focus pills.
|
||||
- Routines has By reset/By game bands, aligned game/routine/progress/view-pin/menu columns, live totals,
|
||||
direct daily status, amount bars/inputs, library and a native custom-routine drawer. Bulk pins combine
|
||||
writes per account. Multi-server row identity includes both account and routine.
|
||||
- Timeline plots event spans and routine periods on one axis with frozen labels, progress fill and
|
||||
reset markers. In-progress bar labels remain visible after scrolling. Deadline ordering includes
|
||||
routine resets, and separate reset strips remain available.
|
||||
- Settings restores separate Default view and Your own events and games pages, game profiles, tracking
|
||||
summaries and Other games. Profiles follow tracking → servers → colour → reset timing. A server
|
||||
selector above tracking keeps choices independent without duplicating tall account panels.
|
||||
- Archive restores the story, interactive outcome bars, game sidebar, saved rows and history timeline.
|
||||
Its detail dialog reads saved metadata, original clock region, notes, days and amounts. It does not
|
||||
open the live progress editor or replace historical state with the current clock.
|
||||
- Structured defaults agree across prepaint, normalization, setup and applied appearance. No IDs,
|
||||
localStorage key spaces, migrations or ingestion rules were changed by this correction.
|
||||
|
||||
## Reference comparisons
|
||||
|
||||
Images are in [the evidence directory](assets/2026-10-17-fidelity/). Representative matched views:
|
||||
|
||||
| View | App | Approved reference |
|
||||
| --- | --- | --- |
|
||||
| Structured Checklist | [Desktop](assets/2026-10-17-fidelity/app-structured-dark-1440.png) | [Desktop](assets/2026-10-17-fidelity/reference-structured-dark-1440.png) |
|
||||
| Relaxed Checklist | [Desktop](assets/2026-10-17-fidelity/app-relaxed-dark-1440.png) | [Desktop](assets/2026-10-17-fidelity/reference-relaxed-dark-1440.png) |
|
||||
| Relaxed mobile | [390px](assets/2026-10-17-fidelity/app-relaxed-dark-390.png) | [390px](assets/2026-10-17-fidelity/reference-relaxed-dark-390.png) |
|
||||
| Routines | [Structured](assets/2026-10-17-fidelity/app-structured-routines.png) | [Structured](assets/2026-10-17-fidelity/reference-structured-routines.png) |
|
||||
| Timeline | [Structured](assets/2026-10-17-fidelity/app-structured-timeline.png) | [Structured](assets/2026-10-17-fidelity/reference-structured-timeline.png) |
|
||||
| Game Setup | [Relaxed](assets/2026-10-17-fidelity/app-relaxed-settings.png) | [Relaxed](assets/2026-10-17-fidelity/reference-relaxed-settings.png) |
|
||||
| Archive | [Structured](assets/2026-10-17-fidelity/app-structured-archive.png) | [Structured](assets/2026-10-17-fidelity/reference-structured-archive.png) |
|
||||
|
||||
Additional captures cover both themes at 1440px/390px, populated mobile utility pages, compact rows,
|
||||
event/archive details, custom-routine drawers, archive history and the Settings pages.
|
||||
|
||||
The comparison harness freezes time at 2026-10-16 12:00 UTC and intercepts the event-feed request
|
||||
with the prototype's **synthetic demonstration events**. It seeds disposable browser storage with
|
||||
matching routine choices and 38 archive snapshots. These fixtures are review evidence only: they
|
||||
are not imported by production, copied into public, or written into source snapshots. Actual setup,
|
||||
HTTP migration and offline checks use the built app and its real feed separately.
|
||||
|
||||
Expected semantic differences: real account rows include Asia events, so totals differ from the
|
||||
prototype's game-only event list. One prototype custom task was not seeded. Production has no
|
||||
version metadata for archive events, so it groups saved records without inventing version names.
|
||||
Real reset clocks and available routines govern progress. Code/release notices reflect actual data;
|
||||
Checklist comparisons hide these notices to align the first viewport. The Structured prototype's
|
||||
filter dropdown is intentionally superseded by the owner's focus-pill decision.
|
||||
|
||||
Reproduce with [fidelity-capture.mjs](fidelity-capture.mjs), from the repository root, setting
|
||||
`PUPPETEER_MODULE` to the scratch installation's ESM entry and `APP_URL` / `MOCKUP_URL` to fresh
|
||||
running origins. Chrome is `/usr/bin/google-chrome-stable`; the harness maps event-clock.test to
|
||||
loopback. Rebuild CSS/JS/static without fetching the feed, and use a new app port after each rebuild.
|
||||
|
||||
## Independent review
|
||||
|
||||
The first reviewer invocation hit a session usage limit; a retry succeeded. Its initial material
|
||||
findings were invisible scrolled timeline labels, substituted Settings navigation, routine column/
|
||||
status hierarchy, multi-account row-key collisions, and insufficient populated Archive evidence.
|
||||
One follow-up also required correcting the game-profile hierarchy. Each finding was fixed and the
|
||||
same screenshot paths recaptured. Final independent verdict: **“ship the reviewed corrections.”**
|
||||
All reported material findings were resolved. This verdict is scoped to the compared screens and
|
||||
reported fixes; it is not owner acceptance or blanket proof of every interaction.
|
||||
|
||||
The Impeccable detector ran once and returned `[]` (no findings).
|
||||
|
||||
## Verification
|
||||
|
||||
Final browser build: `a28021bbe1a8`, production React/JSX transform, 117 bundled modules.
|
||||
|
||||
- TypeScript passes. Full offline suite: **1,594 passed, 0 failed**, 5,410 assertions.
|
||||
- Docker-equivalent copied file layout, without docs/design/public: 1,593 passed, one intentional
|
||||
docs-dependent skip, no failures. This validates the COPY-layout assumption; no Docker image was built.
|
||||
- Eight interface/theme/width combinations: no document overflow or page exceptions. Both densities,
|
||||
reduced motion/effective 200% viewport, custom palette and timezone selection checked.
|
||||
- Ordinary insecure HTTP hostname: new setup, existing v1 migration, daily writes, second server,
|
||||
reset override/revert, backup and reload pass; original legacy bytes retained. Structured is the
|
||||
missing-choice default and saved Relaxed survives reload.
|
||||
- Real two-tab simultaneous writes with Web Locks disabled pass using the existing IndexedDB lock.
|
||||
Offline reload passes on localhost's service-worker-capable origin.
|
||||
- Final-build interaction checks: multi-server bulk pins preserve the other view's placement; numeric
|
||||
edits and custom-routine creation persist; completion, Undo, archive detail, Restore and Escape pass.
|
||||
Final profile's server/reset controls were rechecked on insecure HTTP after layout changes.
|
||||
- `git diff --check` passes. No new runtime dependency, source fetch, commit or publication.
|
||||
|
||||
The earlier rejection is preserved in the 2026-10-16 report. Passing tests did not establish its
|
||||
visual fidelity; the side-by-side evidence and scoped review above are the correction's design record.
|
||||
|
After Width: | Height: | Size: 176 KiB |
|
After Width: | Height: | Size: 163 KiB |
|
After Width: | Height: | Size: 58 KiB |
|
After Width: | Height: | Size: 117 KiB |
|
After Width: | Height: | Size: 53 KiB |
|
After Width: | Height: | Size: 99 KiB |
|
After Width: | Height: | Size: 52 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 100 KiB |
|
After Width: | Height: | Size: 146 KiB |
|
After Width: | Height: | Size: 58 KiB |
|
After Width: | Height: | Size: 151 KiB |
|
After Width: | Height: | Size: 58 KiB |
|
After Width: | Height: | Size: 136 KiB |
|
After Width: | Height: | Size: 60 KiB |
|
After Width: | Height: | Size: 150 KiB |
|
After Width: | Height: | Size: 57 KiB |
|
After Width: | Height: | Size: 108 KiB |
|
After Width: | Height: | Size: 47 KiB |
|
After Width: | Height: | Size: 55 KiB |
|
After Width: | Height: | Size: 97 KiB |
|
After Width: | Height: | Size: 230 KiB |
|
After Width: | Height: | Size: 96 KiB |
|
After Width: | Height: | Size: 112 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 106 KiB |
|
After Width: | Height: | Size: 53 KiB |
|
After Width: | Height: | Size: 194 KiB |
|
After Width: | Height: | Size: 79 KiB |
|
After Width: | Height: | Size: 88 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 99 KiB |
|
After Width: | Height: | Size: 47 KiB |
|
After Width: | Height: | Size: 95 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 59 KiB |
|
After Width: | Height: | Size: 132 KiB |
|
After Width: | Height: | Size: 60 KiB |
|
After Width: | Height: | Size: 88 KiB |
|
After Width: | Height: | Size: 112 KiB |
|
After Width: | Height: | Size: 55 KiB |
|
After Width: | Height: | Size: 92 KiB |
|
After Width: | Height: | Size: 53 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 95 KiB |
|
After Width: | Height: | Size: 144 KiB |
|
After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 141 KiB |
|
After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 140 KiB |
|
After Width: | Height: | Size: 55 KiB |
|
After Width: | Height: | Size: 141 KiB |
|
After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 105 KiB |
|
After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 57 KiB |
|
After Width: | Height: | Size: 99 KiB |
|
After Width: | Height: | Size: 218 KiB |
|
After Width: | Height: | Size: 94 KiB |
|
After Width: | Height: | Size: 102 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 96 KiB |
|
After Width: | Height: | Size: 45 KiB |
|
After Width: | Height: | Size: 180 KiB |
|
After Width: | Height: | Size: 82 KiB |
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 89 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 87 KiB |
|
After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 55 KiB |
|
After Width: | Height: | Size: 122 KiB |
|
After Width: | Height: | Size: 60 KiB |
|
After Width: | Height: | Size: 86 KiB |
@@ -0,0 +1 @@
|
||||
[{"id":"e0","game":"genshin","title":"Anniversary Memories Album","desc":"Look back through the year's moments in an album and claim Primogems for each page you fill.","start":1790564400000,"end":1792292400000,"src":"https://genshin-impact.fandom.com/wiki/Anniversary_Memories_Album"},{"id":"e1","game":"zzz","title":"Clink, Clank, Pinball Knight!","desc":"A pinball minigame with daily stages; clear them for Polychromes and upgrade materials.","start":1789009200000,"end":1792378800000,"src":"https://game8.co/games/Zenless-Zone-Zero/archives/457176"},{"id":"e2","game":"zzz","title":"Diary of an Orbie Parent","desc":"Raise an Orbie through daily check-ins and small tasks.","start":1790737200000,"end":1792378800000,"src":"https://game8.co/games/Zenless-Zone-Zero/archives/457176"},{"id":"e3","game":"nte","title":"Stamina Recharge","desc":"Spend City Stamina twice as fast in select Hethereau Hobby activities.","start":1791169200000,"end":1792378800000,"src":"https://game8.co/games/Neverness-to-Everness/archives/592073"},{"id":"e4","game":"zzz","title":"Data Bounty - Combat Simulation","desc":"Short combat simulations with bonus rewards for the first clear of each.","start":1791946800000,"end":1792378800000,"src":"https://game8.co/games/Zenless-Zone-Zero/archives/457176"},{"id":"e5","game":"zzz","title":"All-New Program","desc":"","start":1788922800000,"end":1792465200000,"src":"https://game8.co/games/Zenless-Zone-Zero/archives/457176"},{"id":"e6","game":"genshin","title":"Predictive Victory Dynamics","desc":"A combat event in stages; each unlocks a day after the last.","start":1791774000000,"end":1792465200000,"src":"https://game8.co/games/Genshin-Impact/archives/301601"},{"id":"e7","game":"wuwa","title":"Bountiful Crescendo","desc":"","start":1792033200000,"end":1792638000000,"src":"https://game8.co/games/Wuthering-Waves/archives/453473"},{"id":"e8","game":"hsr","title":"4.6 Planar Fissure","desc":"Double rewards from Planar Ornament Extraction, a few times a day.","start":1791774000000,"end":1792897200000,"src":"https://game8.co/games/Honkai-Star-Rail/archives/408749"},{"id":"e9","game":"wuwa","title":"Artisan's Search","desc":"","start":1791428400000,"end":1792983600000,"src":"https://game8.co/games/Wuthering-Waves/archives/453473"},{"id":"e10","game":"wuwa","title":"Waking Moon Fishing","desc":"","start":1792033200000,"end":1793502000000,"src":"https://game8.co/games/Wuthering-Waves/archives/453473"},{"id":"e11","game":"genshin","title":"Battle Pass - Moontrace","desc":"","start":1790132400000,"end":1793588400000,"src":"https://game8.co/games/Genshin-Impact/archives/301601"},{"id":"e12","game":"genshin","title":"To Temper Thyself and Journey Far","desc":"","start":1786330800000,"end":1793588400000,"src":"https://game8.co/games/Genshin-Impact/archives/301601"},{"id":"e13","game":"hsr","title":"Love, Ghosts & Robots","desc":"","start":1790564400000,"end":1794366000000,"src":"https://game8.co/games/Honkai-Star-Rail/archives/408749"},{"id":"e14","game":"hsr","title":"Astral Imagea","desc":"","start":1790564400000,"end":1794366000000,"src":"https://game8.co/games/Honkai-Star-Rail/archives/408749"},{"id":"e15","game":"nte","title":"Pukaland Travelogue","desc":"","start":1790737200000,"end":1794366000000,"src":"https://game8.co/games/Neverness-to-Everness/archives/592073"},{"id":"e16","game":"wuwa","title":"3.7 Moonlit Path","desc":"","start":1790737200000,"end":1794366000000,"src":"https://game8.co/games/Wuthering-Waves/archives/453473"},{"id":"e17","game":"nte","title":"Coal Lumps Treasure","desc":"","start":1791428400000,"end":1794366000000,"src":"https://game8.co/games/Neverness-to-Everness/archives/592073"},{"id":"e18","game":"endfield","title":"Originium Supply Run","desc":"Mockup event so Endfield has a row.","start":1791514800000,"end":1792724400000,"src":null},{"id":"e19","game":"hsr","title":"Free Gilgamesh or Archer","desc":"","start":1784862000000,"end":null,"src":"https://game8.co/games/Honkai-Star-Rail/archives/408749"}]
|
||||
|
After Width: | Height: | Size: 55 KiB |
|
After Width: | Height: | Size: 96 KiB |
|
After Width: | Height: | Size: 149 KiB |
|
After Width: | Height: | Size: 57 KiB |
|
After Width: | Height: | Size: 148 KiB |
|
After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 51 KiB |
|
After Width: | Height: | Size: 102 KiB |
|
After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 154 KiB |
|
After Width: | Height: | Size: 64 KiB |