Skip to main content

ishou_tokens/
lib.rs

1//! ishou (意匠) — the pleme-io house crest.
2//!
3//! A typed design-token vocabulary for the pleme-io visual system. Pure data
4//! structures; rendering lives in `ishou-render`. Consumers never hand-craft
5//! CSS / Tailwind / TUI color tables — they call a renderer and get deterministic
6//! output keyed off this token set.
7//!
8//! Layered:
9//!
10//! - `color` — re-exports the irodori Nord palette + semantic role mapping,
11//!   adds the pleme-io brand monochrome (bold-black / paper-white).
12//! - `typography` — font stacks + modular scale.
13//! - `spacing` — 4px-based spacing scale.
14//! - `radius` — border radius scale.
15//! - `shadow` — elevation layers (Nord-tinted, bold; mirrors the brand).
16//! - `motion` — easing curves + durations (shader-informed).
17//! - `shader` — typed uniforms for the 13 blackmatter-ghostty GLSL shaders.
18//! - `brand` — logo paths, mark variants, swerve geometry.
19//!
20//! The entire token set is reachable from `TokenSet::default()`.
21
22pub mod brand;
23pub mod color;
24pub mod fleet_defaults;
25pub mod fleet_keybinds;
26pub mod fleet_theme;
27pub mod motion;
28pub mod radius;
29pub mod refined;
30pub mod shader;
31pub mod shadow;
32pub mod space;
33pub mod spacing;
34pub mod themed_config;
35pub mod typography;
36
37use serde::Serialize;
38
39pub use brand::Brand;
40pub use color::{ColorPalette, Rgb, SemanticRoles};
41pub use fleet_defaults::FleetDefaults;
42pub use fleet_keybinds::{FleetKeybinds, FleetKeybindsConsumer};
43pub use fleet_theme::{FleetTheme, ResolvedTheme};
44pub use refined::{Bounds, Refined};
45pub use themed_config::{convergence, FleetThemedConfig};
46pub use space::{linear_from_hex, Linear, LinearRgba, Srgb, SrgbA};
47pub use motion::Motion;
48pub use radius::Radius;
49pub use shader::Shaders;
50pub use shadow::{Shadow, ShadowSpec};
51pub use spacing::Spacing;
52pub use typography::Typography;
53
54/// The complete ishou token set. Single source of truth for every render target.
55#[derive(Debug, Clone, Serialize)]
56pub struct TokenSet {
57    pub color: ColorPalette,
58    pub roles: SemanticRoles,
59    pub brand: Brand,
60    pub typography: Typography,
61    pub spacing: Spacing,
62    pub radius: Radius,
63    pub shadow: Shadow,
64    pub motion: Motion,
65    pub shader: Shaders,
66}
67
68impl Default for TokenSet {
69    fn default() -> Self {
70        Self {
71            color: ColorPalette::pleme(),
72            roles: SemanticRoles::pleme_dark(),
73            brand: Brand::pleme(),
74            typography: Typography::pleme(),
75            spacing: Spacing::default(),
76            radius: Radius::default(),
77            shadow: Shadow::default(),
78            motion: Motion::default(),
79            shader: Shaders::default(),
80        }
81    }
82}
83
84impl TokenSet {
85    /// The canonical pleme-io token set. Calls `default()`; kept for clarity
86    /// at call sites (`TokenSet::pleme()` reads better than `TokenSet::default()`).
87    #[must_use]
88    pub fn pleme() -> Self {
89        Self::default()
90    }
91
92    /// Deterministic content hash used by arch-synthesizer attestation.
93    /// Two token sets produce identical hashes iff every token is byte-equal.
94    #[must_use]
95    pub fn content_hash(&self) -> [u8; 32] {
96        let json = serde_json::to_vec(self).expect("token set is always serializable");
97        // Simple Fnv64 twice would do; using a plain sha-like fold here to avoid
98        // pulling blake3 into the pure token crate. Renderer/attestation layer
99        // wraps with BLAKE3 when hooked into arch-synthesizer.
100        let mut out = [0u8; 32];
101        for (i, byte) in json.iter().enumerate() {
102            out[i % 32] ^= byte.wrapping_mul(31).wrapping_add(i as u8);
103        }
104        out
105    }
106}