fix(profile): standardize header layout across screen sizes master
The profile header's banner, avatar, and DID drifted to different positions on different devices. SliverAppBar.expandedHeight was hardcoded to 220 while the header content started below a SafeArea whose top inset varies per device (~20pt on older iPhones, ~59pt on Dynamic Island models), so the total height and the content's starting point disagreed: the identity block landed lower and was clipped by a different amount on every screen. Rebuild the header around explicit Positioned layers whose geometry is derived from the device inset and text scale, so the banner's bottom edge always sits a fixed distance below the collapsed app bar and the avatar always straddles that edge by exactly half its height. Note that SliverAppBar computes maxExtent as topPadding + expandedHeight, so expandedHeightFor() deliberately excludes the status-bar inset — including it counts the inset twice and makes the banner grow at twice the inset's rate. Changes: - Derive header geometry from MediaQuery insets and text scale via ProfileHeader.expandedHeightFor / maxExtentFor / collapsedExtentFor - Replace the SafeArea + UnconstrainedBox flow layout with explicit Positioned layers: banner, scrim, avatar, identity - Move bio, stats, and join date into a new ProfileDetails sliver so they are never clipped by the collapsing header, dropping the 2-line bio truncation that the clipping required - Set the banner overhang to avatarSize / 2 so the avatar cannot rise above the collapsed app bar and show through the frosted overlay - Compute collapse progress from the sliver's real max extent, so the frosted blur no longer stalls for the first topPadding px of scroll - Replace the per-platform iOS/Android gradient hacks with one scrim - Make the DID tappable to copy, since it ellipsizes on narrow screens - Add profile_header_test.dart pinning the geometry at insets of 0/20/44/59pt; 3 of its 5 tests fail against the previous layout Verified with flutter analyze, the full test suite (948 passing), and pixel measurements on the Android emulator at two status-bar insets: the banner edge now tracks the inset at 1x (63px between a 24dp and 48dp inset) rather than 2x (126px). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>