# Mokosh Design System Cross-phase visual + interaction reference for the Mokosh extension (internal codename "Mokosh"; public display name currently `"AI Call Recorder"` — open per `brand-identity.md`). Authored 2026-05-17 in response to Plan 01-09's notification-icon discovery that the original placeholder PNGs failed Chrome's notification API. **This file mixes two kinds of content** and the design team should treat them differently: 1. **Engineering sketches** — what the extension currently ships in placeholder builds (colors, fonts, sizes, voice). These exist so the extension *runs*; they are not direction. Override anything aesthetic. 2. **Technical floors** — what Chrome MV3, the notification API, MV3 CSP, or WCAG accessibility require. These are binding regardless of creative direction. Marked explicitly with **(FLOOR)** wherever they appear. Status: `draft` — engineering sketch + binding floors. Both design and brand teams have full authority over everything not marked **(FLOOR)**. --- ## What's locked vs what's open | Decision | Status | |---|---| | Codename **"Mokosh"** | **LOCKED** (engineering — wired through code) | | Public display name | OPEN (brand team) | | All color hexes + token names | OPEN (design team) | | Typography face(s) and scale | OPEN (design team) — must cover Cyrillic, must bundle locally **(FLOOR)** | | Iconography style + mark concept | OPEN (design team) — must ship at 16/48/128 px PNG with file-size floors **(FLOOR)** | | Spacing scale, corner radii, motion | OPEN (design team) | | Brand voice, tagline, copy | OPEN (brand team) | | Welcome-tab layout + treatment | OPEN (design team) | | WCAG AA contrast | **FLOOR** (legal/accessibility — not creative) | | Chrome notification API icon ≥ 128 px | **FLOOR** | | MV3 CSP (no remote fonts/scripts, no `unsafe-eval`) | **FLOOR** | | Toolbar badge text max 4 chars | **FLOOR** (Chrome truncates) | | Russian-first audience | **FLOOR** (product, not visual) — visuals must work without depending on language for legibility | Everything below is engineering's current sketch, framed as starting options, unless explicitly tagged **(FLOOR)**. --- ## 1. Brand voice *(OPEN — brand team)* Engineering has no opinion. Axes to decide: - **Warmth** — clinical / neutral / warm / friendly - **Formality** — system-terse / professional / conversational / casual - **Humour** — none / dry / occasional / playful - **Emoji policy** — never / functional only (✓ × ⚠) / freely - **Two-register vs single-register** — toolbar/notification copy can match welcome-tab copy, or diverge (e.g. terse system messages vs full-prose onboarding) Engineering's current placeholder voice in shipped strings is *calm, brief, operationally serious* — chosen because the product runs for operators under stress. This is a defensible starting point and equally defensible to replace entirely. --- ## 2. Identity *(OPEN except codename)* | | | |---|---| | Codename **(LOCKED)** | Mokosh — Slavic goddess of weaving and fate | | Public display name *(OPEN — brand)* | Currently placeholder `"AI Call Recorder"`. See `brand-identity.md` §2 for options. | | Tagline *(OPEN — brand)* | Currently placeholder `"Записывает, чтобы вы могли воспроизвести."` ("Records so you can reproduce.") Replace, translate, or drop. | | Mark concept *(OPEN — design)* | See §5 below — engineering sketches one possible direction; design team picks from anything. | --- ## 3. Color *(OPEN — design team)* Engineering currently ships the placeholder palette below so the extension runs. **Every hex is open. Every token name is open. The whole palette strategy is open.** ### 3.1 Engineering's current placeholder palette | Token | Hex | Currently used for | |---|---|---| | `--mks-rec` | `#00C853` | Toolbar badge background when recording (Material Green A700) | | `--mks-off` | `#9E9E9E` | Toolbar badge background when idle | | `--mks-error` | `#FFB300` | Toolbar badge background on recoverable error (Material Amber 600) | | `--mks-fatal` | `#D32F2F` | Toolbar badge background on unrecoverable state (Material Red 700) | | `--mks-surface-bg` | `#222222` | Smoke-test page / dark popup surfaces | | `--mks-surface-text` | `#EEEEEE` | Text on dark surfaces | | `--mks-popup-bg-light` | `#FFFFFF` | Popup background, light Chrome theme | | `--mks-popup-bg-dark` | `#1F1F1F` | Popup background, dark Chrome theme | | `--mks-diag-bg` / `--mks-diag-fg` | `#000000` / `#00FF00` | Smoke-test timer overlay (dev-only — keep monospace + high-contrast for legibility, but recolor freely) | ### 3.2 Palette directions for the design team to choose from Direction matters more than specific hexes. Options without ranking: - **Dark-mode-native, monochrome + single accent for "recording"** (current placeholder) - **Light-mode primary with dark-mode variant** - **Multi-accent** — separate distinguishing color per state beyond just green/yellow/red - **Warm / earthy** — browns, ochres, off-whites - **Cool / clinical** — blues, grays, white - **High-contrast monochrome** — pure black/white + one accent - **Whatever the design team coins** ### 3.3 Mechanical hooks the palette has to fill (Not creative — these are surfaces engineering wires colors into.) - `chrome.action.setBadgeBackgroundColor(...)` — one color per toolbar badge state - Popup background + text (two themes if supporting both Chrome light/dark) - Welcome-tab background + text - Smoke-test diagnostic overlay (dev-only — design team can ignore) If the design team lands on N states beyond recording/idle/error, engineering adapts the badge wiring. --- ## 4. Typography *(OPEN — design team, with one floor)* Engineering ships system stack as a placeholder. Open to replacement. ### 4.1 Technical floor **(FLOOR — KEEP)** - **Must cover Cyrillic glyphs.** Russian operators are primary. Latin-only faces are non-starters. - **Must bundle locally.** MV3 CSP forbids remote `@font-face` from external CDNs. Any custom face ships as a static asset in `dist/`. - **Should not block the service worker.** The SW has no DOM and renders no text; this only matters for popup + welcome. ### 4.2 Engineering's current placeholder stack | Family token | Stack | Currently used for | |---|---|---| | `--mks-font-ui` | `-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif` | All UI text | | `--mks-font-mono` | `"SF Mono", Menlo, Consolas, "Courier New", monospace` | Diagnostic overlays, code, timer | Chosen for zero-load, no FOUT, automatic Cyrillic coverage on every OS. **Equally valid:** a licensed custom face (Inter, IBM Plex Sans, JetBrains Mono, or anything), variable fonts, a type pair, a different system fallback chain. ### 4.3 Engineering's current type scale (placeholder) | Token | Size | Line-height | Currently used for | |---|---|---|---| | `--mks-text-xs` | 11px | 1.3 | Badge labels, footnotes | | `--mks-text-sm` | 13px | 1.4 | Secondary UI text | | `--mks-text-base` | 15px | 1.5 | Body text | | `--mks-text-lg` | 18px | 1.4 | Section headings within popup | | `--mks-text-xl` | 24px | 1.3 | Welcome page H1 | | `--mks-text-xxl` | 32px | 1.2 | Diagnostic timer, large status | Replace freely. Modular scale, fluid type, t-shirt sizes — design team picks. ### 4.4 Engineering's current weight ladder (placeholder) - 400 (regular), 500 (medium), 700 (bold) Replace freely. --- ## 5. Iconography *(OPEN — design team, with floors)* ### 5.1 Technical floors **(FLOOR — KEEP)** - Sized PNGs at **16, 48, 128 px** in `dist/icons/`, declared in `manifest.json:icons` and `manifest.json:action.default_icon` - The **128 px is required** for `chrome.notifications.create({type:'basic'})` to render an iconUrl - File-size minimums per `assets-spec.md` (Chrome silently rejects icons below ~200 B / 500 B / 1 KB at the three sizes) - Optional 192 px variant for hi-DPI notification rendering - Inline SVG preferred for popup/welcome surfaces where Chrome permits — sharper at all DPIs. Chrome's `notifications.create` REQUIRES PNG `iconUrl` though. ### 5.2 Engineering's current placeholder direction Solid-filled, 24×24 source grid with 2 px padding, neutral mark + state via badge (the toolbar icon itself doesn't change between idle/recording — the `chrome.action.setBadgeBackgroundColor` does the state work). **This is one of many possible directions.** Equally valid: - Line-only icons - Mixed (solid for primary, line for secondary) - Per-state icon swaps via `chrome.action.setIcon` (adds perf cost — see §7) - Animated SVG icons - Illustrated mark (full scene rather than abstract glyph) ### 5.3 Mark concept *(OPEN — design team)* Engineering's current placeholder is "dark square + green dot" via ImageMagick. **No mark direction is implied.** Possible directions: - Recording-dot inside a frame (conventional, immediately readable as "records") - Thread/spool/weave motif (leans into the Mokosh etymology) - Abstract geometric mark (no figurative reference) - Wordmark only (the letterforms are the mark) - Illustrated mascot - Whatever the design team coins Constraints: must resolve at 16 px (a strong silhouette is hard at that size), must work neutral OR colored (depending on the team's badge-vs-icon-state decision). ### 5.4 Inline glyphs *(OPEN — design team)* The popup and welcome surfaces need glyphs for actions and states. Concepts engineering currently shows: | Concept | Currently shown as | Design-team-owned | |---|---|---| | Save / download | ⬇ filled-arrow-into-tray (Unicode, placeholder) | Replace with custom glyph or icon font | | Stop | ■ filled-square (placeholder) | — | | Recording active | ● solid-circle (placeholder) | — | | Error | ▲ filled-triangle with `!` (placeholder) | — | | Settings | ⚙ filled-gear (placeholder; not currently surfaced) | — | | Welcome / intro | 🧵 thread emoji (smoke-test placeholder only) | Replace at design time | --- ## 6. Spacing *(OPEN — design team)* Engineering currently uses a **4 px base** with the steps below as placeholders. Replace with any base (8 px, variable, t-shirt sizes, golden-ratio, etc.). | Token | Value | Currently used for | |---|---|---| | `--mks-space-1` | 4px | Tight padding within badges | | `--mks-space-2` | 8px | Default padding inside controls | | `--mks-space-3` | 12px | Padding inside popup containers | | `--mks-space-4` | 16px | Section separation | | `--mks-space-6` | 24px | Welcome page section gaps | | `--mks-space-8` | 32px | Welcome page hero spacing | ### 6.1 Surface sizing — current placeholders + technical floors | Surface | Engineering's placeholder | Floor / mechanism | |---|---|---| | Popup | 320 × 200 (comfortable; Chrome auto-sizes) | Chrome popups auto-size; no hard max | | Welcome page | full viewport, content max-width 720 px | None — fully open | | Notification | Chrome-controlled (~360 px wide) | **(FLOOR)** — not styleable | | Toolbar badge text | max 4 chars | **(FLOOR)** — Chrome truncates beyond | --- ## 7. Motion *(OPEN — design team)* Engineering currently ships near-zero motion (200–300 ms opacity fades, no bounce) because the product promise is unobtrusiveness. **Equally valid:** - Lively spring physics - Fully static (no transitions at all) - Cinematic entrances on welcome - Subtle micro-interactions on every state change Engineering's current placeholder durations: | Where | Duration | Easing | Notes | |---|---|---|---| | Hover transitions | 150ms | `ease-out` | Buttons, links | | Badge state change | instant | — | No animation (Chrome badge API doesn't support; setIcon swap interval would cost perf) | | Welcome page CTA hover | 200ms | `ease-out` | Background-color + slight scale | | Notification slide | Chrome default | — | **(FLOOR)** — not controllable | Per-state icon swap animation (e.g. recording-pulse) is possible but adds `setIcon` interval cost; design team picks if worth it. --- ## 8. Component conventions Two layers per component: **functional contract** (KEEP — comes from PLAN, not creative direction) and **visual treatment** (OPEN — design team). ### 8.1 Toolbar action (`chrome.action`) **Functional contract (KEEP):** - Three states surface to operators: IDLE, REC, ERROR (some teams add OFF as a distinct post-stop state) - Click behavior depends on state — IDLE click starts recording; REC click opens SAVE popup; ERROR click opens RESTART popup - Tooltip text changes per state via `chrome.action.setTitle` **Visual treatment (OPEN):** - Badge background color per state (currently mapped to `--mks-rec` / `--mks-off` / `--mks-error`) - Badge text per state (currently `""` / `"REC"` / `"ERR"` / `"OFF"`) - Tooltip wording (currently Russian, placeholder copy below — brand team rewrites) - IDLE: `"Mokosh — щёлкните, чтобы начать запись"` - REC: `"Mokosh — идёт запись (00:42)"` - ERROR: `"Mokosh — ошибка записи, щёлкните для восстановления"` ### 8.2 Notification **Functional contract (KEEP):** - Fired via `chrome.notifications.create({type:'basic', iconUrl, title, message, priority})` - `iconUrl` must be a ≥128 px PNG via `chrome.runtime.getURL` **(FLOOR)** - Fires on startup (until operator dismisses), on recovery (after user-stopped-sharing), optionally on save-complete (Phase 5 candidate) - One notification per state transition (no spam) **Visual treatment (OPEN):** - Title text (currently `"Mokosh"`) - Message text (brand team rewrites) - `priority` (1 default, 2 for urgent — design team can pick when to escalate) ### 8.3 Popup (current scope: SAVE-only per Plan 01-09) **Functional contract (KEEP):** - Represents the current toolbar state (REC / ERROR; IDLE shouldn't normally surface here) - REC state offers a single primary action: save the buffered archive - ERROR state offers a single primary action: restart recording - No secondary actions in either state (Plan 01-09 scope decision) **Visual treatment (OPEN):** - Sizing (current placeholder 320 × 200) - CTA wording (current placeholder Russian; brand team rewrites) - Layout (CTA position, status line, footer) - Status messaging copy - Dark/light theme handling (current placeholder: auto via `prefers-color-scheme`) ### 8.4 Welcome page (Plan 01-10) **Functional contract (KEEP):** - Opens via `chrome.tabs.create` on first install - Static HTML/CSS/JS in `dist/` (no remote loads **(FLOOR)**) - Must communicate: what Mokosh does, how the operator triggers a save, privacy story **Visual treatment (OPEN — design team owns entirely):** - Layout (hero + steps, scrolling story, modal, video walkthrough, anything) - Tone (welcome cheer vs sober briefing — brand team) - Hero treatment (wordmark-only, mark + wordmark, illustrated scene, video) - Primary CTA wording + placement - Whether there's a CTA at all (some onboarding flows just inform) --- ## 9. Accessibility & internationalization *(FLOORS — KEEP)* These are functional/legal floors, not creative: - **Contrast: WCAG AA** (4.5:1 normal text, 3:1 large text). Any palette the design team lands on must validate against this for all state pairings. Engineering's current placeholder palette is pre-validated; new palettes need re-validation. - **Focus indicators:** visible focus rings on all interactive elements (popup buttons, welcome CTA). Chrome's default `outline` works; custom focus styles welcome as long as they remain visible. - **Color-independence:** every color-coded state must pair with text or shape. Color alone is not an accessible state indicator — pairs with badge labels, glyphs, or copy. - **Russian-first localization:** all user-facing strings ship in Russian as the default locale. UI scaffolding must support future locales via Chrome's `_locales/` mechanism. - **Reduced motion:** if any animation is enabled, honor `prefers-reduced-motion: reduce` by falling back to static. --- ## 10. Open creative decisions Non-exhaustive list for both teams. None block engineering today (placeholders ship); each unlocks a polish pass when answered. 1. Public display name (`brand-identity.md` §2) 2. Design system name (`brand-identity.md` §3) 3. Voice register — one tone or two (system-terse vs welcome-prose) 4. Tagline final wording (currently `"Записывает, чтобы вы могли воспроизвести."`) 5. Palette direction (§3.2) + specific hexes 6. Token naming convention (`--mks-rec` placeholder pattern) 7. Typography face(s) — system stack vs custom 8. Type scale + weight ladder 9. Spacing base + steps 10. Corner radii — sharp / soft / mixed 11. Iconography style — solid / line / mixed 12. Mark concept (§5.3) 13. Per-state icon swaps vs fixed mark + dynamic badge 14. Motion vocabulary — minimal / lively / static 15. Welcome-tab layout + treatment (§8.4) 16. Popup layout treatment (§8.3 visual) 17. Notification copy + tone (§8.2) 18. Tooltip wording per state (§8.1) 19. Dark/light theme strategy — auto-detect, follow-Chrome, force one, user-toggle --- ## 11. Implementation notes *(TECHNICAL — KEEP)* - All extension contexts (SW, offscreen, popup, welcome page) share the same CSP. No external font/asset loads. Everything bundled or `chrome.runtime.getURL`. **(FLOOR)** - Icons must be in `dist/icons/` and declared in both `manifest.json:icons` AND `manifest.json:action.default_icon`. **(FLOOR)** - Notification iconUrl uses `chrome.runtime.getURL('icons/icon128.png')` — at least 128 × 128, ideally 192 × 192 for retina. Smaller icons silently fail Chrome's `imageUtil` validation. **(FLOOR)** - All popup HTML/CSS lives in `src/popup/`. All welcome HTML/CSS lives in `src/welcome/` (Plan 01-10). **(file convention — easy to change)** - Inline SVG preferred over PNG where the surface permits — sharper at all DPIs. Notification API requires PNG. **(FLOOR for notification only)** --- ## 12. Related - `brand-identity.md` — naming + blurb + voice (Brief #1) - `assets-spec.md` — concrete file deliverables + technical floors - `src/background/index.ts` — implements toolbar action + notification per §8 - `src/popup/index.html` — implements popup per §8.3 - `src/welcome/welcome.html` — implements welcome per §8.4 (Plan 01-10) - `.planning/phases/01-stabilize-video-pipeline/01-CONTEXT.md` D-15/D-16/D-17 amendments — interaction model this design language sits inside