Spaces:
Runtime error
Runtime error
Upload 8 files
Browse files- design_system/readme.md +174 -0
- design_system/styles.css +13 -0
- design_system/tokens/base.css +58 -0
- design_system/tokens/colors.css +148 -0
- design_system/tokens/elevation.css +35 -0
- design_system/tokens/fonts.css +12 -0
- design_system/tokens/spacing.css +46 -0
- design_system/tokens/typography.css +61 -0
design_system/readme.md
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Chan Compass · Spectrum 2 Design System
|
| 2 |
+
|
| 3 |
+
A design system for **Chan Compass · US** — a multi-timeframe 缠论 (Chan theory)
|
| 4 |
+
stock-signal engine — rendered in **Adobe Spectrum 2**, Adobe's design language.
|
| 5 |
+
It exists to give design agents a single, accurate source of truth for building
|
| 6 |
+
beautiful, on-brand Chan Compass interfaces (the live Gradio app, mocks, slides,
|
| 7 |
+
marketing) without re-deriving Spectrum 2 every time.
|
| 8 |
+
|
| 9 |
+
> **Spectrum 2** is Adobe's open design system. This project recreates its
|
| 10 |
+
> visual foundations (color, type, spacing, elevation, motion) and a set of
|
| 11 |
+
> React components, then applies them to the Chan Compass product surfaces.
|
| 12 |
+
|
| 13 |
+
---
|
| 14 |
+
|
| 15 |
+
## What the product is
|
| 16 |
+
|
| 17 |
+
Chan Compass is an **educational US-equities signal tool** that runs entirely
|
| 18 |
+
locally. It has six surfaces (Gradio tabs):
|
| 19 |
+
|
| 20 |
+
| Surface | What it does |
|
| 21 |
+
|---|---|
|
| 22 |
+
| **Signals** | Runs the Chan engine over a ticker pool; returns next-session **BUY / SELL / HOLD / WAIT / WATCH** with confidence, suggested weight, stop, and a full multi-timeframe ruling chain (monthly → weekly → daily → 60m → 30m → 15m → 5m nested-interval confirmation). |
|
| 23 |
+
| **Sector Rotation** | Where capital is flowing across the 11 SPDR sector ETFs; flow proxy = change % × dollar volume, plus relative strength vs SPY, over 1 / 5 / 20 days. |
|
| 24 |
+
| **Watchlist News** | Checks **today's** news per holding; pushes an AI brief only when news exists. |
|
| 25 |
+
| **Auto Research** | A local multi-step agent: PLAN → 5 evidence tools → sectioned report, with a saved JSON trace. |
|
| 26 |
+
| **Automation** | Daily pipeline at 18:10 America/New_York. |
|
| 27 |
+
| **Model** | Loads Qwen3 GGUF weights through llama.cpp — everything runs locally, nothing leaves the machine. |
|
| 28 |
+
|
| 29 |
+
The AI is a **local sub-agent pool** (Qwen3-1.7B translator/narrator + a deeper
|
| 30 |
+
analyst), served via `llama-cpp-python`. Data comes from Yahoo Finance.
|
| 31 |
+
|
| 32 |
+
## Sources this system was built from
|
| 33 |
+
|
| 34 |
+
- **Codebase:** `chan-compass-us-v1.7/` (attached) — a Gradio app (`app.py`)
|
| 35 |
+
plus the Chan engine (`chan_engine.py`, `chan_multilevel.py`, `chan_enhance.py`),
|
| 36 |
+
signal/rotation/news/research/automation modules. The app already ships an
|
| 37 |
+
*approximation* of Spectrum 2 in Gradio CSS; this system replaces it with the
|
| 38 |
+
real thing. The product deploys as a **Hugging Face Gradio Space**.
|
| 39 |
+
- **Design language — Adobe Spectrum 2 / React Spectrum:**
|
| 40 |
+
<https://github.com/adobe/react-spectrum> (the `@react-spectrum/s2` package —
|
| 41 |
+
`style/spectrum-theme.ts`, `style/tokens.ts` — was read for exact spacing,
|
| 42 |
+
radii, easing, weights and the type scale). Token values were cross-checked
|
| 43 |
+
against <https://spectrum.adobe.com/page/color-palette/>.
|
| 44 |
+
Explore that repo to go deeper on component behavior and accessibility.
|
| 45 |
+
|
| 46 |
+
> **Deploying the live app?** See `gradio/` — a ready-to-paste Spectrum 2 Gradio
|
| 47 |
+
> theme (`theme.py` = `THEME` + `CSS`), a guaranteed-green standalone demo Space,
|
| 48 |
+
> and an HF deploy checklist (`gradio/INTEGRATE.md`).
|
| 49 |
+
|
| 50 |
+
---
|
| 51 |
+
|
| 52 |
+
## Content fundamentals
|
| 53 |
+
|
| 54 |
+
How Chan Compass writes. Match this voice in any UI copy.
|
| 55 |
+
|
| 56 |
+
- **Voice:** expert, terse, instrument-panel. Copy reads like a trading desk
|
| 57 |
+
tool, not a consumer app. Short noun phrases over sentences: *"Tomorrow's
|
| 58 |
+
plan"*, *"Where capital is flowing"*, *"Buy/sell zone"*.
|
| 59 |
+
- **Person:** mostly impersonal/imperative. Buttons are verbs — *"Run analysis"*,
|
| 60 |
+
*"Check today's news"*, *"Load model"*. When it addresses the user it's second
|
| 61 |
+
person and possessive — *"My holdings"*, *"your ticker pool"*.
|
| 62 |
+
- **Casing:** **Sentence case** everywhere — labels, buttons, headings
|
| 63 |
+
(*"Run analysis"*, not "Run Analysis"). Ticker symbols and ETF codes are
|
| 64 |
+
**UPPERCASE monospace** (NVDA, XLK). Signal verbs render UPPERCASE in pills
|
| 65 |
+
(BUY/SELL/HOLD).
|
| 66 |
+
- **Bilingual register:** the engine's internal ruling chain is **Chinese**
|
| 67 |
+
(缠论 terms: 中枢, 背驰, 区间套, 买卖点 B1/B2/B3/S1/S2/S3); user-facing summaries
|
| 68 |
+
are **English**, produced by the local translator sub-agent. Keep Chinese for
|
| 69 |
+
authentic engine output; keep English for everything the user reads first.
|
| 70 |
+
- **Numbers carry meaning, not decoration.** Every percent, confidence score,
|
| 71 |
+
weight and stop price is real signal. No vanity stats. Percentages are signed
|
| 72 |
+
(+2.43% / −3.08%) and color-coded.
|
| 73 |
+
- **Honesty & disclaimers:** always frames itself as *"educational tool — not
|
| 74 |
+
investment advice."* States its data limits plainly (*"Yahoo only keeps 7 days
|
| 75 |
+
of 1-minute bars, so the 1m level is skipped"*). No hype, no guarantees.
|
| 76 |
+
- **AI is labeled.** Anything model-generated is prefixed with the sub-agent and
|
| 77 |
+
model — *"🤖 Translator sub-agent (Qwen3-1.7B · llama.cpp)"* — and notes
|
| 78 |
+
latency honestly (*"first words in ~5–15s"*).
|
| 79 |
+
- **Emoji:** the live app uses tab emoji (📈 🔄 📰 🧪 ⏰ 🧠) and the 🧭 brand mark.
|
| 80 |
+
In the **polished design system we prefer Spectrum line icons** for UI chrome
|
| 81 |
+
and reserve emoji for the brand mark / casual chips. Don't scatter emoji into
|
| 82 |
+
data or buttons.
|
| 83 |
+
|
| 84 |
+
---
|
| 85 |
+
|
| 86 |
+
## Visual foundations
|
| 87 |
+
|
| 88 |
+
The Spectrum 2 look, as applied here.
|
| 89 |
+
|
| 90 |
+
- **Color vibe:** calm, neutral, **light-first**. A near-white canvas
|
| 91 |
+
(`gray-50 #F8F8F8`) with **white cards** (`gray-25`) and crisp hairline borders
|
| 92 |
+
(`gray-100 #E6E6E6`). One disciplined accent — **Spectrum blue `#0265DC`** —
|
| 93 |
+
carries all primary action and selection. Color is otherwise **semantic only**:
|
| 94 |
+
green = positive/BUY, red = negative/SELL, blue = HOLD/accent, orange = WATCH/notice.
|
| 95 |
+
No decorative color, no rainbow dashboards.
|
| 96 |
+
- **Type:** **Source Sans 3** for UI and headings (open stand-in for the
|
| 97 |
+
proprietary Adobe Clean), **Source Serif 4** for editorial/report prose,
|
| 98 |
+
**Source Code Pro** for tickers, prices and logs. Modular scale, ratio **1.125**,
|
| 99 |
+
**14px UI base**. Headings are **bold (700)** and slightly tightened
|
| 100 |
+
(`-0.015em`); body is **regular (400)** at a spacious **1.5** line height.
|
| 101 |
+
- **Spacing:** an **8px base rhythm** (2 · 4 · 8 · 12 · 16 · 24 · 32 · 48 · 64).
|
| 102 |
+
Generous padding inside cards (24px), comfortable 24–32px gaps between regions.
|
| 103 |
+
- **Backgrounds:** **flat, layered surfaces** — no photographic imagery, no
|
| 104 |
+
full-bleed art, no repeating textures. Depth comes from Spectrum's
|
| 105 |
+
*background layering* (canvas → card → subtle well), not from shadows alone.
|
| 106 |
+
The **only gradient** is a small one on the 🧭 brand mark
|
| 107 |
+
(blue → indigo → purple), echoing the app's original hero; the rest is solid.
|
| 108 |
+
- **Corner radii:** soft but not pill-everything — **16px cards**, **8px inputs
|
| 109 |
+
& square buttons**, **4px chips**, and **fully-rounded (pill) action buttons** —
|
| 110 |
+
the single most recognizable Spectrum 2 signature here.
|
| 111 |
+
- **Elevation:** **soft, low-spread** drop shadows (`raised` = `0 1px 3px
|
| 112 |
+
rgba(0,0,0,.06)`), never heavy. Cards sit barely off the canvas. The AI panel
|
| 113 |
+
gets a faint **accent-tinted glow** instead of a darker shadow.
|
| 114 |
+
- **Borders:** 1px hairlines for structure; inputs use a **2px** border that
|
| 115 |
+
turns accent-blue on focus. Tabs sit on a 2px track and the selected tab draws
|
| 116 |
+
a 2px accent underline.
|
| 117 |
+
- **Hover / press:** Spectrum's **one-stop-darker** rule — hover bumps a button
|
| 118 |
+
one color stop darker (`accent → accent-hover`), press goes one more and adds a
|
| 119 |
+
**subtle `scale(.98)`**. Quiet/ghost controls fill with `gray-75` on hover.
|
| 120 |
+
Rows highlight to `gray-75` on hover, `blue-100` when selected.
|
| 121 |
+
- **Focus:** a **2px solid accent ring with 2px offset** on every interactive
|
| 122 |
+
element — visible, never removed.
|
| 123 |
+
- **Motion:** quick and restrained. Durations **130–220ms**; the house easing is
|
| 124 |
+
Spectrum's `cubic-bezier(0.45, 0, 0.4, 1)` (with `ease-out` for entrances).
|
| 125 |
+
Fades and one-stop color shifts; **no bounces**, one tasteful pulse for live
|
| 126 |
+
status and the running pipeline step. Respect `prefers-reduced-motion`.
|
| 127 |
+
- **Transparency / blur:** used sparingly — not a glassmorphism system. Surfaces
|
| 128 |
+
are opaque; selection tints use solid subtle fills (`blue-100`), not alpha.
|
| 129 |
+
- **Cards:** white surface, 16px radius, 1px hairline border, soft raised shadow,
|
| 130 |
+
optional header with title + subtitle + a trailing action slot.
|
| 131 |
+
|
| 132 |
+
---
|
| 133 |
+
|
| 134 |
+
## Index — what's in this project
|
| 135 |
+
|
| 136 |
+
**Foundations (root)**
|
| 137 |
+
- `styles.css` — the single entry point consumers link (`@import`s only).
|
| 138 |
+
- `tokens/` — `colors.css` · `typography.css` · `spacing.css` · `elevation.css`
|
| 139 |
+
· `fonts.css` · `base.css`. Primitives + semantic aliases.
|
| 140 |
+
- `guidelines/` — foundation specimen cards (Colors, Type, Spacing) shown in the
|
| 141 |
+
Design System tab.
|
| 142 |
+
|
| 143 |
+
**Components** (`components/<group>/` — React primitives, bundled to `window.<Namespace>`)
|
| 144 |
+
- `actions/` — **Button** (pill, accent/secondary/negative/quiet)
|
| 145 |
+
- `forms/` — **Field**, **Checkbox**, **Switch**
|
| 146 |
+
- `status/` — **Badge**, **StatusLight**, **SignalBadge** (BUY/SELL/HOLD/WAIT/WATCH)
|
| 147 |
+
- `containers/` — **Card**, **InlineAlert** (incl. the signature `ai` panel)
|
| 148 |
+
- `navigation/` — **Tabs** (quiet tabs + accent underline)
|
| 149 |
+
|
| 150 |
+
**UI kit** (`ui_kits/chan-compass/`)
|
| 151 |
+
- `index.html` — full interactive Spectrum 2 recreation of the 6-tab app
|
| 152 |
+
(Signals, Rotation, Research, News, Model). Composes the components above.
|
| 153 |
+
|
| 154 |
+
**Deploy bridge** (`gradio/`)
|
| 155 |
+
- `theme.py` (`THEME` + `CSS`), standalone demo `app.py`, `requirements.txt`,
|
| 156 |
+
`README.md` (HF Space), `INTEGRATE.md` (port + deploy checklist).
|
| 157 |
+
|
| 158 |
+
**Meta**
|
| 159 |
+
- `SKILL.md` — makes this folder usable as an Agent Skill.
|
| 160 |
+
|
| 161 |
+
---
|
| 162 |
+
|
| 163 |
+
## Iconography
|
| 164 |
+
|
| 165 |
+
See the **Iconography** section below and the `assets/` README. In short: Chan
|
| 166 |
+
Compass has **no custom icon set** of its own — the live app leans on **emoji**
|
| 167 |
+
for tab affordances and the **🧭 compass** as its brand mark. Spectrum's own
|
| 168 |
+
**workflow-icons** are the canonical reference but aren't freely CDN-hosted, so
|
| 169 |
+
this system substitutes **[Lucide](https://lucide.dev)** — clean 2px line icons
|
| 170 |
+
whose weight and rounded joinery read as Spectrum-adjacent — loaded from CDN in
|
| 171 |
+
the UI kit. **Substitution flagged.** If you license Adobe's Spectrum workflow
|
| 172 |
+
icons, swap Lucide for them and the visual language tightens further.
|
| 173 |
+
|
| 174 |
+
*Educational tool — not investment advice.*
|
design_system/styles.css
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/* ============================================================
|
| 2 |
+
Chan Compass · Spectrum 2 Design System
|
| 3 |
+
Global entry point — consumers link THIS one file.
|
| 4 |
+
Import order: fonts → primitives → semantics. Keep this file
|
| 5 |
+
as @import lines only.
|
| 6 |
+
============================================================ */
|
| 7 |
+
|
| 8 |
+
@import url('tokens/fonts.css');
|
| 9 |
+
@import url('tokens/colors.css');
|
| 10 |
+
@import url('tokens/typography.css');
|
| 11 |
+
@import url('tokens/spacing.css');
|
| 12 |
+
@import url('tokens/elevation.css');
|
| 13 |
+
@import url('tokens/base.css');
|
design_system/tokens/base.css
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/* ============================================================
|
| 2 |
+
BASE — Chan Compass · Spectrum 2
|
| 3 |
+
Light, opinionated element defaults. Body uses the canvas
|
| 4 |
+
background and UI type. Helper classes for the few primitives
|
| 5 |
+
that aren't worth a React component.
|
| 6 |
+
============================================================ */
|
| 7 |
+
|
| 8 |
+
*, *::before, *::after { box-sizing: border-box; }
|
| 9 |
+
|
| 10 |
+
body {
|
| 11 |
+
margin: 0;
|
| 12 |
+
background: var(--canvas);
|
| 13 |
+
color: var(--text-body);
|
| 14 |
+
font: var(--type-body);
|
| 15 |
+
-webkit-font-smoothing: antialiased;
|
| 16 |
+
text-rendering: optimizeLegibility;
|
| 17 |
+
}
|
| 18 |
+
|
| 19 |
+
h1, h2, h3, h4 {
|
| 20 |
+
margin: 0;
|
| 21 |
+
color: var(--text-heading);
|
| 22 |
+
letter-spacing: var(--letter-spacing-heading);
|
| 23 |
+
text-wrap: balance;
|
| 24 |
+
}
|
| 25 |
+
h1 { font: var(--type-h1); }
|
| 26 |
+
h2 { font: var(--type-h2); }
|
| 27 |
+
h3 { font: var(--type-h3); letter-spacing: 0; }
|
| 28 |
+
h4 { font: var(--type-h4); letter-spacing: 0; }
|
| 29 |
+
|
| 30 |
+
p { margin: 0; text-wrap: pretty; }
|
| 31 |
+
|
| 32 |
+
a { color: var(--accent-text); text-decoration: none; }
|
| 33 |
+
a:hover { text-decoration: underline; text-underline-offset: 2px; }
|
| 34 |
+
|
| 35 |
+
code, kbd, samp { font-family: var(--font-code); font-size: 0.92em; }
|
| 36 |
+
|
| 37 |
+
::selection { background: var(--accent-subtle); }
|
| 38 |
+
|
| 39 |
+
:focus-visible {
|
| 40 |
+
outline: var(--focus-ring-width) solid var(--focus-ring);
|
| 41 |
+
outline-offset: var(--focus-ring-offset);
|
| 42 |
+
border-radius: var(--radius-sm);
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
/* ---- Eyebrow / overline ---- */
|
| 46 |
+
.s2-eyebrow {
|
| 47 |
+
font: var(--font-weight-bold) var(--font-size-50)/1.2 var(--font-sans);
|
| 48 |
+
letter-spacing: var(--letter-spacing-caps);
|
| 49 |
+
text-transform: uppercase;
|
| 50 |
+
color: var(--text-muted);
|
| 51 |
+
}
|
| 52 |
+
|
| 53 |
+
/* ---- Hairline divider ---- */
|
| 54 |
+
.s2-divider {
|
| 55 |
+
border: none;
|
| 56 |
+
border-top: var(--border-width-100) solid var(--border-hairline);
|
| 57 |
+
margin: var(--space-300) 0;
|
| 58 |
+
}
|
design_system/tokens/colors.css
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/* ============================================================
|
| 2 |
+
COLOR — Chan Compass · Spectrum 2
|
| 3 |
+
Two layers:
|
| 4 |
+
1. PRIMITIVES — the raw Spectrum 2 scales (--s2-gray-100, --s2-blue-900…)
|
| 5 |
+
2. SEMANTICS — purpose-named aliases the UI references (--text-body,
|
| 6 |
+
--surface-card, --accent…)
|
| 7 |
+
Always consume semantics in components; reach for a primitive only
|
| 8 |
+
when no semantic fits. Light theme is the default; .s2-dark flips the
|
| 9 |
+
semantic layer (primitives are not re-pointed here for simplicity).
|
| 10 |
+
============================================================ */
|
| 11 |
+
|
| 12 |
+
:root {
|
| 13 |
+
/* ---- Gray (light) ---- */
|
| 14 |
+
--s2-gray-25: #ffffff;
|
| 15 |
+
--s2-gray-50: #f8f8f8;
|
| 16 |
+
--s2-gray-75: #f3f3f3;
|
| 17 |
+
--s2-gray-100: #e6e6e6;
|
| 18 |
+
--s2-gray-200: #d5d5d5;
|
| 19 |
+
--s2-gray-300: #b1b1b1;
|
| 20 |
+
--s2-gray-400: #909090;
|
| 21 |
+
--s2-gray-500: #6d6d6d;
|
| 22 |
+
--s2-gray-600: #464646;
|
| 23 |
+
--s2-gray-700: #292929;
|
| 24 |
+
--s2-gray-800: #1b1b1b;
|
| 25 |
+
--s2-gray-900: #000000;
|
| 26 |
+
|
| 27 |
+
/* ---- Blue (accent family) ---- */
|
| 28 |
+
--s2-blue-100: #e0f2ff;
|
| 29 |
+
--s2-blue-200: #cae8ff;
|
| 30 |
+
--s2-blue-300: #98cbfe;
|
| 31 |
+
--s2-blue-400: #6fb7fb;
|
| 32 |
+
--s2-blue-500: #4ba0ec;
|
| 33 |
+
--s2-blue-600: #2c84e0;
|
| 34 |
+
--s2-blue-700: #1473e6;
|
| 35 |
+
--s2-blue-800: #0a6fd6;
|
| 36 |
+
--s2-blue-900: #0265dc; /* accent default */
|
| 37 |
+
--s2-blue-1000: #0054b6; /* accent hover */
|
| 38 |
+
--s2-blue-1100: #00418f; /* accent down */
|
| 39 |
+
|
| 40 |
+
/* ---- Green (positive) ---- */
|
| 41 |
+
--s2-green-100: #ebf9ee;
|
| 42 |
+
--s2-green-400: #6cc788;
|
| 43 |
+
--s2-green-700: #15924a;
|
| 44 |
+
--s2-green-900: #007a39; /* positive default */
|
| 45 |
+
--s2-green-1000: #006d31;
|
| 46 |
+
--s2-green-1100: #00601f;
|
| 47 |
+
|
| 48 |
+
/* ---- Red (negative) ---- */
|
| 49 |
+
--s2-red-100: #ffefef;
|
| 50 |
+
--s2-red-400: #ff9b88;
|
| 51 |
+
--s2-red-700: #e34850;
|
| 52 |
+
--s2-red-900: #d7373f; /* negative default */
|
| 53 |
+
--s2-red-1000: #c0272d;
|
| 54 |
+
--s2-red-1100: #a01a1f;
|
| 55 |
+
|
| 56 |
+
/* ---- Orange (notice) ---- */
|
| 57 |
+
--s2-orange-100: #fdf0e1;
|
| 58 |
+
--s2-orange-400: #f8af5a;
|
| 59 |
+
--s2-orange-700: #cb6f10;
|
| 60 |
+
--s2-orange-900: #b25309; /* notice default */
|
| 61 |
+
--s2-orange-1000: #99490b;
|
| 62 |
+
|
| 63 |
+
/* ---- Indigo (informative accent / charts) ---- */
|
| 64 |
+
--s2-indigo-700: #5258e4;
|
| 65 |
+
--s2-indigo-900: #3d43d0;
|
| 66 |
+
|
| 67 |
+
/* ---- Purple (decorative / hero gradient stop) ---- */
|
| 68 |
+
--s2-purple-700: #8c42d6;
|
| 69 |
+
--s2-purple-900: #7326d3;
|
| 70 |
+
|
| 71 |
+
/* ============================================================
|
| 72 |
+
SEMANTIC ALIASES — what components actually reference
|
| 73 |
+
============================================================ */
|
| 74 |
+
|
| 75 |
+
/* Surfaces & framing (Spectrum 2 background layering) */
|
| 76 |
+
--canvas: var(--s2-gray-50); /* app background */
|
| 77 |
+
--surface-card: var(--s2-gray-25); /* cards, panels */
|
| 78 |
+
--surface-elevated:var(--s2-gray-25); /* popovers, menus */
|
| 79 |
+
--surface-subtle: var(--s2-gray-75); /* table head, wells */
|
| 80 |
+
--surface-sunken: var(--s2-gray-75); /* inset fields */
|
| 81 |
+
|
| 82 |
+
/* Text */
|
| 83 |
+
--text-heading: var(--s2-gray-800);
|
| 84 |
+
--text-body: var(--s2-gray-700);
|
| 85 |
+
--text-secondary: var(--s2-gray-600);
|
| 86 |
+
--text-muted: var(--s2-gray-500);
|
| 87 |
+
--text-disabled: var(--s2-gray-400);
|
| 88 |
+
--text-on-accent: #ffffff;
|
| 89 |
+
|
| 90 |
+
/* Borders & dividers */
|
| 91 |
+
--border-hairline: var(--s2-gray-100);
|
| 92 |
+
--border-default: var(--s2-gray-200);
|
| 93 |
+
--border-strong: var(--s2-gray-300);
|
| 94 |
+
--border-field: var(--s2-gray-300);
|
| 95 |
+
|
| 96 |
+
/* Accent (Spectrum blue) */
|
| 97 |
+
--accent: var(--s2-blue-900);
|
| 98 |
+
--accent-hover: var(--s2-blue-1000);
|
| 99 |
+
--accent-down: var(--s2-blue-1100);
|
| 100 |
+
--accent-subtle: var(--s2-blue-100);
|
| 101 |
+
--accent-text: var(--s2-blue-1000);
|
| 102 |
+
|
| 103 |
+
/* Semantic status */
|
| 104 |
+
--positive: var(--s2-green-900);
|
| 105 |
+
--positive-hover: var(--s2-green-1000);
|
| 106 |
+
--positive-subtle: var(--s2-green-100);
|
| 107 |
+
--negative: var(--s2-red-900);
|
| 108 |
+
--negative-hover: var(--s2-red-1000);
|
| 109 |
+
--negative-subtle: var(--s2-red-100);
|
| 110 |
+
--notice: var(--s2-orange-900);
|
| 111 |
+
--notice-subtle: var(--s2-orange-100);
|
| 112 |
+
--informative: var(--s2-blue-900);
|
| 113 |
+
--informative-subtle: var(--s2-blue-100);
|
| 114 |
+
|
| 115 |
+
/* Focus ring */
|
| 116 |
+
--focus-ring: var(--s2-blue-900);
|
| 117 |
+
|
| 118 |
+
/* Market direction (this product's domain colors) */
|
| 119 |
+
--up: var(--s2-green-900); /* gains / BUY */
|
| 120 |
+
--down: var(--s2-red-900); /* losses / SELL */
|
| 121 |
+
--flat: var(--s2-gray-500); /* HOLD / WAIT */
|
| 122 |
+
}
|
| 123 |
+
|
| 124 |
+
/* ---- Dark theme: flip the semantic layer only ---- */
|
| 125 |
+
.s2-dark {
|
| 126 |
+
--canvas: #1d1d1d;
|
| 127 |
+
--surface-card: #262626;
|
| 128 |
+
--surface-elevated:#2c2c2c;
|
| 129 |
+
--surface-subtle: #222222;
|
| 130 |
+
--surface-sunken: #1a1a1a;
|
| 131 |
+
|
| 132 |
+
--text-heading: #f2f2f2;
|
| 133 |
+
--text-body: #e0e0e0;
|
| 134 |
+
--text-secondary: #b8b8b8;
|
| 135 |
+
--text-muted: #8f8f8f;
|
| 136 |
+
--text-disabled: #6a6a6a;
|
| 137 |
+
|
| 138 |
+
--border-hairline: #383838;
|
| 139 |
+
--border-default: #4a4a4a;
|
| 140 |
+
--border-strong: #5e5e5e;
|
| 141 |
+
--border-field: #5e5e5e;
|
| 142 |
+
|
| 143 |
+
--accent: #2680eb;
|
| 144 |
+
--accent-hover: #4ba0ec;
|
| 145 |
+
--accent-down: #6fb7fb;
|
| 146 |
+
--accent-subtle: #1a3a5c;
|
| 147 |
+
--accent-text: #6fb7fb;
|
| 148 |
+
}
|
design_system/tokens/elevation.css
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/* ============================================================
|
| 2 |
+
ELEVATION & MOTION — Chan Compass · Spectrum 2
|
| 3 |
+
Soft, low-spread drop shadows; never heavy. Spectrum easing curves.
|
| 4 |
+
============================================================ */
|
| 5 |
+
|
| 6 |
+
:root {
|
| 7 |
+
/* ---- Drop shadows (Spectrum 2 elevation) ---- */
|
| 8 |
+
--shadow-flat: none;
|
| 9 |
+
--shadow-raised: 0 1px 3px rgba(0,0,0,.06), 0 1px 1px rgba(0,0,0,.04);
|
| 10 |
+
--shadow-elevated: 0 2px 8px rgba(0,0,0,.08), 0 1px 2px rgba(0,0,0,.06);
|
| 11 |
+
--shadow-emphasized:0 6px 20px rgba(0,0,0,.12), 0 2px 6px rgba(0,0,0,.08);
|
| 12 |
+
--shadow-dragged: 0 12px 32px rgba(0,0,0,.18), 0 4px 10px rgba(0,0,0,.10);
|
| 13 |
+
|
| 14 |
+
/* Accent-tinted glow (used on AI / focused panels) */
|
| 15 |
+
--shadow-accent: 0 2px 12px rgba(2,101,220,.12);
|
| 16 |
+
|
| 17 |
+
/* ---- Focus ring ---- */
|
| 18 |
+
--focus-ring-width: 2px;
|
| 19 |
+
--focus-ring-offset: 2px;
|
| 20 |
+
|
| 21 |
+
/* ---- Motion ---- */
|
| 22 |
+
--ease-default: cubic-bezier(0.45, 0, 0.4, 1); /* @kind other */
|
| 23 |
+
--ease-in: cubic-bezier(0.5, 0, 1, 1); /* @kind other */
|
| 24 |
+
--ease-out: cubic-bezier(0, 0, 0.4, 1); /* @kind other */
|
| 25 |
+
--ease-in-out: cubic-bezier(0.45, 0, 0.4, 1); /* @kind other */
|
| 26 |
+
|
| 27 |
+
--duration-fast: 130ms; /* @kind other */
|
| 28 |
+
--duration-default: 160ms; /* @kind other */
|
| 29 |
+
--duration-slow: 220ms; /* @kind other */
|
| 30 |
+
|
| 31 |
+
--transition-default: all var(--duration-default) var(--ease-default);
|
| 32 |
+
--transition-colors: color var(--duration-fast) var(--ease-default),
|
| 33 |
+
background-color var(--duration-fast) var(--ease-default),
|
| 34 |
+
border-color var(--duration-fast) var(--ease-default);
|
| 35 |
+
}
|
design_system/tokens/fonts.css
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/* ============================================================
|
| 2 |
+
FONTS — Chan Compass · Spectrum 2
|
| 3 |
+
Adobe Clean (Spectrum's UI typeface) is proprietary, so this
|
| 4 |
+
system substitutes Adobe's own open-source families:
|
| 5 |
+
· Source Sans 3 → UI / headings (stands in for Adobe Clean)
|
| 6 |
+
· Source Serif 4 → editorial serif (stands in for Adobe Clean Serif)
|
| 7 |
+
· Source Code Pro → mono / code (Spectrum's real code font)
|
| 8 |
+
Loaded from Google Fonts. If you have licensed Adobe Clean,
|
| 9 |
+
swap the @font-face stack and the families resolve automatically.
|
| 10 |
+
============================================================ */
|
| 11 |
+
|
| 12 |
+
@import url('https://fonts.googleapis.com/css2?family=Source+Sans+3:ital,wght@0,400;0,500;0,600;0,700;0,800;1,400&family=Source+Serif+4:ital,wght@0,400;0,600;0,700;1,400&family=Source+Code+Pro:wght@400;500;600&display=swap');
|
design_system/tokens/spacing.css
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/* ============================================================
|
| 2 |
+
SPACING & SIZING — Chan Compass · Spectrum 2
|
| 3 |
+
Spectrum 2 spacing scale (px): 0 2 4 8 12 16 20 24 28 32 40 48 64 80 96.
|
| 4 |
+
8px is the base rhythm. Padding uses px; layout gaps reuse the same scale.
|
| 5 |
+
============================================================ */
|
| 6 |
+
|
| 7 |
+
:root {
|
| 8 |
+
--space-0: 0;
|
| 9 |
+
--space-50: 2px;
|
| 10 |
+
--space-75: 4px;
|
| 11 |
+
--space-100: 8px; /* base unit */
|
| 12 |
+
--space-150: 12px;
|
| 13 |
+
--space-200: 16px;
|
| 14 |
+
--space-250: 20px;
|
| 15 |
+
--space-300: 24px;
|
| 16 |
+
--space-400: 32px;
|
| 17 |
+
--space-500: 40px;
|
| 18 |
+
--space-600: 48px;
|
| 19 |
+
--space-700: 64px;
|
| 20 |
+
--space-800: 80px;
|
| 21 |
+
--space-900: 96px;
|
| 22 |
+
|
| 23 |
+
/* ---- Corner radii (Spectrum 2) ---- */
|
| 24 |
+
--radius-none: 0;
|
| 25 |
+
--radius-sm: 4px; /* chips, small controls */
|
| 26 |
+
--radius-default: 8px; /* inputs, buttons (square)*/
|
| 27 |
+
--radius-lg: 10px; /* nested cards */
|
| 28 |
+
--radius-xl: 16px; /* cards, panels */
|
| 29 |
+
--radius-2xl: 20px; /* hero, large surfaces */
|
| 30 |
+
--radius-full: 9999px; /* pills, avatars */
|
| 31 |
+
|
| 32 |
+
/* ---- Border widths ---- */
|
| 33 |
+
--border-width-100: 1px;
|
| 34 |
+
--border-width-200: 2px;
|
| 35 |
+
--border-width-400: 4px;
|
| 36 |
+
|
| 37 |
+
/* ---- Control heights (medium scale) ---- */
|
| 38 |
+
--control-height-sm: 28px;
|
| 39 |
+
--control-height-md: 32px;
|
| 40 |
+
--control-height-lg: 40px;
|
| 41 |
+
|
| 42 |
+
/* ---- Layout ---- */
|
| 43 |
+
--container-max: 1280px;
|
| 44 |
+
--field-radius: var(--radius-default);
|
| 45 |
+
--card-radius: var(--radius-xl);
|
| 46 |
+
}
|
design_system/tokens/typography.css
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/* ============================================================
|
| 2 |
+
TYPOGRAPHY — Chan Compass · Spectrum 2
|
| 3 |
+
Spectrum 2 desktop UI base = 14px, modular scale ratio 1.125.
|
| 4 |
+
Three families: sans (UI/headings), serif (editorial), code (mono).
|
| 5 |
+
============================================================ */
|
| 6 |
+
|
| 7 |
+
:root {
|
| 8 |
+
/* ---- Families ---- */
|
| 9 |
+
--font-sans: 'Source Sans 3', 'Adobe Clean', ui-sans-serif, system-ui, -apple-system, sans-serif;
|
| 10 |
+
--font-serif: 'Source Serif 4', 'Adobe Clean Serif', Georgia, 'Times New Roman', serif;
|
| 11 |
+
--font-code: 'Source Code Pro', ui-monospace, 'SF Mono', Menlo, Monaco, monospace;
|
| 12 |
+
|
| 13 |
+
/* ---- Type scale (ratio 1.125, base 14px) ---- */
|
| 14 |
+
--font-size-50: 11px;
|
| 15 |
+
--font-size-75: 12px;
|
| 16 |
+
--font-size-100: 14px; /* UI base */
|
| 17 |
+
--font-size-200: 16px;
|
| 18 |
+
--font-size-300: 18px;
|
| 19 |
+
--font-size-400: 20px;
|
| 20 |
+
--font-size-500: 22px;
|
| 21 |
+
--font-size-600: 25px;
|
| 22 |
+
--font-size-700: 28px;
|
| 23 |
+
--font-size-800: 32px;
|
| 24 |
+
--font-size-900: 36px;
|
| 25 |
+
--font-size-1000: 40px;
|
| 26 |
+
--font-size-1100: 45px;
|
| 27 |
+
--font-size-1200: 50px;
|
| 28 |
+
|
| 29 |
+
/* ---- Weights (Source Sans 3 axis) ---- */
|
| 30 |
+
--font-weight-regular: 400;
|
| 31 |
+
--font-weight-medium: 500;
|
| 32 |
+
--font-weight-semibold: 600;
|
| 33 |
+
--font-weight-bold: 700;
|
| 34 |
+
--font-weight-black: 800;
|
| 35 |
+
|
| 36 |
+
/* ---- Line heights ---- */
|
| 37 |
+
--line-height-ui: 1.3; /* UI components, tight */
|
| 38 |
+
--line-height-heading: 1.15; /* large display headings */
|
| 39 |
+
--line-height-body: 1.5; /* paragraphs, spacious */
|
| 40 |
+
--line-height-code: 1.45;
|
| 41 |
+
|
| 42 |
+
/* ---- Letter spacing ---- */
|
| 43 |
+
--letter-spacing-heading: -0.015em; /* Spectrum tightens large type */
|
| 44 |
+
--letter-spacing-ui: 0;
|
| 45 |
+
--letter-spacing-caps: 0.06em; /* eyebrows / overlines */
|
| 46 |
+
|
| 47 |
+
/* ============================================================
|
| 48 |
+
SEMANTIC TYPE ROLES
|
| 49 |
+
============================================================ */
|
| 50 |
+
--type-display: var(--font-weight-bold) var(--font-size-1000)/var(--line-height-heading) var(--font-sans);
|
| 51 |
+
--type-h1: var(--font-weight-bold) var(--font-size-800)/var(--line-height-heading) var(--font-sans);
|
| 52 |
+
--type-h2: var(--font-weight-bold) var(--font-size-600)/var(--line-height-heading) var(--font-sans);
|
| 53 |
+
--type-h3: var(--font-weight-semibold) var(--font-size-400)/var(--line-height-ui) var(--font-sans);
|
| 54 |
+
--type-h4: var(--font-weight-semibold) var(--font-size-300)/var(--line-height-ui) var(--font-sans);
|
| 55 |
+
--type-body-lg: var(--font-weight-regular) var(--font-size-300)/var(--line-height-body) var(--font-sans);
|
| 56 |
+
--type-body: var(--font-weight-regular) var(--font-size-100)/var(--line-height-body) var(--font-sans);
|
| 57 |
+
--type-ui: var(--font-weight-regular) var(--font-size-100)/var(--line-height-ui) var(--font-sans);
|
| 58 |
+
--type-ui-bold: var(--font-weight-semibold) var(--font-size-100)/var(--line-height-ui) var(--font-sans);
|
| 59 |
+
--type-detail: var(--font-weight-regular) var(--font-size-75)/var(--line-height-ui) var(--font-sans);
|
| 60 |
+
--type-code: var(--font-weight-regular) var(--font-size-75)/var(--line-height-code) var(--font-code);
|
| 61 |
+
}
|