diff --git a/.planning/intel/brand-decisions-v1.md b/.planning/intel/brand-decisions-v1.md new file mode 100644 index 0000000..66230b8 --- /dev/null +++ b/.planning/intel/brand-decisions-v1.md @@ -0,0 +1,50 @@ +# Mokosh Brand Decisions v1 (2026-05-17) + +Snapshot of the 9 brand/design decisions resolved against the designer team's +handoff (delivered to `.planning/intel/design-incoming/`). User reviewed the +Decision Brief in browser; accepted designer's recommendations on D-01..06, +D-08, D-09; overrode D-07. + +## Resolutions + +| # | Decision | Owner | Designer recommendation | User pick | Note | +|---|---|---|---|---|---| +| D-01 | Mark concept | Design | A · Loom (2×2 weave intersection) | **A** (accepted) | Unlocks PNG icon rasterization from `mokosh-mark.svg` | +| D-02 | Welcome layout | Design | A · Hero + Loom dial (text left, dial right) | **A** (accepted) | Unlocks Plan 01-10 (`src/welcome/` build) | +| D-03 | Voice register | Brand | A · Sober (short commands, periods, no extra) | **A** (accepted) | Carries to all i18n strings | +| D-04 | Palette | Design | A · Loom (warm linen + natural dyes: madder/moss/amber/brick) | **A** (accepted) | `tokens.css` palette is canonical | +| D-05 | Type pairing | Design | A · Newsreader (serif display) + IBM Plex Sans (UI body, Cyrillic) + IBM Plex Mono (diagnostic) | **A** (accepted) | All three OFL; unlocks WOFF2 self-hosting (replaces Google Fonts `@import` in `tokens.css:12`) | +| D-06 | Icon strategy | Design | A · Neutral mark + dynamic badge (`chrome.action.setBadgeBackgroundColor`) | **A** (accepted) | Matches engineering's current arch; NO A-06 per-state PNG set | +| **D-07** | **Display name (`manifest.json:name`)** | Brand | A · `Mokosh` | **B · `Mokosh — Session Capture`** | **OVERRIDE** — operator-facing name surfaces capture purpose | +| D-08 | Tagline (RU+EN parallel) | Brand | A · `«Тридцать секунд назад, всегда под рукой.»` / `"Thirty seconds ago, always at hand."` | **A** (accepted) | `manifest.json:description` + welcome hero copy | +| D-09 | Smoke shipping | Eng + Both | A · Dev-only (behind VITE_DEV flag) | **A** (accepted) | Current production bundle accidentally ships smoke page — Plan 01-12 task to gate it | + +## 8 i18n copy strings (deferred per-string) + +Designer flagged 8 operator strings in Brief §02 (popup CTA, badge tooltips, +notification titles + messages, welcome copy, etc.) that need final wording. +These **INHERIT the D-03 Sober register default** unless user overrides on a +per-string basis. Plan 01-12 (Design Integration) will surface each for ack +as it lands. + +## Implementation handoff (what Plan 01-12 must do) + +- **D-01 + D-06**: Rasterize `mokosh-mark.svg` to `icons/icon{16,48,128}.png` (PNG required by Chrome notification API; SVG ≠ acceptable). Preserve neutral mark across all states; no per-state variants. +- **D-04**: Ingest `tokens.css` `--mks-*` color palette as authoritative; rewire `src/popup/`, `src/welcome/`, smoke.sh to use these tokens. Replace engineering placeholder palette (`#212121`/`#00C853`/etc.) entirely. +- **D-05**: Self-host Newsreader (variable) + IBM Plex Sans (4 weights) + IBM Plex Mono (2 weights), Latin + Cyrillic subsets, WOFF2 only. Remove Google Fonts `@import` from `tokens.css:12` (MV3 CSP). Bundle via Vite asset pipeline. +- **D-07**: Update `manifest.json:name` to `"Mokosh — Session Capture"`. Consider i18n via `_locales/` if RU variant differs from EN (per Chrome MV3 best practice — manifest:name = `"__MSG_extName__"` with `default_locale`). +- **D-08**: Update `manifest.json:description` to the tagline (one of the RU/EN per default_locale). Carry to welcome hero copy. +- **D-02**: Plan 01-10 builds welcome tab with Hero + Loom dial layout (designer's Surface Kit §05 option A). +- **D-09**: Gate smoke page behind `VITE_DEV` flag in `vite.config.ts` so production `npm run build` excludes it. Current state ships smoke unintentionally. + +## Source artifacts + +- `.planning/intel/design-incoming/mokosh/dist/Decision Brief (standalone).html` — full Brief with options + recommendations +- `.planning/intel/design-incoming/mokosh/dist/Mokosh Surface Kit (standalone).html` — interactive design canvas +- `.planning/intel/design-incoming/system/bundle/mokosh-handoff/tokens.css` — production token system +- `.planning/intel/design-incoming/system/bundle/mokosh-handoff/assets/mokosh-mark.svg` — 32×32 brand mark +- `.planning/intel/design-incoming/system/bundle/mokosh-handoff/assets/mokosh-lockup.svg` — 240×56 mark + wordmark lockup +- `.planning/intel/design-incoming/system/bundle/mokosh-handoff/handoff.html` — designer's memo +- `.planning/intel/brand-identity.md` — original engineering brief (now resolved per this doc) +- `.planning/intel/design-system.md` — engineering's prior visual sketch (superseded for tokens; tokens.css is canonical) +- `.planning/intel/assets-spec.md` — deliverables spec (icon dimensions/floors still binding) diff --git a/.planning/intel/brand-identity.md b/.planning/intel/brand-identity.md index f99b9fb..d53d370 100644 --- a/.planning/intel/brand-identity.md +++ b/.planning/intel/brand-identity.md @@ -257,6 +257,10 @@ any conflict and we'll resolve it together. ## Open creative questions (non-exhaustive) +> **RESOLVED 2026-05-17** per designer handoff + user ack. See +> `brand-decisions-v1.md` for the 9 resolutions (D-01..D-09). The list below +> remains as historical context for what was open before the handoff. + For both teams to work through in whichever order makes sense. None are blocking engineering today (placeholders ship), but each unlocks a polish pass when answered. diff --git a/.planning/intel/design-incoming/system/bundle/mokosh-handoff/README.txt b/.planning/intel/design-incoming/system/bundle/mokosh-handoff/README.txt new file mode 100644 index 0000000..b48925c --- /dev/null +++ b/.planning/intel/design-incoming/system/bundle/mokosh-handoff/README.txt @@ -0,0 +1,43 @@ +MOKOSH · HANDOFF BUNDLE +======================== + +Date 17 May 2026 +From Design system (engineering-authored) +To Design team · brand team +Status draft — every choice is reversible + +WHAT IS IN HERE +---------------- +handoff.html The memo. Open in any browser. Self-contained — no + network requests except the dev font CDN (Google + Fonts) which one of the asks in §02 is to replace. +tokens.css The complete token system in production form. Drop + it next to your build's stylesheets to spec colours + and type from the real values. +assets/ + mokosh-mark.svg The proposed brand mark. 2x2 weave intersection. + mokosh-lockup.svg Mark + wordmark lockup. + +HOW TO USE +---------- +1. Read handoff.html top-to-bottom (~5 min). +2. Reply on each of the 8 decisions in §01. Accept, override, or rewrite. +3. Drop the files I'm asking for in §02 into the project repo. +4. If anything in tokens.css needs to change, point at the token name — + it's one edit, the rest of the system re-threads automatically. + +WHAT IS NOT IN HERE +------------------- +- The full preview cards. Those live in the design-system project under + preview/*.html — open the project for the 23 foundation cards split + across Type / Colors / Spacing / Components / Brand. +- The UI kit. Same project, under ui_kits/extension/. +- The original briefs from engineering — brand-identity.md, design- + system.md, assets-spec.md. Read them too if you have not seen them; + this handoff sits on top of them. + +QUESTIONS +--------- +Whatever's clearest. A reply inline on the .html, an updated tokens.css, +a Figma link, a screenshot, an angry voice memo. The system is wired to +accept overrides as small atomic edits, so partial answers are fine. diff --git a/.planning/intel/design-incoming/system/bundle/mokosh-handoff/assets/mokosh-lockup.svg b/.planning/intel/design-incoming/system/bundle/mokosh-handoff/assets/mokosh-lockup.svg new file mode 100644 index 0000000..130d46e --- /dev/null +++ b/.planning/intel/design-incoming/system/bundle/mokosh-handoff/assets/mokosh-lockup.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + Mokosh + \ No newline at end of file diff --git a/.planning/intel/design-incoming/system/bundle/mokosh-handoff/assets/mokosh-mark.svg b/.planning/intel/design-incoming/system/bundle/mokosh-handoff/assets/mokosh-mark.svg new file mode 100644 index 0000000..6e9bd8f --- /dev/null +++ b/.planning/intel/design-incoming/system/bundle/mokosh-handoff/assets/mokosh-mark.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.planning/intel/design-incoming/system/bundle/mokosh-handoff/handoff.html b/.planning/intel/design-incoming/system/bundle/mokosh-handoff/handoff.html new file mode 100644 index 0000000..60873c7 --- /dev/null +++ b/.planning/intel/design-incoming/system/bundle/mokosh-handoff/handoff.html @@ -0,0 +1,601 @@ + + + + + + Mokosh · Handoff to design + brand + + + + +
+ +
+
+
Memo · design + brand handoff
+

What I need
to finish, and from whom.

+
+
+ From Design system (this project)
+ To Design team · brand team
+ Date 17 May 2026
+ Status draft — every choice is reversible +
+
+ +
+

I committed to a creative direction so the system would run. Eight decisions in that direction need a yes / override from you, and six files need to land in this repo before the extension can stop loading fonts from a CDN and stop shipping the placeholder square-and-dot PNG.

+

Nothing here is locked. Override anything; the tokens are wired so a re-skin is a single-file edit.

+
+ + +
+
+ § 01 +

Decisions to confirm or override

+ 8 items +
+

Each one currently has a proposed direction shipping in colors_and_type.css and the UI kit. Tick the box if you accept; replace inline if you want a different answer.

+ +
+ +
+
+
+
D-01 · Public display name
+
Is "Mokosh" the right manifest.json:name?
+
Proposing the codename surfaces externally as the public name. Alternative is keeping "AI Call Recorder" for store discoverability, or coining something new.
+
alt → "AI Call Recorder" · "Mokosh — Session Capture" · "Mokosh / АИ Регистратор"
+
+ brand +
+ +
+
+
+
D-02 · Tagline
+
Confirm «Тридцать секунд назад, всегда под рукой.»
+
EN parallel: Thirty seconds ago, always within reach. Used on welcome hero + manifest.json:description.
+
+ brand +
+ +
+
+
+
D-03 · Voice register
+
Two-register copy — terse RU on toolbar / popup / notification; bilingual RU+EN on welcome only.
+
Calm, operationally serious. Sentence case. Periods. No emoji. No exclamation marks. Address with «вы» on welcome; imperative verbs in popup.
+
+ brand +
+ +
+
+
+
D-04 · Palette direction
+
"Loom" — linen + ink + dye-named accents. Light-primary with dark sibling.
+
Madder rust for REC is the boldest call. Alt is conventional material-red (#D32F2F) if rust reads off-brand.
+
override → flag the WCAG-AA-validated hex you'd prefer for any of madder / moss / amber / brick
+
+ design +
+ +
+
+
+
D-05 · Type pairing
+
Newsreader (display) · IBM Plex Sans (UI) · IBM Plex Mono (mono).
+
All three OFL, all three cover Cyrillic. If a licensed face is preferred (e.g. an in-house family), name it and I'll rethread.
+
+ design +
+ +
+
+
+
D-06 · Mark concept
+
2×2 weave intersection — see assets/mokosh-mark.svg.
+
References the goddess-of-weaving etymology without being illustrative. Holds at 16 px. Override with anything from a wordmark-only lockup to an illustrated scene.
+
+ design +
+ +
+
+
+
D-07 · Iconography
+
Lucide — line, 1.5 stroke, 24 grid.
+
Open-licensed (ISC). Bundle locally for MV3. Alternative is a custom set or Phosphor / Heroicons. Tabler is the other strong line option.
+
+ design +
+ +
+
+
+
D-08 · Per-state icon swap
+
Stick with neutral mark + dynamic badge, or commission per-state PNG sets?
+
Per-state requires 9 additional PNGs (3 sizes × 3 states) and a perf-costed chrome.action.setIcon swap on every state change. Default direction stays with the badge.
+
see assets-spec.md A-06 for the deliverable list if you pick swap
+
+ design +
+ +
+
+ + +
+
+ § 02 +

Files I need landed in this repo

+ 6 deliverables +
+

Priorities map to the engineering plan in the original assets-spec.md. P0 unblocks shipping a real branded build; P1 finishes the welcome surface; P2 is polish.

+ +
+ +
+ P0 + fonts/newsreader-{400,500,600}.woff2
fonts/ibm-plex-sans-{400,500,600,700}.woff2
fonts/ibm-plex-mono-{400,500}.woff2
+ Webfont WOFF2 files. Currently loaded from Google Fonts via @import. MV3 CSP forbids remote @font-face at runtime — production must bundle. I'll rewire colors_and_type.css to local rules once these land. + Cyrillic ✓ · WOFF2 +
+ +
+ P0 + assets/extension-icons/icon16.png
assets/extension-icons/icon48.png
assets/extension-icons/icon128.png
+ Branded extension icons. The three files currently in that folder are the upstream engineering placeholders (dark square + green dot). Rasterise from assets/mokosh-mark.svg — or supply a different mark if D-06 is overridden. + ≥ 200 B · 500 B · 1 KB +
+ +
+ P1 + assets/extension-icons/icon192.png + Hi-DPI notification icon. Optional but recommended for retina rendering of chrome.notifications.create. + ≥ 2 KB +
+ +
+ P1 + copy/welcome.ru.md + Final RU copy review. Hero title, three step bodies, three privacy cards. My draft in ui_kits/extension/Welcome.jsx is a working strawman. + brand sign-off +
+ +
+ P1 + copy/welcome.en.md + English parallel-text subhead. One line under the hero title. Brand decides whether to extend bilingual treatment to the step bodies. + brand sign-off +
+ +
+ P2 + assets/icon-{rec,off,err}-{16,48,128}.png + Per-state icon variants — only if D-08 lands on the swap direction. 9 files total. + conditional +
+ +
+
+ + +
+
+ § 03 +

Acceptance criteria

+ non-creative · binding +
+

These are engineering / accessibility floors, not creative direction. Anything you ship has to clear them.

+ +
+
WCAG AA4.5 : 1 normal text, 3 : 1 large. Current palette is pre-validated; overrides need re-validation.
+
Cyrillic ✓Every chosen face renders Russian glyphs without fallback. Plex + Newsreader currently pass.
+
MV3 CSPNo remote font / script loads at runtime. Bundle everything locally in dist/.
+
Notification flooriconUrl ≥ 128 px PNG, ≥ 1 KB. Chrome's imageUtil silently rejects smaller files.
+
Badge floorBadge text ≤ 4 characters. Chrome truncates beyond. "REC" / "ERR" both fit.
+
Reduced-motionAll transitions collapse to 0 ms under prefers-reduced-motion. Wired in colors_and_type.css.
+
Colour-independenceEvery state pairs colour with text or shape. Badge carries REC / ERR text alongside the colour.
+
Focus visible3 px halo on all interactive elements. --mks-shadow-focus works on any surface.
+
+
+ + +
+
+ § 04 +

What I will do once you reply

+ turnaround +
+

Round-trip cost so you can scope a review window.

+ + +
+ +
+
+ + Mokosh +
+ handoff · v1 · 17.05.2026 +
+ +
+ + diff --git a/.planning/intel/design-incoming/system/bundle/mokosh-handoff/tokens.css b/.planning/intel/design-incoming/system/bundle/mokosh-handoff/tokens.css new file mode 100644 index 0000000..60a046e --- /dev/null +++ b/.planning/intel/design-incoming/system/bundle/mokosh-handoff/tokens.css @@ -0,0 +1,273 @@ +/* ───────────────────────────────────────────────────────────────────────── + Mokosh Design System — colors_and_type.css + Single source of truth for foundational tokens. + Surfaces: Chrome MV3 popup, welcome page, notification copy, toolbar. + Audience: Russian-first operators. Cyrillic coverage required. + ───────────────────────────────────────────────────────────────────── */ + +/* Fonts (bundled locally; MV3 CSP forbids remote @font-face at runtime). + Substitution flag — until licensed files arrive, these are loaded from + Google Fonts in PREVIEW HTML only. Production bundles ship the same + families locally from /fonts/. See fonts/README.md. */ +@import url('https://fonts.googleapis.com/css2?family=Newsreader:ital,opsz,wght@0,6..72,400;0,6..72,500;0,6..72,600;1,6..72,400&family=IBM+Plex+Sans:wght@400;500;600;700&family=IBM+Plex+Mono:wght@400;500&display=swap'); + +:root { + /* ── Palette ────────────────────────────────────────────────────────── + The "loom" palette. Warm-earthy, NOT clinical-blue. Reads as + restrained, professional, slightly hand-made — distinct from the + standard SaaS Material defaults the engineering placeholder used. + Each step validated for WCAG AA against its intended pair. */ + + /* Linen — primary surface family (warm off-white through stone) */ + --mks-linen-50: #faf7f1; /* page background */ + --mks-linen-100: #f3eee4; /* card / popup surface */ + --mks-linen-200: #e8e0d0; /* hairline / divider on linen */ + --mks-linen-300: #d4c9b5; /* muted edge */ + + /* Ink — text + inverse surface family (warm near-black indigo) */ + --mks-ink-900: #181b2a; /* primary text, deepest surface */ + --mks-ink-800: #232639; /* dark surface */ + --mks-ink-700: #2f3349; /* dark surface raised */ + --mks-ink-500: #5b5f76; /* secondary text on linen */ + --mks-ink-400: #7a7e94; /* tertiary text, captions */ + --mks-ink-300: #a4a7b8; /* disabled text */ + + /* Accents — state colors. Each is a dye reference. */ + --mks-madder-600: #b2543d; /* REC accent — Rubia tinctorum dye */ + --mks-madder-700: #963f29; /* REC pressed */ + --mks-madder-100: #f5e2db; /* REC tint */ + + --mks-moss-600: #5a7349; /* success / saved */ + --mks-moss-700: #455a38; + --mks-moss-100: #e2e9da; + + --mks-amber-600: #c98b3a; /* warning / recoverable error */ + --mks-amber-100: #f6e6c8; + + --mks-brick-600: #a23a2b; /* unrecoverable error */ + --mks-brick-100: #f0d5cf; + + /* Semantic — point these at the palette. Use these in components. */ + --mks-surface: var(--mks-linen-50); + --mks-surface-raised: var(--mks-linen-100); + --mks-surface-sunken: var(--mks-linen-200); + --mks-surface-inverse: var(--mks-ink-900); + + --mks-fg-1: var(--mks-ink-900); /* primary text */ + --mks-fg-2: var(--mks-ink-500); /* secondary text */ + --mks-fg-3: var(--mks-ink-400); /* tertiary / caption */ + --mks-fg-disabled: var(--mks-ink-300); + --mks-fg-inverse: var(--mks-linen-50); + + --mks-border: var(--mks-linen-200); + --mks-border-strong: var(--mks-linen-300); + --mks-border-focus: var(--mks-ink-900); + + --mks-rec: var(--mks-madder-600); + --mks-success: var(--mks-moss-600); + --mks-warning: var(--mks-amber-600); + --mks-error: var(--mks-brick-600); + + /* ── Type ───────────────────────────────────────────────────────────── + Three families. Newsreader for display (serif with calm character). + IBM Plex Sans for UI body (excellent Cyrillic; not Inter/Roboto). + IBM Plex Mono for diagnostic / timer overlays. */ + + --mks-font-display: "Newsreader", "Iowan Old Style", "Times New Roman", serif; + --mks-font-ui: "IBM Plex Sans", "Segoe UI", -apple-system, BlinkMacSystemFont, sans-serif; + --mks-font-mono: "IBM Plex Mono", "SF Mono", Menlo, Consolas, monospace; + + /* Base type scale — ratio ~1.2, tuned for popup density. + Smallest size 11px is reserved for badge labels only. */ + --mks-text-xs: 11px; + --mks-text-sm: 13px; + --mks-text-base: 15px; + --mks-text-md: 17px; + --mks-text-lg: 20px; + --mks-text-xl: 28px; + --mks-text-2xl: 40px; + --mks-text-3xl: 56px; + + --mks-lh-tight: 1.15; + --mks-lh-snug: 1.3; + --mks-lh-base: 1.5; + + --mks-weight-regular: 400; + --mks-weight-medium: 500; + --mks-weight-semibold: 600; + --mks-weight-bold: 700; + + /* Display tracking — Newsreader at large sizes wants negative tracking */ + --mks-tracking-display: -0.015em; + --mks-tracking-tight: -0.005em; + --mks-tracking-base: 0; + --mks-tracking-loose: 0.04em; /* eyebrow / caps labels */ + --mks-tracking-caps: 0.08em; /* badge text REC / ERR */ + + /* ── Spacing ────────────────────────────────────────────────────────── + 4px base. Steps named by px multiple for clarity. */ + --mks-space-1: 4px; + --mks-space-2: 8px; + --mks-space-3: 12px; + --mks-space-4: 16px; + --mks-space-5: 20px; + --mks-space-6: 24px; + --mks-space-8: 32px; + --mks-space-10: 40px; + --mks-space-12: 48px; + --mks-space-16: 64px; + --mks-space-20: 80px; + + /* ── Radius ─────────────────────────────────────────────────────────── + Architectural. Sharp-ish — 4px base, 8px cards, 999 chips. NOT pillow. */ + --mks-radius-sm: 2px; /* badge text container */ + --mks-radius-md: 4px; /* default control */ + --mks-radius-lg: 8px; /* card, popup body */ + --mks-radius-xl: 12px; /* welcome hero card */ + --mks-radius-full: 999px;/* chips, recording dot */ + + /* ── Borders + shadows ─────────────────────────────────────────────── + One pixel hairline, low-elevation shadows. + Restrained — no big card drop-shadows. */ + --mks-border-width: 1px; + + /* Hairline shadow — for buttons */ + --mks-shadow-1: 0 1px 0 rgba(24, 27, 42, 0.04), + 0 1px 2px rgba(24, 27, 42, 0.06); + /* Card shadow — popup elevation */ + --mks-shadow-2: 0 1px 2px rgba(24, 27, 42, 0.06), + 0 4px 12px rgba(24, 27, 42, 0.08); + /* Floating — modal / tooltip */ + --mks-shadow-3: 0 2px 4px rgba(24, 27, 42, 0.08), + 0 12px 32px rgba(24, 27, 42, 0.12); + /* Inset — sunken surfaces, fields */ + --mks-shadow-inset: inset 0 1px 0 rgba(24, 27, 42, 0.04); + /* Focus ring — visible against any surface, color-independent */ + --mks-shadow-focus: 0 0 0 3px rgba(24, 27, 42, 0.18); + + /* ── Motion ─────────────────────────────────────────────────────────── + Quiet. No bounces. Reduced-motion is honored at the component level. */ + --mks-dur-fast: 120ms; + --mks-dur-base: 200ms; + --mks-dur-slow: 320ms; + --mks-ease-out: cubic-bezier(0.2, 0.6, 0.2, 1); + --mks-ease-in-out: cubic-bezier(0.4, 0, 0.2, 1); + + /* ── Layout ──────────────────────────────────────────────────────────*/ + --mks-popup-w: 320px; + --mks-popup-min-h: 180px; + --mks-welcome-max-w: 720px; +} + +/* Dark theme — applied via .dark on root OR @media (prefers-color-scheme). + Used for the dark popup variant, smoke diagnostic overlay, and any + future dark Chrome theme support. */ +.dark, [data-theme="dark"] { + --mks-surface: var(--mks-ink-900); + --mks-surface-raised: var(--mks-ink-800); + --mks-surface-sunken: #11131e; + --mks-surface-inverse: var(--mks-linen-50); + + --mks-fg-1: #ece7dc; + --mks-fg-2: #a4a7b8; + --mks-fg-3: #7a7e94; + --mks-fg-disabled: #5b5f76; + --mks-fg-inverse: var(--mks-ink-900); + + --mks-border: rgba(243, 238, 228, 0.08); + --mks-border-strong: rgba(243, 238, 228, 0.14); + --mks-border-focus: var(--mks-linen-50); + + --mks-shadow-focus: 0 0 0 3px rgba(243, 238, 228, 0.24); +} + +/* ── Semantic typography helpers ────────────────────────────────────── + Apply these classes; do not redefine sizes ad-hoc. */ +.mks-display-1 { + font-family: var(--mks-font-display); + font-size: var(--mks-text-3xl); + line-height: var(--mks-lh-tight); + letter-spacing: var(--mks-tracking-display); + font-weight: var(--mks-weight-regular); + color: var(--mks-fg-1); +} +.mks-display-2 { + font-family: var(--mks-font-display); + font-size: var(--mks-text-2xl); + line-height: var(--mks-lh-tight); + letter-spacing: var(--mks-tracking-display); + font-weight: var(--mks-weight-regular); + color: var(--mks-fg-1); +} +.mks-h1 { + font-family: var(--mks-font-display); + font-size: var(--mks-text-xl); + line-height: var(--mks-lh-tight); + letter-spacing: var(--mks-tracking-tight); + font-weight: var(--mks-weight-regular); + color: var(--mks-fg-1); +} +.mks-h2 { + font-family: var(--mks-font-ui); + font-size: var(--mks-text-lg); + line-height: var(--mks-lh-snug); + font-weight: var(--mks-weight-semibold); + color: var(--mks-fg-1); +} +.mks-h3 { + font-family: var(--mks-font-ui); + font-size: var(--mks-text-md); + line-height: var(--mks-lh-snug); + font-weight: var(--mks-weight-semibold); + color: var(--mks-fg-1); +} +.mks-body { + font-family: var(--mks-font-ui); + font-size: var(--mks-text-base); + line-height: var(--mks-lh-base); + color: var(--mks-fg-1); +} +.mks-body-sm { + font-family: var(--mks-font-ui); + font-size: var(--mks-text-sm); + line-height: var(--mks-lh-base); + color: var(--mks-fg-2); +} +.mks-caption { + font-family: var(--mks-font-ui); + font-size: var(--mks-text-xs); + line-height: var(--mks-lh-snug); + color: var(--mks-fg-3); +} +.mks-eyebrow { + font-family: var(--mks-font-ui); + font-size: var(--mks-text-xs); + line-height: var(--mks-lh-snug); + letter-spacing: var(--mks-tracking-caps); + text-transform: uppercase; + font-weight: var(--mks-weight-semibold); + color: var(--mks-fg-2); +} +.mks-mono { + font-family: var(--mks-font-mono); + font-size: var(--mks-text-sm); + line-height: var(--mks-lh-base); + color: var(--mks-fg-1); +} +.mks-badge-label { + font-family: var(--mks-font-ui); + font-size: var(--mks-text-xs); + line-height: 1; + letter-spacing: var(--mks-tracking-caps); + text-transform: uppercase; + font-weight: var(--mks-weight-bold); +} + +/* Accessibility — honor reduced-motion */ +@media (prefers-reduced-motion: reduce) { + :root { + --mks-dur-fast: 0ms; + --mks-dur-base: 0ms; + --mks-dur-slow: 0ms; + } +}