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