Skip to main content

cvkg_core/
lib.rs

1//! # CVKG Agentic Development Guidelines (v1.2)
2//!
3//! All AI agents contributing to this crate MUST follow ALL seven rules:
4//!
5//! ── Karpathy Guidelines (1–4) ────────────────────────────────────────────
6//! 1. THINK FIRST     — State assumptions. Surface ambiguity. Push back on complexity.
7//! 2. STAY SIMPLE     — Minimum code. No speculative features. No unasked-for abstractions.
8//! 3. BE SURGICAL     — Touch only what's required. Own your orphans. Don't improve neighbors.
9//! 4. VERIFY GOALS    — Turn tasks into checkable criteria. Loop until they pass. Never commit broken.
10//!
11//! ── CVKG Extended Protocols (5–7) ────────────────────────────────────────
12//! 5. TRIPLE-PASS     — Read the target, its surrounding context, and its full call graph
13//                      at least THREE TIMES before making any edit or revision.
14//! 6. COMMENT ALL     — Every major pub fn, unsafe block, and non-trivial algorithm in
15//                      every .rs/.ts/.h/.wgsl file MUST have a descriptive doc comment.
16//                      Comments describe WHY and WHAT CONTRACT, not HOW mechanically.
17//! 7. MONITOR LOOPS   — Check every tool call / command for progress every 30 seconds.
18//                      After 3 consecutive identical failures, stop, write BLOCKED.md,
19//                      and move to unblocked work. Never silently accept a broken state.
20//!
21//! Sources:
22//   Karpathy: https://github.com/multica-ai/andrej-karpathy-skills
23//   CVKG Extended: Section 2 of the CVKG Design Specification
24
25//! The View trait is the fundamental building block of CVKG. Every UI element — from a plain text label
26//! to a complex navigation controller — is a View. The trait is intentionally minimal; complexity emerges
27//! through modifier composition.
28//!
29//! # Conformance rules:
30//! 1. `body()` must be pure and side-effect free
31//! 2. Primitive views use `Never` as `Body` and register a `PaintCommand` directly with the scene graph
32//! 3. `View` types must implement `Send` but not necessarily `Sync`, enabling safe multi-threaded layout passes
33
34use serde::{Deserialize, Serialize};
35use std::collections::HashMap;
36use std::str::FromStr;
37
38pub mod error_types;
39
40pub mod security;
41
42/// Error state for fault isolation at the component level.
43#[derive(Clone, Debug, Default, serde::Serialize, serde::Deserialize)]
44pub struct ComponentErrorState {
45    pub has_error: bool,
46    pub error_message: Option<String>,
47    pub error_location: Option<String>,
48}
49impl ComponentErrorState {
50    pub fn clear() -> Self {
51        Self::default()
52    }
53
54    pub fn error(message: impl Into<String>, location: impl Into<String>) -> Self {
55        Self {
56            has_error: true,
57            error_message: Some(message.into()),
58            error_location: Some(location.into()),
59        }
60    }
61}
62
63/// Knowledge state for the agentic memory system.
64#[derive(Clone, Debug, Default, serde::Serialize, serde::Deserialize)]
65pub struct KnowledgeState {
66    pub thoughts: Vec<String>,
67    pub actions: Vec<String>,
68    pub context: HashMap<String, String>,
69    pub last_query_results: Vec<KnowledgeId>,
70    #[serde(alias = "items")]
71    pub fragments: std::collections::HashMap<KnowledgeId, KnowledgeFragment>,
72    /// The Temporal Graph nodes
73    pub nodes: Vec<TemporalNode>,
74    /// The Temporal Graph edges
75    pub edges: Vec<TemporalEdge>,
76    /// The current operational Realm (Midgard/Asgard)
77    pub realm: Realm,
78    /// Last known pointer position (X, Y)
79    pub last_pointer_pos: [f32; 2],
80    /// Resolved pointer velocity (pixels per frame)
81    pub pointer_velocity: [f32; 2],
82    /// The current 'Focus' node ID (Odin's Eye focus)
83    pub odin_focus: Option<String>,
84    /// Agent attention heatmap (node_id -> intensity)
85    pub agent_attention: HashMap<String, f32>,
86    // Component state storage for dynamic state
87    #[serde(skip)]
88    pub component_states: HashMap<u64, Arc<std::sync::RwLock<dyn std::any::Any + Send + Sync>>>,
89}
90
91impl KnowledgeState {
92    /// Apply activation decay to all temporal nodes and evolving components.
93    /// Nodes with weight below a threshold drift out of the primary context.
94    /// Components lose vitality (Fafnir's Decay) if not actively 'fed'.
95    pub fn apply_decay(&mut self, decay_factor: f32) {
96        for node in &mut self.nodes {
97            node.weight *= decay_factor;
98        }
99
100        // Fafnir's Decay: Components naturally revert to base state over time
101        for state in self.component_states.values() {
102            if let Ok(mut lock) = state.write()
103                && let Some(v) = lock.downcast_mut::<f32>() {
104                    *v = (*v * decay_factor).max(1.0);
105                }
106        }
107    }
108
109    /// Increase the importance weight of nodes associated with a successful task.
110    pub fn reinforce(&mut self, node_ids: &[String], boost: f32) {
111        for node in &mut self.nodes {
112            if node_ids.contains(&node.id) {
113                node.weight += boost;
114            }
115        }
116    }
117
118    /// Update pointer kinematics based on a new position.
119    pub fn update_pointer(&mut self, new_pos: [f32; 2]) {
120        self.pointer_velocity = [
121            new_pos[0] - self.last_pointer_pos[0],
122            new_pos[1] - self.last_pointer_pos[1],
123        ];
124        self.last_pointer_pos = new_pos;
125    }
126}
127// Knowledge System Types
128/// Unique identifier for knowledge fragments
129pub type KnowledgeId = String;
130
131/// A knowledge fragment stored in the memory system
132#[derive(Debug, Clone, Serialize, Deserialize)]
133pub struct KnowledgeFragment {
134    /// Unique identifier for this fragment
135    pub id: String,
136    /// Short summary for prompt injection and quick search
137    pub summary: String,
138    /// Reference source (e.g. filename, URL, or conversation ID)
139    pub source: String,
140    /// Frame number or timestamp of creation
141    pub created_at: u64,
142    /// Number of times this fragment has been retrieved
143    pub accessed_count: u32,
144    /// Full content (optional, can be loaded on-demand)
145    pub content: Option<String>,
146}
147
148impl KnowledgeFragment {
149    pub fn new(id: String, summary: String, source: String) -> Self {
150        Self {
151            id,
152            summary,
153            source,
154            created_at: 0,
155            accessed_count: 0,
156            content: None,
157        }
158    }
159}
160
161/// Memory layers for the layered cognitive engine
162#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
163pub enum MemoryLayer {
164    /// Raw mission events (short-term)
165    Episodic,
166    /// Extracted facts and tactical intelligence (long-term)
167    Semantic,
168    /// Successful command sequences and tool chains
169    Procedural,
170}
171
172/// The operational Realm of the UI.
173/// Midgard: Classic, functional, 2D tactical UI for mortals.
174/// Asgard: High-fidelity, cognitive, shader-heavy UI for the Singularity.
175#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
176#[derive(Default)]
177pub enum Realm {
178    Midgard,
179    #[default]
180    Asgard,
181}
182
183
184/// A node in the Temporal Graph representing a cognitive anchor
185#[derive(Debug, Clone, Serialize, Deserialize)]
186pub struct TemporalNode {
187    /// Unique identifier for this node
188    pub id: String,
189    /// ID of the underlying knowledge fragment
190    pub fragment_id: KnowledgeId,
191    /// Timestamp of the event
192    pub timestamp: u64,
193    /// The memory layer this node belongs to
194    pub layer: MemoryLayer,
195    /// Importance weight for activation decay and retrieval
196    pub weight: f32,
197}
198
199/// An edge in the Temporal Graph representing a relationship between nodes
200#[derive(Debug, Clone, Serialize, Deserialize)]
201pub struct TemporalEdge {
202    /// Source node ID
203    pub source: String,
204    /// Target node ID
205    pub target: String,
206    /// Type of relationship (e.g. "causal", "semantic", "temporal")
207    pub relation: String,
208    /// Weight/strength of the connection
209    pub weight: f32,
210}
211
212#[derive(Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
213pub struct AssetKey(pub String);
214
215impl EnvKey for AssetKey {
216    type Value = Arc<dyn AssetManager>;
217    fn default_value() -> Self::Value {
218        Arc::new(DefaultAssetManager::new())
219    }
220}
221
222/// Asset state for async resource loading.
223#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
224pub enum AssetState<T> {
225    Loading,
226    Ready(T),
227    Error(String),
228}
229
230/// Design token value that can adapt to light/dark mode
231#[derive(Debug, Clone, Serialize, Deserialize)]
232#[serde(untagged)]
233pub enum TokenValue {
234    /// Single value (same for light and dark)
235    Single { value: String },
236    /// Different values for light and dark mode
237    Adaptive { light: String, dark: String },
238}
239
240/// YggdrasilTokens is the authoritative container for all design tokens in the CVKG ecosystem.
241#[derive(Debug, Clone, Serialize, Deserialize)]
242pub struct YggdrasilTokens {
243    pub color: HashMap<String, TokenValue>,
244    pub font: HashMap<String, TokenValue>,
245    pub spacing: HashMap<String, TokenValue>,
246    pub radius: HashMap<String, TokenValue>,
247    pub shadow: HashMap<String, TokenValue>,
248    pub border: HashMap<String, TokenValue>,
249    pub anim: HashMap<String, TokenValue>,
250    pub bifrost: HashMap<String, TokenValue>,
251    pub gungnir: HashMap<String, TokenValue>,
252    pub mjolnir: HashMap<String, TokenValue>,
253    pub accessibility: HashMap<String, TokenValue>,
254}
255
256impl Default for YggdrasilTokens {
257    fn default() -> Self {
258        Self::new()
259    }
260}
261
262
263
264impl YggdrasilTokens {
265    pub fn new() -> Self {
266        Self {
267            color: HashMap::new(),
268            font: HashMap::new(),
269            spacing: HashMap::new(),
270            radius: HashMap::new(),
271            shadow: HashMap::new(),
272            border: HashMap::new(),
273            anim: HashMap::new(),
274            bifrost: HashMap::new(),
275            gungnir: HashMap::new(),
276            mjolnir: HashMap::new(),
277            accessibility: HashMap::new(),
278        }
279    }
280
281    /// Get a color token value for the current mode
282    pub fn get_color(&self, key: &str, is_dark: bool) -> Option<String> {
283        self.color.get(key).map(|token| match token {
284            TokenValue::Single { value } => value.clone(),
285            TokenValue::Adaptive { light, dark } => {
286                if is_dark {
287                    dark.clone()
288                } else {
289                    light.clone()
290                }
291            }
292        })
293    }
294
295    /// Get a token value of any type and parse it into the target type
296    pub fn get<T: FromStr>(&self, category: &str, key: &str, is_dark: bool) -> Option<T> {
297        let map = match category {
298            "color" => &self.color,
299            "font" => &self.font,
300            "spacing" => &self.spacing,
301            "radius" => &self.radius,
302            "shadow" => &self.shadow,
303            "border" => &self.border,
304            "anim" => &self.anim,
305            "bifrost" => &self.bifrost,
306            "gungnir" => &self.gungnir,
307            "mjolnir" => &self.mjolnir,
308            "accessibility" => &self.accessibility,
309            _ => return None,
310        };
311
312        map.get(key).and_then(|token| match token {
313            TokenValue::Single { value } => value.parse().ok(),
314            TokenValue::Adaptive { light, dark } => {
315                let value = if is_dark { dark } else { light };
316                value.parse().ok()
317            }
318        })
319    }
320}
321
322pub trait View: Sized + Send {
323    /// The concrete type produced after applying modifiers.
324    /// For primitive views this is Self.
325    type Body: View;
326
327    fn body(self) -> Self::Body;
328
329    /// Render this view into the provided renderer at the specified bounds.
330    /// Primitive views override this to perform drawing operations.
331    fn render(&self, _renderer: &mut dyn Renderer, _rect: Rect) {}
332
333    /// Calculate the natural (intrinsic) size of this view given proposed constraints.
334    /// This allows views like Buttons or Labels to inform the layout engine of their needs.
335    fn intrinsic_size(&self, _renderer: &mut dyn Renderer, _proposal: SizeProposal) -> Size {
336        Size::ZERO
337    }
338
339    /// Optionally provide a layout implementation for this view.
340    fn layout(&self) -> Option<&dyn layout::LayoutView> {
341        None
342    }
343
344    /// Returns the flex weight of this view for proportional distribution in stacks.
345    fn flex_weight(&self) -> f32 {
346        0.0
347    }
348
349    /// Provided modifier entry point
350    fn modifier<M: ViewModifier>(self, m: M) -> ModifiedView<Self, M> {
351        ModifiedView::new(self, m)
352    }
353
354    /// Apply a Bifrost (Frosted Glass) effect to the view
355    fn bifrost(
356        self,
357        blur: f32,
358        saturation: f32,
359        opacity: f32,
360    ) -> ModifiedView<Self, BifrostModifier> {
361        self.modifier(BifrostModifier {
362            blur,
363            saturation,
364            opacity,
365        })
366    }
367
368    /// Apply a Gungnir (Neon Glow) effect to the view
369    fn gungnir(
370        self,
371        color: impl Into<String>,
372        radius: f32,
373        intensity: f32,
374    ) -> ModifiedView<Self, GungnirModifier> {
375        self.modifier(GungnirModifier {
376            color: color.into(),
377            radius,
378            intensity,
379        })
380    }
381
382    /// Apply a Mjolnir Slice (Geometric cut) to the view
383    fn mjolnir_slice(self, angle: f32, offset: f32) -> ModifiedView<Self, MjolnirSliceModifier> {
384        self.modifier(MjolnirSliceModifier { angle, offset })
385    }
386
387    /// Apply a Mjolnir Shatter (Fragmented transition) to the view
388    fn mjolnir_shatter(
389        self,
390        pieces: u32,
391        force: f32,
392    ) -> ModifiedView<Self, MjolnirShatterModifier> {
393        self.modifier(MjolnirShatterModifier { pieces, force })
394    }
395
396    /// Mark this view as a Bifrost Bridge (Shared Element) for cross-view persistence
397    fn bifrost_bridge(self, id: impl Into<String>) -> ModifiedView<Self, BifrostBridgeModifier> {
398        self.modifier(BifrostBridgeModifier { id: id.into() })
399    }
400
401    /// Add a background color to this view
402    fn background(self, color: [f32; 4]) -> ModifiedView<Self, BackgroundModifier> {
403        self.modifier(BackgroundModifier { color })
404    }
405
406    /// Add padding to this view
407    fn padding(self, amount: f32) -> ModifiedView<Self, PaddingModifier> {
408        self.modifier(PaddingModifier { amount })
409    }
410
411    /// Set the opacity (alpha) of this view in the range [0.0, 1.0].
412    fn opacity(self, opacity: f32) -> ModifiedView<Self, OpacityModifier> {
413        self.modifier(OpacityModifier {
414            opacity: opacity.clamp(0.0, 1.0),
415        })
416    }
417
418    /// Override the foreground (text / icon) color of this view.
419    fn foreground_color(self, color: [f32; 4]) -> ModifiedView<Self, ForegroundColorModifier> {
420        self.modifier(ForegroundColorModifier { color })
421    }
422
423    /// Constrain this view to an explicit width and/or height.
424    fn frame(self, width: Option<f32>, height: Option<f32>) -> ModifiedView<Self, FrameModifier> {
425        self.modifier(FrameModifier { width, height })
426    }
427
428    /// Give this view a flex weight for proportional space distribution in stacks.
429    fn flex(self, weight: f32) -> ModifiedView<Self, FlexModifier> {
430        self.modifier(FlexModifier { weight })
431    }
432
433    /// Automatically add padding to avoid overlapping with platform safe areas (notches, bars).
434    fn safe_area_padding(self) -> ModifiedView<Self, SafeAreaModifier> {
435        self.modifier(SafeAreaModifier { ignores: false })
436    }
437
438    /// Explicitly ignore platform safe areas and draw into the margins.
439    fn ignores_safe_area(self) -> ModifiedView<Self, SafeAreaModifier> {
440        self.modifier(SafeAreaModifier { ignores: true })
441    }
442
443    /// Clip all child drawing to this view's bounds.
444    fn clip_to_bounds(self) -> ModifiedView<Self, ClipModifier> {
445        self.modifier(ClipModifier)
446    }
447
448    /// Draw a colored border around this view.
449    fn border(self, color: [f32; 4], width: f32) -> ModifiedView<Self, BorderModifier> {
450        self.modifier(BorderModifier { color, width })
451    }
452
453    /// Add elevation (shadow) to the view. Level determines the shadow depth.
454    fn elevation(self, level: f32) -> ModifiedView<Self, ElevationModifier> {
455        self.modifier(ElevationModifier { level })
456    }
457
458    /// Add a magnetic effect that pulls the view towards the cursor.
459    fn magnetic(self, radius: f32, intensity: f32) -> ModifiedView<Self, MagneticModifier> {
460        self.modifier(MagneticModifier { radius, intensity })
461    }
462
463    /// Add a ManiGlow (Lunar Illuminator) effect that glows near the cursor.
464    fn mani_glow(self, color: [f32; 4], radius: f32) -> ModifiedView<Self, ManiGlowModifier> {
465        self.modifier(ManiGlowModifier { color, radius })
466    }
467
468    /// Theme this view based on a specific memory layer.
469    fn memory_layer(self, layer: MemoryLayer) -> ModifiedView<Self, BifrostLayerModifier> {
470        self.modifier(BifrostLayerModifier { layer })
471    }
472
473    /// Enable Fafnir's Evolution: The component grows and glows as it is used.
474    fn fafnir_evolve(self, id: u64) -> ModifiedView<Self, FafnirModifier> {
475        self.modifier(FafnirModifier { id })
476    }
477
478    /// Enable Mimir's Intent: The component anticipates user interaction via pointer kinematics.
479    fn mimir_intent(self) -> ModifiedView<Self, MimirIntentModifier> {
480        self.modifier(MimirIntentModifier)
481    }
482
483    /// Enable Kvasir's Vibes: Subconscious telemetry representing cognitive complexity.
484    fn kvasir_vibes(self, complexity: f32) -> ModifiedView<Self, KvasirVibeModifier> {
485        self.modifier(KvasirVibeModifier { complexity })
486    }
487
488    /// Bestow Odin's Eye: Global omniscient observability layer.
489    fn odins_eye(self) -> ModifiedView<Self, OdinsEyeModifier> {
490        self.modifier(OdinsEyeModifier)
491    }
492
493    /// Trigger an action when the view appears
494    fn on_appear<F: Fn() + Send + Sync + 'static>(
495        self,
496        action: F,
497    ) -> ModifiedView<Self, LifecycleModifier> {
498        self.modifier(LifecycleModifier {
499            on_appear: Some(Arc::new(action)),
500            on_disappear: None,
501        })
502    }
503
504    /// Trigger an action when the view disappears
505    fn on_disappear<F: Fn() + Send + Sync + 'static>(
506        self,
507        action: F,
508    ) -> ModifiedView<Self, LifecycleModifier> {
509        self.modifier(LifecycleModifier {
510            on_appear: None,
511            on_disappear: Some(Arc::new(action)),
512        })
513    }
514
515    /// Trigger an action when the view is clicked
516    fn on_click<F: Fn() + Send + Sync + 'static>(
517        self,
518        action: F,
519    ) -> ModifiedView<Self, OnClickModifier> {
520        self.modifier(OnClickModifier {
521            action: Arc::new(action),
522        })
523    }
524
525    /// Trigger an action when the pointer enters the view bounds
526    fn on_pointer_enter<F: Fn() + Send + Sync + 'static>(
527        self,
528        action: F,
529    ) -> ModifiedView<Self, OnPointerEnterModifier> {
530        self.modifier(OnPointerEnterModifier {
531            action: Arc::new(action),
532        })
533    }
534
535    /// Trigger an action when the pointer leaves the view bounds
536    fn on_pointer_leave<F: Fn() + Send + Sync + 'static>(
537        self,
538        action: F,
539    ) -> ModifiedView<Self, OnPointerLeaveModifier> {
540        self.modifier(OnPointerLeaveModifier {
541            action: Arc::new(action),
542        })
543    }
544
545    /// Trigger an action when the pointer moves inside the view bounds
546    fn on_pointer_move<F: Fn(f32, f32) + Send + Sync + 'static>(
547        self,
548        action: F,
549    ) -> ModifiedView<Self, OnPointerMoveModifier> {
550        self.modifier(OnPointerMoveModifier {
551            action: Arc::new(action),
552        })
553    }
554
555    /// Trigger an action when the pointer is pressed down
556    fn on_pointer_down<F: Fn() + Send + Sync + 'static>(
557        self,
558        action: F,
559    ) -> ModifiedView<Self, OnPointerDownModifier> {
560        self.modifier(OnPointerDownModifier {
561            action: Arc::new(action),
562        })
563    }
564
565    /// Trigger an action when the pointer is released
566    fn on_pointer_up<F: Fn() + Send + Sync + 'static>(
567        self,
568        action: F,
569    ) -> ModifiedView<Self, OnPointerUpModifier> {
570        self.modifier(OnPointerUpModifier {
571            action: Arc::new(action),
572        })
573    }
574
575    /// Type-erase this view into AnyView
576    fn erase(self) -> AnyView
577    where
578        Self: Clone + 'static,
579    {
580        AnyView::new(self)
581    }
582}
583
584/// An object-safe version of the View trait for type erasure.
585pub trait ErasedView: Send {
586    fn render_erased(&self, renderer: &mut dyn Renderer, rect: Rect);
587    fn name(&self) -> &'static str;
588    fn flex_weight_erased(&self) -> f32;
589    fn layout_erased(&self) -> Option<&dyn layout::LayoutView>;
590    fn clone_box(&self) -> Box<dyn ErasedView>;
591}
592
593impl<V: View + Clone + 'static> ErasedView for V {
594    fn render_erased(&self, renderer: &mut dyn Renderer, rect: Rect) {
595        self.render(renderer, rect);
596    }
597
598    fn name(&self) -> &'static str {
599        std::any::type_name::<V>()
600    }
601
602    fn flex_weight_erased(&self) -> f32 {
603        self.flex_weight()
604    }
605
606    fn layout_erased(&self) -> Option<&dyn layout::LayoutView> {
607        self.layout()
608    }
609
610    fn clone_box(&self) -> Box<dyn ErasedView> {
611        Box::new(self.clone())
612    }
613}
614
615/// A view that memoizes its rendering based on a stable ID and data hash.
616/// The renderer can use this to skip re-rendering the sub-tree if the data hasn't changed.
617pub struct MemoView<V, F> {
618    id: u64,
619    data_hash: u64,
620    builder: F,
621    _v: std::marker::PhantomData<V>,
622}
623
624impl<V: View, F: Fn() -> V + Send + Sync> MemoView<V, F> {
625    /// Create a new MemoView with a stable ID and a data hash.
626    pub fn new(id: u64, data_hash: u64, builder: F) -> Self {
627        Self {
628            id,
629            data_hash,
630            builder,
631            _v: std::marker::PhantomData,
632        }
633    }
634}
635
636impl<V: View + 'static, F: Fn() -> V + Send + Sync + 'static> View for MemoView<V, F> {
637    type Body = Never;
638    fn body(self) -> Self::Body {
639        unreachable!("MemoView does not have a body")
640    }
641
642    fn render(&self, renderer: &mut dyn Renderer, rect: Rect) {
643        renderer.memoize(self.id, self.data_hash, &|r| {
644            let view = (self.builder)();
645            view.render(r, rect);
646        });
647    }
648}
649
650/// A type-erased View wrapper.
651pub struct AnyView {
652    inner: Box<dyn ErasedView>,
653}
654
655impl Clone for AnyView {
656    fn clone(&self) -> Self {
657        Self {
658            inner: self.inner.clone_box(),
659        }
660    }
661}
662
663impl AnyView {
664    pub fn new<V: View + Clone + 'static>(view: V) -> Self {
665        Self {
666            inner: Box::new(view),
667        }
668    }
669}
670
671impl View for AnyView {
672    type Body = Never;
673    fn body(self) -> Self::Body {
674        unreachable!()
675    }
676
677    fn render(&self, renderer: &mut dyn Renderer, rect: Rect) {
678        renderer.push_vnode(rect, self.inner.name());
679        self.inner.render_erased(renderer, rect);
680        renderer.pop_vnode();
681    }
682
683    fn flex_weight(&self) -> f32 {
684        self.inner.flex_weight_erased()
685    }
686
687    fn layout(&self) -> Option<&dyn layout::LayoutView> {
688        self.inner.layout_erased()
689    }
690}
691
692/// BifrostBridgeModifier enables shared-element transitions.
693/// When two views share the same Bifrost Bridge ID, the Sleipnir solver will
694/// interpolate their geometry and effects (blur, glow) during the transition.
695#[derive(Debug, Clone, PartialEq)]
696pub struct BifrostBridgeModifier {
697    pub id: String,
698}
699
700impl ViewModifier for BifrostBridgeModifier {
701    fn modify<V: View>(self, content: V) -> impl View {
702        ModifiedView::new(content, self)
703    }
704
705    fn render(&self, renderer: &mut dyn Renderer, rect: Rect) {
706        // Register this element with the renderer for shared-element transition logic
707        renderer.register_shared_element(&self.id, rect);
708    }
709}
710
711/// MjolnirSliceModifier implements the "Geometric Slice" aesthetic.
712/// It uses a signed distance field (SDF) to clip the view along a sharp angled line.
713#[derive(Debug, Clone, Copy, PartialEq)]
714pub struct MjolnirSliceModifier {
715    pub angle: f32,
716    pub offset: f32,
717}
718
719impl ViewModifier for MjolnirSliceModifier {
720    fn modify<V: View>(self, content: V) -> impl View {
721        ModifiedView::new(content, self)
722    }
723
724    fn render(&self, renderer: &mut dyn Renderer, _rect: Rect) {
725        renderer.push_mjolnir_slice(self.angle, self.offset);
726    }
727
728    fn post_render(&self, renderer: &mut dyn Renderer, _rect: Rect) {
729        renderer.pop_mjolnir_slice();
730    }
731}
732
733/// MjolnirShatterModifier implements the "Shattering" effect.
734/// It breaks the view into discrete geometric fragments that can be animated.
735#[derive(Debug, Clone, Copy, PartialEq)]
736pub struct MjolnirShatterModifier {
737    pub pieces: u32,
738    pub force: f32,
739}
740
741impl ViewModifier for MjolnirShatterModifier {
742    fn modify<V: View>(self, content: V) -> impl View {
743        ModifiedView::new(content, self)
744    }
745
746    fn render_view<V: View>(&self, view: &V, renderer: &mut dyn Renderer, rect: Rect) {
747        // RADIAL SHATTER: Fragment the view into wedges
748        let pieces = self.pieces.max(1);
749        for i in 0..pieces {
750            let progress = i as f32 / pieces as f32;
751            let next_progress = (i + 1) as f32 / pieces as f32;
752
753            let angle_start = progress * 360.0;
754            let angle_end = next_progress * 360.0;
755
756            // Wedge slice: intersection of two half-planes
757            renderer.push_mjolnir_slice(angle_start, 0.0);
758            renderer.push_mjolnir_slice(angle_end + 180.0, 0.0);
759
760            // Apply radial force offset
761            let mid_angle = (angle_start + angle_end) / 2.0;
762            let rad = mid_angle.to_radians();
763            let dx = rad.cos() * self.force;
764            let dy = rad.sin() * self.force;
765
766            let shard_rect = Rect {
767                x: rect.x + dx,
768                y: rect.y + dy,
769                ..rect
770            };
771
772            view.render(renderer, shard_rect);
773
774            renderer.pop_mjolnir_slice();
775            renderer.pop_mjolnir_slice();
776        }
777    }
778}
779
780/// BifrostModifier implements the Cyberpunk "Frosted Glass" aesthetic.
781/// It triggers backdrop blurring and light scattering in the render pipeline.
782#[derive(Debug, Clone, Copy, PartialEq)]
783pub struct BifrostModifier {
784    pub blur: f32,
785    pub saturation: f32,
786    pub opacity: f32,
787}
788
789impl ViewModifier for BifrostModifier {
790    fn modify<V: View>(self, content: V) -> impl View {
791        ModifiedView::new(content, self)
792    }
793
794    fn render(&self, renderer: &mut dyn Renderer, rect: Rect) {
795        if renderer.is_over_budget() {
796            // Degrade: Use lower quality (half blur) if over budget
797            renderer.bifrost(rect, self.blur * 0.5, self.saturation, self.opacity);
798        } else {
799            renderer.bifrost(rect, self.blur, self.saturation, self.opacity);
800        }
801    }
802}
803
804/// A modifier that adds a background color to a view.
805#[derive(Debug, Clone, Copy, PartialEq)]
806pub struct BackgroundModifier {
807    pub color: [f32; 4],
808}
809
810impl ViewModifier for BackgroundModifier {
811    fn modify<V: View>(self, content: V) -> impl View {
812        ModifiedView::new(content, self)
813    }
814
815    fn render(&self, renderer: &mut dyn Renderer, rect: Rect) {
816        renderer.fill_rect(rect, self.color);
817    }
818}
819
820/// A modifier that adds padding to a view.
821#[derive(Debug, Clone, Copy, PartialEq)]
822pub struct PaddingModifier {
823    pub amount: f32,
824}
825
826impl ViewModifier for PaddingModifier {
827    fn modify<V: View>(self, content: V) -> impl View {
828        ModifiedView::new(content, self)
829    }
830
831    fn transform_rect(&self, rect: Rect) -> Rect {
832        Rect {
833            x: rect.x + self.amount,
834            y: rect.y + self.amount,
835            width: (rect.width - 2.0 * self.amount).max(0.0),
836            height: (rect.height - 2.0 * self.amount).max(0.0),
837        }
838    }
839
840    fn transform_proposal(&self, mut proposal: SizeProposal) -> SizeProposal {
841        if let Some(w) = proposal.width {
842            proposal.width = Some((w - 2.0 * self.amount).max(0.0));
843        }
844        if let Some(h) = proposal.height {
845            proposal.height = Some((h - 2.0 * self.amount).max(0.0));
846        }
847        proposal
848    }
849
850    fn transform_size(&self, mut size: Size) -> Size {
851        size.width += 2.0 * self.amount;
852        size.height += 2.0 * self.amount;
853        size
854    }
855}
856
857/// GungnirModifier implements the "Neon Glow" aesthetic.
858/// It uses additive blending and multi-pass blurring to simulate glowing light.
859#[derive(Debug, Clone, PartialEq)]
860pub struct GungnirModifier {
861    pub color: String,
862    pub radius: f32,
863    pub intensity: f32,
864}
865
866impl ViewModifier for GungnirModifier {
867    fn modify<V: View>(self, content: V) -> impl View {
868        ModifiedView::new(content, self)
869    }
870
871    fn render(&self, renderer: &mut dyn Renderer, rect: Rect) {
872        // Neon Glow using Mode 1 in the Surtr pipeline
873        renderer.stroke_rect(rect, [0.0, 1.0, 1.0, self.intensity], self.radius / 10.0);
874    }
875}
876
877/// GungnirPulseModifier implements a "breathing" neon effect.
878#[derive(Debug, Clone, Copy, PartialEq)]
879pub struct GungnirPulseModifier {
880    pub color: [f32; 4],
881    pub radius: f32,
882    pub speed: f32,
883}
884
885impl ViewModifier for GungnirPulseModifier {
886    fn modify<V: View>(self, content: V) -> impl View {
887        ModifiedView::new(content, self)
888    }
889
890    fn render(&self, renderer: &mut dyn Renderer, rect: Rect) {
891        let time = std::time::SystemTime::now()
892            .duration_since(std::time::UNIX_EPOCH)
893            .unwrap_or_default()
894            .as_secs_f32();
895
896        // Mode 19: Dashed Border
897        // Mode 20: 9-Slice / Patch Scaling
898        let intensity = (time * self.speed).sin() * 0.5 + 0.5;
899        let mut color = self.color;
900        color[3] *= intensity;
901
902        // Mode 1 neon glow with dynamic intensity
903        renderer.stroke_rect(rect, color, self.radius);
904    }
905}
906
907/// MagneticModifier makes a view "magnetic", subtly leaning towards or pulling the cursor.
908/// Inspired by high-fidelity creative studio UIs.
909#[derive(Debug, Clone, Copy, PartialEq)]
910pub struct MagneticModifier {
911    pub radius: f32,
912    pub intensity: f32,
913}
914
915impl ViewModifier for MagneticModifier {
916    fn modify<V: View>(self, content: V) -> impl View {
917        ModifiedView::new(content, self)
918    }
919
920    fn render_view<V: View>(&self, view: &V, renderer: &mut dyn Renderer, rect: Rect) {
921        let [px, py] = renderer.get_pointer_position();
922        let center_x = rect.x + rect.width / 2.0;
923        let center_y = rect.y + rect.height / 2.0;
924
925        let dx = px - center_x;
926        let dy = py - center_y;
927        let dist = (dx * dx + dy * dy).sqrt();
928
929        let mut offset_x = 0.0;
930        let mut offset_y = 0.0;
931
932        if dist < self.radius && dist > 0.0 {
933            let force = (1.0 - dist / self.radius) * self.intensity;
934            offset_x = dx * force;
935            offset_y = dy * force;
936        }
937
938        let magnetic_rect = Rect {
939            x: rect.x + offset_x,
940            y: rect.y + offset_y,
941            ..rect
942        };
943
944        view.render(renderer, magnetic_rect);
945    }
946}
947
948/// ManiGlowModifier adds a soft, lunar-like cursor glow to a view.
949/// Named after Máni, the personification of the Moon.
950#[derive(Debug, Clone, Copy, PartialEq)]
951pub struct ManiGlowModifier {
952    pub color: [f32; 4],
953    pub radius: f32,
954}
955
956impl ViewModifier for ManiGlowModifier {
957    fn modify<V: View>(self, content: V) -> impl View {
958        ModifiedView::new(content, self)
959    }
960
961    fn render_view<V: View>(&self, view: &V, renderer: &mut dyn Renderer, rect: Rect) {
962        if crate::load_system_state().realm == Realm::Asgard {
963            renderer.mani_glow(rect, self.color, self.radius);
964        }
965        view.render(renderer, rect);
966    }
967}
968
969/// BifrostLayerModifier themes a view based on its cognitive memory layer.
970/// Episodic: Shifting aurora clouds.
971/// Semantic: Crystalline gold.
972/// Procedural: Heavy obsidian stone.
973#[derive(Debug, Clone, Copy, PartialEq)]
974pub struct BifrostLayerModifier {
975    pub layer: MemoryLayer,
976}
977
978impl ViewModifier for BifrostLayerModifier {
979    fn modify<V: View>(self, content: V) -> impl View {
980        ModifiedView::new(content, self)
981    }
982
983    fn render_view<V: View>(&self, view: &V, renderer: &mut dyn Renderer, rect: Rect) {
984        let realm = crate::load_system_state().realm;
985        match self.layer {
986            MemoryLayer::Episodic => {
987                if realm == Realm::Asgard {
988                    renderer.bifrost(rect, 40.0, 1.2, 0.7);
989                } else {
990                    renderer.fill_rect(rect, [0.1, 0.12, 0.15, 0.8]);
991                }
992            }
993            MemoryLayer::Semantic => {
994                if realm == Realm::Asgard {
995                    renderer.gungnir(rect, [1.0, 0.84, 0.0, 1.0], 15.0, 0.6);
996                } else {
997                    renderer.stroke_rect(rect, [0.4, 0.4, 0.4, 1.0], 1.5);
998                }
999            }
1000            MemoryLayer::Procedural => {
1001                renderer.fill_rect(rect, [0.05, 0.05, 0.07, 0.95]);
1002                let stroke_color = if realm == Realm::Asgard { [0.3, 0.3, 0.3, 1.0] } else { [0.2, 0.2, 0.2, 1.0] };
1003                renderer.stroke_rect(rect, stroke_color, 2.0);
1004            }
1005        }
1006        view.render(renderer, rect);
1007    }
1008}
1009
1010/// FafnirModifier enables self-evolving UI capabilities.
1011/// Named after Fafnir, the dragon who grows in power based on the gold he hoards.
1012/// In CVKG, 'Gold' is user attention/interaction.
1013#[derive(Debug, Clone, Copy, PartialEq)]
1014pub struct FafnirModifier {
1015    /// Unique ID for tracking this component's vitality across frames.
1016    pub id: u64,
1017}
1018
1019impl ViewModifier for FafnirModifier {
1020    fn modify<V: View>(self, content: V) -> impl View {
1021        ModifiedView::new(content, self)
1022    }
1023
1024    fn render_view<V: View>(&self, view: &V, renderer: &mut dyn Renderer, rect: Rect) {
1025        let state = crate::load_system_state();
1026        let vitality = state.get_component_state::<f32>(self.id)
1027            .map(|v| *v.read().unwrap())
1028            .unwrap_or(1.0);
1029
1030        // Calculate evolutionary growth factors
1031        // Max growth at vitality 5.0 (50% scale increase, strong glow)
1032        let growth = (vitality - 1.0).clamp(0.0, 4.0);
1033        let scale = 1.0 + growth * 0.12;
1034        let glow_intensity = growth * 0.25;
1035        
1036        // Feed Fafnir: Register interaction to boost vitality
1037        let id = self.id;
1038        renderer.register_handler("pointermove", std::sync::Arc::new(move |_| {
1039            crate::update_system_state(|s| {
1040                let mut s = s.clone();
1041                let v = s.get_component_state::<f32>(id)
1042                    .map(|v| *v.read().unwrap())
1043                    .unwrap_or(1.0);
1044                s.set_component_state(id, (v + 0.05).min(5.0)); // Cap at 5.0
1045                s
1046            });
1047        }));
1048
1049        if scale > 1.01 {
1050            renderer.push_transform([0.0, 0.0], [scale, scale], 0.0);
1051        }
1052
1053        if glow_intensity > 0.1 && state.realm == Realm::Asgard {
1054            renderer.gungnir(rect, [1.0, 0.84, 0.0, 1.0], 15.0 * vitality, glow_intensity);
1055        }
1056
1057        view.render(renderer, rect);
1058
1059        if scale > 1.01 {
1060            renderer.pop_transform();
1061        }
1062    }
1063}
1064
1065/// MimirIntentModifier anticipates user movement and manifests holographic ghosts.
1066#[derive(Debug, Clone, Copy, PartialEq)]
1067pub struct MimirIntentModifier;
1068
1069impl ViewModifier for MimirIntentModifier {
1070    fn modify<V: View>(self, content: V) -> impl View {
1071        ModifiedView::new(content, self)
1072    }
1073
1074    fn render_view<V: View>(&self, view: &V, renderer: &mut dyn Renderer, rect: Rect) {
1075        let state = crate::load_system_state();
1076        let pos = state.last_pointer_pos;
1077        let vel = state.pointer_velocity;
1078        
1079        // Calculate if the cursor is moving towards this rect
1080        let center = [rect.x + rect.width / 2.0, rect.y + rect.height / 2.0];
1081        let dx = center[0] - pos[0];
1082        let dy = center[1] - pos[1];
1083        
1084        // Dot product of velocity and direction to center
1085        let dot = vel[0] * dx + vel[1] * dy;
1086        let speed_sq = vel[0]*vel[0] + vel[1]*vel[1];
1087        let dist_sq = dx*dx + dy*dy;
1088        
1089        if dot > 0.0 && dist_sq < 250.0*250.0 && speed_sq > 0.5 && state.realm == Realm::Asgard {
1090            // Intent detected: render a subtle "ghost" reveal
1091            let intent_strength = (dot / (speed_sq.sqrt() * dist_sq.sqrt())).clamp(0.0, 1.0);
1092            renderer.stroke_rect(rect, [0.0, 0.9, 1.0, 0.3 * intent_strength], 1.5);
1093        }
1094        
1095        view.render(renderer, rect);
1096    }
1097}
1098
1099/// KvasirVibeModifier renders a cognitive telemetry cloud representing agent complexity.
1100#[derive(Debug, Clone, Copy, PartialEq)]
1101pub struct KvasirVibeModifier {
1102    pub complexity: f32,
1103}
1104
1105impl ViewModifier for KvasirVibeModifier {
1106    fn modify<V: View>(self, content: V) -> impl View {
1107        ModifiedView::new(content, self)
1108    }
1109
1110    fn render_view<V: View>(&self, view: &V, renderer: &mut dyn Renderer, rect: Rect) {
1111        if crate::load_system_state().realm == Realm::Asgard {
1112            let t = renderer.elapsed_time();
1113            let c = self.complexity.clamp(0.0, 1.0);
1114            
1115            // 1. Core Cognitive Cloud (Bifrost)
1116            // Turbulence increases with complexity
1117            let blur = 20.0 + c * 40.0;
1118            let turbulence_x = (t * (1.0 + c * 2.0)).sin() * 8.0 * c;
1119            let turbulence_y = (t * (0.8 + c * 1.5)).cos() * 5.0 * c;
1120            renderer.bifrost(rect.offset(turbulence_x, turbulence_y), blur, 0.8 + c * 0.4, 0.25);
1121            
1122            // 2. Synaptic Discharge (Gungnir pulses)
1123            if c > 0.2 {
1124                let pulse = (t * (3.0 + c * 5.0)).sin().abs() * c;
1125                let color = [0.0, 0.9, 1.0, 0.4 * pulse]; // Cyan synaptic pulse
1126                renderer.gungnir(rect, color, 12.0 + c * 24.0, 0.6 * pulse);
1127            }
1128            
1129            // 3. Unstable Resonance (Magenta/Red shift for high complexity)
1130            if c > 0.7 {
1131                let instability = (t * 15.0).cos().abs() * (c - 0.7) * 3.3;
1132                let warning_color = [1.0, 0.0, 0.4, 0.12 * instability];
1133                renderer.fill_rect(rect, warning_color);
1134                renderer.stroke_rect(rect, [1.0, 0.0, 0.2, 0.45 * instability], 1.8);
1135            }
1136        }
1137        view.render(renderer, rect);
1138    }
1139}
1140
1141/// OdinsEyeModifier bestows omniscient observability over the entire scene graph.
1142#[derive(Debug, Clone, Copy, PartialEq)]
1143pub struct OdinsEyeModifier;
1144
1145impl ViewModifier for OdinsEyeModifier {
1146    fn modify<V: View>(self, content: V) -> impl View {
1147        ModifiedView::new(content, self)
1148    }
1149
1150    fn render_view<V: View>(&self, view: &V, renderer: &mut dyn Renderer, rect: Rect) {
1151        let state = crate::load_system_state();
1152        let t = renderer.elapsed_time();
1153
1154        // 1. Render Background content
1155        view.render(renderer, rect);
1156
1157        if state.realm == Realm::Asgard {
1158            // 2. Bestow Odin's Eye (Atmospheric Overlay)
1159            // Soft, large circular pulse representing the 'Eye'
1160            let eye_pulse = (t * 0.5).sin().abs() * 0.05;
1161            renderer.draw_radial_gradient(
1162                rect,
1163                [0.0, 0.6, 0.8, 0.08 + eye_pulse], // Inner Cyan
1164                [0.0, 0.0, 0.0, 0.0],              // Outer Black
1165            );
1166
1167            // 3. Hugin (Thought) Telemetry - Left Side
1168            let hugin_rect = Rect { x: rect.x + 20.0, y: rect.y + 40.0, width: 200.0, height: rect.height - 80.0 };
1169            renderer.draw_text("HUGIN: THOUGHT", hugin_rect.x, hugin_rect.y, 10.0, [0.0, 1.0, 1.0, 0.6]);
1170            for (i, thought) in state.thoughts.iter().rev().take(10).enumerate() {
1171                renderer.draw_text(thought, hugin_rect.x, hugin_rect.y + 20.0 + i as f32 * 14.0, 9.0, [1.0, 1.0, 1.0, 0.4]);
1172            }
1173
1174            // 4. Munin (Memory) Telemetry - Right Side
1175            let munin_rect = Rect { x: rect.x + rect.width - 220.0, y: rect.y + 40.0, width: 200.0, height: rect.height - 80.0 };
1176            renderer.draw_text("MUNIN: MEMORY", munin_rect.x, munin_rect.y, 10.0, [1.0, 0.84, 0.0, 0.6]);
1177            for (i, node) in state.nodes.iter().take(10).enumerate() {
1178                let opacity = (node.weight.min(1.0)) * 0.5;
1179                renderer.draw_text(&node.id, munin_rect.x, munin_rect.y + 20.0 + i as f32 * 14.0, 9.0, [1.0, 1.0, 1.0, opacity]);
1180            }
1181
1182            // 5. Omniscient Focus Beams (Gungnir Beams)
1183            if let Some(focus_id) = &state.odin_focus {
1184                // Visualize causal links to the focus node
1185                renderer.draw_text(&format!("EYE FOCUS: {}", focus_id), rect.x + rect.width / 2.0 - 50.0, rect.y + 20.0, 12.0, [0.0, 1.0, 1.0, 0.8]);
1186                
1187                // In a real implementation, we would find the rect of the focus_id component.
1188                // For the 'Eye', we manifest a central beam of wisdom.
1189                renderer.gungnir(Rect { x: rect.x + rect.width / 2.0 - 1.0, y: rect.y, width: 2.0, height: rect.height }, [0.0, 1.0, 1.0, 1.0], 20.0, 0.4);
1190            }
1191        }
1192    }
1193}
1194
1195/// Sleipnir spring parameters for the physics solver
1196#[derive(Debug, Clone, Copy, PartialEq)]
1197pub struct SleipnirParams {
1198    pub stiffness: f32,
1199    pub damping: f32,
1200    pub mass: f32,
1201}
1202
1203impl SleipnirParams {
1204    pub fn snappy() -> Self { Self { stiffness: 230.0, damping: 22.0, mass: 1.0 } }
1205    pub fn fluid() -> Self { Self { stiffness: 170.0, damping: 26.0, mass: 1.0 } }
1206    pub fn heavy() -> Self { Self { stiffness: 90.0, damping: 20.0, mass: 1.0 } }
1207    pub fn bouncy() -> Self { Self { stiffness: 190.0, damping: 14.0, mass: 1.0 } }
1208}
1209
1210impl Default for SleipnirParams {
1211    fn default() -> Self { Self::fluid() }
1212}
1213
1214#[derive(Debug, Clone, Copy, PartialEq)]
1215struct SolverState {
1216    x: f32,
1217    v: f32,
1218}
1219
1220/// SleipnirSolver implements a 4th-order Runge-Kutta (RK4) integration for springs.
1221/// This provides superior stability for high-fidelity interactive motion.
1222#[derive(Debug, Clone, Copy, PartialEq)]
1223pub struct SleipnirSolver {
1224    params: SleipnirParams,
1225    target: f32,
1226    state: SolverState,
1227}
1228
1229impl SleipnirSolver {
1230    /// Create a new solver with a target value and starting state.
1231    pub fn new(params: SleipnirParams, target: f32, current: f32) -> Self {
1232        Self {
1233            params,
1234            target,
1235            state: SolverState { x: current, v: 0.0 },
1236        }
1237    }
1238
1239    /// Advance the simulation by dt seconds using RK4 integration.
1240    pub fn tick(&mut self, dt: f32) -> f32 {
1241        if dt <= 0.0 { return self.state.x; }
1242        
1243        // Use a fixed time step for stability if dt is too large
1244        let mut remaining = dt;
1245        let step = 1.0 / 120.0;
1246        
1247        while remaining > 0.0 {
1248            let d = remaining.min(step);
1249            self.step(d);
1250            remaining -= d;
1251        }
1252        
1253        self.state.x
1254    }
1255
1256    fn step(&mut self, dt: f32) {
1257        let a = self.evaluate(self.state, 0.0, SolverState { x: 0.0, v: 0.0 });
1258        let b = self.evaluate(self.state, dt * 0.5, a);
1259        let c = self.evaluate(self.state, dt * 0.5, b);
1260        let d = self.evaluate(self.state, dt, c);
1261
1262        let dxdt = 1.0 / 6.0 * (a.x + 2.0 * (b.x + c.x) + d.x);
1263        let dvdt = 1.0 / 6.0 * (a.v + 2.0 * (b.v + c.v) + d.v);
1264
1265        self.state.x += dxdt * dt;
1266        self.state.v += dvdt * dt;
1267    }
1268
1269    fn evaluate(&self, initial: SolverState, dt: f32, d: SolverState) -> SolverState {
1270        let state = SolverState {
1271            x: initial.x + d.x * dt,
1272            v: initial.v + d.v * dt,
1273        };
1274        let force = -self.params.stiffness * (state.x - self.target) - self.params.damping * state.v;
1275        let mass = self.params.mass.max(0.001);
1276        SolverState { x: state.v, v: force / mass }
1277    }
1278
1279    pub fn is_settled(&self) -> bool {
1280        (self.state.x - self.target).abs() < 0.001 && self.state.v.abs() < 0.001
1281    }
1282
1283    pub fn set_target(&mut self, target: f32) {
1284        self.target = target;
1285    }
1286
1287    pub fn current_value(&self) -> f32 {
1288        self.state.x
1289    }
1290}
1291
1292/// SleipnirModifier handles physics-based animations via the Sleipnir RK4 solver.
1293#[derive(Debug, Clone, PartialEq)]
1294pub struct SleipnirModifier {
1295    pub id: u64,
1296    pub target: f32,
1297    pub params: SleipnirParams,
1298}
1299
1300impl ViewModifier for SleipnirModifier {
1301    fn modify<V: View>(self, content: V) -> impl View {
1302        ModifiedView::new(content, self)
1303    }
1304
1305    fn render_view<V: View>(&self, view: &V, renderer: &mut dyn Renderer, rect: Rect) {
1306        let state = load_system_state();
1307        
1308        // Try to fetch the solver from persistent state.
1309        let solver_lock_opt = state.get_component_state::<SleipnirSolver>(self.id);
1310        
1311        let current_val;
1312        
1313        if let Some(lock) = solver_lock_opt {
1314            // Found a solver. Tick it.
1315            let mut solver = lock.write().unwrap();
1316            solver.set_target(self.target);
1317            current_val = solver.tick(renderer.delta_time());
1318            
1319            // If the solver hasn't settled yet, request another frame.
1320            if !solver.is_settled() {
1321                renderer.request_redraw();
1322            }
1323        } else {
1324            // First time seeing this ID. Initialize solver state.
1325            let solver = SleipnirSolver::new(
1326                self.params,
1327                self.target,
1328                self.target // Initialize at target to avoid jump on first frame
1329            );
1330            
1331            // Insert into registry for next frame.
1332            get_system_state().rcu(|old| {
1333                let mut new_state = (**old).clone();
1334                new_state.set_component_state(self.id, solver);
1335                new_state
1336            });
1337            
1338            current_val = self.target;
1339        }
1340
1341        // Apply the solved value as a vertical translation.
1342        renderer.push_transform([0.0, current_val], [1.0, 1.0], 0.0);
1343        view.render(renderer, rect);
1344        renderer.pop_transform();
1345    }
1346}
1347
1348/// TransformModifier applies a 2D transform (translation, scale, rotation) to its child.
1349/// This modifier is "layout-neutral" and can be animated without re-running the layout engine.
1350#[derive(Debug, Clone, Copy, PartialEq)]
1351pub struct TransformModifier {
1352    pub translation: [f32; 2],
1353    pub scale: [f32; 2],
1354    pub rotation: f32,
1355}
1356
1357impl Default for TransformModifier {
1358    fn default() -> Self {
1359        Self::new()
1360    }
1361}
1362
1363impl TransformModifier {
1364    pub fn new() -> Self {
1365        Self {
1366            translation: [0.0, 0.0],
1367            scale: [1.0, 1.0],
1368            rotation: 0.0,
1369        }
1370    }
1371
1372    pub fn translate(mut self, x: f32, y: f32) -> Self {
1373        self.translation = [x, y];
1374        self
1375    }
1376
1377    pub fn scale(mut self, x: f32, y: f32) -> Self {
1378        self.scale = [x, y];
1379        self
1380    }
1381
1382    pub fn rotate(mut self, radians: f32) -> Self {
1383        self.rotation = radians;
1384        self
1385    }
1386}
1387
1388impl ViewModifier for TransformModifier {
1389    fn modify<V: View>(self, content: V) -> impl View {
1390        ModifiedView::new(content, self)
1391    }
1392
1393    fn render_view<V: View>(&self, view: &V, renderer: &mut dyn Renderer, rect: Rect) {
1394        renderer.push_transform(self.translation, self.scale, self.rotation);
1395        view.render(renderer, rect);
1396        renderer.pop_transform();
1397    }
1398}
1399
1400/// LifecycleModifier handles on_appear and on_disappear hooks.
1401
1402#[derive(Clone)]
1403pub struct LifecycleModifier {
1404    pub on_appear: Option<Arc<dyn Fn() + Send + Sync>>,
1405    pub on_disappear: Option<Arc<dyn Fn() + Send + Sync>>,
1406}
1407
1408impl ViewModifier for LifecycleModifier {
1409    fn modify<V: View>(self, content: V) -> impl View {
1410        ModifiedView::new(content, self)
1411    }
1412}
1413
1414/// OpacityModifier fades this view and all its descendants to the given alpha.
1415/// The renderer is expected to honour `push_opacity`/`pop_opacity` on the Renderer trait.
1416#[derive(Debug, Clone, Copy, PartialEq)]
1417pub struct OpacityModifier {
1418    pub opacity: f32,
1419}
1420
1421impl ViewModifier for OpacityModifier {
1422    fn modify<V: View>(self, content: V) -> impl View {
1423        ModifiedView::new(content, self)
1424    }
1425
1426    fn render(&self, renderer: &mut dyn Renderer, _rect: Rect) {
1427        renderer.push_opacity(self.opacity);
1428    }
1429
1430    fn post_render(&self, renderer: &mut dyn Renderer, _rect: Rect) {
1431        renderer.pop_opacity();
1432    }
1433}
1434
1435/// OnClickModifier registers a click handler for this view.
1436#[derive(Clone)]
1437pub struct OnClickModifier {
1438    pub action: Arc<dyn Fn() + Send + Sync>,
1439}
1440
1441impl ViewModifier for OnClickModifier {
1442    fn modify<V: View>(self, content: V) -> impl View {
1443        ModifiedView::new(content, self)
1444    }
1445
1446    fn render(&self, renderer: &mut dyn Renderer, _rect: Rect) {
1447        let action = self.action.clone();
1448        renderer.register_handler(
1449            "pointerclick",
1450            std::sync::Arc::new(move |event| {
1451                if let Event::PointerClick { .. } = event {
1452                    (action)();
1453                }
1454            }),
1455        );
1456    }
1457}
1458
1459/// OnPointerEnterModifier registers a pointer enter handler.
1460#[derive(Clone)]
1461pub struct OnPointerEnterModifier {
1462    pub action: Arc<dyn Fn() + Send + Sync>,
1463}
1464
1465impl ViewModifier for OnPointerEnterModifier {
1466    fn modify<V: View>(self, content: V) -> impl View {
1467        ModifiedView::new(content, self)
1468    }
1469
1470    fn render(&self, renderer: &mut dyn Renderer, _rect: Rect) {
1471        let action = self.action.clone();
1472        renderer.register_handler(
1473            "pointerenter",
1474            std::sync::Arc::new(move |event| {
1475                if let Event::PointerEnter = event {
1476                    (action)();
1477                }
1478            }),
1479        );
1480    }
1481}
1482
1483/// OnPointerLeaveModifier registers a pointer leave handler.
1484#[derive(Clone)]
1485pub struct OnPointerLeaveModifier {
1486    pub action: Arc<dyn Fn() + Send + Sync>,
1487}
1488
1489impl ViewModifier for OnPointerLeaveModifier {
1490    fn modify<V: View>(self, content: V) -> impl View {
1491        ModifiedView::new(content, self)
1492    }
1493
1494    fn render(&self, renderer: &mut dyn Renderer, _rect: Rect) {
1495        let action = self.action.clone();
1496        renderer.register_handler(
1497            "pointerleave",
1498            std::sync::Arc::new(move |event| {
1499                if let Event::PointerLeave = event {
1500                    (action)();
1501                }
1502            }),
1503        );
1504    }
1505}
1506
1507/// OnPointerMoveModifier registers a pointer move handler.
1508#[derive(Clone)]
1509pub struct OnPointerMoveModifier {
1510    pub action: Arc<dyn Fn(f32, f32) + Send + Sync>,
1511}
1512
1513impl ViewModifier for OnPointerMoveModifier {
1514    fn modify<V: View>(self, content: V) -> impl View {
1515        ModifiedView::new(content, self)
1516    }
1517
1518    fn render(&self, renderer: &mut dyn Renderer, _rect: Rect) {
1519        let action = self.action.clone();
1520        renderer.register_handler(
1521            "pointermove",
1522            std::sync::Arc::new(move |event| {
1523                if let Event::PointerMove { x, y } = event {
1524                    (action)(x, y);
1525                }
1526            }),
1527        );
1528    }
1529}
1530
1531/// OnPointerDownModifier registers a pointer down handler.
1532#[derive(Clone)]
1533pub struct OnPointerDownModifier {
1534    pub action: Arc<dyn Fn() + Send + Sync>,
1535}
1536
1537impl ViewModifier for OnPointerDownModifier {
1538    fn modify<V: View>(self, content: V) -> impl View {
1539        ModifiedView::new(content, self)
1540    }
1541
1542    fn render(&self, renderer: &mut dyn Renderer, _rect: Rect) {
1543        let action = self.action.clone();
1544        renderer.register_handler(
1545            "pointerdown",
1546            std::sync::Arc::new(move |event| {
1547                if let Event::PointerDown { .. } = event {
1548                    (action)();
1549                }
1550            }),
1551        );
1552    }
1553}
1554
1555/// OnPointerUpModifier registers a pointer up handler.
1556#[derive(Clone)]
1557pub struct OnPointerUpModifier {
1558    pub action: Arc<dyn Fn() + Send + Sync>,
1559}
1560
1561impl ViewModifier for OnPointerUpModifier {
1562    fn modify<V: View>(self, content: V) -> impl View {
1563        ModifiedView::new(content, self)
1564    }
1565
1566    fn render(&self, renderer: &mut dyn Renderer, _rect: Rect) {
1567        let action = self.action.clone();
1568        renderer.register_handler(
1569            "pointerup",
1570            std::sync::Arc::new(move |event| {
1571                if let Event::PointerUp { .. } = event {
1572                    (action)();
1573                }
1574            }),
1575        );
1576    }
1577}
1578
1579/// ForegroundColorModifier overrides the foreground (text / icon) color inherited
1580/// by all descendants until another ForegroundColorModifier is encountered.
1581#[derive(Debug, Clone, Copy, PartialEq)]
1582pub struct ForegroundColorModifier {
1583    pub color: [f32; 4],
1584}
1585
1586impl ViewModifier for ForegroundColorModifier {
1587    fn modify<V: View>(self, content: V) -> impl View {
1588        ModifiedView::new(content, self)
1589    }
1590}
1591
1592/// ClipModifier restricts all child drawing to the view's layout rectangle.
1593/// The renderer must support `push_clip_rect`/`pop_clip_rect`.
1594#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1595pub struct ClipModifier;
1596
1597impl ViewModifier for ClipModifier {
1598    fn modify<V: View>(self, content: V) -> impl View {
1599        ModifiedView::new(content, self)
1600    }
1601
1602    fn render(&self, renderer: &mut dyn Renderer, rect: Rect) {
1603        renderer.push_clip_rect(rect);
1604    }
1605
1606    fn post_render(&self, renderer: &mut dyn Renderer, _rect: Rect) {
1607        renderer.pop_clip_rect();
1608    }
1609}
1610
1611/// BorderModifier draws a solid-color border around the view bounds.
1612#[derive(Debug, Clone, Copy, PartialEq)]
1613pub struct BorderModifier {
1614    pub color: [f32; 4],
1615    pub width: f32,
1616}
1617
1618impl ViewModifier for BorderModifier {
1619    fn modify<V: View>(self, content: V) -> impl View {
1620        ModifiedView::new(content, self)
1621    }
1622
1623    fn render(&self, renderer: &mut dyn Renderer, rect: Rect) {
1624        renderer.stroke_rect(rect, self.color, self.width);
1625    }
1626}
1627
1628// Primitive (leaf) views implement Never as body
1629#[doc(hidden)]
1630pub enum Never {}
1631
1632impl View for Never {
1633    type Body = Never;
1634    fn body(self) -> Never {
1635        unreachable!()
1636    }
1637}
1638
1639/// EmptyView - A view that renders nothing and takes up no space.
1640#[derive(Debug, Clone, Copy, Default)]
1641pub struct EmptyView;
1642
1643impl View for EmptyView {
1644    type Body = Never;
1645    fn body(self) -> Self::Body { unreachable!() }
1646    fn render(&self, _renderer: &mut dyn Renderer, _rect: Rect) {}
1647    fn intrinsic_size(&self, _renderer: &mut dyn Renderer, _proposal: SizeProposal) -> Size {
1648        Size { width: 0.0, height: 0.0 }
1649    }
1650}
1651
1652/// A view that has been transformed by a modifier.
1653///
1654/// Section 4.3: "Each modifier implements ViewModifier and produces a ModifiedView<Inner, Self>."
1655#[derive(Clone)]
1656pub struct ModifiedView<V, M> {
1657    view: V,
1658    modifier: M,
1659}
1660
1661impl<V: View, M: ViewModifier> ModifiedView<V, M> {
1662    #[doc(hidden)]
1663    pub fn new(view: V, modifier: M) -> Self {
1664        Self { view, modifier }
1665    }
1666}
1667
1668impl<V: View, M: ViewModifier> View for ModifiedView<V, M> {
1669    type Body = ModifiedView<V::Body, M>;
1670
1671    fn body(self) -> Self::Body {
1672        ModifiedView {
1673            view: self.view.body(),
1674            modifier: self.modifier.clone(),
1675        }
1676    }
1677
1678    fn render(&self, renderer: &mut dyn Renderer, rect: Rect) {
1679        self.modifier.render_view(&self.view, renderer, rect);
1680    }
1681
1682    fn intrinsic_size(&self, renderer: &mut dyn Renderer, proposal: SizeProposal) -> Size {
1683        self.modifier.measure_view(&self.view, renderer, proposal)
1684    }
1685
1686    fn flex_weight(&self) -> f32 {
1687        self.modifier.child_flex_weight(&self.view)
1688    }
1689
1690    fn layout(&self) -> Option<&dyn layout::LayoutView> {
1691        self.modifier.layout().or_else(|| self.view.layout())
1692    }
1693}
1694
1695pub trait ViewModifier: Send + Clone {
1696    fn modify<V: View>(self, content: V) -> impl View;
1697
1698    /// Core rendering hook called before child views.
1699    fn render(&self, _renderer: &mut dyn Renderer, _rect: Rect) {}
1700
1701    /// Cleanup hook called after child views.
1702    fn post_render(&self, _renderer: &mut dyn Renderer, _rect: Rect) {}
1703
1704    /// Allows a modifier to completely override or wrap the rendering of its child.
1705    /// Default implementation performs a standard push -> transform -> render child -> pop sequence.
1706    fn render_view<V: View>(&self, view: &V, renderer: &mut dyn Renderer, rect: Rect) {
1707        self.render(renderer, rect);
1708        let child_rect = self.transform_rect(rect);
1709        view.render(renderer, child_rect);
1710        self.post_render(renderer, rect);
1711    }
1712
1713    fn transform_rect(&self, rect: Rect) -> Rect {
1714        rect
1715    }
1716
1717    /// Allows a modifier to transform the layout proposal before it reaches the child.
1718    fn transform_proposal(&self, proposal: SizeProposal) -> SizeProposal {
1719        proposal
1720    }
1721
1722    /// Allows a modifier to transform the resulting size from the child.
1723    fn transform_size(&self, size: Size) -> Size {
1724        size
1725    }
1726
1727    /// Measure hook that coordinates size propagation.
1728    fn measure_view<V: View>(&self, view: &V, renderer: &mut dyn Renderer, proposal: SizeProposal) -> Size {
1729        let child_proposal = self.transform_proposal(proposal);
1730        let child_size = view.intrinsic_size(renderer, child_proposal);
1731        self.transform_size(child_size)
1732    }
1733
1734    /// Allows a modifier to override or pass through the child's flex weight.
1735    fn child_flex_weight<V: View>(&self, view: &V) -> f32 {
1736        view.flex_weight()
1737    }
1738
1739    fn layout(&self) -> Option<&dyn layout::LayoutView> {
1740        None
1741    }
1742}
1743
1744/// TelemetryData tracks real-time performance metrics for the GPU renderer.
1745#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)]
1746pub struct TelemetryData {
1747    pub frame_time_ms: f32,
1748    /// 99th percentile frame time over the last window, used to detect tail latency.
1749    pub p99_frame_time_ms: f32,
1750    /// Statistical jitter (variance in frame timing).
1751    pub frame_jitter_ms: f32,
1752    /// Indicates if a hardware stall (DRAM refresh, thermal spike) was detected.
1753    pub hardware_stall_detected: bool,
1754    
1755    // Pass timing
1756    pub input_time_ms: f32,
1757    pub state_flush_time_ms: f32,
1758    pub layout_time_ms: f32,
1759    pub draw_time_ms: f32,
1760    pub gpu_submit_time_ms: f32,
1761    
1762    pub draw_calls: u32,
1763    pub vertices: u32,
1764    
1765    /// Global Berserker Pipeline Intensity (0.0 - 1.0+)
1766    pub berserker_rage: f32,
1767    
1768    // Memory breakdown
1769    pub vram_usage_mb: f32,
1770    pub vram_textures_mb: f32,
1771    pub vram_buffers_mb: f32,
1772    pub vram_pipelines_mb: f32,
1773    /// Indicates if the Mega-Atlas or VRAM pools are at capacity.
1774    pub vram_exhausted: bool,
1775}
1776
1777/// Configuration for render-loop frame timing and degradation strategies.
1778#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
1779pub struct FrameBudget {
1780    /// Target frame time in milliseconds (default: 16.0 for 60FPS)
1781    pub target_ms: f32,
1782    /// If true, the renderer is allowed to dynamically skip non-critical effects
1783    /// (like heavy blurs or complex shadows) when the budget is exceeded.
1784    pub allow_degradation: bool,
1785}
1786
1787impl Default for FrameBudget {
1788    fn default() -> Self {
1789        Self {
1790            target_ms: 16.0,
1791            allow_degradation: true,
1792        }
1793    }
1794}
1795
1796/// The Renderer trait defines the atomic drawing operations for all CVKG backends.
1797/// This trait is object-safe and used by the View::render system.
1798///
1799/// # Implementation Requirements
1800/// 1. Coordinate system is origin-top-left (0,0) with Y increasing downwards.
1801/// 2. Colors are [R, G, B, A] in the [0.0, 1.0] range.
1802/// 3. All operations must be batchable by the underlying backend.
1803///    Trait providing timing information for the render loop.
1804pub trait ElapsedTime {
1805    /// Returns the cumulative time since the renderer started in seconds.
1806    fn elapsed_time(&self) -> f32;
1807    
1808    /// Returns the time elapsed since the last frame in seconds.
1809    fn delta_time(&self) -> f32;
1810}
1811
1812/// The Renderer trait defines the atomic drawing operations for all CVKG backends.
1813/// This trait is object-safe and used by the View::render system.
1814///
1815/// # Implementation Requirements
1816/// 1. Coordinate system is origin-top-left (0,0) with Y increasing downwards.
1817/// 2. Colors are [R, G, B, A] in the [0.0, 1.0] range.
1818/// 3. All operations must be batchable by the underlying backend.
1819pub trait Renderer: ElapsedTime + Send {
1820    /// Requests that the renderer redraws as soon as possible.
1821    /// Used for continuous animations.
1822    fn request_redraw(&mut self) {}
1823
1824    /// Returns true if the current frame is over the time budget.
1825    /// This can be used to skip expensive visual effects.
1826    fn is_over_budget(&self) -> bool {
1827        false
1828    }
1829
1830    // ── Filled shapes ────────────────────────────────────────────────────
1831    fn fill_rect(&mut self, rect: Rect, color: [f32; 4]);
1832    fn fill_rounded_rect(&mut self, rect: Rect, radius: f32, color: [f32; 4]);
1833    /// Fill an ellipse/circle that fits inside `rect`.
1834    fn fill_ellipse(&mut self, rect: Rect, color: [f32; 4]);
1835
1836    /// Draw a high-fidelity 3D cube inside the given rectangle using specialized shader logic.
1837    /// `rotation` is [pitch, yaw, roll] in radians.
1838    fn draw_3d_cube(&mut self, _rect: Rect, _color: [f32; 4], _rotation: [f32; 3]) {}
1839
1840    // ── Stroked shapes ───────────────────────────────────────────────────
1841    fn stroke_rect(&mut self, rect: Rect, color: [f32; 4], stroke_width: f32);
1842    fn stroke_rounded_rect(&mut self, rect: Rect, radius: f32, color: [f32; 4], stroke_width: f32);
1843    /// Stroke an ellipse/circle that fits inside `rect`.
1844    fn stroke_ellipse(&mut self, rect: Rect, color: [f32; 4], stroke_width: f32);
1845    /// Draw a straight line from (x1,y1) to (x2,y2).
1846    fn draw_line(&mut self, x1: f32, y1: f32, x2: f32, y2: f32, color: [f32; 4], stroke_width: f32);
1847    /// Fill a polygon defined by a set of vertices.
1848    fn fill_polygon(&mut self, _vertices: &[[f32; 2]], _color: [f32; 4]) {}
1849    /// Stroke a polygon defined by a set of vertices.
1850    fn stroke_polygon(&mut self, _vertices: &[[f32; 2]], _color: [f32; 4], _stroke_width: f32) {}
1851
1852    // ── Text ─────────────────────────────────────────────────────────────
1853    fn draw_text(&mut self, text: &str, x: f32, y: f32, size: f32, color: [f32; 4]);
1854    /// Measure the width and height of the specified text.
1855    fn measure_text(&mut self, text: &str, size: f32) -> (f32, f32);
1856
1857    // ── Images & textures ────────────────────────────────────────────────
1858    /// Draw a texture (GPU-side) at the specified rect.
1859    fn draw_texture(&mut self, _texture_id: u32, _rect: Rect) {}
1860    /// Draw an image asset by name or path.
1861    fn draw_image(&mut self, _image_name: &str, _rect: Rect) {}
1862    /// Load an image asset from memory.
1863    fn load_image(&mut self, _name: &str, _data: &[u8]) {}
1864    /// Pre-warm the renderer with assets. Implementations can use this
1865    /// to populate texture atlases or warm up shader caches.
1866    fn prewarm_vram(&mut self, _assets: Vec<(String, Vec<u8>)>) {}
1867
1868    /// Get the current pointer (mouse/touch) position.
1869    fn get_pointer_position(&self) -> [f32; 2] {
1870        [0.0, 0.0]
1871    }
1872
1873    // ── Data Visualization ───────────────────────────────────────────────
1874    /// Upload raw float data as a GPU texture for heatmap rendering.
1875    fn upload_data_texture(&mut self, _id: &str, _data: &[f32], _width: u32, _height: u32) {}
1876    /// Draw a heatmap using a previously uploaded data texture.
1877    fn draw_heatmap(&mut self, _texture_id: &str, _rect: Rect, _palette: &str) {}
1878
1879    // ── 3D Objects ───────────────────────────────────────────────────────
1880    /// Draw a 3D mesh.
1881    fn draw_mesh(&mut self, _mesh: &Mesh, _color: [f32; 4], _transform: glam::Mat4) {}
1882
1883    // ── Advanced Visual Effects ──────────────────────────────────────────
1884    /// Draw a linear gradient between two colors at the specified angle.
1885    fn draw_linear_gradient(
1886        &mut self,
1887        _rect: Rect,
1888        _start_color: [f32; 4],
1889        _end_color: [f32; 4],
1890        _angle: f32,
1891    ) {
1892    }
1893    /// Draw a radial gradient between two colors.
1894    fn draw_radial_gradient(
1895        &mut self,
1896        _rect: Rect,
1897        _inner_color: [f32; 4],
1898        _outer_color: [f32; 4],
1899    ) {
1900    }
1901    /// Draw a high-fidelity drop shadow for a rounded rectangle.
1902    fn draw_drop_shadow(
1903        &mut self,
1904        _rect: Rect,
1905        _radius: f32,
1906        _color: [f32; 4],
1907        _blur: f32,
1908        _spread: f32,
1909    ) {
1910    }
1911    /// Draw a dashed border for a rounded rectangle.
1912    fn stroke_dashed_rounded_rect(
1913        &mut self,
1914        _rect: Rect,
1915        _radius: f32,
1916        _color: [f32; 4],
1917        _width: f32,
1918        _dash: f32,
1919        _gap: f32,
1920    ) {
1921    }
1922    /// Draw a 9-slice / patch scaled image.
1923    fn draw_9slice(
1924        &mut self,
1925        _image_name: &str,
1926        _rect: Rect,
1927        _left: f32,
1928        _top: f32,
1929        _right: f32,
1930        _bottom: f32,
1931    ) {
1932    }
1933
1934    // ── Clipping ─────────────────────────────────────────────────────────
1935    /// Push a clip rectangle.  All subsequent drawing is clipped to `rect`.
1936    /// Implementations that do not support clipping may ignore this call.
1937    fn push_clip_rect(&mut self, _rect: Rect) {}
1938    /// Pop the most recently pushed clip rectangle.
1939    fn pop_clip_rect(&mut self) {}
1940    /// Get the current clip rectangle in screen coordinates.
1941    /// Returns a rect covering the entire screen if no clip is active.
1942    fn current_clip_rect(&self) -> Rect {
1943        Rect::new(-10000.0, -10000.0, 20000.0, 20000.0)
1944    }
1945
1946    // ── Global opacity ───────────────────────────────────────────────────
1947    /// Set a global opacity multiplier applied to all subsequent draw calls
1948    /// until `pop_opacity` is called.  `opacity` is in [0.0, 1.0].
1949    fn push_opacity(&mut self, _opacity: f32) {}
1950    /// Restore the previous opacity level.
1951    fn pop_opacity(&mut self) {}
1952
1953    // ── Berserker Pipeline State ─────────────────────────────────────────
1954    fn set_theme(&mut self, _theme: ColorTheme) {}
1955    fn set_rage(&mut self, _rage: f32) {}
1956    fn set_berserker_mode(&mut self, _state: BerserkerMode) {}
1957    fn trigger_shatter_event(&mut self, _origin: [f32; 2], _force: f32) {}
1958    /// Set the desktop scene preset (Aurora, Void, Nebula, Glitch, Yggdrasil).
1959    fn set_scene(&mut self, _scene: &str) {}
1960
1961    // ── Export & Print ───────────────────────────────────────────────────
1962    /// Capture the current frame as a PNG byte buffer.
1963    fn capture_png(&mut self) -> Vec<u8> { Vec::new() }
1964    /// Trigger a native print dialog or spooling operation.
1965    fn print(&mut self) {}
1966
1967    fn set_scene_preset(&mut self, _preset: u32) {}
1968
1969    // ── Cyberpunk Effects ────────────────────────────────────────────────
1970    /// Apply a Bifrost (Frosted Glass) effect to the specified rect.
1971    fn bifrost(&mut self, _rect: Rect, _blur: f32, _saturation: f32, _opacity: f32) {}
1972    /// Apply a Gungnir (Neon Glow) effect to the specified rect.
1973    fn gungnir(&mut self, _rect: Rect, _color: [f32; 4], _radius: f32, _intensity: f32) {}
1974    /// Apply a ManiGlow (Lunar Illuminator) effect.
1975    fn mani_glow(&mut self, _rect: Rect, _color: [f32; 4], _radius: f32) {}
1976    /// Push a Mjolnir Slice (geometric clipping).
1977    fn push_mjolnir_slice(&mut self, _angle: f32, _offset: f32) {}
1978    fn pop_mjolnir_slice(&mut self) {}
1979    /// Execute a render function with memoization.
1980    /// If the renderer supports caching and the `id` + `data_hash` match a previous run,
1981    /// it may replay cached commands instead of executing the function.
1982    fn memoize(&mut self, id: u64, data_hash: u64, render_fn: &dyn Fn(&mut dyn Renderer));
1983    /// Apply a Mjolnir Shatter effect (fragmentation) to the specified rect.
1984    fn mjolnir_shatter(&mut self, _rect: Rect, _pieces: u32, _force: f32, _color: [f32; 4]) {}
1985    fn mjolnir_fluid_shatter(&mut self, _rect: Rect, _pieces: u32, _force: f32, _color: [f32; 4]) {}
1986    /// Draw a Mjolnir Bolt (lightning strike) between two points.
1987    fn draw_mjolnir_bolt(&mut self, _from: [f32; 2], _to: [f32; 2], _color: [f32; 4]) {}
1988
1989    // ── Accessibility (ShieldWall) ───────────────────────────────────────
1990    fn set_aria_role(&mut self, _role: &str) {}
1991    fn set_aria_label(&mut self, _label: &str) {}
1992
1993    /// Register a shared element for Bifrost Bridge transitions.
1994    fn register_shared_element(&mut self, _id: &str, _rect: Rect) {}
1995
1996    /// Set a unique key for the current VDOM node to ensure stable identity during diffing.
1997    fn set_key(&mut self, _key: &str) {}
1998
1999    // ── Telemetry ────────────────────────────────────────────────────────
2000    /// Get real-time performance telemetry.
2001    fn get_telemetry(&self) -> TelemetryData {
2002        TelemetryData::default()
2003    }
2004
2005    // ── GPU State Management ─────────────────────────────────────────────
2006    /// Push a shadow state to the stack. All following draw calls will have this shadow.
2007    fn push_shadow(&mut self, _radius: f32, _color: [f32; 4], _offset: [f32; 2]) {}
2008    /// Pop the last shadow state from the stack.
2009    fn pop_shadow(&mut self) {}
2010
2011    // ── VDOM & Scene Graph ───────────────────────────────────────────────
2012    /// Push a Virtual DOM node onto the stack for hierarchy tracking.
2013    fn push_vnode(&mut self, _rect: Rect, _name: &'static str) {}
2014    /// Pop the current Virtual DOM node from the stack.
2015    fn pop_vnode(&mut self) {}
2016    /// Register an event handler for the current VDOM node.
2017    fn register_handler(
2018        &mut self,
2019        _event_type: &str,
2020        _handler: std::sync::Arc<dyn Fn(Event) + Send + Sync>,
2021    ) {
2022    }
2023
2024    // ── Z-Index & Depth ──────────────────────────────────────────────────
2025    /// Set the current Z-index for depth sorting.
2026    /// Higher values appear closer to the viewer.
2027    fn set_z_index(&mut self, _z: f32) {}
2028    /// Get the current Z-index.
2029    fn get_z_index(&self) -> f32 {
2030        0.0
2031    }
2032
2033    // ── Vector Graphics ──────────────────────────────────────────────────
2034    /// Load an SVG model from raw bytes.
2035    fn load_svg(&mut self, _name: &str, _svg_data: &[u8]) {}
2036    /// Draw a pre-loaded SVG model.
2037    fn draw_svg(&mut self, _name: &str, _rect: Rect) {}
2038
2039    // ── GPU Transformations ──────────────────────────────────────────────
2040    /// Push a 2D transform (translation, scale, rotation) onto the stack.
2041    /// This transform should be applied to all subsequent draw calls until popped.
2042    /// Transform-only animations use this to avoid re-triggering the layout engine.
2043    fn push_transform(&mut self, _translation: [f32; 2], _scale: [f32; 2], _rotation: f32) {}
2044    /// Pop the last 2D transform from the stack.
2045    fn pop_transform(&mut self) {}
2046    /// Return the resolved layout bounds for a specific node ID if it exists.
2047    fn query_layout(&self, _node_id: scene_graph::NodeId) -> Option<Rect> {
2048        None
2049    }
2050    /// Enable or disable the layout debug overlay (bounds, padding, margin).
2051    fn set_debug_layout(&mut self, _enabled: bool) {}
2052    /// Check if the layout debug overlay is currently enabled.
2053    fn get_debug_layout(&self) -> bool {
2054        false
2055    }
2056}
2057
2058/// Utility for accessibility compliance (WCAG 2.1).
2059pub mod accessibility {
2060    /// Calculate the relative luminance of an sRGB color.
2061    pub fn relative_luminance(color: [f32; 4]) -> f32 {
2062        let f = |c: f32| {
2063            if c <= 0.03928 {
2064                c / 12.92
2065            } else {
2066                ((c + 0.055) / 1.055).powf(2.4)
2067            }
2068        };
2069        0.2126 * f(color[0]) + 0.7152 * f(color[1]) + 0.0722 * f(color[2])
2070    }
2071
2072    /// Calculate the contrast ratio between two colors.
2073    pub fn contrast_ratio(c1: [f32; 4], c2: [f32; 4]) -> f32 {
2074        let l1 = relative_luminance(c1);
2075        let l2 = relative_luminance(c2);
2076        let (light, dark) = if l1 > l2 { (l1, l2) } else { (l2, l1) };
2077        (light + 0.05) / (dark + 0.05)
2078    }
2079}
2080/// Defines the hardware acceleration tier and feature set available to the renderer.
2081#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, serde::Serialize, serde::Deserialize)]
2082pub enum RenderTier {
2083    /// High-performance GPU path (WebGPU / Vulkan / Metal / DX12) with full shader support.
2084    Tier1GPU = 0,
2085    /// Mid-tier GPU path (WebGL2 / OpenGL 3.3) with standard shader support.
2086    Tier2GPU = 1,
2087    /// Fallback software or basic hardware path (Canvas 2D / GDI+) with limited effects.
2088    Tier3Fallback = 2,
2089}
2090// =============================================================================
2091// BERSERKER UNIFORMS
2092// =============================================================================
2093use bytemuck::{Pod, Zeroable};
2094/// Fully themeable color palette for the Berserker pipeline.
2095#[repr(C)]
2096#[derive(Copy, Clone, Debug, Pod, Zeroable, serde::Serialize, serde::Deserialize)]
2097pub struct ColorTheme {
2098    pub primary_neon: [f32; 4], // (R, G, B, intensity)
2099    pub shatter_neon: [f32; 4],
2100    pub glass_base: [f32; 4],
2101    pub glass_edge: [f32; 4],
2102    pub rune_glow: [f32; 4],
2103    pub ember_core: [f32; 4],
2104    pub background_deep: [f32; 4],
2105    pub mani_glow: [f32; 4], // (R, G, B, radius)
2106    pub glass_blur_strength: f32,
2107    pub shatter_edge_width: f32,
2108    pub neon_bloom_radius: f32,
2109    pub rune_opacity: f32, 
2110}
2111impl ColorTheme {
2112    /// Asgard Mode: The high-fidelity "Cyberpunk Viking" aesthetic.
2113    pub fn asgard() -> Self {
2114        Self {
2115            primary_neon: [0.0, 1.0, 0.95, 1.2],
2116            shatter_neon: [1.0, 0.0, 0.75, 1.5],
2117            glass_base: [0.04, 0.04, 0.06, 0.82],
2118            glass_edge: [0.0, 0.45, 0.55, 0.6],
2119            rune_glow: [0.75, 0.98, 1.0, 0.9],
2120            ember_core: [0.95, 0.12, 0.12, 1.0],
2121            background_deep: [0.01, 0.01, 0.03, 1.0],
2122            mani_glow: [0.7, 0.9, 1.0, 0.05], 
2123            glass_blur_strength: 0.6,
2124            shatter_edge_width: 1.8,
2125            neon_bloom_radius: 0.022,
2126            rune_opacity: 0.55,
2127        }
2128    }
2129
2130    /// Midgard Mode: A clean, functional tactical HUD for standard operations.
2131    pub fn midgard() -> Self {
2132        Self {
2133            primary_neon: [0.2, 0.4, 0.6, 1.0], // Muted blue
2134            shatter_neon: [0.5, 0.5, 0.5, 1.0], // Neutral gray
2135            glass_base: [0.1, 0.12, 0.15, 1.0], // Solid slate
2136            glass_edge: [0.3, 0.35, 0.4, 1.0], // Subtle border
2137            rune_glow: [0.8, 0.8, 0.8, 0.0],    // Runes disabled
2138            ember_core: [0.5, 0.5, 0.5, 1.0],
2139            background_deep: [0.05, 0.05, 0.07, 1.0],
2140            mani_glow: [0.0, 0.0, 0.0, 0.0],    // No cursor glow
2141            glass_blur_strength: 0.0,           // No blur
2142            shatter_edge_width: 1.0,
2143            neon_bloom_radius: 0.0,
2144            rune_opacity: 0.0,
2145        }
2146    }
2147
2148    pub fn cyberpunk_viking() -> Self {
2149        Self::asgard()
2150    }
2151    pub fn vibrant_glass() -> Self {
2152        Self {
2153            primary_neon: [0.0, 1.0, 0.95, 1.2],
2154            shatter_neon: [1.0, 0.0, 0.75, 1.5],
2155            glass_base: [0.55, 0.6, 0.7, 0.08], // Luminous cool tint
2156            glass_edge: [0.7, 0.85, 1.0, 0.45], // Subtle blue-white rim
2157            rune_glow: [0.75, 0.98, 1.0, 0.9],
2158            ember_core: [1.0, 0.4, 0.1, 1.0],
2159            background_deep: [0.05, 0.05, 0.1, 1.0],
2160            mani_glow: [0.7, 0.9, 1.0, 0.05],
2161            glass_blur_strength: 0.9,
2162            shatter_edge_width: 1.8,
2163            neon_bloom_radius: 0.022,
2164            rune_opacity: 0.55,
2165        }
2166    }
2167}
2168impl Default for ColorTheme {
2169    fn default() -> Self {
2170        Self::vibrant_glass()
2171    }
2172}
2173/// Per-frame scene state for the Berserker pipeline.
2174#[repr(C)]
2175#[derive(Copy, Clone, Debug, Pod, Zeroable, serde::Serialize, serde::Deserialize)]
2176pub struct SceneUniforms {
2177    pub view: glam::Mat4,
2178    pub proj: glam::Mat4,
2179    pub time: f32,
2180    pub delta_time: f32,
2181    pub resolution: [f32; 2],
2182    pub mouse: [f32; 2],
2183    pub mouse_velocity: [f32; 2],
2184    pub shatter_origin: [f32; 2],
2185    pub shatter_time: f32,
2186    pub shatter_force: f32,
2187    pub berzerker_rage: f32,
2188    pub berzerker_mode: u32,
2189    pub scroll_offset: f32,
2190    pub scale_factor: f32,
2191    pub scene_type: u32,
2192    pub _pad: [f32; 3], // Align to 16 bytes if needed, but current struct is 4x16 + 4x16 + 4x16 + ...
2193}
2194
2195pub const SCENE_AURORA: u32 = 0;
2196pub const SCENE_VOID: u32 = 1;
2197pub const SCENE_NEBULA: u32 = 2;
2198pub const SCENE_GLITCH: u32 = 3;
2199pub const SCENE_YGGDRASIL: u32 = 4;
2200
2201impl SceneUniforms {
2202    pub fn new(width: f32, height: f32) -> Self {
2203        Self {
2204            view: glam::Mat4::IDENTITY,
2205            proj: glam::Mat4::orthographic_lh(0.0, width, height, 0.0, -100.0, 100.0),
2206            time: 0.0,
2207            delta_time: 0.016,
2208            resolution: [width, height],
2209            mouse: [0.5, 0.5],
2210            mouse_velocity: [0.0, 0.0],
2211            shatter_origin: [0.5, 0.5],
2212            shatter_time: -100.0,
2213            shatter_force: 0.0,
2214            berzerker_rage: 0.0,
2215            berzerker_mode: 0,
2216            scroll_offset: 0.0,
2217            scale_factor: 1.0,
2218            scene_type: SCENE_AURORA,
2219            _pad: [0.0; 3],
2220        }
2221    }
2222}
2223/// A 3D mesh containing vertex and index data.
2224#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
2225pub struct Mesh {
2226    pub vertices: Vec<[f32; 3]>,
2227    pub normals: Vec<[f32; 3]>,
2228    pub indices: Vec<u32>,
2229}
2230impl Mesh {
2231    pub fn from_obj(data: &[u8]) -> anyhow::Result<Vec<Self>> {
2232        let mut cursor = std::io::Cursor::new(data);
2233        let (models, _) = tobj::load_obj_buf(&mut cursor, &tobj::LoadOptions::default(), |_| {
2234            Ok((Vec::new(), Default::default()))
2235        })?;
2236        let mut meshes = Vec::new();
2237        for m in models {
2238            let mesh = m.mesh;
2239            let vertices: Vec<[f32; 3]> = mesh
2240                .positions
2241                .chunks(3)
2242                .map(|c| [c[0], c[1], c[2]])
2243                .collect();
2244            let normals = if mesh.normals.is_empty() {
2245                vec![[0.0, 0.0, 1.0]; vertices.len()]
2246            } else {
2247                mesh.normals.chunks(3).map(|c| [c[0], c[1], c[2]]).collect()
2248            };
2249            meshes.push(Mesh {
2250                vertices,
2251                normals,
2252                indices: mesh.indices,
2253            });
2254        }
2255        Ok(meshes)
2256    }
2257    pub fn from_stl(data: &[u8]) -> anyhow::Result<Self> {
2258        let mut cursor = std::io::Cursor::new(data);
2259        let stl = stl_io::read_stl(&mut cursor)?;
2260        let vertices: Vec<[f32; 3]> = stl.vertices.iter().map(|v| [v[0], v[1], v[2]]).collect();
2261        let mut indices = Vec::new();
2262        for face in stl.faces {
2263            indices.push(face.vertices[0] as u32);
2264            indices.push(face.vertices[1] as u32);
2265            indices.push(face.vertices[2] as u32);
2266        }
2267        let normals = vec![[0.0, 0.0, 1.0]; vertices.len()];
2268        Ok(Mesh {
2269            vertices,
2270            normals,
2271            indices,
2272        })
2273    }
2274}
2275/// FrameRenderer extends Renderer with frame lifecycle management.
2276/// It is typically implemented by the host windowing/rendering environment.
2277pub trait FrameRenderer<E = ()>: Renderer {
2278    fn begin_frame(&mut self) -> E;
2279    fn render_frame(&mut self) {
2280        // Default implementation does nothing - override for custom frame rendering
2281    }
2282    fn end_frame(&mut self, encoder: E);
2283}
2284use std::sync::Arc;
2285type SubscriberList<T> = Arc<std::sync::Mutex<Vec<Box<dyn Fn(&T) + Send + Sync>>>>;
2286/// State wrapper that owns a value and notifies subscribers when changed
2287#[derive(Clone)]
2288pub struct State<T: Clone + Send + Sync + 'static> {
2289    swap: Arc<arc_swap::ArcSwap<T>>,
2290    metadata_swap: Arc<arc_swap::ArcSwap<Option<agents::MutationMetadata>>>,
2291    #[cfg(not(target_arch = "wasm32"))]
2292    tvar: Arc<stm::TVar<T>>,
2293    #[cfg(not(target_arch = "wasm32"))]
2294    metadata_tvar: Arc<stm::TVar<Option<agents::MutationMetadata>>>,
2295    subscribers: SubscriberList<T>,
2296    version: Arc<std::sync::atomic::AtomicU64>,
2297    resolution: agents::ConflictResolution,
2298}
2299impl<T: Clone + Send + Sync + 'static> State<T> {
2300    /// Create a new State with initial value
2301    pub fn new(value: T) -> Self {
2302        #[cfg(not(target_arch = "wasm32"))]
2303        let tvar = Arc::new(stm::TVar::new(value.clone()));
2304        #[cfg(not(target_arch = "wasm32"))]
2305        let metadata_tvar = Arc::new(stm::TVar::new(None));
2306        Self {
2307            swap: Arc::new(arc_swap::ArcSwap::from_pointee(value)),
2308            metadata_swap: Arc::new(arc_swap::ArcSwap::new(Arc::new(None))),
2309            #[cfg(not(target_arch = "wasm32"))]
2310            tvar,
2311            #[cfg(not(target_arch = "wasm32"))]
2312            metadata_tvar,
2313            subscribers: Arc::new(std::sync::Mutex::new(Vec::new())),
2314            version: Arc::new(std::sync::atomic::AtomicU64::new(0)),
2315            resolution: agents::ConflictResolution::default(),
2316        }
2317    }
2318    /// Set the conflict resolution strategy for this state.
2319    pub fn with_resolution(mut self, resolution: agents::ConflictResolution) -> Self {
2320        self.resolution = resolution;
2321        self
2322    }
2323    /// Get the current value
2324    pub fn get(&self) -> T {
2325        (**self.swap.load()).clone()
2326    }
2327    /// Set a new value, notifying all subscribers. Applies conflict resolution if agents are present.
2328    pub fn set(&self, value: T) {
2329        #[cfg(not(target_arch = "wasm32"))]
2330        let (was_skipped, final_val, final_meta) = stm::atomically(|tx| {
2331            let new_meta = agents::get_current_mutation_metadata();
2332            let existing_meta = self.metadata_tvar.read(tx)?;
2333            let mut skip = false;
2334            if self.resolution == agents::ConflictResolution::PriorityWins
2335                && let (Some(new_m), Some(old_m)) = (new_meta, existing_meta)
2336                && new_m.priority < old_m.priority {
2337                    skip = true;
2338            }
2339            if !skip {
2340                self.tvar.write(tx, value.clone())?;
2341                self.metadata_tvar.write(tx, new_meta)?;
2342                Ok((false, value.clone(), new_meta))
2343            } else {
2344                Ok((true, self.tvar.read(tx)?, existing_meta))
2345            }
2346        });
2347        #[cfg(target_arch = "wasm32")]
2348        let (was_skipped, final_val, final_meta) = (false, value, agents::get_current_mutation_metadata());
2349        if was_skipped {
2350            if let (Some(new_m), Some(old_m)) = (agents::get_current_mutation_metadata(), final_meta) {
2351                agents::notify_conflict(agents::ConflictEvent {
2352                    agent_id: new_m.agent_id,
2353                    priority: new_m.priority,
2354                    existing_agent_id: old_m.agent_id,
2355                    existing_priority: old_m.priority,
2356                    timestamp_ms: new_m.timestamp_ms,
2357                });
2358            }
2359            return;
2360        }
2361        self.swap.store(Arc::new(final_val.clone()));
2362        self.metadata_swap.store(Arc::new(final_meta));
2363        self.version.fetch_add(1, std::sync::atomic::Ordering::Release);
2364        let subs = Arc::clone(&self.subscribers);
2365        if crate::is_batching() {
2366            crate::enqueue_batch_task(Box::new(move || {
2367                let s = subs.lock().unwrap();
2368                for cb in s.iter() {
2369                    cb(&final_val);
2370                }
2371            }));
2372        } else {
2373            let s = subs.lock().unwrap();
2374            for cb in s.iter() {
2375                cb(&final_val);
2376            }
2377        }
2378    }
2379    pub fn mutate<F: Fn(&T) -> T>(&self, f: F) {
2380        #[cfg(not(target_arch = "wasm32"))]
2381        {
2382            let (was_skipped, final_val, final_meta) = stm::atomically(|tx| {
2383                let new_meta = agents::get_current_mutation_metadata();
2384                let existing_meta = self.metadata_tvar.read(tx)?;
2385                let mut skip = false;
2386                if self.resolution == agents::ConflictResolution::PriorityWins
2387                    && let (Some(new_m), Some(old_m)) = (new_meta, existing_meta)
2388                    && new_m.priority < old_m.priority {
2389                        skip = true;
2390                }
2391                if !skip {
2392                    let current = self.tvar.read(tx)?;
2393                    let next = f(&current);
2394                    self.tvar.write(tx, next.clone())?;
2395                    self.metadata_tvar.write(tx, new_meta)?;
2396                    Ok((false, next, new_meta))
2397                } else {
2398                    Ok((true, self.tvar.read(tx)?, existing_meta))
2399                }
2400            });
2401            if was_skipped {
2402                if let (Some(new_m), Some(old_m)) = (agents::get_current_mutation_metadata(), final_meta) {
2403                    agents::notify_conflict(agents::ConflictEvent {
2404                        agent_id: new_m.agent_id,
2405                        priority: new_m.priority,
2406                        existing_agent_id: old_m.agent_id,
2407                        existing_priority: old_m.priority,
2408                        timestamp_ms: new_m.timestamp_ms,
2409                    });
2410                }
2411                return;
2412            }
2413            self.swap.store(Arc::new(final_val.clone()));
2414            self.metadata_swap.store(Arc::new(final_meta));
2415            self.version.fetch_add(1, std::sync::atomic::Ordering::Release);
2416            let subs = Arc::clone(&self.subscribers);
2417            if crate::is_batching() {
2418                crate::enqueue_batch_task(Box::new(move || {
2419                    let s = subs.lock().unwrap();
2420                    for cb in s.iter() {
2421                        cb(&final_val);
2422                    }
2423                }));
2424            } else {
2425                let s = subs.lock().unwrap();
2426                for cb in s.iter() {
2427                    cb(&final_val);
2428                }
2429            }
2430        }
2431        #[cfg(target_arch = "wasm32")]
2432        {
2433            self.set(f(&self.get()));
2434        }
2435    }
2436    /// Get current version
2437    pub fn version(&self) -> u64 {
2438        self.version.load(std::sync::atomic::Ordering::Acquire)
2439    }
2440    /// Subscribe to state changes
2441    pub fn subscribe<F: Fn(&T) + Send + Sync + 'static>(&self, callback: F) {
2442        self.subscribers.lock().unwrap().push(Box::new(callback));
2443    }
2444}
2445use crate::runtime::NodeStateSnapshot;
2446use std::sync::atomic::{AtomicBool, Ordering};
2447use std::sync::OnceLock;
2448/// Global application state registry.
2449pub static SYSTEM_STATE: OnceLock<Arc<arc_swap::ArcSwap<KnowledgeState>>> = OnceLock::new();
2450#[cfg(not(target_arch = "wasm32"))]
2451static KNOWLEDGE_TVAR: OnceLock<stm::TVar<KnowledgeState>> = OnceLock::new();
2452static IS_BATCHING: AtomicBool = AtomicBool::new(false);
2453pub static IS_RENDERING: AtomicBool = AtomicBool::new(false);
2454pub static LAYOUT_DIRTY: AtomicBool = AtomicBool::new(false);
2455type BatchQueue = OnceLock<std::sync::Mutex<Vec<Box<dyn FnOnce() + Send + Sync>>>>;
2456static BATCH_QUEUE: BatchQueue = OnceLock::new();
2457/// Returns true if state updates are currently being batched.
2458pub fn is_batching() -> bool {
2459    IS_BATCHING.load(Ordering::Acquire)
2460}
2461/// Returns true if the system is currently in the render phase.
2462pub fn is_rendering() -> bool {
2463    IS_RENDERING.load(Ordering::Acquire)
2464}
2465/// Signals the start of the render phase. Mutations during this phase trigger warnings.
2466pub fn begin_render_phase() {
2467    IS_RENDERING.store(true, Ordering::Release);
2468}
2469/// Signals the end of the render phase.
2470pub fn end_render_phase() {
2471    IS_RENDERING.store(false, Ordering::Release);
2472}
2473/// Enqueues a notification task to be run when the current batch flushes.
2474pub fn enqueue_batch_task(task: Box<dyn FnOnce() + Send + Sync>) {
2475    let mut queue = BATCH_QUEUE
2476        .get_or_init(|| std::sync::Mutex::new(Vec::new()))
2477        .lock()
2478        .unwrap();
2479    queue.push(task);
2480}
2481/// Executes multiple state updates in a single batch, deferring all subscriber
2482/// notifications until the closure completes. This prevents layout thrashing
2483/// and redundant render cycles when modifying multiple independent states.
2484pub fn batch<F: FnOnce()>(f: F) {
2485    if IS_BATCHING.swap(true, Ordering::AcqRel) {
2486        // Already inside a batch, just execute
2487        f();
2488        return;
2489    }
2490    f();
2491    IS_BATCHING.store(false, Ordering::Release);
2492    let mut queue = BATCH_QUEUE
2493        .get_or_init(|| std::sync::Mutex::new(Vec::new()))
2494        .lock()
2495        .unwrap();
2496    let tasks: Vec<_> = queue.drain(..).collect();
2497    drop(queue);
2498    for task in tasks {
2499        task();
2500    }
2501}
2502/// Get a reference to the global system state.
2503pub fn get_system_state() -> Arc<arc_swap::ArcSwap<KnowledgeState>> {
2504    SYSTEM_STATE
2505        .get_or_init(|| Arc::new(arc_swap::ArcSwap::from_pointee(KnowledgeState::default())))
2506        .clone()
2507}
2508pub fn load_system_state() -> arc_swap::Guard<Arc<KnowledgeState>> {
2509    get_system_state().load()
2510}
2511pub fn update_system_state<F>(f: F)
2512where
2513    F: Fn(&KnowledgeState) -> KnowledgeState,
2514{
2515    if is_rendering() {
2516        log::warn!("LAYOUT THRASH DETECTED: System state mutated during render phase. This may trigger redundant layout passes and impact performance.");
2517    }
2518    LAYOUT_DIRTY.store(true, Ordering::SeqCst);
2519    let swap = get_system_state();
2520    let current = swap.load();
2521    let new_state = Arc::new(f(&current));
2522    swap.store(Arc::clone(&new_state));
2523    #[cfg(not(target_arch = "wasm32"))]
2524    {
2525        let tvar = KNOWLEDGE_TVAR
2526            .get_or_init(|| stm::TVar::new((*new_state).clone()));
2527        stm::atomically(|tx| tvar.write(tx, (*new_state).clone()));
2528    }
2529}
2530pub fn transact_system_state<F>(f: F)
2531where
2532    F: Fn(&KnowledgeState) -> KnowledgeState,
2533{
2534    #[cfg(not(target_arch = "wasm32"))]
2535    {
2536        if is_rendering() {
2537            log::warn!("LAYOUT THRASH DETECTED: System state mutated during render phase. This may trigger redundant layout passes and impact performance.");
2538        }
2539        let tvar = KNOWLEDGE_TVAR
2540            .get_or_init(|| {
2541                stm::TVar::new((**get_system_state().load()).clone())
2542            })
2543            .clone();
2544        let new_state = stm::atomically(move |tx| {
2545            let current = tvar.read(tx)?;
2546            let next = f(&current);
2547            tvar.write(tx, next.clone())?;
2548            Ok(next)
2549        });
2550        get_system_state().store(Arc::new(new_state));
2551    }
2552    #[cfg(target_arch = "wasm32")]
2553    {
2554        if is_rendering() {
2555            log::warn!("LAYOUT THRASH DETECTED: System state mutated during render phase. This may trigger redundant layout passes and impact performance.");
2556        }
2557        update_system_state(f);
2558    }
2559}
2560impl KnowledgeState {
2561    /// Create a new empty KnowledgeState.
2562    pub fn new() -> Self {
2563        Self::default()
2564    }
2565    /// Set a component's internal state.
2566    pub fn set_component_state<T: 'static + Send + Sync>(&mut self, id: u64, state: T) {
2567        self.component_states
2568            .insert(id, Arc::new(std::sync::RwLock::new(state)));
2569    }
2570/// Get a reference to a component's internal state.
2571    pub fn get_component_state<T: 'static + Send + Sync>(
2572        &self,
2573        id: u64,
2574    ) -> Option<Arc<std::sync::RwLock<T>>> {
2575        let lock = self.component_states.get(&id)?;
2576        // Try to downcast the Arc<RwLock<dyn Any>> to Arc<RwLock<T>>
2577let _inner: &std::sync::RwLock<dyn std::any::Any + Send + Sync> = lock;
2578        // We cannot directly cast Arc<RwLock<dyn Any>> to Arc<RwLock<T>>
2579        // Instead, return the raw state - this is a limitation of the design
2580        None // Placeholder - proper implementation would need a different design
2581    }
2582    /// Add a new fragment to memory.
2583    pub fn remember(&mut self, fragment: KnowledgeFragment) {
2584        self.fragments.insert(fragment.id.clone(), fragment);
2585    }
2586    /// Process a search query against the local knowledge base.
2587    pub fn process_query(&mut self, query: &str) {
2588        let query_lower = query.to_lowercase();
2589        let mut results: Vec<(f32, String)> = self
2590            .fragments
2591            .iter()
2592            .map(|(id, frag)| {
2593                let mut score = 0.0;
2594                if frag.summary.to_lowercase().contains(&query_lower) {
2595                    score += 1.0;
2596                }
2597                if frag.source.to_lowercase().contains(&query_lower) {
2598                    score += 0.5;
2599                }
2600                (score, id.clone())
2601            })
2602            .filter(|(score, _)| *score > 0.0)
2603            .collect();
2604        // Sort by relevance score
2605        results.sort_by(|a, b| b.0.partial_cmp(&a.0).unwrap());
2606        self.last_query_results = results.into_iter().map(|(_, id)| id).take(5).collect();
2607    }
2608    /// Captures a snapshot of the current state for debugging and hot-reloading.
2609    pub fn snapshot(&self) -> Vec<NodeStateSnapshot> {
2610        let mut snapshots = Vec::new();
2611        // Snapshots of agentic fragments
2612        for frag in self.fragments.values() {
2613            if let Ok(val) = serde_json::to_value(frag) {
2614                snapshots.push(NodeStateSnapshot { id: 0, state: val });
2615            }
2616        }
2617        snapshots
2618    }
2619}
2620/// A read/write projection into a `State<T>` owned elsewhere.
2621#[derive(Clone)]
2622pub struct Binding<T: Clone + Send + Sync + 'static> {
2623    swap: Arc<arc_swap::ArcSwap<T>>,
2624    #[cfg(not(target_arch = "wasm32"))]
2625    tvar: Arc<stm::TVar<T>>,
2626    version: Arc<std::sync::atomic::AtomicU64>,
2627}
2628impl<T: Clone + Send + Sync + 'static> Binding<T> {
2629    /// Create a binding from a State
2630    pub fn from_state(state: &State<T>) -> Self {
2631        Self {
2632            swap: Arc::clone(&state.swap),
2633            #[cfg(not(target_arch = "wasm32"))]
2634            tvar: Arc::clone(&state.tvar),
2635            version: Arc::clone(&state.version),
2636        }
2637    }
2638    /// Get the current value
2639    pub fn get(&self) -> T {
2640        (**self.swap.load()).clone()
2641    }
2642    /// Set a new value
2643    pub fn set(&self, value: T) {
2644        self.swap.store(Arc::new(value.clone()));
2645        #[cfg(not(target_arch = "wasm32"))]
2646        {
2647            let tvar = Arc::clone(&self.tvar);
2648            let v = value.clone();
2649            stm::atomically(move |tx| tvar.write(tx, v.clone()));
2650        }
2651        self.version.fetch_add(1, std::sync::atomic::Ordering::Release);
2652    }
2653    /// Get current version
2654    pub fn version(&self) -> u64 {
2655        self.version.load(std::sync::atomic::Ordering::Acquire)
2656    }
2657}
2658#[cfg(not(target_arch = "wasm32"))]
2659pub fn transact_pair<A, B, F>(state_a: &State<A>, state_b: &State<B>, f: F)
2660where
2661    A: Clone + Send + Sync + 'static,
2662    B: Clone + Send + Sync + 'static,
2663    F: Fn(&A, &B) -> (A, B),
2664{
2665    let tvar_a = Arc::clone(&state_a.tvar);
2666    let tvar_b = Arc::clone(&state_b.tvar);
2667    let (new_a, new_b) = stm::atomically(move |tx| {
2668        let a = tvar_a.read(tx)?;
2669        let b = tvar_b.read(tx)?;
2670        let (na, nb) = f(&a, &b);
2671        tvar_a.write(tx, na.clone())?;
2672        tvar_b.write(tx, nb.clone())?;
2673        Ok((na, nb))
2674    });
2675    state_a.swap.store(Arc::new(new_a.clone()));
2676    state_b.swap.store(Arc::new(new_b.clone()));
2677    state_a.version.fetch_add(1, std::sync::atomic::Ordering::Release);
2678    state_b.version.fetch_add(1, std::sync::atomic::Ordering::Release);
2679    let subs_a = Arc::clone(&state_a.subscribers);
2680    let subs_b = Arc::clone(&state_b.subscribers);
2681    if crate::is_batching() {
2682        crate::enqueue_batch_task(Box::new(move || {
2683            {
2684                let s = subs_a.lock().unwrap();
2685                for cb in s.iter() { cb(&new_a); }
2686            }
2687            {
2688                let s = subs_b.lock().unwrap();
2689                for cb in s.iter() { cb(&new_b); }
2690            }
2691        }));
2692    } else {
2693        {
2694            let s = subs_a.lock().unwrap();
2695            for cb in s.iter() { cb(&new_a); }
2696        }
2697        {
2698            let s = subs_b.lock().unwrap();
2699            for cb in s.iter() { cb(&new_b); }
2700        }
2701    }
2702}
2703use std::any::TypeId;
2704use std::sync::Mutex;
2705/// Global environment storage using TypeId as keys.
2706pub(crate) static ENVIRONMENT: OnceLock<
2707    Mutex<HashMap<TypeId, Box<dyn std::any::Any + Send + Sync>>>,
2708> = OnceLock::new();
2709/// Environment key type for accessing ambient values
2710///
2711/// Implement this trait to define a new environment key.
2712pub trait EnvKey: 'static + Send + Sync {
2713    /// The type of value stored in the environment
2714    type Value: Clone + Send + Sync + 'static;
2715    /// Get a default value for this key
2716    fn default_value() -> Self::Value;
2717}
2718/// Key for accessing the Yggdrasil design token tree
2719pub struct YggdrasilKey;
2720impl EnvKey for YggdrasilKey {
2721    type Value = YggdrasilTokens;
2722    fn default_value() -> Self::Value {
2723        default_tokens()
2724    }
2725}
2726// Duplicate AssetKey removed - original definition at line 63
2727/// System appearance (Light/Dark mode)
2728#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
2729pub enum Appearance {
2730    Light,
2731    Dark,
2732}
2733/// Orientation for layouts
2734#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
2735pub enum Orientation {
2736    Horizontal,
2737    Vertical,
2738}
2739/// Cross-axis alignment for layout containers.
2740#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
2741pub enum Alignment {
2742    #[default]
2743    Center,
2744    Leading,
2745    Trailing,
2746    Top,
2747    Bottom,
2748}
2749/// Main-axis distribution for linear layout containers.
2750#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
2751pub enum Distribution {
2752    #[default]
2753    Fill,
2754    Center,
2755    Leading,
2756    Trailing,
2757    SpaceBetween,
2758    SpaceAround,
2759    SpaceEvenly,
2760}
2761/// A color represented by RGBA components in the [0.0, 1.0] range.
2762#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
2763pub struct Color {
2764    pub r: f32,
2765    pub g: f32,
2766    pub b: f32,
2767    pub a: f32,
2768}
2769impl Color {
2770    pub const BLACK: Color = Color {
2771        r: 0.0,
2772        g: 0.0,
2773        b: 0.0,
2774        a: 1.0,
2775    };
2776    pub const WHITE: Color = Color {
2777        r: 1.0,
2778        g: 1.0,
2779        b: 1.0,
2780        a: 1.0,
2781    };
2782    pub const TRANSPARENT: Color = Color {
2783        r: 0.0,
2784        g: 0.0,
2785        b: 0.0,
2786        a: 0.0,
2787    };
2788    pub const RED: Color = Color {
2789        r: 1.0,
2790        g: 0.0,
2791        b: 0.0,
2792        a: 1.0,
2793    };
2794    pub const GREEN: Color = Color {
2795        r: 0.0,
2796        g: 1.0,
2797        b: 0.0,
2798        a: 1.0,
2799    };
2800    pub const BLUE: Color = Color {
2801        r: 0.0,
2802        g: 0.0,
2803        b: 1.0,
2804        a: 1.0,
2805    };
2806    pub const VIKING_GOLD: Color = Color {
2807        r: 1.0,
2808        g: 0.84,
2809        b: 0.0,
2810        a: 1.0,
2811    };
2812    pub const MAGENTA_LIQUID: Color = Color {
2813        r: 1.0,
2814        g: 0.0,
2815        b: 1.0,
2816        a: 1.0,
2817    };
2818    pub const TACTICAL_OBSIDIAN: Color = Color {
2819        r: 0.05,
2820        g: 0.05,
2821        b: 0.07,
2822        a: 1.0,
2823    };
2824    /// Calculate the relative luminance of the color as defined by WCAG 2.x
2825    pub fn relative_luminance(&self) -> f32 {
2826        fn res(c: f32) -> f32 {
2827            if c <= 0.03928 {
2828                c / 12.92
2829            } else {
2830                ((c + 0.055) / 1.055).powf(2.4)
2831            }
2832        }
2833        0.2126 * res(self.r) + 0.7152 * res(self.g) + 0.0722 * res(self.b)
2834    }
2835    /// Calculate the contrast ratio between this color and another color
2836    pub fn contrast_ratio(&self, other: &Color) -> f32 {
2837        let l1 = self.relative_luminance();
2838        let l2 = other.relative_luminance();
2839        if l1 > l2 {
2840            (l1 + 0.05) / (l2 + 0.05)
2841        } else {
2842            (l2 + 0.05) / (l1 + 0.05)
2843        }
2844    }
2845    pub const CYAN: Color = Color {
2846        r: 0.0,
2847        g: 1.0,
2848        b: 1.0,
2849        a: 1.0,
2850    };
2851    pub const YELLOW: Color = Color {
2852        r: 1.0,
2853        g: 1.0,
2854        b: 0.0,
2855        a: 1.0,
2856    };
2857    pub const MAGENTA: Color = Color {
2858        r: 1.0,
2859        g: 0.0,
2860        b: 1.0,
2861        a: 1.0,
2862    };
2863    pub const GRAY: Color = Color {
2864        r: 0.5,
2865        g: 0.5,
2866        b: 0.5,
2867        a: 1.0,
2868    };
2869    /// Create a new color from RGBA components.
2870    pub fn new(r: f32, g: f32, b: f32, a: f32) -> Self {
2871        Self { r, g, b, a }
2872    }
2873    /// Convert the color to a [r, g, b, a] array.
2874    pub fn as_array(&self) -> [f32; 4] {
2875        [self.r, self.g, self.b, self.a]
2876    }
2877}
2878impl View for Color {
2879    type Body = Never;
2880    fn body(self) -> Self::Body {
2881        unreachable!()
2882    }
2883    fn render(&self, renderer: &mut dyn Renderer, rect: Rect) {
2884        renderer.fill_rect(rect, self.as_array());
2885    }
2886}
2887/// Key for accessing the current system appearance
2888pub struct AppearanceKey;
2889impl EnvKey for AppearanceKey {
2890    type Value = Appearance;
2891    fn default_value() -> Self::Value {
2892        Appearance::Dark // Default to Dark (Ginnungagap) for Berserker aesthetic
2893    }
2894}
2895/// StyleResolver provides high-level access to themed values from the environment.
2896pub struct StyleResolver;
2897impl StyleResolver {
2898    /// Resolve a color from the current environment
2899    pub fn color(key: &str) -> String {
2900        let tokens = Environment::<YggdrasilKey>::new().get();
2901        let appearance = Environment::<AppearanceKey>::new().get();
2902        let is_dark = appearance == Appearance::Dark;
2903        tokens
2904            .get_color(key, is_dark)
2905            .unwrap_or_else(|| "#FF00FF".to_string()) // Default to MuspelMagenta on failure
2906    }
2907    /// Resolve a generic token value
2908    pub fn get<T: FromStr>(category: &str, key: &str) -> Option<T> {
2909        let tokens = Environment::<YggdrasilKey>::new().get();
2910        let appearance = Environment::<AppearanceKey>::new().get();
2911        let is_dark = appearance == Appearance::Dark;
2912        tokens.get(category, key, is_dark)
2913    }
2914}
2915/// The authoritative Cyberpunk Viking default tokens
2916pub fn default_tokens() -> YggdrasilTokens {
2917    let mut tokens = YggdrasilTokens::new();
2918    // Core Norse Colorways
2919    tokens.color.insert(
2920        "background".to_string(),
2921        TokenValue::Single {
2922            value: "#000000".to_string(), // Ginnungagap (The Void)
2923        },
2924    );
2925    tokens.color.insert(
2926        "primary".to_string(),
2927        TokenValue::Single {
2928            value: "#00FFFF".to_string(), // NiflCyan (Aesir Primary)
2929        },
2930    );
2931    tokens.color.insert(
2932        "secondary".to_string(),
2933        TokenValue::Single {
2934            value: "#FF00FF".to_string(), // MuspelMagenta (Berserker Secondary)
2935        },
2936    );
2937    tokens.color.insert(
2938        "surface".to_string(),
2939        TokenValue::Adaptive {
2940            light: "#FFFFFF".to_string(),
2941            dark: "#121212".to_string(),
2942        },
2943    );
2944    tokens.color.insert(
2945        "text".to_string(),
2946        TokenValue::Adaptive {
2947            light: "#000000".to_string(),
2948            dark: "#FFFFFF".to_string(),
2949        },
2950    );
2951    // Bifrost (Glassmorphism) - Frosted Style
2952    tokens.bifrost.insert(
2953        "blur".to_string(),
2954        TokenValue::Single {
2955            value: "25.0".to_string(),
2956        },
2957    );
2958    tokens.bifrost.insert(
2959        "saturation".to_string(),
2960        TokenValue::Single {
2961            value: "1.2".to_string(),
2962        },
2963    );
2964    tokens.bifrost.insert(
2965        "opacity".to_string(),
2966        TokenValue::Single {
2967            value: "0.65".to_string(),
2968        },
2969    );
2970    // Gungnir (Neon Glow)
2971    tokens.gungnir.insert(
2972        "intensity".to_string(),
2973        TokenValue::Single {
2974            value: "1.0".to_string(),
2975        },
2976    );
2977    tokens.gungnir.insert(
2978        "radius".to_string(),
2979        TokenValue::Single {
2980            value: "15.0".to_string(),
2981        },
2982    );
2983    // Mjolnir (Sharp Geometry)
2984    tokens.mjolnir.insert(
2985        "clip_angle".to_string(),
2986        TokenValue::Single {
2987            value: "12.0".to_string(),
2988        },
2989    );
2990    tokens.mjolnir.insert(
2991        "border_width".to_string(),
2992        TokenValue::Single {
2993            value: "2.0".to_string(),
2994        },
2995    );
2996    // Sleipnir (Spring Animation)
2997    tokens.anim.insert(
2998        "stiffness".to_string(),
2999        TokenValue::Single {
3000            value: "170.0".to_string(),
3001        },
3002    );
3003    tokens.anim.insert(
3004        "damping".to_string(),
3005        TokenValue::Single {
3006            value: "26.0".to_string(),
3007        },
3008    );
3009    tokens.anim.insert(
3010        "mass".to_string(),
3011        TokenValue::Single {
3012            value: "1.0".to_string(),
3013        },
3014    );
3015    // Accessibility
3016    tokens.accessibility.insert(
3017        "reduce_motion".to_string(),
3018        TokenValue::Single {
3019            value: "false".to_string(),
3020        },
3021    );
3022    tokens
3023}
3024/// Environment wrapper for accessing ambient values
3025pub struct Environment<K: EnvKey> {
3026    _marker: std::marker::PhantomData<K>,
3027}
3028impl<K: EnvKey> Default for Environment<K> {
3029    fn default() -> Self {
3030        Self::new()
3031    }
3032}
3033impl<K: EnvKey> Environment<K> {
3034    /// Create a new Environment
3035    pub fn new() -> Self {
3036        Self {
3037            _marker: std::marker::PhantomData,
3038        }
3039    }
3040    /// Get the current value from the environment
3041    pub fn get(&self) -> K::Value {
3042        if let Some(env_store) = ENVIRONMENT.get() {
3043            let env_lock = env_store.lock().unwrap();
3044            if let Some(val) = env_lock.get(&std::any::TypeId::of::<K>()) {
3045                if let Some(typed_val) = val.downcast_ref::<K::Value>() {
3046                    return typed_val.clone();
3047                } else {
3048                    log::warn!("Environment: Downcast failed for key type {:?}", std::any::type_name::<K>());
3049                }
3050            } else {
3051                log::debug!("Environment: Key not found: {:?}. Returning default.", std::any::type_name::<K>());
3052            }
3053        } else {
3054            log::debug!("Environment: Store not initialized. Key: {:?}. Returning default.", std::any::type_name::<K>());
3055        }
3056        K::default_value()
3057    }
3058}
3059/// Ambient environment management
3060pub mod env {
3061    /// Insert a value into the environment
3062    pub fn insert<K: super::EnvKey>(value: K::Value) {
3063        let store = super::ENVIRONMENT.get_or_init(|| std::sync::Mutex::new(std::collections::HashMap::new()));
3064        let mut env_map = store.lock().unwrap();
3065        env_map.insert(std::any::TypeId::of::<K>(), Box::new(value));
3066    }
3067    /// Remove a value from the environment.
3068    pub fn remove<K: super::EnvKey>() {
3069        if let Some(store) = super::ENVIRONMENT.get() {
3070            let mut env_map = store.lock().unwrap();
3071            env_map.remove(&std::any::TypeId::of::<K>());
3072        }
3073    }
3074}
3075/// Geometry modifiers
3076/// Size of the view in logical pixels
3077#[derive(Debug, Clone, Copy, PartialEq)]
3078pub struct Size {
3079    pub width: f32,
3080    pub height: f32,
3081}
3082
3083impl Size {
3084    pub const ZERO: Self = Self { width: 0.0, height: 0.0 };
3085
3086    pub fn new(width: f32, height: f32) -> Self {
3087        Self { width, height }
3088    }
3089}
3090
3091/// Insets for padding
3092#[derive(Debug, Clone, Copy, PartialEq)]
3093pub struct EdgeInsets {
3094    pub top: f32,
3095    pub leading: f32,
3096    pub bottom: f32,
3097    pub trailing: f32,
3098}
3099
3100impl EdgeInsets {
3101    /// Equal insets on all edges
3102    pub fn all(value: f32) -> Self {
3103        Self {
3104            top: value,
3105            leading: value,
3106            bottom: value,
3107            trailing: value,
3108        }
3109    }
3110
3111    /// Vertical insets (top and bottom)
3112    pub fn vertical(value: f32) -> Self {
3113        Self {
3114            top: value,
3115            leading: 0.0,
3116            bottom: value,
3117            trailing: 0.0,
3118        }
3119    }
3120
3121    /// Horizontal insets (leading and trailing)
3122    pub fn horizontal(value: f32) -> Self {
3123        Self {
3124            top: 0.0,
3125            leading: value,
3126            bottom: 0.0,
3127            trailing: value,
3128        }
3129    }
3130}
3131
3132/// Modifier to set the size of a view
3133#[derive(Debug, Clone, Copy, PartialEq)]
3134pub struct FrameModifier {
3135    pub width: Option<f32>,
3136    pub height: Option<f32>,
3137}
3138
3139impl Default for FrameModifier {
3140    fn default() -> Self {
3141        Self::new()
3142    }
3143}
3144
3145impl FrameModifier {
3146    pub fn new() -> Self {
3147        Self {
3148            width: None,
3149            height: None,
3150        }
3151    }
3152
3153    pub fn width(mut self, width: f32) -> Self {
3154        self.width = Some(width);
3155        self
3156    }
3157
3158    pub fn height(mut self, height: f32) -> Self {
3159        self.height = Some(height);
3160        self
3161    }
3162
3163    pub fn size(mut self, width: f32, height: f32) -> Self {
3164        self.width = Some(width);
3165        self.height = Some(height);
3166        self
3167    }
3168}
3169
3170impl ViewModifier for FrameModifier {
3171    fn modify<V: View>(self, content: V) -> impl View {
3172        ModifiedView::new(content, self)
3173    }
3174}
3175
3176/// Modifier to set the flex weight of a view
3177#[derive(Debug, Clone, Copy, PartialEq)]
3178pub struct FlexModifier {
3179    pub weight: f32,
3180}
3181
3182impl ViewModifier for FlexModifier {
3183    fn modify<V: View>(self, content: V) -> impl View {
3184        ModifiedView::new(content, self)
3185    }
3186
3187    fn child_flex_weight<V: View>(&self, _view: &V) -> f32 {
3188        self.weight
3189    }
3190}
3191
3192/// Modifier to offset a view
3193#[derive(Debug, Clone, Copy, PartialEq)]
3194pub struct OffsetModifier {
3195    pub x: f32,
3196    pub y: f32,
3197}
3198
3199impl OffsetModifier {
3200    pub fn new(x: f32, y: f32) -> Self {
3201        Self { x, y }
3202    }
3203}
3204
3205impl ViewModifier for OffsetModifier {
3206    fn modify<V: View>(self, content: V) -> impl View {
3207        ModifiedView::new(content, self)
3208    }
3209}
3210
3211/// Modifier to set the z-index of a view
3212#[derive(Debug, Clone, Copy, PartialEq, Eq)]
3213pub struct ZIndexModifier {
3214    pub z_index: i32,
3215}
3216
3217impl ZIndexModifier {
3218    pub fn new(z_index: i32) -> Self {
3219        Self { z_index }
3220    }
3221}
3222
3223impl ViewModifier for ZIndexModifier {
3224    fn modify<V: View>(self, content: V) -> impl View {
3225        ModifiedView::new(content, self)
3226    }
3227}
3228
3229/// Layout constraints for views
3230#[derive(Debug, Clone, Copy, PartialEq, Default)]
3231pub struct LayoutConstraints {
3232    pub min_width: Option<f32>,
3233    pub max_width: Option<f32>,
3234    pub min_height: Option<f32>,
3235    pub max_height: Option<f32>,
3236}
3237
3238/// Modifier to set layout constraints
3239#[derive(Debug, Clone, Copy, PartialEq)]
3240pub struct LayoutModifier {
3241    pub constraints: LayoutConstraints,
3242}
3243
3244impl LayoutModifier {
3245    pub fn new(constraints: LayoutConstraints) -> Self {
3246        Self { constraints }
3247    }
3248}
3249
3250impl ViewModifier for LayoutModifier {
3251    fn modify<V: View>(self, content: V) -> impl View {
3252        ModifiedView::new(content, self)
3253    }
3254}
3255
3256/// Modifier to handle platform safe areas
3257#[derive(Debug, Clone, Copy, PartialEq)]
3258pub struct SafeAreaModifier {
3259    pub ignores: bool,
3260}
3261
3262impl ViewModifier for SafeAreaModifier {
3263    fn modify<V: View>(self, content: V) -> impl View {
3264        ModifiedView::new(content, self)
3265    }
3266}
3267
3268/// Modifier to add elevation (shadow) to a view
3269#[derive(Debug, Clone, Copy, PartialEq)]
3270pub struct ElevationModifier {
3271    pub level: f32,
3272}
3273
3274impl ViewModifier for ElevationModifier {
3275    fn modify<V: View>(self, content: V) -> impl View {
3276        ModifiedView::new(content, self)
3277    }
3278
3279    fn render_view<V: View>(&self, view: &V, renderer: &mut dyn Renderer, rect: Rect) {
3280        if self.level > 0.0 {
3281            let radius = self.level * 2.0;
3282            let offset_y = self.level * 0.5;
3283            let shadow_color = [0.0, 0.0, 0.0, 0.3];
3284            renderer.push_shadow(radius, shadow_color, [0.0, offset_y]);
3285            view.render(renderer, rect);
3286            renderer.pop_shadow();
3287        } else {
3288            view.render(renderer, rect);
3289        }
3290    }
3291}
3292
3293// Layout subsystem
3294pub mod layout {
3295    use super::*;
3296
3297    // Layout pass scratch space
3298    pub struct LayoutCache {
3299        pub safe_area: SafeArea,
3300        size_cache: HashMap<(u64, u32, u32), Size>, // (ViewHash, ProposalW, ProposalH)
3301    }
3302
3303    impl Default for LayoutCache {
3304        fn default() -> Self {
3305            Self::new()
3306        }
3307    }
3308
3309    impl LayoutCache {
3310        pub fn new() -> Self {
3311            Self {
3312                safe_area: SafeArea::default(),
3313                size_cache: HashMap::new(),
3314            }
3315        }
3316
3317        pub fn clear(&mut self) {
3318            self.safe_area = SafeArea::default();
3319            self.size_cache.clear();
3320        }
3321
3322        pub fn get_size(&self, view_hash: u64, proposal: SizeProposal) -> Option<Size> {
3323            let pw = (proposal.width.unwrap_or(-1.0) * 100.0) as u32;
3324            let ph = (proposal.height.unwrap_or(-1.0) * 100.0) as u32;
3325            self.size_cache.get(&(view_hash, pw, ph)).copied()
3326        }
3327
3328        pub fn set_size(&mut self, view_hash: u64, proposal: SizeProposal, size: Size) {
3329            let pw = (proposal.width.unwrap_or(-1.0) * 100.0) as u32;
3330            let ph = (proposal.height.unwrap_or(-1.0) * 100.0) as u32;
3331            self.size_cache.insert((view_hash, pw, ph), size);
3332        }
3333
3334        /// Remove all cached size entries for a specific view hash.
3335        pub fn invalidate_view(&mut self, view_hash: u64) {
3336            self.size_cache.retain(|&(hash, _, _), _| hash != view_hash);
3337        }
3338    }
3339
3340    /// Proposed size from parent view
3341    #[derive(Debug, Clone, Copy, PartialEq)]
3342    pub struct SizeProposal {
3343        pub width: Option<f32>,
3344        pub height: Option<f32>,
3345    }
3346
3347    impl SizeProposal {
3348        pub fn unspecified() -> Self {
3349            Self {
3350                width: None,
3351                height: None,
3352            }
3353        }
3354
3355        pub fn width(width: f32) -> Self {
3356            Self {
3357                width: Some(width),
3358                height: None,
3359            }
3360        }
3361
3362        pub fn height(height: f32) -> Self {
3363            Self {
3364                width: None,
3365                height: Some(height),
3366            }
3367        }
3368
3369        pub fn tight(width: f32, height: f32) -> Self {
3370            Self {
3371                width: Some(width),
3372                height: Some(height),
3373            }
3374        }
3375
3376        pub fn new(width: Option<f32>, height: Option<f32>) -> Self {
3377            Self { width, height }
3378        }
3379    }
3380
3381    /// A view that can participate in layout
3382    pub trait LayoutView: Send {
3383        /// Propose a size for this view given the available space
3384        fn size_that_fits(
3385            &self,
3386            proposal: SizeProposal,
3387            subviews: &[&dyn LayoutView],
3388            cache: &mut LayoutCache,
3389        ) -> Size;
3390
3391        /// Place subviews within the given bounds
3392        fn place_subviews(
3393            &self,
3394            bounds: Rect,
3395            subviews: &mut [&mut dyn LayoutView],
3396            cache: &mut LayoutCache,
3397        );
3398
3399        /// Returns the flex weight of this view (default is 0.0, which means fixed/intrinsic)
3400        fn flex_weight(&self) -> f32 {
3401            0.0
3402        }
3403    }
3404    /// Edge insets for padding, margins, and safe areas
3405    #[derive(Debug, Clone, Copy, PartialEq, Default, Serialize, Deserialize)]
3406    pub struct EdgeInsets {
3407        pub top: f32,
3408        pub leading: f32,
3409        pub bottom: f32,
3410        pub trailing: f32,
3411    }
3412
3413    impl EdgeInsets {
3414        pub fn new(top: f32, leading: f32, bottom: f32, trailing: f32) -> Self {
3415            Self { top, leading, bottom, trailing }
3416        }
3417
3418        pub fn all(value: f32) -> Self {
3419            Self {
3420                top: value,
3421                leading: value,
3422                bottom: value,
3423                trailing: value,
3424            }
3425        }
3426    }
3427
3428    /// SafeArea constraints provided by the platform
3429    #[derive(Debug, Clone, Copy, PartialEq, Default, Serialize, Deserialize)]
3430    pub struct SafeArea {
3431        pub insets: EdgeInsets,
3432    }
3433
3434    /// Rectangle in logical pixels
3435    #[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
3436    pub struct Rect {
3437        pub x: f32,
3438        pub y: f32,
3439        pub width: f32,
3440        pub height: f32,
3441    }
3442
3443    impl Rect {
3444        pub fn new(x: f32, y: f32, width: f32, height: f32) -> Self {
3445            Self {
3446                x,
3447                y,
3448                width,
3449                height,
3450            }
3451        }
3452
3453        pub fn inset(&self, amount: f32) -> Self {
3454            Self {
3455                x: self.x + amount,
3456                y: self.y + amount,
3457                width: (self.width - amount * 2.0).max(0.0),
3458                height: (self.height - amount * 2.0).max(0.0),
3459            }
3460        }
3461
3462        pub fn offset(&self, dx: f32, dy: f32) -> Self {
3463            Self {
3464                x: self.x + dx,
3465                y: self.y + dy,
3466                ..*self
3467            }
3468        }
3469
3470        pub fn zero() -> Self {
3471            Self {
3472                x: 0.0,
3473                y: 0.0,
3474                width: 0.0,
3475                height: 0.0,
3476            }
3477        }
3478
3479        pub fn contains(&self, x: f32, y: f32) -> bool {
3480            x >= self.x && x <= self.x + self.width && y >= self.y && y <= self.y + self.height
3481        }
3482
3483        pub fn size(&self) -> Size {
3484            Size {
3485                width: self.width,
3486                height: self.height,
3487            }
3488        }
3489
3490        /// Split the rect horizontally into N equal pieces
3491        pub fn split_horizontal(&self, n: usize) -> Vec<Rect> {
3492            if n == 0 {
3493                return vec![];
3494            }
3495            let item_width = self.width / n as f32;
3496            (0..n)
3497                .map(|i| Rect {
3498                    x: self.x + i as f32 * item_width,
3499                    y: self.y,
3500                    width: item_width,
3501                    height: self.height,
3502                })
3503                .collect()
3504        }
3505
3506        /// Split the rect vertically into N equal pieces
3507        pub fn split_vertical(&self, n: usize) -> Vec<Rect> {
3508            if n == 0 {
3509                return vec![];
3510            }
3511            let item_height = self.height / n as f32;
3512            (0..n)
3513                .map(|i| Rect {
3514                    x: self.x,
3515                    y: self.y + i as f32 * item_height,
3516                    width: self.width,
3517                    height: item_height,
3518                })
3519                .collect()
3520        }
3521    }
3522}
3523
3524// Re-export layout items for convenience
3525pub use layout::{LayoutCache, LayoutView, Rect, SizeProposal};
3526// Size and FrameRenderer are pub items in this module; no re-export alias needed.
3527
3528pub mod runtime;
3529pub mod scene_graph;
3530pub mod agents;
3531pub mod material;
3532
3533
3534pub use scene_graph::{NodeId, bifrost_registry};
3535
3536// Duplicate AssetState removed - original definition at line 67
3537
3538/// AssetManager defines the interface for loading and caching external resources.
3539pub trait AssetManager: Send + Sync {
3540    /// Request an image asset. Returns the current state (Loading, Ready, or Error).
3541    fn load_image(&self, url: &str) -> AssetState<Arc<Vec<u8>>>;
3542
3543    /// Pre-load an image into the cache.
3544    fn preload_image(&self, url: &str);
3545}
3546
3547/// User input event types
3548#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
3549pub enum Event {
3550    PointerDown { x: f32, y: f32, button: u32 },
3551    PointerUp { x: f32, y: f32, button: u32 },
3552    PointerMove { x: f32, y: f32 },
3553    PointerClick { x: f32, y: f32, button: u32 },
3554    PointerEnter,
3555    PointerLeave,
3556    KeyDown { key: String },
3557    KeyUp { key: String },
3558    /// Input Method Editor event (e.g. CJK character composition)
3559    Ime(String),
3560}
3561
3562impl Event {
3563    /// Returns the canonical string name of the event for lookup in handler maps.
3564    pub fn name(&self) -> &'static str {
3565        match self {
3566            Self::PointerDown { .. } => "pointerdown",
3567            Self::PointerUp { .. } => "pointerup",
3568            Self::PointerMove { .. } => "pointermove",
3569            Self::PointerClick { .. } => "pointerclick",
3570            Self::PointerEnter => "pointerenter",
3571            Self::PointerLeave => "pointerleave",
3572            Self::KeyDown { .. } => "keydown",
3573            Self::KeyUp { .. } => "keyup",
3574            Self::Ime(_) => "ime",
3575        }
3576    }
3577}
3578
3579/// Response from an event handler
3580#[derive(Debug, Clone, Copy, PartialEq, Eq)]
3581pub enum EventResponse {
3582    Handled,
3583    Ignored,
3584}
3585
3586/// A basic implementation of AssetManager that can be overridden by platform backends.
3587pub struct DefaultAssetManager {
3588    cache: AssetCache,
3589}
3590type AssetCache = Arc<arc_swap::ArcSwap<HashMap<String, AssetState<Arc<Vec<u8>>>>>>;
3591
3592impl Default for DefaultAssetManager {
3593    fn default() -> Self {
3594        Self::new()
3595    }
3596}
3597
3598impl DefaultAssetManager {
3599    pub fn new() -> Self {
3600        Self {
3601            cache: Arc::new(arc_swap::ArcSwap::from_pointee(HashMap::new())),
3602        }
3603    }
3604}
3605
3606impl AssetManager for DefaultAssetManager {
3607    fn load_image(&self, url: &str) -> AssetState<Arc<Vec<u8>>> {
3608        if let Some(state) = self.cache.load().get(url) {
3609            return state.clone();
3610        }
3611
3612        self.cache.rcu(|map| {
3613            let mut m = (**map).clone();
3614            m.entry(url.to_string()).or_insert(AssetState::Loading);
3615            m
3616        });
3617        AssetState::Loading
3618    }
3619
3620    fn preload_image(&self, _url: &str) {}
3621}
3622
3623use std::future::Future;
3624
3625/// Suspense wrapper for asynchronous state management.
3626/// Integrates with State<T> to provide loading/error/ready states for async operations.
3627pub struct Suspense<T: Clone + Send + Sync + 'static> {
3628    inner: State<AssetState<T>>,
3629}
3630
3631impl<T: Clone + Send + Sync + 'static> Default for Suspense<T> {
3632    fn default() -> Self {
3633        Self::new()
3634    }
3635}
3636
3637impl<T: Clone + Send + Sync + 'static> Suspense<T> {
3638    pub fn new() -> Self {
3639        Self {
3640            inner: State::new(AssetState::Loading),
3641        }
3642    }
3643
3644    pub fn new_async<F>(future: F) -> Self
3645    where
3646        F: Future<Output = Result<T, String>> + Send + 'static,
3647    {
3648        let suspense = Self::new();
3649        let suspense_clone = suspense.clone();
3650        
3651        #[cfg(not(target_arch = "wasm32"))]
3652        {
3653            // Try to use an existing tokio runtime, or fallback to a dedicated thread
3654            if let Ok(handle) = tokio::runtime::Handle::try_current() {
3655                handle.spawn(async move {
3656                    let result = future.await;
3657                    match result {
3658                        Ok(val) => suspense_clone.inner.set(AssetState::Ready(val)),
3659                        Err(err) => suspense_clone.inner.set(AssetState::Error(err)),
3660                    }
3661                });
3662            } else {
3663                std::thread::spawn(move || {
3664                    let rt = tokio::runtime::Builder::new_current_thread()
3665                        .enable_all()
3666                        .build()
3667                        .unwrap();
3668                    rt.block_on(async {
3669                        let result = future.await;
3670                        match result {
3671                            Ok(val) => suspense_clone.inner.set(AssetState::Ready(val)),
3672                            Err(err) => suspense_clone.inner.set(AssetState::Error(err)),
3673                        }
3674                    });
3675                });
3676            }
3677        }
3678        #[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
3679        {
3680            wasm_bindgen_futures::spawn_local(async move {
3681                let result = future.await;
3682                match result {
3683                    Ok(val) => suspense_clone.inner.set(AssetState::Ready(val)),
3684                    Err(err) => suspense_clone.inner.set(AssetState::Error(err)),
3685                }
3686            });
3687        }
3688        
3689        suspense
3690    }
3691
3692    pub fn ready(value: T) -> Self {
3693        Self {
3694            inner: State::new(AssetState::Ready(value)),
3695        }
3696    }
3697
3698    pub fn error(message: impl Into<String>) -> Self {
3699        Self {
3700            inner: State::new(AssetState::Error(message.into())),
3701        }
3702    }
3703
3704    pub fn get(&self) -> AssetState<T> {
3705        self.inner.get()
3706    }
3707
3708    pub fn get_ref(&self) -> AssetState<T> {
3709        self.inner.get()
3710    }
3711
3712    pub fn is_loading(&self) -> bool {
3713        matches!(self.get(), AssetState::Loading)
3714    }
3715
3716    pub fn is_ready(&self) -> bool {
3717        matches!(self.get(), AssetState::Ready(_))
3718    }
3719
3720    pub fn is_error(&self) -> bool {
3721        matches!(self.get(), AssetState::Error(_))
3722    }
3723
3724    pub fn ready_value(&self) -> Option<T> {
3725        match self.get() {
3726            AssetState::Ready(value) => Some(value),
3727            _ => None,
3728        }
3729    }
3730
3731    pub fn error_message(&self) -> Option<String> {
3732        match self.get() {
3733            AssetState::Error(message) => Some(message),
3734            _ => None,
3735        }
3736    }
3737
3738    pub fn subscribe<F: Fn(&AssetState<T>) + Send + Sync + 'static>(&self, callback: F) {
3739        self.inner.subscribe(callback)
3740    }
3741
3742    pub fn inner_state(&self) -> &State<AssetState<T>> {
3743        &self.inner
3744    }
3745}
3746
3747impl<T: Clone + Send + Sync + 'static> Clone for Suspense<T> {
3748    fn clone(&self) -> Self {
3749        Self {
3750            inner: self.inner.clone(),
3751        }
3752    }
3753}
3754
3755impl<T: Clone + Send + Sync + 'static> From<T> for Suspense<T> {
3756    fn from(value: T) -> Self {
3757        Self::ready(value)
3758    }
3759}
3760
3761impl<T: Clone + Send + Sync + 'static> From<Result<T, String>> for Suspense<T> {
3762    fn from(result: Result<T, String>) -> Self {
3763        match result {
3764            Ok(value) => Self::ready(value),
3765            Err(error) => Self::error(error),
3766        }
3767    }
3768}
3769
3770#[cfg(test)]
3771mod phase1_test;
3772
3773/// Berserker mode states for the rendering pipeline.
3774#[derive(Debug, Clone, Copy, PartialEq, Eq)]
3775pub enum BerserkerMode {
3776    Normal,
3777    Rage,     // Red tint, slight shake
3778    Frenzy,   // Heavy red tint, motion blur, aggressive shake
3779    GodMode,  // Golden aura, lightning arcs
3780}
3781
3782/// Seer trait for AI-assisted UI components (inspired by Argmax OSS).
3783/// Allows components to receive "prophecies" (predictions) from an AI backend.
3784pub trait Seer: Send + Sync {
3785    /// Provide a prediction for the next user action or content.
3786    fn predict(&self, context: &str) -> String;
3787    /// Stream real-time "whispers" (transcriptions/intent).
3788    fn whispers(&self) -> Vec<String>;
3789}