feat: page interactive, démos Play/Step et simulateur Carnot
Ajoute le pipeline PageSpec (validation, rendu, publication /p/{slug}),
les démos TipTap /demo, et le simulateur Carnot (modes frigo/PAC/moteur,
énergie kJ vs puissance W, unités K/°C/°F) avec correctifs d’équations KaTeX.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
62
memento-note/lib/interactive-demo/intent-colors.ts
Normal file
62
memento-note/lib/interactive-demo/intent-colors.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import type { IntentId } from '@/lib/interactive-demo/types'
|
||||
|
||||
/**
|
||||
* Desaturated palette — one set for light, one for dark (P11).
|
||||
* No free hex in demo JSON; app maps intents here.
|
||||
*/
|
||||
export const INTENT_PALETTE_LIGHT: Record<IntentId | 'neutral', string> = {
|
||||
neutral: '#5c5c5c',
|
||||
highlight: '#5a7a9a', // prune / slate-blue
|
||||
flow: '#4a7d68',
|
||||
cache: '#7a6a8a',
|
||||
compute: '#8a6b4a',
|
||||
output: '#4a7a8a',
|
||||
warning: '#9a6548',
|
||||
}
|
||||
|
||||
export const INTENT_PALETTE_DARK: Record<IntentId | 'neutral', string> = {
|
||||
neutral: '#a8a8a8',
|
||||
highlight: '#8aabca',
|
||||
flow: '#7ab89a',
|
||||
cache: '#a898b8',
|
||||
compute: '#c0a080',
|
||||
output: '#7ab0c0',
|
||||
warning: '#d09070',
|
||||
}
|
||||
|
||||
/** Light: ~35% readable on white; dark: ~20% as spec. */
|
||||
export const DIM_OPACITY_LIGHT = 0.35
|
||||
export const DIM_OPACITY_DARK = 0.2
|
||||
|
||||
export function intentColor(
|
||||
intent: IntentId | null | undefined,
|
||||
dark: boolean
|
||||
): string {
|
||||
const palette = dark ? INTENT_PALETTE_DARK : INTENT_PALETTE_LIGHT
|
||||
if (!intent) return palette.neutral
|
||||
return palette[intent] ?? palette.neutral
|
||||
}
|
||||
|
||||
export function spotlightColor(dark: boolean): string {
|
||||
return intentColor('highlight', dark)
|
||||
}
|
||||
|
||||
export function dimOpacity(dark: boolean): number {
|
||||
return dark ? DIM_OPACITY_DARK : DIM_OPACITY_LIGHT
|
||||
}
|
||||
|
||||
export const CIRCLED_NUMBERS = ['①', '②', '③', '④', '⑤', '⑥', '⑦', '⑧', '⑨', '⑩'] as const
|
||||
|
||||
export function badgeGlyph(index: number): string {
|
||||
if (index >= 1 && index <= CIRCLED_NUMBERS.length) {
|
||||
return CIRCLED_NUMBERS[index - 1]!
|
||||
}
|
||||
return String(index)
|
||||
}
|
||||
|
||||
/** Writing rule for generation prompts (not enforced in renderer). */
|
||||
export const SPEAK_WRITING_GUIDE = {
|
||||
maxWordsApprox: 25,
|
||||
sentences: '1–2',
|
||||
note: 'Demo tempo is decided at writing time, not at render.',
|
||||
} as const
|
||||
Reference in New Issue
Block a user