{
"$schema": "https://design-tokens.github.io/community-group/format/",
"$description": "moss design tokens. Single source of truth for the CSS :root token block; regenerated into src-tauri/src/assets/css/site.css by `cargo run --bin generate-artifacts --features dev-tools -- contract-docs`.",
"$order": ["typography", "color", "code", "syntax", "layout", "spacing"],
"typography": {
"$description": "Font families and sizes",
"moss-font-body": {
"$type": "fontFamily",
"$value": "-apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Moss PingFang SC', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'Noto Sans SC', 'WenQuanYi Micro Hei', sans-serif",
"$description": "Body text font stack. 'Moss PingFang SC' is the weight-pinned PingFang @font-face defined in site.css (see the PingFang weight pin comment there)."
},
"moss-font-heading": {
"$type": "fontFamily",
"$value": "'Iowan Old Style', Athelas, 'Palatino Linotype', Palatino, 'Book Antiqua', 'Songti SC', 'Songti TC', 'STSongti', 'Noto Serif CJK SC', 'Source Han Serif SC', 'NSimSun', 'SimSun', serif",
"$description": "Heading font stack: serif by default for editorial weight"
},
"moss-font-heading-weight": {
"$type": "number",
"$value": "480",
"$description": "Heading font weight. Source: h1-h6 rule in site.css (font-weight: 480)."
},
"moss-font-mono": {
"$type": "fontFamily",
"$value": "ui-monospace, 'Cascadia Code', 'SF Mono', SFMono-Regular, 'JetBrains Mono', Menlo, Consolas, 'Liberation Mono', 'Courier New', monospace",
"$description": "Monospace stack for code"
},
"moss-font-weight-body": {
"$type": "number",
"$value": "320",
"$description": "Default body font weight (renamed from --moss-font-weight in v1.3)"
},
"moss-reading-size-base": {
"$type": "dimension",
"$value": "1.125rem",
"$description": "Body / reading text size. Headings use the --moss-size-lg/-xl/-2xl scale and are unaffected by this token."
},
"moss-reading-size": {
"$type": "dimension",
"$value": "var(--moss-reading-size-base)",
"$description": "Effective reading text size; defaults to --moss-reading-size-base and is adjusted by the reader font-scale control."
},
"moss-size-2xs": {
"$type": "dimension",
"$value": "0.75rem",
"$description": "12px — metadata, captions, chip labels"
},
"moss-size-xs": {
"$type": "dimension",
"$value": "0.875rem",
"$description": "14px"
},
"moss-size-sm": {
"$type": "dimension",
"$value": "1rem",
"$description": "16px"
},
"moss-size-md": {
"$type": "dimension",
"$value": "var(--moss-reading-size-base)",
"$description": "18px reading size — matches --moss-reading-size-base, the body/reading text size"
},
"moss-size-lg": {
"$type": "dimension",
"$value": "1.25rem",
"$description": "20px"
},
"moss-size-xl": {
"$type": "dimension",
"$value": "1.375rem",
"$description": "22px"
},
"moss-size-2xl": {
"$type": "dimension",
"$value": "1.625rem",
"$description": "26px"
},
"moss-size-3xl": {
"$type": "dimension",
"$value": "2rem",
"$description": "32px"
}
},
"color": {
"$description": "Color palette",
"moss-border-light": {
"$type": "color",
"$value": {
"light": "#e6e2db",
"dark": "#332e25"
},
"$description": "Light border color"
},
"moss-border-medium": {
"$type": "color",
"$value": {
"light": "#d1cdc4",
"dark": "#443d32"
},
"$description": "Medium border color"
},
"moss-border-strong": {
"$type": "color",
"$value": {
"light": "#8e8b85",
"dark": "#6f6a61"
},
"$description": "Border for elements whose boundary IS the control — the .moss-input underline. Meets WCAG 1.4.11 non-text contrast (3:1) against the page. Decorative hairlines stay on border-light/medium, which are exempt."
},
"moss-color-accent": {
"$type": "color",
"$value": {
"light": "#2d5a2d",
"dark": "#6a9a5a"
},
"$description": "Links, highlights, accent elements. Dark: lightened forest green (#6a9a5a ≈ 5.3:1 on --moss-color-bg #1c1914) — the raw #2d5a2d is only ~2.2:1 in dark, failing WCAG AA as text/border/icon. #6a9a5a matches the green the codebase already derives for accent-hover/code in dark."
},
"moss-color-accent-hover": {
"$type": "color",
"$value": {
"light": "color-mix(in oklch, var(--moss-color-accent) 85%, black)",
"dark": "color-mix(in oklch, var(--moss-color-accent) 80%, white)"
},
"$description": "Accent color on hover — auto-derived from --moss-color-accent. Light: darkens accent by mixing 85% accent + 15% black (hover = press-down cue). Dark: lightens accent by mixing 80% accent + 20% white (hover = surface lift). Override only if the mix produces a wrong result for a custom palette."
},
"moss-color-accent-quiet": {
"$type": "color",
"$value": {
"light": "rgba(45, 90, 45, 0.28)",
"dark": "rgba(74, 124, 74, 0.4)"
},
"$description": "Quiet accent for ambient indicators (hairlines, tree-row left-borders). ~28% opacity of moss-color-accent. Consumed by the breadcrumb and preview hairlines (ADR-015 Ambient renderer). Ambient only — never a focus indicator: it composites too close to the page to satisfy 1.4.11. Use moss-color-ui-accent for focus."
},
"moss-color-bg": {
"$type": "color",
"$value": {
"light": "#faf8f5",
"dark": "#1c1914"
},
"$description": "Page background"
},
"moss-color-muted": {
"$type": "color",
"$value": {
"light": "#716d69",
"dark": "#9a9080"
},
"$description": "Secondary/muted text. Light value meets 4.5:1 on bg, surface and code backgrounds (WCAG 1.4.3) — it is body text at 14px in ~32 places, not decoration."
},
"moss-color-surface": {
"$type": "color",
"$value": {
"light": "#f4f1ec",
"dark": "#252017"
},
"$description": "Card and surface background"
},
"moss-color-text": {
"$type": "color",
"$value": {
"light": "#2c2825",
"dark": "#d4cbba"
},
"$description": "Primary text"
},
"moss-color-text-secondary": {
"$type": "color",
"$value": {
"light": "#5d5853",
"dark": "#b0a696"
},
"$description": "Secondary text color — darker than --moss-color-muted, used for readable secondary content (nav links, dates, excerpts). Renamed from --moss-text-secondary in v1.3."
},
"moss-color-ui-accent": {
"$type": "color",
"$value": "var(--moss-color-accent)",
"$description": "Accent for navigation, buttons, and site controls (chrome). Defaults to the content accent; set to a neutral (e.g. var(--moss-color-text)) for quiet chrome."
}
},
"code": {
"$description": "Code block colors",
"moss-code-accent-primary": {
"$type": "color",
"$value": {
"light": "#2d5a2d",
"dark": "#6a9a5a"
},
"$description": "Code accent primary — moss green, systems/primary languages. Dark: pinned to #6a9a5a (was color-mix(accent 80%, white)) — since --moss-color-accent now carries its own lightened dark value, re-deriving here would double-lighten the syntax green; pinning keeps code colors stable."
},
"moss-code-accent-quaternary": {
"$type": "color",
"$value": {
"light": "#6b5b4f",
"dark": "#92857a"
},
"$description": "Code accent quaternary — deeper brown, config/data"
},
"moss-code-accent-secondary": {
"$type": "color",
"$value": {
"light": "#5d5853",
"dark": "#b0a696"
},
"$description": "Code accent secondary — warm gray, web languages"
},
"moss-code-accent-tertiary": {
"$type": "color",
"$value": {
"light": "#74706c",
"dark": "#9a9080"
},
"$description": "Code accent tertiary — muted brown, scripting"
},
"moss-code-background": {
"$type": "color",
"$value": {
"light": "#f8f6f3",
"dark": "#221f1a"
},
"$description": "Code block background"
},
"moss-code-border": {
"$type": "color",
"$value": {
"light": "#e0ddd6",
"dark": "#332e25"
},
"$description": "Code block border"
}
},
"syntax": {
"$description": "Syntax highlighting tokens (build-time via syntect). Override in style.css to customize code block colors.",
"moss-hl-addition-bg": {
"$type": "color",
"$value": {
"light": "rgba(74, 106, 42, 0.1)",
"dark": "rgba(138, 186, 106, 0.12)"
},
"$description": "Diff addition background. Note: dark value only appears in data-theme=dark block in site.css; @media prefers-color-scheme:dark block omits it (pre-existing gap, not introduced here)."
},
"moss-hl-attr": {
"$type": "color",
"$value": {
"light": "#5a6a4a",
"dark": "#a0b880"
},
"$description": "Syntax: attribute"
},
"moss-hl-builtin": {
"$type": "color",
"$value": {
"light": "#2d5a2d",
"dark": "#6a9a5a"
},
"$description": "Syntax: builtin"
},
"moss-hl-comment": {
"$type": "color",
"$value": {
"light": "#787064",
"dark": "#8e8578"
},
"$description": "Syntax: comment. Both values meet 4.5:1 on the code background — a comment is text a reader is expected to read, so it is not exempt as decoration."
},
"moss-hl-deletion": {
"$type": "color",
"$value": {
"light": "#8a4a3a",
"dark": "#d08070"
},
"$description": "Syntax: deletion"
},
"moss-hl-deletion-bg": {
"$type": "color",
"$value": {
"light": "rgba(138, 74, 58, 0.1)",
"dark": "rgba(208, 128, 112, 0.12)"
},
"$description": "Diff deletion background. Note: dark value only appears in data-theme=dark block in site.css; @media prefers-color-scheme:dark block omits it (pre-existing gap, not introduced here)."
},
"moss-hl-function": {
"$type": "color",
"$value": {
"light": "#3a5a6a",
"dark": "#7ab0c0"
},
"$description": "Syntax: function"
},
"moss-hl-keyword": {
"$type": "color",
"$value": {
"light": "#7a5834",
"dark": "#d4a06a"
},
"$description": "Syntax: keyword (also used for tags — intentionally shared)"
},
"moss-hl-meta": {
"$type": "color",
"$value": {
"light": "#7c6e5f",
"dark": "#b0a080"
},
"$description": "Syntax: meta"
},
"moss-hl-number": {
"$type": "color",
"$value": {
"light": "#6b5b8a",
"dark": "#b0a0d0"
},
"$description": "Syntax: number"
},
"moss-hl-operator": {
"$type": "color",
"$value": {
"light": "#5d5853",
"dark": "#b0a696"
},
"$description": "Syntax: operator"
},
"moss-hl-string": {
"$type": "color",
"$value": {
"light": "#4a6a2a",
"dark": "#8aba6a"
},
"$description": "Syntax: string"
},
"moss-hl-tag": {
"$type": "color",
"$value": {
"light": "#7a5834",
"dark": "#d4a06a"
},
"$description": "Syntax: tag (same value as moss-hl-keyword — intentionally shared)"
},
"moss-hl-type": {
"$type": "color",
"$value": {
"light": "#8a5a3a",
"dark": "#d0a070"
},
"$description": "Syntax: type"
}
},
"layout": {
"$description": "Content widths and layout",
"$comment": "Do NOT add a `moss-nav-width` token here. The nav reads `var(--moss-nav-width, var(--moss-content-width))` in site.css, so nav-width is an intentional opt-in (unset by default) that lets the nav track --moss-content-width — including per-page content_width=wide/full overrides set on <body>. A `:root` alias `--moss-nav-width: var(--moss-content-width)` freezes at :root's value and breaks the wide preset; the test `test_css_nav_width_not_aliased_in_root` guards against re-adding it.",
"moss-container-padding": {
"$type": "dimension",
"$value": "clamp(1rem, 5vw, 2rem)",
"$description": "Container side padding"
},
"moss-content-width": {
"$type": "dimension",
"$value": "calc(42 * var(--moss-reading-size))",
"$description": "Maximum content width. Font-stable: a multiple of --moss-reading-size (a length), NOT a ch value, so text, inline images, and figures resolve to the same column at any element font-size (a ch measure drifts per-element and desyncs text from figures when a theme changes the prose font). 42 ≈ the prior 67ch for the default font; tracks the scale-* presets via --moss-reading-size."
},
"moss-content-width-sidebar": {
"$type": "dimension",
"$value": "calc(39 * var(--moss-reading-size))",
"$description": "Content width when sidebar is active. Font-stable multiple of --moss-reading-size (≈ prior 62ch); see moss-content-width."
},
"moss-sidebar-width": {
"$type": "dimension",
"$value": "280px",
"$description": "Sidebar width"
},
"moss-site-max-width": {
"$type": "dimension",
"$value": "1200px",
"$description": "Maximum overall site width"
},
"moss-width-wide": {
"$type": "dimension",
"$value": "min(calc(56 * var(--moss-reading-size)), var(--moss-site-max-width))",
"$description": "Width of a data-width=\"wide\" content band (ADR-021 Corollary 2). Font-stable multiple of --moss-reading-size like moss-content-width; the min() clamp is load-bearing — the reader font-scale control scales --moss-reading-size (scale-xlarge = 1.25x), and without the clamp a wide band at xlarge overruns --moss-site-max-width and stops aligning with the nav. data-width=\"page\" reuses --moss-site-max-width directly (it must stay identical to the .container width or the band stops aligning with nav/footer); there is deliberately no second token for it."
}
},
"spacing": {
"$description": "Spacing scale",
"moss-space-xs": {
"$type": "dimension",
"$value": "0.5rem",
"$description": "Extra small (8px)"
},
"moss-space-sm": {
"$type": "dimension",
"$value": "1rem",
"$description": "Small (16px)"
},
"moss-space-md": {
"$type": "dimension",
"$value": "1.5rem",
"$description": "Medium (24px)"
},
"moss-space-lg": {
"$type": "dimension",
"$value": "2rem",
"$description": "Large (32px)"
},
"moss-space-xl": {
"$type": "dimension",
"$value": "3rem",
"$description": "Extra large (48px)"
},
"moss-space-2xl": {
"$type": "dimension",
"$value": "4rem",
"$description": "Double extra large (64px)"
}
}
}