// tokens.jsx — design tokens for Team Task Hub // Newverse brand: deep space, vivid purple, subtle starfield const TH_FONT = '"IBM Plex Sans Thai", "IBM Plex Sans Thai Looped", -apple-system, system-ui, sans-serif'; const NUM_FONT = '"IBM Plex Sans", "Inter", -apple-system, system-ui, sans-serif'; const MONO_FONT = '"JetBrains Mono", "IBM Plex Mono", ui-monospace, monospace'; // All values resolve to CSS custom properties defined in index.html // (:root = dark · :root[data-theme="light"] = light). Switching the // attribute re-themes the entire app live. const COLORS = { // surfaces — deep space bg: 'var(--th-bg)', bgElev: 'var(--th-bg-elev)', bgGrad: 'var(--th-bg-grad)', card: 'var(--th-card)', cardElev: 'var(--th-card-elev)', cardSoft: 'var(--th-card-soft)', // borders hairline: 'var(--th-hairline)', hairlineStr: 'var(--th-hairline-str)', hairlineSoft:'var(--th-hairline-soft)', // text ink: 'var(--th-ink)', inkBright: 'var(--th-ink-bright)', inkMuted: 'var(--th-ink-muted)', inkSubtle: 'var(--th-ink-subtle)', inkFaint: 'var(--th-ink-faint)', // brand accent accent: 'var(--th-accent)', accentBright:'var(--th-accent-bright)', accentSoft: 'var(--th-accent-soft)', accentEdge: 'var(--th-accent-edge)', accentGlow: 'var(--th-accent-glow)', }; // Status — bg as tinted overlays so they sit well on dark cards // palette helpers (reuse 6 semantic colors across the full 22-status vocab) const _S = { gray: { bg: 'var(--th-st-gray-bg)', fg: 'var(--th-st-gray-fg)', dot: 'var(--th-st-gray-dot)' }, blue: { bg: 'var(--th-st-blue-bg)', fg: 'var(--th-st-blue-fg)', dot: 'var(--th-st-blue-dot)' }, amber: { bg: 'var(--th-st-amber-bg)', fg: 'var(--th-st-amber-fg)', dot: 'var(--th-st-amber-dot)' }, orange:{ bg: 'var(--th-st-orange-bg)', fg: 'var(--th-st-orange-fg)', dot: 'var(--th-st-orange-dot)' }, green: { bg: 'var(--th-st-green-bg)', fg: 'var(--th-st-green-fg)', dot: 'var(--th-st-green-dot)' }, red: { bg: 'var(--th-st-red-bg)', fg: 'var(--th-st-red-fg)', dot: 'var(--th-st-red-dot)' }, }; const STATUS = { // neutral / waiting idea: { ..._S.gray, label: 'ไอเดีย' }, not_started: { ..._S.gray, label: 'ยังไม่เริ่ม' }, pending: { ..._S.gray, label: 'รอคิว' }, received: { ..._S.blue, label: 'รับงานแล้ว' }, brief_received:{ ..._S.blue, label: 'รับบรีฟแล้ว' }, // active / in-progress progress: { ..._S.blue, label: 'กำลังทำ' }, in_progress: { ..._S.blue, label: 'กำลังทำ' }, editing: { ..._S.blue, label: 'กำลังตัดต่อ' }, filming: { ..._S.blue, label: 'กำลังถ่าย' }, shoot: { ..._S.blue, label: 'ถ่ายทำ' }, testing: { ..._S.blue, label: 'กำลังทดสอบ' }, // review / revision submitted: { ..._S.amber, label: 'ส่งแล้ว' }, review: { ..._S.orange,label: 'รอรีวิว' }, revision: { ..._S.orange,label: 'แก้ไข' }, // handoff: อนุมัติแล้ว รอคนลงเพจ (คุกกี้) to_publish: { ..._S.amber, label: 'รอลงเพจ' }, // done / shipped approved: { ..._S.green, label: 'อนุมัติ' }, done: { ..._S.green, label: 'เสร็จ' }, deployed: { ..._S.green, label: 'ดีพลอยแล้ว' }, published: { ..._S.green, label: 'เผยแพร่แล้ว' }, // problem returned: { ..._S.red, label: 'ตีกลับ' }, blocked: { ..._S.red, label: 'ติดปัญหา' }, cancelled: { ..._S.gray, label: 'ยกเลิก' }, }; // Pipeline — bright enough to read on dark; bot uses brand purple const PIPELINES = { bot: { color: 'var(--th-pl-bot)', soft: 'var(--th-pl-bot-soft)', label: 'Bot Dev', short: 'Bot' }, long: { color: 'var(--th-pl-long)', soft: 'var(--th-pl-long-soft)', label: 'Long Video', short: 'Long' }, short: { color: 'var(--th-pl-short)', soft: 'var(--th-pl-short-soft)', label: 'Short / IG', short: 'Short' }, graphic: { color: 'var(--th-pl-graphic)', soft: 'var(--th-pl-graphic-soft)', label: 'Graphic', short: 'Graphic' }, video: { color: 'var(--th-pl-video)', soft: 'var(--th-pl-video-soft)', label: 'Video General', short: 'Video' }, page: { color: 'var(--th-pl-page)', soft: 'var(--th-pl-page-soft)', label: 'Page Content', short: 'Page' }, review: { color: 'var(--th-pl-review)', soft: 'var(--th-pl-review-soft)', label: 'Head Review', short: 'Review' }, ops: { color: 'var(--th-pl-ops)', soft: 'var(--th-pl-ops-soft)', label: 'Ops / ทีม', short: 'Ops' }, strategy:{ color: 'var(--th-pl-strategy)', soft: 'var(--th-pl-strategy-soft)', label: 'Strategy', short: 'Strat' }, }; const PRIORITY = { P0: { color: 'var(--th-pri-p0)', bg: 'var(--th-pri-p0-bg)', label: 'P0' }, P1: { color: 'var(--th-pri-p1)', bg: 'var(--th-pri-p1-bg)', label: 'P1' }, P2: { color: 'var(--th-pri-p2)', bg: 'var(--th-pri-p2-bg)', label: 'P2' }, P3: { color: 'var(--th-pri-p3)', bg: 'var(--th-pri-p3-bg)', label: 'P3' }, }; // Long Video has 7 stages — the most complex pipeline const LONG_STAGES = [ { id: 'idea', label: 'ไอเดีย' }, { id: 'script', label: 'สคริปต์' }, { id: 'shoot', label: 'ถ่ายทำ' }, { id: 'edit', label: 'ตัดต่อ' }, { id: 'gfx', label: 'กราฟิก' }, { id: 'review', label: 'รีวิว' }, { id: 'publish', label: 'เผยแพร่' }, ]; // ---- theme switch helper (dark <-> light) · persists to localStorage ---- function getTheme(){ return document.documentElement.dataset.theme === 'light' ? 'light' : 'dark'; } function setTheme(t){ const v = t === 'light' ? 'light' : 'dark'; document.documentElement.dataset.theme = v; try{ localStorage.setItem('th_theme', v); }catch(e){} return v; } function toggleTheme(){ return setTheme(getTheme() === 'light' ? 'dark' : 'light'); } Object.assign(window, { TH_FONT, NUM_FONT, MONO_FONT, COLORS, STATUS, PIPELINES, PRIORITY, LONG_STAGES, getTheme, setTheme, toggleTheme, });