Lipi·design
Design System · v1 · 2026-04-15

Industrial Atelier × Soft Glow

One design language — near-black stage, warm bone ink, a single saturated green that carries every action. Tactile orbs for relays, editorial italic for emphasis, JetBrains Mono for the technical voice. Ships to web, iOS, Android, Mac Catalyst from the same tokens below.

Maintained by
Lipi Studio
lipi.uncloud.club
§ 01

Palette

A deep near-black stage lets one saturated green — #22e07a — carry every action. Voice states get their own chromatic identity so input, execution, and reply are unambiguous.
Stage
--bg
#0a0b0e
Surface
--surface
rgba(22,24,30,0.72)
Well
--surface-well
#0c0d11
Ink
--text
#e8e4d6
Dim
--dim
#74707a
On · Accent
--on
#22e07a
Error
--err
#ff6a6a
Editorial Gold
--accent
#d6c29a
Voice · Listen
--listen
#6bf0d0
Voice · Think
--think
#ffae6e
Voice · Speak
--speak
#c9a4ff
§ 02

Typography

Mono first, serif for emphasis. JetBrains Mono 300/400/500/600 is the technical voice — labels, buttons, meta. Instrument Serif Italic carries the human voice — headings, transcripts, quiet moments.
Display · Instrument Serif Italic · 56/1.05 · −1px
Your home, in your voice.
font-family: 'Instrument Serif', serif · font-style: italic · font-weight: 400
Heading · Instrument Serif Italic · 28/1.1 · −0.5px
Every relay is a breath of light.
font-size: 28px · color: var(--text-hi)
Body · Instrument Serif · 17/1.55
Press and hold to speak. Release and the room responds — softly, precisely, in the language you actually use at home. Hindi, English, Hinglish — Lipi hears you the way your family does.
Used for transcripts + replies in the voice overlay, emptystate messages, long-form lede copy.
Mono · Hi · 500
Lipi·3EF9
Brand lockup + device identifiers · 16px / 500
Mono · Md · 400
+918104515596 · online
Body mono · 13px · session / device meta
Mono · Sm · 3px tracking
Section · label · button
10px · uppercase · letter-spacing 3px
Readout
94:e6:86:2a:6d:d8
MAC addresses, pair codes, user ids · 18px / 500 · --text-hi
§ 03

The Orb

The single most important primitive in Lipi. Every relay is an orb. On the web it's pure CSS (radial gradients + inset shadows + outer glow). On iOS/Android the spec translates to RadialGradient layers + shadow. Tap to toggle.
Press the orbs
ON
OFF
ON
// CSS · the orb is fully declarative — no JS, no canvas.
.orb {
  width: 82px; height: 82px; border-radius: 50%;
  background:
    radial-gradient(circle at 32% 28%, rgba(255,255,255,.05) 0%, transparent 24%),
    radial-gradient(circle at 50% 55%, #1a1c22 0%, #0b0c10 68%, #06060a 100%);
  box-shadow:
    inset 0 -7px 14px rgba(0,0,0,.65),
    inset 0 4px 8px rgba(255,255,255,.035),
    0 3px 14px rgba(0,0,0,.55);
  /* on state swaps the body gradient + adds outer glow */
}
.orb.on {
  background:
    radial-gradient(circle at 30% 26%, rgba(255,255,255,.75) 0%, transparent 22%),
    radial-gradient(circle at 50% 50%, #5cff9f 0%, #22e07a 42%, #118a4d 76%, #053b1f 100%);
  box-shadow:
    0 0 38px 6px rgba(34,224,122,.55),
    0 0 76px 16px rgba(34,224,122,.22),
    inset 0 -8px 16px rgba(0,0,0,.40),
    inset 0 6px 12px rgba(255,255,255,.32);
}
Full relay cell
Kitchen Light
ON
Bedroom Fan
OFF
§ 04

Components

A disciplined kit: one primary button, one ghost, one danger. Inputs share a single chamfered shape. Cards are glass-layered with a 1px hair-line border.
Buttons
Inputs
Device card — the whole package
Lipi 94:e6:86:2a:6d:d8
Kitchen
ON
Bedroom
ON
Hall
OFF
Balcony
OFF
§ 05

Voice

Four distinct states — idle, listen, think, speak — each with its own chromatic identity, so the user always knows whether they're providing input, the system is executing, or Lipi is replying.
State chips
idle listening executing speaking
// State machine — drive everything from data-state on the overlay root.
const STATE_MIX = { idle: 0.0, listen: 0.33, think: 0.66, speak: 1.0 };
const STATE_VERB = {
  idle:   'Hold to speak',
  listen: 'Listening',
  think:  'Executing',
  speak:  'Speaking',
};
// The shader uniform interpolates smoothly between these anchors.
uniforms.uStateMix.value += (target - uniforms.uStateMix.value) * 0.06;
Audio reactivity — three bands
BandDrivesEffect
Bass · 0–8 binsuBassVertex displacement + outer halo scale + base glow
Mid · 8–64 binsuMidHue shift + rim saturation
Treble · 64–256 binsuTrebleChromatic aberration (R/G/B rim split)
§ 06

Tokens

Canonical values. Every client consumes these — CSS vars on web, Color extensions on iOS, MaterialTheme tokens on Android. Change one here; change everywhere.
Radii + Spacing + Shadow
TokenValueUse
--r-sm8 pxButtons, inputs, chips, toasts
--r-md12 pxInline cards, thumbnails
--r-lg18 pxPanels, relay cells, modals
--r-xl24 pxDevice card wrapper
--sp-1 … --sp-104 · 8 · 12 · 16 · 22 · 32 · 48 · 724pt base, skip 20 + 56 + 64
shadow-card0 14px 40px rgba(0,0,0,0.45), inset 0 1px 0 rgba(255,255,255,0.03)Glass panels + device card
shadow-orb-on0 0 38px 6px rgba(34,224,122,0.55), 0 0 76px 16px rgba(34,224,122,0.22)Relay ON halo
blur-glassbackdrop-filter: blur(10px)Every panel/card
Cross-platform mapping
TokeniOS (SwiftUI)Android (Compose)
--bgColor(hex: 0x0A0B0E)Color(0xFF0A0B0E)
--onColor.accentMaterialTheme.colorScheme.primary
JetBrains MonoFont.custom("JetBrainsMono-Medium", size:)FontFamily(Font(R.font.jetbrains_mono_medium))
Instrument Serif italicFont.custom("InstrumentSerif-Italic", size:)FontFamily(Font(R.font.instrument_serif_italic))
Orb ON bodyRadialGradient + .shadow(.green, 38) + .shadow(.green, 76)Brush.radialGradient + Modifier.shadow(glow)
§ 07

Motion

Nothing snaps. Everything eases out with cubic-bezier(0.22, 1, 0.36, 1). Voice-orb state transitions are interpolated across six-frames at 0.06 per frame — silky, not jumpy.
TokenValueUse
--ease-outcubic-bezier(0.22, 1, 0.36, 1)Default. Buttons, cards, state fades.
--ease-in-outcubic-bezier(0.65, 0, 0.35, 1)Modal in/out, overlay fade.
dur-tap100 msButton press (transform: scale(0.98))
dur-state250–350 msOrb color shift, border glow
dur-modal450 msVoice overlay fade-in
loop-pulse1.1 s ease-in-outStatus dot during listen/speak