The problem. Today's nested screens (members/index, members/invite) inherit the default Expo Router Stack header: white panel, hairline rule, iOS system font, centered title, blue back link, and — visible in the current build — the literal route segment "index" rendered as the back-button label. Sign-in, OTP, and home all use the Terracotta editorial system; the nested headers look like a different app.

What's below. Four header treatments, each rendered with realistic Members-screen content so the headers are compared in context. The first frame is the current default for reference. Then an iOS ↔ Android comparison of the recommended variant. Tokens (color, type, spacing, radii) match constants/Colors.ts and constants/tokens.ts exactly.

Before — current default
v0

Default Stack header

What the user's screenshot shows. iOS native chrome sitting on top of a Terracotta screen. Included for reference only.

16:34● ● ●
index Echipa
Invită membru
SC
SC2OK28snUNVPMR1fbefa3dTmIG2
Proprietar
"index" as back label SF system font White panel on cream No design language
A & B — title in body, or title in chrome
v1 · A

Minimal chrome, body title

No header bar. A floating back chip sits in the safe area; the title renders as a display-size heading at the top of the content. Same language as sign-in / OTP.

9:41● ● ●
Echipa
4 membri
AG
Andrei Grosu
Proprietar
MV
Maria Vasilache
Administrator
IC
Ion Crețu
Vânzător
Matches sign-in Editorial weight Lightest chrome Title scrolls away
v2 · B

Slim pinned bar

A ~56px bar persists at the top: back chip + title (15/20, weight 700) left-aligned + optional right slot. No body title. Title stays visible while scrolling.

9:41● ● ●
Echipa
Invită membru
AG
Andrei Grosu
Proprietar
MV
Maria Vasilache
Administrator
IC
Ion Crețu
Vânzător
DR
Dumitru Rotaru
Vânzător
Title always visible Most vertical space Familiar pattern Less editorial
C & D — the polished options
v3 · C

Large-Title collapse

Hybrid of A and B. At rest looks like A; once scrolled, the display title smoothly morphs into the bar and a hairline appears. Frame below auto-loops every 6 seconds.

9:41● ● ●
Echipa
Echipa
4 membri
AG
Andrei Grosu
Proprietar
MV
Maria Vasilache
Administrator
IC
Ion Crețu
Vânzător
DR
Dumitru Rotaru
Vânzător
live · auto-scrolls
Best of A + B Native iOS feel Needs Reanimated Most code
v4 · D

Editorial eyebrow

Variant A plus an uppercase accent eyebrow above the display title. Carries breadcrumb-style context (org, parent section) without adding a subtitle slot to chrome.

9:41● ● ●
Distribuitor SC · Echipa
Membrii echipei
4 persoane · Tu ești proprietar
AG
Andrei Grosu
Proprietar
MV
Maria Vasilache
Administrator
IC
Ion Crețu
Vânzător
Carries breadcrumb context Most editorial of the four Title scrolls away Needs eyebrow content per screen
iOS vs Android — same component, two platforms

The ScreenHeader is a custom RN component, not a platform-default header. Same back chip, same display title, same tokens on both platforms. The only differences come from system chrome: iOS has the Dynamic Island and home indicator; Android has a smaller status bar and a gesture pill at the bottom. Both feed into useSafeAreaInsets(), which the component reads to position the back chip correctly.

iOS

iPhone — variant A

Dynamic Island sits in the 44px status zone. Back chip starts at insets.top + s2.

9:41● ● ●
Echipa
4 membri
AG
Andrei Grosu
Proprietar
MV
Maria Vasilache
Administrator
IC
Ion Crețu
Vânzător
Status bar: 44px Notch / Dynamic Island No bottom system bar
Android

Pixel — variant A

28px status bar, no notch. Gesture pill at the bottom. Body content otherwise identical — same tokens, same component.

9:41 ● ● ●
Echipa
4 membri
AG
Andrei Grosu
Proprietar
MV
Maria Vasilache
Administrator
IC
Ion Crețu
Vânzător
Status bar: 28px No notch Gesture pill: 18px Back chip + system back gesture both work
Recommendation

Ship A as the primitive. Expose D as a mode of A. Defer C until scroll-heavy screens land.

Why A is the base. Sign-in and OTP already establish the visual language: cream page, display-size title at the top of the body, no header bar. A keeps that contract intact when the user enters a nested screen — no visual jolt, no second chrome system. The back chip uses the same 36px pill shape as the bell button in TopBar, so the chrome vocabulary stays coherent. Implementation is plain layout — no Animated, no scroll handlers, no platform branching.

D is A with two extra props. The eyebrow + meta line are additive on top of A's structure. Screens that need breadcrumb-style context opt in by passing eyebrow= and meta=; screens that don't render as plain A.

C is a future upgrade path. The Large-Title collapse needs a Reanimated scroll handler and a coordinated morph. Build A first, ship the Tabs migration on top of it, add C as a collapsible prop once Catalog/Orders make scroll-heaviness real.

B is rejected for nested screens. Cream-on-cream slim bar with a generic label feels closer to a settings sub-screen than to the editorial direction. Reserve B-style chrome for modal flows (e.g., invite flow in a sheet) where the title anchors a focused task.

Anatomy of the proposed ScreenHeader primitive

back chip
36×36 pill · surface bg · 1px borderStrong border · ink chevron drawn as two 2px borders (no glyph font). Same shape as TopBar's bell button.
right slot
Optional 36×36 pill matching the back chip. Holds +, , filter, etc. Hidden when no rightSlot prop is passed.
title
display token (28/32, weight 800, tracking −0.5). Ink color. Lives in body, not chrome.
eyebrow (opt)
eyebrow token (11/14, uppercase, tracking 0.8). Accent color. Above the title.
meta (opt)
caption token (12/16, weight 500). text2 color. Below the title.
spacing
Chrome row: space.s2 top, space.s5 sides. Title block: space.s6 top, space.s5 sides.
safe area
Chrome row sits at insets.top + space.s2; reads from useSafeAreaInsets() so the same component handles iOS notch and Android status bar.
props
{ title; eyebrow?; meta?; rightSlot?; onBack? }onBack defaults to router.back(); null hides the back chip (root-of-stack screens).

How to review

Open in any browser. Give variant C ~6 seconds to see the morph cycle. All tokens match constants/Colors.ts and constants/tokens.ts — what you see is what will ship if a variant is picked.

Reply with the variant name (A / B / C / D), or describe a mix.