pelagia-portal/Wireframe/design-system.html
Hardik 2de883c70f
All checks were successful
PR checks / checks (pull_request) Successful in 36s
PR checks / integration (pull_request) Successful in 26s
chore(design-system): add PPMS design system reference and sync bundle
Captures the live PPMS visual language (tokens from globals.css +
components/ui/* + lib/utils.ts) so new screens can be prototyped with the
same look and feel.

- Wireframe/design-system.html: single-page living style guide (color ramps,
  typography, radius/shadow/spacing, icons, app shell, buttons, badges, PO
  status badges, cards/KPIs, forms, tabs, tables, alerts/dialog, charts,
  formatting conventions, do/don't).
- Wireframe/ds-bundle/: per-component @dsCard preview cards (Foundations /
  Layout / Components) used to sync the design system to the claude.ai
  Design System project.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 04:30:22 +05:30

534 lines
45 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>PPMS — Design System</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
<script>
// ── EXACT theme tokens from App/app/globals.css (@theme) ──
tailwind.config = {
theme: {
extend: {
colors: {
primary: { 50:"#eff6ff",100:"#dbeafe",200:"#bfdbfe",500:"#3b82f6",600:"#2563eb",700:"#1d4ed8",800:"#1e40af" },
success: { DEFAULT:"#16a34a", 50:"#f0fdf4",100:"#dcfce7",700:"#15803d" },
warning: { DEFAULT:"#d97706", 50:"#fffbeb",100:"#fef3c7",700:"#b45309" },
danger: { DEFAULT:"#dc2626", 50:"#fef2f2",100:"#fee2e2",700:"#b91c1c" },
neutral: { 50:"#fafafa",100:"#f5f5f5",200:"#e5e5e5",300:"#d4d4d4",400:"#a3a3a3",500:"#737373",600:"#525252",700:"#404040",800:"#262626",900:"#171717" },
},
fontFamily: {
sans: ['Inter','ui-sans-serif','system-ui','sans-serif'],
mono: ['"JetBrains Mono"','ui-monospace','monospace'],
},
},
},
};
</script>
<style>
body { font-family:'Inter',ui-sans-serif,system-ui,sans-serif; }
code, pre, .mono { font-family:'JetBrains Mono',ui-monospace,monospace; }
.toc a.active { color:#1d4ed8; font-weight:600; }
::-webkit-scrollbar { width:9px; height:9px; }
::-webkit-scrollbar-thumb { background:#d4d4d4; border-radius:5px; }
/* click-to-copy snippet */
.snip { position:relative; }
.snip code { cursor:copy; }
.snip .copied { position:absolute; top:6px; right:8px; font-size:10px; color:#16a34a; opacity:0; transition:opacity .2s; }
.snip.show .copied { opacity:1; }
html { scroll-behavior:smooth; scroll-padding-top:84px; }
</style>
</head>
<body class="bg-neutral-50 text-neutral-900">
<!-- Top bar -->
<header class="sticky top-0 z-30 flex h-16 items-center gap-3 border-b border-neutral-200 bg-white/90 px-6 backdrop-blur">
<div class="flex h-8 w-8 items-center justify-center rounded-lg bg-primary-600">
<svg class="h-4 w-4 text-white" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="22" x2="12" y2="8"/><path d="M5 12H2a10 10 0 0 0 20 0h-3"/><circle cx="12" cy="5" r="3"/></svg>
</div>
<div>
<p class="text-sm font-semibold leading-tight">PPMS Design System</p>
<p class="text-xs text-neutral-400 leading-tight">Pelagia Purchase Management System · v1</p>
</div>
<div class="ml-auto hidden sm:flex items-center gap-2 text-xs text-neutral-400">
<span class="rounded-full bg-neutral-100 px-2 py-0.5">Next.js 15</span>
<span class="rounded-full bg-neutral-100 px-2 py-0.5">Tailwind v4</span>
<span class="rounded-full bg-neutral-100 px-2 py-0.5">lucide-react</span>
<span class="rounded-full bg-neutral-100 px-2 py-0.5">recharts</span>
</div>
</header>
<div class="mx-auto flex max-w-7xl gap-8 px-6">
<!-- TOC -->
<nav class="toc sticky top-16 hidden h-[calc(100vh-4rem)] w-52 shrink-0 overflow-y-auto py-8 text-sm lg:block">
<p class="mb-2 px-2 text-xs font-semibold uppercase tracking-wider text-neutral-400">Foundations</p>
<a href="#overview" class="block rounded px-2 py-1.5 text-neutral-600 hover:bg-neutral-100">Overview</a>
<a href="#color" class="block rounded px-2 py-1.5 text-neutral-600 hover:bg-neutral-100">Color</a>
<a href="#type" class="block rounded px-2 py-1.5 text-neutral-600 hover:bg-neutral-100">Typography</a>
<a href="#tokens" class="block rounded px-2 py-1.5 text-neutral-600 hover:bg-neutral-100">Radius · Shadow · Space</a>
<a href="#icons" class="block rounded px-2 py-1.5 text-neutral-600 hover:bg-neutral-100">Icons</a>
<p class="mb-2 mt-4 px-2 text-xs font-semibold uppercase tracking-wider text-neutral-400">Layout</p>
<a href="#shell" class="block rounded px-2 py-1.5 text-neutral-600 hover:bg-neutral-100">App shell</a>
<a href="#pageheader" class="block rounded px-2 py-1.5 text-neutral-600 hover:bg-neutral-100">Page header</a>
<p class="mb-2 mt-4 px-2 text-xs font-semibold uppercase tracking-wider text-neutral-400">Components</p>
<a href="#buttons" class="block rounded px-2 py-1.5 text-neutral-600 hover:bg-neutral-100">Buttons</a>
<a href="#badges" class="block rounded px-2 py-1.5 text-neutral-600 hover:bg-neutral-100">Badges</a>
<a href="#status" class="block rounded px-2 py-1.5 text-neutral-600 hover:bg-neutral-100">PO status badges</a>
<a href="#cards" class="block rounded px-2 py-1.5 text-neutral-600 hover:bg-neutral-100">Cards & KPIs</a>
<a href="#forms" class="block rounded px-2 py-1.5 text-neutral-600 hover:bg-neutral-100">Forms</a>
<a href="#segmented" class="block rounded px-2 py-1.5 text-neutral-600 hover:bg-neutral-100">Tabs & segmented</a>
<a href="#table" class="block rounded px-2 py-1.5 text-neutral-600 hover:bg-neutral-100">Tables</a>
<a href="#alerts" class="block rounded px-2 py-1.5 text-neutral-600 hover:bg-neutral-100">Alerts & dialog</a>
<a href="#charts" class="block rounded px-2 py-1.5 text-neutral-600 hover:bg-neutral-100">Charts</a>
<p class="mb-2 mt-4 px-2 text-xs font-semibold uppercase tracking-wider text-neutral-400">Conventions</p>
<a href="#format" class="block rounded px-2 py-1.5 text-neutral-600 hover:bg-neutral-100">Formatting</a>
<a href="#voice" class="block rounded px-2 py-1.5 text-neutral-600 hover:bg-neutral-100">Do & don't</a>
</nav>
<!-- Content -->
<main class="min-w-0 flex-1 space-y-16 py-8">
<!-- OVERVIEW -->
<section id="overview">
<h1 class="text-2xl font-semibold tracking-tight">Design System</h1>
<p class="mt-2 max-w-2xl text-sm leading-relaxed text-neutral-600">
The visual language of the Pelagia Purchase Management System — an internal PO tool for a maritime company.
Everything here is lifted from the live codebase (<code class="rounded bg-neutral-100 px-1 text-xs">app/globals.css</code> +
<code class="rounded bg-neutral-100 px-1 text-xs">components/ui/*</code>), so screens built from these tokens drop straight in.
</p>
<div class="mt-4 grid gap-3 sm:grid-cols-2 lg:grid-cols-4 text-sm">
<div class="rounded-lg border border-neutral-200 bg-white p-4"><p class="text-xs font-medium uppercase tracking-wider text-neutral-400">Framework</p><p class="mt-1 font-medium">Next.js 15 · App Router</p></div>
<div class="rounded-lg border border-neutral-200 bg-white p-4"><p class="text-xs font-medium uppercase tracking-wider text-neutral-400">Styling</p><p class="mt-1 font-medium">Tailwind CSS v4</p></div>
<div class="rounded-lg border border-neutral-200 bg-white p-4"><p class="text-xs font-medium uppercase tracking-wider text-neutral-400">Primitives</p><p class="mt-1 font-medium">Radix UI · CVA</p></div>
<div class="rounded-lg border border-neutral-200 bg-white p-4"><p class="text-xs font-medium uppercase tracking-wider text-neutral-400">Charts · Icons</p><p class="mt-1 font-medium">recharts · lucide</p></div>
</div>
<p class="mt-4 text-xs text-neutral-400">Tip: click any <code class="rounded bg-neutral-100 px-1">code snippet</code> to copy it.</p>
</section>
<!-- COLOR -->
<section id="color">
<h2 class="text-lg font-semibold">Color</h2>
<p class="mt-1 max-w-2xl text-sm text-neutral-600">Five ramps. <b>Primary</b> = actions, links, active nav. <b>Success</b> = approved / paid. <b>Warning</b> = needs action (edits, vendor ID, partial). <b>Danger</b> = rejected / destructive. <b>Neutral</b> = all structure, text and borders.</p>
<div class="mt-5 space-y-5" id="ramps"></div>
</section>
<!-- TYPOGRAPHY -->
<section id="type">
<h2 class="text-lg font-semibold">Typography</h2>
<p class="mt-1 text-sm text-neutral-600"><b>Inter</b> for UI, <b>JetBrains Mono</b> for codes &amp; numbers (PO numbers, accounting codes).</p>
<div class="mt-4 divide-y divide-neutral-100 rounded-lg border border-neutral-200 bg-white">
<div class="flex items-baseline justify-between gap-4 p-4"><p class="text-2xl font-semibold text-neutral-900">Page title</p><code class="text-xs text-neutral-400">text-2xl font-semibold</code></div>
<div class="flex items-baseline justify-between gap-4 p-4"><p class="text-lg font-semibold text-neutral-900">Section heading</p><code class="text-xs text-neutral-400">text-lg font-semibold</code></div>
<div class="flex items-baseline justify-between gap-4 p-4"><p class="text-base font-semibold text-neutral-900">Card title</p><code class="text-xs text-neutral-400">text-base font-semibold</code></div>
<div class="flex items-baseline justify-between gap-4 p-4"><p class="text-sm text-neutral-700">Body / table text — the workhorse size for the whole app.</p><code class="text-xs text-neutral-400">text-sm</code></div>
<div class="flex items-baseline justify-between gap-4 p-4"><p class="text-sm text-neutral-500">Muted description &amp; helper text</p><code class="text-xs text-neutral-400">text-sm text-neutral-500</code></div>
<div class="flex items-baseline justify-between gap-4 p-4"><p class="text-xs font-semibold uppercase tracking-wider text-neutral-400">Eyebrow / label</p><code class="text-xs text-neutral-400">text-xs uppercase tracking-wider</code></div>
<div class="flex items-baseline justify-between gap-4 p-4"><p class="mono text-sm text-neutral-700">PMS/HNR1/9000/2024-25</p><code class="text-xs text-neutral-400">font-mono</code></div>
</div>
</section>
<!-- TOKENS -->
<section id="tokens">
<h2 class="text-lg font-semibold">Radius · Shadow · Spacing</h2>
<div class="mt-4 grid gap-4 sm:grid-cols-3">
<div class="rounded-lg border border-neutral-200 bg-white p-5">
<p class="mb-3 text-xs font-semibold uppercase tracking-wider text-neutral-400">Radius</p>
<div class="flex items-end gap-4">
<div class="text-center"><div class="h-12 w-12 rounded-md border border-neutral-300 bg-neutral-50"></div><code class="mt-1 block text-[11px] text-neutral-400">rounded-md</code></div>
<div class="text-center"><div class="h-12 w-12 rounded-lg border border-neutral-300 bg-neutral-50"></div><code class="mt-1 block text-[11px] text-neutral-400">rounded-lg</code></div>
<div class="text-center"><div class="h-12 w-12 rounded-full border border-neutral-300 bg-neutral-50"></div><code class="mt-1 block text-[11px] text-neutral-400">rounded-full</code></div>
</div>
<p class="mt-3 text-xs text-neutral-500"><b>lg</b> for cards/buttons/inputs, <b>md</b> for nav items, <b>full</b> for badges &amp; avatars.</p>
</div>
<div class="rounded-lg border border-neutral-200 bg-white p-5">
<p class="mb-3 text-xs font-semibold uppercase tracking-wider text-neutral-400">Elevation</p>
<div class="flex items-end gap-4">
<div class="text-center"><div class="h-12 w-12 rounded-lg border border-neutral-200 bg-white"></div><code class="mt-1 block text-[11px] text-neutral-400">border</code></div>
<div class="text-center"><div class="h-12 w-12 rounded-lg border border-neutral-200 bg-white shadow-sm"></div><code class="mt-1 block text-[11px] text-neutral-400">shadow-sm</code></div>
<div class="text-center"><div class="h-12 w-12 rounded-lg bg-white shadow-lg"></div><code class="mt-1 block text-[11px] text-neutral-400">shadow-lg</code></div>
</div>
<p class="mt-3 text-xs text-neutral-500">Flat by default — a 1px <b>border-neutral-200</b> separates surfaces. <b>shadow-sm</b> on cards, <b>shadow-lg</b> only for popovers/dialogs.</p>
</div>
<div class="rounded-lg border border-neutral-200 bg-white p-5">
<p class="mb-3 text-xs font-semibold uppercase tracking-wider text-neutral-400">Spacing rhythm</p>
<div class="space-y-1.5">
<div class="flex items-center gap-2"><div class="h-3 bg-primary-200" style="width:16px"></div><code class="text-[11px] text-neutral-400">gap-2 · 8px</code></div>
<div class="flex items-center gap-2"><div class="h-3 bg-primary-200" style="width:24px"></div><code class="text-[11px] text-neutral-400">gap-3 · 12px (rows)</code></div>
<div class="flex items-center gap-2"><div class="h-3 bg-primary-200" style="width:40px"></div><code class="text-[11px] text-neutral-400">p-5 · 20px (cards)</code></div>
<div class="flex items-center gap-2"><div class="h-3 bg-primary-200" style="width:48px"></div><code class="text-[11px] text-neutral-400">p-6 / gap-6 · 24px</code></div>
</div>
<p class="mt-3 text-xs text-neutral-500">Page padding <b>p-6</b>; cards <b>p-5</b>/<b>p-6</b>; controls gap <b>gap-2/3</b>.</p>
</div>
</div>
</section>
<!-- ICONS -->
<section id="icons">
<h2 class="text-lg font-semibold">Icons</h2>
<p class="mt-1 text-sm text-neutral-600"><b>lucide-react</b>, stroke 2, sized <code class="rounded bg-neutral-100 px-1 text-xs">h-4 w-4</code> inline / <code class="rounded bg-neutral-100 px-1 text-xs">h-5 w-5</code> standalone. They inherit text color (<code class="rounded bg-neutral-100 px-1 text-xs">currentColor</code>).</p>
<div class="mt-4 flex flex-wrap gap-3 rounded-lg border border-neutral-200 bg-white p-5 text-neutral-600" id="iconrow"></div>
</section>
<!-- APP SHELL -->
<section id="shell">
<h2 class="text-lg font-semibold">App shell</h2>
<p class="mt-1 max-w-2xl text-sm text-neutral-600">Fixed <b>w-60</b> sidebar (white, <code class="rounded bg-neutral-100 px-1 text-xs">border-r</code>) + <b>h-16</b> top bar + scrollable <code class="rounded bg-neutral-100 px-1 text-xs">main</code> on <code class="rounded bg-neutral-100 px-1 text-xs">bg-neutral-50</code> with <b>p-6</b>. Nav links: <code class="rounded bg-neutral-100 px-1 text-xs">rounded-md px-3 py-2 text-sm font-medium</code>; active = <code class="rounded bg-neutral-100 px-1 text-xs">bg-primary-50 text-primary-700</code>; section eyebrow = <code class="rounded bg-neutral-100 px-1 text-xs">text-xs uppercase tracking-wider text-neutral-400</code>.</p>
<div class="mt-4 overflow-hidden rounded-lg border border-neutral-200">
<div class="flex h-80 bg-neutral-50">
<aside class="flex w-56 shrink-0 flex-col border-r border-neutral-200 bg-white">
<div class="flex h-14 items-center gap-2.5 border-b border-neutral-200 px-4">
<div class="flex h-8 w-8 items-center justify-center rounded-lg bg-primary-600"><svg class="h-4 w-4 text-white" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><line x1="12" y1="22" x2="12" y2="8"/><path d="M5 12H2a10 10 0 0 0 20 0h-3"/><circle cx="12" cy="5" r="3"/></svg></div>
<span class="text-sm font-semibold">PPMS</span>
</div>
<nav class="flex-1 space-y-0.5 p-3 text-sm">
<a class="flex items-center gap-3 rounded-md bg-primary-50 px-3 py-2 font-medium text-primary-700"><span class="h-4 w-4 rounded bg-primary-600/20"></span>Dashboard</a>
<a class="flex items-center gap-3 rounded-md px-3 py-2 font-medium text-neutral-600 hover:bg-neutral-100"><span class="h-4 w-4 rounded bg-neutral-300"></span>New PO</a>
<a class="flex items-center gap-3 rounded-md px-3 py-2 font-medium text-neutral-600 hover:bg-neutral-100"><span class="h-4 w-4 rounded bg-neutral-300"></span>Approvals</a>
<p class="px-3 pb-1 pt-4 text-xs font-semibold uppercase tracking-wider text-neutral-400">Administration</p>
<a class="flex items-center gap-3 rounded-md px-3 py-2 font-medium text-neutral-600 hover:bg-neutral-100"><span class="h-4 w-4 rounded bg-neutral-300"></span>Users</a>
</nav>
</aside>
<div class="flex flex-1 flex-col">
<div class="flex h-14 items-center justify-between border-b border-neutral-200 bg-white px-5">
<span class="text-sm font-medium text-neutral-500">Dashboard</span>
<div class="flex items-center gap-2"><span class="h-7 w-7 rounded-full bg-neutral-200"></span></div>
</div>
<div class="flex-1 space-y-3 overflow-hidden p-5">
<div class="h-4 w-40 rounded bg-neutral-200"></div>
<div class="grid grid-cols-3 gap-3">
<div class="h-16 rounded-lg border border-neutral-200 bg-white"></div>
<div class="h-16 rounded-lg border border-neutral-200 bg-white"></div>
<div class="h-16 rounded-lg border border-neutral-200 bg-white"></div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- PAGE HEADER -->
<section id="pageheader">
<h2 class="text-lg font-semibold">Page header</h2>
<p class="mt-1 text-sm text-neutral-600">Title + muted subtitle on the left, primary action on the right.</p>
<div class="mt-4 rounded-lg border border-neutral-200 bg-white p-6">
<div class="flex items-start justify-between gap-4">
<div>
<h1 class="text-2xl font-semibold text-neutral-900">Purchase Orders</h1>
<p class="mt-1 text-sm text-neutral-500">Create, track and approve orders across the fleet.</p>
</div>
<button class="inline-flex h-10 items-center gap-2 rounded-lg bg-primary-600 px-4 text-sm font-medium text-white hover:bg-primary-700">
<svg class="h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>New PO
</button>
</div>
</div>
<div class="snip mt-2"><pre class="overflow-x-auto rounded-lg bg-neutral-900 p-3 text-xs leading-relaxed text-neutral-100"><code>&lt;div class="flex items-start justify-between gap-4"&gt;
&lt;div&gt;
&lt;h1 class="text-2xl font-semibold text-neutral-900"&gt;Title&lt;/h1&gt;
&lt;p class="mt-1 text-sm text-neutral-500"&gt;Subtitle&lt;/p&gt;
&lt;/div&gt;
&lt;Button&gt;New PO&lt;/Button&gt;
&lt;/div&gt;</code><span class="copied">copied ✓</span></pre></div>
</section>
<!-- BUTTONS -->
<section id="buttons">
<h2 class="text-lg font-semibold">Buttons</h2>
<p class="mt-1 text-sm text-neutral-600">From <code class="rounded bg-neutral-100 px-1 text-xs">components/ui/button.tsx</code> (CVA). Base: <code class="rounded bg-neutral-100 px-1 text-xs">inline-flex items-center gap-2 rounded-lg text-sm font-medium</code> + focus ring.</p>
<div class="mt-4 space-y-4 rounded-lg border border-neutral-200 bg-white p-5">
<div class="flex flex-wrap items-center gap-3">
<button class="inline-flex h-10 items-center gap-2 rounded-lg bg-primary-600 px-4 text-sm font-medium text-white hover:bg-primary-700">Default</button>
<button class="inline-flex h-10 items-center gap-2 rounded-lg border border-neutral-300 bg-white px-4 text-sm font-medium text-neutral-700 hover:bg-neutral-50">Secondary</button>
<button class="inline-flex h-10 items-center gap-2 rounded-lg bg-success px-4 text-sm font-medium text-white hover:opacity-90">Success</button>
<button class="inline-flex h-10 items-center gap-2 rounded-lg border border-warning bg-warning-50 px-4 text-sm font-medium text-warning-700 hover:bg-warning-100">Warning</button>
<button class="inline-flex h-10 items-center gap-2 rounded-lg bg-danger px-4 text-sm font-medium text-white hover:opacity-90">Destructive</button>
<button class="inline-flex h-10 items-center gap-2 rounded-lg px-4 text-sm font-medium text-neutral-700 hover:bg-neutral-100">Ghost</button>
<button class="inline-flex h-10 items-center gap-2 rounded-lg px-1 text-sm font-medium text-primary-600 underline-offset-4 hover:underline">Link</button>
<button class="inline-flex h-10 items-center gap-2 rounded-lg bg-primary-600 px-4 text-sm font-medium text-white opacity-60" disabled>Disabled</button>
</div>
<div class="flex flex-wrap items-center gap-3 border-t border-neutral-100 pt-4">
<button class="inline-flex h-8 items-center gap-1.5 rounded-lg bg-primary-600 px-3 text-xs font-medium text-white">sm · h-8</button>
<button class="inline-flex h-10 items-center gap-2 rounded-lg bg-primary-600 px-4 text-sm font-medium text-white">md · h-10</button>
<button class="inline-flex h-11 items-center gap-2 rounded-lg bg-primary-600 px-5 text-sm font-medium text-white">lg · h-11</button>
<button class="inline-flex h-10 w-10 items-center justify-center rounded-lg border border-neutral-300 bg-white text-neutral-700"><svg class="h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg></button>
</div>
</div>
<div class="snip mt-2"><pre class="overflow-x-auto rounded-lg bg-neutral-900 p-3 text-xs text-neutral-100"><code>&lt;Button variant="default|secondary|success|warning|destructive|ghost|link" size="sm|md|lg|icon"&gt;</code><span class="copied">copied ✓</span></pre></div>
</section>
<!-- BADGES -->
<section id="badges">
<h2 class="text-lg font-semibold">Badges</h2>
<p class="mt-1 text-sm text-neutral-600">From <code class="rounded bg-neutral-100 px-1 text-xs">components/ui/badge.tsx</code>. Base: <code class="rounded bg-neutral-100 px-1 text-xs">rounded-full px-2.5 py-0.5 text-xs font-medium</code>.</p>
<div class="mt-4 flex flex-wrap items-center gap-3 rounded-lg border border-neutral-200 bg-white p-5">
<span class="rounded-full bg-primary-100 px-2.5 py-0.5 text-xs font-medium text-primary-700">default</span>
<span class="rounded-full bg-neutral-100 px-2.5 py-0.5 text-xs font-medium text-neutral-700">secondary</span>
<span class="rounded-full bg-success-100 px-2.5 py-0.5 text-xs font-medium text-success-700">success</span>
<span class="rounded-full bg-warning-100 px-2.5 py-0.5 text-xs font-medium text-warning-700">warning</span>
<span class="rounded-full bg-danger-100 px-2.5 py-0.5 text-xs font-medium text-danger-700">danger</span>
<span class="rounded-full border border-neutral-300 px-2.5 py-0.5 text-xs font-medium text-neutral-600">outline</span>
</div>
</section>
<!-- PO STATUS -->
<section id="status">
<h2 class="text-lg font-semibold">PO status badges</h2>
<p class="mt-1 max-w-2xl text-sm text-neutral-600">The 13 lifecycle states map to badge variants in <code class="rounded bg-neutral-100 px-1 text-xs">lib/utils.ts</code> (<code class="rounded bg-neutral-100 px-1 text-xs">PO_STATUS_LABELS</code> / <code class="rounded bg-neutral-100 px-1 text-xs">PO_STATUS_VARIANTS</code>). Reuse this mapping — don't invent new status colors.</p>
<div class="mt-4 grid gap-2 rounded-lg border border-neutral-200 bg-white p-5 sm:grid-cols-2 lg:grid-cols-3" id="statusgrid"></div>
</section>
<!-- CARDS -->
<section id="cards">
<h2 class="text-lg font-semibold">Cards &amp; KPI stats</h2>
<p class="mt-1 text-sm text-neutral-600">Card = <code class="rounded bg-neutral-100 px-1 text-xs">rounded-lg border border-neutral-200 bg-white shadow-sm</code>. KPI stat cards drop the shadow and use <b>p-4/5</b>.</p>
<div class="mt-4 grid gap-4 lg:grid-cols-2">
<div class="rounded-lg border border-neutral-200 bg-white shadow-sm">
<div class="flex flex-col gap-1 p-6 pb-4">
<h3 class="text-base font-semibold text-neutral-900">Vendor details</h3>
<p class="text-sm text-neutral-500">GST-verified supplier on file.</p>
</div>
<div class="space-y-1 p-6 pt-0 text-sm text-neutral-600"><p>Acme Marine Supplies Pvt Ltd</p><p class="mono text-xs text-neutral-400">GSTIN 27ABCDE1234F1Z5</p></div>
<div class="flex items-center gap-2 p-6 pt-0"><button class="inline-flex h-8 items-center rounded-lg bg-primary-600 px-3 text-xs font-medium text-white">Edit</button><button class="inline-flex h-8 items-center rounded-lg border border-neutral-300 bg-white px-3 text-xs font-medium text-neutral-700">View POs</button></div>
</div>
<div class="grid grid-cols-2 gap-4">
<div class="rounded-lg border border-neutral-200 bg-white p-4"><p class="text-xs font-medium uppercase tracking-wider text-neutral-400">Open POs</p><p class="mt-1.5 text-xl font-semibold">24</p><p class="mt-0.5 text-xs text-success-700">▲ 8% vs last month</p></div>
<div class="rounded-lg border border-neutral-200 bg-white p-4"><p class="text-xs font-medium uppercase tracking-wider text-neutral-400">Awaiting approval</p><p class="mt-1.5 text-xl font-semibold">7</p><p class="mt-0.5 text-xs text-neutral-400">across 3 vessels</p></div>
<div class="rounded-lg border border-neutral-200 bg-white p-4"><p class="text-xs font-medium uppercase tracking-wider text-neutral-400">Spend (FY)</p><p class="mt-1.5 text-xl font-semibold">₹2.4 Cr</p><p class="mt-0.5 text-xs text-neutral-400">FY 202526</p></div>
<div class="rounded-lg border border-neutral-200 bg-white p-4"><p class="text-xs font-medium uppercase tracking-wider text-neutral-400">Overdue</p><p class="mt-1.5 text-xl font-semibold">2</p><p class="mt-0.5 text-xs text-danger-700">needs attention</p></div>
</div>
</div>
</section>
<!-- FORMS -->
<section id="forms">
<h2 class="text-lg font-semibold">Forms</h2>
<p class="mt-1 text-sm text-neutral-600">Inputs from <code class="rounded bg-neutral-100 px-1 text-xs">components/ui/input.tsx</code>: <code class="rounded bg-neutral-100 px-1 text-xs">h-10 rounded-lg border-neutral-300</code>, focus <code class="rounded bg-neutral-100 px-1 text-xs">border-primary-500 ring-2 ring-primary-500/20</code>.</p>
<div class="mt-4 grid max-w-2xl gap-4 rounded-lg border border-neutral-200 bg-white p-6">
<div><label class="mb-1.5 block text-sm font-medium text-neutral-700">PO title</label><input placeholder="e.g. Engine spares — MV Pelagia Star" class="h-10 w-full rounded-lg border border-neutral-300 px-3 text-sm placeholder:text-neutral-400 focus:border-primary-500 focus:outline-none focus:ring-2 focus:ring-primary-500/20" /></div>
<div class="grid grid-cols-2 gap-4">
<div><label class="mb-1.5 block text-sm font-medium text-neutral-700">Cost centre</label><select class="h-10 w-full rounded-lg border border-neutral-300 bg-white px-3 text-sm text-neutral-700 focus:border-primary-500 focus:outline-none focus:ring-2 focus:ring-primary-500/20"><option>MV Pelagia Star</option><option>MV Ocean Dawn</option></select></div>
<div><label class="mb-1.5 block text-sm font-medium text-neutral-700">Date required</label><input type="date" class="h-10 w-full rounded-lg border border-neutral-300 px-3 text-sm text-neutral-700 focus:border-primary-500 focus:outline-none focus:ring-2 focus:ring-primary-500/20" /></div>
</div>
<div><label class="mb-1.5 block text-sm font-medium text-neutral-700">Notes</label><textarea rows="3" placeholder="Optional…" class="w-full rounded-lg border border-neutral-300 px-3 py-2 text-sm placeholder:text-neutral-400 focus:border-primary-500 focus:outline-none focus:ring-2 focus:ring-primary-500/20"></textarea></div>
<div><label class="mb-1.5 block text-sm font-medium text-neutral-700">Disabled</label><input disabled value="Read-only value" class="h-10 w-full cursor-not-allowed rounded-lg border border-neutral-300 bg-neutral-50 px-3 text-sm text-neutral-500 opacity-60" /></div>
<p class="-mt-1 text-xs text-danger-700">Inline validation error sits under the field in <code class="rounded bg-neutral-100 px-1">text-danger-700</code>.</p>
</div>
</section>
<!-- SEGMENTED / TABS -->
<section id="segmented">
<h2 class="text-lg font-semibold">Tabs &amp; segmented controls</h2>
<p class="mt-1 text-sm text-neutral-600">Toolbar filters use a pill segmented control; page sections use an underline tab bar.</p>
<div class="mt-4 flex flex-wrap items-center gap-6 rounded-lg border border-neutral-200 bg-white p-5">
<div class="inline-flex rounded-lg border border-neutral-200 bg-white p-0.5 text-sm">
<button class="rounded-md bg-primary-600 px-3 py-1 font-medium text-white shadow-sm">Monthly</button>
<button class="rounded-md px-3 py-1 font-medium text-neutral-500 hover:text-neutral-800">Yearly</button>
<button class="rounded-md px-3 py-1 font-medium text-neutral-500 hover:text-neutral-800">Weekly</button>
</div>
<div class="flex items-center gap-6 border-b border-neutral-200 text-sm">
<button class="-mb-px border-b-2 border-primary-600 pb-2 font-medium text-primary-700">Details</button>
<button class="-mb-px border-b-2 border-transparent pb-2 font-medium text-neutral-500 hover:text-neutral-800">Line items</button>
<button class="-mb-px border-b-2 border-transparent pb-2 font-medium text-neutral-500 hover:text-neutral-800">History</button>
</div>
</div>
</section>
<!-- TABLE -->
<section id="table">
<h2 class="text-lg font-semibold">Tables</h2>
<p class="mt-1 text-sm text-neutral-600">Header row <code class="rounded bg-neutral-100 px-1 text-xs">bg-neutral-50</code> with <code class="rounded bg-neutral-100 px-1 text-xs">text-xs uppercase tracking-wider text-neutral-400</code>; body rows <code class="rounded bg-neutral-100 px-1 text-xs">divide-y divide-neutral-100</code>, hover <code class="rounded bg-neutral-100 px-1 text-xs">hover:bg-neutral-50</code>; numbers <code class="rounded bg-neutral-100 px-1 text-xs">tabular-nums text-right</code>.</p>
<div class="mt-4 overflow-hidden rounded-lg border border-neutral-200 bg-white">
<table class="w-full text-sm">
<thead class="border-b border-neutral-200 bg-neutral-50 text-left text-xs font-semibold uppercase tracking-wider text-neutral-400">
<tr><th class="px-5 py-3">PO Number</th><th class="px-5 py-3">Vessel</th><th class="px-5 py-3">Status</th><th class="px-5 py-3 text-right">Amount</th></tr>
</thead>
<tbody class="divide-y divide-neutral-100">
<tr class="hover:bg-neutral-50"><td class="px-5 py-3 mono text-xs">PMS/HNR1/9001/2025-26</td><td class="px-5 py-3">MV Pelagia Star</td><td class="px-5 py-3"><span class="rounded-full bg-success-100 px-2.5 py-0.5 text-xs font-medium text-success-700">Approved</span></td><td class="px-5 py-3 text-right tabular-nums">₹4,82,000</td></tr>
<tr class="hover:bg-neutral-50"><td class="px-5 py-3 mono text-xs">PMS/OCD2/9002/2025-26</td><td class="px-5 py-3">MV Ocean Dawn</td><td class="px-5 py-3"><span class="rounded-full bg-warning-100 px-2.5 py-0.5 text-xs font-medium text-warning-700">Edits Requested</span></td><td class="px-5 py-3 text-right tabular-nums">₹1,15,500</td></tr>
<tr class="hover:bg-neutral-50"><td class="px-5 py-3 mono text-xs">PMS/CRT3/9003/2025-26</td><td class="px-5 py-3">MV Coral Trident</td><td class="px-5 py-3"><span class="rounded-full bg-neutral-100 px-2.5 py-0.5 text-xs font-medium text-neutral-700">Closed</span></td><td class="px-5 py-3 text-right tabular-nums">₹92,300</td></tr>
</tbody>
</table>
</div>
</section>
<!-- ALERTS / DIALOG -->
<section id="alerts">
<h2 class="text-lg font-semibold">Alerts &amp; dialog</h2>
<p class="mt-1 text-sm text-neutral-600">Inline callouts use the semantic <b>-50</b> tint + <b>-700</b> text + matching border.</p>
<div class="mt-4 space-y-3">
<div class="flex items-start gap-3 rounded-lg border border-primary-200 bg-primary-50 p-4 text-sm text-primary-800"><span class="font-medium"> Info</span><span>Imported POs are created directly in the Closed state.</span></div>
<div class="flex items-start gap-3 rounded-lg border border-success-100 bg-success-50 p-4 text-sm text-success-700"><span class="font-medium">✓ Success</span><span>Purchase order approved and sent for payment.</span></div>
<div class="flex items-start gap-3 rounded-lg border border-warning-100 bg-warning-50 p-4 text-sm text-warning-700"><span class="font-medium">⚠ Warning</span><span>This vendor is unverified — verify before assigning a vendor code.</span></div>
<div class="flex items-start gap-3 rounded-lg border border-danger-100 bg-danger-50 p-4 text-sm text-danger-700"><span class="font-medium">✕ Error</span><span>Payment date cannot be in the future.</span></div>
</div>
<div class="mt-4">
<p class="mb-2 text-sm font-medium text-neutral-700">Dialog</p>
<div class="relative overflow-hidden rounded-lg border border-neutral-200 bg-neutral-100 p-8">
<div class="mx-auto max-w-sm rounded-lg border border-neutral-200 bg-white p-6 shadow-lg">
<h3 class="text-base font-semibold text-neutral-900">Delete accounting code?</h3>
<p class="mt-1 text-sm text-neutral-500">This removes <b>5110 · Fuel &amp; Lubricants</b>. This action can't be undone.</p>
<div class="mt-5 flex justify-end gap-2">
<button class="inline-flex h-10 items-center rounded-lg border border-neutral-300 bg-white px-4 text-sm font-medium text-neutral-700 hover:bg-neutral-50">Cancel</button>
<button class="inline-flex h-10 items-center rounded-lg bg-danger px-4 text-sm font-medium text-white hover:opacity-90">Delete</button>
</div>
</div>
</div>
</div>
</section>
<!-- CHARTS -->
<section id="charts">
<h2 class="text-lg font-semibold">Charts</h2>
<p class="mt-1 max-w-2xl text-sm text-neutral-600"><b>recharts</b> inside a standard card. Grid <code class="rounded bg-neutral-100 px-1 text-xs">strokeDasharray="3 3"</code> in <code class="rounded bg-neutral-100 px-1 text-xs">#f0f0f0</code>; axis ticks <code class="rounded bg-neutral-100 px-1 text-xs">fontSize 11, #737373</code>; bars <code class="rounded bg-neutral-100 px-1 text-xs">radius</code>, lines <code class="rounded bg-neutral-100 px-1 text-xs">strokeWidth 2</code>. Y-axis money formatted via <code class="rounded bg-neutral-100 px-1 text-xs">formatCompactINR</code>.</p>
<div class="mt-4 grid gap-4 lg:grid-cols-2">
<div class="rounded-lg border border-neutral-200 bg-white p-5">
<p class="mb-4 text-sm font-semibold">Spend by cost centre</p>
<svg viewBox="0 0 320 170" class="w-full"><line x1="34" y1="10" x2="34" y2="140" stroke="#e5e5e5"/><line x1="34" y1="140" x2="320" y2="140" stroke="#e5e5e5"/>
<g><rect x="50" y="40" width="34" height="100" rx="3" fill="#2563eb"/><rect x="104" y="64" width="34" height="76" rx="3" fill="#2563eb"/><rect x="158" y="80" width="34" height="60" rx="3" fill="#2563eb"/><rect x="212" y="98" width="34" height="42" rx="3" fill="#2563eb"/><rect x="266" y="112" width="34" height="28" rx="3" fill="#2563eb"/></g>
<g font-size="9" fill="#737373"><text x="0" y="44">₹3Cr</text><text x="0" y="92">₹1.5Cr</text><text x="6" y="140">₹0</text></g>
</svg>
</div>
<div class="rounded-lg border border-neutral-200 bg-white p-5">
<p class="mb-4 text-sm font-semibold">Monthly trend</p>
<svg viewBox="0 0 320 170" class="w-full"><line x1="34" y1="10" x2="34" y2="140" stroke="#e5e5e5"/><line x1="34" y1="140" x2="320" y2="140" stroke="#e5e5e5"/>
<polyline fill="none" stroke="#2563eb" stroke-width="2" points="46,70 92,52 138,96 184,60 230,108 276,46 308,72"/>
<polyline fill="none" stroke="#16a34a" stroke-width="2" points="46,110 92,100 138,118 184,88 230,124 276,96 308,104"/>
<g fill="#2563eb"><circle cx="92" cy="52" r="2.5"/><circle cx="276" cy="46" r="2.5"/></g>
</svg>
</div>
</div>
<div class="mt-3 rounded-lg border border-neutral-200 bg-white p-5">
<p class="mb-3 text-sm font-semibold">Multi-series palette</p>
<div class="flex flex-wrap gap-2" id="chartpalette"></div>
</div>
</section>
<!-- FORMATTING -->
<section id="format">
<h2 class="text-lg font-semibold">Formatting conventions</h2>
<div class="mt-4 overflow-hidden rounded-lg border border-neutral-200 bg-white text-sm">
<table class="w-full">
<tbody class="divide-y divide-neutral-100">
<tr><td class="w-1/3 px-5 py-3 font-medium text-neutral-700">Currency</td><td class="px-5 py-3 text-neutral-600">Indian locale, INR — <code class="mono text-xs">formatCurrency()</code> → ₹4,82,000</td></tr>
<tr><td class="px-5 py-3 font-medium text-neutral-700">Compact money</td><td class="px-5 py-3 text-neutral-600"><code class="mono text-xs">formatCompactINR()</code> → ₹2 Cr · ₹49 L · ₹75 K (lakh/crore scale)</td></tr>
<tr><td class="px-5 py-3 font-medium text-neutral-700">Dates</td><td class="px-5 py-3 text-neutral-600"><code class="mono text-xs">formatDate()</code> → Jun 22, 2026 · financial year is AprMar (<code class="mono text-xs">2025-26</code>)</td></tr>
<tr><td class="px-5 py-3 font-medium text-neutral-700">PO numbers</td><td class="px-5 py-3 text-neutral-600">Mono font, <code class="mono text-xs">COMPANY/VESSEL/ID/FY</code> → PMS/HNR1/9000/2024-25</td></tr>
<tr><td class="px-5 py-3 font-medium text-neutral-700">Accounting codes</td><td class="px-5 py-3 text-neutral-600">6-digit mono codes; graphs label headings/sub-headings by <b>name</b>, leaves by <b>code</b></td></tr>
</tbody>
</table>
</div>
</section>
<!-- DO / DON'T -->
<section id="voice" class="pb-12">
<h2 class="text-lg font-semibold">Do &amp; don't</h2>
<div class="mt-4 grid gap-4 md:grid-cols-2">
<div class="rounded-lg border border-success-100 bg-success-50 p-5">
<p class="mb-2 text-sm font-semibold text-success-700">Do</p>
<ul class="space-y-1.5 text-sm text-neutral-700">
<li>• Separate surfaces with a 1px <code class="rounded bg-white px-1 text-xs">border-neutral-200</code>, not heavy shadows.</li>
<li>• Reuse <code class="rounded bg-white px-1 text-xs">PO_STATUS_VARIANTS</code> for any PO status pill.</li>
<li>• Keep one primary action per view; everything else secondary/ghost.</li>
<li>• Right-align and <code class="rounded bg-white px-1 text-xs">tabular-nums</code> all money columns.</li>
<li>• Use semantic color only for meaning (success=paid, warning=action, danger=stop).</li>
</ul>
</div>
<div class="rounded-lg border border-danger-100 bg-danger-50 p-5">
<p class="mb-2 text-sm font-semibold text-danger-700">Don't</p>
<ul class="space-y-1.5 text-sm text-neutral-700">
<li>• Don't introduce new hues — stay within the five ramps.</li>
<li>• Don't use primary blue for decoration; it signals an action.</li>
<li>• Don't mix radii — <code class="rounded bg-white px-1 text-xs">rounded-lg</code> for boxes, <code class="rounded bg-white px-1 text-xs">rounded-full</code> for pills.</li>
<li>• Don't crowd charts — one chart per card, generous whitespace.</li>
<li>• Don't hardcode ₹ formatting — use the shared helpers.</li>
</ul>
</div>
</div>
</section>
</main>
</div>
<script>
/* ── data-driven sections ── */
const RAMPS = [
["Primary","primary",[["50","#eff6ff"],["100","#dbeafe"],["200","#bfdbfe"],["500","#3b82f6"],["600","#2563eb"],["700","#1d4ed8"],["800","#1e40af"]],"600"],
["Success","success",[["50","#f0fdf4"],["100","#dcfce7"],["DEFAULT","#16a34a"],["700","#15803d"]],"DEFAULT"],
["Warning","warning",[["50","#fffbeb"],["100","#fef3c7"],["DEFAULT","#d97706"],["700","#b45309"]],"DEFAULT"],
["Danger","danger",[["50","#fef2f2"],["100","#fee2e2"],["DEFAULT","#dc2626"],["700","#b91c1c"]],"DEFAULT"],
["Neutral","neutral",[["50","#fafafa"],["100","#f5f5f5"],["200","#e5e5e5"],["300","#d4d4d4"],["400","#a3a3a3"],["500","#737373"],["600","#525252"],["700","#404040"],["800","#262626"],["900","#171717"]],"900"],
];
document.getElementById("ramps").innerHTML = RAMPS.map(([name,key,stops])=>`
<div>
<div class="mb-1.5 flex items-baseline gap-2"><span class="text-sm font-semibold">${name}</span><code class="text-xs text-neutral-400">--color-${key}-*</code></div>
<div class="grid grid-cols-4 gap-2 sm:grid-cols-7 lg:grid-cols-10">
${stops.map(([s,hex])=>{
const dark = ["600","700","800","900","DEFAULT"].includes(s) && !(key==="neutral"&&["50","100","200","300","400"].includes(s));
const cls = s==="DEFAULT"? key : `${key}-${s}`;
return `<div class="overflow-hidden rounded-lg border border-neutral-200">
<div class="h-12" style="background:${hex}"></div>
<div class="bg-white px-1.5 py-1"><p class="text-[11px] font-medium">${s}</p><p class="mono text-[10px] text-neutral-400">${hex}</p><p class="mono text-[9px] text-neutral-400">${cls}</p></div>
</div>`;}).join("")}
</div>
</div>`).join("");
/* lucide-style icon set (inline svg paths, stroke 2) */
const ICONS = {
dashboard:'<rect x="3" y="3" width="7" height="9"/><rect x="14" y="3" width="7" height="5"/><rect x="14" y="12" width="7" height="9"/><rect x="3" y="16" width="7" height="5"/>',
file:'<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/>',
plus:'<line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/>',
check:'<polyline points="20 6 9 17 4 12"/>',
ship:'<path d="M12 22V8"/><path d="M5 12H2a10 10 0 0 0 20 0h-3"/><circle cx="12" cy="5" r="3"/>',
users:'<path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/>',
card:'<rect x="1" y="4" width="22" height="16" rx="2"/><line x1="1" y1="10" x2="23" y2="10"/>',
download:'<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/>',
search:'<circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/>',
bell:'<path d="M18 8a6 6 0 0 0-12 0c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 0 1-3.46 0"/>',
chart:'<path d="M3 3v18h18"/><rect x="7" y="9" width="3" height="9"/><rect x="14" y="5" width="3" height="13"/>',
settings:'<circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/>',
};
document.getElementById("iconrow").innerHTML = Object.entries(ICONS).map(([n,p])=>`
<div class="flex flex-col items-center gap-1 w-16">
<svg class="h-5 w-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">${p}</svg>
<span class="text-[10px] text-neutral-400">${n}</span>
</div>`).join("");
/* PO status mapping (from lib/utils.ts) */
const VARIANT_CLASS = {
default:"bg-primary-100 text-primary-700", secondary:"bg-neutral-100 text-neutral-700",
success:"bg-success-100 text-success-700", warning:"bg-warning-100 text-warning-700",
danger:"bg-danger-100 text-danger-700", outline:"border border-neutral-300 text-neutral-600",
};
const PO_STATUS = [
["DRAFT","Draft","outline"],["SUBMITTED","Submitted","secondary"],["MGR_REVIEW","Under Review","secondary"],
["VENDOR_ID_PENDING","Vendor ID Pending","warning"],["EDITS_REQUESTED","Edits Requested","warning"],
["REJECTED","Rejected","danger"],["MGR_APPROVED","Approved","success"],["SENT_FOR_PAYMENT","Sent for Payment","default"],
["PARTIALLY_PAID","Partially Paid","warning"],["PAID_DELIVERED","Paid","success"],
["PARTIALLY_CLOSED","Partially Received","warning"],["CLOSED","Closed","secondary"],["CANCELLED","Cancelled","danger"],
];
document.getElementById("statusgrid").innerHTML = PO_STATUS.map(([k,label,v])=>`
<div class="flex items-center justify-between gap-2 rounded-md px-2 py-1.5">
<span class="rounded-full px-2.5 py-0.5 text-xs font-medium ${VARIANT_CLASS[v]}">${label}</span>
<code class="text-[10px] text-neutral-400">${k}</code>
</div>`).join("");
/* chart palette */
const CHART_COLORS=["#2563eb","#16a34a","#9333ea","#ea580c","#0891b2","#dc2626","#ca8a04","#4f46e5"];
document.getElementById("chartpalette").innerHTML = CHART_COLORS.map((c,i)=>`
<div class="flex items-center gap-1.5 rounded-md border border-neutral-200 px-2 py-1"><span class="h-3.5 w-3.5 rounded" style="background:${c}"></span><code class="text-[10px] text-neutral-500">${c}</code></div>`).join("");
/* TOC scroll-spy */
const links=[...document.querySelectorAll('.toc a')];
const map=Object.fromEntries(links.map(a=>[a.getAttribute('href').slice(1),a]));
const io=new IntersectionObserver(es=>{es.forEach(e=>{ if(e.isIntersecting){ links.forEach(l=>l.classList.remove('active')); map[e.target.id]?.classList.add('active'); }});},{rootMargin:'-80px 0px -70% 0px'});
document.querySelectorAll('main section[id]').forEach(s=>io.observe(s));
/* click-to-copy snippets */
document.querySelectorAll('.snip code').forEach(c=>{
c.addEventListener('click',()=>{ navigator.clipboard?.writeText(c.innerText); const w=c.closest('.snip'); w.classList.add('show'); setTimeout(()=>w.classList.remove('show'),1200); });
});
</script>
</body>
</html>