Four new preferences, all in settings.js / applied via applyTheme() so
boot and live changes go through one path:
- fontScale (small/default/large): scales root font-size (92/100/115%);
the whole stylesheet is already rem-based so this alone rescales
everything.
- reduceMotion: an explicit in-app override alongside the existing
`prefers-reduced-motion` OS check, via a new
:root[data-reduce-motion="true"] rule in tokens.css mirroring the
existing media-query kill-switch. New prefersReducedMotion() helper
(checks both) replaces the three hand-rolled matchMedia checks in
router.js/Card.js/PokemonDetail.js.
- defaultRoute (dex/team/search): redirects on a genuinely hash-less
launch only (bookmark, home-screen icon, bare URL) — explicit nav
(e.g. tapping "Dex") is never touched, since it's applied once in
main.js before initRouter runs.
- haptics: a short navigator.vibrate() pulse on the same catch/seen/
favorite toggles that already play the pop animation, via a new
lib/haptics.js buzz() (no-ops without Vibration API support, e.g. iOS
Safari).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Ve7HLspzeG2xDPtJQ8vmu
New "Calc" mode alongside Coverage/Compare. Pick (or quick-pick from your
current team) an attacker, a move, and a defender; get a damage range, %
of the defender's HP, hits-to-KO, and STAB/effectiveness badges.
- src/lib/damage-calc.js: the standard Gen 3+ stat and damage formulas
(statAt, calcDamage), evaluated across the 85–100% roll.
- Move data is era-accurate: picking a move fetches it live for
past_values (power/type/class changes), reusing MovesList's
forGeneration (now exported) via a snapshot-shaped shim so the instant
preview and the refined post-fetch result use the same code path.
- Level/nature/EV inputs per side (defaults: level 100, neutral nature,
0 EV, 31 IV assumed) plus a crit toggle.
- Explicitly out of scope and called out in the UI: items, abilities,
weather, terrain — this is a base-stats estimate, not a battle-exact
number.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Ve7HLspzeG2xDPtJQ8vmu
onSwipe judged horizontal-vs-vertical from a single touchmove sample
compared against the start point. A fast scroll flick's first sample is
often slightly diagonal (thumb motion), so it could get claimed as a
page-swipe and every subsequent touchmove got preventDefault()'d — the
rest of the scroll silently died, so trying to reach off-screen content
in About/Stats/Evolution/etc. would instead flip to the next Pokémon.
Now vertical intent wins by default (bails, permanently, as soon as the
drag is even mildly more vertical than horizontal) and a horizontal
page-swipe only gets claimed once the drag is unambiguous
(dx > 20 && dx > 2*dy). Deliberate left/right swipes still work.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Ve7HLspzeG2xDPtJQ8vmu
- Detail About tab: EV yield, base EXP, catch rate + ~%, base friendship,
growth rate + total EXP, held items; Breeding block with a gender-ratio
bar, egg groups, egg cycles/steps
- Stats tab: 'STAB coverage (attacking)' — types the Pokemon's STAB hits
hard / is walled by (data/type-chart.js offensiveSummary)
- Feed: Type and Generation filter dropdowns + a Random button; cards now
resolve typings for the selected game's generation via snapshot pastTypes
- Recently-viewed strip on the feed (ui.recent, capped at 12)
- Play-cry button on the detail hero; service worker caches PokeAPI cries
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Evolution chain is now a vertical tree (stage, then '↓ trigger' step,
then the next stage) that indents by branch depth. Never overflows a
phone; branching chains (Eevee, Wurmple) stay grouped and readable.
- Swipe left/right on the Pokémon detail page navigates prev/next in the
current dex (src/lib/swipe.js). Claims horizontal drags via
preventDefault so page scroll and the browser's edge back-gesture don't
steal them; vertical drags pass through.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>