Foundations
The styles, live
Everything is a token. Switch the reference brand and mode below — colour, type, shape and motion all re-skin from the same roles. This is exactly what your components read.
These are the same 37 M3 colour roles any Material 3 app uses — see what Odyssey layers on top of them to make a screen read as a specific bank, not a generic app.
Colour roles
37 Material 3 roles (plus Neptune's success family) — authored in OKLCH, resolved to hex/ARGB at build, pinned so Flutter == Web.
Typography
Shape
Elevation
--npt-elev-1..5, tinted by the theme's scrim role so shadows read as the brand's own, not a generic grey.
Dark mode is a glow, not a cast shadow — on both
platforms. A scrim-tinted shadow flattens to literal black in dark mode (see
themes.css's dark blocks), which barely registers against an already-dark surface, so
dark mode instead lerps the shadow 35% toward the brand primary, widens the blur, and
drops the directional offset — reading as ambient light lifting the surface. Web:
system.css's [data-mode="dark"] override of --npt-elev-1..5.
Flutter: NptIdentity.elevation1..5's dark-mode branch. Toggle Dark above to see it.
Motion
Per-brand easing + duration tokens carry the brand's feel. Components read --npt-ease-* / --npt-dur-*; reduced-motion is honoured everywhere. In Flutter, a component's own timing can additionally scale from these tokens — NeptuneCta's sheen-sweep/nudge cycle is derived from each brand's --npt-dur-slow/--npt-dur-standard rather than one fixed duration for every brand, so a calmer brand's buttons visibly move slower than a snappier one's.
Standard
--npt-ease-standard · --npt-dur-standard — most transitions.
Emphasized
--npt-ease-emphasized · --npt-dur-slow — entrances & hero moments.
Spring
--npt-ease-spring — selection overshoot (M3 Expressive).
Density
A comfortable/compact lever, independent of brand — the same theme can run either density. In Flutter, NptDensity scales spacing at density-aware call sites (NeptuneListTile, the NeptuneCta family today; more widgets opt in incrementally).
// flutter NeptuneTheme.light('triton', density: NeptuneDensityMode.compact)
Numerals
Arabic-Indic digits (٠١٢٣…) as an independent lever from the RTL/Arabic flag — a real requirement for Gulf/Libyan banking apps, where the UI language and the digit system don't always follow the same rule. In Flutter, NeptuneNumeralStyle / NptNumerals plus NeptuneTheme.formatDigits apply it independently of arabic:.
Feedback
Haptic and sound cues, weighted to the brand's declared content tone (a formal-authoritative brand taps lighter than a warm-hospitable one). In Flutter, NptFeedback fires real HapticFeedback from NeptuneCta/NeptuneCheckbox/NeptuneSwitch; onSoundCue is a plain hook — neptune_sound_kit is its default implementation, kept as a separate package so apps that don't want sound never pay for an audio-plugin dependency.
Accessibility
- WCAG AA contrast on text (4.5:1) and large/UI (3:1) — baked into the role pairs.
- Visible focus (
:focus-visible), full keyboard nav, ≥48dp targets. - RTL by birth — logical properties only; Arabic faces swap per brand.
- Reduced motion honoured via
prefers-reduced-motion.