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