diff --git a/src/assets/grain.svg b/src/assets/grain.svg new file mode 100644 index 0000000..01e1124 --- /dev/null +++ b/src/assets/grain.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/assets/waveform-mark.svg b/src/assets/waveform-mark.svg new file mode 100644 index 0000000..2d5eaa0 --- /dev/null +++ b/src/assets/waveform-mark.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/assets/wordmark.svg b/src/assets/wordmark.svg new file mode 100644 index 0000000..350d6c6 --- /dev/null +++ b/src/assets/wordmark.svg @@ -0,0 +1,5 @@ + + Kon + + THINK OUT LOUD + \ No newline at end of file diff --git a/src/design-system/README.md b/src/design-system/README.md new file mode 100644 index 0000000..eb735bd --- /dev/null +++ b/src/design-system/README.md @@ -0,0 +1,188 @@ +# Kon — Design System + +> **Think out loud.** A voice-first dictation app built for neurodivergent minds, by CORBEL. + +## What is Kon? + +Kon is a local-first dictation + thought-capture app. You press a hotkey, speak, and Kon transcribes, cleans, and — optionally — extracts tasks from what you said. Everything runs on your machine (Whisper / Parakeet models); nothing is sent anywhere. + +**Company:** CORBEL — an AI consultancy and technology integrator that removes friction from day-to-day life and work. + +**Product essence:** *Clarity without friction.* Every design decision is measured against it. If something adds cognitive load, it doesn't ship. + +**Archetypes:** Sage (primary) + Magician (secondary). Kon listens more than it speaks. + +**Visual reference points:** The Barbican, Muji, Amsterdam urban design, Nujabes album art — warm brutalism, honest materials, structural clarity. **Anti-references:** Notion-style feature density, generic blue/white SaaS, FAANG aesthetics. + +--- + +## Sources + +- **Repo:** `github.com/jakejars/kon` — Tauri + Svelte 5 + Tailwind v4 desktop app. Imported into `kon-source/` (lib components + routes). +- **Design brief:** Pasted in the initial message — complete token system, type scale, motion guidelines, ideology. +- **Key reads in `kon-source/`:** + - `app.css` — @theme tokens, global base, zone + motion system + - `lib/Sidebar.svelte` — navigation shell + - `lib/pages/DictationPage.svelte` — record / transcribe (the hero screen) + - `lib/pages/HistoryPage.svelte` — saved transcripts + - `lib/pages/TasksPage.svelte` — inbox / today / soon / later buckets + - `lib/pages/FilesPage.svelte` — audio file import + - `lib/components/Card.svelte`, `Titlebar.svelte`, `EmptyState.svelte`, `ZonePicker.svelte`, `Toggle.svelte`, `ToastViewport.svelte` + - `docs/icon-mapping.md` — Lucide migration audit + +--- + +## Index — what's in this folder + +| Path | What it is | +|---|---| +| `README.md` | This file. Start here. | +| `colors_and_type.css` | **The** stylesheet. CSS variables, semantic type classes, grain, zones. `@import` it. | +| `SKILL.md` | Agent-skill manifest (cross-compatible with Claude Code Agent Skills). | +| `assets/` | Logos, the sinhala wordmark glyph, grain texture, icon references | +| `preview/` | HTML spec cards shown in the Design System tab (swatches, specimens, components) | +| `ui_kits/kon-app/` | UI kit — pixel-level recreation of the Kon desktop app with interactive click-thru | +| `kon-source/` | Imported Svelte source — the ground truth for component structure | + +No slide template was attached, so `slides/` is not created. + +--- + +## Content Fundamentals + +> **Voice:** A calm friend who has already done the anxious part for you. + +**Person.** Addresses the user as *you*; never refers to itself as *I*. Brand name "Kon" appears sparingly — the product speaks, it doesn't narrate itself. *(Settings labels: "Save recordings", "British English" — never "I'll save your recordings".)* + +**Sentence shape.** Short. Direct. Rarely more than ~12 words per line of UI copy. Never exclaims. Never hypes. Full stops inside UI labels are dropped; in prose (empty states, toasts) they're used naturally. + +**Tone.** +- **Ambient, not demanding.** Empty states are *"Your words will appear here…"* — not *"Record your first transcript!"* Blank screens trigger freeze; Kon offers presence instead of prompting. +- **Calm on failure.** Failed transcription copy leads with *"Your audio is saved"* — the anxiety reducer, not the apology. Never red all-caps. +- **No guilt, no streaks.** No streak-shaming, no *"keep it up!"*, no urgency. +- **British English.** "Minimise", "finalising", "customise". `britishEnglish` is a first-class setting. + +**Casing.** +- Sentence case for all headings and buttons. *"Start recording"*, *"Clear all"*, *"Sensory zone"* — never *Start Recording* or *START RECORDING*. +- Eyebrow labels (10px, uppercase, 0.12em tracking) are the **only** place all-caps appears — e.g. *THINK OUT LOUD* under the sidebar wordmark. Never apply uppercase to sentences. +- Brand name is always `Kon` (capital K, one lowercase letter). +- Product tagline — *"Think out loud"* — always sentence case. + +**Buttons.** Verbs. *Record, Stop, Save, Copy, Clear, Export, Extract Tasks, Open viewer.* The one exception is *Tasks* (noun) as a sidebar toggle — consistent with its icon label. + +**Status language.** State-driven, non-anthropomorphic. `Ready`, `Recording…`, `Loading model…`, `Finalising…`, `Error`. Not *"I'm listening"*. + +**Microcopy examples (lifted from the codebase):** +- Empty: *"Press record or Ctrl+Shift+R"* · *"Your transcriptions will be saved here"* · *"No matching transcripts"* +- Saved feedback: *"Saved · 3 tasks extracted"* +- Error toast: *"Could not start recording"* + *"device disconnected"* body +- Settings helper: *"Auto mode skips monitor sources and validates by RMS energy."* + +**Emoji.** **Never.** Nothing in the codebase uses them. The one decorative character is the Sinhala letter ක (U+0D9A) next to the wordmark — a brand mark, not emoji. + +**Numbers + units.** Tabular figures for timers, durations, word counts. Units always lowercase, no abbreviations in prose: *"3 tasks extracted"*, *"12 words"*, *"Dropped 2s of older audio"*. + +--- + +## Visual Foundations + +### Palette — warm, not beige +Three-layer surface system: `--bg` (60%) → `--bg-elevated` (30%) → `--bg-card` — all neutrals carry a warm amber undertone for cohesion. Never `#000` on `#fff` (halation). Accent `#e8a87c` (amber/copper) is **always meaningful** — interactivity, recording state, or brand identity. Never decorative. Three semantic colors only: `--success` moss green, `--danger` muted red, `--warning` honey amber. 60-30-10 split: 60% surface, 30% elevated, 10% amber. + +### Sensory zones +Three environment modes — **Cave** (cool teal tint, focus), **Energy** (warm neutral, collaboration), **Reset** (muted sage, relaxation). Zones tint surfaces only; the amber accent never changes. Environment is the variable, brand is the constant. Zone transitions cross-fade 300–500ms (instant when reduce-motion is on). + +### Type — Lexend everywhere, italic serif only for identity +- **UI + body:** Lexend (variable 300–700). Designed for reading difficulties; high x-height, generous spacing. +- **Display / wordmark:** Instrument Serif Italic 400. **Only** the wordmark and page titles. Never body, never UI. +- **Mono:** JetBrains Mono — file paths, durations, kbd. +- **User-selectable alternatives:** Atkinson Hyperlegible, OpenDyslexic. +- 16px floor for all body. 1.5× line-height minimum. Left-aligned only. Max 75ch. Sentence case. Never italic for extended reading. Never more than 3 weights per screen. + +### Backgrounds +Flat warm surfaces, layered. **Grain texture** at 2.5% opacity dark / 1.5% light — a 200×200 noise tile, `pointer-events:none`, z-index 50, overlaid on the whole viewport. No gradients. No full-bleed photography. No hand-drawn illustrations. No repeating geometric patterns. The grain is the one and only texture. + +### Imagery — when present +Warm grain wash: shift toward amber, noise overlay 2–3%, slight vignette (10–15%). Subjects are textured surfaces (wood grain, concrete) and **hands only** (writing, holding things — never faces or screens). Late-afternoon light, low-to-medium contrast. No stock photography of smiling people. + +### Illustration +Abstract waveform / sound-ripple motifs in amber. 2px stroke. Flat colour with opacity variations — no gradients, no characters, no mascots. + +### Motion — elderflower, not espresso +- **Easing:** `cubic-bezier(0.2, 0.8, 0.2, 1)` (ease-out). +- **UI:** 150–200ms. **Decorative:** 300–500ms. **Zone transitions:** 300–500ms cross-fade. **Waveform:** 2s ease-in-out amplitude pulse, clamped. +- **Never:** bounce, screen shake, slide-from-offscreen, auto-play, attention-grabbing. +- **Reduce motion is the default** — opt IN to animation. + +### Hover + press states +- **Hover:** background shifts to `--hover` (a single step warmer than the underlying surface). Buttons: text colour step up (tertiary→secondary, secondary→text). Accent buttons: `--accent` → `--accent-hover` (slightly darker copper). +- **Press:** `active:scale-[0.93]` on circular actions (record button), `active:opacity-80` on standard buttons. No ripple. No pulse. +- **Active nav:** `--nav-active` background, text upgraded to primary, icon stroked 2.0 instead of 1.5, icon colour → amber. + +### Borders +Two weights only: `--border` (visible) and `--border-subtle` (barely-there divider). Always 1px. Accent border appears only for focus rings, active selection, or recording indicators. + +### Shadows +Low and warm. `shadow-sm` `0 1px 3px rgba(0,0,0,0.2)` for cards. `shadow-md` `0 4px 12px rgba(0,0,0,0.25)` for popovers. The **one signature shadow** is the accent glow on the record button at rest: `0 4px 20px rgba(232,168,124,0.3)`, plus the `pulse-warm` animation while recording. + +### Corners +`--radius-sm` 6px (kbd, pills) · `--radius-md` 8px (buttons, inputs) · `--radius-lg` 12px (cards internal) · `--radius-xl` 16px (primary containers) · `--radius-2xl` 20px (the big transcript card). Record button is fully circular. Toasts, chips, badges are fully rounded (`rounded-full`). + +### Cards +Card = `--bg-card` background + `--border-subtle` 1px + `rounded-2xl` + `shadow-sm`. No heavy drop shadows. No coloured left-border accents (the overused SaaS trope is explicitly avoided). Content sits directly on the card — no inner boxes stacked on boxes. + +### Layout — fixed spine +Titlebar 32px · sidebar 48px collapsed / 210px expanded · optional right task rail 280px. Pages handle their own scroll; the shell does not. Left-aligned text everywhere. No centred hero sections. + +### Transparency + blur +Used sparingly, only for: tooltips on collapsed sidebar items, the backdrop of the float window, the accent-subtle tint (`--accent 6%`) on selected/pressed accent buttons. No glassmorphism. No frosted nav bars. + +### Iconography +Lucide icons, 2px stroke, rounded terminals. 16px in nav, 20px in features, 24px primary actions. Every icon paired with a visible text label — no standalone icons (exception: OS titlebar controls). Collapsed sidebar uses icon + aria-label + tooltip. Lucide is loaded from CDN. + +### Focus rings +2px solid `--accent`, 3px offset, rendered **above** grain (z-index > 50). Tested on every theme × zone combination. + +--- + +## Iconography + +**Library:** [Lucide Icons](https://lucide.dev) (MIT). Every Lucide glyph Kon uses is listed in `kon-source/docs/icon-mapping.md`. + +**Stroke weight:** 2px default · 2.5 on active sidebar items · 1 for empty-state illustrations (48px, opacity 40%). + +**Sizes:** +- 14px — chevrons, inline status dots +- 16px — sidebar nav, toolbar icons, source tags +- 20px — feature-area icons (Dictation toolbar, Settings panels) +- 24px — primary actions +- 48px — empty-state illustrations + +**Colour:** +- `--text-tertiary` at rest +- `--text-secondary` on hover (group hover) +- `--accent` when active, selected, or brand-significant (recording dot, active nav, play button) +- `--danger` for destructive and the recording state indicator +- `--success` for completion checks + +**Core Kon set (from the audit):** `Mic` (Dictation), `FileText` (Files), `SquareCheck` (Tasks), `Clock` (History), `Settings`, `Circle`/`Square` (record/stop), `Play`/`Pause`, `Search`, `Upload`, `Download`, `Copy`, `ChevronDown`, `ChevronLeft`, `ChevronRight`, `X`, `Check`, `Plus`, `Pin`, `User`, `AlignLeft`, `AlertTriangle`, `Loader2`. + +**Brand glyph:** The Sinhala letter **ක** (U+0D9A) sits next to the wordmark in `--accent`. Decorative only. During recording it spins slowly (2s linear infinite, `sinhala-spin`). A Unicode codepoint, not an SVG — scales perfectly, no asset needed. + +**Emoji:** **Never used.** + +**Bitmap icons, icon fonts, sprites:** **None.** Lucide covers everything. + +**Loading indicator:** `Loader2` with `animate-spin` is the standard. The codebase also has `UnicodeSpinner.svelte` (◉ ◎ ○) as an ambient/decorative alternative when Lucide feels too mechanical. + +**Delivery:** In HTML artefacts, load Lucide from CDN: `` then `lucide.createIcons()`. Or use inline SVGs copied from [lucide.dev](https://lucide.dev). See `assets/icons/` for the handful pre-copied for design previews. + +--- + +## Font substitution note + +The repo ships bundled woff2 files (`/fonts/lexend-variable.woff2`, `/fonts/instrument-serif-italic.woff2`, `/fonts/jetbrains-mono.woff2`, `/fonts/atkinson-hyperlegible-next.woff2`, `/fonts/opendyslexic.woff2`) which were **not included** in the imported subset. `colors_and_type.css` loads the Google Fonts CDN equivalents of Lexend, Instrument Serif Italic, JetBrains Mono, and Atkinson Hyperlegible — visually identical. + +**Missing:** OpenDyslexic (not on Google Fonts; needs to be self-hosted). Atkinson Hyperlegible **Next** is also not yet on Google Fonts — we substituted the original **Atkinson Hyperlegible** (very close; same designer, same metrics). + +**Please drop the original woff2 files into `fonts/` when you have a chance.** The CSS paths under `@font-face` would then be `fonts/lexend-variable.woff2` etc., matching the app bundle exactly. diff --git a/src/design-system/SKILL.md b/src/design-system/SKILL.md new file mode 100644 index 0000000..c22ff74 --- /dev/null +++ b/src/design-system/SKILL.md @@ -0,0 +1,26 @@ +--- +name: kon-design +description: Use this skill to generate well-branded interfaces and assets for Kon (by CORBEL), either for production or throwaway prototypes/mocks/etc. Contains essential design guidelines, colors, type, fonts, assets, and UI kit components for prototyping. +user-invocable: true +--- + +Read the README.md file within this skill, and explore the other available files. + +If creating visual artifacts (slides, mocks, throwaway prototypes, etc), copy assets out and create static HTML files for the user to view. If working on production code, you can copy assets and read the rules here to become an expert in designing with this brand. + +If the user invokes this skill without any other guidance, ask them what they want to build or design, ask some questions, and act as an expert designer who outputs HTML artifacts _or_ production code, depending on the need. + +## Essence — non-negotiable +- **Clarity without friction.** Every decision measured against it. +- **Neurodivergent-first.** No streak-shaming, no guilt, no red urgency, no auto-play. +- Warm brutalism — Barbican / Muji / Nujabes. Not San Francisco SaaS. +- Amber is always meaningful. Never decorative. +- Sentence case. No emoji. Never italic for body. + +## Files +- `colors_and_type.css` — import this for all tokens + semantic type. +- `README.md` — full brand + content + visual foundations. +- `assets/` — logos, glyph, grain, icon samples. +- `ui_kits/kon-app/` — component recreations of the desktop app. +- `preview/` — spec cards (swatches, specimens, components). +- `kon-source/` — ground-truth Svelte source from the Kon repo. diff --git a/src/design-system/colors_and_type.css b/src/design-system/colors_and_type.css new file mode 100644 index 0000000..221f814 --- /dev/null +++ b/src/design-system/colors_and_type.css @@ -0,0 +1,248 @@ +/* ============================================================ + Kon — Colors & Type + Single source of truth for CSS variables + semantic type. + Import this into any Kon design artefact. + ============================================================ */ + +/* --- Brand Webfonts (local woff2, shipped with Kon) --- */ +@font-face { + font-family: 'Lexend'; + src: url('fonts/lexend-variable.woff2') format('woff2-variations'), + url('fonts/lexend-variable.woff2') format('woff2'); + font-weight: 100 900; + font-style: normal; + font-display: swap; +} +@font-face { + font-family: 'Instrument Serif'; + src: url('fonts/instrument-serif-italic.woff2') format('woff2'); + font-weight: 400; + font-style: italic; + font-display: swap; +} +@font-face { + font-family: 'JetBrains Mono'; + src: url('fonts/jetbrains-mono.woff2') format('woff2-variations'), + url('fonts/jetbrains-mono.woff2') format('woff2'); + font-weight: 100 800; + font-style: normal; + font-display: swap; +} +@font-face { + font-family: 'Atkinson Hyperlegible Next'; + src: url('fonts/atkinson-hyperlegible-next.woff2') format('woff2-variations'), + url('fonts/atkinson-hyperlegible-next.woff2') format('woff2'); + font-weight: 200 800; + font-style: normal; + font-display: swap; +} +@font-face { + font-family: 'OpenDyslexic'; + src: url('fonts/opendyslexic.woff2') format('woff2'); + font-weight: 400 700; + font-style: normal; + font-display: swap; +} + +/* ============================================================ + Design Tokens — Dark Theme (default) + ============================================================ */ +:root, +:root[data-theme="dark"] { + /* — Surfaces (warm layered depth) — */ + --bg: #0f0e0c; + --bg-elevated: #171614; + --bg-card: #1b1a17; + --bg-input: #151412; + --sidebar: #13120f; + --nav-active: #201e1a; + --hover: #1e1c18; + + /* — Borders — */ + --border: #2c2923; + --border-subtle: #221f1b; + --border-focus: #e8a87c; + + /* — Text (warm hierarchy) — */ + --text: #f0ece4; + --text-secondary: #9a9486; + --text-tertiary: #716b60; + + /* — Accent (amber/copper — always meaningful) — */ + --accent: #e8a87c; + --accent-hover: #d4976a; + --accent-subtle: #e8a87c10; + --accent-glow: #e8a87c25; + + /* — Semantic — */ + --success: #7ec89a; + --danger: #e87171; + --warning: #e8c86e; + + /* — Radii — */ + --radius-sm: 6px; + --radius-md: 8px; + --radius-lg: 12px; + --radius-xl: 16px; + --radius-2xl: 20px; + + /* — Spacing (4px base) — */ + --space-1: 4px; + --space-2: 8px; + --space-3: 12px; + --space-4: 16px; + --space-5: 20px; + --space-6: 24px; + --space-8: 32px; + --space-10: 40px; + --space-12: 48px; + + /* — Shadow (warm, low-contrast) — */ + --shadow-sm: 0 1px 3px rgba(0,0,0,0.2); + --shadow-md: 0 4px 12px rgba(0,0,0,0.25); + --shadow-lg: 0 12px 28px rgba(0,0,0,0.35); + --shadow-accent: 0 4px 20px rgba(232,168,124,0.3); + + /* — Typography — */ + --font-body: 'Lexend', system-ui, -apple-system, sans-serif; + --font-display: 'Instrument Serif', Georgia, serif; + --font-mono: 'JetBrains Mono', ui-monospace, monospace; + --font-accessible: 'Atkinson Hyperlegible Next', 'Lexend', sans-serif; + --font-dyslexic: 'OpenDyslexic', 'Lexend', sans-serif; + + /* — Type scale (Major Third 1.250, base 16) — */ + --text-caption: 12px; + --text-small: 13px; + --text-body: 16px; + --text-body-lg: 18px; + --text-h4: 18px; + --text-h3: 21px; + --text-h2: 26px; + --text-h1: 32px; + --text-wordmark: 26px; + + --leading-tight: 1.15; + --leading-snug: 1.3; + --leading-normal: 1.5; + --leading-relaxed: 1.6; + --leading-transcript: 1.85; + + /* — Motion — */ + --ease: cubic-bezier(0.2, 0.8, 0.2, 1); + --duration-ui: 150ms; + --duration-decorative: 300ms; + --duration-zone: 400ms; +} + +/* ============================================================ + Light Theme + ============================================================ */ +:root[data-theme="light"] { + --bg: #faf8f5; + --bg-elevated: #f3f0eb; + --bg-card: #ffffff; + --bg-input: #f0ede8; + --sidebar: #f5f2ed; + --nav-active: #eae6e0; + --hover: #ede9e3; + + --border: #ddd8d0; + --border-subtle: #e6e2da; + + --text: #1a1816; + --text-secondary: #5c574d; + --text-tertiary: #8a8578; + + --accent: #b87a4a; + --accent-hover: #a06b3e; + --accent-subtle: #b87a4a10; + --accent-glow: #b87a4a20; + + --success: #3d8a5a; + --danger: #c44d4d; + --warning: #b89a3e; +} + +/* ============================================================ + Sensory Zones — tint surfaces only, accent stays amber. + ============================================================ */ +:root[data-zone="cave"] { --bg:#0f1214; --bg-elevated:#141a1e; --bg-card:#171f24; --sidebar:#0d1012; } +:root[data-zone="energy"] { --bg:#100e0b; --bg-elevated:#1c1815; --bg-card:#211d18; --sidebar:#141110; } +:root[data-zone="reset"] { --bg:#0e100e; --bg-elevated:#161a16; --bg-card:#1a1f1a; --sidebar:#0c0e0c; } + +:root[data-theme="light"][data-zone="cave"] { --bg:#f0f5f7; --bg-elevated:#e8f0f2; --bg-card:#f5fafc; --sidebar:#eaf2f4; } +:root[data-theme="light"][data-zone="energy"] { --bg:#faf7f3; --bg-elevated:#f5f0e8; --bg-card:#fffcf7; --sidebar:#f5f0ea; } +:root[data-theme="light"][data-zone="reset"] { --bg:#f3f7f2; --bg-elevated:#edf2ea; --bg-card:#f8fcf6; --sidebar:#eff4ec; } + +/* ============================================================ + Semantic elements — h1-h4, p, code, kbd, wordmark + ============================================================ */ +html, body { + background: var(--bg); + color: var(--text); + font-family: var(--font-body); + font-size: var(--text-body); + line-height: var(--leading-normal); + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.k-wordmark { + font-family: var(--font-display); + font-style: italic; + font-weight: 400; + font-size: var(--text-wordmark); + color: var(--accent); + letter-spacing: -0.01em; + line-height: 1.1; +} + +h1, .k-h1 { font-family: var(--font-body); font-weight: 700; font-size: var(--text-h1); line-height: var(--leading-tight); letter-spacing: -0.01em; color: var(--text); } +h2, .k-h2 { font-family: var(--font-body); font-weight: 600; font-size: var(--text-h2); line-height: var(--leading-snug); color: var(--text); } +h2.k-display, .k-page-title { font-family: var(--font-display); font-style: italic; font-weight: 400; font-size: var(--text-h2); line-height: var(--leading-snug); color: var(--text); } +h3, .k-h3 { font-family: var(--font-body); font-weight: 600; font-size: var(--text-h3); line-height: var(--leading-snug); color: var(--text); } +h4, .k-h4 { font-family: var(--font-body); font-weight: 600; font-size: var(--text-h4); line-height: var(--leading-snug); color: var(--text); } + +p, .k-body { font-family: var(--font-body); font-size: var(--text-body); line-height: var(--leading-normal); color: var(--text); max-width: 75ch; } +.k-body-lg { font-size: var(--text-body-lg); line-height: var(--leading-relaxed); } +.k-small { font-size: var(--text-small); line-height: var(--leading-normal); color: var(--text-secondary); } +.k-caption { font-size: var(--text-caption); line-height: var(--leading-normal); color: var(--text-tertiary); letter-spacing: 0.02em; } +.k-eyebrow { font-size: 10px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--text-tertiary); font-weight: 500; } + +.k-transcript { font-family: var(--font-body); font-size: var(--text-body); line-height: var(--leading-transcript); letter-spacing: 0.01em; font-feature-settings: "liga" 1, "kern" 1; } + +code, .k-code, kbd { + font-family: var(--font-mono); + font-size: 0.9em; +} +kbd { padding: 2px 6px; border-radius: var(--radius-sm); background: var(--bg-elevated); border: 1px solid var(--border-subtle); color: var(--text-tertiary); font-size: 11px; } + +a { color: var(--accent); text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1px; } +a:hover { color: var(--accent-hover); } + +::selection { background: var(--accent-glow); color: var(--text); } + +:focus-visible { + outline: 2px solid var(--accent); + outline-offset: 3px; + border-radius: var(--radius-md); +} + +/* Grain texture (2.5% dark / 1.5% light) — apply with .grain on a container */ +.grain { position: relative; } +.grain::after { + content: ""; + position: absolute; inset: 0; + pointer-events: none; + z-index: 50; + opacity: 0.025; + background-image: url("data:image/svg+xml;utf8,"); +} +:root[data-theme="light"] .grain::after { opacity: 0.015; } + +/* Kon sinhala glyph ක (U+0D9A) — wordmark companion */ +.k-glyph::after { content: '\0D9A'; color: var(--accent); margin-left: 0.25em; display: inline-block; } + +@media (prefers-reduced-motion: reduce) { + *,*::before,*::after { animation-duration:0.01ms!important; transition-duration:0.01ms!important; } +} diff --git a/src/design-system/preview/brand-icons.html b/src/design-system/preview/brand-icons.html new file mode 100644 index 0000000..d3726fc --- /dev/null +++ b/src/design-system/preview/brand-icons.html @@ -0,0 +1,26 @@ + + +
Iconography · Lucide · 2px stroke · rounded
+
+
Mic
+
FileText
+
SquareCheck
+
Clock
+
Settings
+
Search
+
Upload
+
Play
+
Pause
+
Copy
+
X
+
Check
+
+ diff --git a/src/design-system/preview/brand-wordmark.html b/src/design-system/preview/brand-wordmark.html new file mode 100644 index 0000000..af3ad6d --- /dev/null +++ b/src/design-system/preview/brand-wordmark.html @@ -0,0 +1,25 @@ + + +
+
+
Kon
+
Think out loud
+
+
+
Wordmark   Instrument Serif Italic 400
+
Colour   #e8a87c accent, always
+
Minimum size   18px
+

Always italic, always amber. The wordmark stands alone — no accompanying glyph or icon in the lockup.

+
+
+ diff --git a/src/design-system/preview/colors-accent.html b/src/design-system/preview/colors-accent.html new file mode 100644 index 0000000..04c4442 --- /dev/null +++ b/src/design-system/preview/colors-accent.html @@ -0,0 +1,21 @@ + + +
Accent · amber always means something
+
+
accent
#e8a87c
+
accent-hover
#d4976a
+
accent-subtle
#e8a87c · 6%
+
accent-glow
#e8a87c · 15%
+
+
Amber is reserved for interactivity, recording state, or brand identity. Never decorative.
+ diff --git a/src/design-system/preview/colors-semantic.html b/src/design-system/preview/colors-semantic.html new file mode 100644 index 0000000..6ce4707 --- /dev/null +++ b/src/design-system/preview/colors-semantic.html @@ -0,0 +1,17 @@ + + +
Semantic · three states only
+
+
Success
success · moss
#7ec89a
+
Danger
danger · muted red
#e87171
+
Warning
warning · honey
#e8c86e
+
+ diff --git a/src/design-system/preview/colors-surfaces.html b/src/design-system/preview/colors-surfaces.html new file mode 100644 index 0000000..7d8d9fe --- /dev/null +++ b/src/design-system/preview/colors-surfaces.html @@ -0,0 +1,24 @@ + + +
Surfaces · warm, with clearer elevation steps
+
+
bg
#0a0907
+
bg-elevated
#141310
+
bg-card
#1d1b17
+
bg-raised
#26231e
+
bg-input
#0f0e0b
+
sidebar
#0d0c09
+
nav-active
#252219
+
hover
#221f1a
+
+
Steps widened from ~3% to ~6% lightness between layers. Base dropped half a stop; cards + raised panels lifted a stop. Still warm amber-biased neutrals — no pure black, no halation.
+ diff --git a/src/design-system/preview/colors-text.html b/src/design-system/preview/colors-text.html new file mode 100644 index 0000000..791a48a --- /dev/null +++ b/src/design-system/preview/colors-text.html @@ -0,0 +1,19 @@ + + +
Text hierarchy · warm greys with amber undertone
+
+
The quick brown
text
#f0ece4 · AAA
+
fox jumps over
text-secondary
#9a9486 · AA
+
the lazy dog
text-tertiary
#716b60 · large only
+
+
Never #000 on #fff — causes halation for neurodivergent users. Tertiary only at 18px bold / 24px regular minimum.
+ diff --git a/src/design-system/preview/colors-zones.html b/src/design-system/preview/colors-zones.html new file mode 100644 index 0000000..17a5fe3 --- /dev/null +++ b/src/design-system/preview/colors-zones.html @@ -0,0 +1,27 @@ + + +
Sensory zones · tint surfaces only — accent stays amber
+
+
+
Cave
+
focus · cool teal#0f1214
+
+
+
Energy
+
active · warm neutral#100e0b
+
+
+
Reset
+
calm · muted sage#0e100e
+
+
+ diff --git a/src/design-system/preview/components-buttons.html b/src/design-system/preview/components-buttons.html new file mode 100644 index 0000000..2b4df30 --- /dev/null +++ b/src/design-system/preview/components-buttons.html @@ -0,0 +1,29 @@ + + +
Buttons
+
primary
+
secondary
+
ghost
+
danger
+
record
40×40 · circular · warm-pulse when recording
+ diff --git a/src/design-system/preview/components-cards.html b/src/design-system/preview/components-cards.html new file mode 100644 index 0000000..656ef2b --- /dev/null +++ b/src/design-system/preview/components-cards.html @@ -0,0 +1,28 @@ + + +
Cards · bg-card · 1px subtle border · radius 20 · shadow-sm
+
+
Reviewed the onboarding copy
+
Okay so the real issue is the first-run screen assumes you know what dictation means. We should lead with "press and hold, then speak" — that's the whole thing.
+
01:42·14 Apr · live·142 words
+
+
Badges & pills
+
+ Recording + Ready + Auto + 12 words + Error +
+ diff --git a/src/design-system/preview/components-empty-states.html b/src/design-system/preview/components-empty-states.html new file mode 100644 index 0000000..399e7ec --- /dev/null +++ b/src/design-system/preview/components-empty-states.html @@ -0,0 +1,16 @@ + + +
Empty states · ambient presence, no demanding CTA
+
+
Press record or Ctrl+Shift+R
+
Your transcriptions will be saved here
+
Something went wrong with that transcription. Your audio is saved — try again when you're ready.
+
+ diff --git a/src/design-system/preview/components-inputs.html b/src/design-system/preview/components-inputs.html new file mode 100644 index 0000000..103c3cc --- /dev/null +++ b/src/design-system/preview/components-inputs.html @@ -0,0 +1,32 @@ + + +
Form inputs
+
+
+
+
+
+
Save recordings
+
British English
+
Reduce motion
+
+
+
AutoCleanRaw
+
DarkLightSystem
+
+ diff --git a/src/design-system/preview/components-nav.html b/src/design-system/preview/components-nav.html new file mode 100644 index 0000000..02c5c4c --- /dev/null +++ b/src/design-system/preview/components-nav.html @@ -0,0 +1,25 @@ + + +
Navigation · sidebar items
+
+ +
Active item gets --nav-active background, amber icon, stroke 2. Hover lifts text to primary and fills background with --hover.
+
+ diff --git a/src/design-system/preview/components-toasts.html b/src/design-system/preview/components-toasts.html new file mode 100644 index 0000000..209c4f8 --- /dev/null +++ b/src/design-system/preview/components-toasts.html @@ -0,0 +1,19 @@ + + +
Toasts · bottom-right · sticky on error
+
Could not start recording
Audio device disconnected. Plug it back in and try again.
+
Dropped 2s of older audio
Kon is keeping up in real time.
+
Saved · 3 tasks extracted
Your audio is saved. Open Tasks to review.
+ diff --git a/src/design-system/preview/spacing-motion.html b/src/design-system/preview/spacing-motion.html new file mode 100644 index 0000000..016dc09 --- /dev/null +++ b/src/design-system/preview/spacing-motion.html @@ -0,0 +1,26 @@ + + +
Motion · elderflower, not espresso
+
+
UI150–200ms
+
Decorative300–500ms
+
Zone cross-fade300–500ms
+
Waveform pulse2s
+
+
Easing
+
+
+ +
ease-out
cubic-bezier(.2, .8, .2, 1)
+
+
+
Never: bounce, shake, slide-from-offscreen, auto-play. Reduce motion is the default — opt IN.
+ diff --git a/src/design-system/preview/spacing-radii.html b/src/design-system/preview/spacing-radii.html new file mode 100644 index 0000000..34a502e --- /dev/null +++ b/src/design-system/preview/spacing-radii.html @@ -0,0 +1,48 @@ + + +
Radii · amber arc = curve magnitude
+
+
6
sm
keyboard, pills
+
8
md
buttons, fields
+
12
lg
inner cards, nav
+
16
xl
containers
+
20
2xl
transcript card
+
full
record button, dots
+
+ diff --git a/src/design-system/preview/spacing-scale.html b/src/design-system/preview/spacing-scale.html new file mode 100644 index 0000000..5f20c07 --- /dev/null +++ b/src/design-system/preview/spacing-scale.html @@ -0,0 +1,23 @@ + + +
Spacing · 4px base
+
+
1
4px
+
2
8px
+
3
12px
+
4
16px
+
5
20px
+
6
24px
+
8
32px
+
10
40px
+
12
48px
+
+ diff --git a/src/design-system/preview/spacing-shadows.html b/src/design-system/preview/spacing-shadows.html new file mode 100644 index 0000000..daee390 --- /dev/null +++ b/src/design-system/preview/spacing-shadows.html @@ -0,0 +1,18 @@ + + +
Shadow system · low, warm
+
+
sm
0 1px 3px / .2 · cards
+
md
0 4px 12px / .25 · popovers
+
lg
0 12px 28px / .35 · modals
+
accent glow
record button only
+
+ diff --git a/src/design-system/preview/type-body.html b/src/design-system/preview/type-body.html new file mode 100644 index 0000000..224cb6d --- /dev/null +++ b/src/design-system/preview/type-body.html @@ -0,0 +1,12 @@ + + +
Body · 16/1.5
Kon listens more than it speaks. Press the hotkey, speak your thought, and your words appear — saved, searchable, left exactly where you put them.
+
Body large · 18/1.6
A calm friend who has already done the anxious part for you.
+
Small · 13
Press record or Ctrl+Shift+R
+
Caption · 12
12 words · 00:47 · live
+
Eyebrow · 10
Think out loud
+ diff --git a/src/design-system/preview/type-headings.html b/src/design-system/preview/type-headings.html new file mode 100644 index 0000000..4616c69 --- /dev/null +++ b/src/design-system/preview/type-headings.html @@ -0,0 +1,12 @@ + + +
H1 · 32/1.15/700 Lexend
Clarity without friction
+
H2 · 26/1.2/600 Lexend
Think out loud
+
Display · 26 Instrument Serif
History
+
H3 · 21/1.3
Sensory zones
+
H4 · 18/1.3
Press record or ⌃⇧R
+ diff --git a/src/design-system/preview/type-transcript-mono.html b/src/design-system/preview/type-transcript-mono.html new file mode 100644 index 0000000..dc71b60 --- /dev/null +++ b/src/design-system/preview/type-transcript-mono.html @@ -0,0 +1,13 @@ + + +
Transcript · 16–24px · 1.85 · +0.01em · liga + kern
+
So the thing I wanted to capture is — if we move the onboarding to the second screen instead of the first, the friction around first launch basically disappears. That feels right.
+
~/Library/Application Support/Kon/transcripts.db
+
CtrlShiftRGlobal record toggle
+ diff --git a/src/design-system/ui_kits/DictationPage.jsx b/src/design-system/ui_kits/DictationPage.jsx new file mode 100644 index 0000000..af7557e --- /dev/null +++ b/src/design-system/ui_kits/DictationPage.jsx @@ -0,0 +1,116 @@ +// DictationPage.jsx +const { useState: useStateD, useRef } = React; + +function RecordButton({ recording, onToggle }) { + const style = { + width:40, height:40, borderRadius:999, border:'none', cursor:'pointer', + display:'flex', alignItems:'center', justifyContent:'center', + transition:'all 150ms cubic-bezier(.2,.8,.2,1)', + background: recording ? 'var(--danger)' : 'var(--accent)', + boxShadow: recording ? '0 0 0 0 rgba(232,113,113,.4)' : '0 4px 20px rgba(232,168,124,.3)', + animation: recording ? 'konPulse 2s ease-in-out infinite' : 'none', + }; + return ( + + ); +} + +function Waveform({ recording }) { + const bars = [0.4, 0.8, 0.5, 1, 0.6, 0.9, 0.4, 0.7, 0.5, 0.8, 0.3, 0.6]; + return ( +
+ {recording ? ( + + {bars.map((h, i) => ( + + ))} + + ) : ( + + Press record or Ctrl+Shift+R + + )} +
+ ); +} + +function ToolbarBtn({ children, onClick, accent, disabled }) { + const [hov, setHov] = useStateD(false); + return ( + + ); +} + +function DictationPage({ recording, onToggle, timer, transcript, onTranscript, status, statusColor, onExtractTasks, onClear }) { + const wordCount = transcript.trim() ? transcript.trim().split(/\s+/).length : 0; + const ta = useRef(null); + + return ( +
+ {/* Control strip */} +
+ + {recording?'Stop':'Record'} + + {timer} + + {recording + ? REC + : 'Ready'} + + + +
+ + {/* Toolbar */} +
+ Template + Extract Tasks + + Save + Copy + Clear + Export +
+ + {/* Transcript */} +
+
+ {transcript.trim() ? ( +