Luminous Blue · 2027

DashOne Design System

The complete, portable token and component reference behind dashone.ai — for reuse whenever you're building a new landing page, report, or self-contained artifact that should look and feel like a DashOne property.

Source: dashone.ai repo Astro + plain CSS custom properties Generated 04 Aug 2026

Contents

01 — Color

Color system & the 60-30-10 rule

Three color roles, mixed in fixed proportion. This ratio is the single most important rule in the system — get it right and everything else (contrast, hierarchy, restraint) follows.

60% Neutrals
30% Structure
10% Blue

60% — Neutrals (backgrounds, content areas)

Page backgrounds, card surfaces, section alternates. The silent base layer — it never competes with blue.

--color-chalk#F7F6F2Default page bg (light)
--color-warm#EDE8D8Section alternates, card bg
--color-maize#F5E6A3Highlight bg, callout blocks
--color-stone#D8D6CEDividers, inactive borders
--color-ash#888780Placeholder text, disabled
--color-ink#444441Secondary text
--color-void#1C1A18Primary text (light mode)

30% — Structure (nav, footer, sidebars, dividers)

Anchors the layout. Never blue here.

--color-deep-green#1C2130Nav / footer bg — slate azulado oscuro
--color-forest#252C3ESub-nav, secondary sidebars
--color-pine#1E2A22Verde discreto casi negro, minimal accent
--color-dust#38405ADividers / borders on dark surfaces
--color-sage#C6E8D4Light tint for badges over pine

10% — Luminous Blue (CTAs only)

Max 2 blue tokens in the same viewport. Never as body text, never as a section background.

--color-lb-ice#EAEBFFTinted bg fills (not text)
--color-lb-ghost#C5C8FFLight borders, disabled states
--color-lb-mist#7B80FFDark-mode text on blue surfaces
--color-lb-glow#4B52FFHover state only
--color-lb-vivid#2328FFHigh-energy accents
--color-lb-core#1B1FE8PRIMARY — buttons, active links, badges, focus rings
--color-lb-deep#0E11B0Active / pressed state

Dark-mode surfaces

--color-dark-bg#0A0B1APage background
--color-dark-surface#12152BCard / panel surface
--color-dark-card#1A1E38Elevated card
--color-dark-border#252847Subtle border
--color-dark-muted#3A3D5CDisabled / muted border

Semantic status colors

--color-success#1A5C42bg pair: --color-success-bg #C6E8D4
--color-warning#B07D00bg pair: --color-warning-bg #FFF3C4
--color-error#A32D2Dbg pair: --color-error-bg #FCEBEB
--color-info= lb-corebg pair: --color-info-bg = lb-ice
Contrast — verified, not assumed White on --color-lb-core passes AA (4.8:1) — use it for button labels. --color-lb-core on white/chalk fails AA as text — never use it for body copy or links on a light surface. In dark mode, lb-core on --color-dark-bg reads as clean neon with no extra effects needed; for dark-surface cards use --color-lb-mist instead of lb-core — lb-core on a dark card surface lands around 2:1, which fails AA.
--color-lb-ice:    #EAEBFF;
--color-lb-ghost:  #C5C8FF;
--color-lb-mist:   #7B80FF;
--color-lb-glow:   #4B52FF;
--color-lb-vivid:  #2328FF;
--color-lb-core:   #1B1FE8;
--color-lb-deep:   #0E11B0;

--color-chalk:     #F7F6F2;
--color-warm:      #EDE8D8;
--color-maize:     #F5E6A3;
--color-stone:     #D8D6CE;
--color-ash:       #888780;
--color-ink:       #444441;
--color-void:      #1C1A18;

--color-deep-green:#1C2130;
--color-forest:    #252C3E;
--color-pine:      #1E2A22;
--color-dust:      #38405A;
--color-sage:      #C6E8D4;

--color-dark-bg:      #0A0B1A;
--color-dark-surface: #12152B;
--color-dark-card:    #1A1E38;
--color-dark-border:  #252847;
--color-dark-muted:   #3A3D5C;

--color-success:   #1A5C42;  --color-success-bg:#C6E8D4;
--color-warning:   #B07D00;  --color-warning-bg:#FFF3C4;
--color-error:     #A32D2D;  --color-error-bg:  #FCEBEB;
--color-info:      var(--color-lb-core);
--color-info-bg:   var(--color-lb-ice);

02 — Typography

Type system

Fraunces for anything that should feel editorial and considered. DM Sans for everything functional. Never Inter, Roboto, Arial, or system-ui as a primary face.

--font-display

Fraunces

Display / hero headlines · Georgia, serif fallback

--font-body

DM Sans

Body copy, UI · system-ui fallback

--font-mono → JetBrains Mono, 'Courier New', monospace

Type scale — 1.25 Major Third

TokenSizeUsed forPreview
--text-xs0.64rem / 10.2pxlabels, badgesThe quick brown fox
--text-sm0.8rem / 12.8pxcaptions, metaThe quick brown fox
--text-base1rem / 16pxbodyThe quick brown fox
--text-md1.25rem / 20pxlead / introThe quick brown fox
--text-lg1.563rem / 25pxh3The quick brown fox
--text-xl1.953rem / 31pxh2The quick brown
--text-2xl2.441rem / 39pxh1The quick
--text-3xl3.052rem / 48.8pxdisplayThe quick
--text-4xl4rem / 64pxhero (fixed)Quick
--text-heroclamp(3rem, 7vw, 6rem)fluid heroFluid

Weights

light 300Aa

regular 400Aa

medium 500Aa

bold 600Aa

display 700Aa

Line-height

tight 1.1display

snug 1.3headings

normal 1.6body

loose 1.8prose

Letter-spacing

tight -0.03emdisplay

wide 0.04emlabels

wider 0.08emcaps badges

widest 0.12emeyebrows

Utility classes (live)

Eyebrow label

Lead paragraph — light weight, loose leading, used for intros directly under a heading.

Caption — small, muted, for meta info and timestamps.

.mono → inline code / stats / mono figures

03 — Spacing & Layout

Spacing, radius & layout primitives

4px base grid. Containers, section rhythm and a z-index scale so nothing fights over stacking context.

Space scale (4px grid)

--space-14px
--space-28px
--space-312px
--space-416px
--space-520px
--space-624px
--space-832px
--space-1040px
--space-1248px
--space-1664px
--space-2080px
--space-2496px
--space-32128px

Radius scale

sm 4
md 8
lg 12
xl 16
2xl 24
full

Containers

--container-sm640px
--container-md768px
--container-lg1024px
--container-xl1280px (default .container)
--container-2xl1440px
--container-padclamp(1rem, 4vw, 2rem)

Section rhythm & z-index

TokenValue
--section-smclamp(3rem, 6vw, 5rem)
--section-mdclamp(5rem, 10vw, 8rem) — default .section
--section-lgclamp(7rem, 14vw, 12rem)
TokenValue
--z-below-1
--z-raised10
--z-dropdown100
--z-sticky200 (nav uses this)
--z-overlay300
--z-modal400
--z-toast500

Layout utilities (live)

.grid-auto — auto-fit, min 260px

card
card
card

.layout-feature — golden ratio 1 : 1.618

1fr column
1.618fr column
--space-1: 4px;  --space-2: 8px;  --space-3: 12px; --space-4: 16px;
--space-5: 20px; --space-6: 24px; --space-8: 32px; --space-10: 40px;
--space-12: 48px; --space-16: 64px; --space-20: 80px; --space-24: 96px;
--space-32: 128px;

--section-sm: clamp(3rem, 6vw, 5rem);
--section-md: clamp(5rem, 10vw, 8rem);
--section-lg: clamp(7rem, 14vw, 12rem);

--container-sm: 640px;  --container-md: 768px;  --container-lg: 1024px;
--container-xl: 1280px; --container-2xl: 1440px;
--container-pad: clamp(1rem, 4vw, 2rem);

--radius-sm: 4px; --radius-md: 8px; --radius-lg: 12px;
--radius-xl: 16px; --radius-2xl: 24px; --radius-full: 9999px;

--border-thin: 0.5px; --border-base: 1px; --border-accent: 2px;

--z-below: -1; --z-base: 0; --z-raised: 10; --z-dropdown: 100;
--z-sticky: 200; --z-overlay: 300; --z-modal: 400; --z-toast: 500;

04 — Motion

Motion

Purposeful, not decorative. One orchestrated reveal beats many micro-animations. prefers-reduced-motion is always respected — every animation collapses to 0.01ms.

fade-up

translateY(20px) → 0, opacity 0→1

scale-in

scale(.96) → 1, spring ease

fade-in

opacity 0 → 1

Click a card to replay its keyframe.

Duration

--duration-instant80ms
--duration-fast150ms — hover transitions
--duration-normal250ms
--duration-slow400ms
--duration-xslow600ms
--duration-reveal800ms — page reveals

Easing

--ease-out-expocubic-bezier(.16,1,.3,1)
--ease-out-quartcubic-bezier(.25,1,.5,1)
--ease-in-outcubic-bezier(.4,0,.2,1)
--ease-springcubic-bezier(.34,1.56,.64,1) — slight overshoot
--ease-out-expo:  cubic-bezier(0.16, 1, 0.3, 1);
--ease-out-quart: cubic-bezier(0.25, 1, 0.5, 1);
--ease-in-out:    cubic-bezier(0.4, 0, 0.2, 1);
--ease-spring:    cubic-bezier(0.34, 1.56, 0.64, 1);

--duration-instant: 80ms;  --duration-fast: 150ms;  --duration-normal: 250ms;
--duration-slow: 400ms;    --duration-xslow: 600ms; --duration-reveal: 800ms;

--stagger-1: 0ms;   --stagger-2: 60ms;  --stagger-3: 120ms;
--stagger-4: 180ms; --stagger-5: 240ms; --stagger-6: 300ms;

@keyframes fade-up    { from{opacity:0;transform:translateY(20px)} to{opacity:1;transform:translateY(0)} }
@keyframes fade-in    { from{opacity:0} to{opacity:1} }
@keyframes scale-in   { from{opacity:0;transform:scale(.96)} to{opacity:1;transform:scale(1)} }
@keyframes slide-right{ from{opacity:0;transform:translateX(-16px)} to{opacity:1;transform:translateX(0)} }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}
Rule One reveal animation per page load (fade-up + stagger on hero). Don't stack multiple orchestrated reveals on the same view.

05 — Components

Components

Live-rendered with the actual components.css rules — what you see below is pixel-accurate to the site.

Buttons — .btn-primary max ONE per section

.btn-ghost-light — for dark / gradient hero surfaces

Badges

New Active Draft

Cards

.card

Default surface

.card-warm

Warm neutral variant

.card-tinted

Blue-tinted callout

Input & divider


Focus state uses a 3px lb-ice ring (lb-mist ring at 20% in dark mode).

Nav bar (structure 30%)

.btn        { /* base: inline-flex, radius-md, space-3/6 padding, duration-fast transitions */ }
.btn-primary{ background: var(--color-lb-core); color:#fff; }        /* hover → lb-glow */
.btn-ghost  { background: transparent; color: var(--color-lb-core); border-color: var(--color-lb-core); }
.btn-ghost-light { background: rgba(255,255,255,.12); color:#fff; border-color: rgba(255,255,255,.35); } /* dark hero only */
.btn-neutral{ background: var(--color-stone); color: var(--color-ink); }
.btn-sm / .btn-lg → padding + font-size overrides

.badge      { radius-full, uppercase, border: currentColor }
.badge-blue / .badge-green / .badge-neutral

.card       { chalk bg (dark: dark-surface), stone border, radius-lg, space-6 padding }
.card-warm  { warm bg (dark: dark-card) }
.card-tinted{ lb-ice bg, lb-ghost border }

.input      { chalk bg, stone border, radius-md; focus → lb-core border + 3px lb-ice ring }

.nav        { deep-green bg always — never blue, never flips in dark mode }
.nav-link   { white 45% → white 90% on hover/aria-current }

:focus-visible { outline: 2px solid var(--color-lb-core); outline-offset: 3px; }

06 — Theming

Semantic tokens & the theme-flip rule

Every surface and text color on a content card must flip with prefers-color-scheme. Use semantic tokens — never raw color tokens — for anything sitting on a card or section.

Implementation status — verified against the repo, not assumed This table is the mandated convention per the project's CLAUDE.md, but as of 04 Aug 2026 these custom properties are not declared globally — tokens.css has no :root semantic layer and no dark-mode block. They're only used ad hoc, undeclared, inside two page files (fde.astro, ai-applied-layers.astro, plus their /en copies) — meaning var(--text-default) etc. currently resolve to nothing there unless a fallback is supplied. The recommended values below are a proposed canonical mapping (consistent with how .card / .input already flip via raw-token @media blocks in components.css) — not yet centralized. If you build on this system going forward, define these once at :root instead of re-deriving them per page.
What you're stylingUse (semantic)Never (raw)
Card background--surface-card / --surface-card-alt--color-chalk / --color-warm
Section background--surface-page / --surface-page-alt--color-chalk / --color-warm
Card body text--text-default / --text-strong--color-ink / --color-void
Card title text--text-strong--color-void
Muted / caption text--text-muted--color-ash
Tinted callout bg--surface-tinted--color-lb-ice
Text on tinted bg--text-on-tinted--color-lb-deep
Link text--text-link--color-lb-core
Card border--border-default / --border-tinted--color-stone

Why: raw tokens like --color-deep-green are the same hex in both themes. color: var(--color-deep-green) on a card is fine on a chalk card in light mode — and dark-on-dark, unreadable, on a dark-surface card in dark mode. Semantic tokens swap their backing color via the dark-mode block instead.

Recommended baseline (not yet in tokens.css)

:root {
  --surface-page:      var(--color-chalk);
  --surface-page-alt:  var(--color-warm);
  --surface-card:      var(--color-chalk);
  --surface-card-alt:  var(--color-warm);
  --surface-tinted:    var(--color-lb-ice);
  --text-default:      var(--color-ink);
  --text-strong:       var(--color-void);
  --text-muted:        var(--color-ash);
  --text-on-tinted:    var(--color-lb-deep);
  --text-link:         var(--color-lb-core);
  --border-default:    var(--color-stone);
  --border-tinted:     var(--color-lb-ghost);
}

@media (prefers-color-scheme: dark) {
  :root {
    --surface-page:      var(--color-dark-bg);
    --surface-page-alt:  var(--color-dark-surface);
    --surface-card:      var(--color-dark-surface);
    --surface-card-alt:  var(--color-dark-card);
    --surface-tinted:    rgba(27, 31, 232, 0.15);
    --text-default:      var(--color-stone);
    --text-strong:       var(--color-chalk);
    --text-muted:        var(--color-lb-ghost);
    --text-on-tinted:    var(--color-lb-mist);
    --text-link:         var(--color-lb-mist);   /* lb-core fails AA on dark cards */
    --border-default:    var(--color-dark-border);
    --border-tinted:     rgba(123, 128, 255, 0.3);
  }
}
Never
<span style={`color:${d.accent}`}>tag</span>

<p style="color: var(--color-deep-green)">
  visible in light, invisible in dark
</p>

<div class="card" style="background:#fff;color:#000">
Always
<span class="badge badge-blue">tag</span>

<p style="color: var(--text-default)">
  readable in both themes
</p>

<div class="card"><!-- bg + color from .card --></div>

If you reach for !important to fix a dark-mode contrast bug, the raw token is the bug — swap it for the matching semantic token instead of patching it.

07 — Governance

Hard rules

Non-negotiable constraints. Breaking these is what makes a page stop looking like a DashOne property.

Color

  • Never use lb-core as body text
  • Never use lb-core as a section background
  • Max 2 blue tokens per viewport
  • Never blue in nav or footer
  • 60% neutral / 30% structure / 10% blue, always

Components

  • .btn-primary — ONE per section, max
  • .btn-ghost for secondary actions
  • .nav is always deep-green — no exceptions
  • Semantic tokens on anything inside a .card

Typography

  • Display/hero → Fraunces only
  • Body/UI → DM Sans only
  • Never Inter, Roboto, Arial, system-ui as primary face
  • .eyebrow for section labels above headings

Motion

  • One reveal animation per page load
  • Hover = --duration-fast (150ms)
  • Page reveal = --duration-reveal (800ms)
  • Always respect prefers-reduced-motion

08 — Source

File map (Astro source)

How the system is organized in the dashone.ai repo, for context if you're replicating this in another Astro project.

src/styles/
  global.css ← import this ONLY in the site's root layout (currently src/layouts/Layout.astro — CLAUDE.md's own reference to "BaseLayout.astro" is stale, that file doesn't exist)
  tokens.css ← all raw CSS custom properties (colors)
  typography.css ← font families, scale, utility classes
  spacing.css ← space scale, radius, z-index, containers
  motion.css ← keyframes, easing, duration tokens
  layout.css ← grid, flex, section, container utilities
  components.css ← btn, badge, card, input, nav
  tokens.json ← machine-readable token reference (colors + fonts + 60-30-10 map only — narrower than the CSS)
Import order matters — global.css chains tokens → typography → spacing → motion → layout → components, then resets. Never duplicate token values inside a component-scoped <style> block — always reference the variable.

09 — Portability

Using this outside dashone.ai

To build a self-contained artifact (Claude.ai artifact, a static report, a one-off landing page) that looks like a DashOne property, without the Astro build:

  1. Paste the four copy blocks above (Color, Spacing, Motion, plus Typography's font-family/scale vars) into one :root block.
  2. Add the Google Fonts @import or <link> for Fraunces + DM Sans + JetBrains Mono (see this page's <head> for the exact URL).
  3. Copy the component classes you need from the Components section's code block, or lift them verbatim from components.css in the repo.
  4. Apply 60-30-10 to your layout: neutral backgrounds, deep-green structure (nav/footer), blue only on the one primary CTA.
  5. Wrap card/section content in the semantic-token pattern from the Theming section if the artifact needs to support both light and dark — most one-off artifacts can skip this and just pick one theme, but never mix (no raw structure tokens as text on a surface that flips).
This is a snapshot — token values, rules and the theming-gap note above reflect the repo as of 04 Aug 2026 (commit around a9aee79). If dashone.ai's tokens change, this reference will drift; re-generate it from src/styles/ rather than trusting an old copy indefinitely.