← Journey
Alt Shift Design System v1

The Spec

Twelve chapters of exploration distilled into a practical system. Tokens, atmosphere classes, and three primitives. Everything on this page IS the system, demonstrating itself.

Change the atmosphere dials below and watch this entire page respond. Every card, every button, every heading reads the same cascading variables.

01 — The Foundation

Five Dimensions, One Vocabulary

Every screen, every moment, every interaction has coordinates across these five dimensions. Declare them on your page root and the cascade does the rest.

Space

Where are you in the building? From entrance through to vault.

Atmosphere

What kind of engagement does this moment ask for?

Depth

How many layers does this content have?

Flow

How should challenge relate to the user here?

Juice

How much should the interface respond? Silent through celebratory.

02 — Live Atmosphere

Set the Dials

The whole page has an atmosphere right now. These controls change it in real time.

Space
Atmosphere
Depth
Flow
Juice
<div className="as-page as-space-workshop as-atmo-browsing as-depth-1 as-flow-gentle as-juice-2">
  {/* your content */}
</div>
03 — Tokens · Colour

One Hue, A Whole Palette

The entire colour system derives from a single --as-hue value. Everything else is computed via oklch() for perceptual uniformity.

Ground
--as-ground
Surface
--as-surface
Raised
--as-surface-raised
Deep
--as-surface-deep
Border
--as-border
Accent
--as-accent
Accent soft
--as-accent-soft
Warmth
--as-warmth
04 — Tokens · Spacing

Fibonacci Spacing

Every gap, padding, and margin is drawn from the Fibonacci sequence. Each step is ≈ φ × the previous. The ratios match the type scale.

--as-space-2xs
3px
whisper gap
--as-space-xs
5px
tight gap
--as-space-sm
8px
component padding
--as-space-md
13px
card padding
--as-space-lg
21px
section gaps
--as-space-xl
34px
page sections
--as-space-2xl
55px
hero spacing
--as-space-3xl
89px
page margins
05 — Tokens · Type

Fibonacci Type Scale

Font sizes follow Fibonacci. Each step ≈ φ × the previous. Line height at 1.618 (golden ratio) for body text.

--as-text-xsCaption
The quiet label
--as-text-smSecondary
Supporting text and metadata
--as-text-baseBody
The everyday reading voice
--as-text-lgSubheading
A slightly raised voice
--as-text-xlHeading
A clear declaration
--as-text-2xlLarge
An announcement
--as-text-3xlDisplay
The moment
06 — Tokens · Motion

Easing & Duration

Four easing curves and five durations. Every animation chooses from this vocabulary.

Easings
--as-ease-snap
Dismissals, closures — fast out
cubic-bezier(0.2, 0, 0, 1)
--as-ease-smooth
Transitions, content arrivals
cubic-bezier(0.22, 1, 0.36, 1)
--as-ease-bounce
Juice response, press release
cubic-bezier(0.34, 1.56, 0.64, 1)
--as-ease-settle
Arrivals from motion to rest
cubic-bezier(0.22, 0.68, 0, 1.71)
Durations
--as-dur-instant80ms
state toggles
--as-dur-fast150ms
hover, focus, press
--as-dur-normal250ms
card lift, content shift
--as-dur-slow400ms
page transitions
--as-dur-dramatic700ms
celebrations, reveals
07 — Primitives · Card

Card — Fractal Container

The same container at every scale, with subtle per-level shifts. Set depth to nest. Each level rotates hue, tightens spacing, deepens shadow.

Depth 0

The outermost level. Light, spacious, primary container.

Depth 1

Nested inside. Slight hue shift, tighter spacing.

Depth 2

Deeper still. Warmth starts to emerge.

Depth 3

The inner sanctum. Warmth visible, close and intimate.

<Card depth={0} label="Overview">
  <Card depth={1} label="Detail">
    <Card depth={2} label="Deeper">
      {/* The same component, self-nesting */}
    </Card>
  </Card>
</Card>
08 — Primitives · Button

Button — Tactile Response

Three variants. Juice level inherited from atmosphere — change the juice dial above and press these to feel the difference. Or override per-button with the juice prop.

Variants
Juice override — press each to feel the difference
<Button variant="primary">Continue</Button>
<Button variant="primary" juice={4}>Complete course</Button>
<Button variant="ghost">Cancel</Button>
09 — Primitives · Heading

Heading — Semantic + Scaled

Semantic levels 1-6 map to the Fibonacci type scale. Optional eyebrow adds a small monospaced label above.

DisplayThe name

LargeA declaration

A clear section

A subsection

A quiet title
The smallest voice
<Heading level={1} eyebrow="Chapter 01">
  The Memory Palace
</Heading>

<Heading level={3}>Subsection</Heading>
10 — Primitives · Text

Text — The Reading Voice

Five levels, five tones. Body text gets golden-ratio line-height and text-wrap: pretty automatically. Lead text gets balance.

CAPTION · DIM

Small text in faint tone — supporting metadata, secondary info.

Body text is the everyday reading voice. Line-height sits at the golden ratio (1.618), producing natural space for the eye to travel between lines. Max-width constrained to ~55 characters for optimal readability.

Lead text is larger, warmer, and balanced. Used for opening statements, hero paragraphs, and pull quotes that introduce a section.

And quote text with the italic voice and accent border — the way a pull quote emerges from body text.
<Text level="lead" tone="default" maxWidth="prose">
  The opening voice of a section.
</Text>

<Text level="body" tone="muted">
  Everyday reading with golden-ratio line-height.
</Text>
11 — Primitives · Container

Container — The Layout Anchor

Four max-widths drawn from Fibonacci/golden proportions. Horizontal padding scales with viewport via clamp(). Never sets a background — that's atmosphere's job.

narrow — 480px — for focused CTAs and forms

prose — 620px — for reading content (optimal measure)

wide — 960px — for dashboards and multi-column layouts

full — no max — for hero sections and canvases

<Container width="prose" pad="lg">
  <Heading level={1}>The main content</Heading>
  <Text level="body">Readable max-width, automatic viewport padding.</Text>
</Container>
12 — Primitives · Input

Input — The Quiet Voice of the Form

Label above. Helper text below that emerges on focus. 44pt minimum height. 16px font-size prevents iOS zoom. Accent glow on focus — no harsh browser ring.

This appears on your profile and certificates.
We'll never share this.
Markdown supported.
This field is required.
<Input
  label="Your name"
  placeholder="Hosam"
  helper="This appears on your profile."
  value={value}
  onChange={(e) => setValue(e.target.value)}
  block
/>

<Input multiline rows={4} label="Bio" block />

<Input error="This field is required." />
13 — Primitives · Nav

Nav — The Landmark System

Responsive by default. Top bar on desktop with landmark + items + trailing. Bottom tabs on mobile in the thumb zone. Safe-area aware for modern iPhones. Same component, two shapes, no breakpoint JS.

LIVE PREVIEW (ACTIVE: HOME)
On mobile, the same component renders as a sticky top landmark bar + a bottom tab bar in the thumb zone. Resize this window to see it.
<Nav
  landmark={<Logo />}
  items={[
    { id: "home", label: "Home", icon: <Icon.Home />, active: true },
    { id: "library", label: "Library", icon: <Icon.Library /> },
    { id: "profile", label: "You", icon: <Icon.User /> },
  ]}
  trailing={<Avatar />}
/>
14 — Primitives · Modal

Modal — The Portal to Depth

Not a harsh rectangle on top. The surrounding atmosphere dims and warms slightly. Bottom sheet on mobile, centered on desktop. Spring entrance, escape to close, focus trap, body scroll lock.

const [open, setOpen] = useState(false);

<Button onClick={() => setOpen(true)}>Open</Button>

<Modal
  open={open}
  onClose={() => setOpen(false)}
  eyebrow="Chapter 02"
  title="The title of the modal"
  footer={
    <>
      <Button variant="ghost" onClick={() => setOpen(false)}>Cancel</Button>
      <Button variant="primary">Confirm</Button>
    </>
  }
>
  <Text>Body content inside the modal.</Text>
</Modal>
15 — The System Prompt

For Claude and Developers

Point Claude (or a developer) at this system prompt when building a new feature. It declares the vocabulary and the rules in plain language.

System prompt
# Alt Shift Design System v1

You are building UI for Alt Shift products. Before writing any JSX,
declare the five-dimension coordinates for this screen:

- space: entrance | lounge | workshop | study | vault
- atmo: peripheral | browsing | transitional | focused | immersed | celebrating
- depth: 0 | 1 | 2 | 3 | 4
- flow: restful | gentle | matched | stretching | peak
- juice: 0 | 1 | 2 | 3 | 4

Apply them to the page root as CSS classes:
<div className="as-page as-space-{space} as-atmo-{atmo} as-depth-{depth}
                as-flow-{flow} as-juice-{juice}">

Then build with these primitives from @/components/as:

Containers
- <Card depth={0..4} label="..." variant="raised|flush|deep">
    Fractal container. Self-nesting with per-level hue shift and warmth.
- <Container width="narrow|prose|wide|full" pad="none|sm|md|lg|xl">
    Layout anchor. Auto horizontal padding via clamp().

Content
- <Heading level={1..6} eyebrow="..." size="..." weight={...}>
    Fibonacci-scaled semantic heading.
- <Text level="caption|small|body|lead|quote" tone="default|muted|faint|dim|accent" maxWidth="prose">
    Reading voice. Golden-ratio line-height on body.

Actions
- <Button variant="primary|secondary|ghost" size="compact|standard" juice={0..4}>
    Tactile. Inherits juice from atmosphere unless overridden.

Forms
- <Input label="..." helper="..." error="..." variant="text|email|..." multiline>
    Label above, helper emerges on focus. 44pt min, iOS-zoom-safe.

Navigation
- <Nav shape="responsive|top|bottom" landmark={...} items={...} trailing={...}>
    Responsive by default: top bar desktop, bottom tabs mobile (thumb zone).

Overlays
- <Modal open onClose eyebrow title footer width="narrow|prose|wide">
    Portal to depth. Bottom sheet mobile, centered desktop. Warm ambient glow.

Rules:
- Never hard-code colours. Use var(--as-*) tokens only.
- Never hard-code spacing. Use var(--as-space-{2xs|xs|sm|md|lg|xl|2xl|3xl}).
- Never hard-code font sizes. Use var(--as-text-{xs|sm|base|lg|xl|2xl|3xl}).
- Primary actions in the thumb zone on mobile.
- 44pt minimum tap targets.
- Staggered content arrival: wrap groups in className="as-arrive-stagger".
- Dark ground always. Light emerges from darkness.
- Reach for <Text> before raw <p>. Reach for <Container> before raw div.

The flavour is already baked in. Your job is to declare the coordinates
and trust the cascade.
16 — What Comes Next

This is v1 of the complete primitive set: Card, Button, Heading, Text, Container, Input, Nav, and Modal. Eight components covering the common UI needs of any Alt Shift product.

Next passes will add: an Atmosphere React provider for reading coordinates from JS, a ProgressiveContent pattern for earned depth, particle systems as a drop-in atmosphere layer, haptic hooks, and sound primitives. The canonical blueprint — to be used in any product session — lives at /docs/ALT-SHIFT-DESIGN-SYSTEM.md.