export const CORE_MACHINE_IDS = [ 'four-stroke-petrol-engine', 'two-stroke-engine', 'diesel-engine', 'v8-engine', 'wankel-rotary-engine', 'steam-engine', 'turbojet-engine', 'turbofan-engine', 'planetary-gearbox', 'differential-gear', 'manual-gearbox-5-speed', 'continuously-variable-transmission', 'worm-gear-drive', 'bevel-gear-set', 'centrifugal-pump', 'gear-pump', 'piston-pump', 'hydraulic-cylinder', 'scotch-yoke', 'geneva-drive', 'cam-and-follower', 'rack-and-pinion', 'slider-crank', 'toggle-clamp', 'ball-bearing', 'roller-bearing', 'disc-brake-caliper', 'turbocharger', ] as const; export type CoreMachineId = (typeof CORE_MACHINE_IDS)[number]; export type DossierCategory = | 'Engines' | 'Gearboxes & Drives' | 'Pumps & Fluid Systems' | 'Mechanisms' | 'Structural / Other'; export type DossierDifficulty = 'Beginner' | 'Intermediate' | 'Advanced'; export type DossierAxis = 'x' | 'y' | 'z'; export type DossierVector3 = readonly [number, number, number]; export type DossierLoopMode = 'continuous' | 'reciprocating' | 'indexed' | 'demonstration'; export interface DossierEngineeringFact { readonly label: string; readonly value: string; readonly details: string; } export interface DossierComponentNode { readonly id: string; readonly name: string; readonly kind: 'assembly' | 'part' | 'effect' | 'control' | 'sensor'; readonly description: string; readonly engineeringRole: string; readonly materialHint: string; readonly labelAnchor: DossierVector3; readonly explodedOffset: DossierVector3; readonly replacementNode: string; readonly animationChannels: readonly string[]; readonly specs?: readonly DossierEngineeringFact[]; readonly children?: readonly DossierComponentNode[]; } export interface DossierLabel { readonly partId: string; readonly text: string; readonly position: DossierVector3; readonly priority: 'primary' | 'secondary' | 'detail'; } export interface DossierCameraPreset { readonly id: string; readonly label: string; readonly position: DossierVector3; readonly target: DossierVector3; readonly description: string; readonly lensMm: number; } export interface DossierTourStep { readonly id: string; readonly title: string; readonly body: string; readonly cameraPresetId: string; readonly highlightedPartIds: readonly string[]; readonly durationSeconds: number; readonly animationTimeScale: number; readonly setExplode: number; readonly crossSection?: { readonly axis: DossierAxis; readonly offset: number; }; } export interface DossierAnimationChannel { readonly id: string; readonly label: string; readonly targetPartIds: readonly string[]; readonly transform: | 'rotation' | 'translation' | 'oscillation' | 'opacity' | 'material' | 'flow' | 'indexing' | 'deformation'; readonly driver: string; readonly expression: string; readonly phaseDeg: number; readonly notes: string; } export interface DossierAnimationModel { readonly nominalRpm: number; readonly cycleSecondsAtNominal: number; readonly loopMode: DossierLoopMode; readonly stepCount: number; readonly primaryDriver: string; readonly engineeringNotes: string; readonly channels: readonly DossierAnimationChannel[]; } export interface DossierExplodedGroup { readonly id: string; readonly label: string; readonly partIds: readonly string[]; readonly axis: DossierAxis; readonly direction: number; readonly order: number; readonly reason: string; } export interface DossierExplodedView { readonly defaultDistance: number; readonly maxDistance: number; readonly groups: readonly DossierExplodedGroup[]; } export interface DossierCrossSectionPlane { readonly id: string; readonly label: string; readonly axis: DossierAxis; readonly offset: number; readonly description: string; } export interface DossierCrossSectionPlan { readonly defaultAxis: DossierAxis; readonly recommendedPlanes: readonly DossierCrossSectionPlane[]; } export interface DossierThumbnailStrategy { readonly cameraPresetId: string; readonly primarySilhouette: readonly string[]; readonly accentParts: readonly string[]; readonly backgroundMotif: string; readonly renderNotes: string; } export interface DossierAssetReplacementPlan { readonly proceduralBlueprintId: CoreMachineId; readonly preferredGlbPath: string; readonly rootNodeName: string; readonly requiredNamedNodes: readonly string[]; readonly optionalNamedNodes: readonly string[]; readonly materialSlots: readonly string[]; readonly coordinateSystem: string; readonly replacementInstructions: string; } export interface MachineDossier { readonly machineId: CoreMachineId; readonly slugAliases: readonly string[]; readonly title: string; readonly category: DossierCategory; readonly difficulty: DossierDifficulty; readonly complexityScore: number; readonly registryKeywords: readonly string[]; readonly oneParagraphDescription: string; readonly learningObjectives: readonly string[]; readonly facts: readonly DossierEngineeringFact[]; readonly componentTree: readonly DossierComponentNode[]; readonly labels: readonly DossierLabel[]; readonly cameraPresets: readonly DossierCameraPreset[]; readonly guidedTour: readonly DossierTourStep[]; readonly animationModel: DossierAnimationModel; readonly explodedView: DossierExplodedView; readonly crossSection: DossierCrossSectionPlan; readonly thumbnail: DossierThumbnailStrategy; readonly assetReplacement: DossierAssetReplacementPlan; readonly relatedMachines: readonly CoreMachineId[]; }