Brand
Brand integration
How each platform consumes the Signal mark, and which tokens its colours come from.
How the Signal mark fits the design system and how each platform uses it. Usage rules are in BRAND.md.
Where it sits
The brand assets are in brand/signal/ (svg/, png/, manifest.json).
They are identity artwork, not a component: no states, no contract in components/, and separate
from the transit icons in icons/ (train, bus, train + bus, refresh), which are the app's glyphs.
go generate ./... copies the marks the docs site uses into docs/brand/; nothing under
platforms/ ships them yet.
Tokens
tokens/tokens.json stays the only colour source of truth. There are no
signal.* tokens: every colour in the artwork is already an existing token, listed below with its
key in tokens.json, its CSS custom property (platforms/web/tokens.css) and its Swift name
(DesignTokens.swift). go test ./... fails if a fill or stroke in brand/signal/svg/ isn't one
of these values.
| Part | tokens.json key |
CSS | Swift | Light | Dark |
|---|---|---|---|---|---|
| Housing | fixedColors → alwaysInk |
--always-black |
DesignTokens.FixedColor.alwaysInk |
#101A2E |
#101A2E |
| Top lamp | lines → blue |
--blue-line |
DesignTokens.lineColors "blue" |
#00A1DE |
#00A1DE |
| Middle lamp | lines → brown |
--brown-line |
DesignTokens.lineColors "brown" |
#62361B |
#A8653A |
| Bottom lamp | lines → red |
--red-line |
DesignTokens.lineColors "red" |
#C60C30 |
#C60C30 |
| Wordmark | colors → ink |
--ink |
DesignColorToken.ink |
#101A2E |
#EEF1F6 |
| Subtitle | colors → muted |
--muted |
DesignColorToken.muted |
#5B6472 |
#98A2B3 |
| Dark keyline | colors → ink, dark value |
--ink in dark |
DesignColorToken.ink, dark |
— | #EEF1F6 |
Notes on the mapping the brand package suggested (signal.housing, signal.blue, …):
- Housing is fixed ink, which already exists as
fixedColors.alwaysInk(its CSS name is--always-blackfor historical reasons). Don't use the theme-awareink: it turns near-white in dark mode. - Lamps use the line tokens'
light/darkvalues, notroute(the GTFS colour). They agree for Blue, Brown and Red today except Brown's dark value. - Dark keyline has no fixed token. The SVG bakes in
ink's dark value.liveBghas the same dark value but means something else; don't borrow it. If the keyline needs to be addressable on its own, add a fixed token (for examplefixedColors.alwaysPaleInk) rather than asignal.*group. - Typeface is
font.family(Figtree). The outlined production SVGs use Inter; see BRAND.md.
The assets are static files with colours baked in, so they don't follow a runtime token change. When one of these tokens changes, re-export the SVGs and PNGs together (the colour test above fails until you do).
Web and the docs site
Pick the variant from the colour scheme. On GitHub and anywhere that follows the OS setting:
<picture>
<source srcset="brand/signal/svg/signal-lockup-dark.svg" media="(prefers-color-scheme: dark)">
<img src="brand/signal/svg/signal-lockup-light.svg" alt="Signal — ChiTransit design system" width="320">
</picture>
The docs site serves its copies from /brand/ (/brand/signal-favicon.svg, /brand/signal-mark.svg,
/brand/signal-mark-dark.svg) and uses the favicon on every page. A page with its own theme switch
should choose the variant from the page theme rather than only prefers-color-scheme.
@chitransit/signal (npm, planned in CTA-212) doesn't ship the brand files. Add them to
platforms/web/ through the generator if a consumer needs them.
SwiftUI
The Signal Swift package doesn't ship the brand mark; it isn't app UI. To use it in a docs or
about screen, add the SVGs to an asset catalog with "Preserve Vector Data" (or convert to PDF), as
SignalLockupLight / SignalLockupDark, or one image set with a dark appearance:
Image(colorScheme == .dark ? "SignalLockupDark" : "SignalLockupLight")
.resizable()
.scaledToFit()
.accessibilityLabel("Signal design system")
Android / Compose
No Android package yet (platforms/android/ is reserved). Convert the mark SVGs to
VectorDrawables; they are plain rects and circles and convert cleanly. The outlined lockups convert
too but are heavier; the density PNGs are the fallback. Don't assume Compose's ImageVector reads
SVG directly.
Hygiene
- Keep SVGs and their PNG exports in the same commit.
- Check contrast on the real background, not the artboard.
- Name the mark once: decorative when visible "Signal" text sits next to it.
- After a typeface or colour change, compare the PNG previews before and after.