Privacy-Period-Tracker/core
null ae27ef6490 feat: full-bleed onboarding heroes, in density buckets
closes #40, closes #41

The illustrations span the screen and fade into the page, at roughly a third of
its height, and the seven hand-rolled step layouts became one component.

A UNIFIED STEP

Every step wrote out Spacer / Illustration(size) / Spacer / Heading / controls,
in three different spacer rhythms with a reason recorded for only two. StepBody
holds the rhythm; a step declares what is different about it. artHeight stays
per-step: the two carrying three or four controls take a shorter hero so the
primary button is reachable without scrolling, which is the constraint the old
104dp values existed for.

The screen's padding moved from the scrolling column to the content inside each
step. Compose has no negative padding, so a full-bleed child cannot live inside
a padded parent.

THE CAP IS WHAT MAKES LANDSCAPE SURVIVE

A landscape phone is 914x411dp. A fixed 280dp hero would be 68% of it and every
step would break on rotation — nothing in this app uses WindowSizeClass and
onboarding does not lock orientation. Illustration caps at a third of the screen.

It reads LocalConfiguration.screenHeightDp rather than BoxWithConstraints: inside
a verticalScroll column a child is measured with an INFINITE height constraint,
so maxHeight there is Dp.Infinity and the cap would silently never apply. A guard
that looks right and does nothing.

DENSITY BUCKETS, FIXING A LIVE DEFECT

The old set sat in a density-less drawable/, treated as mdpi and pre-scaled at
decode — roughly 17 MB of heap for one bitmap on an xxxhdpi device, and this
artwork is far larger. Now four widths per theme, 617 to 1644 px, and no plain
drawable/ at all. 2.3 MB across every bucket; a release is an AAB and Play splits
by density, so a device downloads 130-500 KB.

That is also the error-handling fix: painterResource decodes inside composition
and there is no boundary anywhere, so an OOM would crash onboarding on first
launch. Sizing the bitmaps removes the failure rather than hiding it.

The clip is gone with the corners it existed for, and the bottom fade is drawn
from the theme background rather than baked into the art. Titles move to
headlineLarge, which is what 280dp of artwork above them needs.

Driven on PeriodMinSdk26: all steps, both themes, font scale 1.0 and 2.0, and
landscape. No crash, no OOM. ./gradlew check green.

KNOWN, FILED SEPARATELY: dark 01 Welcome is a forecast scene, so dark mode shows
a calendar on step 1. The artwork is wrong, not the wiring.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-19 01:02:06 -05:00
..
data feat: fertility that declines rather than stretches 2026-08-18 14:56:05 -05:00
database feat: the prediction engine section 12 specifies, and it beats the baseline 2026-08-18 03:16:12 -05:00
datastore feat: reminders that stay quiet on a lock screen 2026-08-18 15:26:59 -05:00
designsystem feat: full-bleed onboarding heroes, in density buckets 2026-08-19 01:02:06 -05:00
notifications feat: reminders that stay quiet on a lock screen 2026-08-18 15:26:59 -05:00