App ships universal (iPhone+iPad), so the App Store requires iPad
screenshots. Render the 3 store screens at 2048x2732 (iPad 12.9"/13").
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Drop the In-App Purchases section from the privacy policy and the
'Remove Ads' bullet from the store description, since the app now ships
ad-supported only. Renumber policy sections; bump policy date to Jun 15.
Redeployed the policy to block-seasons.web.app.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The developer is an individual without a Korean business registration, so
the App Store / Play paid-apps (merchant) agreements can't be completed.
Hide the Remove Ads + Restore tiles and skip IAP init; ads always show.
AdMob revenue is independent of those agreements. Reversible: flip
kIapEnabled to re-enable once a merchant agreement exists. Bump to build 2;
drop the now-unused IAP review-screenshot generator.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Headless render of the Settings screen showing the Remove Ads purchase
point + price + Restore Purchases, for the App Store IAP review-screenshot
requirement. Forces a desktop target platform so the real IapService can
be constructed without the store plugin making async channel calls.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
App uses only standard OS-provided encryption (HTTPS via Firebase/AdMob),
which qualifies for export compliance exemption. Baking the key into
Info.plist avoids the per-build encryption prompt on future uploads.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replaces the default Firebase placeholder so the App Store support and
marketing URLs (https://block-seasons.web.app) show a real Block Seasons
page. Deployed to Firebase Hosting root as index.html.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Deployed privacy-policy.html and app-ads.txt to block-seasons.web.app
(gru.farm root is an external site builder, not the NAS, so app-ads.txt
could not live there). Updated phase7 guide with the live URLs.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Headless screenshot harness renders Home, Gameplay, and a denser
score-chase board to PNGs at 1290x2796 (iOS) and 1080x1920 (Android),
in English with a real font loaded. Captures the boundary layer at 3x
inside runAsync (the only way it completes under the test binding).
Season-map cut deferred — its scrollable build stalls headlessly.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Rewrote the Phase 7 guide to reflect completed Play setup (app, AAB,
payments profile, remove_ads) and lay out remaining ordered steps for
both stores with copy/answers inline. Added a hostable bilingual
privacy policy page and a 512x512 Play store icon.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The '(build 4)' marker was a device build-delivery debugging aid, now
resolved. Public release shows a clean version string.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Generator: raise the early bot-win-rate floor to ~0.97 (near-guaranteed first
stages), widen the early move-buffer margin, and delay score-chase/line-sprint
objectives until stage 9/13 so the opening stretch is pure clear-a-gem. Result:
stage 1 now 16 moves (was 11), stages 1-9 all simple gems at 90-99% bot win.
Preserves theme.bgm=season_001; manifest SHA regenerated. Settings tag -> build 4.
- activeSeason now returns the first season (Season 1 'First Bloom') so a new
player starts at spring instead of the newest season.
- Bundle the owner-picked CC0 tracks menu.mp3 + season_001.mp3 (BGM now audible).
- Settings footer shows 'v1.0.0 (build 3)' so test builds are identifiable.
180 tests green, analyze clean.
MusicService (looping audioplayers player, independent of SFX) driven by the
active season theme's new 'bgm' key; switches track on season change, pauses on
app background, all failures swallowed. Separate Music on/off toggle in Settings
(persisted, independent of SFX). Season packs carry bgm keys (menu/season_001/
season_002), manifest regenerated. Assets slot assets/audio/bgm/ ready — drop in
menu.mp3/season_001.mp3/season_002.mp3 (CC0) and it plays; silent until then.
180 tests green, analyze clean.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
On device the floating top-left X (48px IconButton) overlapped the HUD moves
chip. Move it into the column flow above the HUD, left-aligned, so it never
collides. Found via on-device test build.
Replaces the TODO_REAL_* ad-unit placeholders with the owner's real AdMob
console ids (publisher pub-5605900229781491) and the native AdMob app ids
(iOS ~8397095848, Android ~8257495040) in place of the Google sample ids.
Debug builds still serve Google test ads via kDebugMode; release builds now
use the real units.
Step-by-step owner guide to register the AdMob apps + 6 ad units, create the
remove_ads IAP in both stores, and the exact values to send back so the
TODO_REAL_* ad ids and native AdMob app ids get swapped in.
The flutter_test default font draws every glyph as a box, so the wordmark was
unreadable. Load the OFL Titan One TTF via FontLoader in the generator and
render 'Block Seasons' + tagline with it; fit the text within the 1024 width.
Font used only by the asset generator, not bundled in the app.
Adds PressableScale (0.94 squish on tap-down) around the Adventure
FilledButton, Classic OutlinedButton, and each season-map stage node.
Replaces all in-app MaterialPageRoute pushes with a gentle fade+scale
PageRouteBuilder (320ms in, 240ms out) via a new fadeRoute helper.
Introduces AppIconMark (navy gradient field + 2×2 glossy blocks reusing
paintGlossyTile) and a testWidgets generator that writes icon.png,
icon_background.png, and icon_foreground.png to assets/icon/ for the
upcoming flutter_launcher_icons task.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
AdMob ads (interstitial/rewarded/banner) with a pure-Dart frequency policy,
a compliant UMP->ATT->init consent flow, and a remove_ads non-consumable IAP
with Restore. Single repo-backed ownership source (adsRemovedProvider); all
ad/IAP/consent failures swallowed. Runs on Google test ids today; owner swaps
real ids by config. 169 tests green; opus final review passed.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
iapServiceProvider was lazy and only read by Settings, so the purchase stream
attached only after opening Settings — deferred/interrupted/restored
transactions wouldn't be delivered or completed until then. Read it in the
post-frame callback so the stream is live for the whole session.
On a cold start the consent flow is still running when home first builds, so
createBanner returns null and the slot stayed empty until a rebuild. AdService
now exposes an isReady ValueNotifier; BannerAdSlot listens and retries its load
once MobileAds finishes initializing. Verified: analyze clean, 169 tests green.