The reader's question is answered entirely by data already on the device and
countdowns run off the local clock, so losing signal should not lose the app.
The shell is cache-first; the feed is network-first falling back to the last
copy seen, because stale events beat a blank screen. Webfonts are cached too
— without them an offline load silently drops to system faces and the whole
thing changes character.
Offline is surfaced in the header and above the footer rather than hidden:
stale data must never be presented as current.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Game8's editors compile the calendars this depends on, and the studios make
the games — both belong on the same screen as the data rather than one
navigation step away.
States plainly that this is an unofficial fan-made tool with no connection
to Game8, HoYoverse, Kuro Games, Hypergryph or Hotta Studio, and that the
source page is the authority when the two disagree.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A calendar full of games you don't play is worse than an empty one — it
buries the thing you came for.
Nothing is preselected; the button stays disabled until a game is picked,
which is clearer than guessing and hoping the reader notices. The choice is
stored as hiddenGames, the inverse, so a game added later shows up by
default rather than staying invisible.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The whole row is now one click target, which gives a generous tap area and
a single unambiguous hover region.
Hover transitions are fast and eased out (110-160ms) so a row responds on
the way in and settles on the way out — a slow symmetric fade is what makes
an interface feel laggy even at full framerate. The meter is the element
that visibly wakes up, since it is the signature. Press feedback lands on
touch as well as mouse, and every hover rule sits behind `hover: hover` so a
tap never leaves a row stuck looking hovered.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Opens on the single event closest to expiring, at a size nothing else
competes with — the reader arrives with one question. Below it, live events
ordered by what ends soonest, then a quiet timeline view with one lane per
game.
Countdowns use tabular figures so ticking never reflows the row.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A discrete tick-strip rather than a smooth progress bar, borrowed from the
stamina meters these games all use — ticks read as a finite resource visibly
draining, which is the right metaphor for a limited-time event.
An event with no announced end gets a hatched strip, never a full meter.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Completions and prefs live in localStorage and never reach the server —
there is no account and nothing to log into. Reads never throw, so a corrupt
value costs a preference rather than the whole screen.
Import merges and never removes: a completion present on either side stays
completed, because nothing else holds a copy to restore from.
The feed client refuses a schemaVersion it does not know rather than
guessing at unfamiliar fields.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Tailwind v4 @theme carries the two colour axes as tokens: a deep blue-black
ground, per-game hues for identity, and a heat ramp for urgency that is
monotonic in salience (dim, blue, amber, red).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>