/* ───────────────────────────────────────────────────────────────────────── Mokosh Design System — tokens.css Single source of truth for foundational tokens. Surfaces: Chrome MV3 popup, welcome page, notification copy, toolbar. Audience: Russian-first operators. Cyrillic coverage required. This file is the engineering working copy of the designer handoff at .planning/intel/design-incoming/system/bundle/mokosh-handoff/tokens.css. Three surgical edits applied for the engineering working copy (Plan 01-12 Wave 1 Task 2): 1. The handoff's PREVIEW-ONLY Google Fonts @import (handoff line 12) is REPLACED with the seven local @font-face rules below — MV3 CSP requires self-hosting (style-src 'self' + font-src 'self'). 2. --mks-font-display value REPLACED from the handoff's serif family to "Lora" per R2 designer reply 2026-05-19 (full Cyrillic coverage via Cyreal foundry; see .planning/intel/brand-decisions-v1-followup-display-font.md). 3. .mks-word class added at end-of-file per mokosh-lockup.svg line 21 + RESEARCH §8. ───────────────────────────────────────────────────────────────────── */ /* ── Self-hosted fonts (MV3 CSP) ── Faces per D-05 with R2 substitution applied (designer reply 2026-05-19; see brand-decisions-v1-followup-display-font.md). Subsetting: all faces are Latin (U+0020-007E + U+00A0-00FF) + Cyrillic basic (U+0400-045F + supplemental code points per scripts/subset-fonts.sh recipe). All OFL-1.1 (LICENSE-Lora.txt + LICENSE-IBM-Plex.txt next to this directory). */ /* Lora variable — display family with full Cyrillic (R2 substitute, see brand-decisions-v1-followup) */ @font-face { font-family: "Lora"; src: url("./fonts/Lora-VariableFont.woff2") format("woff2-variations"), url("./fonts/Lora-VariableFont.woff2") format("woff2"); font-weight: 400 700; font-style: normal; font-display: swap; } @font-face { font-family: "Lora"; src: url("./fonts/Lora-Italic-VariableFont.woff2") format("woff2-variations"), url("./fonts/Lora-Italic-VariableFont.woff2") format("woff2"); font-weight: 400 700; font-style: italic; font-display: swap; } /* IBM Plex Sans — UI body family with full Cyrillic */ @font-face { font-family: "IBM Plex Sans"; src: url("./fonts/IBMPlexSans-Regular.woff2") format("woff2"); font-weight: 400; font-style: normal; font-display: swap; } @font-face { font-family: "IBM Plex Sans"; src: url("./fonts/IBMPlexSans-Medium.woff2") format("woff2"); font-weight: 500; font-style: normal; font-display: swap; } @font-face { font-family: "IBM Plex Sans"; src: url("./fonts/IBMPlexSans-SemiBold.woff2") format("woff2"); font-weight: 600; font-style: normal; font-display: swap; } @font-face { font-family: "IBM Plex Sans"; src: url("./fonts/IBMPlexSans-Bold.woff2") format("woff2"); font-weight: 700; font-style: normal; font-display: swap; } /* IBM Plex Mono — diagnostic / timer family with full Cyrillic */ @font-face { font-family: "IBM Plex Mono"; src: url("./fonts/IBMPlexMono-Regular.woff2") format("woff2"); font-weight: 400; font-style: normal; font-display: swap; } @font-face { font-family: "IBM Plex Mono"; src: url("./fonts/IBMPlexMono-Medium.woff2") format("woff2"); font-weight: 500; font-style: normal; font-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); /* Brand-component stroke — INTENTIONALLY THEME-INDEPENDENT. Used by the welcome-hero mark wrapper (welcome.css .welcome-hero__mark) so the canonical mokosh-mark.svg's `stroke="currentColor"` cascade resolves to linen-50 on BOTH the light AND dark surfaces. The mark sits on a madder-600 circle (--mks-rec) which is theme-independent, so the stroke must be theme-independent too — otherwise the cascade through the semantic --mks-fg-inverse (which flips per theme) gives a muddy ink-on-madder render in dark mode. This token is NOT overridden in the .dark/[data-theme="dark"] block below; it stays linen-50 everywhere. See Plan 04-06 operator-empirical Task 4 verdict + debug session .planning/debug/resolved/04-06-dark-mode-mark-decouple.md. */ --mks-mark-stroke: 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. Lora for display (Cyreal foundry; R2 substitute per designer reply 2026-05-19; full Cyrillic coverage). IBM Plex Sans for UI body (excellent Cyrillic; not Inter/Roboto). IBM Plex Mono for diagnostic / timer overlays. */ --mks-font-display: "Lora", "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 — Lora 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; } } /* ── Lockup wordmark — referenced by mokosh-lockup.svg line 21 ── The SVG inlines class="mks-word" on its element so the engineering wordmark renders with the Lora display family. Per RESEARCH §8 + Plan 01-12 interfaces block. */ .mks-word { font-family: var(--mks-font-display); font-size: 32px; font-weight: var(--mks-weight-regular); letter-spacing: var(--mks-tracking-display); fill: var(--mks-ink-900); }