Scaffold CommiTea: yarn workspaces, Electron shell, core label schema, design system
- apps/desktop: electron-vite + React + Tailwind mapped onto design tokens (preflight off; tokens/base.css owns the reset); boots to a Reginald placeholder proving fonts/tokens/core wiring - packages/core: pure TS; gitea label schema (est/*, p/*, deadline/hard) with pessimistic conflict resolution + 15 unit tests - docs/design: full design handoff (tokens, 16 component contracts, interactive 14-screen prototype, Reginald voice rules) - docs/PLAN.md: product plan (purity rule, pm-state repo, deterministic scheduler + Monte Carlo, directive log) - Deliberate deviation from novelpad stack: no ElectricSQL/PGlite — local store is a rebuildable cache over gitea REST/webhooks (better-sqlite3 in main process, arriving in P1) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
37
docs/design/tokens/base.css
Normal file
37
docs/design/tokens/base.css
Normal file
@@ -0,0 +1,37 @@
|
||||
/* CommiTea base element styles. */
|
||||
|
||||
* { box-sizing: border-box; }
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font: var(--text-body);
|
||||
color: var(--text-body);
|
||||
background: var(--surface-app);
|
||||
-webkit-font-smoothing: antialiased;
|
||||
text-rendering: optimizeLegibility;
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--accent-text);
|
||||
text-decoration: none;
|
||||
border-bottom: 1px solid var(--line-2);
|
||||
transition: border-color var(--duration-fast) var(--ease-out);
|
||||
}
|
||||
a:hover {
|
||||
color: var(--accent-hover);
|
||||
border-bottom-color: var(--jade);
|
||||
}
|
||||
|
||||
::selection {
|
||||
background: var(--spruce-2);
|
||||
color: var(--ink-1);
|
||||
}
|
||||
|
||||
code, kbd {
|
||||
font: var(--text-data);
|
||||
}
|
||||
|
||||
:focus-visible {
|
||||
outline: 2px solid var(--focus-ring);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
137
docs/design/tokens/colors.css
Normal file
137
docs/design/tokens/colors.css
Normal file
@@ -0,0 +1,137 @@
|
||||
/* CommiTea color system — "Green tea service"
|
||||
Cool porcelain surfaces, slate-green ink, jade accent (from the cup itself).
|
||||
Light is default (morning service). Dark scope: [data-theme="dark"] (evening service). */
|
||||
|
||||
:root {
|
||||
/* ---- base: porcelain (cool green-white surfaces) ---- */
|
||||
--paper-0: #F0F4F0; /* app background */
|
||||
--paper-1: #FAFCF9; /* raised card */
|
||||
--paper-2: #E4EBE4; /* inset wells, rails */
|
||||
--paper-3: #D7E1D8; /* pressed / deep inset */
|
||||
|
||||
/* ---- base: ink (slate-green text scale) ---- */
|
||||
--ink-1: #1D2522; /* primary text */
|
||||
--ink-2: #51605A; /* secondary text */
|
||||
--ink-3: #84928B; /* muted / placeholder */
|
||||
--ink-inverse: #EFF5F0;
|
||||
|
||||
/* ---- base: lines ---- */
|
||||
--line-1: #D7DFD7; /* hairline */
|
||||
--line-2: #BACBBE; /* strong rule */
|
||||
|
||||
/* ---- base: spruce (brand green — the logo's slate-teal) ---- */
|
||||
--spruce-9: #16322A;
|
||||
--spruce-8: #1D4238;
|
||||
--spruce-7: #275546; /* brand anchor */
|
||||
--spruce-6: #3A7260;
|
||||
--spruce-5: #57937C;
|
||||
--spruce-3: #A3CFBB;
|
||||
--spruce-2: #CDE5D7;
|
||||
--spruce-1: #E3F0E8;
|
||||
|
||||
/* ---- base: jade (mint accent — the tea itself) ---- */
|
||||
--jade-7: #2E7A57;
|
||||
--jade-6: #46996F;
|
||||
--jade-5: #66B389;
|
||||
--jade-3: #A8DDBE;
|
||||
--jade-1: #E0F4E7;
|
||||
|
||||
/* ---- semantic: surfaces & text ---- */
|
||||
--surface-app: var(--paper-0);
|
||||
--surface-card: var(--paper-1);
|
||||
--surface-inset: var(--paper-2);
|
||||
--surface-raised: var(--paper-1);
|
||||
--text-body: var(--ink-1);
|
||||
--text-secondary: var(--ink-2);
|
||||
--text-muted: var(--ink-3);
|
||||
--text-on-accent: var(--ink-inverse);
|
||||
--border-hairline: var(--line-1);
|
||||
--border-strong: var(--line-2);
|
||||
|
||||
/* ---- semantic: interactive ---- */
|
||||
--accent: var(--spruce-7);
|
||||
--accent-hover: #1F4A3C;
|
||||
--accent-pressed: #173B30;
|
||||
--accent-tint: var(--spruce-1);
|
||||
--accent-text: var(--spruce-7);
|
||||
--jade: var(--jade-6);
|
||||
--jade-tint: var(--jade-1);
|
||||
--focus-ring: #57937C;
|
||||
|
||||
/* ---- semantic: status ---- */
|
||||
--ok: #2F7D53;
|
||||
--ok-tint: #DFEEE3;
|
||||
--warn: #96772A;
|
||||
--warn-tint: #EFE9D2;
|
||||
--danger: #A84632;
|
||||
--danger-tint: #F2E0DA;
|
||||
--info: #43758F;
|
||||
--info-tint: #DFE9EC;
|
||||
|
||||
/* ---- domain: label chips (gitea label sets) ---- */
|
||||
--label-est-bg: var(--paper-2);
|
||||
--label-est-text: var(--ink-2);
|
||||
--label-p1: #A84632;
|
||||
--label-p2: #96772A;
|
||||
--label-p3: #43758F;
|
||||
--label-p4: #84928B;
|
||||
--label-hard: #A84632;
|
||||
|
||||
/* ---- domain: forecast ---- */
|
||||
--cone-fill: rgba(102, 179, 137, 0.18);
|
||||
--cone-line: #46996F;
|
||||
--cone-actual: var(--ink-1);
|
||||
}
|
||||
|
||||
[data-theme="dark"] {
|
||||
/* evening service */
|
||||
--paper-0: #121C18;
|
||||
--paper-1: #182420;
|
||||
--paper-2: #1F2E28;
|
||||
--paper-3: #283A32;
|
||||
|
||||
--ink-1: #E4EEE7;
|
||||
--ink-2: #9FB2A8;
|
||||
--ink-3: #66796F;
|
||||
--ink-inverse: #EFF5F0;
|
||||
|
||||
--line-1: #263630;
|
||||
--line-2: #35493F;
|
||||
|
||||
--spruce-1: #1E332B;
|
||||
--spruce-2: #27443A;
|
||||
--spruce-3: #3A6353;
|
||||
|
||||
--jade-1: #1F3A2E;
|
||||
--jade-3: #35624A;
|
||||
|
||||
--accent: #3A7260;
|
||||
--accent-hover: #448069;
|
||||
--accent-pressed: #315F51;
|
||||
--accent-tint: #1E332B;
|
||||
--accent-text: #8CC7AC;
|
||||
--jade: #6FC694;
|
||||
--jade-tint: #1F3A2E;
|
||||
--focus-ring: #57937C;
|
||||
|
||||
--ok: #74B992;
|
||||
--ok-tint: #1F3529;
|
||||
--warn: #C0A45B;
|
||||
--warn-tint: #33301F;
|
||||
--danger: #C77B62;
|
||||
--danger-tint: #392823;
|
||||
--info: #7FA6BC;
|
||||
--info-tint: #223038;
|
||||
|
||||
--label-est-bg: var(--paper-3);
|
||||
--label-est-text: var(--ink-2);
|
||||
--label-p1: #C77B62;
|
||||
--label-p2: #C0A45B;
|
||||
--label-p3: #7FA6BC;
|
||||
--label-p4: #66796F;
|
||||
--label-hard: #C77B62;
|
||||
|
||||
--cone-fill: rgba(111, 198, 148, 0.14);
|
||||
--cone-line: #6FC694;
|
||||
--cone-actual: #E4EEE7;
|
||||
}
|
||||
65
docs/design/tokens/fonts.css
Normal file
65
docs/design/tokens/fonts.css
Normal file
@@ -0,0 +1,65 @@
|
||||
/* CommiTea webfonts — self-hosted, latin subsets */
|
||||
|
||||
@font-face {
|
||||
font-family: 'Libre Caslon Display';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(../assets/fonts/caslon-display-normal-400.woff2) format('woff2');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Libre Caslon Text';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(../assets/fonts/caslon-text-normal-400.woff2) format('woff2');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Libre Caslon Text';
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(../assets/fonts/caslon-text-italic-400.woff2) format('woff2');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Libre Caslon Text';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url(../assets/fonts/caslon-text-normal-700.woff2) format('woff2');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Instrument Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400 700;
|
||||
font-display: swap;
|
||||
src: url(../assets/fonts/instrument-sans-normal-400-700.woff2) format('woff2');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Instrument Sans';
|
||||
font-style: italic;
|
||||
font-weight: 400 700;
|
||||
font-display: swap;
|
||||
src: url(../assets/fonts/instrument-sans-italic-400-700.woff2) format('woff2');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'IBM Plex Mono';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(../assets/fonts/plex-mono-normal-400.woff2) format('woff2');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'IBM Plex Mono';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url(../assets/fonts/plex-mono-normal-500.woff2) format('woff2');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'IBM Plex Mono';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(../assets/fonts/plex-mono-normal-600.woff2) format('woff2');
|
||||
}
|
||||
44
docs/design/tokens/spacing.css
Normal file
44
docs/design/tokens/spacing.css
Normal file
@@ -0,0 +1,44 @@
|
||||
/* CommiTea spacing, radius, shadow, border & motion tokens. */
|
||||
|
||||
:root {
|
||||
/* spacing — 4px base */
|
||||
--space-1: 4px;
|
||||
--space-2: 8px;
|
||||
--space-3: 12px;
|
||||
--space-4: 16px;
|
||||
--space-5: 20px;
|
||||
--space-6: 24px;
|
||||
--space-7: 32px;
|
||||
--space-8: 40px;
|
||||
--space-9: 48px;
|
||||
--space-10: 64px;
|
||||
|
||||
/* radii — crisp, not bubbly */
|
||||
--radius-1: 4px; /* chips, inputs' inner elements */
|
||||
--radius-2: 6px; /* buttons, inputs */
|
||||
--radius-3: 10px; /* cards, dialogs */
|
||||
--radius-round: 999px;
|
||||
|
||||
/* borders */
|
||||
--border-w: 1px;
|
||||
--rule-double: 3px double var(--border-strong); /* fine-stationery section rule */
|
||||
|
||||
/* shadows — cool, restrained */
|
||||
--shadow-1: 0 1px 2px rgba(20, 34, 28, 0.06);
|
||||
--shadow-2: 0 2px 8px rgba(20, 34, 28, 0.08), 0 1px 2px rgba(20, 34, 28, 0.05);
|
||||
--shadow-3: 0 12px 32px rgba(20, 34, 28, 0.14), 0 2px 8px rgba(20, 34, 28, 0.07);
|
||||
--shadow-jade-line: inset 0 2px 0 var(--jade); /* jade top rule on key cards */
|
||||
|
||||
/* motion — settled, never bouncy */
|
||||
--ease-out: cubic-bezier(0.25, 0.6, 0.3, 1); /* @kind other */
|
||||
--ease-in-out: cubic-bezier(0.6, 0, 0.3, 1); /* @kind other */
|
||||
--duration-fast: 120ms; /* @kind other */
|
||||
--duration-base: 200ms; /* @kind other */
|
||||
--duration-slow: 320ms; /* @kind other */
|
||||
}
|
||||
|
||||
[data-theme="dark"] {
|
||||
--shadow-1: 0 1px 2px rgba(0, 0, 0, 0.25);
|
||||
--shadow-2: 0 2px 8px rgba(0, 0, 0, 0.3), 0 1px 2px rgba(0, 0, 0, 0.2);
|
||||
--shadow-3: 0 12px 32px rgba(0, 0, 0, 0.45), 0 2px 8px rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
34
docs/design/tokens/typography.css
Normal file
34
docs/design/tokens/typography.css
Normal file
@@ -0,0 +1,34 @@
|
||||
/* CommiTea typography tokens.
|
||||
Voices: Display serif (headlines, big numerals) · Reginald's voice (Caslon Text, upright)
|
||||
· Body sans (UI) · Mono (data: labels, estimates, dates, ids). */
|
||||
|
||||
:root {
|
||||
--font-serif-display: 'Libre Caslon Display', 'Libre Caslon Text', Georgia, serif;
|
||||
--font-serif-text: 'Libre Caslon Text', Georgia, serif;
|
||||
--font-sans: 'Instrument Sans', -apple-system, 'Segoe UI', sans-serif;
|
||||
--font-mono: 'IBM Plex Mono', ui-monospace, 'SF Mono', monospace;
|
||||
|
||||
/* type scale */
|
||||
--text-hero: 400 48px/1.08 var(--font-serif-display); /* big forecast numerals */
|
||||
--text-display: 400 34px/1.15 var(--font-serif-display); /* page titles */
|
||||
--text-title: 400 24px/1.2 var(--font-serif-display); /* card titles */
|
||||
--text-agent: 400 16px/1.55 var(--font-serif-text); /* Reginald speaks — serif, upright */
|
||||
--text-agent-lg: 400 20px/1.5 var(--font-serif-text);
|
||||
--text-body: 400 14px/1.5 var(--font-sans);
|
||||
--text-body-strong: 600 14px/1.5 var(--font-sans);
|
||||
--text-small: 400 13px/1.45 var(--font-sans);
|
||||
--text-caption: 400 12px/1.4 var(--font-sans);
|
||||
--text-data: 400 13px/1.4 var(--font-mono); /* dates, counts */
|
||||
--text-label: 500 11.5px/1 var(--font-mono); /* chips: est/2d, p/1 */
|
||||
--text-overline: 600 11px/1.2 var(--font-sans); /* + letter-spacing-wide */
|
||||
|
||||
/* tracking */
|
||||
--letter-spacing-wide: 0.08em; /* overlines, uppercase */
|
||||
--letter-spacing-label: 0.02em; /* mono chips */
|
||||
|
||||
/* weights (sans is variable 400–700) */
|
||||
--weight-regular: 400;
|
||||
--weight-medium: 500;
|
||||
--weight-semibold: 600;
|
||||
--weight-bold: 700;
|
||||
}
|
||||
Reference in New Issue
Block a user