# NCS Presale Design System

A design system extracted from the **NCS Presale Dashboard** — an internal sales-pipeline command center built by **YIPINTSOI NEXT (YIP NEXT)** for its **NCS (Network & Cyber Security)** business unit. The product helps presale engineers and sales teams register, track, weight and forecast cyber-security deals across the Thai enterprise, FSI, telco, energy and government markets.

It is a dark, data-dense "command center" UI: deep navy canvas, a top-center indigo glow, a red brand accent, and a family of luminous semantic gradients (cyan / violet / emerald / amber / rose) that color KPIs, charts and pipeline stages.

## Sources

- **Codebase:** `dashboard-v4 copy 2/` — a Vite + React 18 + Recharts SPA (`ncs-dashboard-v4`), deployed to Cloudflare Pages behind Cloudflare Access (Google SSO, `@ncs.co.th`). Key files read: `index.html` (global CSS / design tokens), `src/App.jsx` (shell, tabs, auth, session), `src/components/{Header,Sidebar,KpiCards,GlobalFilterBar,ProjectTable,Icon}.jsx`, `src/components/tabs/SalesCommandTab.jsx` (charts), `src/utils/formatters.js` (chart colors, currency, stage colors).
- **Logo:** `assets/yip-next-logo.png` — copied from `dashboard-v4 copy 2/public/yip-next-logo.png` ("YIPINTSOI NEXT" wordmark with red accent dots).
- The product is **bilingual** (English UI, Thai internal docs/notes). Currency is **Thai Baht (฿ / THB)**.

> Note for future readers: the codebase and Figma (if any) may not be re-attached. This README captures everything needed to design on-brand without them.

---

## CONTENT FUNDAMENTALS

**Voice — terse, operational, analyst-grade.** Copy reads like a trading desk, not a marketing site. Labels are nouns or noun phrases ("Weighted Forecast", "At Risk", "Sales Leaderboard"), actions are single imperative verbs ("Apply", "Register", "Update", "Retry", "Export CSV", "Clear").

**Casing & tracking — the signature pattern.** Micro-labels and captions are **UPPERCASE with wide letter-spacing** (`0.1em`–`0.2em`) at small sizes (8–10px), e.g. `TOTAL PIPELINE`, `WEIGHTED COVERAGE`, `LIVE`, `ONLINE NOW · 3`, `NAVIGATION`. Values and headings are mixed-case and **very heavy** (800–900 weight).

**Person.** Second person, sparingly ("Save your work and re-login before making changes"). Mostly impersonal/labelled — the UI states facts, it doesn't chat.

**Domain vocabulary (use verbatim):** Pipeline, Weighted Forecast, Win Probability (WP / Win%), Committed (≥70%), Stage, Workload Status (Active / Inactive), Presale Owner, Presale Team, Sale Owner, Sale Group, NCS Code, Vendor, Solution, Distributor, At-Risk, Stale 30+, Win / Handover, POC / Demo. Pipeline stages, in order: **Requirement → Proposal → POC / Demo → Negotiation → Win / Handover** (+ **Lost**).

**Numbers.** Compact notation (`฿1.2B`, `56.3M`), THB currency, percentages with one decimal in tables (`64.2%`) and rounded in badges (`64%`). Money is almost always emerald (`#10b981`).

**Emoji.** Used *sparingly and only* in the dense header/summary stat clusters as tiny category glyphs — 👥 Presales, 🤝 Sales, ⚡ Active, 💰 Value, 📁 📈. Never in body copy, buttons, headings or marketing. A `✦` star decorates the "Exclusive" tab. Don't introduce new emoji elsewhere.

**Tone examples (verbatim):** "Loading pipeline…", "FETCHING RECORDS…", "No active pipeline found for this engineer.", "All healthy", "Probability-adjusted", "⚠ Your Cloudflare Access session has expired."

---

## VISUAL FOUNDATIONS

**Canvas.** Deep navy `#0b1120` with a **fixed** top-center radial glow: `radial-gradient(circle at 50% 0%, #1e1b4b 0%, #0b1120 70%)`. Every screen sits on this. The sidebar is darker still (`rgba(5,8,20,0.9)`).

**Color.** One brand accent — **red `#dc2626`** (tabs, focus rings, brand chrome, the spinner). Everything else is a **semantic hue** used as a 135° gradient: cyan `#00d4ff→#22d3ee` (info/executive), violet `#8b5cf6→#a78bfa` (analytics/deals), emerald `#10b981→#34d399` (value/success), amber `#f59e0b→#fbbf24` (forecast/caution), rose `#f43f5e→#fb7185` (at-risk/lost), blue `#3b82f6` (data). Neutrals are the Tailwind **slate** scale, extended down to `#050814`. Big numbers are **gradient-clipped text** (`-webkit-background-clip:text`).

**Type.** **Inter** only, run heavy: 900 for display values & headings, 800 for labels/buttons, 500–600 for body/data. Display numerals use tight tracking (`-0.03em`); micro-labels use wide tracking (`0.16em`) + uppercase. Dense scale — UI text is mostly 10–13px; KPI values 26px. Timestamps use monospace.

**Cards.** Two surfaces: (1) **gradient card** — `linear-gradient(145deg,#1e293b,#0f172a)`, `1px solid rgba(255,255,255,0.07)`, radius 14, shadow `0 10px 25px -5px rgba(0,0,0,0.5)`; (2) **glass panel** — `rgba(255,255,255,0.03)` + `backdrop-filter: blur(20px)`. KPI cards add a **colored glow halo** (`0 0 20px rgba(hue,0.2)`), a blurred color **orb** bleeding off the top-right corner, and a small glowing icon chip. Accent state = a 3px top/left border in the stage color.

**Borders & radii.** Hairline white borders at 5–10% opacity. Radii: 5 (tags) · 6 (chips) · 8 (buttons/inputs) · 10 (nav) · 12 (popovers) · 14 (KPI) · 16 (content) · pill (badges/avatars).

**Shadows & glow.** Deep, soft black elevation shadows for cards; colored 20px halos for accent emphasis; `inset 0 1px 0 rgba(255,255,255,0.05)` top-highlight on KPI cards. Popovers: `0 12px 40px rgba(0,0,0,0.6)`.

**Transparency & blur.** Heavy use. The header is glass (`blur(16px)` + `rgba(11,17,32,0.9)` + red-tinted bottom border). Filter bars, tab bars, popovers and the sidebar all blur the navy behind them.

**Motion.** One confident ease-out: `cubic-bezier(0.16,1,0.3,1)`. Content fades up on mount (`fadeUp`, 0.45s). Live/online dots **pulse-glow** (2s). The spinner is a red ring. Charts animate fills/widths (`width 0.8s ease`).

**Hover / press.** Cards & buttons **lift** (`translateY(-2px)`) with a deepened/colored shadow; solid buttons brighten (`filter: brightness(1.08)`); soft/ghost buttons deepen their tint; icon buttons shift to red. Inactive tabs warm from slate-500 → slate-300. No shrink-on-press.

**Imagery.** None photographic — this is a pure data UI. "Imagery" = charts (Recharts: dual-line quarter forecast, stage/group donuts, area projections, bar lists) and the logo. Charts use a fixed palette and the per-stage colors above; grid lines are `rgba(255,255,255,0.06)`, axis text `rgba(255,255,255,0.35)`, tooltips are dark glass with a red-tinted border.

**Layout.** Centered content column, `max-width: 1400px`, `24px` gutters. Sticky glass header (64px) + sticky filter bar + sticky tab bar. KPI grid is `repeat(auto-fit,minmax(200px,1fr))`. Tight 14–16px gaps between blocks, generous 18–22px padding inside cards.

---

## THEMING (dark / light)

The system is **dark by default**; light is **opt-in** via a `data-theme="light"` attribute on `<html>`. Dark is the product's native look; light is a lifted-surface variant that keeps the brand red and every semantic hue — only surfaces, text, borders, gradient text-stops and tint foregrounds change.

**Mechanism — pure CSS variables.** `tokens/colors.css` declares the dark values on `:root` and a `[data-theme="light"]` block overriding the *semantic aliases* (`--surface-card`, `--text-heading`, `--border-card`, …), the gradient tokens (`--grad-*`, darkened so gradient-clipped numerals stay legible on white), and a set of **tint foregrounds** `--fg-{hue}` that flip between a light hue (on dark) and a darker hue (on light). Components never hardcode navy — they read these tokens, so flipping the attribute re-themes everything instantly with no React re-render.

**To switch themes:**
```js
document.documentElement.dataset.theme = 'light'; // or 'dark' / remove for default
```
The UI kit wires this to a sun/moon toggle in the header and persists the choice to `localStorage['ncs-theme']` (with a no-flash init script in `<head>`).

**Authoring rule:** when building new on-brand surfaces, reference the semantic alias tokens (`var(--surface-card)`, `var(--text-heading)`, `var(--border-card)`, `var(--fg-emerald)`, `var(--grad-cyan)`) rather than raw hex — that is what makes a component theme-safe. Fixed hues used as *fills with white text* (solid buttons, badge `solid`, status dots, chart series) stay literal; they read on both themes.

## RESPONSIVE

Mobile-first behaviors used across the kit and components:
- **Stacking grids.** KPI row is `repeat(auto-fit,minmax(200px,1fr))`; the Sales Command chart pair and leaderboard collapse to a single column under **720px**.
- **Tables → cards.** Below 720px the deal table and the sales leaderboard render as **stacked cards** (one card per row) instead of scrolling tables — driven by a `useIsMobile()` (`matchMedia('(max-width: 720px)')`) hook.
- **Header condenses.** The center stat strip hides under 900px; action-button labels collapse to icons under 720px; gutters tighten from 24px → 14px.
- **Touch targets.** Interactive controls stay ≥ the comfortable tap range (icon buttons 28–40px; buttons keep ≥32px height); filter rows wrap rather than overflow.

---


## ICONOGRAPHY

The product ships its **own hand-rolled icon component** (`src/components/Icon.jsx`) — a dictionary of inline SVG paths that are **Lucide / Feather icons** (24×24 viewBox, `fill:none`, `stroke:currentColor`, `stroke-width:2`, round caps/joins). Common glyphs: `dollar-sign`, `trending-up`, `activity`, `pie-chart`, `alert-triangle`, `award`, `list`, `bar-chart`, `package`, `users`, `file-text`, `refresh-ccw`, `edit`, `search`, `compass`, `shield`, `user-check`.

**For this design system, use [Lucide](https://lucide.dev) directly** — it is a pixel-exact match for the product's icons and is CDN-available. This repo includes a faithful subset in `ui_kits/ncs-presale-dashboard/kit-icons.jsx` (`<Icon name=… size=… />`) you can copy. Keep stroke-width 2, round caps. **Substitution flag:** the product's icons are re-drawn Lucide paths, not a licensed icon font — using Lucide is the intended equivalent, not a downgrade.

Beyond SVG, the only other "icons" are the **category emoji** in stat strips (see Content Fundamentals) and a `✦` decorative star. No icon font, no PNG sprites.

---

## INDEX

**Root**
- `styles.css` — the single entry point consumers link (a manifest of `@import`s).
- `readme.md` — this file. `SKILL.md` — Agent Skills wrapper.
- `assets/yip-next-logo.png` — YIPINTSOI NEXT wordmark.

**`tokens/`** — `fonts.css` (Inter) · `colors.css` (navy scale, brand red, semantic hues, gradients, stage colors, semantic aliases) · `typography.css` · `spacing.css` (spacing, layout, radii) · `effects.css` (shadows, glows, blur, motion).

**`components/`** — reusable React primitives (namespace `window.NCSPresaleDesignSystem_3f9137`):
- `core/` — **Button**, **IconButton**, **Badge**, **FilterChip**, **Avatar**, **Spinner**
- `forms/` — **Input**, **Select**
- `data/` — **Card**, **KpiCard**, **ProgressBar**, **StatPill** (+ `StatStrip`)
- `navigation/` — **TabBar**

**`guidelines/foundations/`** — 16 specimen cards (Colors, Type, Spacing, Brand) shown in the Design System tab.

**`ui_kits/ncs-presale-dashboard/`** — interactive recreation of the product: login gate → glass header (logo, stats, presence, actions) → global filter bar → tab bar → KPI row → **Sales Command** (quarter forecast line chart, stage donut, sales leaderboard) and **All Projects** (filterable deal table). Open `index.html`.
