5.9 KiB
Android theme plan — mirroring the website frontend
This is a summary of the website frontend theme (source of truth:
website/client/src/styles/theme.css, applied at runtime by
website/client/src/contexts/SiteContext.jsx) so the native Android client can
present a visually consistent brand. Where the web uses CSS custom properties,
the Android equivalent is a Compose MaterialTheme ColorScheme + Typography.
Overall character
A dark, moody, "arcane fantasy" theme — deep blue-black backgrounds, muted slate-blue accent, parchment-white text, and an engraved serif display face. It reads like a leather-and-moonlight fantasy ledger, not a bright consumer app. There is no light mode on the web; the app should ship dark-only to match.
Color tokens
The web theme is a flat set of CSS variables under :root. Map them to Compose
as follows (hex is authoritative):
| Web token | Hex | Role | Compose slot (suggested) |
|---|---|---|---|
--bg |
#0e1318 |
App background | background |
--bg-deep |
#0b0f14 |
Deepest surface / on-accent text | surfaceDim / onPrimary |
--panel-a |
#192231 |
Card gradient top | surface |
--panel-b |
#141a21 |
Card gradient bottom | surfaceContainer |
--panel-flat |
#11161d |
Flat panels, toolbars | surfaceContainerLow |
--line |
#2a3544 |
Borders / dividers | outline |
--line-soft |
#1d2733 |
Subtle row dividers | outlineVariant |
--accent |
#7f99bd |
Primary accent (brand-overridable) | primary |
--accent-bright |
#cdd9e8 |
Primary button fill, active states | primaryContainer / bright |
--ink |
#eef3f8 |
Highest-contrast text | onBackground |
--head |
#e6edf6 |
Headings | heading color |
--text |
#c4cdd8 |
Body prose | onSurface |
--muted |
#aeb8c4 |
Secondary text | onSurfaceVariant |
--dim |
#6f7d8e |
Meta / captions / placeholders | dim / disabled text |
--blue |
#13243c |
Accent hover/active background | secondaryContainer |
--mode-live |
#5fb98a |
"Shard live" status (green) | success |
--mode-maint |
#e6c26a |
"Maintenance" status (amber) | warning |
Semantic / status colors (used in badges, diffs, moderation)
- Success / published / live: green
#5fb98a(fills at ~16–22% alpha, text#7fd0a4). - Warning / maintenance / moderation (kick/mute/warn): amber
#e0b070/#e6c26a. - Danger / ban / red-link / errors: desaturated red
#d98b84(borders#6e3b38). - Admin badge: near-white
#d8e2efon#3a4a5e.
Branding is data, not code
The --accent value is overridden at runtime per shard instance. On the web,
SiteContext reads brand.accent from the site settings API and sets the CSS
variable, so one build reskins for any shard. The Android app should do the
same: fetch the brand payload (name, accent, colors, logo/hero/favicon) from
the website API and derive the primary color at runtime rather than hardcoding
#7f99bd. Default to #7f99bd when the brand payload is absent/offline.
Typography
Three font families, by role:
- Display (
--display): Cinzel, falling back to Georgia serif — an engraved Roman capitals face used for the logo,h1/.h1, and proseh2/h3. Bundle Cinzel as an app font; this face carries the brand. - Serif body (
--serif): Georgia / Times New Roman — default body and prose text;line-height ≈ 1.6. - Sans (
--sans): Helvetica Neue / Arial — UI chrome: buttons, pills, form labels, table headers, badges, meta. Labels/eyebrows/kickers are UPPERCASE with wide letter-spacing (0.1–0.18em) and small (0.68–0.86rem).
Heading scale is fluid on web (h1 clamps ~2.4–3.6rem); pick fixed Material type
scale equivalents (e.g. display for h1, headline for h2, title for h3).
Shape, elevation & motion
- Corners: cards/panels
10–12pxradius; inputs/small elements8px; pills and buttons are fully rounded (999px/ capsule). - Cards: vertical gradient
--panel-a → --panel-b, 1px--lineborder, soft drop shadow (0 14px 34px rgba(0,0,0,0.3)). On hover the web lifts-3pxand brightens the border to--accent— translate to a pressed/focused accent border on Android. - Buttons: primary = bright fill (
--accent-bright) with dark text; ghost/secondary = translucent dark fill with accent-on-hover border. - Motion: short, subtle transitions (0.12–0.18s). Keep animations understated.
Signature accents (nice-to-have)
- The "moon" motif: a radial-gradient sphere (
#eef3f8 → #9fb0c6 → #5d6e88) — a small brand flourish worth reproducing. - Accent-tinted focus rings and left-border "note" callouts
(
border-left: 3px solid --accentover a translucent--bluebackground).
Implementation note for Compose
Define one darkColorScheme(...) from the table above, a Typography binding the
three families, and a Shapes set (small = 8.dp, medium = 10.dp, capsule for
buttons). Load accent from the brand API into a state holder and rebuild the
primary (and derived primaryContainer) at runtime so a shard's custom accent
flows through the whole UI — exactly as SiteContext does on the web.