| """ |
| ui/modern_components.py - ENHANCED VERSION |
| 🚀 Modern UI Components for ARF v3.3.9 with Complete Psychological Integration |
| Features: |
| 1. Design token system with CSS variables |
| 2. All psychological features (observation gate, sequencing, historical evidence, healing intent) |
| 3. Accessibility (ARIA labels, keyboard nav) |
| 4. Performance optimizations |
| 5. Dark mode support |
| 6. Integration with arf_modern_ui.py systems |
| """ |
|
|
| import json |
| from datetime import datetime, timezone |
| from typing import Dict, List, Any, Optional, Tuple |
| import plotly.graph_objects as go |
| import plotly.express as px |
| import numpy as np |
|
|
| |
| |
| |
| DESIGN_TOKENS = { |
| "colors": { |
| "primary": { |
| "50": "#eff6ff", |
| "100": "#dbeafe", |
| "200": "#bfdbfe", |
| "300": "#93c5fd", |
| "400": "#60a5fa", |
| "500": "#3b82f6", |
| "600": "#2563eb", |
| "700": "#1d4ed8", |
| "800": "#1e40af", |
| "900": "#1e3a8a" |
| }, |
| "success": { |
| "50": "#f0fdf4", |
| "100": "#dcfce7", |
| "200": "#bbf7d0", |
| "300": "#86efac", |
| "400": "#4ade80", |
| "500": "#22c55e", |
| "600": "#16a34a", |
| "700": "#15803d", |
| "800": "#166534", |
| "900": "#14532d" |
| }, |
| "warning": { |
| "50": "#fffbeb", |
| "100": "#fef3c7", |
| "200": "#fde68a", |
| "300": "#fcd34d", |
| "400": "#fbbf24", |
| "500": "#f59e0b", |
| "600": "#d97706", |
| "700": "#b45309", |
| "800": "#92400e", |
| "900": "#78350f" |
| }, |
| "danger": { |
| "50": "#fef2f2", |
| "100": "#fee2e2", |
| "200": "#fecaca", |
| "300": "#fca5a5", |
| "400": "#f87171", |
| "500": "#ef4444", |
| "600": "#dc2626", |
| "700": "#b91c1c", |
| "800": "#991b1b", |
| "900": "#7f1d1d" |
| }, |
| "neutral": { |
| "50": "#f8fafc", |
| "100": "#f1f5f9", |
| "200": "#e2e8f0", |
| "300": "#cbd5e1", |
| "400": "#94a3b8", |
| "500": "#64748b", |
| "600": "#475569", |
| "700": "#334155", |
| "800": "#1e293b", |
| "900": "#0f172a" |
| } |
| }, |
| "spacing": { |
| "1": "0.25rem", |
| "2": "0.5rem", |
| "3": "0.75rem", |
| "4": "1rem", |
| "5": "1.25rem", |
| "6": "1.5rem", |
| "8": "2rem", |
| "10": "2.5rem", |
| "12": "3rem", |
| "16": "4rem", |
| "20": "5rem" |
| }, |
| "typography": { |
| "fontSizes": { |
| "xs": "0.75rem", |
| "sm": "0.875rem", |
| "base": "1rem", |
| "lg": "1.125rem", |
| "xl": "1.25rem", |
| "2xl": "1.5rem", |
| "3xl": "1.875rem", |
| "4xl": "2.25rem" |
| }, |
| "fontWeights": { |
| "light": "300", |
| "normal": "400", |
| "medium": "500", |
| "semibold": "600", |
| "bold": "700", |
| "extrabold": "800" |
| } |
| }, |
| "breakpoints": { |
| "sm": "640px", |
| "md": "768px", |
| "lg": "1024px", |
| "xl": "1280px", |
| "2xl": "1536px" |
| }, |
| "shadows": { |
| "sm": "0 1px 2px 0 rgb(0 0 0 / 0.05)", |
| "md": "0 4px 6px -1px rgb(0 0 0 / 0.1)", |
| "lg": "0 10px 15px -3px rgb(0 0 0 / 0.1)", |
| "xl": "0 20px 25px -5px rgb(0 0 0 / 0.1)" |
| }, |
| "borderRadius": { |
| "sm": "0.25rem", |
| "md": "0.375rem", |
| "lg": "0.5rem", |
| "xl": "0.75rem", |
| "2xl": "1rem", |
| "full": "9999px" |
| } |
| } |
|
|
| |
| |
| |
| def inject_design_tokens() -> str: |
| """Inject CSS variables for design tokens into the page""" |
| css_variables = [] |
| |
| |
| for category, values in DESIGN_TOKENS.items(): |
| if isinstance(values, dict): |
| for key, value in values.items(): |
| if isinstance(value, dict): |
| for subkey, subvalue in value.items(): |
| css_variables.append(f"--{category}-{key}-{subkey}: {subvalue};") |
| else: |
| css_variables.append(f"--{category}-{key}: {value};") |
| |
| return f""" |
| <style id="design-tokens"> |
| :root {{ |
| {chr(10).join(css_variables)} |
| |
| /* Semantic aliases matching arf_modern_ui.py */ |
| --color-enterprise-primary: var(--colors-primary-500); |
| --color-success: var(--colors-success-500); |
| --color-warning: var(--colors-warning-500); |
| --color-danger: var(--colors-danger-500); |
| --color-oss-primary: var(--colors-success-500); |
| --color-surface-light: #ffffff; |
| --color-surface-dark: var(--colors-neutral-800); |
| --color-background-light: var(--colors-neutral-50); |
| --color-background-dark: var(--colors-neutral-900); |
| |
| /* Spacing aliases */ |
| --spacing-xs: var(--spacing-2); |
| --spacing-sm: var(--spacing-3); |
| --spacing-md: var(--spacing-4); |
| --spacing-lg: var(--spacing-6); |
| --spacing-xl: var(--spacing-8); |
| |
| /* Font families */ |
| --font-sans: system-ui, -apple-system, sans-serif; |
| --font-mono: 'JetBrains Mono', 'SF Mono', Monaco, 'Cascadia Code', monospace; |
| |
| /* Transitions matching arf_modern_ui.py */ |
| --transition-fast: 150ms cubic-bezier(0.4, 0, 0.2, 1); |
| --transition-normal: 300ms cubic-bezier(0.4, 0, 0.2, 1); |
| --transition-slow: 500ms cubic-bezier(0.4, 0, 0.2, 1); |
| }} |
| |
| /* Dark mode overrides */ |
| [data-theme="dark"] {{ |
| --colors-neutral-50: #0f172a; |
| --colors-neutral-100: #1e293b; |
| --colors-neutral-200: #334155; |
| --colors-neutral-300: #475569; |
| --colors-neutral-400: #64748b; |
| --colors-neutral-500: #94a3b8; |
| --colors-neutral-600: #cbd5e1; |
| --colors-neutral-700: #e2e8f0; |
| --colors-neutral-800: #f1f5f9; |
| --colors-neutral-900: #f8fafc; |
| }} |
| |
| /* Utility classes */ |
| .sr-only {{ |
| position: absolute; |
| width: 1px; |
| height: 1px; |
| padding: 0; |
| margin: -1px; |
| overflow: hidden; |
| clip: rect(0, 0, 0, 0); |
| white-space: nowrap; |
| border: 0; |
| }} |
| |
| .focus-ring {{ |
| outline: 2px solid var(--color-enterprise-primary); |
| outline-offset: 2px; |
| }} |
| |
| .focus-ring:focus:not(:focus-visible) {{ |
| outline: none; |
| }} |
| |
| @media (prefers-reduced-motion: reduce) {{ |
| *, |
| *::before, |
| *::after {{ |
| animation-duration: 0.01ms !important; |
| animation-iteration-count: 1 !important; |
| transition-duration: 0.01ms !important; |
| }} |
| }} |
| </style> |
| """ |
|
|
| |
| |
| |
| class ModernComponent: |
| """Base class for all modern components with consistent styling""" |
| |
| def __init__(self): |
| self.component_id = f"component_{datetime.now().timestamp()}" |
| |
| @staticmethod |
| def create_container(children: str, **kwargs) -> str: |
| """Create a responsive container""" |
| classes = kwargs.get('classes', '') |
| style = kwargs.get('style', '') |
| |
| return f""" |
| <div class="container {classes}" style="{style}"> |
| {children} |
| </div> |
| """ |
| |
| @staticmethod |
| def create_section(title: str = "", children: str = "", **kwargs) -> str: |
| """Create a semantic section with optional title""" |
| section_id = kwargs.get('id', '') |
| aria_label = kwargs.get('aria_label', title) |
| |
| title_html = f'<h2 class="section-title">{title}</h2>' if title else '' |
| |
| return f""" |
| <section id="{section_id}" class="section" aria-label="{aria_label}"> |
| {title_html} |
| <div class="section-content"> |
| {children} |
| </div> |
| </section> |
| """ |
|
|
| |
| |
| |
| class Card(ModernComponent): |
| """Card component with multiple variants""" |
| |
| @staticmethod |
| def create(content: str, **kwargs) -> str: |
| """Create a card with optional header and footer""" |
| title = kwargs.get('title', '') |
| footer = kwargs.get('footer', '') |
| variant = kwargs.get('variant', 'default') |
| border_color = kwargs.get('border_color', 'var(--colors-neutral-200)') |
| |
| variant_classes = { |
| 'default': 'card-default', |
| 'elevated': 'card-elevated', |
| 'outlined': 'card-outlined', |
| 'filled': 'card-filled' |
| } |
| |
| header_html = f""" |
| <div class="card-header"> |
| <h3 class="card-title">{title}</h3> |
| </div> |
| """ if title else '' |
| |
| footer_html = f""" |
| <div class="card-footer"> |
| {footer} |
| </div> |
| """ if footer else '' |
| |
| return f""" |
| <div class="card {variant_classes.get(variant, 'card-default')}" |
| style="--border-color: {border_color};"> |
| {header_html} |
| <div class="card-body"> |
| {content} |
| </div> |
| {footer_html} |
| </div> |
| """ |
| |
| @staticmethod |
| def create_metric(value: str, label: str, **kwargs) -> str: |
| """Create a metric card for KPIs""" |
| trend = kwargs.get('trend', None) |
| change = kwargs.get('change', '') |
| |
| trend_icon = { |
| 'up': '↗', |
| 'down': '↘', |
| 'neutral': '→' |
| }.get(trend, '') |
| |
| trend_color = { |
| 'up': 'var(--color-success)', |
| 'down': 'var(--color-danger)', |
| 'neutral': 'var(--colors-neutral-500)' |
| }.get(trend, 'var(--colors-neutral-500)') |
| |
| return f""" |
| <div class="card card-metric" role="status" aria-label="{label}: {value}"> |
| <div class="metric-value" aria-live="polite">{value}</div> |
| <div class="metric-label">{label}</div> |
| {f'<div class="metric-trend" style="color: {trend_color};">{trend_icon} {change}</div>' if trend else ''} |
| </div> |
| """ |
|
|
| |
| |
| |
| class ObservationGate(ModernComponent): |
| """Observation gate component showing system restraint - PSYCHOLOGICAL CORE""" |
| |
| @staticmethod |
| def create(confidence: float = 65.0, **kwargs) -> str: |
| """Create observation gate display with psychological restraint""" |
| reason = kwargs.get('reason', 'uncertainty_too_high_for_action') |
| frozen_until = kwargs.get('frozen_until', '') |
| |
| threshold = 70.0 |
| is_blocked = confidence < threshold |
| |
| |
| countdown_html = "" |
| if frozen_until: |
| try: |
| frozen_dt = datetime.fromisoformat(frozen_until.replace("Z", "+00:00")) |
| now = datetime.now(timezone.utc) |
| if frozen_dt.tzinfo is None: |
| frozen_dt = frozen_dt.replace(tzinfo=timezone.utc) |
| time_left = frozen_dt - now |
| minutes_left = max(0, int(time_left.total_seconds() / 60)) |
| countdown_html = f""" |
| <div class="countdown"> |
| <div class="countdown-label">Next evaluation:</div> |
| <div class="countdown-timer">{minutes_left}:00</div> |
| </div> |
| """ |
| except: |
| countdown_html = """ |
| <div class="countdown"> |
| <div class="countdown-label">Next evaluation:</div> |
| <div class="countdown-timer">5:00</div> |
| </div> |
| """ |
| |
| status_text = "Observation Gate: Awaiting confirmation" if is_blocked else "Observation Gate Cleared" |
| status_color = "var(--color-warning)" if is_blocked else "var(--color-success)" |
| icon = "⏳" if is_blocked else "✅" |
| |
| |
| restraint_message = """ |
| <div class="psych-message"> |
| <h4>Decision Intentionally Deferred</h4> |
| <p>The system has detected uncertainty (<strong>{confidence:.1f}% confidence</strong>) |
| and has <strong>chosen to observe</strong> rather than act. Historical evidence indicates |
| premature action increases risk by <strong>47%</strong>, so the system is enforcing an observation-first policy.</p> |
| <p class="psych-note"><em>"What you are seeing is not waiting. It is judgment under uncertainty."</em></p> |
| </div> |
| """ if is_blocked else """ |
| <div class="psych-message"> |
| <h4>Proceed with Policy Action</h4> |
| <p>Confidence exceeds threshold. System may proceed with sequenced actions. |
| Historical evidence will be consulted before any execution.</p> |
| </div> |
| """ |
| |
| return f""" |
| <div class="observation-gate" style="--status-color: {status_color};"> |
| <div class="observation-gate-header"> |
| <div class="observation-icon">{icon}</div> |
| <div class="observation-title"> |
| <h3>{status_text}</h3> |
| <p>System restraint engaged</p> |
| </div> |
| <div class="observation-badge"> |
| ACTIVE RESTRAINT |
| </div> |
| </div> |
| |
| <div class="observation-content"> |
| {restraint_message} |
| |
| <div class="confidence-comparison"> |
| <div class="confidence-item"> |
| <div class="confidence-label">Confidence Threshold</div> |
| <div class="confidence-value">{threshold}%</div> |
| <div class="confidence-note">Required for action</div> |
| </div> |
| |
| <div class="confidence-item"> |
| <div class="confidence-label">Current Confidence</div> |
| <div class="confidence-value" style="color: {status_color};">{confidence:.1f}%</div> |
| <div class="confidence-note">{"Below threshold → Observe" if is_blocked else "Above threshold → Proceed"}</div> |
| </div> |
| </div> |
| |
| <div class="confidence-visualization"> |
| <div class="confidence-scale"> |
| <div class="scale-marker" style="left: {confidence}%;"></div> |
| <div class="scale-bar" style="width: {confidence}%; background: {status_color};"></div> |
| </div> |
| <div class="scale-labels"> |
| <span>{"Observe" if is_blocked else "Ready"} ({confidence:.1f}%)</span> |
| <span>Threshold ({threshold}%)</span> |
| <span>{"Act" if is_blocked else "Proceed"} (75%+)</span> |
| </div> |
| </div> |
| |
| {countdown_html} |
| |
| <div class="prevented-actions"> |
| <h5>Prevented Actions (Contraindicated)</h5> |
| <div class="action-tags"> |
| <span class="action-tag">scale_during_retry_storm</span> |
| <span class="action-tag">add_capacity_during_amplification</span> |
| <span class="action-tag">any_action_during_high_uncertainty</span> |
| </div> |
| </div> |
| </div> |
| </div> |
| """ |
|
|
| class SequencingFlow(ModernComponent): |
| """Visualization of policy-enforced sequencing - PSYCHOLOGICAL CORE""" |
| |
| @staticmethod |
| def create(steps: List[Dict[str, Any]] = None, **kwargs) -> str: |
| """Create sequencing flow visualization""" |
| if steps is None: |
| steps = [ |
| {"title": "Dampening", "description": "Prevent amplification first", "badge": "REQUIRED"}, |
| {"title": "Concurrency", "description": "Manage load, then observe", "badge": "REQUIRED"}, |
| {"title": "Observe", "description": "Validate trends for 5+ minutes", "badge": "REQUIRED"}, |
| {"title": "Scale", "description": "Only if all previous succeed", "badge": "OPTIONAL"} |
| ] |
| |
| current_step = kwargs.get('current_step', 0) |
| |
| steps_html = [] |
| for i, step in enumerate(steps): |
| is_current = i == current_step |
| is_completed = i < current_step |
| is_future = i > current_step |
| |
| status_class = 'completed' if is_completed else 'current' if is_current else 'future' |
| |
| steps_html.append(f""" |
| <div class="sequencing-step {status_class}" data-step="{i}"> |
| <div class="step-number">{i + 1}</div> |
| <div class="step-content"> |
| <div class="step-title">{step.get('title', 'Step')}</div> |
| <div class="step-description">{step.get('description', '')}</div> |
| <div class="step-badge">{step.get('badge', 'REQUIRED')}</div> |
| </div> |
| </div> |
| """) |
| |
| |
| connectors_html = '<div class="step-connectors">' |
| for i in range(len(steps) - 1): |
| is_completed = i < current_step |
| connector_class = 'completed' if is_completed else '' |
| connectors_html += f'<div class="step-connector {connector_class}"></div>' |
| connectors_html += '</div>' |
| |
| return f""" |
| <div class="sequencing-flow"> |
| <div class="sequencing-header"> |
| <h3>🔄 Doctrinal Sequencing: Policy Over Reaction</h3> |
| <p>System enforces sequencing regardless of prediction confidence</p> |
| <div class="policy-badge">POLICY ENFORCED</div> |
| </div> |
| |
| <div class="sequencing-steps"> |
| {connectors_html} |
| {''.join(steps_html)} |
| </div> |
| |
| <div class="sequencing-constraint"> |
| <div class="constraint-icon">🎯</div> |
| <div class="constraint-content"> |
| <h4>Doctrinal Constraint: Scaling Cannot Appear First</h4> |
| <p>If retry amplification is detected, scaling is <strong>contraindicated entirely</strong>. |
| The system must observe stabilization before considering capacity increases. |
| Historical evidence shows scaling-first fails <strong>76%</strong> of the time during amplification.</p> |
| <p class="psych-note"><em>"What happened is more important than what might happen."</em></p> |
| </div> |
| </div> |
| </div> |
| """ |
|
|
| class ProcessDisplay(ModernComponent): |
| """Display for ARF processes (Detection, Recall, Decision) - PSYCHOLOGICAL CORE""" |
| |
| @staticmethod |
| def create(process_type: str, data: Dict[str, Any]) -> str: |
| """Create process display card""" |
| icons = { |
| 'detection': '🕵️♂️', |
| 'recall': '🧠', |
| 'decision': '🎯', |
| 'safety': '🛡️', |
| 'execution': '⚡', |
| 'learning': '📚' |
| } |
| |
| status_colors = { |
| 'active': 'var(--color-success)', |
| 'inactive': 'var(--colors-neutral-400)', |
| 'error': 'var(--color-danger)' |
| } |
| |
| icon = icons.get(process_type, '📊') |
| status = data.get('status', 'inactive') |
| title = data.get('title', process_type.title()) |
| description = data.get('description', '') |
| |
| |
| metrics_html = "" |
| if 'metrics' in data: |
| metrics = data['metrics'] |
| metrics_html = '<div class="process-metrics">' |
| for key, value in metrics.items(): |
| metrics_html += f""" |
| <div class="process-metric"> |
| <div class="metric-key">{key}</div> |
| <div class="metric-value">{value}</div> |
| </div> |
| """ |
| metrics_html += '</div>' |
| |
| |
| next_step_html = "" |
| if 'next_step' in data: |
| next_step_html = f""" |
| <div class="process-next-step"> |
| <div class="next-step-label">Next Step:</div> |
| <div class="next-step-value">{data['next_step']}</div> |
| </div> |
| """ |
| |
| |
| content_html = data.get('content', '') |
| if process_type == 'recall' and 'historical_evidence' in data: |
| content_html += f""" |
| <div class="psych-emphasis"> |
| <div class="emphasis-icon">🧠</div> |
| <div class="emphasis-content"> |
| <strong>Recall Dominance:</strong> Historical evidence outweighs predictive confidence. |
| The system prioritizes what <em>has happened</em> over what <em>might happen</em>. |
| </div> |
| </div> |
| """ |
| |
| return f""" |
| <div class="process-card" data-process="{process_type}" data-status="{status}"> |
| <div class="process-header"> |
| <div class="process-icon">{icon}</div> |
| <div class="process-title"> |
| <h4>{title}</h4> |
| <p>{description}</p> |
| </div> |
| <div class="process-status" style="--status-color: {status_colors.get(status, 'var(--colors-neutral-400)')};"> |
| STATUS: {status.upper()} |
| </div> |
| </div> |
| |
| <div class="process-body"> |
| {metrics_html} |
| {content_html} |
| {next_step_html} |
| </div> |
| </div> |
| """ |
|
|
| class HistoricalEvidencePanel(ModernComponent): |
| """Historical evidence panel - PSYCHOLOGICAL CORE (Recall Dominance)""" |
| |
| @staticmethod |
| def create(evidence_data: Dict[str, Any] = None, **kwargs) -> str: |
| """Create historical evidence panel showing recall dominance""" |
| if evidence_data is None: |
| evidence_data = { |
| "scaling_failures": [ |
| { |
| "date": "2024-11-15", |
| "environment": "prod-east", |
| "action": "Scale during retry storm", |
| "outcome": "Amplification increased 300%", |
| "lesson": "Scaling during amplification worsens the problem" |
| }, |
| { |
| "date": "2024-09-22", |
| "environment": "staging", |
| "action": "Add capacity without dampening", |
| "outcome": "45 min outage, $8.2K loss", |
| "lesson": "New capacity consumed by amplification loop" |
| } |
| ], |
| "dampening_successes": [ |
| { |
| "date": "2024-12-03", |
| "environment": "prod-west", |
| "action": "Request coalescing + backoff", |
| "outcome": "Resolved in 8 min, $5.1K saved", |
| "lesson": "Dampening broke amplification cycle" |
| }, |
| { |
| "date": "2024-10-17", |
| "environment": "prod-eu", |
| "action": "Circuit breaker + observability", |
| "outcome": "12 min recovery, 0 user impact", |
| "lesson": "Sequencing prevented escalation" |
| } |
| ] |
| } |
| |
| |
| failures_html = "" |
| for i, failure in enumerate(evidence_data.get('scaling_failures', [])[:3]): |
| failures_html += f""" |
| <div class="evidence-item evidence-failure"> |
| <div class="evidence-header"> |
| <div class="evidence-date">{failure.get('date', 'Unknown')} • {failure.get('environment', 'Unknown')}</div> |
| <div class="evidence-badge failure">FAILED</div> |
| </div> |
| <div class="evidence-content"> |
| <div class="evidence-action"><strong>Action:</strong> {failure.get('action', 'Unknown')}</div> |
| <div class="evidence-outcome"><strong>Outcome:</strong> {failure.get('outcome', 'Unknown')}</div> |
| <div class="evidence-lesson">"{failure.get('lesson', 'No lesson captured')}"</div> |
| </div> |
| </div> |
| """ |
| |
| |
| successes_html = "" |
| for i, success in enumerate(evidence_data.get('dampening_successes', [])[:3]): |
| successes_html += f""" |
| <div class="evidence-item evidence-success"> |
| <div class="evidence-header"> |
| <div class="evidence-date">{success.get('date', 'Unknown')} • {success.get('environment', 'Unknown')}</div> |
| <div class="evidence-badge success">SUCCESS</div> |
| </div> |
| <div class="evidence-content"> |
| <div class="evidence-action"><strong>Action:</strong> {success.get('action', 'Unknown')}</div> |
| <div class="evidence-outcome"><strong>Outcome:</strong> {success.get('outcome', 'Unknown')}</div> |
| <div class="evidence-lesson">"{success.get('lesson', 'No lesson captured')}"</div> |
| </div> |
| </div> |
| """ |
| |
| return f""" |
| <div class="historical-evidence-panel"> |
| <div class="evidence-header-main"> |
| <div> |
| <h3>🧠 Historical Evidence (Why Sequencing Matters)</h3> |
| <p>Real outcomes from similar incidents—this evidence dominates decision logic</p> |
| </div> |
| <div class="evidence-dominance-badge"> |
| Historical evidence outweighs model confidence |
| </div> |
| </div> |
| |
| <div class="evidence-comparison"> |
| <div class="evidence-column"> |
| <div class="column-header failure"> |
| <span>⛔</span> Scaling-First Failures |
| </div> |
| {failures_html if failures_html else ''' |
| <div class="evidence-empty"> |
| <div class="empty-icon">📊</div> |
| <div class="empty-text">Scaling-First Failures (Evidence Present)</div> |
| </div> |
| '''} |
| </div> |
| |
| <div class="evidence-column"> |
| <div class="column-header success"> |
| <span>✅</span> Dampening-First Successes |
| </div> |
| {successes_html if successes_html else ''' |
| <div class="evidence-empty"> |
| <div class="empty-icon">📊</div> |
| <div class="empty-text">Dampening-First Successes (Evidence Present)</div> |
| </div> |
| '''} |
| </div> |
| </div> |
| |
| <div class="psych-principle"> |
| <div class="principle-icon">🎯</div> |
| <div class="principle-content"> |
| <h4>If history shows failure, the system will not repeat it.</h4> |
| <p>The system prioritizes <strong>historical evidence over predictive confidence</strong>. |
| If scaling-first failed in similar conditions, scaling is contraindicated regardless of model confidence.</p> |
| <p class="psych-note"><em>"What happened is more important than what might happen."</em></p> |
| </div> |
| </div> |
| </div> |
| """ |
|
|
| class HealingIntentDisplay(ModernComponent): |
| """Formal HealingIntent display - PSYCHOLOGICAL CORE""" |
| |
| @staticmethod |
| def create(healing_intent: Dict[str, Any], **kwargs) -> str: |
| """Create formal HealingIntent display with all fields""" |
| confidence = healing_intent.get('confidence', 0.0) |
| primary_action = healing_intent.get('primary_action', '') |
| sequencing_rule = healing_intent.get('sequencing_rule', '') |
| preconditions = healing_intent.get('preconditions', []) |
| contraindications = healing_intent.get('contraindications', []) |
| reversibility = healing_intent.get('reversibility_statement', '') |
| historical_evidence = healing_intent.get('historical_evidence', []) |
| |
| |
| preconditions_html = "" |
| if preconditions: |
| preconditions_html = "<div class='preconditions-list'>" |
| for pre in preconditions: |
| preconditions_html += f"<div class='precondition-item'>• {pre}</div>" |
| preconditions_html += "</div>" |
| |
| |
| contraindications_html = "" |
| if contraindications: |
| contraindications_html = "<div class='contraindications-list'>" |
| for contra in contraindications: |
| contraindications_html += f"<div class='contraindication-item'>⛔ {contra}</div>" |
| contraindications_html += "</div>" |
| |
| |
| historical_html = "" |
| if historical_evidence: |
| historical_html = "<div class='historical-list'>" |
| for evidence in historical_evidence: |
| historical_html += f"<div class='historical-item'>📊 {evidence}</div>" |
| historical_html += "</div>" |
| |
| return f""" |
| <div class="healing-intent-display"> |
| <div class="intent-header"> |
| <div> |
| <h3>📝 Formal HealingIntent Created</h3> |
| <p>Preconditions checked, contraindications listed, reversibility guaranteed</p> |
| </div> |
| <div class="confidence-badge" style="--confidence-color: {'' if confidence >= 70 else 'var(--color-warning)'};"> |
| CONFIDENCE: {confidence:.1f}% |
| </div> |
| </div> |
| |
| <div class="intent-grid"> |
| <div class="intent-section"> |
| <div class="section-title">Primary Action</div> |
| <div class="section-content primary-action"> |
| {primary_action} |
| </div> |
| </div> |
| |
| <div class="intent-section"> |
| <div class="section-title">Sequencing Rule</div> |
| <div class="section-content sequencing-rule"> |
| {sequencing_rule} |
| </div> |
| </div> |
| </div> |
| |
| <div class="intent-details"> |
| <div class="detail-section"> |
| <div class="detail-title">Preconditions</div> |
| <div class="detail-content"> |
| {preconditions_html if preconditions_html else '<div class="empty-detail">No preconditions specified</div>'} |
| </div> |
| </div> |
| |
| <div class="detail-section"> |
| <div class="detail-title">Contraindications</div> |
| <div class="detail-content"> |
| {contraindications_html if contraindications_html else '<div class="empty-detail">No contraindications</div>'} |
| </div> |
| </div> |
| |
| <div class="detail-section"> |
| <div class="detail-title">Reversibility Statement</div> |
| <div class="detail-content reversibility"> |
| {reversibility if reversibility else '<div class="empty-detail">No reversibility statement</div>'} |
| </div> |
| </div> |
| </div> |
| |
| {historical_html if historical_html else ''} |
| |
| <div class="psych-doctrine"> |
| <div class="doctrine-icon">⚖️</div> |
| <div class="doctrine-content"> |
| <h4>Doctrinal Principle: Formal Documentation Prevents Mistakes</h4> |
| <p>Every HealingIntent must document preconditions, contraindications, and reversibility. |
| This formal structure ensures decisions are reviewable, reversible, and grounded in evidence.</p> |
| </div> |
| </div> |
| </div> |
| """ |
|
|
| |
| |
| |
| def create_component_styles() -> str: |
| """Create all component styles with psychological enhancements""" |
| return """ |
| <style> |
| /* Base styles */ |
| body, .gr-box, .gr-form, .gr-panel, .gr-tab, .gr-container { |
| background-color: var(--color-background-light) !important; |
| color: var(--colors-neutral-900) !important; |
| font-family: var(--font-sans); |
| } |
| |
| [data-theme="dark"] body, |
| [data-theme="dark"] .gr-box, |
| [data-theme="dark"] .gr-form, |
| [data-theme="dark"] .gr-panel, |
| [data-theme="dark"] .gr-tab, |
| [data-theme="dark"] .gr-container { |
| background-color: var(--color-background-dark) !important; |
| color: var(--colors-neutral-100) !important; |
| } |
| |
| /* Card styles */ |
| .card { |
| background: var(--color-surface-light); |
| border-radius: var(--borderRadius-lg); |
| padding: var(--spacing-6); |
| border: 1px solid var(--border-color, var(--colors-neutral-200)); |
| transition: box-shadow var(--transition-normal); |
| color: var(--colors-neutral-900); |
| } |
| |
| [data-theme="dark"] .card { |
| background: var(--color-surface-dark); |
| border-color: var(--colors-neutral-700); |
| color: var(--colors-neutral-100); |
| } |
| |
| .card:hover { |
| box-shadow: var(--shadows-md); |
| } |
| |
| /* Observation gate styles */ |
| .observation-gate { |
| border: 3px solid var(--status-color, var(--color-warning)); |
| border-radius: var(--borderRadius-xl); |
| padding: var(--spacing-6); |
| background: linear-gradient(135deg, |
| color-mix(in srgb, var(--status-color, var(--color-warning)) 5%, transparent), |
| color-mix(in srgb, var(--status-color, var(--color-warning)) 10%, transparent)); |
| margin: var(--spacing-6) 0; |
| color: var(--colors-neutral-900); |
| } |
| |
| [data-theme="dark"] .observation-gate { |
| color: var(--colors-neutral-100); |
| } |
| |
| .observation-gate-header { |
| display: flex; |
| align-items: center; |
| gap: var(--spacing-4); |
| margin-bottom: var(--spacing-4); |
| } |
| |
| .observation-icon { |
| font-size: 48px; |
| color: var(--status-color, var(--color-warning)); |
| } |
| |
| .observation-title h3 { |
| margin: 0; |
| color: color-mix(in srgb, var(--status-color, var(--color-warning)) 90%, var(--colors-neutral-900)); |
| font-size: var(--typography-fontSizes-2xl); |
| font-weight: var(--typography-fontWeights-bold); |
| } |
| |
| .observation-title p { |
| margin: var(--spacing-1) 0 0 0; |
| color: color-mix(in srgb, var(--status-color, var(--color-warning)) 70%, var(--colors-neutral-700)); |
| } |
| |
| .observation-badge { |
| margin-left: auto; |
| padding: var(--spacing-2) var(--spacing-4); |
| background: var(--status-color, var(--color-warning)); |
| color: white; |
| border-radius: var(--borderRadius-full); |
| font-size: var(--typography-fontSizes-xs); |
| font-weight: var(--typography-fontWeights-bold); |
| text-transform: uppercase; |
| letter-spacing: 1px; |
| } |
| |
| .psych-message { |
| background: white; |
| border: 2px solid var(--status-color, var(--color-warning)); |
| padding: var(--spacing-4); |
| margin: var(--spacing-4) 0; |
| border-radius: var(--borderRadius-lg); |
| } |
| |
| [data-theme="dark"] .psych-message { |
| background: var(--colors-neutral-800); |
| } |
| |
| .psych-message h4 { |
| margin: 0 0 var(--spacing-2) 0; |
| color: var(--colors-neutral-900); |
| font-size: var(--typography-fontSizes-lg); |
| } |
| |
| .psych-message p { |
| margin: var(--spacing-2) 0; |
| color: var(--colors-neutral-700); |
| line-height: 1.6; |
| } |
| |
| .psych-note { |
| font-style: italic; |
| color: var(--colors-neutral-600); |
| margin-top: var(--spacing-2); |
| border-left: 3px solid var(--status-color, var(--color-warning)); |
| padding-left: var(--spacing-3); |
| } |
| |
| .confidence-comparison { |
| display: grid; |
| grid-template-columns: 1fr 1fr; |
| gap: var(--spacing-4); |
| margin: var(--spacing-4) 0; |
| } |
| |
| .confidence-item { |
| background: var(--color-surface-light); |
| border-radius: var(--borderRadius-lg); |
| padding: var(--spacing-4); |
| text-align: center; |
| border: 1px solid var(--colors-neutral-200); |
| } |
| |
| [data-theme="dark"] .confidence-item { |
| background: var(--colors-neutral-800); |
| border-color: var(--colors-neutral-700); |
| } |
| |
| .confidence-label { |
| font-size: var(--typography-fontSizes-sm); |
| color: var(--colors-neutral-600); |
| text-transform: uppercase; |
| letter-spacing: 0.05em; |
| margin-bottom: var(--spacing-2); |
| } |
| |
| .confidence-value { |
| font-size: var(--typography-fontSizes-3xl); |
| font-weight: var(--typography-fontWeights-bold); |
| margin-bottom: var(--spacing-1); |
| } |
| |
| .confidence-note { |
| font-size: var(--typography-fontSizes-xs); |
| color: var(--colors-neutral-500); |
| } |
| |
| .confidence-visualization { |
| margin: var(--spacing-6) 0; |
| } |
| |
| .confidence-scale { |
| height: 8px; |
| background: var(--colors-neutral-200); |
| border-radius: var(--borderRadius-full); |
| position: relative; |
| margin: var(--spacing-4) 0 var(--spacing-2); |
| } |
| |
| .scale-bar { |
| height: 100%; |
| border-radius: var(--borderRadius-full); |
| transition: width var(--transition-normal); |
| } |
| |
| .scale-marker { |
| position: absolute; |
| top: -4px; |
| width: 16px; |
| height: 16px; |
| background: white; |
| border: 2px solid var(--colors-neutral-900); |
| border-radius: 50%; |
| transform: translateX(-50%); |
| } |
| |
| .scale-labels { |
| display: flex; |
| justify-content: space-between; |
| font-size: var(--typography-fontSizes-xs); |
| color: var(--colors-neutral-600); |
| } |
| |
| .prevented-actions { |
| margin-top: var(--spacing-6); |
| padding-top: var(--spacing-4); |
| border-top: 2px solid var(--colors-neutral-200); |
| } |
| |
| .prevented-actions h5 { |
| margin: 0 0 var(--spacing-3) 0; |
| color: var(--colors-neutral-700); |
| font-size: var(--typography-fontSizes-sm); |
| text-transform: uppercase; |
| letter-spacing: 0.05em; |
| } |
| |
| .action-tags { |
| display: flex; |
| flex-wrap: wrap; |
| gap: var(--spacing-2); |
| } |
| |
| .action-tag { |
| padding: var(--spacing-1) var(--spacing-3); |
| background: var(--color-danger); |
| color: white; |
| border-radius: var(--borderRadius-full); |
| font-size: var(--typography-fontSizes-xs); |
| font-weight: var(--typography-fontWeights-medium); |
| } |
| |
| /* Sequencing flow styles */ |
| .sequencing-flow { |
| background: var(--color-surface-light); |
| border: 2px solid var(--color-enterprise-primary); |
| border-radius: var(--borderRadius-xl); |
| padding: var(--spacing-6); |
| margin: var(--spacing-6) 0; |
| } |
| |
| [data-theme="dark"] .sequencing-flow { |
| background: var(--colors-neutral-800); |
| } |
| |
| .sequencing-header { |
| margin-bottom: var(--spacing-6); |
| text-align: center; |
| } |
| |
| .sequencing-header h3 { |
| margin: 0 0 var(--spacing-2) 0; |
| color: var(--colors-neutral-900); |
| font-size: var(--typography-fontSizes-xl); |
| } |
| |
| .sequencing-header p { |
| margin: 0; |
| color: var(--colors-neutral-600); |
| } |
| |
| .policy-badge { |
| display: inline-block; |
| margin-top: var(--spacing-3); |
| padding: var(--spacing-2) var(--spacing-4); |
| background: var(--color-enterprise-primary); |
| color: white; |
| border-radius: var(--borderRadius-full); |
| font-size: var(--typography-fontSizes-xs); |
| font-weight: var(--typography-fontWeights-bold); |
| text-transform: uppercase; |
| letter-spacing: 1px; |
| } |
| |
| .sequencing-steps { |
| display: flex; |
| justify-content: space-between; |
| align-items: center; |
| position: relative; |
| margin: var(--spacing-8) 0; |
| } |
| |
| .step-connectors { |
| position: absolute; |
| top: 30px; |
| left: 60px; |
| right: 60px; |
| display: flex; |
| justify-content: space-between; |
| z-index: 1; |
| } |
| |
| .step-connector { |
| flex: 1; |
| height: 3px; |
| background: var(--colors-neutral-300); |
| margin: 0 var(--spacing-2); |
| } |
| |
| .step-connector.completed { |
| background: linear-gradient(90deg, var(--color-enterprise-primary), var(--color-success)); |
| } |
| |
| .sequencing-step { |
| text-align: center; |
| position: relative; |
| z-index: 2; |
| flex: 1; |
| } |
| |
| .step-number { |
| width: 60px; |
| height: 60px; |
| background: var(--colors-neutral-100); |
| color: var(--colors-neutral-700); |
| border-radius: 50%; |
| display: flex; |
| align-items: center; |
| justify-content: center; |
| margin: 0 auto var(--spacing-3); |
| font-size: var(--typography-fontSizes-xl); |
| font-weight: var(--typography-fontWeights-bold); |
| border: 4px solid white; |
| transition: all var(--transition-normal); |
| } |
| |
| .sequencing-step.current .step-number { |
| background: var(--color-enterprise-primary); |
| color: white; |
| box-shadow: 0 4px 12px rgba(59, 130, 246, 0.3); |
| } |
| |
| .sequencing-step.completed .step-number { |
| background: var(--color-success); |
| color: white; |
| } |
| |
| .step-title { |
| font-size: var(--typography-fontSizes-base); |
| font-weight: var(--typography-fontWeights-bold); |
| color: var(--colors-neutral-900); |
| margin-bottom: var(--spacing-1); |
| } |
| |
| .step-description { |
| font-size: var(--typography-fontSizes-sm); |
| color: var(--colors-neutral-600); |
| margin-bottom: var(--spacing-2); |
| max-width: 180px; |
| margin: 0 auto; |
| } |
| |
| .step-badge { |
| display: inline-block; |
| padding: var(--spacing-1) var(--spacing-3); |
| background: var(--colors-neutral-100); |
| color: var(--colors-neutral-700); |
| border-radius: var(--borderRadius-full); |
| font-size: var(--typography-fontSizes-xs); |
| font-weight: var(--typography-fontWeights-bold); |
| margin-top: var(--spacing-2); |
| } |
| |
| .sequencing-step.current .step-badge { |
| background: var(--color-enterprise-primary); |
| color: white; |
| } |
| |
| .sequencing-constraint { |
| background: var(--colors-neutral-50); |
| border-radius: var(--borderRadius-lg); |
| padding: var(--spacing-4); |
| border-left: 4px solid var(--color-enterprise-primary); |
| margin-top: var(--spacing-6); |
| } |
| |
| [data-theme="dark"] .sequencing-constraint { |
| background: var(--colors-neutral-800); |
| } |
| |
| .constraint-icon { |
| font-size: 24px; |
| color: var(--color-enterprise-primary); |
| margin-bottom: var(--spacing-2); |
| } |
| |
| .constraint-content h4 { |
| margin: 0 0 var(--spacing-2) 0; |
| color: var(--colors-neutral-900); |
| font-size: var(--typography-fontSizes-lg); |
| } |
| |
| .constraint-content p { |
| margin: 0; |
| color: var(--colors-neutral-700); |
| line-height: 1.6; |
| } |
| |
| /* Historical evidence panel styles */ |
| .historical-evidence-panel { |
| border: 3px solid var(--color-enterprise-primary); |
| border-radius: var(--borderRadius-xl); |
| padding: var(--spacing-6); |
| margin: var(--spacing-6) 0; |
| background: var(--color-surface-light); |
| } |
| |
| [data-theme="dark"] .historical-evidence-panel { |
| background: var(--colors-neutral-800); |
| } |
| |
| .evidence-header-main { |
| display: flex; |
| justify-content: space-between; |
| align-items: center; |
| margin-bottom: var(--spacing-6); |
| } |
| |
| .evidence-header-main h3 { |
| margin: 0 0 var(--spacing-2) 0; |
| color: var(--colors-neutral-900); |
| font-size: var(--typography-fontSizes-xl); |
| } |
| |
| .evidence-header-main p { |
| margin: 0; |
| color: var(--colors-neutral-600); |
| } |
| |
| .evidence-dominance-badge { |
| padding: var(--spacing-2) var(--spacing-4); |
| background: var(--color-enterprise-primary); |
| color: white; |
| border-radius: var(--borderRadius-full); |
| font-size: var(--typography-fontSizes-xs); |
| font-weight: var(--typography-fontWeights-bold); |
| } |
| |
| .evidence-comparison { |
| display: grid; |
| grid-template-columns: 1fr 1fr; |
| gap: var(--spacing-6); |
| margin-bottom: var(--spacing-6); |
| } |
| |
| .evidence-column { |
| display: flex; |
| flex-direction: column; |
| gap: var(--spacing-4); |
| } |
| |
| .column-header { |
| font-size: var(--typography-fontSizes-lg); |
| font-weight: var(--typography-fontWeights-bold); |
| margin-bottom: var(--spacing-2); |
| display: flex; |
| align-items: center; |
| gap: var(--spacing-2); |
| } |
| |
| .column-header.failure { |
| color: var(--color-danger); |
| } |
| |
| .column-header.success { |
| color: var(--color-success); |
| } |
| |
| .evidence-item { |
| border-left: 4px solid; |
| padding-left: var(--spacing-4); |
| margin-bottom: var(--spacing-3); |
| } |
| |
| .evidence-failure { |
| border-left-color: var(--color-danger); |
| } |
| |
| .evidence-success { |
| border-left-color: var(--color-success); |
| } |
| |
| .evidence-header { |
| display: flex; |
| justify-content: space-between; |
| align-items: flex-start; |
| margin-bottom: var(--spacing-2); |
| } |
| |
| .evidence-date { |
| font-size: var(--typography-fontSizes-sm); |
| font-weight: var(--typography-fontWeights-semibold); |
| color: var(--colors-neutral-900); |
| } |
| |
| .evidence-badge { |
| padding: 2px 8px; |
| border-radius: var(--borderRadius-full); |
| font-size: var(--typography-fontSizes-xs); |
| font-weight: var(--typography-fontWeights-bold); |
| } |
| |
| .evidence-badge.failure { |
| background: var(--color-danger); |
| color: white; |
| } |
| |
| .evidence-badge.success { |
| background: var(--color-success); |
| color: white; |
| } |
| |
| .evidence-content { |
| font-size: var(--typography-fontSizes-sm); |
| } |
| |
| .evidence-action { |
| color: var(--colors-neutral-700); |
| margin-bottom: var(--spacing-1); |
| } |
| |
| .evidence-outcome { |
| color: var(--colors-neutral-600); |
| margin-bottom: var(--spacing-2); |
| font-weight: var(--typography-fontWeights-medium); |
| } |
| |
| .evidence-failure .evidence-outcome { |
| color: var(--color-danger); |
| } |
| |
| .evidence-success .evidence-outcome { |
| color: var(--color-success); |
| } |
| |
| .evidence-lesson { |
| font-style: italic; |
| color: var(--colors-neutral-500); |
| background: var(--colors-neutral-50); |
| padding: var(--spacing-2); |
| border-radius: var(--borderRadius-md); |
| font-size: var(--typography-fontSizes-xs); |
| } |
| |
| [data-theme="dark"] .evidence-lesson { |
| background: var(--colors-neutral-700); |
| } |
| |
| .psych-principle { |
| background: linear-gradient(135deg, var(--colors-primary-50), var(--colors-neutral-50)); |
| border-radius: var(--borderRadius-lg); |
| padding: var(--spacing-4); |
| border: 2px solid var(--colors-primary-300); |
| margin-top: var(--spacing-6); |
| } |
| |
| [data-theme="dark"] .psych-principle { |
| background: linear-gradient(135deg, var(--colors-primary-900), var(--colors-neutral-800)); |
| border-color: var(--colors-primary-700); |
| } |
| |
| .principle-icon { |
| font-size: 28px; |
| color: var(--color-enterprise-primary); |
| margin-bottom: var(--spacing-2); |
| } |
| |
| .principle-content h4 { |
| margin: 0 0 var(--spacing-2) 0; |
| color: var(--colors-neutral-900); |
| font-size: var(--typography-fontSizes-lg); |
| } |
| |
| .principle-content p { |
| margin: 0; |
| color: var(--colors-neutral-700); |
| line-height: 1.6; |
| } |
| |
| /* Healing intent display styles */ |
| .healing-intent-display { |
| background: var(--color-surface-light); |
| border: 2px solid var(--color-success); |
| border-radius: var(--borderRadius-xl); |
| padding: var(--spacing-6); |
| margin: var(--spacing-6) 0; |
| } |
| |
| [data-theme="dark"] .healing-intent-display { |
| background: var(--colors-neutral-800); |
| } |
| |
| .intent-header { |
| display: flex; |
| justify-content: space-between; |
| align-items: center; |
| margin-bottom: var(--spacing-6); |
| padding-bottom: var(--spacing-4); |
| border-bottom: 2px solid var(--colors-neutral-200); |
| } |
| |
| .intent-header h3 { |
| margin: 0 0 var(--spacing-2) 0; |
| color: var(--colors-neutral-900); |
| font-size: var(--typography-fontSizes-xl); |
| } |
| |
| .intent-header p { |
| margin: 0; |
| color: var(--colors-neutral-600); |
| } |
| |
| .confidence-badge { |
| padding: var(--spacing-2) var(--spacing-4); |
| background: var(--confidence-color, var(--color-success)); |
| color: white; |
| border-radius: var(--borderRadius-full); |
| font-size: var(--typography-fontSizes-sm); |
| font-weight: var(--typography-fontWeights-bold); |
| text-transform: uppercase; |
| letter-spacing: 0.05em; |
| } |
| |
| .intent-grid { |
| display: grid; |
| grid-template-columns: 1fr 1fr; |
| gap: var(--spacing-4); |
| margin-bottom: var(--spacing-6); |
| } |
| |
| .intent-section { |
| background: var(--colors-neutral-50); |
| border-radius: var(--borderRadius-lg); |
| padding: var(--spacing-4); |
| } |
| |
| [data-theme="dark"] .intent-section { |
| background: var(--colors-neutral-700); |
| } |
| |
| .section-title { |
| font-size: var(--typography-fontSizes-sm); |
| color: var(--colors-neutral-600); |
| text-transform: uppercase; |
| letter-spacing: 0.05em; |
| margin-bottom: var(--spacing-2); |
| } |
| |
| .section-content { |
| font-size: var(--typography-fontSizes-base); |
| color: var(--colors-neutral-900); |
| font-weight: var(--typography-fontWeights-medium); |
| } |
| |
| [data-theme="dark"] .section-content { |
| color: var(--colors-neutral-100); |
| } |
| |
| .primary-action { |
| color: var(--color-success); |
| font-weight: var(--typography-fontWeights-semibold); |
| } |
| |
| .sequencing-rule { |
| color: var(--color-enterprise-primary); |
| font-family: var(--font-mono); |
| font-size: var(--typography-fontSizes-sm); |
| } |
| |
| .intent-details { |
| display: grid; |
| grid-template-columns: repeat(3, 1fr); |
| gap: var(--spacing-4); |
| margin-bottom: var(--spacing-6); |
| } |
| |
| .detail-section { |
| background: var(--colors-neutral-50); |
| border-radius: var(--borderRadius-lg); |
| padding: var(--spacing-4); |
| } |
| |
| [data-theme="dark"] .detail-section { |
| background: var(--colors-neutral-700); |
| } |
| |
| .detail-title { |
| font-size: var(--typography-fontSizes-sm); |
| color: var(--colors-neutral-600); |
| text-transform: uppercase; |
| letter-spacing: 0.05em; |
| margin-bottom: var(--spacing-2); |
| } |
| |
| .detail-content { |
| font-size: var(--typography-fontSizes-sm); |
| color: var(--colors-neutral-700); |
| line-height: 1.5; |
| } |
| |
| [data-theme="dark"] .detail-content { |
| color: var(--colors-neutral-300); |
| } |
| |
| .preconditions-list { |
| display: flex; |
| flex-direction: column; |
| gap: var(--spacing-1); |
| } |
| |
| .precondition-item { |
| color: var(--colors-neutral-700); |
| } |
| |
| .contraindications-list { |
| display: flex; |
| flex-direction: column; |
| gap: var(--spacing-1); |
| } |
| |
| .contraindication-item { |
| color: var(--color-danger); |
| font-weight: var(--typography-fontWeights-medium); |
| } |
| |
| .reversibility { |
| color: var(--color-success); |
| font-style: italic; |
| } |
| |
| .psych-doctrine { |
| background: linear-gradient(135deg, var(--colors-success-50), var(--colors-neutral-50)); |
| border-radius: var(--borderRadius-lg); |
| padding: var(--spacing-4); |
| border: 2px solid var(--colors-success-300); |
| margin-top: var(--spacing-6); |
| } |
| |
| [data-theme="dark"] .psych-doctrine { |
| background: linear-gradient(135deg, var(--colors-success-900), var(--colors-neutral-800)); |
| border-color: var(--colors-success-700); |
| } |
| |
| .doctrine-icon { |
| font-size: 28px; |
| color: var(--color-success); |
| margin-bottom: var(--spacing-2); |
| } |
| |
| .doctrine-content h4 { |
| margin: 0 0 var(--spacing-2) 0; |
| color: var(--colors-neutral-900); |
| font-size: var(--typography-fontSizes-lg); |
| } |
| |
| .doctrine-content p { |
| margin: 0; |
| color: var(--colors-neutral-700); |
| line-height: 1.6; |
| } |
| |
| /* Responsive adjustments */ |
| @media (max-width: 768px) { |
| .confidence-comparison { |
| grid-template-columns: 1fr; |
| } |
| |
| .sequencing-steps { |
| flex-direction: column; |
| gap: var(--spacing-6); |
| } |
| |
| .step-connectors { |
| display: none; |
| } |
| |
| .evidence-comparison { |
| grid-template-columns: 1fr; |
| } |
| |
| .intent-grid { |
| grid-template-columns: 1fr; |
| } |
| |
| .intent-details { |
| grid-template-columns: 1fr; |
| } |
| } |
| |
| @media (max-width: 480px) { |
| .observation-gate-header { |
| flex-direction: column; |
| text-align: center; |
| gap: var(--spacing-2); |
| } |
| |
| .observation-badge { |
| margin-left: 0; |
| margin-top: var(--spacing-2); |
| } |
| |
| .card { |
| padding: var(--spacing-3); |
| } |
| |
| .sequencing-flow, |
| .historical-evidence-panel, |
| .healing-intent-display { |
| padding: var(--spacing-3); |
| } |
| } |
| </style> |
| """ |
|
|
| |
| |
| |
| def initialize_modern_ui() -> str: |
| """Initialize all modern UI components and styles""" |
| components = [ |
| inject_design_tokens(), |
| create_component_styles(), |
| """ |
| <style> |
| /* Additional responsive utilities */ |
| .container { |
| width: 100%; |
| max-width: 1200px; |
| margin: 0 auto; |
| padding: 0 var(--spacing-4); |
| } |
| |
| @media (min-width: 768px) { |
| .container { |
| padding: 0 var(--spacing-6); |
| } |
| } |
| |
| @media (min-width: 1024px) { |
| .container { |
| padding: 0 var(--spacing-8); |
| } |
| } |
| </style> |
| """ |
| ] |
| |
| return "\n".join(components) |
|
|
| |
| |
| |
| __all__ = [ |
| |
| 'ModernComponent', 'Card', |
| |
| |
| 'ObservationGate', 'SequencingFlow', 'ProcessDisplay', |
| 'HistoricalEvidencePanel', 'HealingIntentDisplay', |
| |
| |
| 'DESIGN_TOKENS', |
| |
| |
| 'initialize_modern_ui', 'inject_design_tokens', 'create_component_styles' |
| ] |