// Rising Company

Design System

Machine-readable spec — llms.txt · drop-in stylesheet — rising.css
Themes
2
Color Tokens
31
Type Styles
12
Theme
01

Themes

One brand, two themes. Same type pairing, same spacing, same voice, same token names — only the palette and the amount of chrome change. A product picks a theme and commits to it; it is a product decision, not a viewer preference.

Mission
Operator-facing
Consoles, dashboards, diagram and map views, admin, always-on displays, low-light rooms. Scanlines and corner brackets on.
View pattern
Daylight
User-facing
Landing pages, marketing, onboarding, sign-in for non-staff, forms, long-form reading, bright rooms. No scanlines, no brackets.
View pattern
ThemeUse it for
MissionOperator consoles · dashboards · diagram and map views · admin · internal tools · ambient displays
DaylightLanding and marketing pages · onboarding · sign-in for people who aren’t staff · forms and data entry · docs · anything shown in a bright room
Stranger test
If a stranger sees it first, it’s Daylight. A cold visitor should not be met with a black screen and a bare input — sign-in is the end of a landing page, not a substitute for one.
Switch at the auth boundary
A product may ship both: Daylight for its public surface, Mission for the app behind the login. Switch once, at sign-in — never per-page.
One-way opt-in
A Daylight product may offer Mission as an opt-in dark mode. A Mission product must not silently flip to Daylight.
Chrome is theme-conditional
Scanlines, corner brackets and the atmosphere grid are Mission-only. Daylight carries the brand through mono labels, the // prefix, the mint and the spacing — not through darkness.
<html data-theme="daylight"> /* mission is the default when the attribute is absent */ :root, [data-theme="mission"] { --bg-base: #0a0c10; /* … */ } [data-theme="daylight"] { --bg-base: #f6f8f7; /* … */ }
02

Color

Both themes expose the same variable names, so components are written once. Reference the variable, never the literal hex.

TokenMissionDaylightUse
--bg-base#0a0c10#f6f8f7page background
--bg-surface#0d1117#ffffffcards · panels
--bg-surface-hover#0f1520#eef3f0interactive hover
--bg-inset#0a1410#e8f5eebadges · recessed areas
TokenMissionDaylightUse
--border#1a2a20#dde5e0card borders · dividers
--border-hover#2a4a38#9dc4b0card hover border
--border-subtle#1a3020#e6ede9badge borders · faint rules
--border-grid#111820#e9efebbackground structure
TokenMissionDaylightUse
--text-heading#e8f4ff#0b1a14page & card titles
--text-body#c8d8e8#26332dprimary body text
--text-muted#84a89a#43564cdescriptions
--text-subtle#7d9b8c#4a5d54subtitles · mono metadata
--text-label#6e8f80#52655bsection labels · placeholders
--text-dim#61856d#61746bfooter chrome — decorative only
TokenMissionDaylightUse
--accent#3af0a0#3af0a0brand fill — button/badge background
--accent-hover#6ff7be#22dc8c--accent under hover — keeps --accent-on text
--accent-ink#3af0a0#0b7a4eaccent as text · icon · border
--accent-on#08150f#08150ftext on top of --accent
--accent-2-ink#2a7adf#1f5fbfsecondary accent
--danger-ink#ff4a24#c02a10error · destructive
--warning-ink#f5b83d#8a5a00warning · caution
TokenMissionDaylightUse
--accent-wash#3af0a014#0b7a4e12selected / active wash — @ 8%
--accent-line#3af0a050#0b7a4e45accent border — @ 31%
--accent-bracket#3af0a040#0b7a4e30corner brackets — @ 25%
TokenMissionDaylightVerdict
--text-heading17.5 : 116.8 : 1AAA
--text-body13.5 : 112.4 : 1AAA
--text-muted7.5 : 17.4 : 1AAA
--text-subtle6.5 : 16.6 : 1AA+
--text-label5.5 : 15.8 : 1AA
--text-dim4.6 : 14.7 : 1AA — lowest rung, still legible
--accent-ink13.2 : 15.0 : 1AA
--accent is a fill, not an ink
Mint #3af0a0 is 1.4:1 on white. In Daylight use it as a button or badge background with --accent-on text. For accent text, icons and 1px borders use --accent-ink, which darkens to #0b7a4e.
every rung clears AA, --text-dim included
Almost everything on the bottom three rungs is 12px Share Tech Mono, whose hairline stems go grey on a 1× display. Contrast is what buys them back, so nothing sits under 4.5:1. --text-dim is still the lowest rung — footer chrome and the backlink, never a form placeholder. Use --text-label for that.
SELECTED ERROR CAUTION
03

Typography

Eyebrow / System Label
// RV Power Systems
Share Tech Mono · 12px · ls: 0.2em · uppercase · accent color
Page Title
RV Diagrams
Rajdhani 700 · 36px (26px below 768px) · ls: 3px · uppercase · heading color
Section Heading
Battery Box Structure
Rajdhani 700 · 28px · ls: 2px · heading color
Card Title
Battery Box Structure
Rajdhani 700 · 20px · ls: 1px · heading color
Body Text
3D exploded view of the dual LiFePO4 battery bank — wood frame, foam padding, terminals, bus cables, and output leads.
Rajdhani 500 · 15px · lh: 1.6 · muted color
Stat Value
12V / 24V
Share Tech Mono · 17px · ls: 0.06em · accent color
Subtitle / Description
Interactive 3D component maps — open in any browser
Share Tech Mono · 13px · ls: 0.1em · subtle color
04

Components

System Voltage
12V / 24V
Battery Type
LiFePO₄
Components
7 PARTS
Terminal (+) Bat1
Brass/Copper
Positive terminal — Battery #1. Output (+) lead exits here.
12V / 24V LiFePO4 2x 100Ah Parallel 2 AWG Red
// RV Power Systems
BATTERY BOX
STRUCTURE
Exploded view · Hover to inspect
Voltage
12V
Capacity
200Ah
// Materials
Active Component
Wiring Path

DRAG — Rotate

SCROLL — Zoom

HOVER — Inspect

05

Controls

Buttons and fields are mono, uppercase and tracked — they read as system controls in both themes. Flip the theme in the masthead to check either one.

Primary — solid
The single loudest action on a view. One per screen — a hero CTA or a form submit.
Secondary — wash
The HUD default for in-app actions. A solid mint slab repeated is too loud inside Mission chrome.
Ghost — neutral
Everything else. Secondary navigation, dismissals, low-stakes choices.
Danger
The state recipe applied to --danger-ink. Outline at rest, fills on hover.
Sizes
btn-lg for hero CTAs, btn-sm for nav and table rows.
Disabled
No new colors — drops to the low-emphasis ramp: --text-label on --border-subtle.

We’ll email you a sign-in link. No password to remember.

Not a valid address.

Locked to your organisation.

16px inputs, always
Anything smaller triggers zoom-on-focus in mobile Safari. Field text is Rajdhani 16px / 500 even though the label above it is 12px mono.
Placeholders use --text-label
Never --text-dim. A placeholder people can’t read is worse than no placeholder.
Labels carry the // prefix
A field label is system commentary, same as a section label. // Email, not Email.
Help text is a sentence
Chrome is terse; anything a stranger reads is plain English. Help and error copy are written for humans, not operators.
06

Patterns

Page-level compositions. A user-facing product needs a landing page before it needs a login box, and every product needs the same chrome once someone is signed in — these are the shapes that keep showing up.

// patterns/landing.html · daylight Open full page →
Required order
Nav → hero → proof strip → how it works (3 numbered steps) → feature grid → CTA band → footer. 96px between bands, 64px below 768px.
Hero anatomy
Eyebrow → hero title → lede (one sentence, ≤ 90 chars) → action row (btn-primary btn-lg + btn-ghost btn-lg) → mono trust line. Max-width 720px centered.
Reuse the numerals
The 01 / 02 / 03 mono numerals from the section-head pattern carry straight into “how it works” steps. No new component.
One container
Every band shares one max-width: 1080px; margin: 0 auto; padding-inline: 48px inner container so edges line up down the page.
// patterns/auth-split.html · daylight Open full page →
// patterns/auth-centered.html · mission Open full page →
A bare form is not an auth screen
A centered input on an empty field gives a first-time visitor nothing to decide with. Say what the product does before asking for an address.
Split — user-facing default
50/50 above 900px, stacked below. Left: the pitch — eyebrow, product name, one-line lede, three mono checkpoints on --bg-inset. Right: the form card.
Centered — operator sign-in
A single 400px card. Only appropriate when everyone signing in already knows what the product is — staff tools, not products strangers land on.
Name the mechanism
“We’ll email you a link — no password.” Never let the button be the only text on screen.
// patterns/app-shell.html · mission Open full page →
Three pieces, every product
.app-bar (brand · nav · session) → .app-main with one .page-header → .app-footer (ident · links · backlink). Moving between products should feel like moving between rooms of one building.
Chrome is surface, content is base
Bar and footer sit on --bg-surface; the view sits on --bg-base. That one-step lift is the whole hierarchy — no shadows, no heavier borders. 56px bar, 16px footer, both full-bleed.
One user menu, top-right
Initials chip + email opens a panel: who you are, the account items, then Sign out last — ruled off, --danger-ink on hover. Same order in every product. Status stays outside; it’s system state, not user state.
Not the landing nav
.nav is 64px on --bg-base with a CTA. .app-bar is 56px on --bg-surface with none, and the mark replaces the // Rising eyebrow. Switch at the auth boundary, with the theme.
The way home
by rising.company sits 12px after the wordmark and is the link back — same tab, every product, always there. The brand itself goes to the product’s home, never to Rising. .app-context is only for a real tenant or environment.
// patterns/app-shell-sidebar.html · mission Open full page →
// app-shell.html · 375px
// app-shell-sidebar.html · 375px
One mobile form
Below 768px every product wears the same chrome: brand + session on row one, then the nav as a 44px touch row that scrolls under the gutters with a fade at each edge. A sidebar product hides its sidebar and renders that same bar — modules become the nav row, the org switcher moves into the user menu, build and backlink into the footer. No drawer, no hamburger.
No huddles yet
Create one and share the link — people mark their times without signing up.

Eyebrow → one-line explanation in --text-muted → one btn-secondary. Centered, max-width 420px, 96px vertical padding. Never a bare “No results.”

The one page pattern nobody visits and everybody sees. A product travels by link, so the card is its first impression more often than its home page is — and it earns that by making the product’s argument out of the product’s own data, not by putting a wordmark on a colored rectangle. 1200 × 630, Daylight always, shot at 2×.

// patterns/og-card.html · daylight Open the template →
This site's own link preview card: the same console panel rendered twice, dark under Mission and light under Daylight, over the shared token names.
// as a feed renders it · 350px
The same card at the width a social feed gives it.
Six parts
Edge rule (the arrow’s gradient) → eyebrow // product.rising.company → headline with the decisive value in --accent-ink → one-sentence lede → the evidence band → footer rule with legend left, stamp right.
It has to read at 350px
Feeds downscale the card about 3×. Headline ≥ 48px, lede ≥ 24px, nothing mono under 14px, and no two states told apart by a hairline or a wash — --accent-wash disappears at that size.
Stamp the URL
Scrapers cache og:image by URL. A regenerated card behind an unchanged URL serves last month’s numbers for days — so the image carries ?v=YYYY-MM-DD, bumped in the commit that replaces the PNG.
Pin it with a test
A card built from product data goes stale the moment the data moves and nothing notices. Assert the numbers on the committed PNG against what the data now produces, and the stamp against the data’s timestamp.
07

Motion

Animation quality is the first priority of the design. Motion is the first thing a person feels on a screen and the first thing that reads as cheap when it is wrong — one mistimed panel undoes careful type and color in a single frame. So motion is designed, not added. Before an animation is written, answer what moves, why, how it enters, how it leaves, and what it does under reduced motion. No answer → no animation. A still view beats a careless one.

Everything beyond CSS hover and focus transitions is built on Motion — one engine, one set of curves, so every product moves the same way. Identical in Mission and Daylight.

// npm i motion import { motion, AnimatePresence, MotionConfig, useReducedMotion } from "motion/react" import { animate, stagger } from "motion" // vanilla / non-React // wrap every React app root once — springs by default, reduced motion honoured <MotionConfig reducedMotion="user" transition={{ type: "spring", visualDuration: 0.3, bounce: 0 }}>
No hand-rolled setTimeout / requestAnimationFrame / class-toggle choreography. No second engine (GSAP, react-spring, anime.js). Plain CSS transition stays for hover, focus and color.
TierValueUse
Quick0.2s ease · { duration: 0.2, ease: "easeOut" }Hover, focus, color, border, opacity — the transition on every control
Basespring · visualDuration 0.3 · bounce 0Anything that moves or resizes: menus, panels, drawers, toasts, rows, layout changes
Slowspring · visualDuration 0.5 · bounce 0  /  0.6s ease revealWhole surfaces: page reveal, route change, modal and scrim
Ambient≥ 2.4s ease-out, loopingThe status pulse — and nothing else
Panel · Base
Profile
Preferences
Sign out
Enters y 4 → 0, scale 0.98 → 1 from its anchor on the Base spring. Exits in 0.15s, fade-led. Toggle it mid-flight — it reverses from where it is.
Stagger · 60ms
Huddle · open
Venue · open
Safe · open
OS · open
Rows enter y 8 → 0 with opacity, 60ms apart, capped at eight. Past eight, batch — a 30-row table does not enter one row at a time.
Load Reveal · Slow
Sections rise 8px and fade in, 90ms stagger — the page you are reading booted like an instrument panel.
0.6s ease · one reveal per page · off under prefers-reduced-motion, content fully visible.
Motion has a job
Reveal, confirm, orient or connect. Name the job in the code. If you can’t, cut the animation.
Transform & opacity only
x · y · scale · rotate · opacity. Never width, height, top, left, margin, padding, box-shadow or filter — size and position changes go through layout.
Never block input
Nothing waits on an animation; a user can click through a reveal. Nothing runs longer than Slow except the status pulse.
One entrance per view
The page reveals, or the panel opens — a section that is revealing does not also stagger the cards inside it.
Loops are for live state
The status dot pulses because the system is live. A skeleton may breathe on opacity. Nothing else loops, shimmers or spins.
Reduced motion is a state
Not a fallback. Transforms off, opacity kept, content at its final state. Verify with the OS setting on, not by assumption.
60fps on a 1× machine
Test with CPU throttling at 4×. If it drops frames, simplify — fewer elements, no blur, no layout on long lists.
Review it in motion
A screenshot cannot approve an animation. Watch entrance, exit, mid-flight interruption and reduced motion live before merging.
Enter / reveal
y: 8 → 0 with opacity — sections, cards, toasts.
Menus · popovers
y: 4 → 0 · scale: 0.98 → 1, growing from their anchor via transformOrigin.
Exits
About 0.6× the entry, fade-led, inside AnimatePresence. Nothing pops out of existence.
Never
Scale from 0. Slide from off-screen unless it lives there (a drawer). Bounce — bounce: 0, always.
08

Effects & Interaction

Scanlines Mission only
Fixed overlay on every Mission page — --chrome-scanline lines, 4px rhythm. The token is transparent in Daylight, so the same rule goes inert. Shown exaggerated.
Corner Brackets Mission only
32px L-borders at viewport corners — --accent-bracket, 16px inset. Hidden in Daylight via --chrome-bracket-display.
Hover Gradient
2px --gradient bar at card top — opacity 0 → 1 on hover. Mint → blue in Mission, deep green → blue in Daylight.
Focus Ring
:focus-visible — 1px --accent-ink outline, 3px offset. Keyboard only, never on click.
Selection
Select this text — mint highlight with dark type in both themes. Every copy action carries the brand.
::selection — background --accent, color --accent-on. Mint is a fill, so it holds in Daylight unchanged.
09

Voice & Tone

Prefix
Slash-slash opens a region — once. The eyebrow, the label over a group, the footer ident: // Sign in. Never on data, items in a set (cards, fields, list items) or controls. More than about four in a viewport and it has stopped meaning anything.
Case Rules
UPPERCASE for eyebrows, labels, page titles, stat labels. Normal case for titles, body, tooltips.
Separators
Em dash joins — middle dot separates. SYSTEM A · SYSTEM B
Copy Style
Terse fragments for chrome — plain sentences for anything a stranger reads. Ledes, help and error copy are written for humans, not operators. No exclamation marks. No emoji.
10

Brand Assets

Everything lives in /branding/ and is served from design-system.rising.company/branding/. Reference by URL or copy the file — never redraw the mark. The icon always sits on the dark #0a0c10 base, in both themes.

Rising Company favicon, SVG
favicon.svg
Tab icon · preferred
Rising Company favicon, 512px PNG
favicon.png
512 · alpha · PWA / OG
Rising Company favicon, 1024px PNG
favicon-xl.png
1024 · store listings
Rising Company Apple touch icon, 180px
apple-icon.png
180 · opaque · square — iOS masks it
Rising Company horizontal wordmark on white
rising-logo-white.png
2026×898 · white background · Daylight surfaces on white only. No dark-safe wordmark yet — on Mission use the mark + product name in Rajdhani.
Wire itWhere
<link rel="icon" type="image/svg+xml" href="…/branding/favicon.svg">Any HTML head
<link rel="apple-touch-icon" sizes="180x180" href="…/branding/apple-icon.png">Any HTML head
app/icon.png · app/apple-icon.pngNext.js App Router — copy the files in; the framework emits the links
rising-logo-transparent.pngCheckerboard is baked in (no alpha). Do not place on a page.