/** Interactive Demo schema v1 — caps & allowlists (brainstorm 2026-07-22). */ export const INTERACTIVE_DEMO_SCHEMA_VERSION = 1 as const export const INTERACTIVE_DEMO_CAPS = { maxScenes: 5, maxActs: 8, maxStepsPerAct: 12, maxAnnotationsPerStep: 5, maxPanelsPerScene: 2, maxJsonBytes: 64 * 1024, } as const export const PATTERN_IDS = [ 'progressiveReveal', 'spotlightTour', 'accumulate', 'compareBeforeAfter', 'chartBuild', 'heatmapFill', 'overview', 'flowTrace', ] as const export const INTENT_IDS = [ 'highlight', 'flow', 'cache', 'compute', 'output', 'warning', ] as const export const SCOPE_IDS = ['transient', 'act', 'scene'] as const export const ANNOTATION_KINDS = ['circle', 'arrow', 'badge', 'callout'] as const export const PANEL_TYPES = ['svg-scene', 'chart', 'heatmap-matrix'] as const export const TRANSITIONS = ['fade', 'cut'] as const export const CHART_TYPES = ['line', 'bar', 'area'] as const /** * Human / locale strings — may contain hex/rgb in prose; changeable by translateDemo. * Must stay in sync between color-scan skip, translate strip, and docs. */ export const HUMAN_STRING_KEYS = [ 'lang', 'speak', 'title', 'text', 'disclaimer', 'label', 'rowLabels', 'colLabels', ] as const export type HumanStringKey = (typeof HUMAN_STRING_KEYS)[number] const HUMAN_STRING_KEY_SET = new Set(HUMAN_STRING_KEYS) export function isHumanStringKey(key: string): boolean { return HUMAN_STRING_KEY_SET.has(key) } /** Hex / rgb color literals forbidden in non-human JSON fields (P11). */ export const FORBIDDEN_COLOR_RE = /#(?:[0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})\b|\brgba?\s*\(/i /** * Future generation-prompt rule (not a validator cap): * speak ≈ 1–2 sentences, ~25 words max — tempo is decided at writing time. */ export const SPEAK_WRITING_RULE = 'speak ≈ 1–2 phrases, ~25 mots max — le tempo de la démo se décide à l’écriture, pas au rendu.'