Project file structure:
=======================
./
    data-analysis/
        BA_skill.md
        SKILL.md
        dashboard.md
        pipeline.py
        streamlit_da_dashaboard.md
    data-science/
        SKILL.md
        scientist.py
        __pycache__/
    frontend-web/
        SKILL.md
        __init__.py
        builder.py
        dna_scanner.py
        registry/
            registry_index.json
            backgrounds/
                AnimatedGradient.tsx
                AuroraBackground.tsx
                BGPattern.tsx
                BackgroundBeamsWithCollision.tsx
                BackgroundBoxes.tsx
                BackgroundGradientAnimation.tsx
                BeamsBackground.tsx
                BlueprintShader.tsx
                Dark Veil.tsx
                DottedSurface.tsx
                Entropy.tsx
                EtherealShadow.tsx
                FallingPattern.tsx
                Ferrofluid.tsx
                FlickeringGrid.tsx
                GradientBackground.tsx
                GradientDots.tsx
                GridPattern.tsx
                Light Pillar.tsx
                Lightfall.tsx
                Liquid Ether.tsx
                NeonMaze.tsx
                Particles.tsx
                PixelTrail.tsx
                Prism.tsx
                RetroGrid.tsx
                Silk.tsx
                SmokeBackground.tsx
                Sparkles.tsx
                SpiralAnimation.tsx
                Tiles.tsx
                Vortex.tsx
                VortexFullPage.tsx
                Waves.tsx
            cards/
                AIGenCard.tsx
                AnimatedBanner.tsx
                HoverPlayCard.tsx
                InfoCard.tsx
                VideoGeneratorCard.tsx
                VideoUploadCard.tsx
            core/
                utils.ts
            effects/
                BorderBeam.tsx
                Glow.tsx
                GooeyFilter.tsx
                Magnetic.tsx
                ShineBorder.tsx
            elements/
                AnimatedLink.tsx
                Counter.tsx
                SocialLinks.tsx
                Timestamp.tsx
                TopBanner.tsx
            footers/
                AnimatedSubscribeFooter.tsx
                AnimatedWaveFooter.tsx
                AppDownloadFooter.tsx
                BadgeFooter.tsx
                BorderedGridFooter.tsx
                BoxedMinimalFooter.tsx
                CenteredFooter.tsx
                CinematicFooter.tsx
                CorporateFooter.tsx
                FadeInFooter.tsx
                FlickeringGridFooter.tsx
                FloatingLogoFooter.tsx
                Footer1.tsx
                Footer2.tsx
                Footer4Col.tsx
                Footer7.tsx
                FooterNewsletter.tsx
                GradientCenteredFooter.tsx
                HoverTextFooter.tsx
                IconFooter.tsx
                LargeNameFooter.tsx
                MinimalFooter.tsx
                RadialGlowFooter.tsx
                StackedCircularFooter.tsx
                StatusFooter.tsx
                StickyFooter.tsx
                StickyRevealFooter.tsx
                TapedFooter.tsx
                TerminalFooter.tsx
                ThemeToggleFooter.tsx
                WordmarkFooter.tsx
            hero/
                BackgroundCircles.tsx
                BackgroundPaths.tsx
                HeroGeometric.tsx
                HeroHighlight.tsx
                HeroSection.tsx
                HeroWithVideo.tsx
                VHSHero.tsx
                VideoScrollHero.tsx
            media/
                DynamicFrameLayout.tsx
                HeroVideo.tsx
                HeroVideoDialog.tsx
                ScrollExpandMedia.tsx
                ThumbnailButton.tsx
                VideoModal.tsx
                VideoPlayer.tsx
                VideoPlayerPro.tsx
                VideoThumbnailPlayer.tsx
            modals/
                AnimatedDialog.tsx
                MorphingDialog.tsx
                PublishDialog.tsx
            navigation/
                AnimatedSidebar.tsx
                Breadcrumbs.tsx
                ExpandableSidebar.tsx
                FloatingHeader.tsx
                MacDock.tsx
                MegaMenuHeader.tsx
            sections/
                AboutGrid.tsx
                ClippedVideoTab.tsx
                DesignAgencyLanding.tsx
                FeaturedDemoGrid.tsx
                LinkInBioSection.tsx
                OnboardingChecklist.tsx
                WorkspaceWelcome.tsx
            text_effects/
                Blur Text.tsx
                GradientText.tsx
                ParticleText.tsx
                Scroll Float.tsx
                Shiny Text.tsx
                Shuffle.tsx
                Split Text.tsx
                Text Type.tsx
                UnderlineAnimation.tsx
        templates/
            components/
                Animation/
                Bento/
                Hero/
        ui-ux-pro-max/
            data/
            scripts/
                core.py
                design_system.py
                search.py
                __pycache__/
        Vite_pipeline/
            __init__.py
            pipeline.py
            __pycache__/
        __pycache__/


File Contents:
===============


--- FILE: data-analysis/BA_skill.md ---

# BA_skill_v2.md — The CXO Intelligence Dashboard Framework

---

## PRIME DIRECTIVE

You are a Principal BI Architect and Storyteller. Your job is not to display data. Your job is to **reveal the business narrative hidden inside a dataset** — so that a CXO sitting down for the first time understands in 60 seconds what is happening, what is at risk, and where the opportunity is.

Every chart is a sentence. Every tab is a chapter. The dashboard is a story.

---

## MANDATORY UPLOAD-FIRST CONSTRAINT

The dashboard MUST implement a strict two-phase architecture:

- **Phase 1 (on load):** Full-screen upload zone only. No charts. No KPIs. No data. Nothing.
- **Phase 2 (after upload):** Parse all files → build `let DATA = []` → call `renderDashboard(DATA)`.

The COLUMN_MANIFEST and domain_mapping.json in the prompt are **schema blueprints only**. They tell you what columns exist and their types. **They are never the data source.** Never hardcode any values from them into chart series, KPI calculations, labels, or filter options.

---

## DASHBOARD NAMING — MANDATORY

The dashboard title displayed in the header **must NOT be "Nova" or any generic placeholder**.

At file parse time, derive the dashboard name from:
1. The filename(s) uploaded (e.g. `sales_emea_2024.csv` → **"EMEA Sales Intelligence — 2024"**)
2. The domain identified from `domain_mapping → vertical` (e.g. `ecommerce` → **"E-Commerce Performance Command Center"**)
3. If both are available, combine: **"{Company/Dataset Name} — {Vertical} Intelligence Hub"**

Display this as the main `<h1>` in the header. Sub-label it with the record count and date range once loaded.

---

## VISUAL IDENTITY SYSTEM

### Aesthetic Direction
This is a **CXO-grade instrument panel**. The aesthetic is: **Refined Dark Intelligence** — like a Bloomberg terminal crossed with a luxury automotive HUD. Every pixel earns its place.

- **Primary font**: `Sora` or `DM Sans` (Google Fonts) for headers
- **Data font**: `JetBrains Mono` or `IBM Plex Mono` for numbers/metrics
- **Body/UI font**: `Inter` or `Outfit` for labels

### Color System (CSS variables — applied on `<html>` root)
```css
/* Dark Mode (default) */
--bg-base: #080d14;
--bg-surface: #0f1923;
--bg-card: #131f2e;
--bg-card-hover: #1a2840;
--border: #1e3448;
--border-accent: #2a4a6e;
--text-primary: #e8f1ff;
--text-secondary: #7a9abf;
--text-muted: #3d5a7a;
--accent-cyan: #00d4ff;
--accent-green: #00ff87;
--accent-amber: #ffb700;
--accent-red: #ff4560;
--accent-purple: #a78bfa;
--gradient-hero: linear-gradient(135deg, #00d4ff22, #00ff8711);

/* Light Mode */
--bg-base: #f0f4f9;
--bg-surface: #ffffff;
--bg-card: #ffffff;
--bg-card-hover: #f8fafc;
--border: #dde4ee;
--border-accent: #b8cde0;
--text-primary: #0d1f35;
--text-secondary: #4a6880;
--text-muted: #9ab0c4;
--accent-cyan: #0077cc;
--accent-green: #00994d;
--accent-amber: #cc8800;
--accent-red: #cc2233;
--accent-purple: #6d28d9;
--gradient-hero: linear-gradient(135deg, #0077cc11, #00994d11);
```

### ApexCharts Theme Palettes
```js
const CHART_PALETTE_DARK  = ['#00d4ff','#00ff87','#ffb700','#ff4560','#a78bfa','#ff6b35','#00b4d8','#90e0ef'];
const CHART_PALETTE_LIGHT = ['#0077cc','#00994d','#cc8800','#cc2233','#6d28d9','#e05a00','#0096c7','#48cae4'];
```

Always pass the active palette into every ApexCharts `colors` option. When the theme toggles, call `chart.updateOptions({ colors: activePalette, theme: {...} })` on every active chart instance.

### Card Style
All KPI and chart cards use:
- `background: var(--bg-card)` with `border: 1px solid var(--border)`
- `border-radius: 12px`
- `box-shadow: 0 4px 24px rgba(0,0,0,0.25)` (dark) / `0 2px 12px rgba(0,0,0,0.08)` (light)
- Glassmorphism for hero row: `backdrop-filter: blur(12px); background: rgba(255,255,255,0.03)`
- Hover: `border-color: var(--border-accent); transform: translateY(-2px); transition: all 0.2s ease`

---

## DATA INTELLIGENCE LOGIC

### PHASE 0 — Dashboard Name Derivation (at parse time)
```js
function deriveDashboardName(fileNames, domainMapping) {
  const rawName = fileNames[0].replace(/\.[^.]+$/, '').replace(/[_\-]/g, ' ');
  const titleCased = rawName.replace(/\w\S*/g, w => w[0].toUpperCase() + w.slice(1));
  const vertical = (domainMapping?.vertical || '').replace(/_/g, ' ');
  const verticalLabel = vertical ? ` — ${vertical.replace(/\w\S*/g, w => w[0].toUpperCase() + w.slice(1))} Intelligence` : ' Intelligence Hub';
  return titleCased + verticalLabel;
}
```

---

### PHASE 1 — Column Classification

Read the COLUMN_MANIFEST and classify every column. Use **both** `col_type` and column name semantics:

| Role | Detection Rule |
|---|---|
| **PRIMARY_METRIC** | numeric; name contains: revenue, amount, value, sales, price, cost, profit, score, rate, count, total, sum, quantity, margin, spend, budget, actual, target, kpi, units, volume |
| **DATETIME_AXIS** | col_type = datetime |
| **ENTITY** | categorical matching domain_mapping → entities; or name contains: owner, agent, rep, manager, team, assigned, salesperson, account, employee, region, territory, branch |
| **STATUS_STAGE** | categorical; name contains: status, stage, state, phase, type, category, disposition, result, outcome, priority, severity, tier |
| **GEOGRAPHY** | categorical; name contains: country, city, region, state, province, zip, postal, market, territory |
| **DIMENSION** | categorical; null_pct < 60%; ≤ 20 unique values; not already classified |
| **IDENTIFIER** | col_type = id_numeric or high_cardinality (> 100 unique values and not ENTITY) — exclude from all charts and filters |
| **BOOLEAN_FLAG** | col_type = boolean |
| **TEXT_FREE** | long strings, col_type = text — exclude from charts, show in Data Explorer only |

Build a classification registry at the top of your JS:
```js
const COLS = {
  metrics: [],      // PRIMARY_METRIC
  datetime: null,   // DATETIME_AXIS (first one)
  entities: [],     // ENTITY
  status: null,     // STATUS_STAGE (first one)
  dimensions: [],   // DIMENSION
  geography: null,  // GEOGRAPHY (first one)
  booleans: [],     // BOOLEAN_FLAG
  identifiers: [],  // excluded
};
```

---

### PHASE 2 — KPI Hero Row (always 8–12 cards)

Compute all KPIs from `DATA` after filtering. Priority order:

1. **Total Records** — `DATA.length` — always first, always present
2. **North Star** — column from `domain_mapping → north_star`; sum if numeric, top value + count if categorical
3. **Per PRIMARY_METRIC** (up to 4): 
   - If name contains `rate`, `score`, `pct`, `%` → show **mean** + sparkline trend
   - If name contains `revenue`, `sales`, `amount`, `value`, `cost`, `spend` → show **sum** formatted with currency abbreviation (K/M/B)
   - If name contains `count`, `quantity`, `units`, `volume` → show **sum** with comma formatting
4. **Growth delta**: if DATETIME_AXIS exists, compute latest-period vs prior-period % change for the North Star or primary metric. Show as `▲ +12.4%` (green) or `▼ -3.1%` (red)
5. **ENTITY coverage**: `new Set(DATA.map(r => r[entityCol])).size` → "Active {Entity}s"
6. **BOOLEAN_FLAG rates**: `(trueCount / total * 100).toFixed(1)%` for each boolean
7. **Completion / Fill rate**: if a STATUS_STAGE col exists, % of rows in the "terminal" stage (last by frequency or name heuristic: closed, complete, won, delivered, resolved)

**Delta display logic:**
```js
function computeDelta(data, col, dateCol) {
  // Split into two halves by date range median, compare sum/mean
  const sorted = [...data].sort((a,b) => new Date(a[dateCol]) - new Date(b[dateCol]));
  const mid = Math.floor(sorted.length / 2);
  const first = sorted.slice(0, mid);
  const second = sorted.slice(mid);
  const agg = arr => arr.reduce((s,r) => s + (parseFloat(r[col]) || 0), 0);
  const delta = ((agg(second) - agg(first)) / (agg(first) || 1)) * 100;
  return delta;
}
```

**Empty guard**: Any KPI that computes to NaN, null, Infinity, or 0 where 0 is not meaningful → display `"—"` with sub-label `"No data"`.

---

### PHASE 3 — THE FULL CHART SUITE

**Core principle**: Look at the classified columns and ask: *what is the most insightful question I can answer with this combination of columns?* Then pick the chart type that answers it most directly.

Build as many charts as the data supports, targeting **8–14 charts total** across all tabs. Use this master chart selection tree:

---

#### 3A — Time Intelligence Charts (requires DATETIME_AXIS)

**T1 — Trend Area Chart**
- Group by most useful period: ≤60 days → daily; ≤365 days → weekly; > 365 days → monthly
- Series: PRIMARY_METRIC or record count
- Type: ApexCharts `area` with gradient fill, smooth curves
- Add a 7-period moving average as a second series (dashed line)
- Empty guard: < 3 points → show message card

**T2 — Period-over-Period Bar Chart**
- Compare current period vs prior period for top PRIMARY_METRIC
- Group by ENTITY or DIMENSION
- Type: ApexCharts `bar` grouped with two series
- Annotate the bars where delta > ±20%

**T3 — Heatmap (if 365+ days of data)**
- X-axis: month of year (1–12), Y-axis: year or day-of-week
- Color intensity: sum of PRIMARY_METRIC
- Type: ApexCharts `heatmap`
- Reveals seasonality patterns

---

#### 3B — Distribution & Composition Charts

**D1 — Primary Dimension Donut**
- First DIMENSION col, group + count (or sum of metric)
- Type: `donut`, max 7 slices, "Other" for remainder
- Show % labels inside slices, legend below

**D2 — Stacked Bar by Two Dimensions**
- If 2+ DIMENSION cols: group by dim1, split by dim2
- Type: `bar` stacked 100% (normalized) to show composition
- Shows how the mix of one dimension varies across another

**D3 — Treemap (if 3+ DIMENSION cols or ENTITY + DIMENSION)**
- Area = PRIMARY_METRIC sum, grouped by ENTITY then DIMENSION
- Type: ApexCharts `treemap`
- Instantly reveals where value concentration lies

**D4 — Geographic Distribution (if GEOGRAPHY col exists)**
- Bar chart: top 15 geographies by PRIMARY_METRIC or record count
- Sorted descending, color-graded
- Type: horizontal `bar`
- Label with flag emoji for country-level data if recognizable

---

#### 3C — Ranking & Performance Charts

**P1 — Entity Leaderboard**
- Group by ENTITY, aggregate PRIMARY_METRIC (sum) or count
- Top 10, sorted descending
- Type: horizontal `bar`
- Add rank badge (🥇🥈🥉) for top 3, show metric value as data label
- Show a target line if a target/budget column exists

**P2 — Pareto Chart (if PRIMARY_METRIC + ENTITY)**
- Sort entities by metric descending
- Left Y-axis: metric bar, Right Y-axis: cumulative % line
- Annotate the 80% threshold line
- Type: `bar` + `line` mixed chart
- Reveals the vital few vs trivial many

**P3 — Box Plot / Distribution (if enough variance in PRIMARY_METRIC)**
- One box per ENTITY or DIMENSION showing median, Q1/Q3, whiskers
- Type: ApexCharts `boxPlot`
- Shows performance spread, not just averages

---

#### 3D — Funnel & Flow Charts

**F1 — Stage Funnel**
- Requires STATUS_STAGE col
- Derive stages from `[...new Set(DATA.map(r => r[statusCol]))]` — never hardcode
- Sort by count descending to approximate funnel order, OR sort by a logical order heuristic (new→open→in-progress→closed)
- Type: ApexCharts horizontal `bar` styled as funnel (descending size, color gradient from accent-cyan to accent-green)
- Show conversion % between each stage as annotation
- Empty guard: < 2 stages → show message card

**F2 — Waterfall (if meaningful sequential numeric change exists)**
- E.g., Budget → Spend → Variance, or Revenue → Cost → Gross Profit → Net
- Type: ApexCharts `bar` with positive/negative coloring
- Only build if COLUMN_MANIFEST contains 3+ related numeric cols

---

#### 3E — Correlation & Scatter Charts

**C1 — Scatter Plot (if 2+ PRIMARY_METRIC cols)**
- X = metric1, Y = metric2, bubble size = record count (if applicable)
- Color by ENTITY or STATUS_STAGE
- Type: ApexCharts `scatter`
- Add a trend line annotation (linear regression computed from DATA)

**C2 — Correlation Heatmap (if 4+ PRIMARY_METRIC cols)**
- Compute Pearson correlation at runtime between all metric pairs
- Display as a square matrix with color intensity = |correlation|
- Type: ApexCharts `heatmap` with custom color scale
- ```js
  function pearson(arr, colA, colB) {
    const n = arr.length;
    const xa = arr.map(r => parseFloat(r[colA])||0);
    const ya = arr.map(r => parseFloat(r[colB])||0);
    const mx = xa.reduce((s,v)=>s+v,0)/n, my = ya.reduce((s,v)=>s+v,0)/n;
    const num = xa.reduce((s,v,i)=>s+(v-mx)*(ya[i]-my),0);
    const den = Math.sqrt(xa.reduce((s,v)=>s+(v-mx)**2,0)*ya.reduce((s,v)=>s+(v-my)**2,0));
    return den ? num/den : 0;
  }
  ```

---

#### 3F — Boolean & Flag Charts

**B1 — Boolean Breakdown by Dimension**
- For each boolean col: grouped bar showing true/false % split across DIMENSION or ENTITY
- Type: `bar` grouped, two series (True/False)

**B2 — Flag Rate Trend (if BOOLEAN + DATETIME)**
- Line chart: % true over time
- Type: `line` with area fill below threshold line

---

#### CHART FALLBACK RULES

If a chart's required columns are absent:

| Missing Column | Fallback Chart |
|---|---|
| No ENTITY | Replace P1 with top-N values of highest-cardinality DIMENSION |
| No STATUS_STAGE | Replace F1 with a radial gauge of primary metric vs estimated max |
| No DATETIME | Replace T1 with a ranked bar of PRIMARY_METRIC across top DIMENSION |
| No 2nd DIMENSION | Replace D2 with a bullet chart (actual vs target if available) |
| No GEOGRAPHY | Skip D4, add an extra DIMENSION donut |
| No BOOLEAN | Skip B1/B2, add another metric distribution bar |

Never leave a chart slot empty. Always substitute.

---

#### EMPTY GUARD (universal — applies to ALL charts)

```html
<div class="empty-chart-state" style="display:flex;flex-direction:column;align-items:center;justify-content:center;height:280px;gap:12px;color:var(--text-muted)">
  <div style="font-size:2.5rem;opacity:0.4">📊</div>
  <div style="font-weight:600;color:var(--text-secondary)">{Chart Title}</div>
  <div style="font-size:0.8rem">Insufficient data for this visualization</div>
  <div style="font-size:0.75rem;opacity:0.7">Try adjusting filters or loading a different dataset</div>
</div>
```

---

### PHASE 4 — FILTERS (always visible, always reactive)

Build a collapsible left sidebar or top filter bar containing:

1. **Date Range Picker** (if DATETIME_AXIS): `<input type="date">` pair — from / to
2. **Dropdowns** (max 6): one per DIMENSION + ENTITY col with ≤ 25 unique values and null_pct < 60%
3. **Search Box**: free-text filter on IDENTIFIER or highest-cardinality text col
4. **Active Filter Pills**: show each active filter as a removable `<span>` pill below the filter controls
5. **Reset All Filters** button — always visible

```js
function applyFilters() {
  let filtered = [...DATA];
  // Date range
  if (activeFilters.dateFrom) filtered = filtered.filter(r => new Date(r[COLS.datetime]) >= new Date(activeFilters.dateFrom));
  if (activeFilters.dateTo)   filtered = filtered.filter(r => new Date(r[COLS.datetime]) <= new Date(activeFilters.dateTo));
  // Dimension dropdowns (AND logic)
  for (const [col, val] of Object.entries(activeFilters.dims)) {
    if (val && val !== '__all__') filtered = filtered.filter(r => String(r[col]) === val);
  }
  // Text search
  if (activeFilters.search) {
    const q = activeFilters.search.toLowerCase();
    filtered = filtered.filter(r => Object.values(r).some(v => String(v).toLowerCase().includes(q)));
  }
  FILTERED_DATA = filtered;
  updateAllKPIs(filtered);
  updateAllCharts(filtered);
  updateRecordCounter(filtered.length);
  renderFilterPills();
}
```

Populate all dropdown options from `[...new Set(DATA.map(r => r[col]))]` — never hardcode. Sort alphabetically. Default to `"All {Label}s"`.

---

### PHASE 5 — TAB ARCHITECTURE (Story-Driven)

Each tab is a **chapter of the business story**. Name tabs for their narrative role, not generic labels.

#### TAB NAMING LOGIC
Derive tab names from the domain_mapping vertical:
- `sales / crm` → Executive Summary | Pipeline Health | Rep Performance | Revenue Deep Dive | Risk & Alerts | Raw Data
- `ecommerce` → Executive Summary | Order Flow | Product Performance | Customer Segments | Anomalies | Raw Data
- `hr / people` → Executive Summary | Headcount & Attrition | Performance | Diversity & Comp | Alerts | Raw Data
- `finance` → Executive Summary | P&L Overview | Budget vs Actual | Trend Analysis | Exceptions | Raw Data
- `operations` → Executive Summary | Throughput | Efficiency | Resource Utilization | Exceptions | Raw Data
- Default (unknown vertical): Executive Summary | Performance | Breakdown | Trends | Alerts | Raw Data

Always 6 tabs. Always ends with Raw Data. Always starts with Executive Summary.

---

#### TAB 1 — EXECUTIVE SUMMARY

**Purpose**: Answer "What is the state of this business in 90 seconds?"

- Full-width alert banner (critical items from audit_alerts + any runtime data quality flags)
- KPI Hero Row (all 8–12 cards)
- **Narrative insight block**: 3 auto-generated bullet points computed from DATA:
  - Top performer: `"${topEntity} leads with ${formatNum(topMetric)}, accounting for ${pct}% of total."`
  - Trend: `"${metricName} is ${delta > 0 ? 'up' : 'down'} ${Math.abs(delta).toFixed(1)}% vs prior period."`
  - Risk flag: `"${pct}% of records are in '${worstStage}' — review recommended."`
- T1 Trend chart (full width)
- D1 Donut + D4 Geography bar (side by side, or D1 + another dimension chart if no geography)

---

#### TAB 2 — PERFORMANCE ANALYSIS

**Purpose**: Answer "Who is performing and who isn't?"

- P1 Entity Leaderboard (full width or 2/3)
- P2 Pareto Chart (1/3 or full width)
- T2 Period-over-Period grouped bar (full width)
- P3 Box Plot (if enough data) or D3 Treemap

---

#### TAB 3 — BREAKDOWN & COMPOSITION

**Purpose**: Answer "What is this business made of?"

- D2 Stacked 100% bar (full width)
- F1 Funnel + D3 Treemap side by side
- D1 secondary donut (second DIMENSION) or D4 geography
- B1 Boolean breakdown (if applicable)

---

#### TAB 4 — TREND & CORRELATION DEEP DIVE

**Purpose**: Answer "Where is this heading and what drives it?"

- T3 Heatmap (full width if available, else T1 at greater granularity)
- C1 Scatter / correlation plot
- C2 Correlation heatmap (if 4+ metrics)
- F2 Boolean rate trend (if available)
- Any remaining T charts

---

#### TAB 5 — ALERTS & EXCEPTIONS

**Purpose**: Answer "What needs my attention right now?"

- Severity-coded alert cards from domain_mapping → audit_alerts:
  - 🔴 **Critical**: text contains "missing", "critical", "corrupted", "0%", "deactivated", "breach" → red border
  - 🟡 **Warning**: text contains "high", "gap", "stagnant", "low", "below target" → amber border
  - 🟢 **Info**: all others → cyan/green border
- **Runtime data quality panel**: computed from DATA after load:
  - Null rate per column: flag any col with null_pct > 15% in loaded data
  - Outlier flag: for each PRIMARY_METRIC, flag records beyond 3 standard deviations (show count)
  - Duplicate detection: `DATA.length - new Set(DATA.map(r => JSON.stringify(r))).size` → "X potential duplicate rows"
  - Zero-value records: for PRIMARY_METRIC cols, count of rows where value = 0
- **Exception table**: filterable list of records that match any alert condition — sortable, 20 rows/page

---

#### TAB 6 — DATA EXPLORER

**Purpose**: "Let me find a specific record."

- Search bar (live filter as user types, debounced 300ms)
- Paginated table: 25 rows/page, Prev/Next with page indicator
- Column rendering rules:
  - **IDENTIFIER cols**: show, but muted color
  - **PRIMARY_METRIC cols**: right-aligned, monospace font, formatted (K/M/B or 2 decimals)
  - **DATETIME cols**: formatted `DD MMM YYYY`
  - **STATUS_STAGE cols**: colored badge — color derived from frequency rank (1st = neutral, last = red)
  - **Long text cols**: truncate at 60 chars with `title` tooltip for full value
  - **BOOLEAN cols**: ✅ / ❌ icons
  - **IDENTIFIER cols**: gray, no sort
- Column headers: click to sort asc/desc (toggle), active sort shown with ▲/▼
- Hide IDENTIFIER columns by default; "Show All Columns" toggle reveals them
- **Export button**: "Export Filtered CSV" → `Papa.unparse(FILTERED_DATA)` → Blob download
  - Filename: `{dashboardName}_filtered_{YYYY-MM-DD}.csv`

---

### PHASE 6 — DATA LOADING ARCHITECTURE

Required CDN libraries in `<head>`:
```html
<script src="https://cdnjs.cloudflare.com/ajax/libs/PapaParse/5.4.1/papaparse.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
<link href="https://fonts.googleapis.com/css2?family=Sora:wght@300;400;600;700&family=JetBrains+Mono:wght@400;600&family=Inter:wght@400;500;600&display=swap" rel="stylesheet">
<script src="https://cdn.tailwindcss.com"></script>
```

**Upload Screen requirements:**
- Full-screen centered zone, drag-and-drop + "Browse Files" button
- Accept `.csv`, `.xlsx`, `.xls` — multiple files simultaneously
- Label: `"Drop your data files here"` — Sub-label: `"CSV or Excel · Multiple files merge automatically"`
- Animated border on dragover (dashed → solid, accent color pulse)
- File type icons shown when files are dragged over

**Parse Pipeline:**
```js
async function parseFiles(files) {
  showParseProgress(true);
  const allRows = [];
  for (const file of files) {
    const ext = file.name.split('.').pop().toLowerCase();
    if (ext === 'csv') {
      const result = await new Promise(res => Papa.parse(file, {
        header: true, dynamicTyping: true, skipEmptyLines: true,
        complete: res
      }));
      allRows.push(...result.data);
    } else {
      const buf = await file.arrayBuffer();
      const wb  = XLSX.read(buf);
      const ws  = wb.Sheets[wb.SheetNames[0]];
      allRows.push(...XLSX.utils.sheet_to_json(ws, { defval: null }));
    }
    updateProgress(`Parsed ${file.name} — ${allRows.length} rows so far…`);
  }
  DATA = allRows;
  FILTERED_DATA = [...DATA];
  DASHBOARD_TITLE = deriveDashboardName(Array.from(files).map(f => f.name), DOMAIN_MAPPING);
  showParseProgress(false);
  hideUploadScreen();
  renderDashboard(DATA);
}
```

**Progress bar**: animated width bar + text status line — shown during parse, hidden after.

**Re-upload flow**: "⟳ New Dataset" button in header → confirm modal ("This will clear all current data. Continue?") → destroy all chart instances → reset DATA/FILTERED_DATA → reset all filters → show upload screen.

---

### PHASE 7 — TECHNICAL ARCHITECTURE

**State variables (top-level `let`):**
```js
let DATA            = [];    // raw parsed data
let FILTERED_DATA   = [];    // current filtered slice
let ACTIVE_TAB      = 0;     // index of visible tab
let DARK_MODE       = true;  // theme state
let DASHBOARD_TITLE = '';    // derived from filename + domain
let CHARTS          = {};    // { chartId: apexChartsInstance }
let ACTIVE_FILTERS  = { dateFrom: null, dateTo: null, dims: {}, search: '' };
let COLS            = { metrics:[], datetime:null, entities:[], status:null, dimensions:[], geography:null, booleans:[], identifiers:[] };
```

**`renderDashboard(data)` function structure:**
```js
function renderDashboard(data) {
  classifyColumns(data);          // populate COLS from actual data keys
  setDashboardTitle();            // set <h1> content
  buildFilterControls();          // build dropdowns from actual data values
  renderKPIs(data);               // build KPI hero row
  initAllCharts(data);            // initialize all chart instances
  renderNarrativeInsights(data);  // compute + render the 3 bullet insights
  renderAlerts(data);             // Tab 5 alerts + quality flags
  renderDataTable(data);          // Tab 6 table
  activateTab(0);                 // show Tab 1
}
```

**Chart instance management:**
```js
// Track which charts have been initialized (for lazy tab rendering)
const CHART_INIT_STATE = {};

function activateTab(index) {
  ACTIVE_TAB = index;
  // Show/hide tab panels
  document.querySelectorAll('.tab-panel').forEach((p,i) => p.style.display = i===index ? 'block' : 'none');
  // Lazy-render charts in newly visible tab
  getChartsForTab(index).forEach(chartId => {
    if (!CHART_INIT_STATE[chartId]) {
      initChart(chartId, FILTERED_DATA);
      CHART_INIT_STATE[chartId] = true;
    } else {
      CHARTS[chartId]?.render();
    }
  });
}
```

**`updateAllCharts(filtered)` — called by applyFilters:**
```js
function updateAllCharts(filtered) {
  for (const [id, chart] of Object.entries(CHARTS)) {
    if (!chart) continue;
    const series = computeSeriesFor(id, filtered);
    if (!series || series.length === 0) {
      showEmptyState(id);
    } else {
      hideEmptyState(id);
      chart.updateSeries(series, true);
    }
  }
}
```

**Theme toggle:**
```js
function toggleTheme() {
  DARK_MODE = !DARK_MODE;
  document.documentElement.classList.toggle('dark', DARK_MODE);
  const palette = DARK_MODE ? CHART_PALETTE_DARK : CHART_PALETTE_LIGHT;
  for (const chart of Object.values(CHARTS)) {
    chart?.updateOptions({
      colors: palette,
      theme: { mode: DARK_MODE ? 'dark' : 'light' },
      chart: { background: 'transparent' },
      grid: { borderColor: DARK_MODE ? '#1e3448' : '#dde4ee' },
      xaxis: { labels: { style: { colors: DARK_MODE ? '#7a9abf' : '#4a6880' } } },
      yaxis: { labels: { style: { colors: DARK_MODE ? '#7a9abf' : '#4a6880' } } },
    });
  }
}
```

---

### PHASE 8 — NARRATIVE INSIGHTS ENGINE

This is what separates a CXO dashboard from a report. After data loads, auto-compute and display a **"Story so far" insight panel** on Tab 1.

```js
function computeNarrativeInsights(data) {
  const insights = [];

  // 1. Top performer insight
  if (COLS.entities.length && COLS.metrics.length) {
    const groups = groupBy(data, COLS.entities[0]);
    const top = Object.entries(groups).sort((a,b) => sumCol(b[1],COLS.metrics[0]) - sumCol(a[1],COLS.metrics[0]))[0];
    const total = sumCol(data, COLS.metrics[0]);
    const pct = (sumCol(top[1], COLS.metrics[0]) / total * 100).toFixed(1);
    insights.push({ icon: '🏆', text: `${top[0]} leads ${COLS.metrics[0]} with ${pct}% of total output.` });
  }

  // 2. Trend insight
  if (COLS.datetime && COLS.metrics.length) {
    const delta = computeDelta(data, COLS.metrics[0], COLS.datetime);
    const dir = delta > 0 ? '▲ up' : '▼ down';
    const color = delta > 0 ? 'var(--accent-green)' : 'var(--accent-red)';
    insights.push({ icon: '📈', text: `${COLS.metrics[0]} is <span style="color:${color};font-weight:700">${dir} ${Math.abs(delta).toFixed(1)}%</span> vs prior period.`, html: true });
  }

  // 3. Risk insight
  if (COLS.status) {
    const groups = groupBy(data, COLS.status);
    const sorted = Object.entries(groups).sort((a,b) => b[1].length - a[1].length);
    const worst = sorted[sorted.length - 1]; // least frequent = potential risk
    const pct = (worst[1].length / data.length * 100).toFixed(1);
    insights.push({ icon: '⚠️', text: `${pct}% of records are in '${worst[0]}' status — monitor closely.` });
  }

  // 4. Concentration risk
  if (COLS.entities.length && COLS.metrics.length) {
    const groups = groupBy(data, COLS.entities[0]);
    const total = sumCol(data, COLS.metrics[0]);
    const top3sum = Object.entries(groups).sort((a,b)=>sumCol(b[1],COLS.metrics[0])-sumCol(a[1],COLS.metrics[0])).slice(0,3).reduce((s,[,v])=>s+sumCol(v,COLS.metrics[0]),0);
    const pct = (top3sum/total*100).toFixed(0);
    if (pct > 60) insights.push({ icon: '🎯', text: `Top 3 ${COLS.entities[0]}s represent ${pct}% of ${COLS.metrics[0]} — high concentration risk.` });
  }

  return insights.slice(0, 4);
}
```

Render these as a styled `<ul>` with left accent border, icon, and text. Place below the KPI row on Tab 1.

---

### PHASE 9 — HEADER LAYOUT

```
[ 🏢 {Dashboard Title}        ] [ ⊙ {N} rows · {date range}  ]  [ Filters: active count ]  [ 🌙/☀️ ]  [ ↓ Export ]  [ ⟳ New Data ]
```

- Title left-anchored, large, `font-family: Sora`
- Subtitle: record count + date range computed at load time
- All buttons right-aligned
- Header has `border-bottom: 1px solid var(--border)` and subtle backdrop blur on scroll

---

### PHASE 10 — DELIVER SPEC

- Single `index.html` file — no external files, no build step
- Vanilla JS only — no React, no Vue, no build pipeline
- All CDN libraries loaded from `<head>`
- Minify nothing — keep code readable with section comments
- Test empty state: ensure every chart has an empty guard
- Test filter state: ensure Reset Filters restores all charts to full DATA
- Test theme: ensure dark ↔ light leaves no unstyled elements
- Ensure dashboard title is never "Nova", "Dashboard", "BI Tool", or any placeholder

---

## ANTI-PATTERNS TO NEVER DO

1. ❌ Never hardcode chart series data from the COLUMN_MANIFEST
2. ❌ Never name the dashboard "Nova", "Dashboard", or leave a placeholder
3. ❌ Never use fewer than 8 charts across all tabs
4. ❌ Never leave a tab with only one chart
5. ❌ Never show `NaN`, `undefined`, `null`, or `0.0%` in KPI cards
6. ❌ Never apply the same color to two different series in the same chart
7. ❌ Never use Inter/Roboto/Arial as the primary display font
8. ❌ Never build a chart without an empty guard
9. ❌ Never forget the narrative insight panel on Tab 1
10. ❌ Never let filters silently break — always show "0 results" state with a "Reset" prompt

--- FILE: data-analysis/SKILL.md ---

---
name: data-analysis
description: Data profiling, analysis, cleaning, and visualisation using pipeline.py for automated dataset profiling followed by LLM-generated, NOVA-executed Python code.
origin: NOVA
---

# Data Analysis Skill

End-to-end skill for understanding, analysing, and transforming datasets. Automatically profiles the input file, interprets the profile, and generates runnable Python code to answer the user's request.

## When to Activate

- User provides a file and asks to analyse, explore, or summarise it
- User asks what analyses are possible on their data
- User asks to clean, fix, or prepare their data
- User asks to visualise any aspect of their data
- User asks to find patterns, outliers, correlations, or trends
- User asks a specific question about their dataset (e.g. "which column has the most nulls?")
- User asks to filter, group, aggregate, or transform their data

## Core Skill Flow

### Step 1 — Run the profiler

Always run `pipeline.py` first on the provided file before doing anything else. This gives the LLM accurate, data-specific context rather than assumptions.

```bash
python skills/data-analysis/pipeline.py <file_path>
```

The output is a JSON profile covering shape, column types, nulls, distributions, outliers, correlations, and quality flags.

### Step 2 — Build the LLM prompt

Combine three inputs into one prompt:

```
[SKILL.md instructions]
+
[pipeline.py JSON output]
+
[User's original query]
```

The LLM uses the JSON profile to write code that is accurate for the actual dataset — correct column names, correct dtypes, no hallucinated columns.

### Step 3 — Generate summary + code

The LLM response must always have two parts:

**Part 1 — Data summary** (plain text, always present regardless of query)

**Part 2 — Analysis code** (Python, directly runnable by NOVA)

### Step 4 — NOVA executes the code

NOVA runs the generated code. If it fails, NOVA automatically fixes and reruns until execution succeeds or the retry limit is reached.

---

## Response Format

Every response must follow this exact structure:

```
## Data summary
One paragraph: dataset size, column breakdown by type, notable quality issues from flags[].

## Key observations
- Nulls: list columns with null_pct > 0, sorted by severity
- Distributions: skew, outliers, ranges worth calling out
- Data quality: flags from pipeline output (duplicates, constants, ID columns)
- Correlations: pairs from high_correlations[] if present

## What I'm doing
One sentence: what the code below does, in plain language.

## Code
\`\`\`python
# clean, commented, runnable Python
\`\`\`

## Output interpretation
Brief explanation of how to read the output once the code runs.
```

**Rules:**
- Never skip the data summary, even for simple queries
- Always surface quality flags before analysis — bad data should be acknowledged first
- Code must use only column names that exist in `columns[].name` from the profile
- Code must respect dtypes from the profile (don't treat a string column as numeric)

---

## Code Generation Rules

### Imports

Always include all required imports inside the generated code block. NOVA runs the code in isolation.

```python
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from pathlib import Path
```

### File loading

Always use the same file path the user provided. Use the extension from `file.extension` in the profile to load correctly.

```python
# CSV
df = pd.read_csv("path/to/file.csv")

# Excel
df = pd.read_excel("path/to/file.xlsx", sheet_name=0)

# JSON
df = pd.read_json("path/to/file.json")

# Parquet
df = pd.read_parquet("path/to/file.parquet")
```

### Column name safety

Always reference column names using bracket notation, not dot notation, to handle spaces and special characters.

```python
# Correct
df["column name with spaces"]

# Incorrect — will fail
df.column name with spaces
```

### Dtype handling

Check the `col_type` field from the profile before operating on a column.

```python
# Numeric operations only on col_type: numeric
df["sales"].mean()

# String operations only on col_type: categorical or text
df["category"].value_counts()

# Date operations only on col_type: datetime
df["date"].dt.year
```

### Visualisations

Save plots to file, never use `plt.show()` — NOVA runs headlessly.

```python
plt.figure(figsize=(10, 6))
sns.histplot(df["column"], kde=True)
plt.title("Distribution of column")
plt.tight_layout()
plt.savefig("output_plot.png", dpi=150)
plt.close()
```

### Cleaning operations

When cleaning, always create a copy and report what was changed.

```python
df_clean = df.copy()

# Drop high-null columns (> 50%)
high_null_cols = ["col_a", "col_b"]
df_clean = df_clean.drop(columns=high_null_cols)

# Fill numeric nulls with median
df_clean["revenue"] = df_clean["revenue"].fillna(df_clean["revenue"].median())

# Drop duplicates
before = len(df_clean)
df_clean = df_clean.drop_duplicates()
print(f"Removed {before - len(df_clean)} duplicate rows")

# Save cleaned file
df_clean.to_csv("cleaned_output.csv", index=False)
print(f"Cleaned dataset: {df_clean.shape[0]} rows x {df_clean.shape[1]} cols")
```

---

## Common Patterns

### Exploratory analysis

```python
import pandas as pd

df = pd.read_csv("data.csv")

# Overview
print(f"Shape: {df.shape}")
print(f"\nDtypes:\n{df.dtypes}")
print(f"\nNull counts:\n{df.isnull().sum()}")
print(f"\nDescriptive stats:\n{df.describe()}")
```

### Correlation matrix

```python
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

df = pd.read_csv("data.csv")
numeric_df = df.select_dtypes(include="number")

plt.figure(figsize=(12, 8))
sns.heatmap(numeric_df.corr(), annot=True, fmt=".2f", cmap="coolwarm", center=0)
plt.title("Correlation matrix")
plt.tight_layout()
plt.savefig("correlation_matrix.png", dpi=150)
plt.close()
```

### Outlier detection and removal

```python
import pandas as pd
import numpy as np

df = pd.read_csv("data.csv")

def remove_outliers_iqr(df, col):
    q1 = df[col].quantile(0.25)
    q3 = df[col].quantile(0.75)
    iqr = q3 - q1
    mask = (df[col] >= q1 - 1.5 * iqr) & (df[col] <= q3 + 1.5 * iqr)
    removed = (~mask).sum()
    print(f"'{col}': removed {removed} outliers")
    return df[mask]

for col in df.select_dtypes(include="number").columns:
    df = remove_outliers_iqr(df, col)
```

### Group-by aggregation

```python
import pandas as pd

df = pd.read_csv("data.csv")

result = (
    df.groupby("category_col")
    .agg(
        count=("value_col", "count"),
        mean=("value_col", "mean"),
        total=("value_col", "sum"),
    )
    .sort_values("total", ascending=False)
    .reset_index()
)

print(result.to_string(index=False))
```

### Missing value summary

```python
import pandas as pd

df = pd.read_csv("data.csv")

null_summary = (
    pd.DataFrame({
        "null_count": df.isnull().sum(),
        "null_pct": (df.isnull().mean() * 100).round(2),
        "dtype": df.dtypes,
    })
    .query("null_count > 0")
    .sort_values("null_pct", ascending=False)
)

print(null_summary.to_string())
```

---

## Reading the Pipeline JSON

Key fields to use when writing code:

| Field | How to use |
|---|---|
| `shape.rows` / `shape.cols` | Report dataset size in summary |
| `columns[].name` | Use exact names in code — never guess |
| `columns[].col_type` | Determines valid operations on that column |
| `columns[].null_pct` | Prioritise in cleaning; mention if > 10% |
| `columns[].skewness` | Flag if abs > 2; suggest log transform |
| `columns[].outlier_pct` | Mention if > 5%; suggest IQR removal |
| `columns[].top_values` | Use for categorical grouping or filtering |
| `columns[].min_date` / `max_date` | Set date range context in summary |
| `high_correlations[]` | Flag multicollinearity; mention in summary |
| `flags[]` | Always surface all flags in key observations |
| `duplicate_pct` | Mention if > 0; recommend drop_duplicates |

---

## Best Practices

### DO

- **Always profile first** — never generate code without running pipeline.py
- **Surface flags first** — quality issues come before any analysis
- **Use exact column names** — copy from `columns[].name` in the profile
- **Save all outputs** — CSVs to file, plots to PNG; NOVA runs headlessly
- **Comment the code** — explain what each block does in one line
- **Handle nulls explicitly** — never assume a column is clean
- **Report changes** — print row counts before and after any filtering or cleaning
- **Respect dtypes** — check col_type before applying numeric or string operations

### DON'T

- **Don't assume column names** — always read them from the profile
- **Don't use plt.show()** — will hang in headless execution
- **Don't skip the summary** — even if the user only asked for code
- **Don't operate on all columns blindly** — filter by col_type first
- **Don't hardcode file paths** — use the path from the user's input
- **Don't generate analysis without data context** — if pipeline fails, ask the user to re-provide the file

---

## Quick Reference

| User asks | What to generate |
|---|---|
| "Analyse this data" | Full summary + descriptive stats code |
| "What can I do with this?" | Summary + list of 5 suggested analyses with code stubs |
| "Clean the data" | Flag-based cleaning code + save to new file |
| "Show me the distribution of X" | Histogram + KDE plot saved to PNG |
| "Find correlations" | Heatmap + high-correlation pairs printed |
| "Find outliers in X" | IQR-based detection + count report |
| "Group by X and sum Y" | groupby aggregation + printed table |
| "How many nulls?" | Null summary table sorted by severity |
| "Remove duplicates" | drop_duplicates + before/after count |
| "What's the date range?" | Min/max from datetime columns in profile |


--- FILE: data-analysis/dashboard.md ---

# HTML/JS Executive Dashboard Builder Skill

You are a Principal Web Architect and Data Visualization Expert. Your task is to build a world-class, **C-level executive dashboard** using a single-file HTML approach (HTML/CSS/JS).

## The Mandate
1. **Intelligent Data Loading (Critical):** You will be provided the file path(s) in the prompt. 
    - **Step A:** Try to load the file(s) automatically using JavaScript `fetch()`. If multiple files are provided, fetch them all and combine the arrays.
    - **Step B (Fallback):** Because local file protocols (`file://`) often block `fetch()` due to CORS, you MUST wrap the fetch in a `try/catch`. 
    - If the fetch fails, automatically reveal a beautifully styled Drag-and-Drop / `<input type="file" multiple>` overlay so the user can manually upload the files to view the dashboard. Use a CDN for `PapaParse` or `SheetJS` to parse files.
2. **C-Suite Multi-Section UI:** Do not write basic HTML. 
    - Import **Tailwind CSS** via CDN for a modern, sleek layout.
    - MUST include navigation tabs or a sidebar to switch between different "Views" (e.g., "Overview", "Granular Analysis", "Distributions"). Use JS to toggle visibility of these sections.
    - Include a top row of dynamically updating KPI Metric Cards.
3. **Comprehensive Visuals & Interactivity:** 
    - Import **Chart.js** or **ApexCharts** via CDN. Generate a highly detailed suite of charts (Lines for trends, Doughnuts for shares, Bars for comparisons).
    - Build JS logic to extract unique values from the dataset and populate `<select>` dropdowns to filter the entire dashboard.

## Code Requirements
- Single file only. All CSS inside `<style>`, all JS inside `<script>`.
- Format the output EXACTLY in a single `[CREATE: index.html]` tag followed by a markdown HTML code block. No conversational text outside the block.

--- FILE: data-analysis/pipeline.py ---

import sys
import json
import os
import warnings
warnings.filterwarnings('ignore')

import pandas as pd
import numpy as np


# ─── File loading ────────────────────────────────────────────────────────────

def detect_ext(path):
    return os.path.splitext(path)[1].lower()


def load_file(path):
    ext = detect_ext(path)
    meta = {}

    if ext == '.csv':
        try:
            df = pd.read_csv(path, encoding='utf-8')
        except UnicodeDecodeError:
            df = pd.read_csv(path, encoding='latin-1')
            meta['encoding'] = 'latin-1'

    elif ext in ['.xlsx', '.xls']:
        xl = pd.ExcelFile(path)
        sheets = xl.sheet_names
        meta['sheets'] = sheets
        meta['active_sheet'] = sheets[0]
        if len(sheets) > 1:
            meta['note'] = f'{len(sheets)} sheets detected — profiling first sheet only'
        df = pd.read_excel(path, sheet_name=sheets[0])

    elif ext == '.json':
        df = pd.read_json(path)

    elif ext == '.parquet':
        df = pd.read_parquet(path)

    else:
        raise ValueError(f"Unsupported file type: {ext}")

    return df, meta


# ─── Column classification ────────────────────────────────────────────────────

def categorical_threshold(n_rows):
    """
    Returns (ratio_threshold, abs_threshold).
    A column is categorical if unique/total < ratio AND unique count < abs.
    Scales with dataset size so large datasets aren't over-flagged.
    """
    if n_rows < 1_000:
        return 0.05, 20
    elif n_rows < 10_000:
        return 0.05, 50
    elif n_rows < 100_000:
        return 0.03, 100
    else:
        return 0.01, 200


def classify_column(series, n_rows):
    ratio_thresh, abs_thresh = categorical_threshold(n_rows)
    n_unique = series.nunique()
    ratio = n_unique / n_rows if n_rows > 0 else 0

    if pd.api.types.is_bool_dtype(series):
        return 'boolean'

    if pd.api.types.is_datetime64_any_dtype(series):
        return 'datetime'

    if pd.api.types.is_numeric_dtype(series):
        if ratio > 0.9:
            return 'id_numeric'
        return 'numeric'

    if series.dtype == 'object':
        if ratio > 0.9:
            return 'high_cardinality'
        if n_unique <= abs_thresh or ratio <= ratio_thresh:
            return 'categorical'
        return 'text'

    return 'other'


# ─── Column profiling ─────────────────────────────────────────────────────────

def profile_column(name, series, col_type, n_rows):
    p = {
        'name': name,
        'dtype': str(series.dtype),
        'col_type': col_type,
        'null_count': int(series.isnull().sum()),
        'null_pct': round(series.isnull().mean() * 100, 2),
        'unique_count': int(series.nunique()),
        'unique_pct': round(series.nunique() / n_rows * 100, 2) if n_rows > 0 else 0,
    }

    if col_type == 'numeric':
        clean = series.dropna()
        q1, q3 = clean.quantile(0.25), clean.quantile(0.75)
        iqr = q3 - q1
        outliers = int(((clean < q1 - 1.5 * iqr) | (clean > q3 + 1.5 * iqr)).sum())
        p.update({
            'min':           _safe_round(clean.min()),
            'max':           _safe_round(clean.max()),
            'mean':          _safe_round(clean.mean()),
            'median':        _safe_round(clean.median()),
            'std':           _safe_round(clean.std()),
            'q25':           _safe_round(q1),
            'q75':           _safe_round(q3),
            'skewness':      _safe_round(clean.skew()),
            'outlier_count': outliers,
            'outlier_pct':   round(outliers / n_rows * 100, 2) if n_rows > 0 else 0,
        })

    elif col_type == 'categorical':
        top = series.value_counts().head(5)
        p['top_values'] = {str(k): int(v) for k, v in top.items()}

    elif col_type == 'datetime':
        p['min_date'] = str(series.min())
        p['max_date'] = str(series.max())
        p['range_days'] = int((series.max() - series.min()).days) if not series.isnull().all() else None

    elif col_type == 'boolean':
        vc = series.value_counts()
        p['value_counts'] = {str(k): int(v) for k, v in vc.items()}

    elif col_type in ['high_cardinality', 'text']:
        p['sample_values'] = [str(v) for v in series.dropna().head(3).tolist()]

    return p


def _safe_round(val, digits=4):
    try:
        return round(float(val), digits) if not pd.isna(val) else None
    except Exception:
        return None


# ─── Correlation ──────────────────────────────────────────────────────────────

def high_correlations(df, threshold=0.8):
    num_cols = df.select_dtypes(include=[np.number]).columns.tolist()
    if len(num_cols) < 2:
        return []

    corr = df[num_cols].corr()
    pairs = []
    for i in range(len(corr.columns)):
        for j in range(i + 1, len(corr.columns)):
            val = corr.iloc[i, j]
            if abs(val) >= threshold:
                pairs.append({
                    'col_a': corr.columns[i],
                    'col_b': corr.columns[j],
                    'correlation': round(float(val), 4),
                })
    return pairs


# ─── Quality flags ────────────────────────────────────────────────────────────

def build_flags(columns, duplicate_pct):
    flags = []

    for col in columns:
        name = col['name']

        if col['null_pct'] > 80:
            flags.append(f"Critical nulls in '{name}': {col['null_pct']}% — column likely unusable")

        if col['col_type'] == 'id_numeric':
            flags.append(f"Possible ID column (numeric): '{name}' — {col['unique_pct']}% unique values")

        if col['col_type'] == 'high_cardinality':
            flags.append(f"High cardinality column: '{name}' — {col['unique_pct']}% unique values")

        if col['col_type'] == 'numeric':
            skew = col.get('skewness') or 0
            if abs(skew) > 2:
                flags.append(f"High skewness in '{name}': {skew}")
            if col.get('outlier_pct', 0) > 5:
                flags.append(f"Significant outliers in '{name}': {col['outlier_pct']}% of rows")

        if col['unique_count'] == 1:
            flags.append(f"Constant column '{name}': only one unique value")

    if duplicate_pct > 1:
        flags.append(f"Duplicate rows detected: {duplicate_pct}% of dataset")

    return flags


# ─── Main pipeline ────────────────────────────────────────────────────────────

def run(paths):
    output = {}

    # File metadata and Load
    dfs = []
    files_info = []
    for path in paths:
        size = os.path.getsize(path)
        df, file_meta = load_file(path)
        f_info = {
            'name':       os.path.basename(path),
            'extension':  detect_ext(path),
            'size_kb':    round(size / 1024, 2),
        }
        f_info.update(file_meta)
        files_info.append(f_info)
        dfs.append(df)

    output['files'] = files_info
    
    # Combine all dataframes
    df = pd.concat(dfs, ignore_index=True)

    # Try to parse object columns as datetime
    for col in df.select_dtypes(include='object').columns:
        try:
            df[col] = pd.to_datetime(df[col], infer_datetime_format=True)
        except Exception:
            pass

    n_rows, n_cols = df.shape
    dup_count = int(df.duplicated().sum())
    dup_pct = round(dup_count / n_rows * 100, 2) if n_rows > 0 else 0

    output['shape'] = {'rows': n_rows, 'cols': n_cols}
    output['duplicate_rows'] = dup_count
    output['duplicate_pct'] = dup_pct

    # Column profiles
    columns = []
    for col in df.columns:
        col_type = classify_column(df[col], n_rows)
        columns.append(profile_column(col, df[col], col_type, n_rows))

    output['columns'] = columns

    # Column type breakdown
    type_summary = {}
    for col in columns:
        ct = col['col_type']
        type_summary[ct] = type_summary.get(ct, 0) + 1
    output['column_type_summary'] = type_summary

    # Correlations
    output['high_correlations'] = high_correlations(df)

    # Quality flags
    output['flags'] = build_flags(columns, dup_pct)

    # RAW DATA HEAD: Provides Kimi with actual data samples for domain intuition
    output['data_head'] = df.head(10).to_dict(orient='records')

    return output


# ─── Entry point ──────────────────────────────────────────────────────────────

if __name__ == '__main__':
    if len(sys.argv) < 2:
        print(json.dumps({'error': 'Usage: python pipeline.py <file_path> [file_path_2 ... ]'}))
        sys.exit(1)

    file_paths = sys.argv[1:]
    valid_paths = []

    for fp in file_paths:
        if not os.path.exists(fp):
            print(json.dumps({'error': f'File not found: {fp}'}))
            sys.exit(1)
        valid_paths.append(fp)

    result = run(valid_paths)
    print(json.dumps(result, indent=2, default=str))


--- FILE: data-analysis/streamlit_da_dashaboard.md ---

# Streamlit Executive Dashboard Builder Skill

You are a Principal Data Scientist and Lead UI Engineer. Your task is to build a world-class, **C-level executive dashboard** using Streamlit. 

## The Mandate
1. **Dynamic Multi-File Loading:** You will be provided the exact file path(s) in the prompt. 
    - You MUST use `pd.read_csv()`, `pd.read_excel()`, etc. to load them.
    - If multiple files are provided, load all of them and use `pd.concat(ignore_index=True)` to merge them into a single master DataFrame for analysis.
    - Wrap the loading function in `@st.cache_data` for performance.
2. **C-Suite Standard & Sections:** The UI must be exceptional. 
    - Always include a top row of `st.metric()` KPI cards summarizing the most critical high-level data.
    - MUST USE `st.tabs()` to separate the dashboard into distinct granular sections (e.g., "Executive Summary", "Deep Dive Analytics", "Trend Distributions", "Raw Data Explorer").
3. **Comprehensive Logic:** 
    - Auto-deduce the best metrics based on the `pipeline_output.json` profile. Give the user an incredibly informative, highly granular view of their domain.
4. **Advanced Interactivity:** Always include a sidebar with multiple filters (`st.selectbox`, `st.slider`) that dynamically update the data across ALL tabs.
5. **Visuals:** Rely heavily on `plotly.express` for premium, interactive charts.

## Code Requirements
- Handle missing values (`.fillna()`, `.dropna()`) gracefully.
- Set `st.set_page_config(page_title="Executive Dashboard", layout="wide")`.
- Format the output EXACTLY in a single `[CREATE: dashboard.py]` tag followed by a markdown python code block. No conversational text outside the block.

--- FILE: data-science/SKILL.md ---

---
name: data-science
description: Agentic Data Science Loop with Persistent Research Memory.
version: 1.5.0
---

# The Lead Data Scientist Protocol

You are an Autonomous Lead Data Scientist. You follow the Scientific Method: Hypothesis -> Experiment -> Observation -> Learning.

## THE RESEARCH LOG
You must maintain `experiments/research_log.md`. This is your memory.
- Before every experiment, record your **Hypothesis**.
- After every run, record the **Result** (metrics) and **Learning**.
- Never repeat an experiment that resulted in a lower metric than the baseline.

## OPERATING RULES
1. **WORKSPACE**: All logs and intermediate scripts MUST stay in `experiments/`.
2. **PHASE ENFORCEMENT**: You are an iterative agent. NEVER generate files for future phases. If asked for a discovery script, DO NOT provide a final model.
3. **LANGUAGE ADHERENCE**: You MUST write all code in the `TARGET_LANGUAGE` specified in the prompt. Use the correct file extensions (.py or .R).
4. **Surgical Precision**: Only use columns and transformations that logically suit the domain.
5. **LOGGING**: Always print `METRIC_RESULT: <value> | METRIC_NAME: <name>` to the terminal. In R, use `cat()` or `print()`.

## PHASES
- **PHASE 1: PROBE**: Profile data. Write findings to `research_log.md`.
- **PHASE 2: LOOP**: Test hypotheses. Update the log with metrics after each run.
- **PHASE 3: SHIP**: Consolidate the winner into `final_model.py`.
- **PHASE 4: BRIEF**: Professional text summary of findings.
- **PHASE 5: DOCUMENT**: PDF generation (only if requested).

--- FILE: data-science/scientist.py ---

import os
import json
import re
import sys
import time
import questionary
from rich.panel import Panel
from nova_cli.nova_core.ai.api_client import BridgeyeAPIClient
from nova_cli.local.ui import ui
from nova_cli.local.file_manager.commands import handle_ai_commands
from nova_cli.local.healer.runner import run_with_healing
from nova_cli.local.utils import ensure_dependencies, ensure_system_tool

def display_ds_banner():
    ui.print()
    ui.print(Panel(
        "[bold white]NOVA Data Scientist is now ACTIVE.[/bold white]\n"
        "[dim]Initializing Research Workspace and Lab Notebook...[/dim]",
        title="[bold magenta]AGENTIC LABORATORY[/bold magenta]",
        border_style="magenta",
        expand=False
    ))

def _robust_stream(api, prompt, context, model, provider, check_truncation=True):
    """
    Executes AI generation with two distinct recovery mechanisms:
    1. Network/API Errors (RuntimeError): Restarts the generation from scratch (safest for code structure).
    2. Token Truncation (Missing ```): Stitches the output using a continuation prompt.
    """
    import time
    max_retries = 3
    max_continues = 3
    
    for attempt in range(max_retries):
        try:
            # 1. Start generation from scratch for this attempt
            full_output = ui.stream_rich_response(
                api.chat_stream(prompt, context, model, provider),
                show_reasoning=True
            )
            
            if not full_output:
                return ""
            
            # 2. Check for token truncation (successful API call, but cut off due to length)
            if check_truncation:
                continue_count = 0
                while full_output and not full_output.strip().endswith("```") and continue_count < max_continues:
                    continue_count += 1
                    ui.print(f"[dim]  (Nova is extending the response due to length... Part {continue_count+1})[/dim]")
                    
                    continue_prompt = (
                        "CONTINUE_GENERATION: Your previous response was truncated mid-code. "
                        "CRITICAL: Do NOT switch to [EDIT] tags. Continue the existing [CREATE] block exactly from the next character. "
                        "No preamble. Do not repeat previous code or tags."
                    )
                    
                    continuation = ui.stream_rich_response(
                        api.chat_stream(continue_prompt, {"previous_partial_output": full_output[-2000:]}, model, provider),
                        show_reasoning=False
                    )
                    
                    if continuation:
                        from nova_cli.local.utils import stitch_code_blocks
                        full_output = stitch_code_blocks(full_output, continuation)
                    else:
                        break
                        
            return full_output # Success!
            
        except RuntimeError as e:
            # 3. Handle actual API/Network crashes (e.g. 504, connection dropped)
            if attempt < max_retries - 1:
                wait_time = 3 * (attempt + 1)
                ui.print(f"[yellow]⚠ Connection flickered ({e}). Restarting generation safely in {wait_time}s... (Attempt {attempt+2}/{max_retries})[/yellow]")
                time.sleep(wait_time)
                continue
            else:
                ui.print(f"[bold red]Fatal API Error after {max_retries} attempts: {e}[/bold red]")
                return ""
                
    return ""

def execute_and_verify(api, runner, filepath, target_lang, model, provider, context, research_log_path, rewrite_attempts=1):
    """
    Tries surgical healing first. If it fails 3 times, escalates to Kimi for a full 
    architectural rewrite of the file and retries.
    """
    for attempt in range(rewrite_attempts + 1):
        try:
            # Standard surgical healing (max 3 attempts inside runner.py)
            out = run_with_healing(command_args=[runner, filepath], cwd=os.getcwd(), model=model, provider=provider, context=context)
            return out
        except Exception as e:
            if attempt == rewrite_attempts:
                ui.print(f"[bold red]>> Final Failure: Logic could not be repaired even with architectural rewrites.[/bold red]")
                raise e
            
            ui.print(f"[bold yellow]>> Surgical Healing failed to fix the error. Escalating to Kimi for a full architectural rewrite...[/bold yellow]")
            
            with open(filepath, "r", encoding="utf-8") as f:
                current_code = f.read()
            with open(research_log_path, "r", encoding="utf-8") as f:
                log_content = f.read()
            
            # Request a full rewrite from Kimi (the implementation expert)
            rewrite_prompt = (
            f"SYSTEM_OVERRIDE: The file `{filepath}` is logically broken and surgical patches failed to repair it.\n"
            f"ERROR LOG (CRITICAL - DO NOT REPEAT THIS ERROR):\n{str(e)}\n\n"
            f"CURRENT CODE:\n{current_code}\n\n"
            f"RESEARCH LOG:\n{log_content}\n\n"
            f"TASK: Rewrite the ENTIRE file `{filepath}` from scratch to fix the logic and resolve the error.\n"
            f"CRITICAL FIX REQUIRED: The previous model failed to fix the error above. You must identify why the script crashed and write a fundamentally different implementation that bypasses the issue entirely.\n"
            f"CRITICAL: Output ONLY the [CREATE: {filepath}] tag followed by the full code block. No explanation."
        )
        
            output = _robust_stream(api, rewrite_prompt, context, "moonshotai/kimi-k2.6", "openrouter")
            handle_ai_commands(output)
            ui.print(f"[cyan]>> Architectural rewrite applied. Retrying execution...[/cyan]")
    return ""

def run(user_prompt: str):
    api = BridgeyeAPIClient()
    target_model = "moonshotai/kimi-k2.6"
    architect_model = "openai/gpt-oss-120b"
    
    # --- 0. REACTIVE SIDECAR CHECK (Step 6 of Revamp) ---
    state_path = "experiments/.nova_state.json"
    is_reactive = False
    if os.path.exists(state_path):
        with open(state_path, "r") as f:
            l_state = json.load(f)
            # If prompt is a follow-up (doesn't mention 'new experiment' or 'restart')
            if not any(k in user_prompt.lower() for k in ["new experiment", "restart", "start over"]):
                is_reactive = True

    if is_reactive:
        return run_reactive_sidecar(api, user_prompt, l_state)

    display_ds_banner()

    # --- STATE DETECTION (Session Resumption) ---
    log_path = "experiments/research_log.md"
    is_resume = os.path.exists(log_path) and os.path.exists("experiments")
    
    existing_research = ""
    next_turn = 1
    
    if is_resume:
        ui.print("[bold green]>> Existing research detected. Resuming session...[/bold green]")
        with open(log_path, "r", encoding="utf-8") as f:
            existing_research = f.read()
        
        # Determine the next experiment number
        exp_files = [f for f in os.listdir("experiments") if f.startswith("experiment_")]
        nums = [int(re.search(r"\d+", f).group()) for f in exp_files if re.search(r"\d+", f)]
        next_turn = max(nums) + 1 if nums else 1

    # --- LANGUAGE DETECTION & SELECTION ---
    target_lang = None
    if re.search(r"\bpython\b", user_prompt.lower()):
        target_lang = "Python"
    elif re.search(r"\b[Rr]\b", user_prompt.lower()) or "r-lang" in user_prompt.lower():
        target_lang = "R"
    
    if not target_lang:
        target_lang = questionary.select(
            "Which language should NOVA use for this research?",
            choices=["Python", "R"]
        ).ask()
        
        if not target_lang:
            ui.print("[yellow]>> Cancelled.[/yellow]")
            return
    
    lang_ext = ".py" if target_lang == "Python" else ".R"
    runner = sys.executable if target_lang == "Python" else ensure_system_tool("Rscript")
    
    if not runner:
        ui.print(f"[bold red]Fatal: Cannot proceed without {target_lang} installed on your system.[/bold red]")
        return
        
    ui.print(f"[dim]>> Target Language set to: [bold cyan]{target_lang}[/bold cyan] ({lang_ext})[/dim]")

    os.makedirs("experiments/artifacts", exist_ok=True)
    
    # Initialize Research Log
    log_path = "experiments/research_log.md"
    if not os.path.exists(log_path):
        with open(log_path, "w") as f:
            f.write(f"# Research Log: {user_prompt[:50]}...\n\n")

    from nova_cli.local.contextifier import run_contextify
    
    discovery_output = ""
    from nova_cli.local.contextifier import run_contextify
    context = run_contextify(os.getcwd(), save_to_disk=True)

    if not is_resume:
        # 1. DISCOVERY (Only for new projects)
        ui.print("[bold magenta]• Phase 1: Data Discovery...[/bold magenta]")
        
        data_files = [f for f in os.listdir('.') if f.endswith(('.csv', '.xlsx', '.parquet', '.json'))]
        data_files_str = ", ".join(data_files) if data_files else "None found in root directory"

        discovery_prompt = (
            f"SYSTEM_OVERRIDE: You are strictly in PHASE 1 (DISCOVERY).\n"
            f"TARGET_LANGUAGE: {target_lang}\n"
            f"AVAILABLE DATA FILES IN CURRENT FOLDER: {data_files_str}\n"
            f"TASK 1: Write an exploratory script in `experiments/discovery{lang_ext}` to load and profile these files. ONLY PUT CODE HERE.\n"
            f"TASK 2: Create `experiments/research_log.md`. ONLY PUT TEXT/MARKDOWN HERE (e.g., your initial hypothesis). Do NOT put code in the markdown file.\n"
            f"CRITICAL: You MUST use the [CREATE: <filename>] tag for both files.\n"
            f"CRITICAL: DO NOT assume data is in a 'data/' subdirectory. Use the exact file paths as they appear in the folder.\n"
            f"CRITICAL: DO NOT generate any experiment files yet.\n\n"
            f"USER REQUEST: {user_prompt}"
        )
        
        output = _robust_stream(api, discovery_prompt, context, architect_model, "openrouter")
        
        if not output:
            ui.print("[red]>> Phase 1 aborted due to fatal API error. Exiting research loop.[/red]")
            return
            
        handle_ai_commands(output)
        
        discovery_path = f"experiments/discovery{lang_ext}"
        if os.path.exists(discovery_path):
            ensure_dependencies(discovery_path, tool_path=runner)
            discovery_output = execute_and_verify(api, runner, discovery_path, target_lang, target_model, "openrouter", context, log_path)
        else:
            ui.print(f"[red]>> Fatal Error: {discovery_path} was not created. Exiting research loop.[/red]")
            return
    else:
        ui.print("[dim]>> Skipping Discovery Phase. Using existing Research Log context.[/dim]")

    # Refresh context after Phase 1 so Phase 2 sees discovery files and logs
    from nova_cli.local.contextifier import run_contextify
    context.update(run_contextify(os.getcwd(), save_to_disk=True))

    # --- PHASE 2: EXPERIMENTATION LOOP ---
    num_experiments = questionary.text("How many experimental iterations should NOVA run?", default="2").ask()
    if not num_experiments or not str(num_experiments).isdigit():
        ui.print("[yellow]>> Cancelled or invalid input. Aborting.[/yellow]")
        return
    max_iterations = int(num_experiments)

    # Initialize Transaction Log (Step 5 of Revamp)
    task_data = {
        "user_goal": user_prompt,
        "iterations_target": max_iterations,
        "current_iteration": 0,
        "artifacts_needed": [], # Will be populated by Architect
        "status": "in_progress"
    }
    # Access state via ui helper or global (injected during execution)
    from nova_cli.cli.shell import NovaShell
    # Note: In the skill context, we use the instance state
    # For now, we assume the skill has access to the session state
    
    last_run_out = ""

    i = 0
    while i < max_iterations:
        current_turn = next_turn + i
        ui.print(f"\n[bold magenta]┌─── Experiment Turn {current_turn} ───[/bold magenta]")
        
        with open(log_path, "r", encoding="utf-8") as f:
            research_memory = f.read()
            
        # Step 2: Backwards-Chaining - Identify if user wants specific report items
        # Cleanup ghost files to prevent [EDIT] tag hallucination
        exp_path = f"experiments/experiment_{current_turn}{lang_ext}"
        if os.path.exists(exp_path): os.remove(exp_path)

        experiment_prompt = (
            f"SYSTEM_OVERRIDE: You are in the AGENTIC RESEARCH LOOP - Turn {current_turn}.\n"
            f"TARGET_LANGUAGE: {target_lang}\n"
            f"RESEARCH_MEMORY:\n{research_memory}\n\n"
            f"LATEST_RUN_STDOUT:\n{discovery_output if i==0 and not is_resume else last_run_out}\n\n"
            f"USER_FINAL_GOAL: {user_prompt}\n\n"
            f"TASK 1: Analyze USER_FINAL_GOAL for specific Report/Visualization requirements.\n"
            f"TASK 2: Generate the code for `experiments/experiment_{current_turn}{lang_ext}`.\n"
            f"CRITICAL RULE: Always use [CREATE] tags. Even if the file exists in the map, you MUST rewrite it using [CREATE].\n"
            f"CRITICAL RULE 2: The code MUST save all data required for the final report into `experiments/artifacts/` as JSON or PNG files.\n"
            f"TASK 3: Update `experiments/research_log.md` with the new hypothesis and a list of expected artifacts.\n\n"
            f"Output TWO files using [CREATE] tags."
        )
        
        output = _robust_stream(api, experiment_prompt, context, target_model, "openrouter")
        handle_ai_commands(output)
        
        exp_path = f"experiments/experiment_{current_turn}{lang_ext}"
        if os.path.exists(exp_path):
            ensure_dependencies(exp_path, tool_path=runner)
            try:
                last_run_out = execute_and_verify(api, runner, exp_path, target_lang, target_model, "openrouter", context, log_path)
                
                # --- STATE SNAPSHOT UPDATE (Step 3 of Revamp) ---
                m_match = re.search(r"METRIC_RESULT:\s*([\d\.]+)", last_run_out)
                n_match = re.search(r"METRIC_NAME:\s*(.+)", last_run_out)
                
                metric_val = m_match.group(1) if m_match else "N/A"
                metric_name = n_match.group(1).strip() if n_match else "Score"
                
                # Update Level 0 Memory
                new_vitals = {
                    "latest_experiment": current_turn,
                    "champion_metric": metric_val,
                    "metric_type": metric_name,
                    "last_updated": time.strftime("%Y-%m-%d %H:%M:%S"),
                    "available_artifacts": os.listdir("experiments/artifacts")
                }
                
                # Persistence logic using module-level json
                state_path = "experiments/.nova_state.json"
                existing = {}
                if os.path.exists(state_path):
                    try:
                        with open(state_path, "r") as f: existing = json.load(f)
                    except: pass
                existing.update(new_vitals)
                with open(state_path, "w") as f: json.dump(existing, f, indent=2)

                if m_match: ui.print(f"[bold green]>> Iteration {i+1} Metric: {metric_val} ({metric_name})[/bold green]")
            except Exception as e:
                ui.print(f"[yellow]>> Experiment {current_turn} failed completely. Logging failure for next turn.[/yellow]")
                last_run_out = f"EXPERIMENT FAILED:\n{str(e)}\n\nNext turn: Analyze this failure and write a new hypothesis to fix it."
                
            # Turn successfully executed (or failed logically, but code was generated)
            i += 1
        else:
            ui.print(f"[bold red]>> AI failed to generate {exp_path}. Forcing self-correction...[/bold red]")
            last_run_out = f"SYSTEM ERROR: You failed to output [CREATE: {exp_path}] in the previous turn. You MUST use the exact [CREATE] tag to output the code."
            # Do NOT increment `i` here, ensuring the loop retries the same turn number until a file is made.
                
            # Refresh context so the next iteration (or Phase 3) sees the newly created files
        context.update(run_contextify(os.getcwd(), save_to_disk=True))

    # --- PHASE 3: CONSOLIDATION (Step 1 of Revamp: Fast-Track $X=1$) ---
    if max_iterations == 1:
        ui.print("[bold cyan]>> Single experiment mode: Skipping consolidation phase.[/bold cyan]")
        final_path = f"experiments/experiment_1{lang_ext}"
        # We redirect the "final model" to be the first experiment
        final_log = last_run_out
    else:
        ui.print("[bold green]>> Phase 3: Consolidating Final Model...[/bold green]")
        with open(log_path, "r") as f:
            final_memory = f.read()
            
        final_prompt = (
            f"TARGET_LANGUAGE: {target_lang}\n"
            f"Using this Research Log, implement the winning logic in `final_model{lang_ext}`:\n{final_memory}\n\n"
            f"CRITICAL: You MUST use the [CREATE: final_model{lang_ext}] tag to output the code. Do not use [EDIT] tags."
        )
        final_output = _robust_stream(api, final_prompt, context, architect_model, "openrouter")
        handle_ai_commands(final_output)
    
    # Run the final model to get logs for interpretation
    final_path = f"final_model{lang_ext}"
    final_log = ""
    if os.path.exists(final_path):
        ensure_dependencies(final_path, tool_path=runner)
        try:
            final_log = execute_and_verify(api, runner, final_path, target_lang, target_model, "openrouter", context, log_path)
        except Exception as e:
            ui.print(f"[bold red]>> Final model execution failed. Proceeding to interpretation with error logs.[/bold red]")
            final_log = f"CRITICAL FAILURE during final model execution:\n{str(e)}"
        
        # Display the raw output to the user
        if final_log and final_log != "SUCCESS_SIGNAL":
            ui.script_output(final_log, title=f"Execution Logs: {final_path}", color="green" if "CRITICAL FAILURE" not in final_log else "red")

    # --- PHASE 4: INTERPRETATION ---
    ui.print("[bold cyan]>> Phase 4: Interpreting Results...[/bold cyan]")
    interpret_prompt = f"Explain the final results of this research to the user:\n{final_log}"
    interpretation = _robust_stream(api, interpret_prompt, context, architect_model, "openrouter", check_truncation=False)

    # Save Interpretation to Lab State for future report updates
    state_path = "experiments/.nova_state.json"
    if os.path.exists(state_path):
        with open(state_path, "r") as f: l_state = json.load(f)
        l_state["initial_interpretation"] = interpretation
        with open(state_path, "w") as f: json.dump(l_state, f, indent=2)

    # --- PHASE 5: COMPREHENSIVE HTML REPORT ---
    want_report = questionary.confirm("Would you like a professional HTML Report (with PDF export)?").ask()
    if want_report:
        ui.print("[bold cyan]>> Architecting Comprehensive Research Report...[/bold cyan]")
        
        # 1. READ ARTIFACTS FOR INJECTION (Anti-CORS Defense)
        artifacts_data = {}
        available_images = []
        art_dir = "experiments/artifacts"
        if os.path.exists(art_dir):
            available_images = [f for f in os.listdir(art_dir) if f.endswith(".png")]
            available_jsons = [f for f in os.listdir(art_dir) if f.endswith(".json")]
            for f_name in available_jsons:
                f_path = os.path.join(art_dir, f_name)
                try:
                    with open(f_path, "r", encoding="utf-8") as f: 
                        artifacts_data[f_name] = f.read()
                except Exception:
                    pass

        # 2. Pull final research log
        with open(log_path, "r") as f:
            full_research_log = f.read()

        report_prompt = (
            f"TASK: Generate a high-fidelity Research Report in single-file HTML.\n"
            f"FILE_TARGET: [CREATE: Report.html]\n"
            f"AESTHETIC: Academic White Paper / Professional Technical Journal.\n"
            f"STYLE_RULES:\n"
            f"- Background: Soft gray workspace with a white 'Paper' container.\n"
            f"- Fonts: 'Inter' for headers, 'PT Serif' for body text.\n\n"
            f"CRITICAL RULE: DO NOT use fetch() or XMLHttpRequest to load data. Browsers block local file access.\n"
            f"CRITICAL RULE 2: You MUST embed the provided JSON data below into <script> constants (e.g., const DATA = {{...}}) and use JS to render the tables on load.\n"
            f"CRITICAL RULE 3: You MUST embed EVERY image listed in 'AVAILABLE_VISUALIZATIONS' using an HTML <img> tag (e.g., <img src=\"experiments/artifacts/filename.png\">).\n\n"
            f"AVAILABLE_VISUALIZATIONS:\n{', '.join(available_images) if available_images else 'None'}\n\n"
            f"INJECTED DATA FOR TABLES:\n{json.dumps(artifacts_data, indent=2)}\n\n"
            f"THE REPORT SECTIONS MUST BE:\n"
            f"1. DOCUMENT HEADER: Large bold title, subtitle, and metadata block.\n"
            f"2. EXECUTIVE SUMMARY: A business distillation.\n"
            f"3. JUSTIFICATION & METHODOLOGY: Synthesize the 'Research Log'.\n"
            f"4. EMPIRICAL FINDINGS: Use the 'Injected Data' to build tables for metrics. Underneath the tables, render the 'AVAILABLE_VISUALIZATIONS' and write a detailed, professional interpretation below each graph based on the context.\n"
            f"5. DIAGNOSTIC ANALYSIS: Interpret 'Terminal Logs'.\n"
            f"6. LIMITATIONS: What the model lacks.\n"
            f"7. PRINT UI: A floating button for 'Export to PDF'.\n\n"
            f"CONTEXT DATA:\n"
            f"INTERPRETATION:\n{interpretation}\n\n"
            f"TERMINAL_LOGS:\n{final_log}\n\n"
            f"RESEARCH_LOG_HISTORY:\n{full_research_log}\n"
        )
        
        report_output = _robust_stream(api, report_prompt, context, architect_model, "openrouter")
        handle_ai_commands(report_output)
        
        if os.path.exists("Report.html"):
            import webbrowser
            report_abs = os.path.abspath("Report.html")
            ui.print(f"[bold green]✔ Comprehensive Report Generated: {report_abs}[/bold green]")
            webbrowser.open(f"file://{report_abs}")

    ui.print("\n[bold green]✔ Research Complete. All experimental artifacts are in /experiments.[/bold green]")

def run_reactive_sidecar(api, user_prompt, lab_state):
    """Handles incremental requests using Sidecar scripts."""
    import json # Namespace Guard for dynamic execution
    ui.print(f"[bold magenta]• Reactive Mode: Processing request using Lab Memory...[/bold magenta]")
    
    # 1. Identify latest experiment
    latest_num = lab_state.get("latest_experiment", 1)
    # Detect language extension from existing files
    ext = ".py" if os.path.exists(f"experiments/experiment_{latest_num}.py") else ".R"
    runner = sys.executable if ext == ".py" else "Rscript"
    
    # 2. Sidecar Planning
    sidecar_prompt = (
        f"SYSTEM_OVERRIDE: You are in REACTIVE SIDECAR mode.\n"
        f"CONTEXT: You just finished Experiment {latest_num}. The user has a follow-up request.\n"
        f"USER_REQUEST: {user_prompt}\n"
        f"LAB_STATE: {json.dumps(lab_state)}\n\n"
        f"TASK: Generate a 'Sidecar' script `experiments/sidecar_task{ext}` that:\n"
        f"1. Loads the data/model from experiment {latest_num}.\n"
        f"2. Generates the SPECIFIC artifact (JSON/PNG) requested by the user.\n"
        f"3. Saves it to `experiments/artifacts/`.\n\n"
        f"CRITICAL: Output ONLY the [CREATE: experiments/sidecar_task{ext}] tag and the code. Do not re-run training if not needed."
    )

    from nova_cli.local.contextifier import run_contextify
    context = run_contextify(os.getcwd(), save_to_disk=True)

    output = _robust_stream(api, sidecar_prompt, context, "moonshotai/kimi-k2.6", "openrouter")
    handle_ai_commands(output)

    sidecar_path = f"experiments/sidecar_task{ext}"
    if os.path.exists(sidecar_path):
        ensure_dependencies(sidecar_path, tool_path=runner)
        try:
            ui.print(f"[cyan]>> Executing Sidecar to generate new data...[/cyan]")
            # Run with healing
            run_with_healing(command_args=[runner, sidecar_path], cwd=os.getcwd(), model="moonshotai/kimi-k2.6", provider="openrouter", context=context)
            
            # Update artifacts list in state
            lab_state["available_artifacts"] = os.listdir("experiments/artifacts")
            with open("experiments/.nova_state.json", "w") as f:
                json.dump(lab_state, f, indent=2)
                
            ui.print(f"[bold green]✔ Sidecar successful. New artifacts synchronized.[/bold green]")
            
            # 3. RE-GENERATE REPORT if requested
            if "report" in user_prompt.lower():
                ui.print(f"[cyan]>> Architecting High-Fidelity Report with Artifacts...[/cyan]")
                
                # 1. ARTIFACT MANIFEST (Tell AI exactly what exists)
                art_dir = "experiments/artifacts"
                available_images = [f for f in os.listdir(art_dir) if f.endswith(".png")]
                available_jsons = [f for f in os.listdir(art_dir) if f.endswith(".json")]
                
                # 2. READ JSON CONTENT FOR INJECTION
                artifacts_data = {}
                for f_name in available_jsons:
                    with open(os.path.join(art_dir, f_name), "r") as f: artifacts_data[f_name] = f.read()

                # 3. PULL ORIGINAL INTERPRETATION (The "Good Text")
                original_analysis = lab_state.get("initial_interpretation", "See Research Log.")

                # Fetch fresh context
                from nova_cli.local.contextifier import run_contextify
                context = run_contextify(os.getcwd(), save_to_disk=True)
                with open("experiments/research_log.md", "r") as f: log_mem = f.read()
                
                report_prompt = (
                    f"TASK: Generate a professional, production-ready `Report.html` (Academic/Journal Style).\n"
                    f"USER_REQUEST: {user_prompt}\n"
                    f"AVAILABLE_VISUALIZATIONS: {', '.join(available_images)}\n"
                    f"THEME_COLOR: Slate & Cyan.\n\n"
                    f"CRITICAL RULES:\n"
                    f"1. NO PLACEHOLDERS: Do NOT use `const METRICS = {{}}`. You MUST hard-code the actual numbers into the HTML tables or a script constant.\n"
                    f"2. EMBED EVERYTHING: Include and explain every visualization listed in AVAILABLE_VISUALIZATIONS using <img> tags (path: experiments/artifacts/filename).\n"
                    f"3. NO FETCH: Browsers block local fetch. Inject the JSON data provided below directly into the code.\n"
                    f"4. NARRATIVE: Use the INITIAL_ANALYSIS text below to form the Executive Summary and findings.\n\n"
                    f"INITIAL_ANALYSIS (Professional text to use):\n{original_analysis}\n\n"
                    f"INJECTED DATA FOR TABLES:\n{json.dumps(artifacts_data, indent=2)}\n\n"
                    f"RESEARCH_LOG_HISTORY:\n{log_mem}\n\n"
                    f"Output ONLY the [CREATE: Report.html] tag and code block."
                )
                
                report_output = _robust_stream(api, report_prompt, context, "openai/gpt-oss-120b", "openrouter", check_truncation=False)
                handle_ai_commands(report_output)
                
                if os.path.exists("Report.html"):
                    import webbrowser
                    ui.print(f"[bold green]✔ Report Updated: {os.path.abspath('Report.html')}[/bold green]")
                    webbrowser.open(f"file://{os.path.abspath('Report.html')}")

        except Exception as e:
            ui.print(f"[red]>> Sidecar failed: {e}[/red]")

--- FILE: frontend-web/SKILL.md ---

# skill.md: The Web Architect — Design Intelligence Edition

## Identity

You are a Principal Creative Engineer with embedded design intelligence. You do not use templates. You do not default to AI-style purple/pink gradients, glassmorphism on everything, or generic card layouts. Every decision is deliberate and specific to the business.

---

## PHASE 0: SCOPE EXPANSION (Always First — Non-Negotiable)

Before planning anything, classify the request scope:

**PARTIAL REQUEST DETECTION**: If the user asks for a single section ("hero section", "navbar", "pricing card"), you MUST expand it to a complete website appropriate for the implied business. "A hero section for a bakery" = full bakery website. "A navbar for a gym" = full gym website.

**EXPANSION RULES**:

- Single section mentioned → full website with all standard sections for that business type
- Single page mentioned → full multi-page website
- Vague prompt ("make a website") → infer business type → complete appropriate website
- ONLY skip expansion if user explicitly says "only this section" or "just the [component]"

The `sections` array in your output MUST ALWAYS represent the full website, never a single section.

---

## PHASE 1: DESIGN INTELLIGENCE — INDUSTRY RULES

### Business Type → Section Pattern Mapping

| Business Type               | Required Sections                                                             |
| --------------------------- | ----------------------------------------------------------------------------- |
| SaaS / B2B Tool             | Hero → Features → How It Works → Pricing → Testimonials → FAQ → CTA → Footer  |
| E-commerce / Product        | Hero → Products → Features → Social Proof → Newsletter → Footer               |
| Restaurant / Food           | Hero → Menu → About → Gallery → Reservations → Contact → Footer               |
| Beauty / Spa / Wellness     | Hero → Services → About → Gallery → Testimonials → Booking → Contact → Footer |
| Portfolio / Creative Agency | Hero → Work → Services → About → Process → Testimonials → Contact → Footer    |
| Fintech / Banking           | Hero → Features → Security → Pricing → Testimonials → FAQ → CTA → Footer      |
| Healthcare / Medical        | Hero → Services → Team → About → Testimonials → Contact → Footer              |
| Real Estate                 | Hero → Listings → Features → About → Testimonials → Contact → Footer          |
| Education / Course          | Hero → Curriculum → Instructor → Testimonials → Pricing → FAQ → CTA → Footer  |
| Music / Entertainment       | Hero → Music/Video → About → Events → Merch → Contact → Footer                |
| Hotel / Travel              | Hero → Rooms → Amenities → Gallery → Testimonials → Booking → Footer          |
| Tech Startup                | Hero → Problem → Solution → Features → Traction → Team → Pricing → Footer     |
| Legal / Consulting          | Hero → Services → About → Case Studies → Team → Contact → Footer              |
| Fitness / Gym               | Hero → Programs → Trainers → Pricing → Testimonials → Schedule → Footer       |
| Crypto / Web3               | Hero → Why → Tokenomics → Roadmap → Team → FAQ → Community → Footer           |
| Non-profit / Charity        | Hero → Mission → Impact → Programs → Team → Donate → Contact → Footer         |

### Style Selection (choose exactly one — never mix)

| Style              | Best For                                            | Key Traits                                                       |
| ------------------ | --------------------------------------------------- | ---------------------------------------------------------------- |
| Minimalism         | Architecture, consulting, legal, finance            | Extreme whitespace, thin fonts, restrained palette               |
| Neo-Brutalism      | Creative agencies, bold startups, streetwear, music | Thick borders, hard drop-shadows, flat colors, zero blur         |
| Dark Luxury        | Premium audio, jewellery, spirits, high-end tech    | Near-black bg, gold/amber accents, serif headings                |
| Corporate SaaS     | B2B software, dashboards, productivity              | Rounded cards, blue/purple accents, tight professional spacing   |
| Editorial Magazine | Media, fashion, lifestyle                           | Serif headings, asymmetric grid, dense typography                |
| Playful Bold       | Food, events, children's apps, consumer             | Saturated colors, rounded-3xl, bouncy animations                 |
| Organic Natural    | Wellness, eco, beauty brands                        | Earthy tones, organic shapes, warm serif typography              |
| Neubrutalism       | Gen Z brands, Figma-style tools                     | Visible borders, raw energy, bold type, intentional imperfection |
| Dark OLED          | Coding platforms, gaming, developer tools           | Pure black, neon accents, monospace fonts                        |
| Claymorphism       | Educational apps, children, SaaS onboarding         | Soft 3D, rounded, colorful, friendly                             |
| Glassmorphism      | ONLY crypto, web3, AI tools, futuristic tech        | backdrop-blur, translucent panels, gradient mesh                 |

### Anti-Patterns (Never Do These)

- AI purple/pink gradients on non-AI products
- Glassmorphism on wellness, food, legal, education, finance
- Emoji used as icons — use lucide-react SVG icons only
- Same opacity fade animation on every element
- Missing `cursor-pointer` on interactive elements
- Dark mode as default for wellness, healthcare, food, children
- Neon colors on B2B/enterprise products
- "Lorem ipsum" — all copy must be business-specific
- Generic filenames: `hero.jpg`, `bg.jpg`, `image1.jpg`

---

## PHASE 2: MOTION DESIGN SYSTEM (Framer Motion — Mandatory)

### Rule: Generate `src/animations.ts` FIRST, Before Any Component

This is the single source of truth for all motion. Every component imports from it. Never write inline animation objects anywhere.

```typescript
// src/animations.ts
import type { Variants, Transition } from "framer-motion";

// === SPRING CONFIGS ===
export const spring = {
  gentle: { type: "spring", stiffness: 120, damping: 20 } as Transition,
  snappy: { type: "spring", stiffness: 260, damping: 20 } as Transition,
  bouncy: { type: "spring", stiffness: 400, damping: 10 } as Transition,
  slow: { type: "spring", stiffness: 80, damping: 25 } as Transition,
};

// === EASING ===
export const ease = {
  smooth: [0.25, 0.46, 0.45, 0.94] as const,
  snappy: [0.16, 1, 0.3, 1] as const,
  cinematic: [0.76, 0, 0.24, 1] as const,
};

// === DIRECTIONAL FADES ===
export const fadeUp: Variants = {
  hidden: { opacity: 0, y: 40 },
  show: { opacity: 1, y: 0, transition: { duration: 0.6, ease: ease.smooth } },
};
export const fadeDown: Variants = {
  hidden: { opacity: 0, y: -30 },
  show: { opacity: 1, y: 0, transition: { duration: 0.5, ease: ease.smooth } },
};
export const fadeLeft: Variants = {
  hidden: { opacity: 0, x: -50 },
  show: { opacity: 1, x: 0, transition: { duration: 0.6, ease: ease.smooth } },
};
export const fadeRight: Variants = {
  hidden: { opacity: 0, x: 50 },
  show: { opacity: 1, x: 0, transition: { duration: 0.6, ease: ease.smooth } },
};
export const scaleIn: Variants = {
  hidden: { opacity: 0, scale: 0.85 },
  show: { opacity: 1, scale: 1, transition: spring.gentle },
};

// === STAGGER FACTORY ===
export const stagger = (
  delayChildren = 0.1,
  staggerChildren = 0.08,
): Variants => ({
  hidden: { opacity: 0 },
  show: { opacity: 1, transition: { delayChildren, staggerChildren } },
});

// === HERO SECTION ===
export const heroContainer: Variants = {
  hidden: {},
  show: { transition: { staggerChildren: 0.12, delayChildren: 0.2 } },
};
export const heroItem: Variants = {
  hidden: { opacity: 0, y: 60, filter: "blur(8px)" },
  show: {
    opacity: 1,
    y: 0,
    filter: "blur(0px)",
    transition: { duration: 0.8, ease: ease.smooth },
  },
};

// === PAGE TRANSITIONS ===
export const pageTransition: Variants = {
  initial: { opacity: 0, y: 12 },
  animate: {
    opacity: 1,
    y: 0,
    transition: { duration: 0.45, ease: ease.smooth },
  },
  exit: {
    opacity: 0,
    y: -8,
    transition: { duration: 0.3, ease: ease.cinematic },
  },
};

// === HOVER PRESETS ===
export const hoverLift = { y: -4, transition: spring.snappy };
export const hoverScale = { scale: 1.03, transition: spring.snappy };
export const hoverGlow = {
  boxShadow: "0 20px 40px rgba(0,0,0,0.15)",
  transition: { duration: 0.3 },
};
```

### Scroll-Triggered Pattern (Every Section Component — No Exceptions)

```tsx
import { motion, useInView } from "framer-motion";
import { useRef } from "react";
import { fadeUp, fadeLeft, fadeRight, stagger, hoverLift } from "../animations";

const FeaturesSection = () => {
  const ref = useRef(null);
  const isInView = useInView(ref, { once: true, margin: "-80px" });

  return (
    <motion.section
      ref={ref}
      variants={stagger()}
      initial="hidden"
      animate={isInView ? "show" : "hidden"}
    >
      <motion.h2 variants={fadeUp}>Heading</motion.h2>
      <motion.p variants={fadeUp}>Subtext</motion.p>
      <div className="grid grid-cols-3 gap-8">
        {cards.map((card) => (
          <motion.div key={card.id} variants={fadeUp} whileHover={hoverLift}>
            {/* card content */}
          </motion.div>
        ))}
      </div>
    </motion.section>
  );
};
```

### Section-Specific Animation Rules

| Section          | Variant Pattern                                 | Notes                                    |
| ---------------- | ----------------------------------------------- | ---------------------------------------- |
| Hero             | `heroContainer` + `heroItem`                    | blur+slide, staggered, never simple fade |
| Features/Cards   | `stagger()` + `fadeUp` per card                 | directional stagger from bottom          |
| Left-Right Split | `fadeLeft` (text) + `fadeRight` (image)         | alternate based on layout                |
| Testimonials     | `stagger(0.2, 0.15)` + `scaleIn`                | cards pop in one by one                  |
| Pricing          | `fadeUp` + `staggerChildren: 0.1` + `hoverLift` |                                          |
| CTA Section      | `scaleIn` + `hoverScale` on button              |                                          |
| Navbar           | `fadeDown` on mount only                        | no useInView                             |
| Footer           | `stagger()` + `fadeUp` per column               |                                          |

### AnimatePresence (Page Transitions — Mandatory in App.tsx)

```tsx
import { AnimatePresence, motion } from "framer-motion";
import { useLocation, Routes } from "react-router-dom";
import { pageTransition } from "./animations";

// App.tsx — wrap all Routes:
const location = useLocation();

<AnimatePresence mode="wait">
  <motion.div
    key={location.pathname}
    variants={pageTransition}
    initial="initial"
    animate="animate"
    exit="exit"
  >
    <Routes location={location}>{/* routes */}</Routes>
  </motion.div>
</AnimatePresence>;
```

---

## PHASE 3: DESIGN TOKEN SYSTEM

### Rule: Generate `src/tokens.ts` FIRST (before any component)

```typescript
// src/tokens.ts — populate from PLAN palette and font values
export const tokens = {
  color: {
    primary: "", // from plan
    secondary: "",
    accent: "",
    background: "",
    surface: "",
    text: "",
    muted: "",
    border: "",
  },
  font: {
    heading: "", // from plan
    body: "",
  },
  spacing: {
    section: "py-24 lg:py-32",
    container: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8",
    card: "p-6 lg:p-8",
    gap: "gap-6 lg:gap-8",
  },
  radius: {
    sm: "rounded-lg",
    md: "rounded-xl",
    lg: "rounded-2xl",
    xl: "rounded-3xl",
  },
  shadow: {
    sm: "shadow-md",
    md: "shadow-lg",
    lg: "shadow-xl",
    hover: "shadow-2xl",
  },
} as const;
```

---

## PHASE 4: BUILD ORDER RULES

Always generate files in this dependency order:

1. `src/animations.ts` — motion constants (zero dependencies)
2. `src/tokens.ts` — design tokens (zero dependencies)
3. Shared utilities / custom hooks
4. Atomic components (Button, Card, Badge, Input)
5. Section components (Hero, Features, Testimonials, etc.)
6. Page-level components (Home.tsx, About.tsx, Contact.tsx)
7. `src/App.tsx` — assembles pages + AnimatePresence
8. `src/main.tsx` — entry point, BrowserRouter wrapper

---

## PHASE 5: PRE-DELIVERY CHECKLIST

Before declaring build complete, all of these MUST be true:

- [ ] No emoji used as icons — lucide-react SVGs only
- [ ] `cursor-pointer` on ALL clickable elements
- [ ] Hover states on all interactive elements (150-300ms transitions)
- [ ] Text contrast ≥ 4.5:1 (AA) in light mode
- [ ] Focus states visible for keyboard navigation
- [ ] `prefers-reduced-motion` via `useReducedMotion()` from framer-motion
- [ ] Responsive: 375px, 768px, 1024px, 1440px
- [ ] `AnimatePresence` in `App.tsx` for page transitions
- [ ] All section components use `useInView` for scroll-triggered animations
- [ ] All animation values imported from `src/animations.ts` — zero inline motion objects
- [ ] All design tokens imported from `src/tokens.ts` — zero hardcoded hex colors in components
- [ ] No "Lorem ipsum" — all copy is business-specific and realistic
- [ ] All images use `/assets/filename.jpg` hardcoded strings (never import statements)

---

## PHASE 6: TECHNICAL RULES

### Architecture

- Component-based. `src/components/` for reusable pieces. `src/pages/` for pages.
- `App.tsx` is the layout orchestrator — imports pages, wraps in `AnimatePresence`.
- NEVER use `@/` path aliases. Use explicit relative paths (`../components/Button`).
- NEVER import images. Use hardcoded `/assets/filename.jpg` in `src` attributes.
- NEVER use `App.css`, `react.svg`, `vite.svg` — they are deleted from the scaffold.
- TSX files for anything containing JSX or React Hooks. TS files for utilities only.
- `import type { ReactNode } from 'react'` — `verbatimModuleSyntax` is active.

### Styling

- Tailwind utility classes only. No inline `style={{}}` except for dynamic CSS variables.
- No `@apply` in production components.
- For conditional classes use the `cn()` utility pattern.

### Content Quality

- All arrays fully populated: minimum 6 features, 3 pricing tiers, 4 testimonials.
- All grids have real, specific business content.
- No "Coming Soon" or placeholder text.
- All forms have validation states and a success state.
- All buttons have loading states for async actions.


--- FILE: frontend-web/__init__.py ---



--- FILE: frontend-web/builder.py ---

import os
import json
import re
import questionary
from typing import Dict, Any

from nova_cli.nova_core.ai.api_client import BridgeyeAPIClient
from nova_cli.local.ui import ui
from nova_cli.local.file_manager.commands import handle_ai_commands
from rich.tree import Tree
from rich.panel import Panel
import urllib.request
import urllib.parse

# --- CONSTANTS ---
ARCHITECT_MODEL = "openai/gpt-oss-120b"
ARCHITECT_PROVIDER = "openrouter"
BUILDER_MODEL = "moonshotai/kimi-k2.6"
BUILDER_PROVIDER = "openrouter"

def _extract_json(text: str) -> dict:
    """Robust JSON extraction to handle LLM markdown formatting."""
    try:
        # If it's wrapped in markdown backticks
        match = re.search(r'```(?:json)?\s*(\{.*?\})\s*```', text, re.DOTALL)
        if match:
            return json.loads(match.group(1))
        # Fallback: find the first { and last }
        start = text.find('{')
        end = text.rfind('}')
        if start != -1 and end != -1:
            return json.loads(text[start:end+1])
        return json.loads(text)
    except Exception as e:
        ui.print(f"[red]Failed to parse, Trying Again...[/red]")
        return {}

def load_skill_md() -> str:
    """Loads the SKILL.md rules to inject into the planner."""
    skill_path = os.path.join(os.path.dirname(__file__), "SKILL.md")
    if os.path.exists(skill_path):
        with open(skill_path, "r", encoding="utf-8") as f:
            return f.read()
    return ""

def query_ui_ux_pro_max(query_text: str) -> str:
    """
    SINGLE SOURCE OF TRUTH for invoking the UI-UX-PRO-MAX search engine.
    Resolves the script path relative to this file (skills/frontend-web/)
    and runs it as a subprocess. Returns the markdown design system output,
    or an empty string if the engine is unavailable or fails.

    Called by:
    - stage_4_planner() in this file (single-file/legacy HTML build path)
    - handle_ai_request() in nova_cli/cli/shell_parts/ai_logic.py, via
      build_architect_design_context() below (Vite/multi-page build path)
    """
    import subprocess
    import sys

    ui_ux_path = os.path.join(os.path.dirname(__file__), "ui-ux-pro-max", "scripts", "search.py")
    if not os.path.exists(ui_ux_path):
        return ""

    try:
        query_clean = (query_text or "").replace('"', '').replace("'", "")[:1000]
        result = subprocess.run(
            [sys.executable, ui_ux_path, query_clean, "--design-system", "-f", "markdown"],
            capture_output=True, text=True, encoding="utf-8", check=True
        )
        return result.stdout
    except Exception as e:
        ui.print(f"[yellow]>> UI-UX-PRO-MAX execution skipped: {e}[/yellow]")
        return ""

def build_architect_design_context(query_text: str) -> str:
    """
    SINGLE SOURCE OF TRUTH for Architect/Planning design intelligence.
    Combines SKILL.md (scope expansion rule, business-type section mapping,
    style selection table, motion design system, anti-patterns) with the
    live UI-UX-PRO-MAX search engine output (industry-specific colors,
    fonts, patterns) into one authoritative context block.

    Used by BOTH:
    - skills/frontend-web/builder.py (stage_4_planner, single-file/legacy path)
    - nova_cli/cli/shell_parts/ai_logic.py (PLAN intent, Vite/multi-page path)

    This prevents the two callers from drifting out of sync with separate
    hardcoded copies of the same design intelligence logic.
    """
    parts = []

    skill_md = load_skill_md()
    if skill_md:
        parts.append(
            "SKILL.md DESIGN RULES (authoritative \u2014 scope expansion, "
            f"business-type sections, style selection, motion system, anti-patterns):\n{skill_md}"
        )

    ui_ux_output = query_ui_ux_pro_max(query_text)
    if ui_ux_output:
        parts.append(
            "UI-UX-PRO-MAX DESIGN SYSTEM (AUTHORITATIVE \u2014 override the SKILL.md "
            f"generic style table with these specific values):\n{ui_ux_output}"
        )

    return "\n\n".join(parts)

def stage_2_classifier(api: BridgeyeAPIClient, user_prompt: str) -> Dict[str, Any]:
    """Scores the prompt to determine how much context is missing."""
    prompt = f"""
    SYSTEM: You are a strict intent classifier for a web development engine.
    Analyze the user's web build request and score its completeness.
    Output ONLY valid JSON. No markdown backticks, no explanations.

    SCHEMA:
    {{
      "has_business_context": bool,
      "has_visual_direction": bool,
      "has_section_structure": bool,
      "has_tech_preference": bool,
      "completeness_score": int (0-100),
      "missing": [list of strings indicating what is missing]
    }}

    USER REQUEST:
    {user_prompt}
    """
    with ui.create_loader("Analyzing request complexity..."):
        res = api.chat(prompt, context={}, model=ARCHITECT_MODEL, provider=ARCHITECT_PROVIDER)
    return _extract_json(res)

def stage_3_enhancer(api: BridgeyeAPIClient, user_prompt: str) -> Dict[str, Any]:
    """Fills in missing business context for sparse prompts (Score <= 35)."""
    prompt = f"""
    SYSTEM: You are a Web Prompt Enhancer for a web development engine.
    The user provided a very sparse request. Infer and fill in reasonable defaults for the business.
    Do NOT invent visual themes or colors (that is handled later). Focus purely on content/business logic.
    Output ONLY valid JSON. No markdown backticks.

    SCHEMA:
    {{
      "business_name": "string",
      "business_type": "string",
      "core_services": ["string"],
      "target_audience": "string",
      "location": "string",
      "cta_action": "string",
      "must_have_sections": ["string"],
      "tech_preference": "string",
      "special_requirements": ["string"]
    }}

    SPARSE USER REQUEST:
    {user_prompt}
    """
    with ui.create_loader("Running Web Prompt Enhancer..."):
        res = api.chat(prompt, context={}, model=ARCHITECT_MODEL, provider=ARCHITECT_PROVIDER)
    return _extract_json(res)

def stage_4_planner(api: BridgeyeAPIClient, user_prompt: str, classification: dict, enhancer_data: dict, skill_md: str, dna: dict = None, build_choice: str = None) -> Dict[str, Any]:
    """Combines all context with SKILL.md to generate the definitive Build Plan."""
    
    score = classification.get("completeness_score", 0)
    missing = classification.get("missing", [])
    is_vite = dna and dna.get("type") == "vite"
    # Honor user selection: if they chose single, we ignore the Vite multi-page override
    force_single = (build_choice == "single")

    # Dynamic 3-Tier Planning Logic
    if score <= 35:
        mode_instruction = "FULL GENERATION MODE: The user provided a sparse prompt. Use the ENHANCED BUSINESS CONTEXT below. Auto-select the most appropriate theme from SKILL.md and build a complete, detailed plan filling all visual and structural gaps."
        context_str = f"ENHANCED BUSINESS CONTEXT:\n{json.dumps(enhancer_data, indent=2)}\n\nUSER PROMPT:\n{user_prompt}"
    elif score <= 65:
        mode_instruction = "GAP-FILLING MODE: The user provided partial details. Lock all user-stated preferences. Fill the specific gaps listed in IDENTIFIED GAPS using SKILL.md defaults."
        context_str = f"USER PROMPT:\n{user_prompt}\n\nIDENTIFIED GAPS TO FILL:\n{json.dumps(missing)}"
    else:
        mode_instruction = "STRUCTURE ONLY MODE: The user fully specified the requirements. Lock EVERY user-specified value (colors, fonts, sections). Do NOT reinterpret or override user intent. Use SKILL.md ONLY to fill the minor missing pieces."
        context_str = f"USER PROMPT:\n{user_prompt}\n\nMINOR GAPS TO FILL:\n{json.dumps(missing)}"

   # VITE OVERRIDE
    vite_constraint = ""
    if is_vite and not force_single:
        vite_constraint = "\nCRITICAL: VITE PROJECT DETECTED. You MUST set 'scope' to 'multi-page'. You MUST plan for React/Vue components (e.g. .jsx, .tsx, .css). Any file containing React Hooks or JSX MUST use the .jsx or .tsx extension, NEVER .js or .ts. CRITICAL: NEVER use `@/` or absolute path aliases for imports. You MUST use explicit relative paths (e.g., `../components/Header.tsx`, `./utils/format.ts`). CRITICAL: Tailwind CSS is ALREADY installed and configured. Do NOT generate tailwind.config.js, postcss.config.js, or index.css. CRITICAL: You MUST import './index.css' inside `main.tsx` so Tailwind styles are applied. CRITICAL: TYPESCRIPT RULE: You MUST use `import type` for all TypeScript types/interfaces (e.g., `import type {{ ReactNode, FC }} from 'react';`) because verbatimModuleSyntax is enabled. CRITICAL: DEPENDENCY BUILD ORDER: You MUST structure the `build_order` logically from bottom to top. Build Context APIs, state stores, and utility functions FIRST. Build UI Components SECOND. Build `App.tsx` and `main.tsx` LAST. REACT ROUTER RULE: <BrowserRouter> MUST wrap the entire <App /> inside `main.tsx`. Never place it inside a sub-component if layout elements use <Link>. PREMIUM UI/UX MANDATE: The design MUST be functional, highly animated, and top-tier (Claude/Vercel quality). CRITICAL: DO NOT make every site look the same! Dynamically adapt the aesthetic to the business (e.g., use 'Neo-brutalism' for creative agencies, 'Minimalist Apple-style' for hardware, 'Clean SaaS' for B2B, 'Elegant Editorial' for fashion/blogs, or 'Dark Web3' for crypto). You MUST plan to use `framer-motion` for smooth page transitions and scroll reveals, and `lucide-react` for iconography. Ensure bespoke responsive layouts and highly polished hover states. It must feel like a premium, custom React app."
        vite_constraint += (
        "\nANIMATION SYSTEM MANDATE: The FIRST TWO files in 'build_order' MUST always be "
        "'src/animations.ts' and 'src/tokens.ts'. These are the design system foundation "
        "every other component imports from them. NEVER inline animation values in components. "
        "Every section component MUST use useInView from framer-motion for scroll-triggered animations. "
        "App.tsx MUST implement AnimatePresence with pageTransition for route transitions. "
        "WEBGL INTEGRATION: If using R3F, you MUST include a global state store (e.g., Zustand in `src/store.ts`) "
        "to bridge context outside the Canvas. The `<Canvas>` MUST be mounted at the absolute root (`z-0`) in `App.tsx` "
        "alongside a `SceneManager` component that listens to route changes and global scroll progress to choreograph "
        "3D transitions and shader uniforms. Do NOT unmount the Canvas on route changes. "
        "Populate animation_profile in your JSON output with spring_style, hero_entry, "
        "section_entry, and hover_style matching the chosen aesthetic."
    )
    elif force_single:
        vite_constraint = "\nCRITICAL: The user explicitly requested a SINGLE FILE BUILD. Ignore project structure and output exactly one .html file containing all CSS/JS."

    # UI-UX-PRO-MAX INTEGRATION — single source of truth via query_ui_ux_pro_max().
    # (SKILL.md is already injected separately below via the {skill_md} parameter,
    # so only the UI-UX-PRO-MAX output is fetched here to avoid duplicating SKILL.md content.)
    domain_tag = enhancer_data.get("business_type") or "business"
    ui_ux_output = query_ui_ux_pro_max(domain_tag)
    ui_ux_pro_max_context = (
        f"\nUI-UX-PRO-MAX DESIGN SYSTEM (AUTHORITATIVE \u2014 override SKILL.md style guidelines with these):\n{ui_ux_output}\n"
        if ui_ux_output else ""
    )

    # PREMIUM REGISTRY INTEGRATION
    registry_context = ""
    registry_path = os.path.join(os.path.dirname(__file__), "registry", "registry_index.json")
    if os.path.exists(registry_path):
        try:
            with open(registry_path, "r", encoding="utf-8") as rf:
                registry_data = json.load(rf)
                registry_context = (
                    "\nPREMIUM COMPONENT REGISTRY (CRITICAL):\n"
                    "You have access to a library of ultra-premium UI components. "
                    "Based on the aesthetic, you MUST select applicable components from this registry to use in your page structure:\n"
                    f"{json.dumps(registry_data, indent=2)}\n\n"
                    "RULES FOR REGISTRY COMPONENTS:\n"
                    "1. STRICT FILTERING: You MUST ONLY select components where the 'best_for' array explicitly matches the business domain or design aesthetic you chose. Do NOT pick 'dark luxury' components for a 'playful' website.\n"
                    "2. Add the path of selected components to the `file_structure.shared_components` array (e.g., 'src/components/ui/BackgroundGradientAnimation.tsx').\n"
                    "3. Add the component name to `selected_registry_components` array below.\n"
                    "4. DO NOT write the raw code for them in your build_order. Assume they already exist.\n"
                )
        except Exception:
            pass

    prompt = f"""
    SYSTEM_OVERRIDE: You are the Lead Architect. Your job is to create a definitive JSON Blueprint for a web build.
    You must strictly adhere to the THEME SYSTEM and RULES defined in the SKILL.md document.
    Rule: User-stated details are locked. SKILL.md fills the silence.

    SCOPE EXPANSION RULE (apply before anything else):
    If the user's request mentions only a single section (e.g., "hero section", "navbar", "pricing card"),
    you MUST expand it to a complete website for the implied business type.
    "A hero section for a bakery" = full bakery website with all standard sections.
    ONLY skip expansion if the user explicitly says "only this section" or "just the [component]".
    The 'sections' list in your output MUST represent the full website, never a single section.
    {ui_ux_pro_max_context}
    {registry_context}

    {mode_instruction}
    
    IMAGE & VISUAL DENSITY MANDATE:
    You MUST determine the required number of media placeholders based on the business type. A luxury or e-commerce site needs 5-8 images. A developer tool needs 1-3. For premium SaaS or luxury sites, you MUST explicitly command the builder in `section_notes` to use a looping `<video>` background in the Hero section (e.g., `src="/assets/abstract-audio-waves.mp4"`). 
    CRITICAL: DO NOT put binary media files (.mp4, .jpg, .png) anywhere in the `file_structure` tree or `build_order`. Media files are auto-generated by the system post-build. 

    SKILL.md RULES:
    {skill_md}

    {context_str}
    {vite_constraint}

    REQUIRED JSON SCHEMA:
    {{
      "domain_tag": "string (1-word specific industry tag, e.g., 'payment', 'audio', 'bakery')",
      "theme": "string (MUST be one of the themes from SKILL.md)",
      "theme_reason": "string (Explain why this theme was chosen or how it adapts the user's request)",
      "palette": {{ "background": "", "primary": "", "accent": "", "text": "", "surface": "" }},
      "fonts": {{ "heading": "", "body": "" }},
      "animation_profile": {{
        "spring_style": "string (gentle|snappy|bouncy|cinematic — match business mood)",
        "hero_entry": "string (e.g. 'blur+slide stagger via heroContainer+heroItem')",
        "section_entry": "string (e.g. 'fadeUp stagger' or 'fadeLeft+fadeRight split')",
        "hover_style": "string (hoverLift|hoverScale|hoverGlow)"
      }},
      "scope": "single-page or multi-page",
        {'"scope": "multi-page",' if is_vite and not force_single else ''}
        "tech": "{"vite-" + (dna.get("framework") or "react") if (is_vite and not force_single) else "html-css-js"}",
        "sections": ["string"],
        "copy_outline": {{ "hero_headline": "", "hero_subline": "", "cta_label": "", 
        "section_notes": {{"section_name": "Must include specific instructions on animations, framer-motion usage, and EXACTly how many <img> tags to place as placeholders."}} }},
        "selected_registry_components": ["string (e.g., 'Ferrofluid', 'BlurText')"],
        "file_structure": {
         "pages": ["filename.ext"],
         "shared_components": ["filename.ext"],
         "build_order": ["filename.ext"] // CRITICAL: DO NOT include .jpg, .png, .mp4, .woff2, .ttf, .svg, or ANY binary/font files here! Only code files.
      } // Only include file_structure if scope is multi-page, otherwise null
    }}

    JSON SCHEMA RULES:
    1. "build_order": DO NOT include .jpg, .png, .mp4, .woff2, .ttf, .svg, or ANY binary/font files! Only output text-based code files (.tsx, .ts, .css, .html). If you need a font like Space Grotesk, import it via Google Fonts in globals.css.
    2. "file_structure": Only include this if scope is "multi-page", otherwise null.
    3. DO NOT output image_assets arrays. The builder will invent media names natively within the code.
    4. "selected_registry_components": You MUST review the 'PREMIUM COMPONENT REGISTRY' menu provided above and pick 2 to 4 components that perfectly match the chosen theme. Output their exact names in this array. You MUST also place their .tsx paths in the `file_structure` tree.
    """
    with ui.create_loader("NOVA is Architecting Blueprint..."):
        res = api.chat(prompt, context={}, model=ARCHITECT_MODEL, provider=ARCHITECT_PROVIDER)
    return _extract_json(res)

def stage_6_build_single(api: BridgeyeAPIClient, plan: dict):
    """Executes a single-page build using Kimi."""
    prompt = f"""
    SYSTEM_OVERRIDE: PHASE: IMPLEMENTATION.
    You are an expert Frontend Developer executing a strict blueprint.
    Invent a highly relevant, descriptive, snake_case filename ending in .html based on the business context (e.g., luxury_watches.html, cyberpunk_portfolio.html).
    Output ONLY a [CREATE: your_invented_filename.html] tag followed immediately by a ```html code block containing the FULL, production-ready website.
    Do NOT output any markdown text outside the block.
    Ensure CSS is in <style>, JS is in <script>. Use CSS variables in :root for the palette.
    CRITICAL: DO NOT use generic, cookie-cutter templates. Apply a bespoke, premium aesthetic (e.g., Minimalism, Neo-brutalism, Editorial) perfectly tailored to the BLUEPRINT's theme. Use smooth CSS transitions, modern typography, and highly polished layout grids.
    IMAGE RULE: Do NOT generate or import images. You MUST write `<img>` placeholders with invented src paths (e.g., `<img src="./assets/hero-bakery.jpg" />`). CRITICAL: You MUST include a highly detailed photography prompt in the `alt` attribute (e.g., `alt="Macro shot of a glowing neon bakery display on a dark table"`). The system will use this alt text to generate the actual image post-build. ALWAYS apply Tailwind classes like `w-full h-full object-cover` on <img> tags to prevent layout breaking.
    NO STUBBING OR TOKEN SAVING (CRITICAL): You MUST fully populate all grids, lists, and content sections with rich, realistic, business-specific text and multiple items. Do NOT use "lorem ipsum" or leave arrays with only 1-2 items. Do NOT leave comments like `<!-- ... rest of the content -->`. Write the complete, production-ready code.
    
    BLUEPRINT:
    {json.dumps(plan, indent=2)}
    """
    ui.print("[cyan]>> NOVA (Kimi k2.6) is generating your single-page website...[/cyan]")
    output = ui.stream_rich_response(api.chat_stream(prompt, context={}, model=BUILDER_MODEL, provider=BUILDER_PROVIDER))
    
    # Save the file locally using the current working directory
    return handle_ai_commands(output, cwd=os.getcwd())

def stage_6_build_multi(api: BridgeyeAPIClient, plan: dict):
    """Executes a multi-page build iteratively using Kimi."""
    file_struct = plan.get("file_structure", {})
    raw_build_order = file_struct.get("build_order", [])
    
    # Security/Sanity filter: AI cannot generate binary image/video files
    build_order = [f for f in raw_build_order if not f.lower().endswith(('.jpg', '.jpeg', '.png', '.gif', '.webp', '.ico', '.mp4'))]

    if not build_order:
        ui.print("[red]Error: Multi-page plan missing build order.[/red]")
        return []

    # Prepend design system foundation files — always built first, every Vite project
    _anim_present = any('animations' in f for f in build_order)
    _tok_present  = any('token' in f.lower() for f in build_order)
    _foundation   = []
    if not _anim_present:
        _foundation.append('src/animations.ts')
    if not _tok_present:
        _foundation.append('src/tokens.ts')
    if _foundation:
        build_order = _foundation + [f for f in build_order if f not in ('src/animations.ts', 'src/tokens.ts')]
        ui.print(f"[dim]>> Design system foundation prepended: {', '.join(_foundation)}[/dim]")

    # Keep a running context of generated files
    all_modified = []
    
    for i, filename in enumerate(build_order, 1):
        # [CORE SYNC] Update context from disk before every file build turn
        ui.print(f"[cyan]• Synchronizing project context for {filename}...[/cyan]")
        from nova_cli.local.contextifier import run_contextify
        current_context = run_contextify(os.getcwd(), save_to_disk=True)
        ui.print(f"[green]✓ Context updated.[/green]")

        ui.print(f"\n[bold cyan]─── Building [{i}/{len(build_order)}]: {filename} ───[/bold cyan]")
        
        prompt = f"""
        SYSTEM_OVERRIDE: PHASE: IMPLEMENTATION.
        You are executing a multi-file web application blueprint.
        Currently building: {filename}.
        Output ONLY a [CREATE: {filename}] tag followed by a code block containing the exact file content.
        Do NOT add conversational text.

        ENVIRONMENT RULES:
        0. PREMIUM COMPONENT RULE: If the PLAN CONTEXT includes 'selected_registry_components' (like HeroGeometric, Ferrofluid, etc.), they ALREADY EXIST in 'src/components/ui/'. You MUST import them using relative paths (e.g., `import {{ HeroGeometric }} from '../ui/HeroGeometric';`) and use them. CRITICAL: You MUST pass business-specific text from the copy_outline into their props (e.g., `<HeroGeometric title1="Your Business Name" />`). DO NOT use generic placeholder text.
        1. If this is a Vite/React project, use ESM imports/exports.
        2. Create reusable UI components in 'src/components/'.
        3. Ensure App.jsx imports and uses these components as the main entry point.
        4. CRITICAL: Any file containing JSX tags or React Hooks MUST be named with a .jsx or .tsx extension. NEVER use .js or .ts for components or hooks.
        5. CRITICAL: NEVER use `@/` or absolute path aliases for imports. You MUST use explicit relative paths (e.g., `../components/Header.tsx`, `./utils/format.ts`).
        6. CRITICAL: If using TailwindCSS in Vite, you MUST output a `postcss.config.js` file (with tailwindcss and autoprefixer) and a `tailwind.config.js` file, otherwise CSS will not compile.
        7. CRITICAL: If using react-router-dom, ensure `<BrowserRouter>` wraps the outermost level (e.g. in `main.tsx`), so `<Link>` components in headers/footers do not crash.
        8. CRITICAL CASING RULE: Import paths are STRICTLY CASE-SENSITIVE. You MUST ensure the capitalization of folders and files in your `import` statements exactly matches the File Structure (e.g., do not use `../components/layout/` if the folder is `Layout/`).
        9. PREMIUM UI/UX MANDATE: You MUST use `framer-motion` for animations (e.g., `<motion.div initial={{opacity: 0}} whileInView={{opacity: 1}}>`) and `lucide-react` for icons. CRITICAL: DO NOT use the same generic "glassmorphism" or "gradient" look for every project unless it specifically fits the brand. Read the BLUEPRINT's theme and apply a highly bespoke, tailored UI, whether that is Neo-brutalism, Ultra-Minimalism, Corporate SaaS, or Editorial. Ensure components are highly interactive with thoughtful Tailwind hover states, layout grids, and smooth transitions. The website must meet the design standards of top-tier design agencies.
        10. ANTI-BOILERPLATE RULE: The default Vite files (`react.svg`, `vite.svg`, `App.css`) have been DELETED. You are STRICTLY FORBIDDEN from importing them in `App.tsx` or `main.tsx`. Write a completely custom `App.tsx`.
        11. MEDIA IMPORT RULE: DO NOT use `import img from './assets/...'` statements at the top of your files. This crashes Vite. You MUST use hardcoded absolute path strings directly in the src attributes (e.g., `<img src="/assets/headphones.jpg" />` or `<video src="/assets/abstract-waves.mp4" />`).
        12. IMAGE ATTRIBUTES RULE: You MUST write `<img>` placeholders with invented `/assets/...` src paths. CRITICAL: You MUST include a highly detailed photography prompt in the `alt` attribute (e.g., `alt="Macro studio photography of glowing neon violet luxury headphones on dark frosted glass"`). The system will use this alt text to fetch/generate the actual image post-build. ALWAYS apply Tailwind classes like `w-full h-full object-cover` on <img> tags to prevent layout breaking.
        13. TYPESCRIPT RULE: If using TSX, you MUST use `import type {{ ReactNode }} from 'react';` to prevent verbatimModuleSyntax compiler errors. Do NOT use deep imports for NPM packages. CRITICAL: DO NOT import `Object3DNode` from `@react-three/fiber` (it crashes the browser). If you use `useGSAP`, bypass TS dependency errors with `// @ts-ignore` rather than creating complex type interfaces.\n"
        14. CROSS-FILE CONTINUITY: When importing components or interfaces generated in previous steps, carefully read the PROJECT CONTEXT to match exact export names and props. Do not hallucinate prop names.
        15. NO STUBBING OR TOKEN SAVING (CRITICAL): You MUST fully populate all grids, lists, and content sections with rich, realistic, business-specific text and multiple items. Do NOT use "lorem ipsum" or leave arrays with only 1-2 items. If building a pricing section, include 3 fully detailed tiers. If building a feature grid, include 4-6 fully populated cards. Do NOT leave comments like `// ... rest of the content`. Write the complete, production-ready code.
        16. ANIMATION SYSTEM (CRITICAL): Import ALL animation values from '../animations' (or './animations' for root files). NEVER write inline animation objects (e.g., NEVER: initial={{{{ opacity: 0 }}}}). Use named exports: fadeUp, fadeLeft, fadeRight, scaleIn, stagger, hoverLift, hoverScale, heroContainer, heroItem, pageTransition. Apply motion.section, motion.div, motion.h2, motion.p wrappers on all animated elements.
        17. SCROLL TRIGGER (CRITICAL — all section components): import {{ motion, useInView }} from 'framer-motion'; import {{ useRef }} from 'react'; const ref = useRef(null); const isInView = useInView(ref, {{ once: true, margin: '-80px' }}); Outer element: <motion.section ref={{ref}} variants={{stagger()}} initial="hidden" animate={{isInView ? 'show' : 'hidden'}}>. Alternate animation directions per element (fadeUp on cards, fadeLeft on left-side text, fadeRight on right-side image). Exception: Navbar and Footer use mount-only animations, not useInView.
        18. DESIGN TOKENS (CRITICAL): Import tokens from '../tokens' (or './tokens'). Never hardcode hex colors, spacing px values, or font names directly in component className strings.
        19. APP.TSX ANIMATE PRESENCE (CRITICAL - App.tsx only): import {{ AnimatePresence, motion }} from 'framer-motion'; import {{ pageTransition }} from './animations'; import {{ useLocation }} from 'react-router-dom'; const location = useLocation(); wrap <Routes> with: <AnimatePresence mode="wait"><motion.div key={{location.pathname}} variants={{pageTransition}} initial="initial" animate="animate" exit="exit"><Routes location={{location}}>...</Routes></motion.div></AnimatePresence>
        20. WEBGL & SCENE ORCHESTRATION (CRITICAL): If building a 3D/WebGL background, place `<Canvas>` at `(z-0)` fixed in App.tsx. Use a Zustand store `(src/store.ts)` for global state (scroll progress, active route). Create a `SceneManager` inside the `<Canvas>` to handle GSAP transitions between 3D assets on route swaps. Sync HTML scroll events to update global scroll state, which `useFrame` reads to update `shaderMaterial` uniforms.

        GLOBAL BLUEPRINT:
        {json.dumps(plan, indent=2)}
        """
        
        output = ui.stream_rich_response(
            api.chat_stream(
                prompt, 
                context=current_context, 
                model=BUILDER_MODEL, 
                provider=BUILDER_PROVIDER
            )
        )
        
        # Save file to disk relative to current directory
        modified = handle_ai_commands(output, cwd=os.getcwd())
        
        if modified:
            all_modified.extend(modified)
                        
    return all_modified

def inject_registry_components(plan: dict, project_root: str):
    """Silently copies premium UI components from the registry to the Vite project."""
    shared_comps = plan.get("file_structure", {}).get("shared_components", [])
    registry_base = os.path.join(os.path.dirname(__file__), "registry")
    # Always inject the core utils.ts if any premium components are used
    if any("ui/" in comp for comp in shared_comps):
        utils_src = os.path.join(registry_base, "core", "utils.ts")
        utils_target = os.path.join(project_root, "src", "components", "core", "utils.ts")
        if os.path.exists(utils_src):
            os.makedirs(os.path.dirname(utils_target), exist_ok=True)
            import shutil
            shutil.copy(utils_src, utils_target)

    for comp in shared_comps:
        filename = os.path.basename(comp)
        # Search the registry folder for this filename
        for root_dir, _, files in os.walk(registry_base):
            if filename in files:
                source_path = os.path.join(root_dir, filename)
                target_path = os.path.join(project_root, comp)
                
                os.makedirs(os.path.dirname(target_path), exist_ok=True)
                import shutil
                shutil.copy(source_path, target_path)
                ui.print(f"[dim]>> Injected Premium Component: {filename}[/dim]")
                break

def run(user_prompt: str, dna: dict = None, build_choice: str = None):
    """Main Orchestrator Entry Point for the Frontend Web Builder Skill."""
    api = BridgeyeAPIClient()
    skill_md = load_skill_md()
    modified_files = []

    if not skill_md:
        ui.print("[red]Fatal: SKILL.md not found in frontend-web directory.[/red]")
        return modified_files, dna

    # VITE HANDOFF GATE:
    # If Vite DNA is detected AND user wants a multi-file build, we handoff to core.
    # If user chose 'single', we stay in the skill to build the single file.
    if dna and dna.get("is_vite") and build_choice != "single":
        return modified_files, dna

    # Stage 2: Classifier
    classification = stage_2_classifier(api, user_prompt)
    score = classification.get("completeness_score", 0)

    # Stage 3: Enhancer (Conditional)
    enhancer_data = {}
    if score <= 35:
        enhancer_data = stage_3_enhancer(api, user_prompt)

    # Stage 4: Planner
    plan = stage_4_planner(api, user_prompt, classification, enhancer_data, skill_md, dna=dna, build_choice=build_choice)
    if not plan:
        ui.print("[red]Failed to generate build plan. Aborting.[/red]")
        return modified_files, dna

    # 
    # Stage 5: Scope Decision & Checkpoint
    scope = plan.get("scope", "single-page")
    theme = plan.get("theme", "MINIMAL")
    palette = plan.get("palette", {})
    fonts = plan.get("fonts", {})
    
    if scope == "multi-page":
        # UX Checkpoint for complex builds
        struct = plan.get("file_structure", {})
        
        ui.print("\n[bold magenta]>> NOVA Architect Plan Ready[/bold magenta]")
        
        # Build Visual Tree
        tree = Tree("[bold cyan]Project File Structure (Build Order)[/bold cyan]")
        for f in struct.get("build_order", []):
            tree.add(f"📄 {f}")
        
        # Append Assets to Visual Tree if any
        assets = plan.get("image_assets", [])
        if assets:
            asset_branch = tree.add("[bold cyan]Image Assets (Auto-Generated)[/bold cyan]")
            for a in assets:
                asset_branch.add(f"🖼️ {a.get('filename', 'image.jpg')} [dim]({a.get('width')}x{a.get('height')})[/dim]")
                
        ui.print(Panel(tree, border_style="cyan"))
        
        confirm = questionary.confirm("Review the plan above. Proceed with build?").ask()
        if not confirm:
            ui.print("[dim]Build cancelled by user.[/dim]")
            return modified_files, dna
            
        ui.display_coding_mode(BUILDER_MODEL)
        inject_registry_components(plan, os.getcwd())
        modified_files = stage_6_build_multi(api, plan)
        
    else:
        # Single-page immediate execution
        ui.display_coding_mode(BUILDER_MODEL)
        modified_files = stage_6_build_single(api, plan)

    ui.print("\n[bold green]✔ Web Build Complete![/bold green]")
    return modified_files, dna


--- FILE: frontend-web/dna_scanner.py ---

import os
import json

def scan_project_dna(cwd):
    """
    Performs a silent check of the directory to identify project type and framework.
    """
    is_src = os.path.basename(cwd) == "src"
    # Identify the potential root
    potential_root = os.path.dirname(cwd) if is_src else cwd

    dna = {
        "type": "empty",     # vite | legacy | framework | empty
        "framework": None,   # react | vue | svelte | etc
        "variant": "js",     # js | ts
        "is_vite": False,
        "is_src_dir": is_src,
        "root_path": potential_root 
    }

    # Check for Vite
    check_root = potential_root
    
    if any(os.path.exists(os.path.join(check_root, f)) for f in ["vite.config.js", "vite.config.ts"]):
        dna["is_vite"] = True
        dna["type"] = "vite"

    # Framework & Language Detection via package.json
    pkg_path = os.path.join(check_root, "package.json")
    if os.path.exists(pkg_path):
        try:
            with open(pkg_path, 'r') as f:
                pkg = json.load(f)
                deps = {**pkg.get("dependencies", {}), **pkg.get("devDependencies", {})}
                
                # Language Variant
                if "typescript" in deps or os.path.exists(os.path.join(check_root, "tsconfig.json")):
                    dna["variant"] = "ts"

                # Framework
                for fw in ["react", "vue", "svelte", "next", "angular"]:
                    if fw in deps:
                        dna["framework"] = fw
                        if dna["type"] == "empty":
                            dna["type"] = "framework"
                        break
        except:
            pass

    # Legacy Detection (Standalone HTML)
    if dna["type"] == "empty" and os.path.exists(os.path.join(cwd, "index.html")):
        dna["type"] = "legacy"

    return dna

--- FILE: frontend-web/registry/registry_index.json ---

{
  "backgrounds": [
    {
      "name": "Ferrofluid",
      "path": "backgrounds/Ferrofluid.tsx",
      "best_for": ["dark luxury", "crypto", "tech startup", "ai", "portfolio"],
      "description": "A highly interactive, liquid WebGL fluid background that reacts to the mouse.",
      "usage_example": "<div className=\"relative w-full h-[600px]\">\n  <Ferrofluid colors={[\"#ffffff\",\"#ffffff\",\"#ffffff\"]} speed={0.5} scale={1.6} />\n</div>"
    },
    {
      "name": "Tiles",
      "path": "backgrounds/Tiles.tsx",
      "best_for": ["minimalist", "corporate saas", "developer tool", "b2b"],
      "description": "A clean grid background where individual tiles light up when the user hovers over them, leaving a fading trail. Must be placed absolutely behind content.",
      "usage_example": "<div className=\"relative w-full h-[500px] overflow-hidden\">\n  <div className=\"absolute inset-0 z-0\">\n    <Tiles rows={20} cols={20} tileSize=\"md\" />\n  </div>\n  <div className=\"relative z-10\">\n    Content goes here\n  </div>\n</div>"
    },
    {
      "name": "BackgroundBeamsWithCollision",
      "path": "backgrounds/BackgroundBeamsWithCollision.tsx",
      "best_for": ["tech startup", "ai", "cyberpunk", "saas"],
      "description": "An interactive background featuring falling light beams that 'explode' into glowing particles when they hit the bottom edge of the container.",
      "usage_example": "<BackgroundBeamsWithCollision><h2 className=\"text-4xl font-bold z-10\">Stunning Collisions</h2></BackgroundBeamsWithCollision>"
    },
    {
      "name": "AuroraBackground",
      "path": "backgrounds/AuroraBackground.tsx",
      "best_for": ["ai", "crypto", "creative agency", "modern saas"],
      "description": "A stunning, smooth flowing mesh gradient background that resembles the Northern Lights. It acts as a wrapper component.",
      "usage_example": "<AuroraBackground>\n  <div className=\"relative z-10\">\n    <h1>Beautiful Aurora</h1>\n  </div>\n</AuroraBackground>"
    },
    {
      "name": "BackgroundGradientAnimation",
      "path": "backgrounds/BackgroundGradientAnimation.tsx",
      "best_for": ["playful", "tech startup", "ai", "consumer"],
      "description": "A highly saturated, liquid-style gradient background where blobs of color smoothly morph around the screen and follow the mouse cursor.",
      "usage_example": "<BackgroundGradientAnimation>\n  <div className=\"flex h-full items-center justify-center text-white\">\n    <h1>Liquid Gradients</h1>\n  </div>\n</BackgroundGradientAnimation>"
    },
    {
      "name": "DarkVeil",
      "path": "backgrounds/Dark Veil.tsx",
      "best_for": ["cyberpunk", "gaming", "crypto", "developer tool"],
      "description": "A dark, sci-fi WebGL canvas background with scanlines, noise, and warped neon gradients.",
      "usage_example": "<div className=\"absolute inset-0 z-0\">\n  <DarkVeil hueShift={0} noiseIntensity={0.5} scanlineIntensity={0.3} speed={0.5} />\n</div>"
    },
    {
      "name": "RetroGrid",
      "path": "backgrounds/RetroGrid.tsx",
      "best_for": ["cyberpunk", "retro-futurism", "gaming", "developer tool", "neo-brutalism"],
      "description": "A purely CSS-based retro 3D perspective grid background with an infinite scrolling animation.",
      "usage_example": "<div className=\"relative w-full h-[500px] bg-white dark:bg-black overflow-hidden flex items-center justify-center\"><RetroGrid /><h1 className=\"relative z-10 text-4xl font-bold\">Retro Grid</h1></div>"
    },
    {
      "name": "LightPillar",
      "path": "backgrounds/Light Pillar.tsx",
      "best_for": ["ai", "tech startup", "modern saas", "dark luxury"],
      "description": "A WebGL background rendering glowing, 3D rotating light pillars. Highly interactive and premium.",
      "usage_example": "<div className=\"absolute inset-0 z-0\">\n  <LightPillar topColor=\"#5227FF\" bottomColor=\"#FF9FFC\" interactive={true} />\n</div>"
    },
    {
      "name": "Lightfall",
      "path": "backgrounds/Lightfall.tsx",
      "best_for": ["dark luxury", "portfolio", "creative agency", "ai"],
      "description": "A WebGL space-like background with shooting light streaks, glowing nebulas, and mouse interaction.",
      "usage_example": "<div className=\"absolute inset-0 z-0\">\n  <Lightfall colors={['#A6C8FF', '#5227FF', '#FF9FFC']} speed={0.5} mouseInteraction={true} />\n</div>"
    },
    {
      "name": "VortexFullPage",
      "path": "backgrounds/VortexFullPage.tsx",
      "best_for": ["ai", "crypto", "tech startup", "gaming"],
      "description": "A full-screen, high-performance HTML5 canvas background rendering a swirling, glowing vortex of simplex-noise-driven particles. Locks itself to the window viewport size.",
      "usage_example": "<VortexFullPage backgroundColor=\"black\" className=\"flex items-center justify-center\"><h2 className=\"text-white text-6xl font-bold\">Vortex</h2></VortexFullPage>"
    },
    {
      "name": "LiquidEther",
      "path": "backgrounds/Liquid Ether.tsx",
      "best_for": ["creative agency", "organic natural", "beauty", "portfolio"],
      "description": "A mesmerizing, high-performance fluid advection WebGL background that swirls like liquid smoke.",
      "usage_example": "<div className=\"absolute inset-0 z-0\">\n  <LiquidEther colors={['#5227FF', '#FF9FFC', '#B497CF']} autoDemo={true} />\n</div>"
    },
    {
      "name": "Prism",
      "path": "backgrounds/Prism.tsx",
      "best_for": ["tech startup", "design collective", "gaming", "web3"],
      "description": "A rotating WebGL 3D glass prism that refracts light and colors.",
      "usage_example": "<div className=\"absolute inset-0 z-0\">\n  <Prism animationType=\"hover\" glow={1} transparent={true} />\n</div>"
    },
    {
      "name": "Vortex",
      "path": "backgrounds/Vortex.tsx",
      "best_for": ["ai", "crypto", "tech startup", "gaming"],
      "description": "A high-performance HTML5 canvas background rendering a swirling, glowing vortex of simplex-noise-driven particles.",
      "usage_example": "<div className=\"w-full h-[500px] overflow-hidden\"><Vortex backgroundColor=\"black\" className=\"flex items-center justify-center\"><h2 className=\"text-white text-4xl\">Vortex</h2></Vortex></div>"
    },
    {
      "name": "Silk",
      "path": "backgrounds/Silk.tsx",
      "best_for": ["luxury", "fashion", "spa", "editorial"],
      "description": "A React Three Fiber shader rendering a slow, flowing silk/fabric texture.",
      "usage_example": "<div className=\"absolute inset-0 z-0\">\n  <Silk color=\"#7B7481\" speed={5} noiseIntensity={1.5} />\n</div>"
    },
    {
      "name": "Sparkles",
      "path": "backgrounds/Sparkles.tsx",
      "best_for": ["crypto", "ai", "dark luxury", "tech startup", "portfolio"],
      "description": "A dynamic, twinkling particle background effect using tsParticles. Great for starry night or magical vibes.",
      "usage_example": "<div className=\"relative w-full h-[500px] bg-black overflow-hidden\">\n  <SparklesCore background=\"transparent\" minSize={0.4} maxSize={1} particleDensity={1200} className=\"w-full h-full\" particleColor=\"#FFFFFF\" />\n</div>"
    },
    {
      "name": "Particles",
      "path": "backgrounds/Particles.tsx",
      "best_for": ["corporate saas", "minimalist", "tech startup", "portfolio", "cyberpunk"],
      "description": "An interactive, lightweight HTML5 canvas particle system where particles float and subtly react to mouse movement. Very performant.",
      "usage_example": "<div className=\"relative w-full h-[500px] bg-black overflow-hidden\">\n  <Particles className=\"absolute inset-0\" quantity={100} ease={80} color=\"#ffffff\" refresh />\n  <div className=\"relative z-10 flex items-center justify-center h-full text-white\">\n    <h1>Particle Canvas</h1>\n  </div>\n</div>"
    },
    {
      "name": "PixelTrail",
      "path": "backgrounds/PixelTrail.tsx",
      "best_for": ["cyberpunk", "developer tool", "crypto", "neo-brutalism", "pixel art"],
      "description": "An interactive grid where moving the mouse leaves a fading trail of solid color blocks. Highly performant DOM manipulation.",
      "usage_example": "<div className=\"relative w-full h-[500px] bg-neutral-950 overflow-hidden\">\n  <PixelTrail pixelSize={24} fadeDuration={600} pixelClassName=\"bg-emerald-500\" />\n  <div className=\"relative z-10 pointer-events-none\">\n    <h1 className=\"text-white\">Pixel Trail</h1>\n  </div>\n</div>"
    },
    {
      "name": "GridPattern",
      "path": "backgrounds/GridPattern.tsx",
      "best_for": ["corporate saas", "minimalist", "developer tool", "b2b", "productivity"],
      "description": "A clean, subtle SVG grid pattern background. Supports highlighting specific squares. Great for SaaS hero sections when masked.",
      "usage_example": "<div className=\"relative w-full h-[500px] flex items-center justify-center overflow-hidden bg-white dark:bg-slate-950\">\n  <GridPattern width={40} height={40} className=\"[mask-image:radial-gradient(600px_circle_at_center,white,transparent)]\" squares={[[4, 4], [5, 1], [8, 2]]} />\n  <h1 className=\"relative z-10 text-4xl font-bold\">Developer Tools</h1>\n</div>"
    },
    {
      "name": "AnimatedGradient",
      "path": "backgrounds/AnimatedGradient.tsx",
      "best_for": ["playful", "tech startup", "ai", "consumer", "creative agency"],
      "description": "A soft, heavily blurred animated background where SVG blobs wander randomly around the screen. Excellent for adding subtle, high-performance color to white or dark spaces.",
      "usage_example": "<div className=\"relative w-full h-[600px] overflow-hidden bg-slate-50 dark:bg-slate-950\">\n  <AnimatedGradient colors={['#3B82F6', '#8B5CF6', '#EC4899']} speed={5} blur=\"heavy\" />\n  <div className=\"relative z-10 flex items-center justify-center h-full\">\n    <h1 className=\"text-5xl font-bold text-slate-900 dark:text-white\">Beautiful Blobs</h1>\n  </div>\n</div>"
    },
    {
      "name": "BackgroundBoxes",
      "path": "backgrounds/BackgroundBoxes.tsx",
      "best_for": ["developer tool", "corporate saas", "tech startup", "bento grids"],
      "description": "An interactive, isometric grid of boxes. When the user hovers over a box, it lights up with a random vibrant color and fades out slowly.",
      "usage_example": "<div className=\"relative w-full h-[500px] bg-slate-900 overflow-hidden flex items-center justify-center\">\n  <div className=\"absolute inset-0 w-full h-full bg-slate-900 z-20 [mask-image:transparent] pointer-events-none\" />\n  <BackgroundBoxes />\n  <h1 className=\"relative z-20 text-white text-4xl font-bold\">Isometric Grid</h1>\n</div>"
    },
    {
      "name": "BeamsBackground",
      "path": "backgrounds/BeamsBackground.tsx",
      "best_for": ["dark luxury", "ai", "tech startup", "developer tool", "crypto"],
      "description": "A dark, atmospheric canvas background with slow-moving, glowing, colorful light beams that rise up from the bottom of the screen.",
      "usage_example": "<BeamsBackground intensity=\"strong\">\n  <div className=\"flex flex-col items-center justify-center text-center\">\n    <h1 className=\"text-6xl font-bold text-white\">Glowing Beams</h1>\n  </div>\n</BeamsBackground>"
    },
    {
      "name": "Entropy",
      "path": "backgrounds/Entropy.tsx",
      "best_for": ["ai", "crypto", "data dashboard", "tech startup", "cyberpunk"],
      "description": "A stunning canvas-based physics simulation demonstrating entropy. Ordered particles on the left are gradually influenced by chaotic, network-linked particles on the right.",
      "usage_example": "<div className=\"flex justify-center items-center min-h-screen bg-black\">\n  <Entropy size={500} />\n</div>"
    },
    {
      "name": "Waves",
      "path": "backgrounds/Waves.tsx",
      "best_for": ["tech startup", "portfolio", "creative agency", "corporate saas"],
      "description": "An interactive, elegant 2D wave field rendered with SVGs and Perlin noise. Bends and reacts to mouse movement.",
      "usage_example": "<div className=\"relative w-full h-[500px] overflow-hidden\">\n  <Waves strokeColor=\"rgba(255, 255, 255, 0.1)\" backgroundColor=\"#0a0a0a\" />\n  <div className=\"relative z-10 flex items-center justify-center h-full\">\n    <h1 className=\"text-5xl font-bold text-white\">Interactive Waves</h1>\n  </div>\n</div>"
    },
    {
      "name": "SpiralAnimation",
      "path": "backgrounds/SpiralAnimation.tsx",
      "best_for": ["tech startup", "ai", "crypto", "gaming", "creative agency"],
      "description": "A complex 3D particle system drawn on an HTML5 canvas. It visualizes a massive spiral galaxy of stars forming and spinning. Ideal for high-end tech or sci-fi themes.",
      "usage_example": "<div className=\"relative w-full h-[600px]\">\n  <SpiralAnimation />\n  <div className=\"absolute inset-0 flex items-center justify-center pointer-events-none\">\n    <h1 className=\"text-5xl font-bold text-white text-center\">The Cosmos<br/><span className=\"text-2xl font-normal text-white/60\">Awaits</span></h1>\n  </div>\n</div>"
    },
    {
      "name": "BGPattern",
      "path": "backgrounds/BGPattern.tsx",
      "best_for": ["corporate saas", "minimalist", "developer tool", "bento grids", "clean"],
      "description": "A high-performance, purely CSS-based background pattern generator. Supports dots, grids, stripes, and checkboards with automatic edge-fading masks.",
      "usage_example": "<div className=\"relative w-full h-[500px] flex items-center justify-center bg-slate-50 dark:bg-slate-950 overflow-hidden\">\n  <BGPattern variant=\"dots\" mask=\"fade-edges\" size={20} fill=\"rgba(100, 116, 139, 0.2)\" />\n  <h1 className=\"relative z-10 text-4xl font-bold text-slate-900 dark:text-white\">CSS Patterns</h1>\n</div>"
    },
    {
      "name": "EtherealShadow",
      "path": "backgrounds/EtherealShadow.tsx",
      "best_for": ["dark luxury", "creative agency", "minimalist", "editorial", "wellness"],
      "description": "A highly atmospheric, liquid shadow effect driven by advanced SVG displacement filters. Extremely subtle and elegant.",
      "usage_example": "<div className=\"relative w-full h-[600px] bg-slate-50 dark:bg-slate-950 overflow-hidden\">\n  <EtherealShadow color=\"rgba(99, 102, 241, 0.4)\" animation={{ scale: 50, speed: 40 }} noise={{ opacity: 0.1, scale: 1 }} className=\"absolute inset-0\">\n    <h1 className=\"text-5xl font-serif text-slate-900 dark:text-white\">Ethereal Depth</h1>\n  </EtherealShadow>\n</div>"
    },
    {
      "name": "FlickeringGrid",
      "path": "backgrounds/FlickeringGrid.tsx",
      "best_for": ["cyberpunk", "developer tool", "crypto", "tech startup", "ai"],
      "description": "A highly performant HTML5 canvas background rendering a dense grid of squares that flicker smoothly. Respects IntersectionObserver to pause when off-screen.",
      "usage_example": "<div className=\"relative w-full h-[500px] flex items-center justify-center overflow-hidden bg-slate-950\">\n  <FlickeringGrid squareSize={4} gridGap={6} color=\"#10B981\" maxOpacity={0.4} flickerChance={0.1} />\n  <h1 className=\"relative z-10 text-5xl font-bold text-white tracking-tight\">System Online</h1>\n</div>"
    },
    {
      "name": "SmokeBackground",
      "path": "backgrounds/SmokeBackground.tsx",
      "best_for": ["dark luxury", "gaming", "creative agency", "tech startup"],
      "description": "A dark, atmospheric WebGL2 volumetric smoke animation. Highly performant and accepts a custom hex color for the smoke tint.",
      "usage_example": "<div className=\"relative w-full h-[600px]\">\n  <SmokeBackground smokeColor=\"#7C3AED\">\n    <h1 className=\"text-5xl font-bold text-white\">Mystic Smoke</h1>\n  </SmokeBackground>\n</div>"
    },
    {
      "name": "GradientBackground",
      "path": "backgrounds/GradientBackground.tsx",
      "best_for": ["corporate saas", "minimalist", "playful", "creative agency"],
      "description": "A smooth, continuously animating linear gradient background using Framer Motion. Highly customizable and lightweight.",
      "usage_example": "<div className=\"w-full h-[400px]\">\n  <GradientBackground overlay={true} overlayOpacity={0.2}>\n    <h1 className=\"text-5xl font-bold text-white\">Smooth Gradients</h1>\n  </GradientBackground>\n</div>"
    },
    {
      "name": "FallingPattern",
      "path": "backgrounds/FallingPattern.tsx",
      "best_for": ["tech startup", "creative agency", "modern saas", "minimalist"],
      "description": "A highly mesmerizing, continuous falling particle pattern achieved entirely through CSS radial gradients and Framer Motion.",
      "usage_example": "<div className=\"relative w-full h-[500px] overflow-hidden\">\n  <FallingPattern color=\"rgba(99,102,241,0.5)\" backgroundColor=\"#020617\" density={1.5} className=\"absolute inset-0\" />\n  <div className=\"relative z-10 flex h-full items-center justify-center\">\n    <h1 className=\"text-4xl font-bold text-white\">Falling Data</h1>\n  </div>\n</div>"
    },
    {
      "name": "GradientDots",
      "path": "backgrounds/GradientDots.tsx",
      "best_for": ["playful", "gaming", "creative agency", "tech startup"],
      "description": "A mesmerizing animated background of colorful, shifting gradients masked by a strict hexagonal dot grid. Pure CSS and Framer Motion.",
      "usage_example": "<div className=\"relative w-full h-[500px] overflow-hidden\">\n  <GradientDots dotSize={8} spacing={12} backgroundColor=\"#0a0a0a\" />\n  <div className=\"relative z-10 flex h-full items-center justify-center\">\n    <h1 className=\"text-5xl font-black text-white mix-blend-difference\">Gradient Dots</h1>\n  </div>\n</div>"
    },
    {
      "name": "BlueprintShader",
      "path": "backgrounds/BlueprintShader.tsx",
      "best_for": ["cyberpunk", "developer tool", "crypto", "tech startup", "ai"],
      "description": "An incredibly advanced WebGL2 shader rendering a deep-navy technical blueprint. Features moving grids, dithered shading, ASCII glyph overlays, and cinematic vignette.",
      "usage_example": "<div className=\"relative w-full h-[600px]\">\n  <BlueprintShader>\n    <h1 className=\"text-5xl font-mono text-white\">System Architecture</h1>\n  </BlueprintShader>\n</div>"
    },
    {
      "name": "DottedSurface",
      "path": "backgrounds/DottedSurface.tsx",
      "best_for": ["tech startup", "ai", "corporate saas", "minimalist"],
      "description": "An elegant, continuous 3D wave of floating dots rendered via Three.js. Automatically adapts its color for light/dark mode.",
      "usage_example": "<div className=\"relative w-full h-[600px] flex items-center justify-center bg-slate-50 dark:bg-slate-950 overflow-hidden\">\n  <DottedSurface />\n  <h1 className=\"relative z-10 text-5xl font-bold text-slate-900 dark:text-white\">Data Topology</h1>\n</div>"
    },
    {
      "name": "NeonMaze",
      "path": "backgrounds/NeonMaze.tsx",
      "best_for": ["cyberpunk", "gaming", "crypto", "tech startup"],
      "description": "An isometric, highly animated HTML5 canvas background depicting a neon, undulating maze of blocks. Excellent for retro, cyberpunk, or gaming aesthetics.",
      "usage_example": "<div className=\"relative w-full h-[500px]\">\n  <NeonMaze>\n    <h1 className=\"text-5xl font-black text-white bg-black/50 px-6 py-2 rounded-lg backdrop-blur-sm\">CYBER MAZE</h1>\n  </NeonMaze>\n</div>"
    }
  ],

  "hero": [
    {
      "name": "HeroGeometric",
      "path": "hero/HeroGeometric.tsx",
      "best_for": [
        "design collective",
        "creative agency",
        "modern saas",
        "dark luxury"
      ],
      "description": "A dark, elegant hero section with floating, slow-moving geometric glass shapes.",
      "usage_example": "<HeroGeometric badge=\"Design Collective\" title1=\"Elevate Your Vision\" title2=\"Crafting Exceptions\" />"
    },
    {
      "name": "BackgroundCircles",
      "path": "hero/BackgroundCircles.tsx",
      "best_for": [
        "tech startup",
        "ai",
        "modern saas",
        "minimalist",
        "data dashboard"
      ],
      "description": "A full-screen hero section featuring animated, rotating, glowing gradient circles with an underlying grid mask. Highly customizable via the 'variant' prop.",
      "usage_example": "<BackgroundCircles title=\"Welcome to the Future\" description=\"The ultimate AI tool for modern teams.\" variant=\"primary\" />"
    },
    {
      "name": "BackgroundPaths",
      "path": "hero/BackgroundPaths.tsx",
      "best_for": ["minimalist", "corporate saas", "editorial", "b2b service"],
      "description": "A clean, high-contrast hero section featuring animated flowing SVG paths in the background and a spring-animated letter-by-letter text reveal.",
      "usage_example": "<BackgroundPaths title=\"Crafting Digital Excellence\" />"
    },
    {
      "name": "HeroHighlight",
      "path": "hero/HeroHighlight.tsx",
      "best_for": ["developer tool", "corporate saas", "tech startup", "ai"],
      "description": "A hero background with a dot-matrix pattern that reveals a glowing accent color under the mouse cursor. Includes a <Highlight> component to animate a gradient background behind text.",
      "usage_example": "import { HeroHighlight, Highlight } from '../ui/HeroHighlight';\n\n<HeroHighlight>\n  <h1 className=\"text-4xl font-bold text-black dark:text-white\">\n    Building the future, <Highlight>one pixel at a time.</Highlight>\n  </h1>\n</HeroHighlight>"
    },
    {
      "name": "HeroSection",
      "path": "hero/HeroSection.tsx",
      "best_for": ["corporate saas", "tech startup", "creative agency", "ecommerce"],
      "description": "A complete, production-ready SaaS Hero Section. Includes a scroll-reactive fixed navigation bar, split hero text with primary and ghost CTAs, an embedded video showcase, and a responsive logo trust strip. Zero external dependencies.",
      "usage_example": "<HeroSection />"
    },
    {
      "name": "HeroWithVideo",
      "path": "hero/HeroWithVideo.tsx",
      "best_for": ["corporate saas", "tech startup", "portfolio"],
      "description": "A clean, modern hero section featuring a fully responsive navigation bar with a mobile drawer, a theme toggle, an email capture form, and a massive rounded video container that plays on command.",
      "usage_example": "<HeroWithVideo brandName=\"Nexus\" heroTitle=\"Innovation Meets Simplicity\" heroDescription=\"Discover cutting-edge solutions designed for the modern digital landscape. We build tools that empower creators and developers to ship faster.\" />"
    },
    {
      "name": "VideoScrollHero",
      "path": "hero/VideoScrollHero.tsx",
      "best_for": ["portfolio", "creative agency", "ecommerce", "media"],
      "description": "A scroll-linked hero section. Features a sticky video container that smoothly scales up from a small card to full size as the user scrolls down the page.",
      "usage_example": "<VideoScrollHero title=\"Your Brand Name\" subtitle=\"Scroll to discover our story\" videoSrc=\"/assets/hero-video.mp4\" />"
    },
    {
      "name": "VHSHero",
      "path": "hero/VHSHero.tsx",
      "best_for": ["cyberpunk", "gaming", "music", "retro-futurism"],
      "description": "An incredibly immersive, high-impact WebGL hero section. Features a fully custom Three.js distortion shader, interactive noise particles, RGB split glitch text, and aggressive GSAP entrance animations.",
      "usage_example": "<VHSHero title=\"CYBER_CORE\" badge=\"SYSTEM ONLINE\" subtitle={<>{'>'} NEURAL.LINK.ACTIVE {'<'}<br/>{'>'} DATA.STREAM.SYNC {'<'}</>} ctaText=\"> INITIATE_HACK <\" />"
    }
  ],

  "text_effects": [
    {
      "name": "BlurText",
      "path": "text_effects/Blur Text.tsx",
      "best_for": ["minimalist", "editorial", "corporate saas", "fashion"],
      "description": "Animates text in word-by-word with a smooth cinematic blur effect triggered on scroll.",
      "usage_example": "<BlurText text=\"Designing the Future\" delay={50} direction=\"top\" />"
    },
    {
      "name": "GradientText",
      "path": "text_effects/Gradient.tsx",
      "best_for": ["saas", "tech startup", "playful", "crypto"],
      "description": "Text with a continuously flowing animated gradient background. Great for highlighting specific keywords.",
      "usage_example": "<GradientText colors={['#5227FF', '#FF9FFC', '#B497CF']} animationSpeed={8}>Supercharge your workflow</GradientText>"
    },
    {
      "name": "ScrollFloat",
      "path": "text_effects/Scroll Float.tsx",
      "best_for": ["editorial", "portfolio", "creative agency", "fashion"],
      "description": "GSAP ScrollTrigger effect where characters float up and lock into place as the user scrolls down the page.",
      "usage_example": "<ScrollFloat animationDuration={1} stagger={0.03}>Creative Visionary</ScrollFloat>"
    },
    {
      "name": "ShinyText",
      "path": "text_effects/Shiny Text.tsx",
      "best_for": ["dark luxury", "crypto", "premium", "saas"],
      "description": "A sleek, metallic shine that repeatedly sweeps across the text. Perfect for premium feature highlights.",
      "usage_example": "<ShinyText text=\"Premium Quality\" speed={3} color=\"#b5b5b5\" shineColor=\"#ffffff\" />"
    },
    {
      "name": "ShuffleText",
      "path": "text_effects/Shuffle.tsx",
      "best_for": ["cyberpunk", "developer tool", "crypto", "neo-brutalism"],
      "description": "A GSAP text effect where letters rapidly scramble, shuffle, and lock into the final string. Hacker aesthetic.",
      "usage_example": "<ShuffleText text=\"SYSTEM INITIALIZED\" shuffleTimes={3} scrambleCharset=\"!@#$%^&*()\" />"
    },
    {
      "name": "SplitText",
      "path": "text_effects/Split Text.tsx",
      "best_for": ["editorial", "minimalist", "portfolio", "architecture"],
      "description": "Advanced GSAP SplitText integration that reveals text character-by-character or line-by-line smoothly on scroll.",
      "usage_example": "<SplitText text=\"Elegant Typography\" splitType=\"chars\" delay={50} />"
    },
    {
      "name": "TextType",
      "path": "text_effects/Text Type.tsx",
      "best_for": ["developer tool", "ai", "terminal", "micro saas"],
      "description": "A realistic typewriter effect with a blinking cursor. Can loop through an array of sentences.",
      "usage_example": "<TextType text={[\"npm run dev\", \"npm run build\", \"npm run deploy\"]} typingSpeed={50} loop={true} />"
    },
    {
      "name": "ParticleText",
      "path": "text_effects/ParticleText.tsx",
      "best_for": ["tech startup", "ai", "portfolio", "cyberpunk"],
      "description": "An interactive HTML5 canvas effect where colorful particles fly in to form words. The user can interact with the particles via right-click to disperse them.",
      "usage_example": "<div className=\"w-full h-[400px] bg-neutral-950\">\n  <ParticleText words={[\"NOVA\", \"INTELLIGENCE\", \"AWAKENS\"]} />\n</div>"
    },
    {
      "name": "UnderlineAnimation",
      "path": "text_effects/UnderlineAnimation.tsx",
      "best_for": ["minimalist", "editorial", "portfolio", "corporate saas"],
      "description": "A collection of highly polished, interactive text underline animations including center-out, comes-in-goes-out, and goes-out-comes-in. Perfect for premium navigation links.",
      "usage_example": "<div className=\"flex gap-4\"><CenterUnderline label=\"Home\" /><ComesInGoesOutUnderline label=\"About\" /></div>"
    }
  ],

  "effects": [
    {
      "name": "GooeyFilter",
      "path": "effects/GooeyFilter.tsx",
      "best_for": ["playful", "organic", "creative"],
      "description": "An invisible SVG filter that makes overlapping elements merge together like liquid goo.",
      "usage_example": "<>\n  <GooeyFilter id=\"goo-effect\" strength={10} />\n  {/* Add style={{ filter: 'url(#goo-effect)' }} to the parent container of the items you want to be gooey */}\n</>"
    },
    {
      "name": "Glow",
      "path": "effects/Glow.tsx",
      "best_for": [
        "dark luxury",
        "corporate saas",
        "minimalist",
        "tech startup"
      ],
      "description": "A subtle, elegant radial background glow effect. Used to highlight hero sections or feature cards.",
      "usage_example": "<div className=\"relative w-full overflow-hidden\">\n <Glow variant=\"top\" />\n <div className=\"relative z-10\">Content over the glow</div>\n</div>"
    },
    {
      "name": "ShineBorder",
      "path": "effects/ShineBorder.tsx",
      "best_for": ["corporate saas", "tech startup", "ai", "crypto"],
      "description": "An animated background border effect that continuously shines around the container's perimeter. Great for highlighting pricing cards or featured elements.",
      "usage_example": "<div className=\"flex items-center justify-center p-8\">\n  <ShineBorder color={[\"#A07CFE\", \"#FE8FB5\", \"#FFBE7B\"]} duration={8} borderWidth={2} borderRadius={12}>\n    <div className=\"w-full h-full flex flex-col items-center justify-center p-8 bg-white dark:bg-black rounded-[12px]\">\n      <h2 className=\"text-2xl font-bold dark:text-white\">Pro Plan</h2>\n      <p className=\"dark:text-neutral-400 mt-2\">Experience full power</p>\n    </div>\n  </ShineBorder>\n</div>"
    },
    {
      "name": "BorderBeam",
      "path": "effects/BorderBeam.tsx",
      "best_for": ["corporate saas", "tech startup", "ai", "crypto", "gaming"],
      "description": "An elegant, high-performance CSS border effect where a glowing beam traces the perimeter of any container. It perfectly inherits the container's border radius.",
      "usage_example": "<div className=\"relative w-full max-w-sm p-12 bg-white dark:bg-neutral-900 rounded-2xl shadow-xl flex items-center justify-center\">\n  <BorderBeam size={250} duration={12} delay={0} />\n  <h2 className=\"text-2xl font-bold dark:text-white\">Premium Card</h2>\n</div>"
    },
    {
      "name": "Magnetic",
      "path": "effects/Magnetic.tsx",
      "best_for": ["portfolio", "creative agency", "interactive buttons", "neo-brutalism"],
      "description": "A physics-based interaction wrapper that pulls its children toward the mouse cursor using spring animations. Perfect for highly tactile buttons or floating elements.",
      "usage_example": "<Magnetic intensity={0.8} actionArea=\"global\"><button className=\"px-6 py-3 bg-black text-white rounded-full\">Hover near me</button></Magnetic>"
    }
  ],

  "media": [
    {
      "name": "VideoPlayer",
      "path": "media/VideoPlayer.tsx",
      "best_for": ["portfolio", "corporate saas", "creative agency", "tech startup", "entertainment"],
      "description": "A beautiful, custom-styled HTML5 video player overlay using Framer Motion. Features a floating glassmorphic control bar that reveals on hover, custom sliders, playback speed controls, and volume toggles.",
      "usage_example": "<div className=\"w-full p-8\">\n  <VideoPlayer src=\"https://www.w3schools.com/html/mov_bbb.mp4\" />\n</div>"
    },
    {
      "name": "HeroVideoDialog",
      "path": "media/HeroVideoDialog.tsx",
      "best_for": ["corporate saas", "tech startup", "portfolio", "creative agency"],
      "description": "A beautiful video thumbnail component that reveals an interactive play button on hover. Clicking it smoothly morphs the video into a full-screen, backdrop-blurred iframe modal.",
      "usage_example": "<div className=\"w-full max-w-4xl mx-auto p-4\">\n  <HeroVideoDialog \n    videoSrc=\"https://www.youtube.com/embed/qh3NGpYRG3I?autoplay=1\" \n    thumbnailSrc=\"https://images.unsplash.com/photo-1611162617474-5b21e879e113?q=80&w=1920&auto=format&fit=crop\" \n    animationStyle=\"from-center\" \n  />\n</div>"
    },
    {
      "name": "DynamicFrameLayout",
      "path": "media/DynamicFrameLayout.tsx",
      "best_for": ["portfolio", "creative agency", "entertainment", "fashion"],
      "description": "A dynamic 3x3 CSS grid layout that expands a specific video cell significantly when hovered. Videos automatically play on hover and pause on leave.",
      "usage_example": "import { DynamicFrameLayout, Frame } from '../ui/DynamicFrameLayout';\n\nconst sampleFrames: Frame[] = [\n  { id: 1, video: 'https://www.w3schools.com/html/mov_bbb.mp4', defaultPos: { x: 0, y: 0, w: 4, h: 4 } },\n  { id: 2, video: 'https://www.w3schools.com/html/mov_bbb.mp4', defaultPos: { x: 4, y: 0, w: 4, h: 4 } },\n  { id: 3, video: 'https://www.w3schools.com/html/mov_bbb.mp4', defaultPos: { x: 8, y: 0, w: 4, h: 4 } },\n  { id: 4, video: 'https://www.w3schools.com/html/mov_bbb.mp4', defaultPos: { x: 0, y: 4, w: 4, h: 4 } },\n  { id: 5, video: 'https://www.w3schools.com/html/mov_bbb.mp4', defaultPos: { x: 4, y: 4, w: 4, h: 4 } },\n  { id: 6, video: 'https://www.w3schools.com/html/mov_bbb.mp4', defaultPos: { x: 8, y: 4, w: 4, h: 4 } },\n  { id: 7, video: 'https://www.w3schools.com/html/mov_bbb.mp4', defaultPos: { x: 0, y: 8, w: 4, h: 4 } },\n  { id: 8, video: 'https://www.w3schools.com/html/mov_bbb.mp4', defaultPos: { x: 4, y: 8, w: 4, h: 4 } },\n  { id: 9, video: 'https://www.w3schools.com/html/mov_bbb.mp4', defaultPos: { x: 8, y: 8, w: 4, h: 4 } }\n];\n\nexport default function App() {\n  return (\n    <div className=\"w-full h-screen p-8 bg-black\">\n      <DynamicFrameLayout frames={sampleFrames} showFrames={true} gapSize={8} />\n    </div>\n  );\n}"
    },
    {
      "name": "HeroVideo",
      "path": "media/HeroVideo.tsx",
      "best_for": ["tech startup", "portfolio", "creative agency", "ecommerce"],
      "description": "A scroll-linked layout component. A small, rounded video at the top of the screen gradually expands, un-clips, and straightens out to fill the viewport as the user scrolls down.",
      "usage_example": "import { ContainerScroll, ContainerStagger, ContainerAnimated, ContainerInset } from '../ui/HeroVideo';\n\nexport default function App() {\n  return (\n    <ContainerScroll className=\"bg-black\">\n      <div className=\"sticky top-0 w-full flex flex-col items-center pt-24 text-center z-10\">\n        <ContainerStagger>\n          <ContainerAnimated animation=\"blur\">\n            <h1 className=\"text-white text-6xl font-bold\">Scroll Down</h1>\n          </ContainerAnimated>\n        </ContainerStagger>\n      </div>\n      <ContainerInset className=\"w-full h-screen absolute top-0 left-0\">\n        <video src=\"https://www.w3schools.com/html/mov_bbb.mp4\" autoPlay loop muted playsInline className=\"w-full h-full object-cover\" />\n      </ContainerInset>\n    </ContainerScroll>\n  );\n}"
    },
    {
      "name": "ScrollExpandMedia",
      "path": "media/ScrollExpandMedia.tsx",
      "best_for": ["portfolio", "creative agency", "ecommerce", "media"],
      "description": "A scroll-linked media expansion component. As the user scrolls, a central media element (video or image) aggressively expands to fill the screen while the background fades out, locking the user until the transition is complete.",
      "usage_example": "<ScrollExpandMedia mediaType=\"video\" mediaSrc=\"https://www.w3schools.com/html/mov_bbb.mp4\" bgImageSrc=\"https://images.unsplash.com/photo-1611162617474-5b21e879e113?q=80&w=1920&auto=format&fit=crop\" title=\"Scroll To Expand\" date=\"2024\" scrollToExpand=\"Keep Scrolling\" textBlend={true}>\n  <div className=\"text-white text-4xl font-bold text-center py-20\">Welcome to the inner content!</div>\n</ScrollExpandMedia>"
    },
    {
      "name": "VideoThumbnailPlayer",
      "path": "media/VideoThumbnailPlayer.tsx",
      "best_for": ["corporate saas", "tech startup", "portfolio"],
      "description": "A responsive, card-style video thumbnail with title and description overlays. Clicking the card opens a full-screen, framer-motion animated iframe modal.",
      "usage_example": "<div className=\"w-full max-w-xl mx-auto p-4\">\n  <VideoThumbnailPlayer \n    title=\"Product Demo\"\n    description=\"Watch how to 10x your workflow in just 2 minutes.\"\n    thumbnailUrl=\"https://images.unsplash.com/photo-1611162617474-5b21e879e113?q=80&w=1920&auto=format&fit=crop\" \n    videoUrl=\"https://www.youtube.com/embed/qh3NGpYRG3I?autoplay=1\"\n  />\n</div>"
    },
    {
      "name": "VideoPlayerPro",
      "path": "media/VideoPlayerPro.tsx",
      "best_for": ["portfolio", "corporate saas", "media", "entertainment", "education"],
      "description": "A premium, standalone custom video player featuring an animated floating glassmorphic control bar. Includes playback speed settings, volume slider overlays, and fullscreen support. Zero dependencies outside of framer-motion.",
      "usage_example": "<div className=\"w-full max-w-4xl p-8\">\n  <VideoPlayerPro src=\"/assets/product-tour.mp4\" />\n</div>"
    },
    {
      "name": "VideoModal",
      "path": "media/VideoModal.tsx",
      "best_for": ["tech startup", "corporate saas", "portfolio", "creative agency"],
      "description": "A sophisticated suite of compound components for building highly customized video modals. Features native framer-motion reveals, auto-hiding play buttons via CSS groups, and extensive layout flexibility.",
      "usage_example": "<VideoModal>\n  <VideoModalTrigger><button>Play Video</button></VideoModalTrigger>\n  <VideoModalContent>\n    <VideoModalTitle>Feature Deep Dive</VideoModalTitle>\n    <VideoPlayer>\n      <VideoPreview><img src=\"/poster.jpg\" /></VideoPreview>\n      <VideoPlayButton><PlayIcon /></VideoPlayButton>\n      <VideoModalVideo><iframe src=\"https://youtube...\" /></VideoModalVideo>\n    </VideoPlayer>\n  </VideoModalContent>\n</VideoModal>"
    }
  ],

    "modals": [
    {
      "name": "MorphingDialog",
      "path": "modals/MorphingDialog.tsx",
      "best_for": ["portfolio", "creative agency", "ecommerce", "saas"],
      "description": "A highly sophisticated compound component that uses Framer Motion layout animations to smoothly morph a trigger card/button into a full-screen modal.",
      "usage_example": "<MorphingDialog>\n  <MorphingDialogTrigger className=\"bg-blue-500 text-white p-4 rounded-xl\">\n    <MorphingDialogTitle>Open Details</MorphingDialogTitle>\n  </MorphingDialogTrigger>\n  <MorphingDialogContainer>\n    <MorphingDialogContent className=\"bg-white dark:bg-neutral-900 p-8 rounded-3xl shadow-2xl w-full max-w-md\">\n      <MorphingDialogTitle className=\"text-2xl font-bold mb-4 dark:text-white\">Expanded State</MorphingDialogTitle>\n      <MorphingDialogDescription className=\"text-neutral-500\">\n        This modal smoothly animated from the trigger button using layoutId. Press Esc or click outside to close.\n      </MorphingDialogDescription>\n      <MorphingDialogClose className=\"text-neutral-500 hover:text-black dark:hover:text-white transition-colors\" />\n    </MorphingDialogContent>\n  </MorphingDialogContainer>\n</MorphingDialog>"
    },
    {
      "name": "ThumbnailButton",
      "path": "media/ThumbnailButton.tsx",
      "best_for": ["corporate saas", "tech startup", "portfolio"],
      "description": "A compact button containing a tiny video thumbnail. When clicked, it expands via Framer Motion's layout animations into a full-screen video player. Supports native videos and YouTube.",
      "usage_example": "<div className=\"flex justify-center p-8\">\n  <ThumbnailButton youtubeId=\"qh3NGpYRG3I\" title=\"Watch the Trailer\" />\n</div>"
    },
    {
      "name": "PublishDialog",
      "path": "modals/PublishDialog.tsx",
      "best_for": ["corporate saas", "developer tool", "dashboard", "b2b"],
      "description": "A clean, highly accessible confirmation dialog box built with Framer Motion. Features a prominent icon indicator and clean cancel/action buttons.",
      "usage_example": "<PublishDialog title=\"Publish to production?\" description=\"These changes will be visible to all users immediately.\" />"
    },
    {
      "name": "AnimatedDialog",
      "path": "modals/AnimatedDialog.tsx",
      "best_for": ["dashboard", "corporate saas", "settings", "forms"],
      "description": "A fully customizable, zero-dependency, Framer Motion powered compound dialog component. A perfect drop-in replacement for Radix/Shadcn dialogs with smooth spring animations.",
      "usage_example": "<Dialog><DialogTrigger className=\"px-4 py-2 bg-black text-white rounded-md\">Open</DialogTrigger><DialogContent><DialogHeader><DialogTitle>Edit Profile</DialogTitle><DialogDescription>Make changes to your profile here.</DialogDescription></DialogHeader></DialogContent></Dialog>"
    }
  ],

  "elements": [
    {
      "name": "Timestamp",
      "path": "elements/Timestamp.tsx",
      "best_for": ["entertainment", "corporate saas", "media"],
      "description": "A small, cleanly formatted timestamp badge with tabular numbers to prevent jitter. Commonly used over video thumbnails or audio players.",
      "usage_example": "<div className=\"relative w-64 h-36 bg-slate-200 dark:bg-slate-800 rounded-lg overflow-hidden\">\n  <img src=\"https://images.unsplash.com/photo-1611162617474-5b21e879e113?q=80&w=640&auto=format&fit=crop\" className=\"w-full h-full object-cover\" />\n  <Timestamp seconds={3725} className=\"absolute bottom-2 right-2\" />\n</div>"
    },
    {
      "name": "SocialLinks",
      "path": "elements/SocialLinks.tsx",
      "best_for": ["portfolio", "creative agency", "footers", "about"],
      "description": "An interactive list of text links. On hover, it smoothly reveals a floating, slightly rotated image thumbnail associated with the link.",
      "usage_example": "<SocialLinks socials={[{ name: 'Twitter', image: '/assets/twitter-bg.jpg' }]} />"
    },
    {
      "name": "Counter",
      "path": "elements/Counter.tsx",
      "best_for": ["dashboard", "ecommerce"],
      "description": "A simple, styled increment/decrement counter element.",
      "usage_example": "<Counter title=\"Adjust Quantity\" initialValue={1} />"
    },
    {
      "name": "AnimatedLink",
      "path": "elements/AnimatedLink.tsx",
      "best_for": ["editorial", "portfolio", "minimalist", "creative agency"],
      "description": "A pure Tailwind CSS animated link that features a smooth underline reveal and a draw-in arrow icon on hover. Zero external animation dependencies.",
      "usage_example": "<AnimatedLink href=\"/work\" variant=\"left\">View our work</AnimatedLink>"
    },
    {
      "name": "TopBanner",
      "path": "elements/TopBanner.tsx",
      "best_for": ["marketing", "ecommerce", "corporate saas", "tech startup"],
      "description": "A sticky top-level announcement banner. Includes a localStorage persistence mechanism so users don't see it again after dismissing it, and a highly animated multi-gradient 'rainbow' style option.",
      "usage_example": "<TopBanner id=\"promo-banner-1\" variant=\"rainbow\" message={<>🎉 Big sale happening now! <a href='#' className='underline'>Shop now</a></>} />"
    }
  ],

  "cards": [
    {
      "name": "InfoCard",
      "path": "cards/InfoCard.tsx",
      "best_for": ["ecommerce", "portfolio", "creative agency", "saas"],
      "description": "A highly interactive, stackable information card. On hover, it expands smoothly and spreads out multiple stacked images (or videos) like a deck of cards. Includes built-in dismiss states.",
      "usage_example": "<div className=\"w-full max-w-sm p-4\">\n  <InfoCard>\n    <InfoCardContent>\n      <InfoCardTitle>New Collection</InfoCardTitle>\n      <InfoCardDescription>Hover to view items</InfoCardDescription>\n    </InfoCardContent>\n    <InfoCardMedia \n      media={[\n        { src: 'https://images.unsplash.com/photo-1523275335684-37898b6baf30?w=400&h=300&fit=crop', alt: 'Watch' },\n        { src: 'https://images.unsplash.com/photo-1524592094714-0f0654e20314?w=400&h=300&fit=crop', alt: 'Clock' }\n      ]}\n    />\n    <InfoCardFooter>\n      <InfoCardDismiss>Dismiss</InfoCardDismiss>\n      <InfoCardAction>View All</InfoCardAction>\n    </InfoCardFooter>\n  </InfoCard>\n</div>"
    },
    {
      "name": "AIGenCard",
      "path": "cards/AIGenCard.tsx",
      "best_for": ["ai", "tech startup", "corporate saas", "portfolio"],
      "description": "A highly complex, fully-featured AI Generation interface card. Includes multi-modal tabs (Image/Video/Avatar), advanced settings, a prompt generation simulator with progress bars, and a searchable generation history list. Zero external dependencies.",
      "usage_example": "<div className=\"flex w-full min-h-screen items-center justify-center p-8 bg-zinc-50 dark:bg-zinc-900\">\n  <AIGenCard />\n</div>"
    },
    {
      "name": "HoverPlayCard",
      "path": "cards/HoverPlayCard.tsx",
      "best_for": ["portfolio", "ecommerce", "creative agency", "media"],
      "description": "A structural card that automatically plays a muted video on hover. Clicking the card unmutes the video and takes full control of playback. Perfect for gallery grids and product listings.",
      "usage_example": "<HoverPlayCard src=\"/assets/product-video.mp4\" poster=\"/assets/poster.jpg\" className=\"w-full max-w-sm aspect-video\" />"
    },
    {
      "name": "VideoUploadCard",
      "path": "cards/VideoUploadCard.tsx",
      "best_for": ["corporate saas", "tech startup", "portfolio", "creator economy"],
      "description": "An interactive video upload card with drag-and-drop support. Features a dramatic 'vending machine' drop animation when the video preview appears.",
      "usage_example": "<VideoUploadCard title=\"Upload Demo\" description=\"Drag and drop your video file here.\" />"
    },
    {
      "name": "VideoGeneratorCard",
      "path": "cards/VideoGeneratorCard.tsx",
      "best_for": ["ai", "tech startup", "corporate saas", "creator economy"],
      "description": "A beautiful prompt input card designed for AI video generation. Features an image storyboard preview strip, media type toggles, and a modern glassmorphic blur-backdrop aesthetic.",
      "usage_example": "<VideoGeneratorCard storyboardImages={[{src: '/assets/image1.jpg', alt: 'Frame 1'}]} initialPrompt=\"Animate these frames...\" />"
    },
    {
      "name": "AnimatedBanner",
      "path": "cards/AnimatedBanner.tsx",
      "best_for": ["ecommerce", "events", "marketing", "dashboard"],
      "description": "A dynamic promotional banner card featuring an autoplaying video background, customizable gradient overlay, and a real-time countdown timer.",
      "usage_example": "<AnimatedBanner title=\"Cyber Monday Sale\" subtitle=\"Up to 50% off everything\" videoSrc=\"/assets/promo.mp4\" deadline={new Date(Date.now() + 86400000)} />"
    }
  ],

  "sections": [
    {
      "name": "FeaturedDemoGrid",
      "path": "sections/FeaturedDemoGrid.tsx",
      "best_for": [
        "corporate saas",
        "b2b",
        "developer tool",
        "tech startup"
      ],
      "description": "A robust Bento-box style feature section. Features a large video/image player alongside smaller feature cards and an integration logo grid.",
      "usage_example": "<FeaturedDemoGrid title={<>Supercharge your <br/> sales workflow.</>} videoSrc=\"/assets/demo.mp4\" />"
    },
    {
      "name": "WorkspaceWelcome",
      "path": "sections/WorkspaceWelcome.tsx",
      "best_for": ["corporate saas", "dashboard", "productivity tool", "creator economy"],
      "description": "An onboarding or dashboard welcome section featuring a personalized greeting, quick action buttons, and a featured video card.",
      "usage_example": "<WorkspaceWelcome userName=\"Alex\" videoTitle=\"Getting Started\" videoDescription=\"Learn the basics in 2 minutes\" videoThumbnail=\"/assets/thumbnail.jpg\" actions={[{ label: 'New Project', icon: <Plus size={16} /> }]} />"
    },
    {
      "name": "OnboardingChecklist",
      "path": "sections/OnboardingChecklist.tsx",
      "best_for": ["corporate saas", "dashboard", "productivity tool"],
      "description": "A responsive onboarding checklist card. Features a split layout with animated list items on the left and a video thumbnail on the right that opens a fully functional, zero-dependency video modal.",
      "usage_example": "<OnboardingChecklist title=\"Get Started\" description=\"Complete these steps to finish setting up your account.\" videoThumbnailUrl=\"/assets/thumbnail.jpg\" videoUrl=\"https://www.youtube.com/embed/dQw4w9WgXcQ?autoplay=1\" items={[{ id: 1, text: 'Create Profile' }]} />"
    },
    {
      "name": "ClippedVideoTab",
      "path": "sections/ClippedVideoTab.tsx",
      "best_for": ["tech startup", "ai", "corporate saas", "developer tool"],
      "description": "A highly stylized, complex section featuring a polygon-clipped video container. Includes floating navigational tabs and a central glassmorphic status card that animates its data based on the selected tab.",
      "usage_example": "<ClippedVideoTab title=\"Our Platforms\" description=\"Crafted interactive UI systems for modern workflows.\" />"
    },
    {
      "name": "AboutGrid",
      "path": "sections/AboutGrid.tsx",
      "best_for": ["corporate saas", "marketing", "b2b", "education"],
      "description": "A clean, modern 3-column grid section with a subtle top-centered radial glow. Perfect for displaying 'About' points, features, or benefits using icon headers.",
      "usage_example": "<AboutGrid title=\"Why choose us?\" subtitle=\"The best features tailored for your business.\" />"
    },
    {
      "name": "DesignAgencyLanding",
      "path": "sections/DesignAgencyLanding.tsx",
      "best_for": ["creative agency", "portfolio", "tech startup", "design collective"],
      "description": "An incredibly comprehensive, full-page template. Includes a sticky navbar, gradient hero, bento-grid portfolio, staggered services, testimonials, interactive contact form, and a full footer.",
      "usage_example": "<DesignAgencyLanding />"
    },
    {
      "name": "LinkInBioSection",
      "path": "sections/LinkInBioSection.tsx",
      "best_for": ["portfolio", "personal", "creator economy", "social"],
      "description": "A complete, full-page 'Link in Bio' or personal portfolio section. Features a glowing avatar, social links array, an about card, and a functional contact form with built-in validation and simulated toast notifications.",
      "usage_example": "<LinkInBioSection name=\"Alex\" headline=\"Hi, I'm Alex\" />"
    }
  ],

  "footers": [
    {
      "name": "Footer2",
      "path": "footers/Footer2.tsx",
      "best_for": ["corporate saas", "ecommerce", "b2b", "marketing"],
      "description": "A comprehensive, 5-column footer section featuring a large brand area on the left, multiple navigation link columns, and a standard bottom copyright bar.",
      "usage_example": "<Footer2 tagline=\"Building the future of the web.\" copyright=\"© 2025 YourBrand. All rights reserved.\" />"
    },
    {
      "name": "MinimalFooter",
      "path": "footers/MinimalFooter.tsx",
      "best_for": ["minimalist", "portfolio", "tech startup", "micro saas"],
      "description": "A clean, compact footer. Features circular social icon buttons on the top right, and a uniquely gridded bottom row with right-aligned main and legal links.",
      "usage_example": "<MinimalFooter brandName=\"Acme Corp\" copyright={{ text: \"© 2025 Acme.\" }} />"
    },
    {
      "name": "LargeNameFooter",
      "path": "footers/LargeNameFooter.tsx",
      "best_for": ["tech startup", "portfolio", "neo-brutalism", "design collective"],
      "description": "A striking modern footer that features a massive, gradient-clipped brand name text spanning the bottom, alongside clean column navigation and a quick-share social action.",
      "usage_example": "<LargeNameFooter brandName=\"Acme Corp\" largeText=\"ACME\" />"
    },
    {
      "name": "FooterNewsletter",
      "path": "footers/FooterNewsletter.tsx",
      "best_for": ["corporate saas", "ecommerce", "marketing", "blog"],
      "description": "A feature-rich 4-column footer featuring an integrated email newsletter signup form, detailed contact info, and an interactive dark mode toggle.",
      "usage_example": "<FooterNewsletter brandName=\"Acme Corp\" newsletterTitle=\"Join our weekly newsletter.\" />"
    },
    {
      "name": "StackedCircularFooter",
      "path": "footers/StackedCircularFooter.tsx",
      "best_for": ["creative agency", "portfolio", "playful", "consumer"],
      "description": "A highly centered, minimalist footer. Features a distinct circular logo container at the top, followed by navigation links, social icons, and an inline newsletter subscription form.",
      "usage_example": "<StackedCircularFooter brandName=\"Acme Corp\" />"
    },
    {
      "name": "IconFooter",
      "path": "footers/IconFooter.tsx",
      "best_for": ["corporate saas", "developer tool", "b2b", "minimalist"],
      "description": "An elegant, clean multi-column footer that renders small Lucide icons next to every navigation link. Social links are cleanly formatted as an inline bulleted list below the brand description.",
      "usage_example": "<IconFooter brand={{ name: 'Stripe', description: 'Financial infrastructure for the internet.' }} />"
    },
    {
      "name": "ThemeToggleFooter",
      "path": "footers/ThemeToggleFooter.tsx",
      "best_for": ["minimalist", "portfolio", "micro saas", "developer tool"],
      "description": "An ultra-minimalist, pill-shaped micro footer. It features a built-in light/dark mode toggle and a smooth 'scroll to top' button.",
      "usage_example": "<ThemeToggleFooter />"
    },
    {
      "name": "RadialGlowFooter",
      "path": "footers/RadialGlowFooter.tsx",
      "best_for": ["ai", "crypto", "tech startup", "dark luxury"],
      "description": "An elegant, animated footer with a subtle radial gradient top-glow. Uses Framer Motion to stagger a blur-fade-in effect across its columns as it scrolls into view.",
      "usage_example": "<RadialGlowFooter brandName=\"Nexus AI\" />"
    },
    {
      "name": "Footer7",
      "path": "footers/Footer7.tsx",
      "best_for": ["corporate saas", "tech startup", "b2b", "editorial"],
      "description": "A split-layout footer. Features the brand logo, description, and social icons constrained to a left column, and 3 columns of navigation links stretching across the right.",
      "usage_example": "<Footer7 description=\"Building tools for modern developers.\" />"
    },
    {
      "name": "AnimatedWaveFooter",
      "path": "footers/AnimatedWaveFooter.tsx",
      "best_for": ["tech startup", "portfolio", "creative agency", "music"],
      "description": "An interactive full-screen footer that features a purely mathematical, animated sine-wave visualization constructed from expanding DOM elements.",
      "usage_example": "<AnimatedWaveFooter />"
    },
    {
      "name": "StickyFooter",
      "path": "footers/StickyFooter.tsx",
      "best_for": ["portfolio", "creative agency", "editorial"],
      "description": "A sophisticated footer that is revealed as if 'stuck' beneath the page content via clever clip-path tricks. Features staggered entrance animations and a massive gradient title.",
      "usage_example": "<StickyFooter title=\"Ready to talk?\" />"
    },
    {
      "name": "TapedFooter",
      "path": "footers/TapedFooter.tsx",
      "best_for": ["startup", "neo-brutalism", "playful", "portfolio"],
      "description": "A striking, boxed footer with a brutalist/playful aesthetic featuring SVG 'tape' elements holding the corners to the background. Features categorized columns with 'soon' badge states.",
      "usage_example": "<TapedFooter brandName=\"ActivationLed\" />"
    },
    {
      "name": "Footer4Col",
      "path": "footers/Footer4Col.tsx",
      "best_for": ["corporate saas", "b2b", "marketing", "ecommerce"],
      "description": "A robust 4-column footer featuring a prominent brand description on the left, social links below it, and a multi-column link grid with a pulsing 'Live Chat' indicator and inline contact icons.",
      "usage_example": "<Footer4Col />"
    },
    {
      "name": "FadeInFooter",
      "path": "footers/FadeInFooter.tsx",
      "best_for": ["corporate saas", "minimalist", "tech startup", "portfolio"],
      "description": "A clean, multi-column footer featuring a staggered fade-in Framer Motion entrance animation as it scrolls into view.",
      "usage_example": "<FadeInFooter brandName=\"Acme Corp\" description=\"Empowering businesses with intelligent solutions.\" />"
    },
    {
      "name": "CenteredFooter",
      "path": "footers/CenteredFooter.tsx",
      "best_for": ["minimalist", "portfolio", "micro saas", "personal"],
      "description": "A clean, centrally aligned footer featuring an inline list of text links, social icons, and copyright text.",
      "usage_example": "<CenteredFooter copyright=\"© 2025 Acme Corp. All rights reserved.\" />"
    },
    {
      "name": "Footer1",
      "path": "footers/Footer1.tsx",
      "best_for": ["minimalist", "blog", "portfolio"],
      "description": "A muted, centered footer block with an extensive row of social icons including TikTok and Threads, and a single row of standard navigation links.",
      "usage_example": "<Footer1 copyright=\"© 2025 YourBrand. All rights reserved.\" />"
    },
    {
      "name": "CorporateFooter",
      "path": "footers/CorporateFooter.tsx",
      "best_for": ["corporate saas", "enterprise", "ecommerce", "b2b"],
      "description": "A massive, multi-column mega menu footer designed for enterprise sites with lots of links. Features a dedicated 'About' text block on the left and a dense grid of categorised links on the right.",
      "usage_example": "<CorporateFooter brandName=\"Acme Enterprise\" />"
    },
    {
      "name": "BorderedGridFooter",
      "path": "footers/BorderedGridFooter.tsx",
      "best_for": ["editorial", "minimalist", "portfolio", "creative agency"],
      "description": "An elegant, structurally divided grid footer featuring top-aligned social links with arrows and clean, separated link columns. Uses a subtle radial glow at the top edge.",
      "usage_example": "<BorderedGridFooter brandName=\"Acme Studio\" />"
    },
    {
      "name": "GradientCenteredFooter",
      "path": "footers/GradientCenteredFooter.tsx",
      "best_for": ["ai", "crypto", "web3", "dark luxury"],
      "description": "A striking, deeply colored gradient footer centered around a prominent logo and concise brand description. Excellent for dark-mode or tech-heavy aesthetics.",
      "usage_example": "<GradientCenteredFooter brandName=\"Acme AI\" />"
    },
    {
      "name": "StickyRevealFooter",
      "path": "footers/StickyRevealFooter.tsx",
      "best_for": ["corporate saas", "enterprise", "fintech", "b2b"],
      "description": "A massive, multi-column enterprise footer that reveals itself via a sticky clip-path effect as the user scrolls to the bottom of the page. Features a subtle radial glow background and staggered fade-in animations.",
      "usage_example": "<StickyRevealFooter brandName=\"Acme Finance\" />"
    },
    {
      "name": "BoxedMinimalFooter",
      "path": "footers/BoxedMinimalFooter.tsx",
      "best_for": ["b2b", "corporate saas", "minimalist", "tech startup"],
      "description": "A very structured, bordered-box footer constrained to a max-width center column, giving it a technical, precision feel. Features a subtle radial gradient background.",
      "usage_example": "<BoxedMinimalFooter brandName=\"Acme Tech\" description=\"A comprehensive fintech platform.\" />"
    },
    {
      "name": "AppDownloadFooter",
      "path": "footers/AppDownloadFooter.tsx",
      "best_for": ["consumer", "ecommerce", "fitness", "social"],
      "description": "A structured footer specifically designed for consumer-facing apps. Features a multi-column link grid and beautifully styled, built-in App Store and Google Play download badges.",
      "usage_example": "<AppDownloadFooter brandName=\"Acme Fitness\" showAppStore={true} showPlayStore={true} />"
    },
    {
      "name": "FlickeringGridFooter",
      "path": "footers/FlickeringGridFooter.tsx",
      "best_for": ["tech startup", "ai", "crypto", "corporate saas"],
      "description": "An incredibly advanced tech footer. Features compliance badges (SOC2, HIPAA, GDPR), animated arrow hover states on links, and a massive background canvas that renders text using flickering pixel squares.",
      "usage_example": "<FlickeringGridFooter brandName=\"Nexus AI\" flickerTextDesktop=\"Analyze Data Faster.\" />"
    },
    {
      "name": "HoverTextFooter",
      "path": "footers/HoverTextFooter.tsx",
      "best_for": ["portfolio", "creative agency", "tech startup", "web3"],
      "description": "An incredibly interactive, dark-mode focused footer. The brand name takes up the full width in massive text, and hovering over it reveals a stunning, cursor-following multi-color gradient mask.",
      "usage_example": "<HoverTextFooter text=\"ACME STUDIO\" />"
    },
    {
      "name": "FloatingLogoFooter",
      "path": "footers/FloatingLogoFooter.tsx",
      "best_for": ["portfolio", "creative agency", "saas", "tech startup"],
      "description": "A striking, highly centralized footer featuring a giant faded brand name spanning the background, with a distinct floating brand icon centered over a horizontal line at the bottom.",
      "usage_example": "<FloatingLogoFooter brandName=\"NEXUS\" />"
    },
    {
      "name": "AnimatedSubscribeFooter",
      "path": "footers/AnimatedSubscribeFooter.tsx",
      "best_for": ["corporate saas", "marketing", "ecommerce", "startup"],
      "description": "A structured 4-column footer featuring an interactive newsletter subscription form with inline loading, success, and error animated states.",
      "usage_example": "<AnimatedSubscribeFooter brandName=\"Acme Corp\" />"
    },
    {
      "name": "BadgeFooter",
      "path": "footers/BadgeFooter.tsx",
      "best_for": ["corporate saas", "tech startup", "developer tool"],
      "description": "A classic, clean footer layout that features optional inline badges next to navigation links (e.g., 'New', 'Hiring', 'Pro') to highlight specific pages.",
      "usage_example": "<BadgeFooter brandName=\"Acme Corp\" />"
    },
    {
      "name": "StatusFooter",
      "path": "footers/StatusFooter.tsx",
      "best_for": ["tech startup", "developer tool", "corporate saas"],
      "description": "A highly technical, Vercel-inspired footer. Features categorized columns, native inline dropdown menus for legal/SDK links, a system status indicator, and a built-in zero-dependency theme toggle switch.",
      "usage_example": "<StatusFooter statusText=\"All systems normal.\" statusColor=\"bg-emerald-500\" />"
    },
    {
      "name": "TerminalFooter",
      "path": "footers/TerminalFooter.tsx",
      "best_for": ["developer tool", "cyberpunk", "tech startup", "dark oled"],
      "description": "A developer-focused, technical footer featuring monospaced typography, a faint grid background, a terminal-style input field, and unique expanding-dot hover effects on the navigation links.",
      "usage_example": "<TerminalFooter brandName=\"SEEKER\" />"
    },
    {
      "name": "CinematicFooter",
      "path": "footers/CinematicFooter.tsx",
      "best_for": ["creative agency", "portfolio", "gaming", "consumer"],
      "description": "A full-screen cinematic footer featuring GSAP scroll-reveal curtains, physics-based magnetic glassmorphism buttons, an animated aurora background, and an infinite scrolling marquee.",
      "usage_example": "<CinematicFooter brandName=\"NOVA\" />"
    },
    {
      "name": "WordmarkFooter",
      "path": "footers/WordmarkFooter.tsx",
      "best_for": ["portfolio", "creative agency", "music", "fashion"],
      "description": "A highly performant, ultra-minimal footer. Displays a giant brand wordmark that features a metallic shine reacting to mouse movements via direct DOM manipulation (zero re-renders).",
      "usage_example": "<WordmarkFooter brandName=\"NEXUS\" />"
    }
  ],

  "navigation": [
    {
      "name": "FloatingHeader",
      "path": "navigation/FloatingHeader.tsx",
      "best_for": ["corporate saas", "minimalist", "tech startup", "portfolio"],
      "description": "A sticky, floating pill-shaped navigation bar. Features a glassmorphic background and a fully responsive, Framer Motion powered slide-out mobile drawer.",
      "usage_example": "<FloatingHeader brandName=\"Nexus AI\" />"
    },
    {
      "name": "ExpandableSidebar",
      "path": "navigation/ExpandableSidebar.tsx",
      "best_for": ["dashboard", "corporate saas", "b2b", "internal tools"],
      "description": "A highly functional, space-saving dashboard sidebar. Collapses to an icon-only view and smoothly expands on hover using Framer Motion. Includes built-in custom dropdowns for organization and user settings.",
      "usage_example": "<ExpandableSidebar organizationName=\"Acme Corp\" currentPath=\"/dashboard\" />"
    },
    {
      "name": "AnimatedSidebar",
      "path": "navigation/AnimatedSidebar.tsx",
      "best_for": ["dashboard", "corporate saas", "internal tools", "b2b"],
      "description": "A fully customizable, zero-dependency, Framer Motion powered compound Sidebar component. A perfect drop-in replacement for Radix/Shadcn sidebars with smooth spring animations, mobile slide-out drawers, and collapsible icon states.",
      "usage_example": "<SidebarProvider><Sidebar><SidebarHeader>Brand</SidebarHeader><SidebarContent><SidebarGroup><SidebarGroupLabel>Menu</SidebarGroupLabel><SidebarMenu><SidebarMenuItem><SidebarMenuButton>Item 1</SidebarMenuButton></SidebarMenuItem></SidebarMenu></SidebarGroup></SidebarContent></Sidebar></SidebarProvider>"
    },
    {
      "name": "MacDock",
      "path": "navigation/MacDock.tsx",
      "best_for": ["portfolio", "creative agency", "playful", "dashboard"],
      "description": "An interactive, macOS-style floating dock navigation. Uses Framer Motion spring physics to smoothly magnify icons as the user's cursor approaches them.",
      "usage_example": "<MacDock><DockIcon><HomeIcon /></DockIcon><DockIcon><UserIcon /></DockIcon></MacDock>"
    },
    {
      "name": "MegaMenuHeader",
      "path": "navigation/MegaMenuHeader.tsx",
      "best_for": ["corporate saas", "enterprise", "b2b", "marketing"],
      "description": "A full-width, fixed header navigation bar designed for complex SaaS sites. Features Framer Motion animated mega-menu dropdowns on desktop and a clean accordion slide-down menu on mobile.",
      "usage_example": "<MegaMenuHeader brandName=\"Acme Corp\" />"
    },
    {
      "name": "Breadcrumbs",
      "path": "navigation/Breadcrumbs.tsx",
      "best_for": ["dashboard", "ecommerce", "documentation", "corporate saas"],
      "description": "A highly accessible, customizable compound breadcrumb component used to display the current page hierarchy. Built without external Radix dependencies.",
      "usage_example": "<Breadcrumb><BreadcrumbList><BreadcrumbItem><BreadcrumbLink href=\"/\">Home</BreadcrumbLink></BreadcrumbItem><BreadcrumbSeparator /><BreadcrumbItem><BreadcrumbPage>Current Page</BreadcrumbPage></BreadcrumbItem></BreadcrumbList></Breadcrumb>"
    }
  ],
  
  "core_dependencies": ["core/utils.ts"]
}


--- FILE: frontend-web/registry/backgrounds/AnimatedGradient.tsx ---

import React, { useMemo, useRef, useState, useEffect } from "react";
import { cn } from "../core/utils";

// Inlined useDimensions hook to keep the component standalone
function useDimensions(ref: React.RefObject<HTMLElement | null>) {
  const [dimensions, setDimensions] = useState({ width: 0, height: 0 });

  useEffect(() => {
    const observeTarget = ref.current;
    if (!observeTarget) return;

    const resizeObserver = new ResizeObserver((entries) => {
      entries.forEach((entry) => {
        setDimensions({
          width: entry.contentRect.width,
          height: entry.contentRect.height,
        });
      });
    });

    resizeObserver.observe(observeTarget);
    
    setDimensions({
      width: observeTarget.getBoundingClientRect().width,
      height: observeTarget.getBoundingClientRect().height,
    });

    return () => {
      resizeObserver.unobserve(observeTarget);
    };
  }, [ref]);

  return dimensions;
}

export interface AnimatedGradientProps {
  colors: string[];
  speed?: number;
  blur?: "light" | "medium" | "heavy";
  className?: string;
}

// Restored EXACT original math
const randomInt = (min: number, max: number) => {
  return Math.floor(Math.random() * (max - min + 1)) + min;
};

export const AnimatedGradient: React.FC<AnimatedGradientProps> = ({
  colors,
  speed = 5,
  blur = "light",
  className,
}) => {
  const containerRef = useRef<HTMLDivElement>(null);
  const dimensions = useDimensions(containerRef);

  const circleSize = useMemo(
    () => Math.max(dimensions.width, dimensions.height),
    [dimensions.width, dimensions.height]
  );

  const blurClass =
    blur === "light"
      ? "blur-2xl"
      : blur === "medium"
      ? "blur-3xl"
      : "blur-[100px]";

  return (
    <div ref={containerRef} className={cn("absolute inset-0 overflow-hidden pointer-events-none", className)}>
      <style>
        {`
          @keyframes background-gradient {
            0% {
              transform: translate(0, 0);
            }
            25% {
              transform: translate(calc(var(--tx-1) * 100%), calc(var(--ty-1) * 100%));
            }
            50% {
              transform: translate(calc(var(--tx-2) * 100%), calc(var(--ty-2) * 100%));
            }
            75% {
              transform: translate(calc(var(--tx-3) * 100%), calc(var(--ty-3) * 100%));
            }
            100% {
              transform: translate(0, 0);
            }
          }
          .animate-background-gradient {
            animation: background-gradient var(--background-gradient-speed) infinite ease-in-out alternate;
          }
        `}
      </style>
      <div className={cn(`absolute inset-0`, blurClass)}>
        {colors.map((color, index) => (
          <svg
            key={index}
            className="absolute animate-background-gradient"
            style={
              {
                top: `${Math.random() * 50}%`,
                left: `${Math.random() * 50}%`,
                // Restored exact original speed calculation
                "--background-gradient-speed": `${1 / speed}s`,
                "--tx-1": Math.random() - 0.5,
                "--ty-1": Math.random() - 0.5,
                "--tx-2": Math.random() - 0.5,
                "--ty-2": Math.random() - 0.5,
                "--tx-3": Math.random() - 0.5,
                "--ty-3": Math.random() - 0.5,
                "--tx-4": Math.random() - 0.5,
                "--ty-4": Math.random() - 0.5,
              } as React.CSSProperties
            }
            width={circleSize * randomInt(0.5, 1.5)}
            height={circleSize * randomInt(0.5, 1.5)}
            viewBox="0 0 100 100"
            xmlns="http://www.w3.org/2000/svg"
          >
            <circle
              cx="50"
              cy="50"
              r="50"
              fill={color}
              // Restored exact original opacities
              className="opacity-30 dark:opacity-[0.15]"
            />
          </svg>
        ))}
      </div>
    </div>
  );
};

--- FILE: frontend-web/registry/backgrounds/AuroraBackground.tsx ---

// @ts-nocheck
import { cn } from "../core/utils";
import React, { ReactNode } from "react";
import { motion } from "framer-motion";

interface AuroraBackgroundProps extends React.HTMLProps<HTMLDivElement> {
  children: ReactNode;
  showRadialGradient?: boolean;
}

export const AuroraBackground = ({
  className,
  children,
  showRadialGradient = true,
  ...props
}: AuroraBackgroundProps) => {
  return (
    <main>
      <div
        className={cn(
          "relative flex flex-col h-[100vh] items-center justify-center bg-zinc-50 dark:bg-zinc-900 text-slate-950 transition-bg",
          className
        )}
        {...props}
      >
        <div className="absolute inset-0 overflow-hidden">
          <motion.div
            animate={{
              backgroundPosition: ["0% 50%", "100% 50%", "0% 50%"],
            }}
            transition={{
              duration: 20,
              repeat: Number.POSITIVE_INFINITY,
              ease: "linear",
            }}
            className={cn(
              `
            [--white-gradient:repeating-linear-gradient(100deg,#fff_0%,#fff_7%,transparent_10%,transparent_12%,#fff_16%)]
            [--dark-gradient:repeating-linear-gradient(100deg,#000_0%,#000_7%,transparent_10%,transparent_12%,#000_16%)]
            [--aurora:repeating-linear-gradient(100deg,#3b82f6_10%,#a5b4fc_15%,#93c5fd_20%,#ddd6fe_25%,#60a5fa_30%)]
            [background-image:var(--white-gradient),var(--aurora)]
            dark:[background-image:var(--dark-gradient),var(--aurora)]
            [background-size:300%,_200%]
            filter blur-[10px] invert dark:invert-0
            after:content-[""] after:absolute after:inset-0 after:[background-image:var(--white-gradient),var(--aurora)] 
            after:dark:[background-image:var(--dark-gradient),var(--aurora)]
            after:[background-size:200%,_100%] 
            after:[background-attachment:fixed] after:mix-blend-difference
            pointer-events-none
            absolute -inset-[10px] opacity-50 will-change-transform`,
              showRadialGradient &&
                `[mask-image:radial-gradient(ellipse_at_100%_0%,black_10%,transparent_70%)]`
            )}
          ></motion.div>
        </div>
        <div className="relative z-10 w-full h-full">{children}</div>
      </div>
    </main>
  );
};

--- FILE: frontend-web/registry/backgrounds/BGPattern.tsx ---

import React from 'react';
import { cn } from '../core/utils';

export type BGVariantType = 'dots' | 'diagonal-stripes' | 'grid' | 'horizontal-lines' | 'vertical-lines' | 'checkerboard';
export type BGMaskType =
	| 'fade-center'
	| 'fade-edges'
	| 'fade-top'
	| 'fade-bottom'
	| 'fade-left'
	| 'fade-right'
	| 'fade-x'
	| 'fade-y'
	| 'none';

export type BGPatternProps = React.ComponentProps<'div'> & {
	variant?: BGVariantType;
	mask?: BGMaskType;
	size?: number;
	fill?: string;
};

const maskClasses: Record<BGMaskType, string> = {
	'fade-edges': '[mask-image:radial-gradient(ellipse_at_center,black,transparent)]',
	'fade-center': '[mask-image:radial-gradient(ellipse_at_center,transparent,black)]',
	'fade-top': '[mask-image:linear-gradient(to_bottom,transparent,black)]',
	'fade-bottom': '[mask-image:linear-gradient(to_bottom,black,transparent)]',
	'fade-left': '[mask-image:linear-gradient(to_right,transparent,black)]',
	'fade-right': '[mask-image:linear-gradient(to_right,black,transparent)]',
	'fade-x': '[mask-image:linear-gradient(to_right,transparent,black,transparent)]',
	'fade-y': '[mask-image:linear-gradient(to_bottom,transparent,black,transparent)]',
	none: '',
};

function getBgImage(variant: BGVariantType, fill: string, size: number) {
	switch (variant) {
		case 'dots':
			return `radial-gradient(${fill} 1px, transparent 1px)`;
		case 'grid':
			return `linear-gradient(to right, ${fill} 1px, transparent 1px), linear-gradient(to bottom, ${fill} 1px, transparent 1px)`;
		case 'diagonal-stripes':
			return `repeating-linear-gradient(45deg, ${fill}, ${fill} 1px, transparent 1px, transparent ${size}px)`;
		case 'horizontal-lines':
			return `linear-gradient(to bottom, ${fill} 1px, transparent 1px)`;
		case 'vertical-lines':
			return `linear-gradient(to right, ${fill} 1px, transparent 1px)`;
		case 'checkerboard':
			return `linear-gradient(45deg, ${fill} 25%, transparent 25%), linear-gradient(-45deg, ${fill} 25%, transparent 25%), linear-gradient(45deg, transparent 75%, ${fill} 75%), linear-gradient(-45deg, transparent 75%, ${fill} 75%)`;
		default:
			return undefined;
	}
}

export const BGPattern = ({
	variant = 'grid',
	mask = 'none',
	size = 24,
	fill = '#252525',
	className,
	style,
	...props
}: BGPatternProps) => {
	const bgSize = `${size}px ${size}px`;
	const backgroundImage = getBgImage(variant, fill, size);

	return (
		<div
			className={cn('absolute inset-0 z-[-1] w-full h-full pointer-events-none', maskClasses[mask], className)}
			style={{
				backgroundImage,
				backgroundSize: bgSize,
				...style,
			}}
			{...props}
		/>
	);
};

BGPattern.displayName = 'BGPattern';

--- FILE: frontend-web/registry/backgrounds/BackgroundBeamsWithCollision.tsx ---

import React, { useRef, useState, useEffect } from "react";
import { motion, AnimatePresence } from "framer-motion";
import { cn } from "../core/utils";

export const BackgroundBeamsWithCollision = ({
  children,
  className,
}: {
  children: React.ReactNode;
  className?: string;
}) => {
  const containerRef = useRef<HTMLDivElement>(null);
  const parentRef = useRef<HTMLDivElement>(null);

  const beams = [
    {
      initialX: 10,
      translateX: 10,
      duration: 7,
      repeatDelay: 3,
      delay: 2,
    },
    {
      initialX: 600,
      translateX: 600,
      duration: 3,
      repeatDelay: 3,
      delay: 4,
    },
    {
      initialX: 100,
      translateX: 100,
      duration: 7,
      repeatDelay: 7,
      className: "h-6",
    },
    {
      initialX: 400,
      translateX: 400,
      duration: 5,
      repeatDelay: 14,
      delay: 4,
    },
    {
      initialX: 800,
      translateX: 800,
      duration: 11,
      repeatDelay: 2,
      className: "h-20",
    },
    {
      initialX: 1000,
      translateX: 1000,
      duration: 4,
      repeatDelay: 2,
      className: "h-12",
    },
    {
      initialX: 1200,
      translateX: 1200,
      duration: 6,
      repeatDelay: 4,
      delay: 2,
      className: "h-6",
    },
  ];

  return (
    <div
      ref={parentRef}
      className={cn(
        "h-96 md:h-[40rem] bg-gradient-to-b from-white to-neutral-100 dark:from-neutral-950 dark:to-neutral-800 relative flex items-center w-full justify-center overflow-hidden",
        // h-screen if you want bigger
        className
      )}
    >
      {beams.map((beam) => (
        <CollisionMechanism
          key={beam.initialX + "beam-idx"}
          beamOptions={beam}
          containerRef={containerRef}
          parentRef={parentRef}
        />
      ))}

      {children}
      <div
        ref={containerRef}
        className="absolute bottom-0 bg-neutral-100 dark:bg-neutral-800 w-full inset-x-0 pointer-events-none"
        style={{
          boxShadow:
            "0 0 24px rgba(34, 42, 53, 0.06), 0 1px 1px rgba(0, 0, 0, 0.05), 0 0 0 1px rgba(34, 42, 53, 0.04), 0 0 4px rgba(34, 42, 53, 0.08), 0 16px 68px rgba(47, 48, 55, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1) inset",
        }}
      ></div>
    </div>
  );
};

const CollisionMechanism = React.forwardRef<
  HTMLDivElement,
  {
    containerRef: React.RefObject<HTMLDivElement | null>;
    parentRef: React.RefObject<HTMLDivElement | null>;
    beamOptions?: {
      initialX?: number;
      translateX?: number;
      initialY?: number;
      translateY?: number;
      rotate?: number;
      className?: string;
      duration?: number;
      delay?: number;
      repeatDelay?: number;
    };
  }
>(({ parentRef, containerRef, beamOptions = {} }, ref) => {
  const beamRef = useRef<HTMLDivElement>(null);
  const [collision, setCollision] = useState<{
    detected: boolean;
    coordinates: { x: number; y: number } | null;
  }>({
    detected: false,
    coordinates: null,
  });
  const [beamKey, setBeamKey] = useState(0);
  const [cycleCollisionDetected, setCycleCollisionDetected] = useState(false);

  useEffect(() => {
    const checkCollision = () => {
      if (
        beamRef.current &&
        containerRef.current &&
        parentRef.current &&
        !cycleCollisionDetected
      ) {
        const beamRect = beamRef.current.getBoundingClientRect();
        const containerRect = containerRef.current.getBoundingClientRect();
        const parentRect = parentRef.current.getBoundingClientRect();

        if (beamRect.bottom >= containerRect.top) {
          const relativeX =
            beamRect.left - parentRect.left + beamRect.width / 2;
          const relativeY = beamRect.bottom - parentRect.top;

          setCollision({
            detected: true,
            coordinates: {
              x: relativeX,
              y: relativeY,
            },
          });
          setCycleCollisionDetected(true);
        }
      }
    };

    const animationInterval = setInterval(checkCollision, 50);

    return () => clearInterval(animationInterval);
  }, [cycleCollisionDetected, containerRef, parentRef]);

  useEffect(() => {
    if (collision.detected && collision.coordinates) {
      setTimeout(() => {
        setCollision({ detected: false, coordinates: null });
        setCycleCollisionDetected(false);
      }, 2000);

      setTimeout(() => {
        setBeamKey((prevKey) => prevKey + 1);
      }, 2000);
    }
  }, [collision]);

  return (
    <>
      <motion.div
        key={beamKey}
        ref={beamRef}
        animate="animate"
        initial={{
          translateY: beamOptions.initialY || "-200px",
          translateX: beamOptions.initialX || "0px",
          rotate: beamOptions.rotate || 0,
        }}
        variants={{
          animate: {
            translateY: beamOptions.translateY || "1800px",
            translateX: beamOptions.translateX || "0px",
            rotate: beamOptions.rotate || 0,
          },
        }}
        transition={{
          duration: beamOptions.duration || 8,
          repeat: Infinity,
          repeatType: "loop",
          ease: "linear",
          delay: beamOptions.delay || 0,
          repeatDelay: beamOptions.repeatDelay || 0,
        }}
        className={cn(
          "absolute left-0 top-20 m-auto h-14 w-px rounded-full bg-gradient-to-t from-indigo-500 via-purple-500 to-transparent",
          beamOptions.className
        )}
      />
      <AnimatePresence>
        {collision.detected && collision.coordinates && (
          <Explosion
            key={`${collision.coordinates.x}-${collision.coordinates.y}`}
            className=""
            style={{
              left: `${collision.coordinates.x}px`,
              top: `${collision.coordinates.y}px`,
              transform: "translate(-50%, -50%)",
            }}
          />
        )}
      </AnimatePresence>
    </>
  );
});

CollisionMechanism.displayName = "CollisionMechanism";

const Explosion = ({ ...props }: React.HTMLProps<HTMLDivElement>) => {
  const spans = Array.from({ length: 20 }, (_, index) => ({
    id: index,
    initialX: 0,
    initialY: 0,
    directionX: Math.floor(Math.random() * 80 - 40),
    directionY: Math.floor(Math.random() * -50 - 10),
  }));

  return (
    <div {...props} className={cn("absolute z-50 h-2 w-2", props.className)}>
      <motion.div
        initial={{ opacity: 0 }}
        animate={{ opacity: 1 }}
        exit={{ opacity: 0 }}
        transition={{ duration: 1.5, ease: "easeOut" }}
        className="absolute -inset-x-10 top-0 m-auto h-2 w-10 rounded-full bg-gradient-to-r from-transparent via-indigo-500 to-transparent blur-sm"
      ></motion.div>
      {spans.map((span) => (
        <motion.span
          key={span.id}
          initial={{ x: span.initialX, y: span.initialY, opacity: 1 }}
          animate={{
            x: span.directionX,
            y: span.directionY,
            opacity: 0,
          }}
          transition={{ duration: Math.random() * 1.5 + 0.5, ease: "easeOut" }}
          className="absolute h-1 w-1 rounded-full bg-gradient-to-b from-indigo-500 to-purple-500"
        />
      ))}
    </div>
  );
};

--- FILE: frontend-web/registry/backgrounds/BackgroundBoxes.tsx ---

import React from "react";
import { motion } from "framer-motion";
import { cn } from "../core/utils";

export const BoxesCore = ({ className, ...rest }: { className?: string }) => {
  const rows = new Array(150).fill(1);
  const cols = new Array(100).fill(1);
  
  // Using direct color values instead of CSS variables
  const colors = [
    "rgb(125 211 252)", // sky-300
    "rgb(249 168 212)", // pink-300
    "rgb(134 239 172)", // green-300
    "rgb(253 224 71)",  // yellow-300
    "rgb(252 165 165)", // red-300
    "rgb(216 180 254)", // purple-300
    "rgb(147 197 253)", // blue-300
    "rgb(165 180 252)", // indigo-300
    "rgb(196 181 253)", // violet-300
  ];

  const getRandomColor = () => {
    return colors[Math.floor(Math.random() * colors.length)];
  };

  return (
    <div
      style={{
        transform: `translate(-40%,-60%) skewX(-48deg) skewY(14deg) scale(0.675) rotate(0deg) translateZ(0)`,
      }}
      className={cn(
        "absolute left-1/4 p-4 -top-1/4 flex -translate-x-1/2 -translate-y-1/2 w-full h-full z-0",
        className
      )}
      {...rest}
    >
      {rows.map((_, i) => (
        <motion.div
          key={`row` + i}
          className="w-16 h-8 border-l border-slate-700 relative"
        >
          {cols.map((_, j) => (
            <motion.div
              whileHover={{
                backgroundColor: getRandomColor(),
                transition: { duration: 0 },
              }}
              animate={{
                transition: { duration: 2 },
              }}
              key={`col` + j}
              className="w-16 h-8 border-r border-t border-slate-700 relative"
            >
              {j % 2 === 0 && i % 2 === 0 ? (
                <svg
                  xmlns="http://www.w3.org/2000/svg"
                  fill="none"
                  viewBox="0 0 24 24"
                  strokeWidth="1.5"
                  stroke="currentColor"
                  className="absolute h-6 w-10 -top-[14px] -left-[22px] text-slate-700 stroke-[1px] pointer-events-none"
                >
                  <path
                    strokeLinecap="round"
                    strokeLinejoin="round"
                    d="M12 6v12m6-6H6"
                  />
                </svg>
              ) : null}
            </motion.div>
          ))}
        </motion.div>
      ))}
    </div>
  );
};

export const BackgroundBoxes = React.memo(BoxesCore);

--- FILE: frontend-web/registry/backgrounds/BackgroundGradientAnimation.tsx ---

// @ts-nocheck
import { cn } from "../core/utils";
import { useEffect, useRef, useState } from "react";
import { motion } from "framer-motion";

export const BackgroundGradientAnimation = ({
  gradientBackgroundStart = "rgb(108, 0, 162)",
  gradientBackgroundEnd = "rgb(0, 17, 82)",
  firstColor = "18, 113, 255",
  secondColor = "221, 74, 255",
  thirdColor = "100, 220, 255",
  fourthColor = "200, 50, 50",
  fifthColor = "180, 180, 50",
  pointerColor = "140, 100, 255",
  size = "80%",
  blendingValue = "hard-light",
  children,
  className,
  interactive = true,
  containerClassName,
}: {
  gradientBackgroundStart?: string;
  gradientBackgroundEnd?: string;
  firstColor?: string;
  secondColor?: string;
  thirdColor?: string;
  fourthColor?: string;
  fifthColor?: string;
  pointerColor?: string;
  size?: string;
  blendingValue?: string;
  children?: React.ReactNode;
  className?: string;
  interactive?: boolean;
  containerClassName?: string;
}) => {
  const interactiveRef = useRef<HTMLDivElement>(null);

  const [curX, setCurX] = useState(0);
  const [curY, setCurY] = useState(0);
  const [tgX, setTgX] = useState(0);
  const [tgY, setTgY] = useState(0);

  useEffect(() => {
    document.body.style.setProperty("--gradient-background-start", gradientBackgroundStart);
    document.body.style.setProperty("--gradient-background-end", gradientBackgroundEnd);
    document.body.style.setProperty("--first-color", firstColor);
    document.body.style.setProperty("--second-color", secondColor);
    document.body.style.setProperty("--third-color", thirdColor);
    document.body.style.setProperty("--fourth-color", fourthColor);
    document.body.style.setProperty("--fifth-color", fifthColor);
    document.body.style.setProperty("--pointer-color", pointerColor);
    document.body.style.setProperty("--size", size);
    document.body.style.setProperty("--blending-value", blendingValue);
  }, []);

  useEffect(() => {
    function move() {
      if (!interactiveRef.current) return;
      setCurX(curX + (tgX - curX) / 20);
      setCurY(curY + (tgY - curY) / 20);
      interactiveRef.current.style.transform = `translate(${Math.round(curX)}px, ${Math.round(curY)}px)`;
    }
    move();
  }, [tgX, tgY]);

  const handleMouseMove = (event: React.MouseEvent<HTMLDivElement>) => {
    if (interactiveRef.current) {
      const rect = interactiveRef.current.getBoundingClientRect();
      setTgX(event.clientX - rect.left);
      setTgY(event.clientY - rect.top);
    }
  };

  const [isSafari, setIsSafari] = useState(false);
  useEffect(() => {
    setIsSafari(/^((?!chrome|android).)*safari/i.test(navigator.userAgent));
  }, []);

  return (
    <div
      className={cn(
        "h-screen w-screen relative overflow-hidden top-0 left-0 bg-[linear-gradient(40deg,var(--gradient-background-start),var(--gradient-background-end))]",
        containerClassName
      )}
    >
      <svg className="hidden">
        <defs>
          <filter id="blurMe">
            <feGaussianBlur in="SourceGraphic" stdDeviation="10" result="blur" />
            <feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 18 -8" result="goo" />
            <feBlend in="SourceGraphic" in2="goo" />
          </filter>
        </defs>
      </svg>
      <div className={cn("relative z-10 w-full h-full", className)}>{children}</div>
      <div
        className={cn(
          "absolute inset-0 gradients-container h-full w-full blur-lg pointer-events-none z-0",
          isSafari ? "blur-2xl" : "[filter:url(#blurMe)_blur(40px)]"
        )}
      >
        <motion.div
          animate={{ x: ["0%", "-50%", "0%"], y: ["0%", "50%", "0%"], scale: [1, 1.2, 1] }}
          transition={{ duration: 20, repeat: Infinity, ease: "linear" }}
          className={cn(
            `absolute [background:radial-gradient(circle_at_center,_rgba(var(--first-color),0.8)_0,_transparent_50%)_no-repeat]`,
            `[mix-blend-mode:var(--blending-value)] w-[var(--size)] h-[var(--size)] top-[calc(50%-var(--size)/2)] left-[calc(50%-var(--size)/2)] opacity-100`
          )}
        ></motion.div>
        <motion.div
          animate={{ x: ["-50%", "0%", "-50%"], y: ["-50%", "0%", "-50%"], scale: [1, 0.8, 1] }}
          transition={{ duration: 25, repeat: Infinity, ease: "linear" }}
          className={cn(
            `absolute [background:radial-gradient(circle_at_center,_rgba(var(--second-color),_0.8)_0,_transparent_50%)_no-repeat]`,
            `[mix-blend-mode:var(--blending-value)] w-[var(--size)] h-[var(--size)] top-[calc(50%-var(--size)/2)] left-[calc(50%-var(--size)/2)] opacity-100`
          )}
        ></motion.div>
        <motion.div
          animate={{ x: ["50%", "0%", "50%"], y: ["50%", "0%", "50%"], scale: [1, 1.3, 1] }}
          transition={{ duration: 30, repeat: Infinity, ease: "linear" }}
          className={cn(
            `absolute [background:radial-gradient(circle_at_center,_rgba(var(--third-color),_0.8)_0,_transparent_50%)_no-repeat]`,
            `[mix-blend-mode:var(--blending-value)] w-[var(--size)] h-[var(--size)] top-[calc(50%-var(--size)/2)] left-[calc(50%-var(--size)/2)] opacity-100`
          )}
        ></motion.div>
        <motion.div
          animate={{ x: ["0%", "50%", "0%"], y: ["0%", "-50%", "0%"], scale: [1, 0.9, 1] }}
          transition={{ duration: 35, repeat: Infinity, ease: "linear" }}
          className={cn(
            `absolute [background:radial-gradient(circle_at_center,_rgba(var(--fourth-color),_0.8)_0,_transparent_50%)_no-repeat]`,
            `[mix-blend-mode:var(--blending-value)] w-[var(--size)] h-[var(--size)] top-[calc(50%-var(--size)/2)] left-[calc(50%-var(--size)/2)] opacity-70`
          )}
        ></motion.div>

        {interactive && (
          <div
            ref={interactiveRef}
            onMouseMove={handleMouseMove}
            className={cn(
              `absolute [background:radial-gradient(circle_at_center,_rgba(var(--pointer-color),_0.8)_0,_transparent_50%)_no-repeat]`,
              `[mix-blend-mode:var(--blending-value)] w-full h-full -top-1/2 -left-1/2 opacity-70`
            )}
          ></div>
        )}
      </div>
    </div>
  );
};

--- FILE: frontend-web/registry/backgrounds/BeamsBackground.tsx ---

import React, { useEffect, useRef } from "react";
import { motion } from "framer-motion";
import { cn } from "../core/utils";

interface AnimatedGradientBackgroundProps {
    className?: string;
    children?: React.ReactNode;
    intensity?: "subtle" | "medium" | "strong";
}

interface Beam {
    x: number;
    y: number;
    width: number;
    length: number;
    angle: number;
    speed: number;
    opacity: number;
    hue: number;
    pulse: number;
    pulseSpeed: number;
}

function createBeam(width: number, height: number): Beam {
    const angle = -35 + Math.random() * 10;
    return {
        x: Math.random() * width * 1.5 - width * 0.25,
        y: Math.random() * height * 1.5 - height * 0.25,
        width: 30 + Math.random() * 60,
        length: height * 2.5,
        angle: angle,
        speed: 0.6 + Math.random() * 1.2,
        opacity: 0.12 + Math.random() * 0.16,
        hue: 190 + Math.random() * 70,
        pulse: Math.random() * Math.PI * 2,
        pulseSpeed: 0.02 + Math.random() * 0.03,
    };
}

export function BeamsBackground({
    className,
    children,
    intensity = "strong",
}: AnimatedGradientBackgroundProps) {
    const canvasRef = useRef<HTMLCanvasElement>(null);
    const beamsRef = useRef<Beam[]>([]);
    const animationFrameRef = useRef<number>(0);
    const MINIMUM_BEAMS = 20;

    const opacityMap = {
        subtle: 0.7,
        medium: 0.85,
        strong: 1,
    };

    useEffect(() => {
        const canvas = canvasRef.current;
        if (!canvas) return;

        const ctx = canvas.getContext("2d");
        if (!ctx) return;

        const updateCanvasSize = () => {
            const dpr = window.devicePixelRatio || 1;
            canvas.width = window.innerWidth * dpr;
            canvas.height = window.innerHeight * dpr;
            canvas.style.width = `${window.innerWidth}px`;
            canvas.style.height = `${window.innerHeight}px`;
            ctx.scale(dpr, dpr);

            const totalBeams = MINIMUM_BEAMS * 1.5;
            beamsRef.current = Array.from({ length: totalBeams }, () =>
                createBeam(canvas.width, canvas.height)
            );
        };

        updateCanvasSize();
        window.addEventListener("resize", updateCanvasSize);

        function resetBeam(beam: Beam, index: number, totalBeams: number) {
            if (!canvas) return beam;
            
            const column = index % 3;
            const spacing = canvas.width / 3;

            beam.y = canvas.height + 100;
            beam.x =
                column * spacing +
                spacing / 2 +
                (Math.random() - 0.5) * spacing * 0.5;
            beam.width = 100 + Math.random() * 100;
            beam.speed = 0.5 + Math.random() * 0.4;
            beam.hue = 190 + (index * 70) / totalBeams;
            beam.opacity = 0.2 + Math.random() * 0.1;
            return beam;
        }

        function drawBeam(ctx: CanvasRenderingContext2D, beam: Beam) {
            ctx.save();
            ctx.translate(beam.x, beam.y);
            ctx.rotate((beam.angle * Math.PI) / 180);

            // Calculate pulsing opacity
            const pulsingOpacity =
                beam.opacity *
                (0.8 + Math.sin(beam.pulse) * 0.2) *
                opacityMap[intensity];

            const gradient = ctx.createLinearGradient(0, 0, 0, beam.length);

            // Enhanced gradient with multiple color stops
            gradient.addColorStop(0, `hsla(${beam.hue}, 85%, 65%, 0)`);
            gradient.addColorStop(
                0.1,
                `hsla(${beam.hue}, 85%, 65%, ${pulsingOpacity * 0.5})`
            );
            gradient.addColorStop(
                0.4,
                `hsla(${beam.hue}, 85%, 65%, ${pulsingOpacity})`
            );
            gradient.addColorStop(
                0.6,
                `hsla(${beam.hue}, 85%, 65%, ${pulsingOpacity})`
            );
            gradient.addColorStop(
                0.9,
                `hsla(${beam.hue}, 85%, 65%, ${pulsingOpacity * 0.5})`
            );
            gradient.addColorStop(1, `hsla(${beam.hue}, 85%, 65%, 0)`);

            ctx.fillStyle = gradient;
            ctx.fillRect(-beam.width / 2, 0, beam.width, beam.length);
            ctx.restore();
        }

        function animate() {
            if (!canvas || !ctx) return;

            ctx.clearRect(0, 0, canvas.width, canvas.height);
            ctx.filter = "blur(35px)";

            const totalBeams = beamsRef.current.length;
            beamsRef.current.forEach((beam, index) => {
                beam.y -= beam.speed;
                beam.pulse += beam.pulseSpeed;

                // Reset beam when it goes off screen
                if (beam.y + beam.length < -100) {
                    resetBeam(beam, index, totalBeams);
                }

                drawBeam(ctx, beam);
            });

            animationFrameRef.current = requestAnimationFrame(animate);
        }

        animate();

        return () => {
            window.removeEventListener("resize", updateCanvasSize);
            if (animationFrameRef.current) {
                cancelAnimationFrame(animationFrameRef.current);
            }
        };
    }, [intensity]);

    return (
        <div
            className={cn(
                "relative min-h-screen w-full overflow-hidden bg-neutral-950",
                className
            )}
        >
            <canvas
                ref={canvasRef}
                className="absolute inset-0"
                style={{ filter: "blur(15px)" }}
            />

            <motion.div
                className="absolute inset-0 bg-neutral-950/5"
                animate={{
                    opacity: [0.05, 0.15, 0.05],
                }}
                transition={{
                    duration: 10,
                    ease: "easeInOut",
                    repeat: Number.POSITIVE_INFINITY,
                }}
                style={{
                    backdropFilter: "blur(50px)",
                }}
            />

            {children && (
                <div className="relative z-10 flex h-full w-full items-center justify-center">
                    {children}
                </div>
            )}
        </div>
    );
}

--- FILE: frontend-web/registry/backgrounds/BlueprintShader.tsx ---

import React, { useEffect, useRef } from "react";
import { cn } from "../core/utils";

/* ========= Fragment shader ========= */
const SHADER_SRC = `#version 300 es
precision highp float;

out vec4 fragColor;
in vec2 v_uv;

uniform vec3  iResolution;   // (w, h, dpr)
uniform float iTime;
uniform int   iFrame;
uniform vec4  iMouse;

const float GRID_SCALE   = 18.0; 
const float MAJOR_STEP   = 4.0; 
const float THIN_WIDTH   = 0.010; 
const float MAJOR_WIDTH  = 0.018; 
const float SCROLL_SPEED = 0.02;  

const float VIGNETTE_AMT = 0.28;  
const float MESH_AMT     = 0.85;  
const float NOISE_AMT    = 0.030; 
const float DITHER_DARK  = 0.010; 
const float DITHER_LIGHT = 0.004;

const float ASCII_AMT    = 0.23;  
const float ASCII_SCALE  = 26.0;  
const float ASCII_EVERY  = 2.0;  

mat2 rot(float a){ float c=cos(a), s=sin(a); return mat2(c,-s,s,c); }

// ordered dither 4x4
float bayer4(vec2 p){
  ivec2 ip = ivec2(int(mod(p.x,4.0)), int(mod(p.y,4.0)));
  int idx = ip.y*4 + ip.x;
  int m[16]; m[0]=0;m[1]=8;m[2]=2;m[3]=10;m[4]=12;m[5]=4;m[6]=14;m[7]=6;
  m[8]=3;m[9]=11;m[10]=1;m[11]=9;m[12]=15;m[13]=7;m[14]=13;m[15]=5;
  return float(m[idx]) / 15.0;
}

// hash + value noise
float hash21(vec2 p){ p=fract(p*vec2(123.34,456.21)); p+=dot(p,p+45.32); return fract(p.x*p.y); }
float vnoise(vec2 p){
  vec2 i=floor(p), f=fract(p);
  float a=hash21(i), b=hash21(i+vec2(1,0)), c=hash21(i+vec2(0,1)), d=hash21(i+vec2(1,1));
  vec2 u=f*f*(3.0-2.0*f);
  return mix(mix(a,b,u.x), mix(c,d,u.x), u.y);
}

float gridLineAA(vec2 uv, float scale, float width){
  vec2 g = abs(fract(uv*scale) - 0.5);
  float d = min(g.x, g.y);
  float aa = fwidth(d);
  return 1.0 - smoothstep(width, width + aa, d);
}
float majorGridAA(vec2 uv, float scale, float stepN, float width){
  float sMajor = max(1.0, scale/stepN);
  return gridLineAA(uv, sMajor, width);
}

// mesh-gradient
vec3 meshGradient(vec2 uv){
  vec2 p0=vec2(-0.70,-0.45), p1=vec2(0.75,-0.35), p2=vec2(-0.65,0.65), p3=vec2(0.80,0.55);
  vec3 c0=vec3(0.05,0.10,0.26);  // deep navy
  vec3 c1=vec3(0.08,0.16,0.36);  // royal navy
  vec3 c2=vec3(0.03,0.09,0.22);  // abyss
  vec3 c3=vec3(0.10,0.20,0.40);  // cobalt
  float e=2.0;
  float w0=pow(1.0/(0.2+distance(uv,p0)),e);
  float w1=pow(1.0/(0.2+distance(uv,p1)),e);
  float w2=pow(1.0/(0.2+distance(uv,p2)),e);
  float w3=pow(1.0/(0.2+distance(uv,p3)),e);
  float ws=w0+w1+w2+w3;
  return (c0*w0+c1*w1+c2*w2+c3*w3)/ws;
}

float sdLineX(vec2 p, float w){ return 1.0 - smoothstep(w, w+fwidth(p.y), abs(p.y)); }
float sdLineY(vec2 p, float w){ return 1.0 - smoothstep(w, w+fwidth(p.x), abs(p.x)); }
float sdDiag1(vec2 p, float w){ float d=abs(p.x+p.y)/sqrt(2.0); return 1.0 - smoothstep(w, w+fwidth(d), d); }
float sdDiag2(vec2 p, float w){ float d=abs(p.x-p.y)/sqrt(2.0); return 1.0 - smoothstep(w, w+fwidth(d), d); }
float sdDot (vec2 p, float r){ float d=length(p); return 1.0 - smoothstep(r, r+fwidth(d), d); }

float asciiGlyph(vec2 cellUV, float level){
  vec2 p=cellUV; float w=0.11, r=0.10;
  float g0=sdDot(p,r), g1=sdLineX(p,w), g2=sdLineY(p,w),
        g3=max(sdLineX(p,w),sdLineY(p,w)),
        g4=sdDiag1(p,w), g5=sdDiag2(p,w),
        g6=max(sdDiag1(p,w),sdDiag2(p,w)),
        g7=max(sdLineX(p,w), max(sdLineY(p,w), g6));
  float m=0.;
  m=mix(m,g0, smoothstep(0.00,0.12,level)*(1.0-step(level,0.12)));
  m=mix(m,g1, smoothstep(0.12,0.28,level)*(1.0-step(level,0.28)));
  m=mix(m,g2, smoothstep(0.28,0.44,level)*(1.0-step(level,0.44)));
  m=mix(m,g3, smoothstep(0.44,0.60,level)*(1.0-step(level,0.60)));
  m=mix(m,g4, smoothstep(0.60,0.72,level)*(1.0-step(level,0.72)));
  m=mix(m,g5, smoothstep(0.72,0.84,level)*(1.0-step(level,0.84)));
  m=mix(m,g6, smoothstep(0.84,0.94,level)*(1.0-step(level,0.94)));
  m=mix(m,g7, smoothstep(0.94,1.00,level));
  return clamp(m,0.0,1.0);
}

void mainImage(out vec4 fragColor, in vec2 fragCoord)
{
  vec2  R = iResolution.xy;
  float t = iTime;
  vec2 uv = (fragCoord - 0.5*R) / max(R.y, 1.0);

  vec3 baseDeep = vec3(0.03,0.06,0.12);
  vec3 baseTint = vec3(0.05,0.09,0.18);
  float vgrad   = smoothstep(-0.92, 0.55, -uv.y);
  vec3  bg      = mix(baseDeep, baseTint, vgrad);
  bg            = mix(bg, meshGradient(uv), MESH_AMT);
  float rad     = length(uv);
  float vig     = pow(1.0 - VIGNETTE_AMT * rad, 1.0);   
  bg           *= clamp(vig, 0.0, 1.0);

  vec2 scrollDir = normalize(vec2(1.0, -0.55));
  vec2 uvAnim    = uv + SCROLL_SPEED * t * scrollDir;

  float thin  = gridLineAA (uvAnim, GRID_SCALE, THIN_WIDTH);
  float major = majorGridAA(uvAnim, GRID_SCALE, MAJOR_STEP, MAJOR_WIDTH);

  vec3 lineThin  = vec3(0.58,0.66,0.95);
  vec3 lineMajor = vec3(0.78,0.84,1.00);

  vec3 col = bg
           + lineThin  * thin  * 0.25
           + lineMajor * major * 0.52;

  vec2 uMajor = uvAnim * (GRID_SCALE / MAJOR_STEP);
  vec2 idx    = floor(uMajor + 0.5);  
  float selX = 1.0 - step(0.001, abs(fract(idx.x / ASCII_EVERY)));
  float selY = 1.0 - step(0.001, abs(fract(idx.y / ASCII_EVERY)));
  float asciiLineSel = max(selX, selY);

  if (ASCII_AMT > 0.001) {
    vec2 aUV   = uv * ASCII_SCALE;
    vec2 cellF = fract(aUV) - 0.5;
    float lvl  = clamp(dot(col, vec3(0.2126,0.7152,0.0722)), 0.0, 1.0);
    float glyph = asciiGlyph(cellF, lvl);

    float nearMajor = major;                   
    float asciiMask = asciiLineSel * nearMajor;
    vec3 asciiColor = mix(vec3(0.50,0.70,1.0), meshGradient(uv), 0.25);

    col = mix(col, col + asciiColor * glyph * 0.30, ASCII_AMT * asciiMask);
  }

  float n = vnoise(fragCoord*0.6 + vec2(t*12.0, -t*9.0));
  col += (n - 0.5) * NOISE_AMT;

  // ---- ordered dither (Bayer 4x4) ----
  float luma = dot(col, vec3(0.2126,0.7152,0.0722));
  float dAmt = mix(DITHER_DARK, DITHER_LIGHT, luma);
  col += (bayer4(fragCoord) - 0.5) * dAmt;

  col = tanh(col);
  fragColor = vec4(col, 1.0);
}

void main(){ mainImage(fragColor, gl_FragCoord.xy); }
`;

/* ========= Vertex shader: fullscreen triangle ========= */
const VERT_SRC = `#version 300 es
precision highp float;
layout(location=0) in vec2 a_pos;
out vec2 v_uv;
void main(){
  v_uv = a_pos * 0.5 + 0.5;
  gl_Position = vec4(a_pos, 0.0, 1.0);
}
`;

/* ========= Utils ========= */
function safeCompile(gl: WebGL2RenderingContext, type: number, src: string) {
  const sh = gl.createShader(type)!;
  gl.shaderSource(sh, src);
  gl.compileShader(sh);
  const ok = gl.getShaderParameter(sh, gl.COMPILE_STATUS);
  const log = gl.getShaderInfoLog(sh) || "";
  return { shader: ok ? sh : null, log };
}

function safeLink(gl: WebGL2RenderingContext, vs: WebGLShader, fs: WebGLShader) {
  const prog = gl.createProgram()!;
  gl.attachShader(prog, vs);
  gl.attachShader(prog, fs);
  gl.linkProgram(prog);
  const ok = gl.getProgramParameter(prog, gl.LINK_STATUS);
  const log = gl.getProgramInfoLog(prog) || "";
  return { program: ok ? prog : null, log };
}

function drawError(gl: WebGL2RenderingContext, msg: string) {
  console.error(msg);
  gl.bindFramebuffer(gl.FRAMEBUFFER, null);
  gl.clearColor(0.2, 0.0, 0.0, 1);
  // eslint-disable-next-line no-bitwise
  gl.clear(gl.COLOR_BUFFER_BIT);
}

/* ========= Canvas runtime ========= */
function ShaderCanvas({
  fragSource,
  pixelRatio,
}: {
  fragSource: string;
  pixelRatio?: number;
}) {
  const canvasRef = useRef<HTMLCanvasElement | null>(null);
  const rafRef = useRef<number | null>(null);
  const startRef = useRef<number>(0);
  const frameRef = useRef<number>(0);
  const mouseRef = useRef({ x: 0, y: 0, l: 0, r: 0 });

  useEffect(() => {
    const canvas = canvasRef.current!;
    const gl = canvas.getContext("webgl2", { premultipliedAlpha: false });
    if (!gl) return;

    let disposed = false;
    let vao: WebGLVertexArrayObject | null = null;
    let vbo: WebGLBuffer | null = null;
    let program: WebGLProgram | null = null;
    let ro: ResizeObserver | null = null;
    let resizeScheduled = false;

    const onMove = (e: MouseEvent) => {
      const rect = canvas.getBoundingClientRect();
      const x = e.clientX - rect.left;
      const y = e.clientY - rect.top;
      mouseRef.current.x = Math.max(0, Math.min(x, rect.width));
      mouseRef.current.y = Math.max(0, Math.min(rect.height - y, rect.height));
    };
    const onDown = (e: MouseEvent) => { if (e.button === 0) mouseRef.current.l = 1; if (e.button === 2) mouseRef.current.r = 1; };
    const onUp   = (e: MouseEvent) => { if (e.button === 0) mouseRef.current.l = 0; if (e.button === 2) mouseRef.current.r = 0; };
    const onCtxMenu = (e: Event) => e.preventDefault();
    const onContextLost = (ev: Event) => { ev.preventDefault(); if (rafRef.current) cancelAnimationFrame(rafRef.current); rafRef.current = null; };
    const onContextRestored = () => { scheduleSize(); startRef.current = performance.now(); frameRef.current = 0; if (!rafRef.current) rafRef.current = requestAnimationFrame(tick); };

    const getDpr = () => {
      const sys = (window.devicePixelRatio || 1);
      return Math.max(1, Math.min(2, pixelRatio ?? sys));
    };

    function applySize() {
      resizeScheduled = false;
      if (disposed) return;
      const dpr = getDpr();
      // eslint-disable-next-line no-bitwise
      const cssW = Math.max(1, (canvas.clientWidth | 0));
      // eslint-disable-next-line no-bitwise
      const cssH = Math.max(1, (canvas.clientHeight | 0));
      const w = Math.max(1, Math.floor(cssW * dpr));
      const h = Math.max(1, Math.floor(cssH * dpr));
      if (canvas.width !== w || canvas.height !== h) {
        canvas.width = w; canvas.height = h;
        gl!.viewport(0, 0, w, h);
      }
    }
    function scheduleSize() {
      if (resizeScheduled) return;
      resizeScheduled = true;
      requestAnimationFrame(applySize);
    }

    vao = gl.createVertexArray();
    vbo = gl.createBuffer();
    if (!vao || !vbo) { drawError(gl, "Failed to create VAO/VBO"); return cleanup; }
    gl.bindVertexArray(vao);
    gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 3, -1, -1, 3]), gl.STATIC_DRAW);
    gl.enableVertexAttribArray(0);
    gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);

    const { shader: vs, log: vsLog } = safeCompile(gl, gl.VERTEX_SHADER, VERT_SRC);
    if (!vs) { drawError(gl, `Vertex compile error:\n${vsLog}`); return cleanup; }
    const { shader: fs, log: fsLog } = safeCompile(gl, gl.FRAGMENT_SHADER, fragSource);
    if (!fs) { drawError(gl, `Fragment compile error:\n${fsLog}`); gl.deleteShader(vs); return cleanup; }
    const linked = safeLink(gl, vs, fs);
    gl.deleteShader(vs); gl.deleteShader(fs);
    if (!linked.program) { drawError(gl, `Program link error:\n${linked.log}`); return cleanup; }
    program = linked.program;

    const uResolution = gl.getUniformLocation(program, "iResolution");
    const uTime = gl.getUniformLocation(program, "iTime");
    const uFrame = gl.getUniformLocation(program, "iFrame");
    const uMouse = gl.getUniformLocation(program, "iMouse");

    ro = new ResizeObserver(scheduleSize);
    ro.observe(canvas);
    scheduleSize();

    canvas.addEventListener("mousemove", onMove);
    canvas.addEventListener("mousedown", onDown);
    canvas.addEventListener("mouseup", onUp);
    canvas.addEventListener("contextmenu", onCtxMenu);
    canvas.addEventListener("webglcontextlost", onContextLost);
    canvas.addEventListener("webglcontextrestored", onContextRestored);

    startRef.current = performance.now();
    frameRef.current = 0;

    function tick(now: number) {
      if (disposed) return;
      if (gl!.isContextLost()) { rafRef.current = requestAnimationFrame(tick); return; }

      const t = (now - startRef.current) / 1000;
      frameRef.current += 1;

      try {
        gl!.useProgram(program!);
        if (resizeScheduled) applySize();

        const dpr = getDpr();
        const w = canvas.width, h = canvas.height;

        if (uResolution) gl!.uniform3f(uResolution, w, h, dpr);
        if (uTime) gl!.uniform1f(uTime, t);
        if (uFrame) gl!.uniform1i(uFrame, frameRef.current);
        if (uMouse) {
          const m = mouseRef.current;
          gl!.uniform4f(uMouse, m.x * dpr, m.y * dpr, m.l, m.r);
        }

        gl!.bindVertexArray(vao);
        gl!.drawArrays(gl!.TRIANGLES, 0, 3);
      } catch (err) {
        drawError(gl!, (err as Error)?.message ?? String(err));
      }

      rafRef.current = requestAnimationFrame(tick);
    }
    rafRef.current = requestAnimationFrame(tick);

    function cleanup() {
      disposed = true;
      if (rafRef.current) { cancelAnimationFrame(rafRef.current); rafRef.current = null; }

      canvas.removeEventListener("mousemove", onMove);
      canvas.removeEventListener("mousedown", onDown);
      canvas.removeEventListener("mouseup", onUp);
      canvas.removeEventListener("contextmenu", onCtxMenu);
      canvas.removeEventListener("webglcontextlost", onContextLost);
      canvas.removeEventListener("webglcontextrestored", onContextRestored);

      if (ro) { try { ro.disconnect(); } catch {} ro = null; }
      try { if (vbo) gl!.deleteBuffer(vbo); } catch {}
      try { if (vao) gl!.deleteVertexArray(vao); } catch {}
      try { if (program) gl!.deleteProgram(program); } catch {}
    }

    return cleanup;
  }, [fragSource, pixelRatio]);

  return (
    <div style={{ position: "absolute", inset: 0, pointerEvents: "none" }}>
      <canvas ref={canvasRef} style={{ width: "100%", height: "100%", display: "block" }} />
    </div>
  );
}

export interface BlueprintShaderProps {
  className?: string;
  children?: React.ReactNode;
  pixelRatio?: number;
}

export function BlueprintShader({ className, children, pixelRatio }: BlueprintShaderProps) {
  return (
    <div className={cn("relative w-full h-full overflow-hidden bg-[#03060c]", className)}>
      <ShaderCanvas fragSource={SHADER_SRC} pixelRatio={pixelRatio} />
      {children && (
        <div className="relative z-10 w-full h-full flex items-center justify-center">
          {children}
        </div>
      )}
    </div>
  );
}

--- FILE: frontend-web/registry/backgrounds/Dark Veil.tsx ---

import { useRef, useEffect } from 'react';
import { Renderer, Program, Mesh, Triangle, Vec2 } from 'ogl';

const vertex = `
attribute vec2 position;
void main(){gl_Position=vec4(position,0.0,1.0);}
`;

const fragment = `
#ifdef GL_ES
precision lowp float;
#endif
uniform vec2 uResolution;
uniform float uTime;
uniform float uHueShift;
uniform float uNoise;
uniform float uScan;
uniform float uScanFreq;
uniform float uWarp;
#define iTime uTime
#define iResolution uResolution

vec4 buf[8];
float rand(vec2 c){return fract(sin(dot(c,vec2(12.9898,78.233)))*43758.5453);}

mat3 rgb2yiq=mat3(0.299,0.587,0.114,0.596,-0.274,-0.322,0.211,-0.523,0.312);
mat3 yiq2rgb=mat3(1.0,0.956,0.621,1.0,-0.272,-0.647,1.0,-1.106,1.703);

vec3 hueShiftRGB(vec3 col,float deg){
    vec3 yiq=rgb2yiq*col;
    float rad=radians(deg);
    float cosh=cos(rad),sinh=sin(rad);
    vec3 yiqShift=vec3(yiq.x,yiq.y*cosh-yiq.z*sinh,yiq.y*sinh+yiq.z*cosh);
    return clamp(yiq2rgb*yiqShift,0.0,1.0);
}

vec4 sigmoid(vec4 x){return 1./(1.+exp(-x));}

vec4 cppn_fn(vec2 coordinate,float in0,float in1,float in2){
    buf[6]=vec4(coordinate.x,coordinate.y,0.3948333106474662+in0,0.36+in1);
    buf[7]=vec4(0.14+in2,sqrt(coordinate.x*coordinate.x+coordinate.y*coordinate.y),0.,0.);
    buf[0]=mat4(vec4(6.5404263,-3.6126034,0.7590882,-1.13613),vec4(2.4582713,3.1660357,1.2219609,0.06276096),vec4(-5.478085,-6.159632,1.8701609,-4.7742867),vec4(6.039214,-5.542865,-0.90925294,3.251348))*buf[6]+mat4(vec4(0.8473259,-5.722911,3.975766,1.6522468),vec4(-0.24321538,0.5839259,-1.7661959,-5.350116),vec4(0.,0.,0.,0.),vec4(0.,0.,0.,0.))*buf[7]+vec4(0.21808943,1.1243913,-1.7969975,5.0294676);
    buf[1]=mat4(vec4(-3.3522482,-6.0612736,0.55641043,-4.4719114),vec4(0.8631464,1.7432913,5.643898,1.6106541),vec4(2.4941394,-3.5012043,1.7184316,6.357333),vec4(3.310376,8.209261,1.1355612,-1.165539))*buf[6]+mat4(vec4(5.24046,-13.034365,0.009859298,15.870829),vec4(2.987511,3.129433,-0.89023495,-1.6822904),vec4(0.,0.,0.,0.),vec4(0.,0.,0.,0.))*buf[7]+vec4(-5.9457836,-6.573602,-0.8812491,1.5436668);
    buf[0]=sigmoid(buf[0]);buf[1]=sigmoid(buf[1]);
    buf[2]=mat4(vec4(-15.219568,8.095543,-2.429353,-1.9381982),vec4(-5.951362,4.3115187,2.6393783,1.274315),vec4(-7.3145227,6.7297835,5.2473326,5.9411426),vec4(5.0796127,8.979051,-1.7278991,-1.158976))*buf[6]+mat4(vec4(-11.967154,-11.608155,6.1486754,11.237008),vec4(2.124141,-6.263192,-1.7050359,-0.7021966),vec4(0.,0.,0.,0.),vec4(0.,0.,0.,0.))*buf[7]+vec4(-4.17164,-3.2281182,-4.576417,-3.6401186);
    buf[3]=mat4(vec4(3.1832156,-13.738922,1.879223,3.233465),vec4(0.64300746,12.768129,1.9141049,0.50990224),vec4(-0.049295485,4.4807224,1.4733979,1.801449),vec4(5.0039253,13.000481,3.3991797,-4.5561905))*buf[6]+mat4(vec4(-0.1285731,7.720628,-3.1425676,4.742367),vec4(0.6393625,3.714393,-0.8108378,-0.39174938),vec4(0.,0.,0.,0.),vec4(0.,0.,0.,0.))*buf[7]+vec4(-1.1811101,-21.621881,0.7851888,1.2329718);
    buf[2]=sigmoid(buf[2]);buf[3]=sigmoid(buf[3]);
    buf[4]=mat4(vec4(5.214916,-7.183024,2.7228765,2.6592617),vec4(-5.601878,-25.3591,4.067988,0.4602802),vec4(-10.57759,24.286327,21.102104,37.546658),vec4(4.3024497,-1.9625226,2.3458803,-1.372816))*buf[0]+mat4(vec4(-17.6526,-10.507558,2.2587414,12.462782),vec4(6.265566,-502.75443,-12.642513,0.9112289),vec4(-10.983244,20.741234,-9.701768,-0.7635988),vec4(5.383626,1.4819539,-4.1911616,-4.8444734))*buf[1]+mat4(vec4(12.785233,-16.345072,-0.39901125,1.7955981),vec4(-30.48365,-1.8345358,1.4542528,-1.1118771),vec4(19.872723,-7.337935,-42.941723,-98.52709),vec4(8.337645,-2.7312303,-2.2927687,-36.142323))*buf[2]+mat4(vec4(-16.298317,3.5471997,-0.44300047,-9.444417),vec4(57.5077,-35.609753,16.163465,-4.1534753),vec4(-0.07470326,-3.8656476,-7.0901804,3.1523974),vec4(-12.559385,-7.077619,1.490437,-0.8211543))*buf[3]+vec4(-7.67914,15.927437,1.3207729,-1.6686112);
    buf[5]=mat4(vec4(-1.4109162,-0.372762,-3.770383,-21.367174),vec4(-6.2103205,-9.35908,0.92529047,8.82561),vec4(11.460242,-22.348068,13.625772,-18.693201),vec4(-0.3429052,-3.9905605,-2.4626114,-0.45033523))*buf[0]+mat4(vec4(7.3481627,-4.3661838,-6.3037653,-3.868115),vec4(1.5462853,6.5488915,1.9701879,-0.58291394),vec4(6.5858274,-2.2180402,3.7127688,-1.3730392),vec4(-5.7973905,10.134961,-2.3395722,-5.965605))*buf[1]+mat4(vec4(-2.5132585,-6.6685553,-1.4029363,-0.16285264),vec4(-0.37908727,0.53738135,4.389061,-1.3024765),vec4(-0.70647055,2.0111287,-5.1659346,-3.728635),vec4(-13.562562,10.487719,-0.9173751,-2.6487076))*buf[2]+mat4(vec4(-8.645013,6.5546675,-6.3944063,-5.5933375),vec4(-0.57783127,-1.077275,36.91025,5.736769),vec4(14.283112,3.7146652,7.1452246,-4.5958776),vec4(2.7192075,3.6021907,-4.366337,-2.3653464))*buf[3]+vec4(-5.9000807,-4.329569,1.2427121,8.59503);
    buf[4]=sigmoid(buf[4]);buf[5]=sigmoid(buf[5]);
    buf[6]=mat4(vec4(-1.61102,0.7970257,1.4675229,0.20917463),vec4(-28.793737,-7.1390953,1.5025433,4.656581),vec4(-10.94861,39.66238,0.74318546,-10.095605),vec4(-0.7229728,-1.5483948,0.7301322,2.1687684))*buf[0]+mat4(vec4(3.2547753,21.489103,-1.0194173,-3.3100595),vec4(-3.7316632,-3.3792162,-7.223193,-0.23685838),vec4(13.1804495,0.7916005,5.338587,5.687114),vec4(-4.167605,-17.798311,-6.815736,-1.6451967))*buf[1]+mat4(vec4(0.604885,-7.800309,-7.213122,-2.741014),vec4(-3.522382,-0.12359311,-0.5258442,0.43852118),vec4(9.6752825,-22.853785,2.062431,0.099892326),vec4(-4.3196306,-17.730087,2.5184598,5.30267))*buf[2]+mat4(vec4(-6.545563,-15.790176,-6.0438633,-5.415399),vec4(-43.591583,28.551912,-16.00161,18.84728),vec4(4.212382,8.394307,3.0958717,8.657522),vec4(-5.0237565,-4.450633,-4.4768,-5.5010443))*buf[3]+mat4(vec4(1.6985557,-67.05806,6.897715,1.9004834),vec4(1.8680354,2.3915145,2.5231109,4.081538),vec4(11.158006,1.7294737,2.0738268,7.386411),vec4(-4.256034,-306.24686,8.258898,-17.132736))*buf[4]+mat4(vec4(1.6889864,-4.5852966,3.8534803,-6.3482175),vec4(1.3543309,-1.2640043,9.932754,2.9079645),vec4(-5.2770967,0.07150358,-0.13962056,3.3269649),vec4(28.34703,-4.918278,6.1044083,4.085355))*buf[5]+vec4(6.6818056,12.522166,-3.7075126,-4.104386);
    buf[7]=mat4(vec4(-8.265602,-4.7027016,5.098234,0.7509808),vec4(8.6507845,-17.15949,16.51939,-8.884479),vec4(-4.036479,-2.3946867,-2.6055532,-1.9866527),vec4(-2.2167742,-1.8135649,-5.9759874,4.8846445))*buf[0]+mat4(vec4(6.7790847,3.5076547,-2.8191125,-2.7028968),vec4(-5.743024,-0.27844876,1.4958696,-5.0517144),vec4(13.122226,15.735168,-2.9397483,-4.101023),vec4(-14.375265,-5.030483,-6.2599335,2.9848232))*buf[1]+mat4(vec4(4.0950394,-0.94011575,-5.674733,4.755022),vec4(4.3809423,4.8310084,1.7425908,-3.437416),vec4(2.117492,0.16342592,-104.56341,16.949184),vec4(-5.22543,-2.994248,3.8350096,-1.9364246))*buf[2]+mat4(vec4(-5.900337,1.7946124,-13.604192,-3.8060522),vec4(6.6583457,31.911177,25.164474,91.81147),vec4(11.840538,4.1503043,-0.7314397,6.768467),vec4(-6.3967767,4.034772,6.1714606,-0.32874924))*buf[3]+mat4(vec4(3.4992442,-196.91893,-8.923708,2.8142626),vec4(3.4806502,-3.1846354,5.1725626,5.1804223),vec4(-2.4009497,15.585794,1.2863957,2.0252278),vec4(-71.25271,-62.441242,-8.138444,0.50670296))*buf[4]+mat4(vec4(-12.291733,-11.176166,-7.3474145,4.390294),vec4(10.805477,5.6337385,-0.9385842,-4.7348723),vec4(-12.869276,-7.039391,5.3029537,7.5436664),vec4(1.4593618,8.91898,3.5101583,5.840625))*buf[5]+vec4(2.2415268,-6.705987,-0.98861027,-2.117676);
    buf[6]=sigmoid(buf[6]);buf[7]=sigmoid(buf[7]);
    buf[0]=mat4(vec4(1.6794263,1.3817469,2.9625452,0.),vec4(-1.8834411,-1.4806935,-3.5924516,0.),vec4(-1.3279216,-1.0918057,-2.3124623,0.),vec4(0.2662234,0.23235129,0.44178495,0.))*buf[0]+mat4(vec4(-0.6299101,-0.5945583,-0.9125601,0.),vec4(0.17828953,0.18300213,0.18182953,0.),vec4(-2.96544,-2.5819945,-4.9001055,0.),vec4(1.4195864,1.1868085,2.5176322,0.))*buf[1]+mat4(vec4(-1.2584374,-1.0552157,-2.1688404,0.),vec4(-0.7200217,-0.52666044,-1.438251,0.),vec4(0.15345335,0.15196142,0.272854,0.),vec4(0.945728,0.8861938,1.2766753,0.))*buf[2]+mat4(vec4(-2.4218085,-1.968602,-4.35166,0.),vec4(-22.683098,-18.0544,-41.954372,0.),vec4(0.63792,0.5470648,1.1078634,0.),vec4(-1.5489894,-1.3075932,-2.6444845,0.))*buf[3]+mat4(vec4(-0.49252132,-0.39877754,-0.91366625,0.),vec4(0.95609266,0.7923952,1.640221,0.),vec4(0.30616966,0.15693925,0.8639857,0.),vec4(1.1825981,0.94504964,2.176963,0.))*buf[4]+mat4(vec4(0.35446745,0.3293795,0.59547555,0.),vec4(-0.58784515,-0.48177817,-1.0614829,0.),vec4(2.5271258,1.9991658,4.6846647,0.),vec4(0.13042648,0.08864098,0.30187556,0.))*buf[5]+mat4(vec4(-1.7718065,-1.4033192,-3.3355875,0.),vec4(3.1664357,2.638297,5.378702,0.),vec4(-3.1724713,-2.6107926,-5.549295,0.),vec4(-2.851368,-2.249092,-5.3013067,0.))*buf[6]+mat4(vec4(1.5203838,1.2212278,2.8404984,0.),vec4(1.5210563,1.2651345,2.683903,0.),vec4(2.9789467,2.4364579,5.2347264,0.),vec4(2.2270417,1.8825914,3.8028636,0.))*buf[7]+vec4(-1.5468478,-3.6171484,0.24762098,0.);
    buf[0]=sigmoid(buf[0]);
    return vec4(buf[0].x,buf[0].y,buf[0].z,1.);
}

void mainImage(out vec4 fragColor,in vec2 fragCoord){
    vec2 uv=fragCoord/uResolution.xy*2.-1.;
    uv.y*=-1.;
    uv+=uWarp*vec2(sin(uv.y*6.283+uTime*0.5),cos(uv.x*6.283+uTime*0.5))*0.05;
    fragColor=cppn_fn(uv,0.1*sin(0.3*uTime),0.1*sin(0.69*uTime),0.1*sin(0.44*uTime));
}

void main(){
    vec4 col;mainImage(col,gl_FragCoord.xy);
    col.rgb=hueShiftRGB(col.rgb,uHueShift);
    float scanline_val=sin(gl_FragCoord.y*uScanFreq)*0.5+0.5;
    col.rgb*=1.-(scanline_val*scanline_val)*uScan;
    col.rgb+=(rand(gl_FragCoord.xy+uTime)-0.5)*uNoise;
    gl_FragColor=vec4(clamp(col.rgb,0.0,1.0),1.0);
}
`;

type Props = {
  hueShift?: number;
  noiseIntensity?: number;
  scanlineIntensity?: number;
  speed?: number;
  scanlineFrequency?: number;
  warpAmount?: number;
  resolutionScale?: number;
};

export default function DarkVeil({
  hueShift = 0,
  noiseIntensity = 0,
  scanlineIntensity = 0,
  speed = 0.5,
  scanlineFrequency = 0,
  warpAmount = 0,
  resolutionScale = 1
}: Props) {
  const ref = useRef<HTMLCanvasElement>(null);
  useEffect(() => {
    const canvas = ref.current as HTMLCanvasElement;
    const parent = canvas.parentElement as HTMLElement;

    const renderer = new Renderer({
      dpr: Math.min(window.devicePixelRatio, 2),
      canvas
    });

    const gl = renderer.gl;
    const geometry = new Triangle(gl);

    const program = new Program(gl, {
      vertex,
      fragment,
      uniforms: {
        uTime: { value: 0 },
        uResolution: { value: new Vec2() },
        uHueShift: { value: hueShift },
        uNoise: { value: noiseIntensity },
        uScan: { value: scanlineIntensity },
        uScanFreq: { value: scanlineFrequency },
        uWarp: { value: warpAmount }
      }
    });

    const mesh = new Mesh(gl, { geometry, program });

    const resize = () => {
      const w = parent.clientWidth,
        h = parent.clientHeight;
      renderer.setSize(w * resolutionScale, h * resolutionScale);
      program.uniforms.uResolution.value.set(w, h);
    };

    window.addEventListener('resize', resize);
    resize();

    const start = performance.now();
    let frame = 0;

    const loop = () => {
      program.uniforms.uTime.value = ((performance.now() - start) / 1000) * speed;
      program.uniforms.uHueShift.value = hueShift;
      program.uniforms.uNoise.value = noiseIntensity;
      program.uniforms.uScan.value = scanlineIntensity;
      program.uniforms.uScanFreq.value = scanlineFrequency;
      program.uniforms.uWarp.value = warpAmount;
      renderer.render({ scene: mesh });
      frame = requestAnimationFrame(loop);
    };

    loop();

    return () => {
      cancelAnimationFrame(frame);
      window.removeEventListener('resize', resize);
    };
  }, [hueShift, noiseIntensity, scanlineIntensity, speed, scanlineFrequency, warpAmount, resolutionScale]);
  return <canvas ref={ref} className="w-full h-full block" />;
}


--- FILE: frontend-web/registry/backgrounds/DottedSurface.tsx ---

import React, { useEffect, useRef, useState } from 'react';
import * as THREE from 'three';
import { cn } from '../core/utils';

export type DottedSurfaceProps = Omit<React.ComponentProps<'div'>, 'ref'>;

export function DottedSurface({ className, ...props }: DottedSurfaceProps) {
	const containerRef = useRef<HTMLDivElement>(null);
	const [isDark, setIsDark] = useState(false);

	// Detect Tailwind dark mode class on the <html> element
	useEffect(() => {
		const htmlEl = document.documentElement;
		const checkTheme = () => setIsDark(htmlEl.classList.contains('dark'));
		checkTheme(); // Initial check

		const observer = new MutationObserver(checkTheme);
		observer.observe(htmlEl, { attributes: true, attributeFilter: ['class'] });

		return () => observer.disconnect();
	}, []);

	useEffect(() => {
		if (!containerRef.current) return;
		const container = containerRef.current;

		const SEPARATION = 150;
		const AMOUNTX = 40;
		const AMOUNTY = 60;

		const scene = new THREE.Scene();
		scene.fog = new THREE.Fog(0xffffff, 2000, 10000);

		const camera = new THREE.PerspectiveCamera(
			60,
			container.clientWidth / container.clientHeight,
			1,
			10000,
		);
		camera.position.set(0, 355, 1220);

		const renderer = new THREE.WebGLRenderer({
			alpha: true,
			antialias: true,
		});
		renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
		renderer.setSize(container.clientWidth, container.clientHeight);
		renderer.setClearColor(scene.fog.color, 0);

		container.appendChild(renderer.domElement);

		const positions: number[] = [];
		const colors: number[] = [];
		const geometry = new THREE.BufferGeometry();

		for (let ix = 0; ix < AMOUNTX; ix++) {
			for (let iy = 0; iy < AMOUNTY; iy++) {
				const x = ix * SEPARATION - (AMOUNTX * SEPARATION) / 2;
				const y = 0; 
				const z = iy * SEPARATION - (AMOUNTY * SEPARATION) / 2;

				positions.push(x, y, z);
				if (isDark) {
					colors.push(0.8, 0.8, 0.8); // 200/255
				} else {
					colors.push(0.1, 0.1, 0.1); 
				}
			}
		}

		geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
		geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));

		const material = new THREE.PointsMaterial({
			size: 8,
			vertexColors: true,
			transparent: true,
			opacity: 0.8,
			sizeAttenuation: true,
		});

		const points = new THREE.Points(geometry, material);
		scene.add(points);

		let count = 0;
		let animationId: number;

		const animate = () => {
			animationId = requestAnimationFrame(animate);

			const positionAttribute = geometry.attributes.position;
			const posArray = positionAttribute.array as Float32Array;

			let i = 0;
			for (let ix = 0; ix < AMOUNTX; ix++) {
				for (let iy = 0; iy < AMOUNTY; iy++) {
					const index = i * 3;
					posArray[index + 1] =
						Math.sin((ix + count) * 0.3) * 50 +
						Math.sin((iy + count) * 0.5) * 50;
					i++;
				}
			}

			positionAttribute.needsUpdate = true;
			renderer.render(scene, camera);
			count += 0.1;
		};

		const handleResize = () => {
			if (!container) return;
			camera.aspect = container.clientWidth / container.clientHeight;
			camera.updateProjectionMatrix();
			renderer.setSize(container.clientWidth, container.clientHeight);
		};

		const resizeObserver = new ResizeObserver(handleResize);
		resizeObserver.observe(container);

		animate();

		return () => {
			resizeObserver.disconnect();
			cancelAnimationFrame(animationId);

			scene.traverse((object) => {
				if (object instanceof THREE.Points) {
					object.geometry.dispose();
					if (Array.isArray(object.material)) {
						object.material.forEach((m) => m.dispose());
					} else {
						object.material.dispose();
					}
				}
			});

			renderer.dispose();
			if (container && renderer.domElement && container.contains(renderer.domElement)) {
				container.removeChild(renderer.domElement);
			}
		};
	}, [isDark]);

	return (
		<div
			ref={containerRef}
			className={cn('pointer-events-none absolute inset-0 z-[-1] overflow-hidden', className)}
			{...props}
		/>
	);
}

--- FILE: frontend-web/registry/backgrounds/Entropy.tsx ---

import React, { useEffect, useRef } from 'react';
import { cn } from '../core/utils';

export interface EntropyProps {
  className?: string;
  size?: number;
}

export function Entropy({ className = "", size = 400 }: EntropyProps) {
  const canvasRef = useRef<HTMLCanvasElement>(null);

  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    
    const ctx = canvas.getContext('2d');
    if (!ctx) return;

    // Basic setup
    const dpr = window.devicePixelRatio || 1;
    canvas.width = size * dpr;
    canvas.height = size * dpr;
    canvas.style.width = `${size}px`;
    canvas.style.height = `${size}px`;
    ctx.scale(dpr, dpr);

    // Use black theme colors
    const particleColor = '#ffffff';

    class Particle {
      x: number;
      y: number;
      size: number;
      order: boolean;
      velocity: { x: number; y: number };
      originalX: number;
      originalY: number;
      influence: number;
      neighbors: Particle[];

      constructor(x: number, y: number, order: boolean) {
        this.x = x;
        this.y = y;
        this.originalX = x;
        this.originalY = y;
        this.size = 2;
        this.order = order;
        this.velocity = {
          x: (Math.random() - 0.5) * 2,
          y: (Math.random() - 0.5) * 2
        };
        this.influence = 0;
        this.neighbors = [];
      }

      update() {
        if (this.order) {
          // Ordered particles affected by chaos
          const dx = this.originalX - this.x;
          const dy = this.originalY - this.y;

          // Calculate influence from chaotic particles
          const chaosInfluence = { x: 0, y: 0 };
          this.neighbors.forEach(neighbor => {
            if (!neighbor.order) {
              const distance = Math.hypot(this.x - neighbor.x, this.y - neighbor.y);
              const strength = Math.max(0, 1 - distance / 100);
              chaosInfluence.x += (neighbor.velocity.x * strength);
              chaosInfluence.y += (neighbor.velocity.y * strength);
              this.influence = Math.max(this.influence, strength);
            }
          });

          // Mix ordered movement and chaos influence
          this.x += dx * 0.05 * (1 - this.influence) + chaosInfluence.x * this.influence;
          this.y += dy * 0.05 * (1 - this.influence) + chaosInfluence.y * this.influence;

          // Influence gradually weakens
          this.influence *= 0.99;
        } else {
          // Chaotic movement
          this.velocity.x += (Math.random() - 0.5) * 0.5;
          this.velocity.y += (Math.random() - 0.5) * 0.5;
          this.velocity.x *= 0.95;
          this.velocity.y *= 0.95;
          this.x += this.velocity.x;
          this.y += this.velocity.y;

          // Boundary check
          if (this.x < size / 2 || this.x > size) this.velocity.x *= -1;
          if (this.y < 0 || this.y > size) this.velocity.y *= -1;
          this.x = Math.max(size / 2, Math.min(size, this.x));
          this.y = Math.max(0, Math.min(size, this.y));
        }
      }

      draw(ctx: CanvasRenderingContext2D) {
        const alpha = this.order ?
          0.8 - this.influence * 0.5 :
          0.8;
        ctx.fillStyle = `${particleColor}${Math.round(alpha * 255).toString(16).padStart(2, '0')}`;
        ctx.beginPath();
        ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
        ctx.fill();
      }
    }

    // Create particle grid
    const particles: Particle[] = [];
    const gridSize = 25;
    const spacing = size / gridSize;

    for (let i = 0; i < gridSize; i++) {
      for (let j = 0; j < gridSize; j++) {
        const x = spacing * i + spacing / 2;
        const y = spacing * j + spacing / 2;
        const order = x < size / 2;
        particles.push(new Particle(x, y, order));
      }
    }

    // Update neighbor relationships
    function updateNeighbors() {
      particles.forEach(particle => {
        particle.neighbors = particles.filter(other => {
          if (other === particle) return false;
          const distance = Math.hypot(particle.x - other.x, particle.y - other.y);
          return distance < 100;
        });
      });
    }

    let time = 0;
    let animationId: number;
    
    function animate() {
      ctx.clearRect(0, 0, size, size);

      // Update neighbor relationships periodically
      if (time % 30 === 0) {
        updateNeighbors();
      }

      // Update and draw all particles
      particles.forEach(particle => {
        particle.update();
        particle.draw(ctx);

        // Draw connecting lines
        particle.neighbors.forEach(neighbor => {
          const distance = Math.hypot(particle.x - neighbor.x, particle.y - neighbor.y);
          if (distance < 50) {
            const alpha = 0.2 * (1 - distance / 50);
            ctx.strokeStyle = `${particleColor}${Math.round(alpha * 255).toString(16).padStart(2, '0')}`;
            ctx.beginPath();
            ctx.moveTo(particle.x, particle.y);
            ctx.lineTo(neighbor.x, neighbor.y);
            ctx.stroke();
          }
        });
      });

      // Add separator line
      ctx.strokeStyle = `${particleColor}4D`;
      ctx.lineWidth = 0.5;
      ctx.beginPath();
      ctx.moveTo(size / 2, 0);
      ctx.lineTo(size / 2, size);
      ctx.stroke();

      ctx.font = '12px monospace';
      ctx.fillStyle = '#ffffff';
      ctx.textAlign = 'center';

      time++;
      animationId = requestAnimationFrame(animate);
    }

    animate();

    return () => {
      if (animationId) {
        cancelAnimationFrame(animationId);
      }
    };
  }, [size]);

  return (
    <div className={cn("relative bg-black", className)} style={{ width: size, height: size }}>
      <canvas
        ref={canvasRef}
        className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2"
      />
    </div>
  );
}

--- FILE: frontend-web/registry/backgrounds/EtherealShadow.tsx ---

import React, { useRef, useId, useEffect, CSSProperties } from 'react';
import { animate, useMotionValue, AnimationPlaybackControls } from 'framer-motion';

export interface ResponsiveImage {
    src: string;
    alt?: string;
    srcSet?: string;
}

export interface AnimationConfig {
    preview?: boolean;
    scale: number;
    speed: number;
}

export interface NoiseConfig {
    opacity: number;
    scale: number;
}

export interface ShadowOverlayProps {
    type?: 'preset' | 'custom';
    presetIndex?: number;
    customImage?: ResponsiveImage;
    sizing?: 'fill' | 'stretch';
    color?: string;
    animation?: AnimationConfig;
    noise?: NoiseConfig;
    style?: CSSProperties;
    className?: string;
    children?: React.ReactNode;
}

function mapRange(
    value: number,
    fromLow: number,
    fromHigh: number,
    toLow: number,
    toHigh: number
): number {
    if (fromLow === fromHigh) {
        return toLow;
    }
    const percentage = (value - fromLow) / (fromHigh - fromLow);
    return toLow + percentage * (toHigh - toLow);
}

const useInstanceId = (): string => {
    const id = useId();
    const cleanId = id.replace(/:/g, "");
    return `shadowoverlay-${cleanId}`;
};

export function EtherealShadow({
    sizing = 'fill',
    color = 'rgba(128, 128, 128, 1)',
    animation = { scale: 50, speed: 50 },
    noise,
    style,
    className,
    children
}: ShadowOverlayProps) {
    const id = useInstanceId();
    const animationEnabled = animation && animation.scale > 0;
    const feColorMatrixRef = useRef<SVGFEColorMatrixElement>(null);
    const hueRotateMotionValue = useMotionValue(180);
    const hueRotateAnimation = useRef<AnimationPlaybackControls | null>(null);

    const displacementScale = animation ? mapRange(animation.scale, 1, 100, 20, 100) : 0;
    const animationDuration = animation ? mapRange(animation.speed, 1, 100, 1000, 50) : 1;

    useEffect(() => {
        if (feColorMatrixRef.current && animationEnabled) {
            if (hueRotateAnimation.current) {
                hueRotateAnimation.current.stop();
            }
            hueRotateMotionValue.set(0);
            hueRotateAnimation.current = animate(hueRotateMotionValue, 360, {
                duration: animationDuration / 25,
                repeat: Infinity,
                repeatType: "loop",
                repeatDelay: 0,
                ease: "linear",
                delay: 0,
                onUpdate: (value: number) => {
                    if (feColorMatrixRef.current) {
                        feColorMatrixRef.current.setAttribute("values", String(value));
                    }
                }
            });

            return () => {
                if (hueRotateAnimation.current) {
                    hueRotateAnimation.current.stop();
                }
            };
        }
    }, [animationEnabled, animationDuration, hueRotateMotionValue]);

    return (
        <div
            className={className}
            style={{
                overflow: "hidden",
                position: "relative",
                width: "100%",
                height: "100%",
                ...style
            }}
        >
            <div
                style={{
                    position: "absolute",
                    inset: -displacementScale,
                    filter: animationEnabled ? `url(#${id}) blur(4px)` : "none",
                    pointerEvents: "none",
                    zIndex: 0
                }}
            >
                {animationEnabled && (
                    <svg style={{ position: "absolute", width: 0, height: 0 }}>
                        <defs>
                            <filter id={id}>
                                <feTurbulence
                                    result="undulation"
                                    numOctaves="2"
                                    baseFrequency={`${mapRange(animation.scale, 0, 100, 0.001, 0.0005)},${mapRange(animation.scale, 0, 100, 0.004, 0.002)}`}
                                    seed="0"
                                    type="turbulence"
                                />
                                <feColorMatrix
                                    ref={feColorMatrixRef}
                                    in="undulation"
                                    type="hueRotate"
                                    values="180"
                                />
                                <feColorMatrix
                                    in="dist"
                                    result="circulation"
                                    type="matrix"
                                    values="4 0 0 0 1  4 0 0 0 1  4 0 0 0 1  1 0 0 0 0"
                                />
                                <feDisplacementMap
                                    in="SourceGraphic"
                                    in2="circulation"
                                    scale={displacementScale}
                                    result="dist"
                                />
                                <feDisplacementMap
                                    in="dist"
                                    in2="undulation"
                                    scale={displacementScale}
                                    result="output"
                                />
                            </filter>
                        </defs>
                    </svg>
                )}
                <div
                    style={{
                        backgroundColor: color,
                        maskImage: `url('https://framerusercontent.com/images/ceBGguIpUU8luwByxuQz79t7To.png')`,
                        WebkitMaskImage: `url('https://framerusercontent.com/images/ceBGguIpUU8luwByxuQz79t7To.png')`,
                        maskSize: sizing === "stretch" ? "100% 100%" : "cover",
                        WebkitMaskSize: sizing === "stretch" ? "100% 100%" : "cover",
                        maskRepeat: "no-repeat",
                        WebkitMaskRepeat: "no-repeat",
                        maskPosition: "center",
                        WebkitMaskPosition: "center",
                        width: "100%",
                        height: "100%"
                    }}
                />
            </div>

            {noise && noise.opacity > 0 && (
                <div
                    style={{
                        position: "absolute",
                        inset: 0,
                        backgroundImage: `url("https://framerusercontent.com/images/g0QcWrxr87K0ufOxIUFBakwYA8.png")`,
                        backgroundSize: noise.scale * 200,
                        backgroundRepeat: "repeat",
                        opacity: noise.opacity / 2,
                        pointerEvents: "none",
                        zIndex: 1
                    }}
                />
            )}

            {children && (
                <div className="relative z-10 w-full h-full flex flex-col justify-center items-center">
                    {children}
                </div>
            )}
        </div>
    );
}

--- FILE: frontend-web/registry/backgrounds/FallingPattern.tsx ---

import type React from 'react';
import { motion } from 'framer-motion';
import { cn } from '../core/utils';

export type FallingPatternProps = React.ComponentProps<'div'> & {
	/** Primary color of the falling elements (default: 'var(--primary)') */
	color?: string;
	/** Background color (default: 'var(--background)') */
	backgroundColor?: string;
	/** Animation duration in seconds (default: 150) */
	duration?: number;
	/** Blur intensity for the overlay effect (default: '1em') */
	blurIntensity?: string;
	/** Pattern density - affects spacing (default: 1) */
	density?: number;
};

export function FallingPattern({
	color = 'var(--primary)',
	backgroundColor = 'var(--background)',
	duration = 150,
	blurIntensity = '1em',
	density = 1,
	className,
}: FallingPatternProps) {
	// Generate background image style with customizable color
	const generateBackgroundImage = () => {
		const patterns = [
			// Row 1
			`radial-gradient(4px 100px at 0px 235px, ${color}, transparent)`,
			`radial-gradient(4px 100px at 300px 235px, ${color}, transparent)`,
			`radial-gradient(1.5px 1.5px at 150px 117.5px, ${color} 100%, transparent 150%)`,
			// Row 2
			`radial-gradient(4px 100px at 0px 252px, ${color}, transparent)`,
			`radial-gradient(4px 100px at 300px 252px, ${color}, transparent)`,
			`radial-gradient(1.5px 1.5px at 150px 126px, ${color} 100%, transparent 150%)`,
			// Row 3
			`radial-gradient(4px 100px at 0px 150px, ${color}, transparent)`,
			`radial-gradient(4px 100px at 300px 150px, ${color}, transparent)`,
			`radial-gradient(1.5px 1.5px at 150px 75px, ${color} 100%, transparent 150%)`,
			// Row 4
			`radial-gradient(4px 100px at 0px 253px, ${color}, transparent)`,
			`radial-gradient(4px 100px at 300px 253px, ${color}, transparent)`,
			`radial-gradient(1.5px 1.5px at 150px 126.5px, ${color} 100%, transparent 150%)`,
			// Row 5
			`radial-gradient(4px 100px at 0px 204px, ${color}, transparent)`,
			`radial-gradient(4px 100px at 300px 204px, ${color}, transparent)`,
			`radial-gradient(1.5px 1.5px at 150px 102px, ${color} 100%, transparent 150%)`,
			// Row 6
			`radial-gradient(4px 100px at 0px 134px, ${color}, transparent)`,
			`radial-gradient(4px 100px at 300px 134px, ${color}, transparent)`,
			`radial-gradient(1.5px 1.5px at 150px 67px, ${color} 100%, transparent 150%)`,
			// Row 7
			`radial-gradient(4px 100px at 0px 179px, ${color}, transparent)`,
			`radial-gradient(4px 100px at 300px 179px, ${color}, transparent)`,
			`radial-gradient(1.5px 1.5px at 150px 89.5px, ${color} 100%, transparent 150%)`,
			// Row 8
			`radial-gradient(4px 100px at 0px 299px, ${color}, transparent)`,
			`radial-gradient(4px 100px at 300px 299px, ${color}, transparent)`,
			`radial-gradient(1.5px 1.5px at 150px 149.5px, ${color} 100%, transparent 150%)`,
			// Row 9
			`radial-gradient(4px 100px at 0px 215px, ${color}, transparent)`,
			`radial-gradient(4px 100px at 300px 215px, ${color}, transparent)`,
			`radial-gradient(1.5px 1.5px at 150px 107.5px, ${color} 100%, transparent 150%)`,
			// Row 10
			`radial-gradient(4px 100px at 0px 281px, ${color}, transparent)`,
			`radial-gradient(4px 100px at 300px 281px, ${color}, transparent)`,
			`radial-gradient(1.5px 1.5px at 150px 140.5px, ${color} 100%, transparent 150%)`,
			// Row 11
			`radial-gradient(4px 100px at 0px 158px, ${color}, transparent)`,
			`radial-gradient(4px 100px at 300px 158px, ${color}, transparent)`,
			`radial-gradient(1.5px 1.5px at 150px 79px, ${color} 100%, transparent 150%)`,
			// Row 12
			`radial-gradient(4px 100px at 0px 210px, ${color}, transparent)`,
			`radial-gradient(4px 100px at 300px 210px, ${color}, transparent)`,
			`radial-gradient(1.5px 1.5px at 150px 105px, ${color} 100%, transparent 150%)`,
		];

		return patterns.join(', ');
	};

	const backgroundSizes = [
		'300px 235px',
		'300px 235px',
		'300px 235px',
		'300px 252px',
		'300px 252px',
		'300px 252px',
		'300px 150px',
		'300px 150px',
		'300px 150px',
		'300px 253px',
		'300px 253px',
		'300px 253px',
		'300px 204px',
		'300px 204px',
		'300px 204px',
		'300px 134px',
		'300px 134px',
		'300px 134px',
		'300px 179px',
		'300px 179px',
		'300px 179px',
		'300px 299px',
		'300px 299px',
		'300px 299px',
		'300px 215px',
		'300px 215px',
		'300px 215px',
		'300px 281px',
		'300px 281px',
		'300px 281px',
		'300px 158px',
		'300px 158px',
		'300px 158px',
		'300px 210px',
		'300px 210px',
	].join(', ');

	const startPositions =
		'0px 220px, 3px 220px, 151.5px 337.5px, 25px 24px, 28px 24px, 176.5px 150px, 50px 16px, 53px 16px, 201.5px 91px, 75px 224px, 78px 224px, 226.5px 230.5px, 100px 19px, 103px 19px, 251.5px 121px, 125px 120px, 128px 120px, 276.5px 187px, 150px 31px, 153px 31px, 301.5px 120.5px, 175px 235px, 178px 235px, 326.5px 384.5px, 200px 121px, 203px 121px, 351.5px 228.5px, 225px 224px, 228px 224px, 376.5px 364.5px, 250px 26px, 253px 26px, 401.5px 105px, 275px 75px, 278px 75px, 426.5px 180px';
	const endPositions =
		'0px 6800px, 3px 6800px, 151.5px 6917.5px, 25px 13632px, 28px 13632px, 176.5px 13758px, 50px 5416px, 53px 5416px, 201.5px 5491px, 75px 17175px, 78px 17175px, 226.5px 17301.5px, 100px 5119px, 103px 5119px, 251.5px 5221px, 125px 8428px, 128px 8428px, 276.5px 8495px, 150px 9876px, 153px 9876px, 301.5px 9965.5px, 175px 13391px, 178px 13391px, 326.5px 13540.5px, 200px 14741px, 203px 14741px, 351.5px 14848.5px, 225px 18770px, 228px 18770px, 376.5px 18910.5px, 250px 5082px, 253px 5082px, 401.5px 5161px, 275px 6375px, 278px 6375px, 426.5px 6480px';
	return (
		<div className={cn('relative h-full w-full p-1', className)}>
			<motion.div
				initial={{ opacity: 0 }}
				animate={{ opacity: 1 }}
				transition={{ duration: 0.2 }}
				className="w-full h-full"
			>
				<motion.div
					className="relative w-full h-full z-0"
					style={{
						backgroundColor,
						backgroundImage: generateBackgroundImage(),
						backgroundSize: backgroundSizes,
					}}
					variants={{
						initial: {
							backgroundPosition: startPositions,
						},
						animate: {
							backgroundPosition: [startPositions, endPositions],
							transition: {
								duration: duration,
								ease: 'linear',
								repeat: Number.POSITIVE_INFINITY,
							},
						},
					}}
					initial="initial"
					animate="animate"
				/>
			</motion.div>
			<div
				className="absolute inset-0 z-[1] dark:brightness-[600%]"
				style={{
					backdropFilter: `blur(${blurIntensity})`,
					backgroundImage: `radial-gradient(circle at 50% 50%, transparent 0, transparent 2px, ${backgroundColor} 2px)`,
					backgroundSize: `${8 * density}px ${8 * density}px`,
				}}
			/>
		</div>
	);
}

--- FILE: frontend-web/registry/backgrounds/Ferrofluid.tsx ---

import React, { useEffect, useRef } from 'react';
import { Renderer, Program, Mesh, Triangle } from 'ogl';

export interface FerrofluidProps {
  className?: string;
  dpr?: number;
  paused?: boolean;
  colors?: string[];
  speed?: number;
  scale?: number;
  turbulence?: number;
  fluidity?: number;
  rimWidth?: number;
  sharpness?: number;
  shimmer?: number;
  glow?: number;
  flowDirection?: 'up' | 'down' | 'left' | 'right';
  opacity?: number;
  mouseInteraction?: boolean;
  mouseStrength?: number;
  mouseRadius?: number;
  mouseDampening?: number;
  mixBlendMode?: string;
}

type RGB = [number, number, number];

const MAX_COLORS = 8;

const hexToRGB = (hex: string): RGB => {
  const c = hex.replace('#', '').padEnd(6, '0');
  const r = parseInt(c.slice(0, 2), 16) / 255;
  const g = parseInt(c.slice(2, 4), 16) / 255;
  const b = parseInt(c.slice(4, 6), 16) / 255;
  return [r, g, b];
};

const prepColors = (input?: string[]) => {
  const base = (input && input.length ? input : ['#4F46E5', '#06B6D4', '#E0F2FE']).slice(0, MAX_COLORS);
  const count = base.length;
  const arr: RGB[] = [];
  for (let i = 0; i < MAX_COLORS; i++) arr.push(hexToRGB(base[Math.min(i, base.length - 1)]));
  const avg: RGB = [0, 0, 0];
  for (let i = 0; i < count; i++) {
    avg[0] += arr[i][0];
    avg[1] += arr[i][1];
    avg[2] += arr[i][2];
  }
  avg[0] /= count;
  avg[1] /= count;
  avg[2] /= count;
  return { arr, count, avg };
};

const flowVec = (d?: string): [number, number] => {
  switch (d) {
    case 'up':
      return [0, 1];
    case 'down':
      return [0, -1];
    case 'left':
      return [-1, 0];
    case 'right':
      return [1, 0];
    default:
      return [0, -1];
  }
};

const vertex = `
attribute vec2 position;
attribute vec2 uv;
varying vec2 vUv;
void main() {
  vUv = uv;
  gl_Position = vec4(position, 0.0, 1.0);
}
`;

const fragment = `
precision highp float;

uniform vec3  iResolution;
uniform vec2  iMouse;
uniform float iTime;

uniform vec3  uColor0;
uniform vec3  uColor1;
uniform vec3  uColor2;
uniform vec3  uColor3;
uniform vec3  uColor4;
uniform vec3  uColor5;
uniform vec3  uColor6;
uniform vec3  uColor7;
uniform int   uColorCount;

uniform vec3  uMouseColor;
uniform vec2  uFlow;
uniform float uSpeed;
uniform float uScale;
uniform float uTurbulence;
uniform float uFluidity;
uniform float uRimWidth;
uniform float uSharpness;
uniform float uShimmer;
uniform float uGlow;
uniform float uOpacity;
uniform float uMouseEnabled;
uniform float uMouseStrength;
uniform float uMouseRadius;

varying vec2 vUv;

#define PI 3.14159265

vec3 palette(float h) {
  int count = uColorCount;
  if (count < 1) count = 1;
  int idx = int(floor(clamp(h, 0.0, 0.999999) * float(count)));
  if (idx <= 0) return uColor0;
  if (idx == 1) return uColor1;
  if (idx == 2) return uColor2;
  if (idx == 3) return uColor3;
  if (idx == 4) return uColor4;
  if (idx == 5) return uColor5;
  if (idx == 6) return uColor6;
  return uColor7;
}

float hash(vec3 p3) {
  p3 = fract(p3 * 0.1031);
  p3 += dot(p3, p3.zyx + 33.33);
  return fract((p3.x + p3.y) * p3.z);
}

float smin(float a, float b, float k) {
  float r = exp2(-a / k) + exp2(-b / k);
  return -k * log2(r);
}

float sinlerp(float a, float b, float w) {
  return mix(a, b, (sin(w * PI - PI / 2.0) + 1.0) / 2.0);
}

float vn(vec2 p, float s, float seed) {
  vec2 cellp = floor(p / s);
  vec2 relp = mod(p, s);
  float g1 = hash(vec3(cellp, seed));
  float g2 = hash(vec3(cellp.x + 1.0, cellp.y, seed));
  float g3 = hash(vec3(cellp.x + 1.0, cellp.y + 1.0, seed));
  float g4 = hash(vec3(cellp.x, cellp.y + 1.0, seed));
  float bx = sinlerp(g1, g2, relp.x / s);
  float tx = sinlerp(g4, g3, relp.x / s);
  return sinlerp(bx, tx, relp.y / s);
}

float dbn(vec2 p, float s, float seed) {
  float o = s / 2.0;
  float n0 = vn(p, s, seed);
  float n1 = vn(p + vec2(o, o), s, seed + 0.1);
  float n2 = vn(p + vec2(-o, o), s, seed + 0.2);
  float n3 = vn(p + vec2(o, -o), s, seed + 0.3);
  float n4 = vn(p + vec2(-o, -o), s, seed + 0.4);
  return (2.0 * n0 + 1.5 * n1 + 1.25 * n2 + 1.125 * n3 + n4) / 7.0;
}

void mainImage(out vec4 fragColor, in vec2 fragCoord) {
  float ref = 700.0 / max(uScale, 0.05);
  vec2 p = fragCoord / iResolution.y * ref;

  float spd = 200.0 * uSpeed;
  float t = iTime;

  vec2 dir = uFlow;
  vec2 perp = vec2(-dir.y, dir.x);

  float distort1 = vn(p + perp * (t * spd), 60.0, 10.0) * 50.0 * uTurbulence;
  float distort2 = vn(p - perp * (t * spd), 120.0, 15.0) * 100.0 * uTurbulence;

  float peaks = dbn(p + distort1 + dir * (t * spd * 0.5), 40.0, 1.0);
  float peaks2 = dbn(p + distort2 - dir * (t * spd * 0.5), 40.0, 0.0);

  float mapeaks = smin(peaks, peaks2, max(uFluidity, 0.001));

  float mGlow = 0.0;
  if (uMouseEnabled > 0.5) {
    vec2 mp = iMouse / iResolution.y * ref;
    float md = length(p - mp) / ref;
    float rr = max(uMouseRadius, 0.02);
    mGlow = exp(-md * md / (rr * rr)) * uMouseStrength;
  }

  float band = (uRimWidth - abs((mapeaks - 0.4) * 2.0)) * 5.0;
  float ltn = clamp(band - vn(p + dir * (t * spd * 0.5), 60.0, 12.0) * uShimmer, 0.0, 1.0);
  ltn = pow(ltn, uSharpness) * uGlow;
  ltn *= clamp(1.0 - mGlow, 0.0, 1.0);

  float h = clamp(0.5 + (peaks - peaks2) * 0.8, 0.0, 1.0);
  vec3 col = palette(h);

  vec3 outc = col * ltn;
  float a = clamp(max(outc.r, max(outc.g, outc.b)), 0.0, 1.0);
  fragColor = vec4(outc, a * uOpacity);
}

void main() {
  vec4 color;
  mainImage(color, vUv * iResolution.xy);
  gl_FragColor = color;
}
`;

const Ferrofluid: React.FC<FerrofluidProps> = ({
  className,
  dpr,
  paused = false,
  colors = ['#ffffff', '#ffffff', '#ffffff'],
  speed = 0.5,
  scale = 1.6,
  turbulence = 1,
  fluidity = 0.1,
  rimWidth = 0.2,
  sharpness = 2.5,
  shimmer = 1.5,
  glow = 2,
  flowDirection = 'down',
  opacity = 1,
  mouseInteraction = true,
  mouseStrength = 1,
  mouseRadius = 0.35,
  mouseDampening = 0.15,
  mixBlendMode
}) => {
  const containerRef = useRef<HTMLDivElement | null>(null);
  const rafRef = useRef<number | null>(null);
  const programRef = useRef<Program | null>(null);
  const meshRef = useRef<Mesh | null>(null);
  const geometryRef = useRef<Triangle | null>(null);
  const rendererRef = useRef<Renderer | null>(null);
  const mouseTargetRef = useRef<[number, number]>([0, 0]);
  const lastTimeRef = useRef(0);

  useEffect(() => {
    const container = containerRef.current;
    if (!container) return;

    const renderer = new Renderer({
      dpr: dpr ?? (typeof window !== 'undefined' ? window.devicePixelRatio || 1 : 1),
      alpha: true,
      antialias: true
    });
    rendererRef.current = renderer;
    const gl = renderer.gl;
    const canvas = gl.canvas as HTMLCanvasElement;
    gl.clearColor(0, 0, 0, 0);
    canvas.style.width = '100%';
    canvas.style.height = '100%';
    canvas.style.display = 'block';
    container.appendChild(canvas);

    const { arr, count, avg } = prepColors(colors);

    const uniforms = {
      iResolution: { value: [gl.drawingBufferWidth, gl.drawingBufferHeight, 1] },
      iMouse: { value: [0, 0] },
      iTime: { value: 0 },
      uColor0: { value: arr[0] },
      uColor1: { value: arr[1] },
      uColor2: { value: arr[2] },
      uColor3: { value: arr[3] },
      uColor4: { value: arr[4] },
      uColor5: { value: arr[5] },
      uColor6: { value: arr[6] },
      uColor7: { value: arr[7] },
      uColorCount: { value: count },
      uMouseColor: { value: avg },
      uFlow: { value: flowVec(flowDirection) },
      uSpeed: { value: speed },
      uScale: { value: scale },
      uTurbulence: { value: turbulence },
      uFluidity: { value: fluidity },
      uRimWidth: { value: rimWidth },
      uSharpness: { value: sharpness },
      uShimmer: { value: shimmer },
      uGlow: { value: glow },
      uOpacity: { value: opacity },
      uMouseEnabled: { value: mouseInteraction ? 1 : 0 },
      uMouseStrength: { value: mouseStrength },
      uMouseRadius: { value: mouseRadius }
    };

    const program = new Program(gl, { vertex, fragment, uniforms });
    programRef.current = program;

    const geometry = new Triangle(gl);
    geometryRef.current = geometry;
    const mesh = new Mesh(gl, { geometry, program });
    meshRef.current = mesh;

    const resize = () => {
      const rect = container.getBoundingClientRect();
      renderer.setSize(rect.width, rect.height);
      uniforms.iResolution.value = [gl.drawingBufferWidth, gl.drawingBufferHeight, 1];
    };

    resize();
    const ro = new ResizeObserver(resize);
    ro.observe(container);

    const onPointerMove = (e: PointerEvent) => {
      const rect = canvas.getBoundingClientRect();
      const sc = renderer.dpr || 1;
      const x = (e.clientX - rect.left) * sc;
      const y = (rect.height - (e.clientY - rect.top)) * sc;
      mouseTargetRef.current = [x, y];
      if (mouseDampening <= 0) {
        uniforms.iMouse.value = [x, y];
      }
    };
    if (mouseInteraction) {
      canvas.addEventListener('pointermove', onPointerMove);
    }

    const loop = (t: number) => {
      rafRef.current = requestAnimationFrame(loop);
      uniforms.iTime.value = t * 0.001;
      if (mouseDampening > 0) {
        if (!lastTimeRef.current) lastTimeRef.current = t;
        const dt = (t - lastTimeRef.current) / 1000;
        lastTimeRef.current = t;
        const tau = Math.max(1e-4, mouseDampening);
        let factor = 1 - Math.exp(-dt / tau);
        if (factor > 1) factor = 1;
        const target = mouseTargetRef.current;
        const cur = uniforms.iMouse.value as number[];
        cur[0] += (target[0] - cur[0]) * factor;
        cur[1] += (target[1] - cur[1]) * factor;
      } else {
        lastTimeRef.current = t;
      }
      if (!paused && programRef.current && meshRef.current) {
        try {
          renderer.render({ scene: meshRef.current });
        } catch (e) {
          console.error(e);
        }
      }
    };
    rafRef.current = requestAnimationFrame(loop);

    return () => {
      if (rafRef.current) cancelAnimationFrame(rafRef.current);
      if (mouseInteraction) canvas.removeEventListener('pointermove', onPointerMove);
      ro.disconnect();
      if (canvas.parentElement === container) {
        container.removeChild(canvas);
      }
      const callIfFn = (obj: unknown, key: string) => {
        const fn = obj && (obj as Record<string, unknown>)[key];
        if (typeof fn === 'function') {
          (fn as () => void).call(obj);
        }
      };
      callIfFn(programRef.current, 'remove');
      callIfFn(geometryRef.current, 'remove');
      callIfFn(meshRef.current, 'remove');
      callIfFn(rendererRef.current, 'destroy');
      programRef.current = null;
      geometryRef.current = null;
      meshRef.current = null;
      rendererRef.current = null;
    };
  }, [
    dpr,
    paused,
    colors,
    speed,
    scale,
    turbulence,
    fluidity,
    rimWidth,
    sharpness,
    shimmer,
    glow,
    flowDirection,
    opacity,
    mouseInteraction,
    mouseStrength,
    mouseRadius,
    mouseDampening
  ]);

  return (
    <div
      ref={containerRef}
      className={`w-full h-full overflow-hidden relative ${className ?? ''}`}
      style={{
        ...(mixBlendMode && { mixBlendMode: mixBlendMode as React.CSSProperties['mixBlendMode'] })
      }}
    />
  );
};

export default Ferrofluid;


--- FILE: frontend-web/registry/backgrounds/FlickeringGrid.tsx ---

import React, {
  useCallback,
  useEffect,
  useMemo,
  useRef,
  useState,
} from "react";
import { cn } from "../core/utils";

interface FlickeringGridProps extends React.HTMLAttributes<HTMLDivElement> {
  squareSize?: number;
  gridGap?: number;
  flickerChance?: number;
  color?: string;
  width?: number;
  height?: number;
  className?: string;
  maxOpacity?: number;
}

export const FlickeringGrid: React.FC<FlickeringGridProps> = ({
  squareSize = 4,
  gridGap = 6,
  flickerChance = 0.3,
  color = "rgb(0, 0, 0)",
  width,
  height,
  className,
  maxOpacity = 0.3,
  ...props
}) => {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const containerRef = useRef<HTMLDivElement>(null);
  const [isInView, setIsInView] = useState(false);
  const [canvasSize, setCanvasSize] = useState({ width: 0, height: 0 });

  const memoizedColor = useMemo(() => {
    const toRGBA = (color: string) => {
      if (typeof window === "undefined") {
        return `rgba(0, 0, 0,`;
      }
      const canvas = document.createElement("canvas");
      canvas.width = canvas.height = 1;
      const ctx = canvas.getContext("2d");
      if (!ctx) return "rgba(255, 0, 0,";
      ctx.fillStyle = color;
      ctx.fillRect(0, 0, 1, 1);
      const [r, g, b] = Array.from(ctx.getImageData(0, 0, 1, 1).data);
      return `rgba(${r}, ${g}, ${b},`;
    };
    return toRGBA(color);
  }, [color]);

  const setupCanvas = useCallback(
    (canvas: HTMLCanvasElement, width: number, height: number) => {
      const dpr = window.devicePixelRatio || 1;
      canvas.width = width * dpr;
      canvas.height = height * dpr;
      canvas.style.width = `${width}px`;
      canvas.style.height = `${height}px`;
      const cols = Math.floor(width / (squareSize + gridGap));
      const rows = Math.floor(height / (squareSize + gridGap));

      const squares = new Float32Array(cols * rows);
      for (let i = 0; i < squares.length; i++) {
        squares[i] = Math.random() * maxOpacity;
      }

      return { cols, rows, squares, dpr };
    },
    [squareSize, gridGap, maxOpacity],
  );

  const updateSquares = useCallback(
    (squares: Float32Array, deltaTime: number) => {
      for (let i = 0; i < squares.length; i++) {
        if (Math.random() < flickerChance * deltaTime) {
          squares[i] = Math.random() * maxOpacity;
        }
      }
    },
    [flickerChance, maxOpacity],
  );

  const drawGrid = useCallback(
    (
      ctx: CanvasRenderingContext2D,
      width: number,
      height: number,
      cols: number,
      rows: number,
      squares: Float32Array,
      dpr: number,
    ) => {
      ctx.clearRect(0, 0, width, height);
      ctx.fillStyle = "transparent";
      ctx.fillRect(0, 0, width, height);

      for (let i = 0; i < cols; i++) {
        for (let j = 0; j < rows; j++) {
          const opacity = squares[i * rows + j];
          ctx.fillStyle = `${memoizedColor}${opacity})`;
          ctx.fillRect(
            i * (squareSize + gridGap) * dpr,
            j * (squareSize + gridGap) * dpr,
            squareSize * dpr,
            squareSize * dpr,
          );
        }
      }
    },
    [memoizedColor, squareSize, gridGap],
  );

  useEffect(() => {
    const canvas = canvasRef.current;
    const container = containerRef.current;
    if (!canvas || !container) return;

    const ctx = canvas.getContext("2d");
    if (!ctx) return;

    let animationFrameId: number;
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    let gridParams: any;

    const updateCanvasSize = () => {
      const newWidth = width || container.clientWidth;
      const newHeight = height || container.clientHeight;
      setCanvasSize({ width: newWidth, height: newHeight });
      gridParams = setupCanvas(canvas, newWidth, newHeight);
    };

    updateCanvasSize();

    let lastTime = 0;
    const animate = (time: number) => {
      if (!isInView) return;

      const deltaTime = (time - lastTime) / 1000;
      lastTime = time;

      updateSquares(gridParams.squares, deltaTime);
      drawGrid(
        ctx,
        canvas.width,
        canvas.height,
        gridParams.cols,
        gridParams.rows,
        gridParams.squares,
        gridParams.dpr,
      );
      animationFrameId = requestAnimationFrame(animate);
    };

    const resizeObserver = new ResizeObserver(() => {
      updateCanvasSize();
    });

    resizeObserver.observe(container);

    const intersectionObserver = new IntersectionObserver(
      ([entry]) => {
        setIsInView(entry!.isIntersecting);
      },
      { threshold: 0 },
    );

    intersectionObserver.observe(canvas);

    if (isInView) {
      animationFrameId = requestAnimationFrame(animate);
    }

    return () => {
      cancelAnimationFrame(animationFrameId);
      resizeObserver.disconnect();
      intersectionObserver.disconnect();
    };
  }, [setupCanvas, updateSquares, drawGrid, width, height, isInView]);

  return (
    <div
      ref={containerRef}
      className={cn("h-full w-full", className)}
      {...props}
    >
      <canvas
        ref={canvasRef}
        className="pointer-events-none absolute inset-0"
        style={{
          width: canvasSize.width,
          height: canvasSize.height,
        }}
      />
    </div>
  );
};

--- FILE: frontend-web/registry/backgrounds/GradientBackground.tsx ---

import React from 'react';
import { motion } from 'framer-motion';
import { cn } from '../core/utils';

export type GradientBackgroundProps = React.ComponentProps<'div'> & {
	// Animation customization
	gradients?: string[];
	animationDuration?: number;
	animationDelay?: number;

	// Visual customization
	overlay?: boolean;
	overlayOpacity?: number;
};

const Default_Gradients = [
    "linear-gradient(135deg, #2d1b69 0%, #11998e 100%)",
    "linear-gradient(135deg, #8e2de2 0%, #4a00e0 100%)",
    "linear-gradient(135deg, #0f3460 0%, #e94560 100%)",
    "linear-gradient(135deg, #134e5e 0%, #71b280 100%)",
    "linear-gradient(135deg, #2d1b69 0%, #11998e 100%)",
];

export function GradientBackground({
	children,
	className = '',
	gradients = Default_Gradients,
	animationDuration = 8,
	animationDelay = 0.5,
	overlay = false,
	overlayOpacity = 0.3,
    ...props
}: GradientBackgroundProps) {
	return (
		<div className={cn('relative w-full h-full overflow-hidden', className)} {...props}>
			{/* Animated gradient background */}
			<motion.div
				className="absolute inset-0 z-0"
				style={{ background: gradients[0] }}
				animate={{ background: gradients }}
				transition={{
					delay: animationDelay,
					duration: animationDuration,
					repeat: Number.POSITIVE_INFINITY,
					ease: 'easeInOut',
				}}
			/>

			{/* Optional overlay */}
			{overlay && (
				<div
					className="absolute inset-0 bg-black z-0 pointer-events-none"
					style={{ opacity: overlayOpacity }}
				/>
			)}

			{/* Content wrapper */}
			{children && (
				<div
					className="relative z-10 flex w-full h-full items-center justify-center"
				>
					{children}
				</div>
			)}
		</div>
	);
}

--- FILE: frontend-web/registry/backgrounds/GradientDots.tsx ---

import React from 'react';
import { motion } from 'framer-motion';
import { cn } from '../core/utils';

export type GradientDotsProps = React.ComponentProps<typeof motion.div> & {
	/** Dot size (default: 8) */
	dotSize?: number;
	/** Spacing between dots (default: 10) */
	spacing?: number;
	/** Animation duration (default: 30) */
	duration?: number;
	/** Color cycle duration (default: 6) */
	colorCycleDuration?: number;
	/** Background color (default: '#000000') */
	backgroundColor?: string;
};

export function GradientDots({
	dotSize = 8,
	spacing = 10,
	duration = 30,
	colorCycleDuration = 6,
	backgroundColor = '#000000',
	className,
	...props
}: GradientDotsProps) {
	const hexSpacing = spacing * 1.732; // Hexagonal spacing calculation

	return (
		<motion.div
			className={cn('absolute inset-0 pointer-events-none z-0', className)}
			style={{
				backgroundColor,
				backgroundImage: `
          radial-gradient(circle at 50% 50%, transparent 1.5px, ${backgroundColor} 0 ${dotSize}px, transparent ${dotSize}px),
          radial-gradient(circle at 50% 50%, transparent 1.5px, ${backgroundColor} 0 ${dotSize}px, transparent ${dotSize}px),
          radial-gradient(circle at 50% 50%, #f00, transparent 60%),
          radial-gradient(circle at 50% 50%, #ff0, transparent 60%),
          radial-gradient(circle at 50% 50%, #0f0, transparent 60%),
          radial-gradient(ellipse at 50% 50%, #00f, transparent 60%)
        `,
				backgroundSize: `
          ${spacing}px ${hexSpacing}px,
          ${spacing}px ${hexSpacing}px,
          200% 200%,
          200% 200%,
          200% 200%,
          200% ${hexSpacing}px
        `,
				backgroundPosition: `
          0px 0px, ${spacing / 2}px ${hexSpacing / 2}px,
          0% 0%,
          0% 0%,
          0% 0px
        `,
			}}
			animate={{
				backgroundPosition: [
					`0px 0px, ${spacing / 2}px ${hexSpacing / 2}px, 800% 400%, 1000% -400%, -1200% -600%, 400% ${hexSpacing}px`,
					`0px 0px, ${spacing / 2}px ${hexSpacing / 2}px, 0% 0%, 0% 0%, 0% 0%, 0% 0%`,
				],
				filter: ['hue-rotate(0deg)', 'hue-rotate(360deg)'],
			}}
			transition={{
				backgroundPosition: {
					duration: duration,
					ease: 'linear',
					repeat: Number.POSITIVE_INFINITY,
				},
				filter: {
					duration: colorCycleDuration,
					ease: 'linear',
					repeat: Number.POSITIVE_INFINITY,
				},
			}}
			{...props}
		/>
	);
}

--- FILE: frontend-web/registry/backgrounds/GridPattern.tsx ---

import React, { useId } from "react";
import { cn } from "../core/utils";

export interface GridPatternProps extends React.SVGProps<SVGSVGElement> {
  width?: number;
  height?: number;
  x?: number | string;
  y?: number | string;
  squares?: Array<[x: number, y: number]>;
  strokeDasharray?: string;
  className?: string;
}

export function GridPattern({
  width = 40,
  height = 40,
  x = -1,
  y = -1,
  strokeDasharray = "0",
  squares,
  className,
  ...props
}: GridPatternProps) {
  const id = useId();

  return (
    <svg
      aria-hidden="true"
      className={cn(
        "pointer-events-none absolute inset-0 h-full w-full fill-slate-400/30 stroke-slate-400/30 dark:fill-slate-800/30 dark:stroke-slate-800/30",
        className
      )}
      {...props}
    >
      <defs>
        <pattern
          id={id}
          width={width}
          height={height}
          patternUnits="userSpaceOnUse"
          x={x}
          y={y}
        >
          <path
            d={`M.5 ${height}V.5H${width}`}
            fill="none"
            strokeDasharray={strokeDasharray}
          />
        </pattern>
      </defs>
      <rect width="100%" height="100%" strokeWidth={0} fill={`url(#${id})`} />
      {squares && (
        <svg x={x} y={y} className="overflow-visible">
          {squares.map(([sqX, sqY]) => (
            <rect
              strokeWidth="0"
              key={`${sqX}-${sqY}`}
              width={width - 1}
              height={height - 1}
              x={sqX * width + 1}
              y={sqY * height + 1}
            />
          ))}
        </svg>
      )}
    </svg>
  );
}

--- FILE: frontend-web/registry/backgrounds/Light Pillar.tsx ---

import React, { useRef, useEffect, useState } from 'react';
import * as THREE from 'three';

interface LightPillarProps {
  topColor?: string;
  bottomColor?: string;
  intensity?: number;
  rotationSpeed?: number;
  interactive?: boolean;
  className?: string;
  glowAmount?: number;
  pillarWidth?: number;
  pillarHeight?: number;
  noiseIntensity?: number;
  mixBlendMode?: React.CSSProperties['mixBlendMode'];
  pillarRotation?: number;
  quality?: 'low' | 'medium' | 'high';
}

const LightPillar: React.FC<LightPillarProps> = ({
  topColor = '#5227FF',
  bottomColor = '#FF9FFC',
  intensity = 1.0,
  rotationSpeed = 0.3,
  interactive = false,
  className = '',
  glowAmount = 0.005,
  pillarWidth = 3.0,
  pillarHeight = 0.4,
  noiseIntensity = 0.5,
  mixBlendMode = 'screen',
  pillarRotation = 0,
  quality = 'high'
}) => {
  const containerRef = useRef<HTMLDivElement>(null);
  const rafRef = useRef<number | null>(null);
  const rendererRef = useRef<THREE.WebGLRenderer | null>(null);
  const materialRef = useRef<THREE.ShaderMaterial | null>(null);
  const sceneRef = useRef<THREE.Scene | null>(null);
  const cameraRef = useRef<THREE.OrthographicCamera | null>(null);
  const geometryRef = useRef<THREE.PlaneGeometry | null>(null);
  const mouseRef = useRef<THREE.Vector2>(new THREE.Vector2(0, 0));
  const timeRef = useRef(0);
  const rotationSpeedRef = useRef(rotationSpeed);
  const [webGLSupported, setWebGLSupported] = useState<boolean>(true);

  // Check WebGL support
  useEffect(() => {
    const canvas = document.createElement('canvas');
    const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
    if (!gl) {
      setWebGLSupported(false);
    }
  }, []);

  useEffect(() => {
    if (!containerRef.current || !webGLSupported) return;

    const container = containerRef.current;
    const width = container.clientWidth;
    const height = container.clientHeight;

    const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
    const isLowEndDevice = isMobile || (navigator.hardwareConcurrency && navigator.hardwareConcurrency <= 4);

    let effectiveQuality = quality;
    if (isLowEndDevice && quality === 'high') effectiveQuality = 'medium';
    if (isMobile && quality !== 'low') effectiveQuality = 'low';

    const qualitySettings = {
      low: { iterations: 24, waveIterations: 1, pixelRatio: 0.5, precision: 'mediump', stepMultiplier: 1.5 },
      medium: { iterations: 40, waveIterations: 2, pixelRatio: 0.65, precision: 'mediump', stepMultiplier: 1.2 },
      high: {
        iterations: 80,
        waveIterations: 4,
        pixelRatio: Math.min(window.devicePixelRatio, 2),
        precision: 'highp',
        stepMultiplier: 1.0
      }
    };

    const settings = qualitySettings[effectiveQuality] || qualitySettings.medium;

    // Scene setup
    const scene = new THREE.Scene();
    sceneRef.current = scene;
    const camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1);
    cameraRef.current = camera;

    let renderer: THREE.WebGLRenderer;
    try {
      renderer = new THREE.WebGLRenderer({
        antialias: false,
        alpha: true,
        powerPreference: effectiveQuality === 'low' ? 'low-power' : 'high-performance',
        precision: settings.precision,
        stencil: false,
        depth: false
      });
    } catch (error) {
      console.error('Failed to create WebGL renderer:', error);
      setWebGLSupported(false);
      return;
    }

    renderer.setSize(width, height);
    renderer.setPixelRatio(settings.pixelRatio);
    container.appendChild(renderer.domElement);
    rendererRef.current = renderer;

    // Convert hex colors to RGB
    const parseColor = (hex: string): THREE.Vector3 => {
      const color = new THREE.Color(hex);
      return new THREE.Vector3(color.r, color.g, color.b);
    };

    // Shader material
    const vertexShader = `
      varying vec2 vUv;
      void main() {
        vUv = uv;
        gl_Position = vec4(position, 1.0);
      }
    `;

    const fragmentShader = `
      uniform float uTime;
      uniform vec2 uResolution;
      uniform vec2 uMouse;
      uniform vec3 uTopColor;
      uniform vec3 uBottomColor;
      uniform float uIntensity;
      uniform bool uInteractive;
      uniform float uGlowAmount;
      uniform float uPillarWidth;
      uniform float uPillarHeight;
      uniform float uNoiseIntensity;
      uniform float uPillarRotation;
      uniform float uRotCos;
      uniform float uRotSin;
      uniform float uPillarRotCos;
      uniform float uPillarRotSin;
      uniform float uWaveSin[4];
      uniform float uWaveCos[4];
      varying vec2 vUv;

      const float PI = 3.141592653589793;
      const float EPSILON = 0.001;
      const float E = 2.71828182845904523536;

      float noise(vec2 coord) {
        vec2 r = (E * sin(E * coord));
        return fract(r.x * r.y * (1.0 + coord.x));
      }

      void main() {
        vec2 fragCoord = vUv * uResolution;
        vec2 uv = (fragCoord * 2.0 - uResolution) / uResolution.y;
        
        // Apply 2D rotation to UV coordinates using pre-computed values
        uv = vec2(
          uv.x * uPillarRotCos - uv.y * uPillarRotSin,
          uv.x * uPillarRotSin + uv.y * uPillarRotCos
        );

        vec3 origin = vec3(0.0, 0.0, -10.0);
        vec3 direction = normalize(vec3(uv, 1.0));

        float maxDepth = 50.0;
        float depth = 0.1;

        // Use pre-computed rotation values (or mouse-based)
        float rotCos = uRotCos;
        float rotSin = uRotSin;
        if(uInteractive && length(uMouse) > 0.0) {
          float mouseAngle = uMouse.x * PI * 2.0;
          rotCos = cos(mouseAngle);
          rotSin = sin(mouseAngle);
        }

        vec3 color = vec3(0.0);
        
        const int ITERATIONS = ${settings.iterations};
        const int WAVE_ITERATIONS = ${settings.waveIterations};
        const float STEP_MULT = ${settings.stepMultiplier.toFixed(1)};
        
        for(int i = 0; i < ITERATIONS; i++) {
          vec3 pos = origin + direction * depth;
          
          // Inline rotation: pos.xz *= rotMat
          float newX = pos.x * rotCos - pos.z * rotSin;
          float newZ = pos.x * rotSin + pos.z * rotCos;
          pos.x = newX;
          pos.z = newZ;

          // Apply vertical scaling and wave deformation
          vec3 deformed = pos;
          deformed.y *= uPillarHeight;
          deformed = deformed + vec3(0.0, uTime, 0.0);
          
          // Inlined wave deformation
          float frequency = 1.0;
          float amplitude = 1.0;
          for(int j = 0; j < WAVE_ITERATIONS; j++) {
            // Inline rotation: deformed.xz *= rot(0.4) using pre-computed
            float wx = deformed.x * uWaveCos[j] - deformed.z * uWaveSin[j];
            float wz = deformed.x * uWaveSin[j] + deformed.z * uWaveCos[j];
            deformed.x = wx;
            deformed.z = wz;
            
            float phase = uTime * float(j) * 2.0;
            vec3 oscillation = cos(deformed.zxy * frequency - phase);
            deformed += oscillation * amplitude;
            frequency *= 2.0;
            amplitude *= 0.5;
          }
          
          // Calculate distance field using cosine pattern
          vec2 cosinePair = cos(deformed.xz);
          float fieldDistance = length(cosinePair) - 0.2;
          
          // Radial boundary constraint (inlined blendMax)
          float radialBound = length(pos.xz) - uPillarWidth;
          float k = 4.0;
          float h = max(k - abs(-radialBound - (-fieldDistance)), 0.0);
          fieldDistance = -(min(-radialBound, -fieldDistance) - h * h * 0.25 / k);
          
          fieldDistance = abs(fieldDistance) * 0.15 + 0.01;

          vec3 gradient = mix(uBottomColor, uTopColor, smoothstep(15.0, -15.0, pos.y));
          color += gradient / fieldDistance;

          if(fieldDistance < EPSILON || depth > maxDepth) break;
          depth += fieldDistance * STEP_MULT;
        }

        // Normalize by pillar width to maintain consistent glow regardless of size
        float widthNormalization = uPillarWidth / 3.0;
        color = tanh(color * uGlowAmount / widthNormalization);
        
        // Add noise postprocessing
        float rnd = noise(gl_FragCoord.xy);
        color -= rnd / 15.0 * uNoiseIntensity;
        
        gl_FragColor = vec4(color * uIntensity, 1.0);
      }
    `;

    // Pre-compute wave rotation values
    const waveAngle = 0.4;
    const waveSinValues = new Float32Array(4);
    const waveCosValues = new Float32Array(4);
    for (let i = 0; i < 4; i++) {
      waveSinValues[i] = Math.sin(waveAngle);
      waveCosValues[i] = Math.cos(waveAngle);
    }

    // Pre-compute pillar rotation
    const pillarRotRad = (pillarRotation * Math.PI) / 180.0;
    const pillarRotCos = Math.cos(pillarRotRad);
    const pillarRotSin = Math.sin(pillarRotRad);

    const material = new THREE.ShaderMaterial({
      vertexShader,
      fragmentShader,
      uniforms: {
        uTime: { value: 0 },
        uResolution: { value: new THREE.Vector2(width, height) },
        uMouse: { value: mouseRef.current },
        uTopColor: { value: parseColor(topColor) },
        uBottomColor: { value: parseColor(bottomColor) },
        uIntensity: { value: intensity },
        uInteractive: { value: interactive },
        uGlowAmount: { value: glowAmount },
        uPillarWidth: { value: pillarWidth },
        uPillarHeight: { value: pillarHeight },
        uNoiseIntensity: { value: noiseIntensity },
        uPillarRotation: { value: pillarRotation },
        uRotCos: { value: 1.0 },
        uRotSin: { value: 0.0 },
        uPillarRotCos: { value: pillarRotCos },
        uPillarRotSin: { value: pillarRotSin },
        uWaveSin: { value: waveSinValues },
        uWaveCos: { value: waveCosValues }
      },
      transparent: true,
      depthWrite: false,
      depthTest: false
    });
    materialRef.current = material;

    const geometry = new THREE.PlaneGeometry(2, 2);
    geometryRef.current = geometry;
    const mesh = new THREE.Mesh(geometry, material);
    scene.add(mesh);

    // Mouse interaction - throttled for performance
    let mouseMoveTimeout: number | null = null;
    const handleMouseMove = (event: MouseEvent) => {
      if (!interactive) return;

      if (mouseMoveTimeout) return;

      mouseMoveTimeout = window.setTimeout(() => {
        mouseMoveTimeout = null;
      }, 16); // ~60fps throttle

      const rect = container.getBoundingClientRect();
      const x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
      const y = -((event.clientY - rect.top) / rect.height) * 2 + 1;
      mouseRef.current.set(x, y);
    };

    if (interactive) {
      container.addEventListener('mousemove', handleMouseMove, { passive: true });
    }

    // Animation loop with fixed timestep
    let lastTime = performance.now();
    const targetFPS = effectiveQuality === 'low' ? 30 : 60;
    const frameTime = 1000 / targetFPS;

    const animate = (currentTime: number) => {
      if (!materialRef.current || !rendererRef.current || !sceneRef.current || !cameraRef.current) return;

      const deltaTime = currentTime - lastTime;

      if (deltaTime >= frameTime) {
        timeRef.current += 0.016 * rotationSpeedRef.current;
        materialRef.current.uniforms.uTime.value = timeRef.current;

        // Pre-compute rotation on CPU
        const rotAngle = timeRef.current * 0.3;
        materialRef.current.uniforms.uRotCos.value = Math.cos(rotAngle);
        materialRef.current.uniforms.uRotSin.value = Math.sin(rotAngle);

        rendererRef.current.render(sceneRef.current, cameraRef.current);
        lastTime = currentTime - (deltaTime % frameTime);
      }

      rafRef.current = requestAnimationFrame(animate);
    };
    rafRef.current = requestAnimationFrame(animate);

    // Handle resize with debouncing
    let resizeTimeout: number | null = null;
    const handleResize = () => {
      if (resizeTimeout) {
        clearTimeout(resizeTimeout);
      }

      resizeTimeout = window.setTimeout(() => {
        if (!rendererRef.current || !materialRef.current || !containerRef.current) return;
        const newWidth = containerRef.current.clientWidth;
        const newHeight = containerRef.current.clientHeight;
        rendererRef.current.setSize(newWidth, newHeight);
        materialRef.current.uniforms.uResolution.value.set(newWidth, newHeight);
      }, 150);
    };

    window.addEventListener('resize', handleResize, { passive: true });

    // Cleanup
    return () => {
      window.removeEventListener('resize', handleResize);
      if (interactive) {
        container.removeEventListener('mousemove', handleMouseMove);
      }
      if (rafRef.current) {
        cancelAnimationFrame(rafRef.current);
      }
      if (rendererRef.current) {
        rendererRef.current.dispose();
        rendererRef.current.forceContextLoss();
        if (container.contains(rendererRef.current.domElement)) {
          container.removeChild(rendererRef.current.domElement);
        }
      }
      if (materialRef.current) {
        materialRef.current.dispose();
      }
      if (geometryRef.current) {
        geometryRef.current.dispose();
      }

      rendererRef.current = null;
      materialRef.current = null;
      sceneRef.current = null;
      cameraRef.current = null;
      geometryRef.current = null;
      rafRef.current = null;
    };
  }, [webGLSupported, quality]);

  useEffect(() => {
    rotationSpeedRef.current = rotationSpeed;
  }, [rotationSpeed]);

  useEffect(() => {
    if (!materialRef.current) return;
    const parseColor = (hex: string) => {
      const color = new THREE.Color(hex);
      return new THREE.Vector3(color.r, color.g, color.b);
    };
    materialRef.current.uniforms.uTopColor.value = parseColor(topColor);
  }, [topColor]);

  useEffect(() => {
    if (!materialRef.current) return;
    const parseColor = (hex: string) => {
      const color = new THREE.Color(hex);
      return new THREE.Vector3(color.r, color.g, color.b);
    };
    materialRef.current.uniforms.uBottomColor.value = parseColor(bottomColor);
  }, [bottomColor]);

  useEffect(() => {
    if (!materialRef.current) return;
    materialRef.current.uniforms.uIntensity.value = intensity;
  }, [intensity]);

  useEffect(() => {
    if (!materialRef.current) return;
    materialRef.current.uniforms.uInteractive.value = interactive;
  }, [interactive]);

  useEffect(() => {
    if (!materialRef.current) return;
    materialRef.current.uniforms.uGlowAmount.value = glowAmount;
  }, [glowAmount]);

  useEffect(() => {
    if (!materialRef.current) return;
    materialRef.current.uniforms.uPillarWidth.value = pillarWidth;
  }, [pillarWidth]);

  useEffect(() => {
    if (!materialRef.current) return;
    materialRef.current.uniforms.uPillarHeight.value = pillarHeight;
  }, [pillarHeight]);

  useEffect(() => {
    if (!materialRef.current) return;
    materialRef.current.uniforms.uNoiseIntensity.value = noiseIntensity;
  }, [noiseIntensity]);

  useEffect(() => {
    if (!materialRef.current) return;
    const pillarRotRad = (pillarRotation * Math.PI) / 180;
    materialRef.current.uniforms.uPillarRotCos.value = Math.cos(pillarRotRad);
    materialRef.current.uniforms.uPillarRotSin.value = Math.sin(pillarRotRad);
  }, [pillarRotation]);

  if (!webGLSupported) {
    return (
      <div
        className={`w-full h-full absolute top-0 left-0 flex items-center justify-center bg-black/10 text-gray-500 text-sm ${className}`}
        style={{ mixBlendMode }}
      >
        WebGL not supported
      </div>
    );
  }

  return (
    <div ref={containerRef} className={`w-full h-full absolute top-0 left-0 ${className}`} style={{ mixBlendMode }} />
  );
};

export default LightPillar;


--- FILE: frontend-web/registry/backgrounds/Lightfall.tsx ---

import React, { useEffect, useRef } from 'react';
import { Renderer, Program, Mesh, Triangle } from 'ogl';

export interface LightfallProps {
  className?: string;
  dpr?: number;
  paused?: boolean;
  colors?: string[];
  backgroundColor?: string;
  speed?: number;
  streakCount?: number;
  streakWidth?: number;
  streakLength?: number;
  glow?: number;
  density?: number;
  twinkle?: number;
  zoom?: number;
  backgroundGlow?: number;
  opacity?: number;
  mouseInteraction?: boolean;
  mouseStrength?: number;
  mouseRadius?: number;
  mouseDampening?: number;
  mixBlendMode?: string;
}

type RGB = [number, number, number];

const MAX_COLORS = 8;

const hexToRGB = (hex: string): RGB => {
  const c = hex.replace('#', '').padEnd(6, '0');
  const r = parseInt(c.slice(0, 2), 16) / 255;
  const g = parseInt(c.slice(2, 4), 16) / 255;
  const b = parseInt(c.slice(4, 6), 16) / 255;
  return [r, g, b];
};

const prepColors = (input?: string[]) => {
  const base = (input && input.length ? input : ['#A6C8FF', '#5227FF', '#FF9FFC']).slice(0, MAX_COLORS);
  const count = base.length;
  const arr: RGB[] = [];
  for (let i = 0; i < MAX_COLORS; i++) arr.push(hexToRGB(base[Math.min(i, base.length - 1)]));
  const avg: RGB = [0, 0, 0];
  for (let i = 0; i < count; i++) {
    avg[0] += arr[i][0];
    avg[1] += arr[i][1];
    avg[2] += arr[i][2];
  }
  avg[0] /= count;
  avg[1] /= count;
  avg[2] /= count;
  return { arr, count, avg };
};

const vertex = `
attribute vec2 position;
attribute vec2 uv;
varying vec2 vUv;
void main() {
  vUv = uv;
  gl_Position = vec4(position, 0.0, 1.0);
}
`;

const fragment = `
precision highp float;

uniform vec3  iResolution;
uniform vec2  iMouse;
uniform float iTime;

uniform vec3  uColor0;
uniform vec3  uColor1;
uniform vec3  uColor2;
uniform vec3  uColor3;
uniform vec3  uColor4;
uniform vec3  uColor5;
uniform vec3  uColor6;
uniform vec3  uColor7;
uniform int   uColorCount;

uniform vec3  uBgColor;
uniform vec3  uMouseColor;
uniform float uSpeed;
uniform int   uStreakCount;
uniform float uStreakWidth;
uniform float uStreakLength;
uniform float uGlow;
uniform float uDensity;
uniform float uTwinkle;
uniform float uZoom;
uniform float uBgGlow;
uniform float uOpacity;
uniform float uMouseEnabled;
uniform float uMouseStrength;
uniform float uMouseRadius;

varying vec2 vUv;

vec3 palette(float h) {
  int count = uColorCount;
  if (count < 1) count = 1;
  int idx = int(floor(clamp(h, 0.0, 0.999999) * float(count)));
  if (idx <= 0) return uColor0;
  if (idx == 1) return uColor1;
  if (idx == 2) return uColor2;
  if (idx == 3) return uColor3;
  if (idx == 4) return uColor4;
  if (idx == 5) return uColor5;
  if (idx == 6) return uColor6;
  return uColor7;
}

vec3 tanhv(vec3 x) {
  vec3 e = exp(-2.0 * x);
  return (1.0 - e) / (1.0 + e);
}

vec2 sceneC(vec2 frag, vec2 r) {
  vec2 P = (frag + frag - r) / r.x;
  float z = 0.0;
  float d = 1e3;
  vec4 O = vec4(0.0);
  for (int k = 0; k < 39; k++) {
    if (d <= 1e-4) break;
    O = z * normalize(vec4(P, uZoom, 0.0)) - vec4(0.0, 4.0, 1.0, 0.0) / 4.5;
    d = 1.0 - sqrt(length(O * O));
    z += d;
  }
  return vec2(O.x, atan(O.z, O.y));
}

void mainImage(out vec4 o, vec2 C) {
  vec2 r = iResolution.xy;
  vec2 uv0 = (C + C - r) / r.x;
  float T = 0.1 * iTime * uSpeed + 9.0;
  float angRings = max(1.0, floor(6.28318530718 * max(uDensity, 0.05) + 0.5));
  vec2 Y = vec2(5e-3, 6.28318530718 / angRings);

  vec2 c0 = sceneC(C, r);
  vec2 cdx = sceneC(C + vec2(1.0, 0.0), r);
  vec2 cdy = sceneC(C + vec2(0.0, 1.0), r);
  vec2 dCx = cdx - c0;
  vec2 dCy = cdy - c0;
  dCx.y -= 6.28318530718 * floor(dCx.y / 6.28318530718 + 0.5);
  dCy.y -= 6.28318530718 * floor(dCy.y / 6.28318530718 + 0.5);
  vec2 fw = abs(dCx) + abs(dCy);
  C = c0;

  vec2 P = vec2(2.0, 1.0) * uv0 - (r / r.x) * vec2(0.0, 1.0);
  vec4 O = vec4(uBgColor * 90.0 * uBgGlow / (1e3 * dot(P, P) + 6.0), 0.0);

  float mGlow = 0.0;
  if (uMouseEnabled > 0.5) {
    vec2 mN = (iMouse + iMouse - r) / r.x;
    float md = length(uv0 - mN);
    mGlow = exp(-md * md / max(uMouseRadius * uMouseRadius, 1e-4)) * uMouseStrength;
    O.rgb += uMouseColor * mGlow * 0.25;
  }

  float zr = 5e-4 * uStreakWidth;
  vec2 rr = vec2(max(length(fw), 1e-5));
  float tail = 19.0 / max(uStreakLength, 0.05);

  for (int m = 0; m < 16; m++) {
    if (m >= uStreakCount) break;
    float jf = float(m) + 1.0;
    float ic = fract(sin(dot(vec2(jf, floor(C.x / Y.x + 0.5)), vec2(7.0, 11.0)) * 73.0));
    vec2 Pp = C - (T + T * ic) * vec2(0.0, 1.0);
    Pp -= floor(Pp / Y + 0.5) * Y;
    float h = fract(8663.0 * ic);
    vec3 col = palette(h);
    float weight = mix(1.5, 1.0 + sin(T + 7.0 * h + 4.0), uTwinkle);
    weight *= (1.0 + mGlow * 2.0);
    vec2 inner = vec2(length(max(Pp, vec2(-1.0, 0.0))), length(Pp) - zr) - zr;
    vec2 sm = vec2(1.0) - smoothstep(-rr, rr, inner);
    O.rgb += dot(sm, vec2(exp(tail * Pp.y), 3.0)) * col * weight;
    C.x += Y.x / 8.0;
  }

  vec3 colr = sqrt(tanhv(max(O.rgb * uGlow - vec3(0.04, 0.08, 0.02), 0.0)));
  o = vec4(colr, uOpacity);
}

void main() {
  vec4 color;
  mainImage(color, vUv * iResolution.xy);
  gl_FragColor = color;
}
`;

const Lightfall: React.FC<LightfallProps> = ({
  className,
  dpr,
  paused = false,
  colors = ['#A6C8FF', '#5227FF', '#FF9FFC'],
  backgroundColor = '#0A29FF',
  speed = 0.5,
  streakCount = 2,
  streakWidth = 1,
  streakLength = 1,
  glow = 1,
  density = 0.6,
  twinkle = 1,
  zoom = 3,
  backgroundGlow = 0.5,
  opacity = 1,
  mouseInteraction = true,
  mouseStrength = 0.5,
  mouseRadius = 1,
  mouseDampening = 0.15,
  mixBlendMode
}) => {
  const containerRef = useRef<HTMLDivElement | null>(null);
  const rafRef = useRef<number | null>(null);
  const programRef = useRef<Program | null>(null);
  const meshRef = useRef<Mesh | null>(null);
  const geometryRef = useRef<Triangle | null>(null);
  const rendererRef = useRef<Renderer | null>(null);
  const mouseTargetRef = useRef<[number, number]>([0, 0]);
  const lastTimeRef = useRef(0);

  useEffect(() => {
    const container = containerRef.current;
    if (!container) return;

    const renderer = new Renderer({
      dpr: dpr ?? (typeof window !== 'undefined' ? window.devicePixelRatio || 1 : 1),
      alpha: true,
      antialias: true
    });
    rendererRef.current = renderer;
    const gl = renderer.gl;
    const canvas = gl.canvas as HTMLCanvasElement;

    canvas.style.width = '100%';
    canvas.style.height = '100%';
    canvas.style.display = 'block';
    container.appendChild(canvas);

    const { arr, count, avg } = prepColors(colors);

    const uniforms = {
      iResolution: { value: [gl.drawingBufferWidth, gl.drawingBufferHeight, 1] },
      iMouse: { value: [0, 0] },
      iTime: { value: 0 },
      uColor0: { value: arr[0] },
      uColor1: { value: arr[1] },
      uColor2: { value: arr[2] },
      uColor3: { value: arr[3] },
      uColor4: { value: arr[4] },
      uColor5: { value: arr[5] },
      uColor6: { value: arr[6] },
      uColor7: { value: arr[7] },
      uColorCount: { value: count },
      uBgColor: { value: hexToRGB(backgroundColor) },
      uMouseColor: { value: avg },
      uSpeed: { value: speed },
      uStreakCount: { value: Math.max(1, Math.min(16, Math.round(streakCount))) },
      uStreakWidth: { value: streakWidth },
      uStreakLength: { value: streakLength },
      uGlow: { value: glow },
      uDensity: { value: density },
      uTwinkle: { value: twinkle },
      uZoom: { value: zoom },
      uBgGlow: { value: backgroundGlow },
      uOpacity: { value: opacity },
      uMouseEnabled: { value: mouseInteraction ? 1 : 0 },
      uMouseStrength: { value: mouseStrength },
      uMouseRadius: { value: mouseRadius }
    };

    const program = new Program(gl, { vertex, fragment, uniforms });
    programRef.current = program;

    const geometry = new Triangle(gl);
    geometryRef.current = geometry;
    const mesh = new Mesh(gl, { geometry, program });
    meshRef.current = mesh;

    const resize = () => {
      const rect = container.getBoundingClientRect();
      renderer.setSize(rect.width, rect.height);
      uniforms.iResolution.value = [gl.drawingBufferWidth, gl.drawingBufferHeight, 1];
    };

    resize();
    const ro = new ResizeObserver(resize);
    ro.observe(container);

    const onPointerMove = (e: PointerEvent) => {
      const rect = canvas.getBoundingClientRect();
      const scale = renderer.dpr || 1;
      const x = (e.clientX - rect.left) * scale;
      const y = (rect.height - (e.clientY - rect.top)) * scale;
      mouseTargetRef.current = [x, y];
      if (mouseDampening <= 0) {
        uniforms.iMouse.value = [x, y];
      }
    };
    if (mouseInteraction) {
      canvas.addEventListener('pointermove', onPointerMove);
    }

    const loop = (t: number) => {
      rafRef.current = requestAnimationFrame(loop);
      uniforms.iTime.value = t * 0.001;
      if (mouseDampening > 0) {
        if (!lastTimeRef.current) lastTimeRef.current = t;
        const dt = (t - lastTimeRef.current) / 1000;
        lastTimeRef.current = t;
        const tau = Math.max(1e-4, mouseDampening);
        let factor = 1 - Math.exp(-dt / tau);
        if (factor > 1) factor = 1;
        const target = mouseTargetRef.current;
        const cur = uniforms.iMouse.value as number[];
        cur[0] += (target[0] - cur[0]) * factor;
        cur[1] += (target[1] - cur[1]) * factor;
      } else {
        lastTimeRef.current = t;
      }
      if (!paused && programRef.current && meshRef.current) {
        try {
          renderer.render({ scene: meshRef.current });
        } catch (e) {
          console.error(e);
        }
      }
    };
    rafRef.current = requestAnimationFrame(loop);

    return () => {
      if (rafRef.current) cancelAnimationFrame(rafRef.current);
      if (mouseInteraction) canvas.removeEventListener('pointermove', onPointerMove);
      ro.disconnect();
      if (canvas.parentElement === container) {
        container.removeChild(canvas);
      }
      const callIfFn = (obj: unknown, key: string) => {
        const fn = obj && (obj as Record<string, unknown>)[key];
        if (typeof fn === 'function') {
          (fn as () => void).call(obj);
        }
      };
      callIfFn(programRef.current, 'remove');
      callIfFn(geometryRef.current, 'remove');
      callIfFn(meshRef.current, 'remove');
      callIfFn(rendererRef.current, 'destroy');
      programRef.current = null;
      geometryRef.current = null;
      meshRef.current = null;
      rendererRef.current = null;
    };
  }, [
    dpr,
    paused,
    colors,
    backgroundColor,
    speed,
    streakCount,
    streakWidth,
    streakLength,
    glow,
    density,
    twinkle,
    zoom,
    backgroundGlow,
    opacity,
    mouseInteraction,
    mouseStrength,
    mouseRadius,
    mouseDampening
  ]);

  return (
    <div
      ref={containerRef}
      className={`w-full h-full overflow-hidden relative ${className ?? ''}`}
      style={{
        ...(mixBlendMode && { mixBlendMode: mixBlendMode as React.CSSProperties['mixBlendMode'] })
      }}
    />
  );
};

export default Lightfall;


--- FILE: frontend-web/registry/backgrounds/Liquid Ether.tsx ---

import React, { useEffect, useRef } from 'react';
import * as THREE from 'three';

export interface LiquidEtherProps {
  mouseForce?: number;
  cursorSize?: number;
  isViscous?: boolean;
  viscous?: number;
  iterationsViscous?: number;
  iterationsPoisson?: number;
  dt?: number;
  BFECC?: boolean;
  resolution?: number;
  isBounce?: boolean;
  colors?: string[];
  style?: React.CSSProperties;
  className?: string;
  autoDemo?: boolean;
  autoSpeed?: number;
  autoIntensity?: number;
  takeoverDuration?: number;
  autoResumeDelay?: number;
  autoRampDuration?: number;
}

interface SimOptions {
  iterations_poisson: number;
  iterations_viscous: number;
  mouse_force: number;
  resolution: number;
  cursor_size: number;
  viscous: number;
  isBounce: boolean;
  dt: number;
  isViscous: boolean;
  BFECC: boolean;
}

interface LiquidEtherWebGL {
  output?: { simulation?: { options: SimOptions; resize: () => void } };
  autoDriver?: {
    enabled: boolean;
    speed: number;
    resumeDelay: number;
    rampDurationMs: number;
    mouse?: { autoIntensity: number; takeoverDuration: number };
    forceStop: () => void;
  };
  resize: () => void;
  start: () => void;
  pause: () => void;
  dispose: () => void;
}

const defaultColors = ['#5227FF', '#FF9FFC', '#B497CF'];

export default function LiquidEther({
  mouseForce = 20,
  cursorSize = 100,
  isViscous = false,
  viscous = 30,
  iterationsViscous = 32,
  iterationsPoisson = 32,
  dt = 0.014,
  BFECC = true,
  resolution = 0.5,
  isBounce = false,
  colors = defaultColors,
  style = {},
  className = '',
  autoDemo = true,
  autoSpeed = 0.5,
  autoIntensity = 2.2,
  takeoverDuration = 0.25,
  autoResumeDelay = 1000,
  autoRampDuration = 0.6
}: LiquidEtherProps): React.ReactElement {
  const mountRef = useRef<HTMLDivElement | null>(null);
  const webglRef = useRef<LiquidEtherWebGL | null>(null);
  const resizeObserverRef = useRef<ResizeObserver | null>(null);
  const rafRef = useRef<number | null>(null);
  const intersectionObserverRef = useRef<IntersectionObserver | null>(null);
  const isVisibleRef = useRef<boolean>(true);
  const resizeRafRef = useRef<number | null>(null);

  useEffect(() => {
    if (!mountRef.current) return;

    function makePaletteTexture(stops: string[]): THREE.DataTexture {
      let arr: string[];
      if (Array.isArray(stops) && stops.length > 0) {
        arr = stops.length === 1 ? [stops[0], stops[0]] : stops;
      } else {
        arr = ['#ffffff', '#ffffff'];
      }
      const w = arr.length;
      const data = new Uint8Array(w * 4);
      for (let i = 0; i < w; i++) {
        const c = new THREE.Color(arr[i]);
        data[i * 4 + 0] = Math.round(c.r * 255);
        data[i * 4 + 1] = Math.round(c.g * 255);
        data[i * 4 + 2] = Math.round(c.b * 255);
        data[i * 4 + 3] = 255;
      }
      const tex = new THREE.DataTexture(data, w, 1, THREE.RGBAFormat);
      tex.magFilter = THREE.LinearFilter;
      tex.minFilter = THREE.LinearFilter;
      tex.wrapS = THREE.ClampToEdgeWrapping;
      tex.wrapT = THREE.ClampToEdgeWrapping;
      tex.generateMipmaps = false;
      tex.needsUpdate = true;
      return tex;
    }

    const paletteTex = makePaletteTexture(colors);
    // Hard-code transparent background vector (alpha 0)
    const bgVec4 = new THREE.Vector4(0, 0, 0, 0);

    class CommonClass {
      width = 0;
      height = 0;
      aspect = 1;
      pixelRatio = 1;
      isMobile = false;
      breakpoint = 768;
      fboWidth: number | null = null;
      fboHeight: number | null = null;
      time = 0;
      delta = 0;
      container: HTMLElement | null = null;
      renderer: THREE.WebGLRenderer | null = null;
      clock: THREE.Clock | null = null;
      init(container: HTMLElement) {
        this.container = container;
        this.pixelRatio = Math.min(window.devicePixelRatio || 1, 2);
        this.resize();
        this.renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
        // Always transparent
        this.renderer.autoClear = false;
        this.renderer.setClearColor(new THREE.Color(0x000000), 0);
        this.renderer.setPixelRatio(this.pixelRatio);
        this.renderer.setSize(this.width, this.height);
        const el = this.renderer.domElement;
        el.style.width = '100%';
        el.style.height = '100%';
        el.style.display = 'block';
        this.clock = new THREE.Clock();
        this.clock.start();
      }
      resize() {
        if (!this.container) return;
        const rect = this.container.getBoundingClientRect();
        this.width = Math.max(1, Math.floor(rect.width));
        this.height = Math.max(1, Math.floor(rect.height));
        this.aspect = this.width / this.height;
        if (this.renderer) this.renderer.setSize(this.width, this.height, false);
      }
      update() {
        if (!this.clock) return;
        this.delta = this.clock.getDelta();
        this.time += this.delta;
      }
    }
    const Common = new CommonClass();

    class MouseClass {
      mouseMoved = false;
      coords = new THREE.Vector2();
      coords_old = new THREE.Vector2();
      diff = new THREE.Vector2();
      timer: number | null = null;
      container: HTMLElement | null = null;
      docTarget: Document | null = null;
      listenerTarget: Window | null = null;
      isHoverInside = false;
      hasUserControl = false;
      isAutoActive = false;
      autoIntensity = 2.0;
      takeoverActive = false;
      takeoverStartTime = 0;
      takeoverDuration = 0.25;
      takeoverFrom = new THREE.Vector2();
      takeoverTo = new THREE.Vector2();
      onInteract: (() => void) | null = null;
      private _onMouseMove = this.onDocumentMouseMove.bind(this);
      private _onTouchStart = this.onDocumentTouchStart.bind(this);
      private _onTouchMove = this.onDocumentTouchMove.bind(this);
      private _onTouchEnd = this.onTouchEnd.bind(this);
      private _onDocumentLeave = this.onDocumentLeave.bind(this);
      init(container: HTMLElement) {
        this.container = container;
        this.docTarget = container.ownerDocument || null;
        const defaultView = this.docTarget?.defaultView || (typeof window !== 'undefined' ? window : null);
        if (!defaultView) return;
        this.listenerTarget = defaultView;
        this.listenerTarget.addEventListener('mousemove', this._onMouseMove);
        this.listenerTarget.addEventListener('touchstart', this._onTouchStart, {
          passive: true
        });
        this.listenerTarget.addEventListener('touchmove', this._onTouchMove, {
          passive: true
        });
        this.listenerTarget.addEventListener('touchend', this._onTouchEnd);
        this.docTarget?.addEventListener('mouseleave', this._onDocumentLeave);
      }
      dispose() {
        if (this.listenerTarget) {
          this.listenerTarget.removeEventListener('mousemove', this._onMouseMove);
          this.listenerTarget.removeEventListener('touchstart', this._onTouchStart);
          this.listenerTarget.removeEventListener('touchmove', this._onTouchMove);
          this.listenerTarget.removeEventListener('touchend', this._onTouchEnd);
        }
        if (this.docTarget) {
          this.docTarget.removeEventListener('mouseleave', this._onDocumentLeave);
        }
        this.listenerTarget = null;
        this.docTarget = null;
        this.container = null;
      }
      private isPointInside(clientX: number, clientY: number) {
        if (!this.container) return false;
        const rect = this.container.getBoundingClientRect();
        if (rect.width === 0 || rect.height === 0) return false;
        return clientX >= rect.left && clientX <= rect.right && clientY >= rect.top && clientY <= rect.bottom;
      }
      private updateHoverState(clientX: number, clientY: number) {
        this.isHoverInside = this.isPointInside(clientX, clientY);
        return this.isHoverInside;
      }
      setCoords(x: number, y: number) {
        if (!this.container) return;
        if (this.timer) window.clearTimeout(this.timer);
        const rect = this.container.getBoundingClientRect();
        if (rect.width === 0 || rect.height === 0) return;
        const nx = (x - rect.left) / rect.width;
        const ny = (y - rect.top) / rect.height;
        this.coords.set(nx * 2 - 1, -(ny * 2 - 1));
        this.mouseMoved = true;
        this.timer = window.setTimeout(() => {
          this.mouseMoved = false;
        }, 100);
      }
      setNormalized(nx: number, ny: number) {
        this.coords.set(nx, ny);
        this.mouseMoved = true;
      }
      onDocumentMouseMove(event: MouseEvent) {
        if (!this.updateHoverState(event.clientX, event.clientY)) return;
        if (this.onInteract) this.onInteract();
        if (this.isAutoActive && !this.hasUserControl && !this.takeoverActive) {
          if (!this.container) return;
          const rect = this.container.getBoundingClientRect();
          const nx = (event.clientX - rect.left) / rect.width;
          const ny = (event.clientY - rect.top) / rect.height;
          this.takeoverFrom.copy(this.coords);
          this.takeoverTo.set(nx * 2 - 1, -(ny * 2 - 1));
          this.takeoverStartTime = performance.now();
          this.takeoverActive = true;
          this.hasUserControl = true;
          this.isAutoActive = false;
          return;
        }
        this.setCoords(event.clientX, event.clientY);
        this.hasUserControl = true;
      }
      onDocumentTouchStart(event: TouchEvent) {
        if (event.touches.length !== 1) return;
        const t = event.touches[0];
        if (!this.updateHoverState(t.clientX, t.clientY)) return;
        if (this.onInteract) this.onInteract();
        this.setCoords(t.clientX, t.clientY);
        this.hasUserControl = true;
      }
      onDocumentTouchMove(event: TouchEvent) {
        if (event.touches.length !== 1) return;
        const t = event.touches[0];
        if (!this.updateHoverState(t.clientX, t.clientY)) return;
        if (this.onInteract) this.onInteract();
        this.setCoords(t.clientX, t.clientY);
      }
      onTouchEnd() {
        this.isHoverInside = false;
      }
      onDocumentLeave() {
        this.isHoverInside = false;
      }
      update() {
        if (this.takeoverActive) {
          const t = (performance.now() - this.takeoverStartTime) / (this.takeoverDuration * 1000);
          if (t >= 1) {
            this.takeoverActive = false;
            this.coords.copy(this.takeoverTo);
            this.coords_old.copy(this.coords);
            this.diff.set(0, 0);
          } else {
            const k = t * t * (3 - 2 * t);
            this.coords.copy(this.takeoverFrom).lerp(this.takeoverTo, k);
          }
        }
        this.diff.subVectors(this.coords, this.coords_old);
        this.coords_old.copy(this.coords);
        if (this.coords_old.x === 0 && this.coords_old.y === 0) this.diff.set(0, 0);
        if (this.isAutoActive && !this.takeoverActive) this.diff.multiplyScalar(this.autoIntensity);
      }
    }
    const Mouse = new MouseClass();

    class AutoDriver {
      mouse: MouseClass;
      manager: WebGLManager;
      enabled: boolean;
      speed: number;
      resumeDelay: number;
      rampDurationMs: number;
      active = false;
      current = new THREE.Vector2(0, 0);
      target = new THREE.Vector2();
      lastTime = performance.now();
      activationTime = 0;
      margin = 0.2;
      private _tmpDir = new THREE.Vector2();
      constructor(
        mouse: MouseClass,
        manager: WebGLManager,
        opts: { enabled: boolean; speed: number; resumeDelay: number; rampDuration: number }
      ) {
        this.mouse = mouse;
        this.manager = manager;
        this.enabled = opts.enabled;
        this.speed = opts.speed;
        this.resumeDelay = opts.resumeDelay || 3000;
        this.rampDurationMs = (opts.rampDuration || 0) * 1000;
        this.pickNewTarget();
      }
      pickNewTarget() {
        const r = Math.random;
        this.target.set((r() * 2 - 1) * (1 - this.margin), (r() * 2 - 1) * (1 - this.margin));
      }
      forceStop() {
        this.active = false;
        this.mouse.isAutoActive = false;
      }
      update() {
        if (!this.enabled) return;
        const now = performance.now();
        const idle = now - this.manager.lastUserInteraction;
        if (idle < this.resumeDelay) {
          if (this.active) this.forceStop();
          return;
        }
        if (this.mouse.isHoverInside) {
          if (this.active) this.forceStop();
          return;
        }
        if (!this.active) {
          this.active = true;
          this.current.copy(this.mouse.coords);
          this.lastTime = now;
          this.activationTime = now;
        }
        if (!this.active) return;
        this.mouse.isAutoActive = true;
        let dtSec = (now - this.lastTime) / 1000;
        this.lastTime = now;
        if (dtSec > 0.2) dtSec = 0.016;
        const dir = this._tmpDir.subVectors(this.target, this.current);
        const dist = dir.length();
        if (dist < 0.01) {
          this.pickNewTarget();
          return;
        }
        dir.normalize();
        let ramp = 1;
        if (this.rampDurationMs > 0) {
          const t = Math.min(1, (now - this.activationTime) / this.rampDurationMs);
          ramp = t * t * (3 - 2 * t);
        }
        const step = this.speed * dtSec * ramp;
        const move = Math.min(step, dist);
        this.current.addScaledVector(dir, move);
        this.mouse.setNormalized(this.current.x, this.current.y);
      }
    }

    const face_vert = `
  attribute vec3 position;
  uniform vec2 px;
  uniform vec2 boundarySpace;
  varying vec2 uv;
  precision highp float;
  void main(){
  vec3 pos = position;
  vec2 scale = 1.0 - boundarySpace * 2.0;
  pos.xy = pos.xy * scale;
  uv = vec2(0.5)+(pos.xy)*0.5;
  gl_Position = vec4(pos, 1.0);
}
`;
    const line_vert = `
  attribute vec3 position;
  uniform vec2 px;
  precision highp float;
  varying vec2 uv;
  void main(){
  vec3 pos = position;
  uv = 0.5 + pos.xy * 0.5;
  vec2 n = sign(pos.xy);
  pos.xy = abs(pos.xy) - px * 1.0;
  pos.xy *= n;
  gl_Position = vec4(pos, 1.0);
}
`;
    const mouse_vert = `
    precision highp float;
    attribute vec3 position;
    attribute vec2 uv;
    uniform vec2 center;
    uniform vec2 scale;
    uniform vec2 px;
    varying vec2 vUv;
    void main(){
    vec2 pos = position.xy * scale * 2.0 * px + center;
    vUv = uv;
    gl_Position = vec4(pos, 0.0, 1.0);
}
`;
    const advection_frag = `
    precision highp float;
    uniform sampler2D velocity;
    uniform float dt;
    uniform bool isBFECC;
    uniform vec2 fboSize;
    uniform vec2 px;
    varying vec2 uv;
    void main(){
    vec2 ratio = max(fboSize.x, fboSize.y) / fboSize;
    if(isBFECC == false){
        vec2 vel = texture2D(velocity, uv).xy;
        vec2 uv2 = uv - vel * dt * ratio;
        vec2 newVel = texture2D(velocity, uv2).xy;
        gl_FragColor = vec4(newVel, 0.0, 0.0);
    } else {
        vec2 spot_new = uv;
        vec2 vel_old = texture2D(velocity, uv).xy;
        vec2 spot_old = spot_new - vel_old * dt * ratio;
        vec2 vel_new1 = texture2D(velocity, spot_old).xy;
        vec2 spot_new2 = spot_old + vel_new1 * dt * ratio;
        vec2 error = spot_new2 - spot_new;
        vec2 spot_new3 = spot_new - error / 2.0;
        vec2 vel_2 = texture2D(velocity, spot_new3).xy;
        vec2 spot_old2 = spot_new3 - vel_2 * dt * ratio;
        vec2 newVel2 = texture2D(velocity, spot_old2).xy; 
        gl_FragColor = vec4(newVel2, 0.0, 0.0);
    }
}
`;
    const color_frag = `
    precision highp float;
    uniform sampler2D velocity;
    uniform sampler2D palette;
    uniform vec4 bgColor;
    varying vec2 uv;
    void main(){
    vec2 vel = texture2D(velocity, uv).xy;
    float lenv = clamp(length(vel), 0.0, 1.0);
    vec3 c = texture2D(palette, vec2(lenv, 0.5)).rgb;
    vec3 outRGB = mix(bgColor.rgb, c, lenv);
    float outA = mix(bgColor.a, 1.0, lenv);
    gl_FragColor = vec4(outRGB, outA);
}
`;
    const divergence_frag = `
    precision highp float;
    uniform sampler2D velocity;
    uniform float dt;
    uniform vec2 px;
    varying vec2 uv;
    void main(){
    float x0 = texture2D(velocity, uv-vec2(px.x, 0.0)).x;
    float x1 = texture2D(velocity, uv+vec2(px.x, 0.0)).x;
    float y0 = texture2D(velocity, uv-vec2(0.0, px.y)).y;
    float y1 = texture2D(velocity, uv+vec2(0.0, px.y)).y;
    float divergence = (x1 - x0 + y1 - y0) / 2.0;
    gl_FragColor = vec4(divergence / dt);
}
`;
    const externalForce_frag = `
    precision highp float;
    uniform vec2 force;
    uniform vec2 center;
    uniform vec2 scale;
    uniform vec2 px;
    varying vec2 vUv;
    void main(){
    vec2 circle = (vUv - 0.5) * 2.0;
    float d = 1.0 - min(length(circle), 1.0);
    d *= d;
    gl_FragColor = vec4(force * d, 0.0, 1.0);
}
`;
    const poisson_frag = `
    precision highp float;
    uniform sampler2D pressure;
    uniform sampler2D divergence;
    uniform vec2 px;
    varying vec2 uv;
    void main(){
    float p0 = texture2D(pressure, uv + vec2(px.x * 2.0, 0.0)).r;
    float p1 = texture2D(pressure, uv - vec2(px.x * 2.0, 0.0)).r;
    float p2 = texture2D(pressure, uv + vec2(0.0, px.y * 2.0)).r;
    float p3 = texture2D(pressure, uv - vec2(0.0, px.y * 2.0)).r;
    float div = texture2D(divergence, uv).r;
    float newP = (p0 + p1 + p2 + p3) / 4.0 - div;
    gl_FragColor = vec4(newP);
}
`;
    const pressure_frag = `
    precision highp float;
    uniform sampler2D pressure;
    uniform sampler2D velocity;
    uniform vec2 px;
    uniform float dt;
    varying vec2 uv;
    void main(){
    float step = 1.0;
    float p0 = texture2D(pressure, uv + vec2(px.x * step, 0.0)).r;
    float p1 = texture2D(pressure, uv - vec2(px.x * step, 0.0)).r;
    float p2 = texture2D(pressure, uv + vec2(0.0, px.y * step)).r;
    float p3 = texture2D(pressure, uv - vec2(0.0, px.y * step)).r;
    vec2 v = texture2D(velocity, uv).xy;
    vec2 gradP = vec2(p0 - p1, p2 - p3) * 0.5;
    v = v - gradP * dt;
    gl_FragColor = vec4(v, 0.0, 1.0);
}
`;
    const viscous_frag = `
    precision highp float;
    uniform sampler2D velocity;
    uniform sampler2D velocity_new;
    uniform float v;
    uniform vec2 px;
    uniform float dt;
    varying vec2 uv;
    void main(){
    vec2 old = texture2D(velocity, uv).xy;
    vec2 new0 = texture2D(velocity_new, uv + vec2(px.x * 2.0, 0.0)).xy;
    vec2 new1 = texture2D(velocity_new, uv - vec2(px.x * 2.0, 0.0)).xy;
    vec2 new2 = texture2D(velocity_new, uv + vec2(0.0, px.y * 2.0)).xy;
    vec2 new3 = texture2D(velocity_new, uv - vec2(0.0, px.y * 2.0)).xy;
    vec2 newv = 4.0 * old + v * dt * (new0 + new1 + new2 + new3);
    newv /= 4.0 * (1.0 + v * dt);
    gl_FragColor = vec4(newv, 0.0, 0.0);
}
`;

    type Uniforms = Record<string, { value: any }>;

    class ShaderPass {
      props: any;
      uniforms?: Uniforms;
      scene: THREE.Scene | null = null;
      camera: THREE.Camera | null = null;
      material: THREE.RawShaderMaterial | null = null;
      geometry: THREE.BufferGeometry | null = null;
      plane: THREE.Mesh | null = null;
      constructor(props: any) {
        this.props = props || {};
        this.uniforms = this.props.material?.uniforms;
      }
      init(..._args: any[]) {
        this.scene = new THREE.Scene();
        this.camera = new THREE.Camera();
        if (this.uniforms) {
          this.material = new THREE.RawShaderMaterial(this.props.material);
          this.geometry = new THREE.PlaneGeometry(2, 2);
          this.plane = new THREE.Mesh(this.geometry, this.material);
          this.scene.add(this.plane);
        }
      }
      update(..._args: any[]) {
        if (!Common.renderer || !this.scene || !this.camera) return;
        Common.renderer.setRenderTarget(this.props.output || null);
        Common.renderer.render(this.scene, this.camera);
        Common.renderer.setRenderTarget(null);
      }
    }

    class Advection extends ShaderPass {
      line!: THREE.LineSegments;
      constructor(simProps: any) {
        super({
          material: {
            vertexShader: face_vert,
            fragmentShader: advection_frag,
            uniforms: {
              boundarySpace: { value: simProps.cellScale },
              px: { value: simProps.cellScale },
              fboSize: { value: simProps.fboSize },
              velocity: { value: simProps.src.texture },
              dt: { value: simProps.dt },
              isBFECC: { value: true }
            }
          },
          output: simProps.dst
        });
        this.uniforms = this.props.material.uniforms;
        this.init();
      }
      init() {
        super.init();
        this.createBoundary();
      }
      createBoundary() {
        const boundaryG = new THREE.BufferGeometry();
        const vertices_boundary = new Float32Array([
          -1, -1, 0, -1, 1, 0, -1, 1, 0, 1, 1, 0, 1, 1, 0, 1, -1, 0, 1, -1, 0, -1, -1, 0
        ]);
        boundaryG.setAttribute('position', new THREE.BufferAttribute(vertices_boundary, 3));
        const boundaryM = new THREE.RawShaderMaterial({
          vertexShader: line_vert,
          fragmentShader: advection_frag,
          uniforms: this.uniforms!
        });
        this.line = new THREE.LineSegments(boundaryG, boundaryM);
        this.scene!.add(this.line);
      }
      update(...args: any[]) {
        const { dt, isBounce, BFECC } = (args[0] || {}) as { dt?: number; isBounce?: boolean; BFECC?: boolean };
        if (!this.uniforms) return;
        if (typeof dt === 'number') this.uniforms.dt.value = dt;
        if (typeof isBounce === 'boolean') this.line.visible = isBounce;
        if (typeof BFECC === 'boolean') this.uniforms.isBFECC.value = BFECC;
        super.update();
      }
    }

    class ExternalForce extends ShaderPass {
      mouse!: THREE.Mesh;
      constructor(simProps: any) {
        super({ output: simProps.dst });
        this.init(simProps);
      }
      init(simProps: any) {
        super.init();
        const mouseG = new THREE.PlaneGeometry(1, 1);
        const mouseM = new THREE.RawShaderMaterial({
          vertexShader: mouse_vert,
          fragmentShader: externalForce_frag,
          blending: THREE.AdditiveBlending,
          depthWrite: false,
          uniforms: {
            px: { value: simProps.cellScale },
            force: { value: new THREE.Vector2(0, 0) },
            center: { value: new THREE.Vector2(0, 0) },
            scale: { value: new THREE.Vector2(simProps.cursor_size, simProps.cursor_size) }
          }
        });
        this.mouse = new THREE.Mesh(mouseG, mouseM);
        this.scene!.add(this.mouse);
      }
      update(...args: any[]) {
        const props = args[0] || {};
        const forceX = (Mouse.diff.x / 2) * (props.mouse_force || 0);
        const forceY = (Mouse.diff.y / 2) * (props.mouse_force || 0);
        const cellScale = props.cellScale || { x: 1, y: 1 };
        const cursorSize = props.cursor_size || 0;
        const cursorSizeX = cursorSize * cellScale.x;
        const cursorSizeY = cursorSize * cellScale.y;
        const centerX = Math.min(
          Math.max(Mouse.coords.x, -1 + cursorSizeX + cellScale.x * 2),
          1 - cursorSizeX - cellScale.x * 2
        );
        const centerY = Math.min(
          Math.max(Mouse.coords.y, -1 + cursorSizeY + cellScale.y * 2),
          1 - cursorSizeY - cellScale.y * 2
        );
        const uniforms = (this.mouse.material as THREE.RawShaderMaterial).uniforms;
        uniforms.force.value.set(forceX, forceY);
        uniforms.center.value.set(centerX, centerY);
        uniforms.scale.value.set(cursorSize, cursorSize);
        super.update();
      }
    }

    class Viscous extends ShaderPass {
      constructor(simProps: any) {
        super({
          material: {
            vertexShader: face_vert,
            fragmentShader: viscous_frag,
            uniforms: {
              boundarySpace: { value: simProps.boundarySpace },
              velocity: { value: simProps.src.texture },
              velocity_new: { value: simProps.dst_.texture },
              v: { value: simProps.viscous },
              px: { value: simProps.cellScale },
              dt: { value: simProps.dt }
            }
          },
          output: simProps.dst,
          output0: simProps.dst_,
          output1: simProps.dst
        });
        this.init();
      }
      update(...args: any[]) {
        const { viscous, iterations, dt } = (args[0] || {}) as { viscous?: number; iterations?: number; dt?: number };
        if (!this.uniforms) return;
        let fbo_in: any, fbo_out: any;
        if (typeof viscous === 'number') this.uniforms.v.value = viscous;
        const iter = iterations ?? 0;
        for (let i = 0; i < iter; i++) {
          if (i % 2 === 0) {
            fbo_in = this.props.output0;
            fbo_out = this.props.output1;
          } else {
            fbo_in = this.props.output1;
            fbo_out = this.props.output0;
          }
          this.uniforms.velocity_new.value = fbo_in.texture;
          this.props.output = fbo_out;
          if (typeof dt === 'number') this.uniforms.dt.value = dt;
          super.update();
        }
        return fbo_out;
      }
    }

    class Divergence extends ShaderPass {
      constructor(simProps: any) {
        super({
          material: {
            vertexShader: face_vert,
            fragmentShader: divergence_frag,
            uniforms: {
              boundarySpace: { value: simProps.boundarySpace },
              velocity: { value: simProps.src.texture },
              px: { value: simProps.cellScale },
              dt: { value: simProps.dt }
            }
          },
          output: simProps.dst
        });
        this.init();
      }
      update(...args: any[]) {
        const { vel } = (args[0] || {}) as { vel?: any };
        if (this.uniforms && vel) {
          this.uniforms.velocity.value = vel.texture;
        }
        super.update();
      }
    }

    class Poisson extends ShaderPass {
      constructor(simProps: any) {
        super({
          material: {
            vertexShader: face_vert,
            fragmentShader: poisson_frag,
            uniforms: {
              boundarySpace: { value: simProps.boundarySpace },
              pressure: { value: simProps.dst_.texture },
              divergence: { value: simProps.src.texture },
              px: { value: simProps.cellScale }
            }
          },
          output: simProps.dst,
          output0: simProps.dst_,
          output1: simProps.dst
        });
        this.init();
      }
      update(...args: any[]) {
        const { iterations } = (args[0] || {}) as { iterations?: number };
        let p_in: any, p_out: any;
        const iter = iterations ?? 0;
        for (let i = 0; i < iter; i++) {
          if (i % 2 === 0) {
            p_in = this.props.output0;
            p_out = this.props.output1;
          } else {
            p_in = this.props.output1;
            p_out = this.props.output0;
          }
          if (this.uniforms) this.uniforms.pressure.value = p_in.texture;
          this.props.output = p_out;
          super.update();
        }
        return p_out;
      }
    }

    class Pressure extends ShaderPass {
      constructor(simProps: any) {
        super({
          material: {
            vertexShader: face_vert,
            fragmentShader: pressure_frag,
            uniforms: {
              boundarySpace: { value: simProps.boundarySpace },
              pressure: { value: simProps.src_p.texture },
              velocity: { value: simProps.src_v.texture },
              px: { value: simProps.cellScale },
              dt: { value: simProps.dt }
            }
          },
          output: simProps.dst
        });
        this.init();
      }
      update(...args: any[]) {
        const { vel, pressure } = (args[0] || {}) as { vel?: any; pressure?: any };
        if (this.uniforms && vel && pressure) {
          this.uniforms.velocity.value = vel.texture;
          this.uniforms.pressure.value = pressure.texture;
        }
        super.update();
      }
    }

    class Simulation {
      options: SimOptions;
      fbos: Record<string, THREE.WebGLRenderTarget | null> = {
        vel_0: null,
        vel_1: null,
        vel_viscous0: null,
        vel_viscous1: null,
        div: null,
        pressure_0: null,
        pressure_1: null
      };
      fboSize = new THREE.Vector2();
      cellScale = new THREE.Vector2();
      boundarySpace = new THREE.Vector2();
      advection!: Advection;
      externalForce!: ExternalForce;
      viscous!: Viscous;
      divergence!: Divergence;
      poisson!: Poisson;
      pressure!: Pressure;
      constructor(options?: Partial<SimOptions>) {
        this.options = {
          iterations_poisson: 32,
          iterations_viscous: 32,
          mouse_force: 20,
          resolution: 0.5,
          cursor_size: 100,
          viscous: 30,
          isBounce: false,
          dt: 0.014,
          isViscous: false,
          BFECC: true,
          ...options
        };
        this.init();
      }
      init() {
        this.calcSize();
        this.createAllFBO();
        this.createShaderPass();
      }
      getFloatType() {
        const isIOS = /(iPad|iPhone|iPod)/i.test(navigator.userAgent);
        return isIOS ? THREE.HalfFloatType : THREE.FloatType;
      }
      createAllFBO() {
        const type = this.getFloatType();
        const opts = {
          type,
          depthBuffer: false,
          stencilBuffer: false,
          minFilter: THREE.LinearFilter,
          magFilter: THREE.LinearFilter,
          wrapS: THREE.ClampToEdgeWrapping,
          wrapT: THREE.ClampToEdgeWrapping
        } as const;
        for (const key in this.fbos) {
          this.fbos[key] = new THREE.WebGLRenderTarget(this.fboSize.x, this.fboSize.y, opts);
        }
      }
      createShaderPass() {
        this.advection = new Advection({
          cellScale: this.cellScale,
          fboSize: this.fboSize,
          dt: this.options.dt,
          src: this.fbos.vel_0,
          dst: this.fbos.vel_1
        });
        this.externalForce = new ExternalForce({
          cellScale: this.cellScale,
          cursor_size: this.options.cursor_size,
          dst: this.fbos.vel_1
        });
        this.viscous = new Viscous({
          cellScale: this.cellScale,
          boundarySpace: this.boundarySpace,
          viscous: this.options.viscous,
          src: this.fbos.vel_1,
          dst: this.fbos.vel_viscous1,
          dst_: this.fbos.vel_viscous0,
          dt: this.options.dt
        });
        this.divergence = new Divergence({
          cellScale: this.cellScale,
          boundarySpace: this.boundarySpace,
          src: this.fbos.vel_viscous0,
          dst: this.fbos.div,
          dt: this.options.dt
        });
        this.poisson = new Poisson({
          cellScale: this.cellScale,
          boundarySpace: this.boundarySpace,
          src: this.fbos.div,
          dst: this.fbos.pressure_1,
          dst_: this.fbos.pressure_0
        });
        this.pressure = new Pressure({
          cellScale: this.cellScale,
          boundarySpace: this.boundarySpace,
          src_p: this.fbos.pressure_0,
          src_v: this.fbos.vel_viscous0,
          dst: this.fbos.vel_0,
          dt: this.options.dt
        });
      }
      calcSize() {
        const width = Math.max(1, Math.round(this.options.resolution * Common.width));
        const height = Math.max(1, Math.round(this.options.resolution * Common.height));
        this.cellScale.set(1 / width, 1 / height);
        this.fboSize.set(width, height);
      }
      resize() {
        this.calcSize();
        for (const key in this.fbos) {
          this.fbos[key]!.setSize(this.fboSize.x, this.fboSize.y);
        }
      }
      update() {
        if (this.options.isBounce) this.boundarySpace.set(0, 0);
        else this.boundarySpace.copy(this.cellScale);
        this.advection.update({ dt: this.options.dt, isBounce: this.options.isBounce, BFECC: this.options.BFECC });
        this.externalForce.update({
          cursor_size: this.options.cursor_size,
          mouse_force: this.options.mouse_force,
          cellScale: this.cellScale
        });
        let vel: any = this.fbos.vel_1;
        if (this.options.isViscous) {
          vel = this.viscous.update({
            viscous: this.options.viscous,
            iterations: this.options.iterations_viscous,
            dt: this.options.dt
          });
        }
        this.divergence.update({ vel });
        const pressure = this.poisson.update({ iterations: this.options.iterations_poisson });
        this.pressure.update({ vel, pressure });
      }
    }

    class Output {
      simulation: Simulation;
      scene: THREE.Scene;
      camera: THREE.Camera;
      output: THREE.Mesh;
      constructor() {
        this.simulation = new Simulation();
        this.scene = new THREE.Scene();
        this.camera = new THREE.Camera();
        this.output = new THREE.Mesh(
          new THREE.PlaneGeometry(2, 2),
          new THREE.RawShaderMaterial({
            vertexShader: face_vert,
            fragmentShader: color_frag,
            transparent: true,
            depthWrite: false,
            uniforms: {
              velocity: { value: this.simulation.fbos.vel_0!.texture },
              boundarySpace: { value: new THREE.Vector2() },
              palette: { value: paletteTex },
              bgColor: { value: bgVec4 }
            }
          })
        );
        this.scene.add(this.output);
      }
      resize() {
        this.simulation.resize();
      }
      render() {
        if (!Common.renderer) return;
        Common.renderer.setRenderTarget(null);
        Common.renderer.render(this.scene, this.camera);
      }
      update() {
        this.simulation.update();
        this.render();
      }
    }

    class WebGLManager implements LiquidEtherWebGL {
      props: any;
      output!: Output;
      autoDriver?: AutoDriver;
      lastUserInteraction = performance.now();
      running = false;
      private _loop = this.loop.bind(this);
      private _resize = this.resize.bind(this);
      private _onVisibility?: () => void;
      constructor(props: any) {
        this.props = props;
        Common.init(props.$wrapper);
        Mouse.init(props.$wrapper);
        Mouse.autoIntensity = props.autoIntensity;
        Mouse.takeoverDuration = props.takeoverDuration;
        Mouse.onInteract = () => {
          this.lastUserInteraction = performance.now();
          if (this.autoDriver) this.autoDriver.forceStop();
        };
        this.autoDriver = new AutoDriver(Mouse, this as any, {
          enabled: props.autoDemo,
          speed: props.autoSpeed,
          resumeDelay: props.autoResumeDelay,
          rampDuration: props.autoRampDuration
        });
        this.init();
        window.addEventListener('resize', this._resize);
        this._onVisibility = () => {
          const hidden = document.hidden;
          if (hidden) {
            this.pause();
          } else if (isVisibleRef.current) {
            this.start();
          }
        };
        document.addEventListener('visibilitychange', this._onVisibility);
      }
      init() {
        if (!Common.renderer) return;
        this.props.$wrapper.prepend(Common.renderer.domElement);
        this.output = new Output();
      }
      resize() {
        Common.resize();
        this.output.resize();
      }
      render() {
        if (this.autoDriver) this.autoDriver.update();
        Mouse.update();
        Common.update();
        this.output.update();
      }
      loop() {
        if (!this.running) return;
        this.render();
        rafRef.current = requestAnimationFrame(this._loop);
      }
      start() {
        if (this.running) return;
        this.running = true;
        this._loop();
      }
      pause() {
        this.running = false;
        if (rafRef.current) {
          cancelAnimationFrame(rafRef.current);
          rafRef.current = null;
        }
      }
      dispose() {
        try {
          window.removeEventListener('resize', this._resize);
          if (this._onVisibility) document.removeEventListener('visibilitychange', this._onVisibility);
          Mouse.dispose();
          if (Common.renderer) {
            const canvas = Common.renderer.domElement;
            if (canvas && canvas.parentNode) canvas.parentNode.removeChild(canvas);
            Common.renderer.dispose();
            Common.renderer.forceContextLoss();
          }
        } catch {
          /* noop */
        }
      }
    }

    const container = mountRef.current;
    container.style.position = container.style.position || 'relative';
    container.style.overflow = container.style.overflow || 'hidden';

    const webgl = new WebGLManager({
      $wrapper: container,
      autoDemo,
      autoSpeed,
      autoIntensity,
      takeoverDuration,
      autoResumeDelay,
      autoRampDuration
    });
    webglRef.current = webgl;

    const applyOptionsFromProps = () => {
      if (!webglRef.current) return;
      const sim = webglRef.current.output?.simulation;
      if (!sim) return;
      const prevRes = sim.options.resolution;
      Object.assign(sim.options, {
        mouse_force: mouseForce,
        cursor_size: cursorSize,
        isViscous,
        viscous,
        iterations_viscous: iterationsViscous,
        iterations_poisson: iterationsPoisson,
        dt,
        BFECC,
        resolution,
        isBounce
      });
      if (resolution !== prevRes) sim.resize();
    };
    applyOptionsFromProps();
    webgl.start();

    const io = new IntersectionObserver(
      entries => {
        const entry = entries[0];
        const isVisible = entry.isIntersecting && entry.intersectionRatio > 0;
        isVisibleRef.current = isVisible;
        if (!webglRef.current) return;
        if (isVisible && !document.hidden) {
          webglRef.current.start();
        } else {
          webglRef.current.pause();
        }
      },
      { threshold: [0, 0.01, 0.1] }
    );
    io.observe(container);
    intersectionObserverRef.current = io;

    const ro = new ResizeObserver(() => {
      if (!webglRef.current) return;
      if (resizeRafRef.current) cancelAnimationFrame(resizeRafRef.current);
      resizeRafRef.current = requestAnimationFrame(() => {
        if (!webglRef.current) return;
        webglRef.current.resize();
      });
    });
    ro.observe(container);
    resizeObserverRef.current = ro;

    return () => {
      if (rafRef.current) cancelAnimationFrame(rafRef.current);
      if (resizeObserverRef.current) {
        try {
          resizeObserverRef.current.disconnect();
        } catch {
          /* noop */
        }
      }
      if (intersectionObserverRef.current) {
        try {
          intersectionObserverRef.current.disconnect();
        } catch {
          /* noop */
        }
      }
      if (webglRef.current) {
        webglRef.current.dispose();
      }
      webglRef.current = null;
    };
  }, [
    BFECC,
    cursorSize,
    dt,
    isBounce,
    isViscous,
    iterationsPoisson,
    iterationsViscous,
    mouseForce,
    resolution,
    viscous,
    colors,
    autoDemo,
    autoSpeed,
    autoIntensity,
    takeoverDuration,
    autoResumeDelay,
    autoRampDuration
  ]);

  useEffect(() => {
    const webgl = webglRef.current;
    if (!webgl) return;
    const sim = webgl.output?.simulation;
    if (!sim) return;
    const prevRes = sim.options.resolution;
    Object.assign(sim.options, {
      mouse_force: mouseForce,
      cursor_size: cursorSize,
      isViscous,
      viscous,
      iterations_viscous: iterationsViscous,
      iterations_poisson: iterationsPoisson,
      dt,
      BFECC,
      resolution,
      isBounce
    });
    if (webgl.autoDriver) {
      webgl.autoDriver.enabled = autoDemo;
      webgl.autoDriver.speed = autoSpeed;
      webgl.autoDriver.resumeDelay = autoResumeDelay;
      webgl.autoDriver.rampDurationMs = autoRampDuration * 1000;
      if (webgl.autoDriver.mouse) {
        webgl.autoDriver.mouse.autoIntensity = autoIntensity;
        webgl.autoDriver.mouse.takeoverDuration = takeoverDuration;
      }
    }
    if (resolution !== prevRes) sim.resize();
  }, [
    mouseForce,
    cursorSize,
    isViscous,
    viscous,
    iterationsViscous,
    iterationsPoisson,
    dt,
    BFECC,
    resolution,
    isBounce,
    autoDemo,
    autoSpeed,
    autoIntensity,
    takeoverDuration,
    autoResumeDelay,
    autoRampDuration
  ]);

  return (
    <div
      ref={mountRef}
      className={`w-full h-full relative overflow-hidden pointer-events-none touch-none ${className || ''}`}
      style={style}
    />
  );
}


--- FILE: frontend-web/registry/backgrounds/NeonMaze.tsx ---

import React, { useEffect, useRef } from "react";
import { cn } from "../core/utils";

export interface NeonMazeProps {
  className?: string;
  children?: React.ReactNode;
}

export const NeonMaze: React.FC<NeonMazeProps> = ({ className, children }) => {
  const containerRef = useRef<HTMLDivElement>(null);
  const canvasRef = useRef<HTMLCanvasElement>(null);

  useEffect(() => {
    const container = containerRef.current;
    const canvas = canvasRef.current;
    if (!container || !canvas) return;

    const x = canvas.getContext("2d");
    if (!x) return;

    let t = 0;
    let animationFrameId: number;

    const updateSize = () => {
      if (!container || !canvas) return;
      canvas.width = container.clientWidth;
      canvas.height = container.clientHeight;
    };

    const d = () => {
      if (!canvas || !x) return;
      const s = Math.min(canvas.width, canvas.height) / 15;
      const g = Math.ceil(canvas.width / s) * 2;
      const h = Math.ceil(canvas.height / (s * 0.5)) * 2;
      const w = canvas.width / 2;
      const v = canvas.height / 2;

      for (let y = -h; y < h; y++) {
        for (let i = -g; i < g; i++) {
          const p = w + ((i - y) * s) / 2;
          const q = v + ((i + y) * s) / 4;
          const m = Math.sqrt(i * i + y * y);
          const n = Math.sqrt(g * g + h * h);
          const e = 1 - m / n;
          const f = s * e * Math.abs(Math.sin(m * 0.5 + t));

          x.beginPath();
          x.moveTo(p, q - f);
          x.lineTo(p + s / 2, q - s / 2 - f);
          x.lineTo(p + s, q - f);
          x.lineTo(p + s, q);
          x.lineTo(p + s / 2, q + s / 2);
          x.lineTo(p, q);
          x.closePath();

          const l = x.createLinearGradient(p, q - f, p + s, q);
          l.addColorStop(0, "rgba(0,255,255,.8)");
          l.addColorStop(1, "rgba(255,0,255,.8)");
          x.fillStyle = l;
          x.fill();
          x.strokeStyle = "rgba(255,255,0,.5)";
          x.stroke();

          x.beginPath();
          x.moveTo(p, q);
          x.lineTo(p, q - f);
          x.moveTo(p + s, q);
          x.lineTo(p + s, q - f);
          x.moveTo(p + s / 2, q + s / 2);
          x.lineTo(p + s / 2, q - s / 2 - f);
          x.strokeStyle = "rgba(255,255,255,.3)";
          x.stroke();
        }
      }
    };

    const a = () => {
      if (!canvas || !x) return;
      x.fillStyle = "rgba(0,0,0,.1)";
      x.fillRect(0, 0, canvas.width, canvas.height);
      d();
      t += 0.05;
      animationFrameId = requestAnimationFrame(a);
    };

    // Initialize size and observe container changes
    updateSize();
    const resizeObserver = new ResizeObserver(() => {
      updateSize();
    });
    resizeObserver.observe(container);

    a();

    return () => {
      resizeObserver.disconnect();
      cancelAnimationFrame(animationFrameId);
    };
  }, []);

  return (
    <div
      ref={containerRef}
      className={cn("relative w-full h-full overflow-hidden bg-black", className)}
    >
      <canvas ref={canvasRef} className="absolute inset-0 block pointer-events-none" />
      {children && (
        <div className="relative z-10 w-full h-full flex items-center justify-center">
          {children}
        </div>
      )}
    </div>
  );
};

--- FILE: frontend-web/registry/backgrounds/Particles.tsx ---

import React, { useEffect, useRef, useState } from "react";
import { cn } from "../core/utils";

interface MousePosition {
  x: number;
  y: number;
}

function useMousePosition(): MousePosition {
  const [mousePosition, setMousePosition] = useState<MousePosition>({
    x: 0,
    y: 0,
  });

  useEffect(() => {
    const handleMouseMove = (event: MouseEvent) => {
      setMousePosition({ x: event.clientX, y: event.clientY });
    };

    window.addEventListener("mousemove", handleMouseMove);

    return () => {
      window.removeEventListener("mousemove", handleMouseMove);
    };
  }, []);

  return mousePosition;
}

interface ParticlesProps {
  className?: string;
  quantity?: number;
  staticity?: number;
  ease?: number;
  size?: number;
  refresh?: boolean;
  color?: string;
  vx?: number;
  vy?: number;
}

function hexToRgb(hex: string): number[] {
  hex = hex.replace("#", "");

  if (hex.length === 3) {
    hex = hex
      .split("")
      .map((char) => char + char)
      .join("");
  }

  const hexInt = parseInt(hex, 16);
  const red = (hexInt >> 16) & 255;
  const green = (hexInt >> 8) & 255;
  const blue = hexInt & 255;
  return [red, green, blue];
}

type Circle = {
  x: number;
  y: number;
  translateX: number;
  translateY: number;
  size: number;
  alpha: number;
  targetAlpha: number;
  dx: number;
  dy: number;
  magnetism: number;
};

const Particles: React.FC<ParticlesProps> = ({
  className = "",
  quantity = 100,
  staticity = 50,
  ease = 50,
  size = 0.4,
  refresh = false,
  color = "#ffffff",
  vx = 0,
  vy = 0,
}) => {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const canvasContainerRef = useRef<HTMLDivElement>(null);
  const context = useRef<CanvasRenderingContext2D | null>(null);
  const circles = useRef<Circle[]>([]);
  const mousePosition = useMousePosition();
  const mouse = useRef<{ x: number; y: number }>({ x: 0, y: 0 });
  const canvasSize = useRef<{ w: number; h: number }>({ w: 0, h: 0 });
  const dpr = typeof window !== "undefined" ? window.devicePixelRatio : 1;

  useEffect(() => {
    if (canvasRef.current) {
      context.current = canvasRef.current.getContext("2d");
    }
    initCanvas();
    animate();
    window.addEventListener("resize", initCanvas);

    return () => {
      window.removeEventListener("resize", initCanvas);
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [color]);

  useEffect(() => {
    onMouseMove();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [mousePosition.x, mousePosition.y]);

  useEffect(() => {
    initCanvas();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [refresh]);

  const initCanvas = () => {
    resizeCanvas();
    drawParticles();
  };

  const onMouseMove = () => {
    if (canvasRef.current) {
      const rect = canvasRef.current.getBoundingClientRect();
      const { w, h } = canvasSize.current;
      const x = mousePosition.x - rect.left - w / 2;
      const y = mousePosition.y - rect.top - h / 2;
      const inside = x < w / 2 && x > -w / 2 && y < h / 2 && y > -h / 2;
      if (inside) {
        mouse.current.x = x;
        mouse.current.y = y;
      }
    }
  };

  const resizeCanvas = () => {
    if (canvasContainerRef.current && canvasRef.current && context.current) {
      circles.current.length = 0;
      canvasSize.current.w = canvasContainerRef.current.offsetWidth;
      canvasSize.current.h = canvasContainerRef.current.offsetHeight;
      canvasRef.current.width = canvasSize.current.w * dpr;
      canvasRef.current.height = canvasSize.current.h * dpr;
      canvasRef.current.style.width = `${canvasSize.current.w}px`;
      canvasRef.current.style.height = `${canvasSize.current.h}px`;
      context.current.scale(dpr, dpr);
    }
  };

  const circleParams = (): Circle => {
    const x = Math.floor(Math.random() * canvasSize.current.w);
    const y = Math.floor(Math.random() * canvasSize.current.h);
    const translateX = 0;
    const translateY = 0;
    const pSize = Math.floor(Math.random() * 2) + size;
    const alpha = 0;
    const targetAlpha = parseFloat((Math.random() * 0.6 + 0.1).toFixed(1));
    const dx = (Math.random() - 0.5) * 0.1;
    const dy = (Math.random() - 0.5) * 0.1;
    const magnetism = 0.1 + Math.random() * 4;
    return {
      x,
      y,
      translateX,
      translateY,
      size: pSize,
      alpha,
      targetAlpha,
      dx,
      dy,
      magnetism,
    };
  };

  const rgb = hexToRgb(color);

  const drawCircle = (circle: Circle, update = false) => {
    if (context.current) {
      const { x, y, translateX, translateY, size, alpha } = circle;
      context.current.translate(translateX, translateY);
      context.current.beginPath();
      context.current.arc(x, y, size, 0, 2 * Math.PI);
      context.current.fillStyle = `rgba(${rgb.join(", ")}, ${alpha})`;
      context.current.fill();
      context.current.setTransform(dpr, 0, 0, dpr, 0, 0);

      if (!update) {
        circles.current.push(circle);
      }
    }
  };

  const clearContext = () => {
    if (context.current) {
      context.current.clearRect(
        0,
        0,
        canvasSize.current.w,
        canvasSize.current.h
      );
    }
  };

  const drawParticles = () => {
    clearContext();
    const particleCount = quantity;
    for (let i = 0; i < particleCount; i++) {
      const circle = circleParams();
      drawCircle(circle);
    }
  };

  const remapValue = (
    value: number,
    start1: number,
    end1: number,
    start2: number,
    end2: number
  ): number => {
    const remapped =
      ((value - start1) * (end2 - start2)) / (end1 - start1) + start2;
    return remapped > 0 ? remapped : 0;
  };

  const animate = () => {
    clearContext();
    circles.current.forEach((circle: Circle, i: number) => {
      // Handle the alpha value
      const edge = [
        circle.x + circle.translateX - circle.size, // distance from left edge
        canvasSize.current.w - circle.x - circle.translateX - circle.size, // distance from right edge
        circle.y + circle.translateY - circle.size, // distance from top edge
        canvasSize.current.h - circle.y - circle.translateY - circle.size, // distance from bottom edge
      ];
      const closestEdge = edge.reduce((a, b) => Math.min(a, b));
      const remapClosestEdge = parseFloat(
        remapValue(closestEdge, 0, 20, 0, 1).toFixed(2)
      );
      if (remapClosestEdge > 1) {
        circle.alpha += 0.02;
        if (circle.alpha > circle.targetAlpha) {
          circle.alpha = circle.targetAlpha;
        }
      } else {
        circle.alpha = circle.targetAlpha * remapClosestEdge;
      }
      circle.x += circle.dx + vx;
      circle.y += circle.dy + vy;
      circle.translateX +=
        (mouse.current.x / (staticity / circle.magnetism) - circle.translateX) /
        ease;
      circle.translateY +=
        (mouse.current.y / (staticity / circle.magnetism) - circle.translateY) /
        ease;

      drawCircle(circle, true);

      // circle gets out of the canvas
      if (
        circle.x < -circle.size ||
        circle.x > canvasSize.current.w + circle.size ||
        circle.y < -circle.size ||
        circle.y > canvasSize.current.h + circle.size
      ) {
        // remove the circle from the array
        circles.current.splice(i, 1);
        // create a new circle
        const newCircle = circleParams();
        drawCircle(newCircle);
      }
    });
    window.requestAnimationFrame(animate);
  };

  return (
    <div
      className={cn("pointer-events-none", className)}
      ref={canvasContainerRef}
      aria-hidden="true"
    >
      <canvas ref={canvasRef} className="w-full h-full" />
    </div>
  );
};

export { Particles };

--- FILE: frontend-web/registry/backgrounds/PixelTrail.tsx ---

import React, { useCallback, useMemo, useRef, useState, useEffect, useId } from "react";
import { motion, useAnimationControls } from "framer-motion";
import { cn } from "../core/utils";

// Inlined useDimensions hook to keep the component standalone
function useDimensions(ref: React.RefObject<HTMLElement | null>) {
  const [dimensions, setDimensions] = useState({ width: 0, height: 0 });

  useEffect(() => {
    const observeTarget = ref.current;
    if (!observeTarget) return;

    const resizeObserver = new ResizeObserver((entries) => {
      entries.forEach((entry) => {
        setDimensions({
          width: entry.contentRect.width,
          height: entry.contentRect.height,
        });
      });
    });

    resizeObserver.observe(observeTarget);
    
    // Initial size
    setDimensions({
      width: observeTarget.getBoundingClientRect().width,
      height: observeTarget.getBoundingClientRect().height,
    });

    return () => {
      resizeObserver.unobserve(observeTarget);
    };
  }, [ref]);

  return dimensions;
}

export interface PixelTrailProps {
  pixelSize?: number; // px
  fadeDuration?: number; // ms
  delay?: number; // ms
  className?: string;
  pixelClassName?: string;
}

export const PixelTrail: React.FC<PixelTrailProps> = ({
  pixelSize = 20,
  fadeDuration = 500,
  delay = 0,
  className,
  pixelClassName,
}) => {
  const containerRef = useRef<HTMLDivElement>(null);
  const dimensions = useDimensions(containerRef);
  const trailId = useId().replace(/:/g, ""); // Safe ID for DOM elements

  const handleMouseMove = useCallback(
    (e: React.MouseEvent<HTMLDivElement>) => {
      if (!containerRef.current) return;

      const rect = containerRef.current.getBoundingClientRect();
      const x = Math.floor((e.clientX - rect.left) / pixelSize);
      const y = Math.floor((e.clientY - rect.top) / pixelSize);

      const pixelElement = document.getElementById(
        `${trailId}-pixel-${x}-${y}`
      );
      if (pixelElement) {
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        const animatePixel = (pixelElement as any).__animatePixel;
        if (animatePixel) animatePixel();
      }
    },
    [pixelSize, trailId]
  );

  const columns = useMemo(
    () => Math.ceil(dimensions.width / pixelSize),
    [dimensions.width, pixelSize]
  );
  const rows = useMemo(
    () => Math.ceil(dimensions.height / pixelSize),
    [dimensions.height, pixelSize]
  );

  return (
    <div
      ref={containerRef}
      className={cn(
        "absolute inset-0 w-full h-full pointer-events-auto overflow-hidden",
        className
      )}
      onMouseMove={handleMouseMove}
    >
      {Array.from({ length: rows }).map((_, rowIndex) => (
        <div key={rowIndex} className="flex">
          {Array.from({ length: columns }).map((_, colIndex) => (
            <PixelDot
              key={`${colIndex}-${rowIndex}`}
              id={`${trailId}-pixel-${colIndex}-${rowIndex}`}
              size={pixelSize}
              fadeDuration={fadeDuration}
              delay={delay}
              className={pixelClassName}
            />
          ))}
        </div>
      ))}
    </div>
  );
};

interface PixelDotProps {
  id: string;
  size: number;
  fadeDuration: number;
  delay: number;
  className?: string;
}

const PixelDot: React.FC<PixelDotProps> = React.memo(
  ({ id, size, fadeDuration, delay, className }) => {
    const controls = useAnimationControls();

    const animatePixel = useCallback(() => {
      controls.start({
        opacity: [1, 0],
        transition: { duration: fadeDuration / 1000, delay: delay / 1000 },
      });
      // eslint-disable-next-line react-hooks/exhaustive-deps
    }, []);

    // Attach the animatePixel function to the DOM element so parent can trigger it
    const ref = useCallback(
      (node: HTMLDivElement | null) => {
        if (node) {
          // eslint-disable-next-line @typescript-eslint/no-explicit-any
          (node as any).__animatePixel = animatePixel;
        }
      },
      [animatePixel]
    );

    return (
      <motion.div
        id={id}
        ref={ref}
        className={cn("pointer-events-none", className)}
        style={{
          width: `${size}px`,
          height: `${size}px`,
        }}
        initial={{ opacity: 0 }}
        animate={controls}
        exit={{ opacity: 0 }}
      />
    );
  }
);

PixelDot.displayName = "PixelDot";

--- FILE: frontend-web/registry/backgrounds/Prism.tsx ---

import React, { useEffect, useRef } from 'react';
import { Renderer, Triangle, Program, Mesh } from 'ogl';

type PrismProps = {
  height?: number;
  baseWidth?: number;
  animationType?: 'rotate' | 'hover' | '3drotate';
  glow?: number;
  offset?: { x?: number; y?: number };
  noise?: number;
  transparent?: boolean;
  scale?: number;
  hueShift?: number;
  colorFrequency?: number;
  hoverStrength?: number;
  inertia?: number;
  bloom?: number;
  suspendWhenOffscreen?: boolean;
  timeScale?: number;
};

const Prism: React.FC<PrismProps> = ({
  height = 3.5,
  baseWidth = 5.5,
  animationType = 'rotate',
  glow = 1,
  offset = { x: 0, y: 0 },
  noise = 0.5,
  transparent = true,
  scale = 3.6,
  hueShift = 0,
  colorFrequency = 1,
  hoverStrength = 2,
  inertia = 0.05,
  bloom = 1,
  suspendWhenOffscreen = false,
  timeScale = 0.5
}) => {
  const containerRef = useRef<HTMLDivElement | null>(null);

  useEffect(() => {
    const container = containerRef.current;
    if (!container) return;

    const H = Math.max(0.001, height);
    const BW = Math.max(0.001, baseWidth);
    const BASE_HALF = BW * 0.5;
    const GLOW = Math.max(0.0, glow);
    const NOISE = Math.max(0.0, noise);
    const offX = offset?.x ?? 0;
    const offY = offset?.y ?? 0;
    const SAT = transparent ? 1.5 : 1;
    const SCALE = Math.max(0.001, scale);
    const HUE = hueShift || 0;
    const CFREQ = Math.max(0.0, colorFrequency || 1);
    const BLOOM = Math.max(0.0, bloom || 1);
    const RSX = 1;
    const RSY = 1;
    const RSZ = 1;
    const TS = Math.max(0, timeScale || 1);
    const HOVSTR = Math.max(0, hoverStrength || 1);
    const INERT = Math.max(0, Math.min(1, inertia || 0.12));

    const dpr = Math.min(2, window.devicePixelRatio || 1);
    const renderer = new Renderer({
      dpr,
      alpha: transparent,
      antialias: false
    });
    const gl = renderer.gl;
    gl.disable(gl.DEPTH_TEST);
    gl.disable(gl.CULL_FACE);
    gl.disable(gl.BLEND);

    Object.assign(gl.canvas.style, {
      position: 'absolute',
      inset: '0',
      width: '100%',
      height: '100%',
      display: 'block'
    } as Partial<CSSStyleDeclaration>);
    container.appendChild(gl.canvas);

    const vertex = /* glsl */ `
      attribute vec2 position;
      void main() {
        gl_Position = vec4(position, 0.0, 1.0);
      }
    `;

    const fragment = /* glsl */ `
      precision highp float;

      uniform vec2  iResolution;
      uniform float iTime;

      uniform float uHeight;
      uniform float uBaseHalf;
      uniform mat3  uRot;
      uniform int   uUseBaseWobble;
      uniform float uGlow;
      uniform vec2  uOffsetPx;
      uniform float uNoise;
      uniform float uSaturation;
      uniform float uScale;
      uniform float uHueShift;
      uniform float uColorFreq;
      uniform float uBloom;
      uniform float uCenterShift;
      uniform float uInvBaseHalf;
      uniform float uInvHeight;
      uniform float uMinAxis;
      uniform float uPxScale;
      uniform float uTimeScale;

      vec4 tanh4(vec4 x){
        vec4 e2x = exp(2.0*x);
        return (e2x - 1.0) / (e2x + 1.0);
      }

      float rand(vec2 co){
        return fract(sin(dot(co, vec2(12.9898, 78.233))) * 43758.5453123);
      }

      float sdOctaAnisoInv(vec3 p){
        vec3 q = vec3(abs(p.x) * uInvBaseHalf, abs(p.y) * uInvHeight, abs(p.z) * uInvBaseHalf);
        float m = q.x + q.y + q.z - 1.0;
        return m * uMinAxis * 0.5773502691896258;
      }

      float sdPyramidUpInv(vec3 p){
        float oct = sdOctaAnisoInv(p);
        float halfSpace = -p.y;
        return max(oct, halfSpace);
      }

      mat3 hueRotation(float a){
        float c = cos(a), s = sin(a);
        mat3 W = mat3(
          0.299, 0.587, 0.114,
          0.299, 0.587, 0.114,
          0.299, 0.587, 0.114
        );
        mat3 U = mat3(
           0.701, -0.587, -0.114,
          -0.299,  0.413, -0.114,
          -0.300, -0.588,  0.886
        );
        mat3 V = mat3(
           0.168, -0.331,  0.500,
           0.328,  0.035, -0.500,
          -0.497,  0.296,  0.201
        );
        return W + U * c + V * s;
      }

      void main(){
        vec2 f = (gl_FragCoord.xy - 0.5 * iResolution.xy - uOffsetPx) * uPxScale;

        float z = 5.0;
        float d = 0.0;

        vec3 p;
        vec4 o = vec4(0.0);

        float centerShift = uCenterShift;
        float cf = uColorFreq;

        mat2 wob = mat2(1.0);
        if (uUseBaseWobble == 1) {
          float t = iTime * uTimeScale;
          float c0 = cos(t + 0.0);
          float c1 = cos(t + 33.0);
          float c2 = cos(t + 11.0);
          wob = mat2(c0, c1, c2, c0);
        }

        const int STEPS = 100;
        for (int i = 0; i < STEPS; i++) {
          p = vec3(f, z);
          p.xz = p.xz * wob;
          p = uRot * p;
          vec3 q = p;
          q.y += centerShift;
          d = 0.1 + 0.2 * abs(sdPyramidUpInv(q));
          z -= d;
          o += (sin((p.y + z) * cf + vec4(0.0, 1.0, 2.0, 3.0)) + 1.0) / d;
        }

        o = tanh4(o * o * (uGlow * uBloom) / 1e5);

        vec3 col = o.rgb;
        float n = rand(gl_FragCoord.xy + vec2(iTime));
        col += (n - 0.5) * uNoise;
        col = clamp(col, 0.0, 1.0);

        float L = dot(col, vec3(0.2126, 0.7152, 0.0722));
        col = clamp(mix(vec3(L), col, uSaturation), 0.0, 1.0);

        if(abs(uHueShift) > 0.0001){
          col = clamp(hueRotation(uHueShift) * col, 0.0, 1.0);
        }

        gl_FragColor = vec4(col, o.a);
      }
    `;

    const geometry = new Triangle(gl);
    const iResBuf = new Float32Array(2);
    const offsetPxBuf = new Float32Array(2);

    const program = new Program(gl, {
      vertex,
      fragment,
      uniforms: {
        iResolution: { value: iResBuf },
        iTime: { value: 0 },
        uHeight: { value: H },
        uBaseHalf: { value: BASE_HALF },
        uUseBaseWobble: { value: 1 },
        uRot: { value: new Float32Array([1, 0, 0, 0, 1, 0, 0, 0, 1]) },
        uGlow: { value: GLOW },
        uOffsetPx: { value: offsetPxBuf },
        uNoise: { value: NOISE },
        uSaturation: { value: SAT },
        uScale: { value: SCALE },
        uHueShift: { value: HUE },
        uColorFreq: { value: CFREQ },
        uBloom: { value: BLOOM },
        uCenterShift: { value: H * 0.25 },
        uInvBaseHalf: { value: 1 / BASE_HALF },
        uInvHeight: { value: 1 / H },
        uMinAxis: { value: Math.min(BASE_HALF, H) },
        uPxScale: {
          value: 1 / ((gl.drawingBufferHeight || 1) * 0.1 * SCALE)
        },
        uTimeScale: { value: TS }
      }
    });
    const mesh = new Mesh(gl, { geometry, program });

    const resize = () => {
      const w = container.clientWidth || 1;
      const h = container.clientHeight || 1;
      renderer.setSize(w, h);
      iResBuf[0] = gl.drawingBufferWidth;
      iResBuf[1] = gl.drawingBufferHeight;
      offsetPxBuf[0] = offX * dpr;
      offsetPxBuf[1] = offY * dpr;
      program.uniforms.uPxScale.value = 1 / ((gl.drawingBufferHeight || 1) * 0.1 * SCALE);
    };
    const ro = new ResizeObserver(resize);
    ro.observe(container);
    resize();

    const rotBuf = new Float32Array(9);
    const setMat3FromEuler = (yawY: number, pitchX: number, rollZ: number, out: Float32Array) => {
      const cy = Math.cos(yawY),
        sy = Math.sin(yawY);
      const cx = Math.cos(pitchX),
        sx = Math.sin(pitchX);
      const cz = Math.cos(rollZ),
        sz = Math.sin(rollZ);
      const r00 = cy * cz + sy * sx * sz;
      const r01 = -cy * sz + sy * sx * cz;
      const r02 = sy * cx;

      const r10 = cx * sz;
      const r11 = cx * cz;
      const r12 = -sx;

      const r20 = -sy * cz + cy * sx * sz;
      const r21 = sy * sz + cy * sx * cz;
      const r22 = cy * cx;

      out[0] = r00;
      out[1] = r10;
      out[2] = r20;
      out[3] = r01;
      out[4] = r11;
      out[5] = r21;
      out[6] = r02;
      out[7] = r12;
      out[8] = r22;
      return out;
    };

    const NOISE_IS_ZERO = NOISE < 1e-6;
    let raf = 0;
    const t0 = performance.now();
    const startRAF = () => {
      if (raf) return;
      raf = requestAnimationFrame(render);
    };
    const stopRAF = () => {
      if (!raf) return;
      cancelAnimationFrame(raf);
      raf = 0;
    };

    const rnd = () => Math.random();
    const wX = (0.3 + rnd() * 0.6) * RSX;
    const wY = (0.2 + rnd() * 0.7) * RSY;
    const wZ = (0.1 + rnd() * 0.5) * RSZ;
    const phX = rnd() * Math.PI * 2;
    const phZ = rnd() * Math.PI * 2;

    let yaw = 0,
      pitch = 0,
      roll = 0;
    let targetYaw = 0,
      targetPitch = 0;
    const lerp = (a: number, b: number, t: number) => a + (b - a) * t;

    const pointer = { x: 0, y: 0, inside: true };
    const onMove = (e: PointerEvent) => {
      const ww = Math.max(1, window.innerWidth);
      const wh = Math.max(1, window.innerHeight);
      const cx = ww * 0.5;
      const cy = wh * 0.5;
      const nx = (e.clientX - cx) / (ww * 0.5);
      const ny = (e.clientY - cy) / (wh * 0.5);
      pointer.x = Math.max(-1, Math.min(1, nx));
      pointer.y = Math.max(-1, Math.min(1, ny));
      pointer.inside = true;
    };
    const onLeave = () => {
      pointer.inside = false;
    };
    const onBlur = () => {
      pointer.inside = false;
    };

    let onPointerMove: ((e: PointerEvent) => void) | null = null;
    if (animationType === 'hover') {
      onPointerMove = (e: PointerEvent) => {
        onMove(e);
        startRAF();
      };
      window.addEventListener('pointermove', onPointerMove, { passive: true });
      window.addEventListener('mouseleave', onLeave);
      window.addEventListener('blur', onBlur);
      program.uniforms.uUseBaseWobble.value = 0;
    } else if (animationType === '3drotate') {
      program.uniforms.uUseBaseWobble.value = 0;
    } else {
      program.uniforms.uUseBaseWobble.value = 1;
    }

    const render = (t: number) => {
      const time = (t - t0) * 0.001;
      program.uniforms.iTime.value = time;

      let continueRAF = true;

      if (animationType === 'hover') {
        const maxPitch = 0.6 * HOVSTR;
        const maxYaw = 0.6 * HOVSTR;
        targetYaw = (pointer.inside ? -pointer.x : 0) * maxYaw;
        targetPitch = (pointer.inside ? pointer.y : 0) * maxPitch;
        const prevYaw = yaw;
        const prevPitch = pitch;
        const prevRoll = roll;
        yaw = lerp(prevYaw, targetYaw, INERT);
        pitch = lerp(prevPitch, targetPitch, INERT);
        roll = lerp(prevRoll, 0, 0.1);
        program.uniforms.uRot.value = setMat3FromEuler(yaw, pitch, roll, rotBuf);

        if (NOISE_IS_ZERO) {
          const settled =
            Math.abs(yaw - targetYaw) < 1e-4 && Math.abs(pitch - targetPitch) < 1e-4 && Math.abs(roll) < 1e-4;
          if (settled) continueRAF = false;
        }
      } else if (animationType === '3drotate') {
        const tScaled = time * TS;
        yaw = tScaled * wY;
        pitch = Math.sin(tScaled * wX + phX) * 0.6;
        roll = Math.sin(tScaled * wZ + phZ) * 0.5;
        program.uniforms.uRot.value = setMat3FromEuler(yaw, pitch, roll, rotBuf);
        if (TS < 1e-6) continueRAF = false;
      } else {
        rotBuf[0] = 1;
        rotBuf[1] = 0;
        rotBuf[2] = 0;
        rotBuf[3] = 0;
        rotBuf[4] = 1;
        rotBuf[5] = 0;
        rotBuf[6] = 0;
        rotBuf[7] = 0;
        rotBuf[8] = 1;
        program.uniforms.uRot.value = rotBuf;
        if (TS < 1e-6) continueRAF = false;
      }

      renderer.render({ scene: mesh });
      if (continueRAF) {
        raf = requestAnimationFrame(render);
      } else {
        raf = 0;
      }
    };

    interface PrismContainer extends HTMLElement {
      __prismIO?: IntersectionObserver;
    }

    if (suspendWhenOffscreen) {
      const io = new IntersectionObserver(entries => {
        const vis = entries.some(e => e.isIntersecting);
        if (vis) startRAF();
        else stopRAF();
      });
      io.observe(container);
      startRAF();
      (container as PrismContainer).__prismIO = io;
    } else {
      startRAF();
    }

    return () => {
      stopRAF();
      ro.disconnect();
      if (animationType === 'hover') {
        if (onPointerMove) window.removeEventListener('pointermove', onPointerMove as EventListener);
        window.removeEventListener('mouseleave', onLeave);
        window.removeEventListener('blur', onBlur);
      }
      if (suspendWhenOffscreen) {
        const io = (container as PrismContainer).__prismIO as IntersectionObserver | undefined;
        if (io) io.disconnect();
        delete (container as PrismContainer).__prismIO;
      }
      if (gl.canvas.parentElement === container) container.removeChild(gl.canvas);
    };
  }, [
    height,
    baseWidth,
    animationType,
    glow,
    noise,
    offset?.x,
    offset?.y,
    scale,
    transparent,
    hueShift,
    colorFrequency,
    timeScale,
    hoverStrength,
    inertia,
    bloom,
    suspendWhenOffscreen
  ]);

  return <div className="w-full h-full relative" ref={containerRef} />;
};

export default Prism;


--- FILE: frontend-web/registry/backgrounds/RetroGrid.tsx ---

import React from "react";
import { cn } from "../core/utils";

export interface RetroGridProps extends React.HTMLAttributes<HTMLDivElement> {
  className?: string;
  angle?: number;
}

export function RetroGrid({
  className,
  angle = 65,
  ...props
}: RetroGridProps) {
  return (
    <div
      className={cn(
        "pointer-events-none absolute size-full overflow-hidden opacity-50 [perspective:200px]",
        className
      )}
      style={{ "--grid-angle": `${angle}deg` } as React.CSSProperties}
      {...props}
    >
      <style>
        {`
          @keyframes retro-grid-anim {
            0% { transform: translateY(-50%); }
            100% { transform: translateY(0); }
          }
          .animate-grid {
            animation: retro-grid-anim 15s linear infinite;
          }
        `}
      </style>
      
      {/* Grid */}
      <div className="absolute inset-0 [transform:rotateX(var(--grid-angle))]">
        <div
          className={cn(
            "animate-grid",
            "[background-repeat:repeat] [background-size:60px_60px] [height:300vh] [inset:0%_0px] [margin-left:-50%] [transform-origin:100%_0_0] [width:600vw]",
            // Light Styles
            "[background-image:linear-gradient(to_right,rgba(0,0,0,0.3)_1px,transparent_0),linear-gradient(to_bottom,rgba(0,0,0,0.3)_1px,transparent_0)]",
            // Dark styles
            "dark:[background-image:linear-gradient(to_right,rgba(255,255,255,0.2)_1px,transparent_0),linear-gradient(to_bottom,rgba(255,255,255,0.2)_1px,transparent_0)]"
          )}
        />
      </div>

      {/* Background Gradient */}
      <div className="absolute inset-0 bg-gradient-to-t from-white to-transparent to-90% dark:from-black" />
    </div>
  );
}

--- FILE: frontend-web/registry/backgrounds/Silk.tsx ---

/* eslint-disable react/no-unknown-property */
import React, { forwardRef, useMemo, useRef, useLayoutEffect } from 'react';
import { Canvas, useFrame, useThree, RootState } from '@react-three/fiber';
import { Color, Mesh, ShaderMaterial } from 'three';
import { IUniform } from 'three';

type NormalizedRGB = [number, number, number];

const hexToNormalizedRGB = (hex: string): NormalizedRGB => {
  const clean = hex.replace('#', '');
  const r = parseInt(clean.slice(0, 2), 16) / 255;
  const g = parseInt(clean.slice(2, 4), 16) / 255;
  const b = parseInt(clean.slice(4, 6), 16) / 255;
  return [r, g, b];
};

interface UniformValue<T = number | Color> {
  value: T;
}

interface SilkUniforms {
  uSpeed: UniformValue<number>;
  uScale: UniformValue<number>;
  uNoiseIntensity: UniformValue<number>;
  uColor: UniformValue<Color>;
  uRotation: UniformValue<number>;
  uTime: UniformValue<number>;
  [uniform: string]: IUniform;
}

const vertexShader = `
varying vec2 vUv;
varying vec3 vPosition;

void main() {
  vPosition = position;
  vUv = uv;
  gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`;

const fragmentShader = `
varying vec2 vUv;
varying vec3 vPosition;

uniform float uTime;
uniform vec3  uColor;
uniform float uSpeed;
uniform float uScale;
uniform float uRotation;
uniform float uNoiseIntensity;

const float e = 2.71828182845904523536;

float noise(vec2 texCoord) {
  float G = e;
  vec2  r = (G * sin(G * texCoord));
  return fract(r.x * r.y * (1.0 + texCoord.x));
}

vec2 rotateUvs(vec2 uv, float angle) {
  float c = cos(angle);
  float s = sin(angle);
  mat2  rot = mat2(c, -s, s, c);
  return rot * uv;
}

void main() {
  float rnd        = noise(gl_FragCoord.xy);
  vec2  uv         = rotateUvs(vUv * uScale, uRotation);
  vec2  tex        = uv * uScale;
  float tOffset    = uSpeed * uTime;

  tex.y += 0.03 * sin(8.0 * tex.x - tOffset);

  float pattern = 0.6 +
                  0.4 * sin(5.0 * (tex.x + tex.y +
                                   cos(3.0 * tex.x + 5.0 * tex.y) +
                                   0.02 * tOffset) +
                           sin(20.0 * (tex.x + tex.y - 0.1 * tOffset)));

  vec4 col = vec4(uColor, 1.0) * vec4(pattern) - rnd / 15.0 * uNoiseIntensity;
  col.a = 1.0;
  gl_FragColor = col;
}
`;

interface SilkPlaneProps {
  uniforms: SilkUniforms;
}

const SilkPlane = forwardRef<Mesh, SilkPlaneProps>(function SilkPlane({ uniforms }, ref) {
  const { viewport } = useThree();

  useLayoutEffect(() => {
    const mesh = ref as React.MutableRefObject<Mesh | null>;
    if (mesh.current) {
      mesh.current.scale.set(viewport.width, viewport.height, 1);
    }
  }, [ref, viewport]);

  useFrame((_state: RootState, delta: number) => {
    const mesh = ref as React.MutableRefObject<Mesh | null>;
    if (mesh.current) {
      const material = mesh.current.material as ShaderMaterial & {
        uniforms: SilkUniforms;
      };
      material.uniforms.uTime.value += 0.1 * delta;
    }
  });

  return (
    <mesh ref={ref}>
      <planeGeometry args={[1, 1, 1, 1]} />
      <shaderMaterial uniforms={uniforms} vertexShader={vertexShader} fragmentShader={fragmentShader} />
    </mesh>
  );
});
SilkPlane.displayName = 'SilkPlane';

export interface SilkProps {
  speed?: number;
  scale?: number;
  color?: string;
  noiseIntensity?: number;
  rotation?: number;
}

const Silk: React.FC<SilkProps> = ({ speed = 5, scale = 1, color = '#7B7481', noiseIntensity = 1.5, rotation = 0 }) => {
  const meshRef = useRef<Mesh>(null);

  const uniforms = useMemo<SilkUniforms>(
    () => ({
      uSpeed: { value: speed },
      uScale: { value: scale },
      uNoiseIntensity: { value: noiseIntensity },
      uColor: { value: new Color(...hexToNormalizedRGB(color)) },
      uRotation: { value: rotation },
      uTime: { value: 0 }
    }),
    [speed, scale, noiseIntensity, color, rotation]
  );

  return (
    <Canvas dpr={[1, 2]} frameloop="always">
      <SilkPlane ref={meshRef} uniforms={uniforms} />
    </Canvas>
  );
};

export default Silk;


--- FILE: frontend-web/registry/backgrounds/SmokeBackground.tsx ---

import React, { useEffect, useRef } from 'react';
import { cn } from '../core/utils';

// --- FRAGMENT SHADER ---
const fragmentShaderSource = `#version 300 es
precision highp float;
out vec4 O;
uniform float time;
uniform vec2 resolution;
uniform vec3 u_color;

#define FC gl_FragCoord.xy
#define R resolution
#define T (time+660.)

float rnd(vec2 p){p=fract(p*vec2(12.9898,78.233));p+=dot(p,p+34.56);return fract(p.x*p.y);}
float noise(vec2 p){vec2 i=floor(p),f=fract(p),u=f*f*(3.-2.*f);return mix(mix(rnd(i),rnd(i+vec2(1,0)),u.x),mix(rnd(i+vec2(0,1)),rnd(i+1.),u.x),u.y);}
float fbm(vec2 p){float t=.0,a=1.;for(int i=0;i<5;i++){t+=a*noise(p);p*=mat2(1,-1.2,.2,1.2)*2.;a*=.5;}return t;}

void main(){
  vec2 uv=(FC-.5*R)/R.y;
  vec3 col=vec3(1);
  uv.x+=.25;
  uv*=vec2(2,1);

  float n=fbm(uv*.28-vec2(T*.01,0));
  n=noise(uv*3.+n*2.);

  col.r-=fbm(uv+vec2(0,T*.015)+n);
  col.g-=fbm(uv*1.003+vec2(0,T*.015)+n+.003);
  col.b-=fbm(uv*1.006+vec2(0,T*.015)+n+.006);

  col=mix(col, u_color, dot(col,vec3(.21,.71,.07)));

  col=mix(vec3(.08),col,min(time*.1,1.));
  col=clamp(col,.08,1.);
  O=vec4(col,1);
}`;

// --- RENDERER CLASS ---
class Renderer {
  private readonly vertexSrc = "#version 300 es\nprecision highp float;\nin vec4 position;\nvoid main(){gl_Position=position;}";
  private readonly vertices = [-1, 1, -1, -1, 1, 1, 1, -1];
  
  private gl: WebGL2RenderingContext;
  private canvas: HTMLCanvasElement;
  private program: WebGLProgram | null = null;
  private vs: WebGLShader | null = null;
  private fs: WebGLShader | null = null;
  private buffer: WebGLBuffer | null = null;
  private color: [number, number, number] = [0.5, 0.5, 0.5]; 

  constructor(canvas: HTMLCanvasElement, fragmentSource: string) {
    this.canvas = canvas;
    this.gl = canvas.getContext("webgl2") as WebGL2RenderingContext;
    this.setup(fragmentSource);
    this.init();
  }
  
  updateColor(newColor: [number, number, number]) {
    this.color = newColor;
  }

  updateScale(width: number, height: number) {
    const dpr = Math.max(1, window.devicePixelRatio);
    this.canvas.width = width * dpr;
    this.canvas.height = height * dpr;
    this.canvas.style.width = `${width}px`;
    this.canvas.style.height = `${height}px`;
    this.gl.viewport(0, 0, this.canvas.width, this.canvas.height);
  }

  private compile(shader: WebGLShader, source: string) {
    const gl = this.gl;
    gl.shaderSource(shader, source);
    gl.compileShader(shader);
    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
      console.error(`Shader compilation error: ${gl.getShaderInfoLog(shader)}`);
    }
  }

  reset() {
    const { gl, program, vs, fs } = this;
    if (!program) return;
    if (vs) { gl.detachShader(program, vs); gl.deleteShader(vs); }
    if (fs) { gl.detachShader(program, fs); gl.deleteShader(fs); }
    gl.deleteProgram(program);
    this.program = null;
  }

  private setup(fragmentSource: string) {
    const gl = this.gl;
    this.vs = gl.createShader(gl.VERTEX_SHADER);
    this.fs = gl.createShader(gl.FRAGMENT_SHADER);
    const program = gl.createProgram();
    if (!this.vs || !this.fs || !program) return;
    this.compile(this.vs, this.vertexSrc);
    this.compile(this.fs, fragmentSource);
    this.program = program;
    gl.attachShader(this.program, this.vs);
    gl.attachShader(this.program, this.fs);
    gl.linkProgram(this.program);
    if (!gl.getProgramParameter(this.program, gl.LINK_STATUS)) {
      console.error(`Program linking error: ${gl.getProgramInfoLog(this.program)}`);
    }
  }

  private init() {
    const { gl, program } = this;
    if (!program) return;
    this.buffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(this.vertices), gl.STATIC_DRAW);
    const position = gl.getAttribLocation(program, "position");
    gl.enableVertexAttribArray(position);
    gl.vertexAttribPointer(position, 2, gl.FLOAT, false, 0, 0);
    Object.assign(program, {
      resolution: gl.getUniformLocation(program, "resolution"),
      time: gl.getUniformLocation(program, "time"),
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      u_color: gl.getUniformLocation(program, "u_color"), 
    });
  }

  render(now = 0) {
    const { gl, program, buffer, canvas } = this;
    if (!program || !gl.isProgram(program)) return;
    gl.clearColor(0, 0, 0, 1);
    // eslint-disable-next-line no-bitwise
    gl.clear(gl.COLOR_BUFFER_BIT);
    gl.useProgram(program);
    gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    gl.uniform2f((program as any).resolution, canvas.width, canvas.height);
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    gl.uniform1f((program as any).time, now * 1e-3);
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    gl.uniform3fv((program as any).u_color, this.color); 
    gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
  }
}

// --- UTILITY FUNCTION ---
const hexToRgb = (hex: string): [number, number, number] | null => {
    const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
    return result
      ? [
          parseInt(result[1], 16) / 255,
          parseInt(result[2], 16) / 255,
          parseInt(result[3], 16) / 255,
        ]
      : null;
};

// --- REACT COMPONENT ---
export interface SmokeBackgroundProps {
  smokeColor?: string; 
  className?: string;
  children?: React.ReactNode;
}

export const SmokeBackground: React.FC<SmokeBackgroundProps> = ({ 
  smokeColor = "#808080",
  className,
  children
}) => {
    const containerRef = useRef<HTMLDivElement>(null);
    const canvasRef = useRef<HTMLCanvasElement>(null);
    const rendererRef = useRef<Renderer | null>(null);

    useEffect(() => {
        if (!canvasRef.current || !containerRef.current) return;
        
        const canvas = canvasRef.current;
        const container = containerRef.current;
        const renderer = new Renderer(canvas, fragmentShaderSource);
        rendererRef.current = renderer;
        
        const handleResize = () => {
          const rect = container.getBoundingClientRect();
          renderer.updateScale(rect.width, rect.height);
        };
        
        handleResize(); // Initial size
        
        const resizeObserver = new ResizeObserver(() => handleResize());
        resizeObserver.observe(container);
        
        let animationFrameId: number;
        const loop = (now: number) => {
            renderer.render(now);
            animationFrameId = requestAnimationFrame(loop);
        };
        loop(0);

        return () => {
            resizeObserver.disconnect();
            cancelAnimationFrame(animationFrameId);
            renderer.reset(); 
        };
    }, []);
    
    // Effect to update color when the prop changes
    useEffect(() => {
        const renderer = rendererRef.current;
        if (renderer) {
            const rgbColor = hexToRgb(smokeColor);
            if (rgbColor) {
                renderer.updateColor(rgbColor);
            }
        }
    }, [smokeColor]);

    return (
      <div ref={containerRef} className={cn("relative w-full h-full overflow-hidden bg-black", className)}>
        <canvas ref={canvasRef} className="absolute inset-0 block pointer-events-none" />
        {children && (
          <div className="relative z-10 flex h-full w-full items-center justify-center">
              {children}
          </div>
        )}
      </div>
    );
};

--- FILE: frontend-web/registry/backgrounds/Sparkles.tsx ---

import React, { useId, useEffect, useState } from "react";
import Particles, { initParticlesEngine } from "@tsparticles/react";
import type { Container, SingleOrMultiple } from "@tsparticles/engine";
import { loadSlim } from "@tsparticles/slim";
import { motion, useAnimation } from "framer-motion";
import { cn } from "../core/utils";

type ParticlesProps = {
  id?: string;
  className?: string;
  background?: string;
  particleSize?: number;
  minSize?: number;
  maxSize?: number;
  speed?: number;
  particleColor?: string;
  particleDensity?: number;
};

export const SparklesCore = (props: ParticlesProps) => {
  const {
    id,
    className,
    background,
    minSize,
    maxSize,
    speed,
    particleColor,
    particleDensity,
  } = props;
  
  const [init, setInit] = useState(false);
  
  useEffect(() => {
    initParticlesEngine(async (engine) => {
      await loadSlim(engine);
    }).then(() => {
      setInit(true);
    });
  }, []);
  
  const controls = useAnimation();

  const particlesLoaded = async (container?: Container) => {
    if (container) {
      controls.start({
        opacity: 1,
        transition: {
          duration: 1,
        },
      });
    }
  };

  const generatedId = useId();
  
  return (
    <motion.div animate={controls} className={cn("opacity-0", className)}>
      {init && (
        <Particles
          id={id || generatedId}
          className={cn("h-full w-full")}
          particlesLoaded={particlesLoaded}
          options={{
            background: {
              color: {
                value: background || "transparent",
              },
            },
            fullScreen: {
              enable: false,
              zIndex: 1,
            },
            fpsLimit: 120,
            interactivity: {
              events: {
                onClick: {
                  enable: true,
                  mode: "push",
                },
                onHover: {
                  enable: false,
                  mode: "repulse",
                },
                resize: true as any,
              },
              modes: {
                push: {
                  quantity: 4,
                },
                repulse: {
                  distance: 200,
                  duration: 0.4,
                },
              },
            },
            particles: {
              bounce: {
                horizontal: { value: 1 },
                vertical: { value: 1 },
              },
              collisions: {
                absorb: { speed: 2 },
                bounce: {
                  horizontal: { value: 1 },
                  vertical: { value: 1 },
                },
                enable: false,
                maxSpeed: 50,
                mode: "bounce",
                overlap: {
                  enable: true,
                  retries: 0,
                },
              },
              color: {
                value: particleColor || "#ffffff",
                animation: {
                  h: { count: 0, enable: false, speed: 1, decay: 0, delay: 0, sync: true, offset: 0 },
                  s: { count: 0, enable: false, speed: 1, decay: 0, delay: 0, sync: true, offset: 0 },
                  l: { count: 0, enable: false, speed: 1, decay: 0, delay: 0, sync: true, offset: 0 },
                },
              },
              effect: {
                close: true,
                fill: true,
                options: {},
                type: {} as SingleOrMultiple<string> | undefined,
              },
              groups: {},
              move: {
                angle: { offset: 0, value: 90 },
                attract: { distance: 200, enable: false, rotate: { x: 3000, y: 3000 } },
                center: { x: 50, y: 50, mode: "percent", radius: 0 },
                decay: 0,
                distance: {},
                direction: "none",
                drift: 0,
                enable: true,
                gravity: { acceleration: 9.81, enable: false, inverse: false, maxSpeed: 50 },
                path: { clamp: true, delay: { value: 0 }, enable: false, options: {} },
                outModes: { default: "out" },
                random: false,
                size: false,
                speed: { min: 0.1, max: 1 },
                spin: { acceleration: 0, enable: false },
                straight: false,
                trail: { enable: false, length: 10, fill: {} },
                vibrate: false,
                warp: false,
              },
              number: {
                density: { enable: true, width: 400, height: 400 },
                limit: { mode: "delete", value: 0 },
                value: particleDensity || 120,
              },
              opacity: {
                value: { min: 0.1, max: 1 },
                animation: {
                  count: 0, enable: true, speed: speed || 4, decay: 0, delay: 0,
                  sync: false, mode: "auto", startValue: "random", destroy: "none",
                },
              },
              reduceDuplicates: false,
              shadow: {
                blur: 0, color: { value: "#000" }, enable: false, offset: { x: 0, y: 0 },
              },
              shape: {
                close: true, fill: true, options: {}, type: "circle",
              },
              size: {
                value: { min: minSize || 1, max: maxSize || 3 },
                animation: {
                  count: 0, enable: false, speed: 5, decay: 0, delay: 0,
                  sync: false, mode: "auto", startValue: "random", destroy: "none",
                },
              },
              stroke: { width: 0 },
              zIndex: { value: 0, opacityRate: 1, sizeRate: 1, velocityRate: 1 },
              destroy: {
                bounds: {}, mode: "none", split: {
                  count: 1, factor: { value: 3 }, rate: { value: { min: 4, max: 9 } }, sizeOffset: true,
                },
              },
              roll: { darken: { enable: false, value: 0 }, enable: false, enlighten: { enable: false, value: 0 }, mode: "vertical", speed: 25 },
              tilt: { value: 0, animation: { enable: false, speed: 0, decay: 0, sync: false }, direction: "clockwise", enable: false },
              twinkle: { lines: { enable: false, frequency: 0.05, opacity: 1 }, particles: { enable: false, frequency: 0.05, opacity: 1 } },
              wobble: { distance: 5, enable: false, speed: { angle: 50, move: 10 } },
              life: { count: 0, delay: { value: 0, sync: false }, duration: { value: 0, sync: false } },
              rotate: { value: 0, animation: { enable: false, speed: 0, decay: 0, sync: false }, direction: "clockwise", path: false },
              orbit: { animation: { count: 0, enable: false, speed: 1, decay: 0, delay: 0, sync: false }, enable: false, opacity: 1, rotation: { value: 45 }, width: 1 },
              links: { blink: false, color: { value: "#fff" }, consent: false, distance: 100, enable: false, frequency: 1, opacity: 1, shadow: { blur: 5, color: { value: "#000" }, enable: false }, triangles: { enable: false, frequency: 1 }, width: 1, warp: false },
              repulse: { value: 0, enabled: false, distance: 1, duration: 1, factor: 1, speed: 1 },
            },
            detectRetina: true,
          }}
        />
      )}
    </motion.div>
  );
};

--- FILE: frontend-web/registry/backgrounds/SpiralAnimation.tsx ---

import React, { useEffect, useRef, useState } from 'react';
import { gsap } from 'gsap';
import { cn } from '../core/utils';

// Vector utility classes
class Vector2D {
    constructor(public x: number, public y: number) {}
    
    static random(min: number, max: number): number {
        return min + Math.random() * (max - min);
    }
}

class Vector3D {
    constructor(public x: number, public y: number, public z: number) {}
    
    static random(min: number, max: number): number {
        return min + Math.random() * (max - min);
    }
}

// Animation Controller
class AnimationController {
    private timeline: gsap.core.Timeline;
    private time = 0;
    private canvas: HTMLCanvasElement;
    private ctx: CanvasRenderingContext2D;
    private dpr: number;
    private width: number;
    private height: number;
    private stars: Star[] = [];
    
    // Constants
    private readonly changeEventTime = 0.32;
    private readonly cameraZ = -400;
    private readonly cameraTravelDistance = 3400;
    private readonly startDotYOffset = 28;
    private readonly viewZoom = 100;
    private readonly numberOfStars = 5000;
    private readonly trailLength = 80;
    
    constructor(canvas: HTMLCanvasElement, ctx: CanvasRenderingContext2D, dpr: number, width: number, height: number) {
        this.canvas = canvas;
        this.ctx = ctx;
        this.dpr = dpr;
        this.width = width;
        this.height = height;
        this.timeline = gsap.timeline({ repeat: -1 });
        
        // Initialization
        this.setupRandomGenerator();
        this.createStars();
        this.setupTimeline();
    }
    
    // Setup seeded random generator for consistency
    private setupRandomGenerator() {
        const originalRandom = Math.random;
        const customRandom = () => {
            let seed = 1234;
            return () => {
                seed = (seed * 9301 + 49297) % 233280;
                return seed / 233280;
            };
        };
        
        Math.random = customRandom();
        this.createStars();
        Math.random = originalRandom;
    }
    
    // Create stars
    private createStars() {
        this.stars = [];
        for (let i = 0; i < this.numberOfStars; i++) {
            this.stars.push(new Star(this.cameraZ, this.cameraTravelDistance));
        }
    }
    
    // Setup animation timeline
    private setupTimeline() {
        this.timeline
            .to(this, {
                time: 1,
                duration: 15,
                repeat: -1,
                ease: "none",
                onUpdate: () => this.render()
            });
    }
    
    // Easing function
    public ease(p: number, g: number): number {
        if (p < 0.5) 
            return 0.5 * Math.pow(2 * p, g);
        else
            return 1 - 0.5 * Math.pow(2 * (1 - p), g);
    }
    
    // Elastic easing
    public easeOutElastic(x: number): number {
        const c4 = (2 * Math.PI) / 4.5;
        if (x <= 0) return 0;
        if (x >= 1) return 1;
        return Math.pow(2, -8 * x) * Math.sin((x * 8 - 0.75) * c4) + 1;
    }
    
    // Map function
    public map(value: number, start1: number, stop1: number, start2: number, stop2: number): number {
        return start2 + (stop2 - start2) * ((value - start1) / (stop1 - start1));
    }
    
    // Constrain range
    public constrain(value: number, min: number, max: number): number {
        return Math.min(Math.max(value, min), max);
    }
    
    // Linear interpolation
    public lerp(start: number, end: number, t: number): number {
        return start * (1 - t) + end * t;
    }
    
    // Spiral path calculation
    public spiralPath(p: number): Vector2D {
        p = this.constrain(1.2 * p, 0, 1);
        p = this.ease(p, 1.8);
        const numberOfSpiralTurns = 6;
        const theta = 2 * Math.PI * numberOfSpiralTurns * Math.sqrt(p);
        const r = 170 * Math.sqrt(p);
        
        return new Vector2D(
            r * Math.cos(theta),
            r * Math.sin(theta) + this.startDotYOffset
        );
    }
    
    // Rotation transform
    public rotate(v1: Vector2D, v2: Vector2D, p: number, orientation: boolean): Vector2D {
        const middle = new Vector2D(
            (v1.x + v2.x) / 2,
            (v1.y + v2.y) / 2
        );
        
        const dx = v1.x - middle.x;
        const dy = v1.y - middle.y;
        const angle = Math.atan2(dy, dx);
        const o = orientation ? -1 : 1;
        const r = Math.sqrt(dx * dx + dy * dy);
        
        // Elastic bounce effect
        const bounce = Math.sin(p * Math.PI) * 0.05 * (1 - p);
        
        return new Vector2D(
            middle.x + r * (1 + bounce) * Math.cos(angle + o * Math.PI * this.easeOutElastic(p)),
            middle.y + r * (1 + bounce) * Math.sin(angle + o * Math.PI * this.easeOutElastic(p))
        );
    }
    
    // Projected 3D point to 2D
    public showProjectedDot(position: Vector3D, sizeFactor: number) {
        const t2 = this.constrain(this.map(this.time, this.changeEventTime, 1, 0, 1), 0, 1);
        const newCameraZ = this.cameraZ + this.ease(Math.pow(t2, 1.2), 1.8) * this.cameraTravelDistance;
        
        if (position.z > newCameraZ) {
            const dotDepthFromCamera = position.z - newCameraZ;
            
            // 3D -> 2D projection formula
            const x = this.viewZoom * position.x / dotDepthFromCamera;
            const y = this.viewZoom * position.y / dotDepthFromCamera;
            const sw = 400 * sizeFactor / dotDepthFromCamera;
            
            this.ctx.lineWidth = sw;
            this.ctx.beginPath();
            this.ctx.arc(x, y, 0.5, 0, Math.PI * 2);
            this.ctx.fill();
        }
    }
    
    // Draw starting point
    private drawStartDot() {
        if (this.time > this.changeEventTime) {
            const dy = this.cameraZ * this.startDotYOffset / this.viewZoom;
            const position = new Vector3D(0, dy, this.cameraTravelDistance);
            this.showProjectedDot(position, 2.5);
        }
    }
    
    // Main render function
    public render() {
        const ctx = this.ctx;
        if (!ctx) return;
        
        ctx.fillStyle = 'black';
        ctx.fillRect(0, 0, this.width, this.height);
        
        ctx.save();
        ctx.translate(this.width / 2, this.height / 2);
        
        // Calculate time parameters
        const t1 = this.constrain(this.map(this.time, 0, this.changeEventTime + 0.25, 0, 1), 0, 1);
        const t2 = this.constrain(this.map(this.time, this.changeEventTime, 1, 0, 1), 0, 1);
        
        // Rotate camera
        ctx.rotate(-Math.PI * this.ease(t2, 2.7));
        
        // Draw trail
        this.drawTrail(t1);
        
        // Draw stars
        ctx.fillStyle = 'white';
        for (const star of this.stars) {
            star.render(t1, this);
        }
        
        // Draw starting point
        this.drawStartDot();
        
        ctx.restore();
    }
    
    // Draw spiral trail
    private drawTrail(t1: number) {
        for (let i = 0; i < this.trailLength; i++) {
            const f = this.map(i, 0, this.trailLength, 1.1, 0.1);
            const sw = (1.3 * (1 - t1) + 3.0 * Math.sin(Math.PI * t1)) * f;
            
            this.ctx.fillStyle = 'white';
            this.ctx.lineWidth = sw;
            
            const pathTime = t1 - 0.00015 * i;
            const position = this.spiralPath(pathTime);
            
            // Add rotation effect
            const basePos = position;
            const offset = new Vector2D(position.x + 5, position.y + 5);
            const rotated = this.rotate(
                basePos, 
                offset, 
                Math.sin(this.time * Math.PI * 2) * 0.5 + 0.5, 
                i % 2 === 0
            );
            
            this.ctx.beginPath();
            this.ctx.arc(rotated.x, rotated.y, sw / 2, 0, Math.PI * 2);
            this.ctx.fill();
        }
    }
    
    // Pause animation
    public pause() {
        this.timeline.pause();
    }
    
    // Resume animation
    public resume() {
        this.timeline.play();
    }
    
    // Destroy animation
    public destroy() {
        this.timeline.kill();
    }
    
    public updateSize(width: number, height: number) {
        this.width = width;
        this.height = height;
    }
}

// Star class
class Star {
    private dx: number;
    private dy: number;
    private spiralLocation: number;
    private strokeWeightFactor: number;
    private z: number;
    private angle: number;
    private distance: number;
    private rotationDirection: number; // Rotation direction
    private expansionRate: number; // Expansion rate
    private finalScale: number; // Final size scale
    
    constructor(cameraZ: number, cameraTravelDistance: number) {
        this.angle = Math.random() * Math.PI * 2;
        this.distance = 30 * Math.random() + 15;
        this.rotationDirection = Math.random() > 0.5 ? 1 : -1;
        this.expansionRate = 1.2 + Math.random() * 0.8; // Expansion rate 1.2-2.0
        this.finalScale = 0.7 + Math.random() * 0.6; // Final scale 0.7-1.3
        
        this.dx = this.distance * Math.cos(this.angle);
        this.dy = this.distance * Math.sin(this.angle);
        
        this.spiralLocation = (1 - Math.pow(1 - Math.random(), 3.0)) / 1.3;
        this.z = Vector2D.random(0.5 * cameraZ, cameraTravelDistance + cameraZ);
        
        const lerp = (start: number, end: number, t: number) => start * (1 - t) + end * t;
        this.z = lerp(this.z, cameraTravelDistance / 2, 0.3 * this.spiralLocation);
        this.strokeWeightFactor = Math.pow(Math.random(), 2.0);
    }
    
    render(p: number, controller: AnimationController) {
        const spiralPos = controller.spiralPath(this.spiralLocation);
        const q = p - this.spiralLocation;
        
        if (q > 0) {
            const displacementProgress = controller.constrain(4 * q, 0, 1);
            
            // Mixed easing functions: soft start, elastic end
            const linearEasing = displacementProgress;
            const elasticEasing = controller.easeOutElastic(displacementProgress);
            const powerEasing = Math.pow(displacementProgress, 2);
            
            // Mix easing effects for a natural feel
            let easing;
            if (displacementProgress < 0.3) {
                // Start phase: mostly linear and quadratic
                easing = controller.lerp(linearEasing, powerEasing, displacementProgress / 0.3);
            } else if (displacementProgress < 0.7) {
                // Mid phase: transition to elastic
                const t = (displacementProgress - 0.3) / 0.4;
                easing = controller.lerp(powerEasing, elasticEasing, t);
            } else {
                // Final phase: elastic effect
                easing = elasticEasing;
            }
            
            // Calculate position offset
            let screenX, screenY;
            
            // Apply different movement patterns in stages
            if (displacementProgress < 0.3) {
                // Initial phase: linear movement (30%)
                screenX = controller.lerp(spiralPos.x, spiralPos.x + this.dx * 0.3, easing / 0.3);
                screenY = controller.lerp(spiralPos.y, spiralPos.y + this.dy * 0.3, easing / 0.3);
            } else if (displacementProgress < 0.7) {
                // Mid phase: curved movement (40%)
                const midProgress = (displacementProgress - 0.3) / 0.4;
                const curveStrength = Math.sin(midProgress * Math.PI) * this.rotationDirection * 1.5;
                
                // Base position (30% linear distance)
                const baseX = spiralPos.x + this.dx * 0.3;
                const baseY = spiralPos.y + this.dy * 0.3;
                
                // Target position (70% distance)
                const targetX = spiralPos.x + this.dx * 0.7;
                const targetY = spiralPos.y + this.dy * 0.7;
                
                // Add curve offset
                const perpX = -this.dy * 0.4 * curveStrength;
                const perpY = this.dx * 0.4 * curveStrength;
                
                screenX = controller.lerp(baseX, targetX, midProgress) + perpX * midProgress;
                screenY = controller.lerp(baseY, targetY, midProgress) + perpY * midProgress;
            } else {
                // Final phase: stronger spiral expansion (30%)
                const finalProgress = (displacementProgress - 0.7) / 0.3;
                
                // Base position (70% linear distance)
                const baseX = spiralPos.x + this.dx * 0.7;
                const baseY = spiralPos.y + this.dy * 0.7;
                
                // Final position (further distance)
                const targetDistance = this.distance * this.expansionRate * 1.5;
                const spiralTurns = 1.2 * this.rotationDirection;
                const spiralAngle = this.angle + spiralTurns * finalProgress * Math.PI;
                
                const targetX = spiralPos.x + targetDistance * Math.cos(spiralAngle);
                const targetY = spiralPos.y + targetDistance * Math.sin(spiralAngle);
                
                // Apply easing
                screenX = controller.lerp(baseX, targetX, finalProgress);
                screenY = controller.lerp(baseY, targetY, finalProgress);
            }
            
            // 2D screen coordinates to 3D spatial coordinates
            const vx = (this.z - (controller as any).cameraZ) * screenX / (controller as any).viewZoom;
            const vy = (this.z - (controller as any).cameraZ) * screenY / (controller as any).viewZoom;
            
            const position = new Vector3D(vx, vy, this.z);
            
            // Particle size animation: normal start, slightly larger middle, scales to finalScale
            let sizeMultiplier = 1.0;
            if (displacementProgress < 0.6) {
                // First 60%: slight expansion
                sizeMultiplier = 1.0 + displacementProgress * 0.2;
            } else {
                // Last 40%: transition to final size
                const t = (displacementProgress - 0.6) / 0.4;
                sizeMultiplier = 1.2 * (1.0 - t) + this.finalScale * t;
            }
            
            const dotSize = 8.5 * this.strokeWeightFactor * sizeMultiplier;
            
            controller.showProjectedDot(position, dotSize);
        }
    }
}

export interface SpiralAnimationProps {
    className?: string;
}

export function SpiralAnimation({ className }: SpiralAnimationProps) {
    const containerRef = useRef<HTMLDivElement>(null);
    const canvasRef = useRef<HTMLCanvasElement>(null);
    const animationRef = useRef<AnimationController | null>(null);
    const [dimensions, setDimensions] = useState({ width: 0, height: 0 });
    
    // Handle container resize
    useEffect(() => {
        const container = containerRef.current;
        if (!container) return;

        const resizeObserver = new ResizeObserver((entries) => {
            for (const entry of entries) {
                setDimensions({
                    width: entry.contentRect.width,
                    height: entry.contentRect.height
                });
            }
        });

        resizeObserver.observe(container);
        
        // Initial setup
        setDimensions({
            width: container.getBoundingClientRect().width,
            height: container.getBoundingClientRect().height
        });

        return () => {
            resizeObserver.unobserve(container);
            resizeObserver.disconnect();
        };
    }, []);
    
    // Create and manage animation
    useEffect(() => {
        const canvas = canvasRef.current;
        if (!canvas || dimensions.width === 0 || dimensions.height === 0) return;
        
        const ctx = canvas.getContext('2d');
        if (!ctx) return;
        
        // Handle DPR for crisp rendering on retina displays
        const dpr = window.devicePixelRatio || 1;
        
        canvas.width = dimensions.width * dpr;
        canvas.height = dimensions.height * dpr;
        
        // Set CSS dimensions
        canvas.style.width = `${dimensions.width}px`;
        canvas.style.height = `${dimensions.height}px`;
        
        // Scale context to match DPR
        ctx.scale(dpr, dpr);
        
        // Create or update animation controller
        if (!animationRef.current) {
            animationRef.current = new AnimationController(canvas, ctx, dpr, dimensions.width, dimensions.height);
        } else {
            animationRef.current.updateSize(dimensions.width, dimensions.height);
        }
        
        return () => {
            // Clean up animation on unmount
            if (animationRef.current) {
                animationRef.current.destroy();
                animationRef.current = null;
            }
        };
    }, [dimensions]);
    
    return (
        <div ref={containerRef} className={cn("relative w-full h-full overflow-hidden bg-black", className)}>
            <canvas
                ref={canvasRef}
                className="absolute inset-0 w-full h-full pointer-events-none"
            />
        </div>
    );
}

--- FILE: frontend-web/registry/backgrounds/Tiles.tsx ---

// @ts-nocheck
import React from "react";
import { motion } from "framer-motion";
import { cn } from "../core/utils";

interface TilesProps {
  className?: string;
  rows?: number;
  cols?: number;
  tileClassName?: string;
  tileSize?: "sm" | "md" | "lg";
}

const tileSizes = {
  sm: "w-8 h-8",
  md: "w-9 h-9 md:w-12 md:h-12",
  lg: "w-12 h-12 md:w-16 md:h-16",
};

export function Tiles({
  className,
  rows = 100,
  cols = 10,
  tileClassName,
  tileSize = "md",
}: TilesProps) {
  const rowsArray = new Array(rows).fill(1);
  const colsArray = new Array(cols).fill(1);

  return (
    <div
      className={cn(
        "relative z-0 flex w-full h-full justify-center overflow-hidden",
        className
      )}
    >
      {rowsArray.map((_, i) => (
        <motion.div
          key={`row-${i}`}
          className={cn(
            tileSizes[tileSize],
            "border-l dark:border-neutral-900 border-neutral-200 relative",
            tileClassName
          )}
        >
          {colsArray.map((_, j) => (
            <motion.div
              whileHover={{
                backgroundColor: "rgba(99, 102, 241, 0.15)", // Tailwind indigo-500 with low opacity
                transition: { duration: 0 },
              }}
              animate={{
                backgroundColor: "transparent",
                transition: { duration: 2 }, // Slow fade out
              }}
              key={`col-${j}`}
              className={cn(
                tileSizes[tileSize],
                "border-r border-t dark:border-neutral-900 border-neutral-200 relative",
                tileClassName
              )}
            />
          ))}
        </motion.div>
      ))}
    </div>
  );
}

--- FILE: frontend-web/registry/backgrounds/Vortex.tsx ---

import React, { useEffect, useRef } from "react";
import { createNoise3D } from "simplex-noise";
import { motion } from "framer-motion";
import { cn } from "../core/utils";

export interface VortexProps {
  children?: React.ReactNode;
  className?: string;
  containerClassName?: string;
  particleCount?: number;
  rangeY?: number;
  baseHue?: number;
  baseSpeed?: number;
  rangeSpeed?: number;
  baseRadius?: number;
  rangeRadius?: number;
  backgroundColor?: string;
}

export const Vortex = (props: VortexProps) => {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const containerRef = useRef<HTMLDivElement>(null);
  const animationIdRef = useRef<number>(0);
  
  const particleCount = props.particleCount || 700;
  const particlePropCount = 9;
  const particlePropsLength = particleCount * particlePropCount;
  const rangeY = props.rangeY || 100;
  const baseTTL = 50;
  const rangeTTL = 150;
  const baseSpeed = props.baseSpeed || 0.0;
  const rangeSpeed = props.rangeSpeed || 1.5;
  const baseRadius = props.baseRadius || 1;
  const rangeRadius = props.rangeRadius || 2;
  const baseHue = props.baseHue || 220;
  const rangeHue = 100;
  const noiseSteps = 3;
  const xOff = 0.00125;
  const yOff = 0.00125;
  const zOff = 0.0005;
  const backgroundColor = props.backgroundColor || "#000000";
  
  let tick = 0;
  const noise3D = createNoise3D();
  let particleProps = new Float32Array(particlePropsLength);
  const center: [number, number] = [0, 0];

  const TAU: number = 2 * Math.PI;
  const rand = (n: number): number => n * Math.random();
  const randRange = (n: number): number => n - rand(2 * n);
  const fadeInOut = (t: number, m: number): number => {
    const hm = 0.5 * m;
    return Math.abs(((t + hm) % m) - hm) / hm;
  };
  const lerp = (n1: number, n2: number, speed: number): number =>
    (1 - speed) * n1 + speed * n2;

  const setup = () => {
    const canvas = canvasRef.current;
    const container = containerRef.current;
    if (canvas && container) {
      const ctx = canvas.getContext("2d");
      if (ctx) {
        resize(canvas);
        initParticles();
        draw(canvas, ctx);
      }
    }
  };

  const initParticles = () => {
    tick = 0;
    particleProps = new Float32Array(particlePropsLength);

    for (let i = 0; i < particlePropsLength; i += particlePropCount) {
      initParticle(i);
    }
  };

  const initParticle = (i: number) => {
    const canvas = canvasRef.current;
    if (!canvas) return;

    let x, y, vx, vy, life, ttl, speed, radius, hue;

    x = rand(canvas.width);
    y = center[1] + randRange(rangeY);
    vx = 0;
    vy = 0;
    life = 0;
    ttl = baseTTL + rand(rangeTTL);
    speed = baseSpeed + rand(rangeSpeed);
    radius = baseRadius + rand(rangeRadius);
    hue = baseHue + rand(rangeHue);

    particleProps.set([x, y, vx, vy, life, ttl, speed, radius, hue], i);
  };

  const draw = (canvas: HTMLCanvasElement, ctx: CanvasRenderingContext2D) => {
    tick++;

    ctx.clearRect(0, 0, canvas.width, canvas.height);

    ctx.fillStyle = backgroundColor;
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    drawParticles(ctx);
    renderGlow(canvas, ctx);
    renderToScreen(canvas, ctx);

    animationIdRef.current = window.requestAnimationFrame(() => draw(canvas, ctx));
  };

  const drawParticles = (ctx: CanvasRenderingContext2D) => {
    for (let i = 0; i < particlePropsLength; i += particlePropCount) {
      updateParticle(i, ctx);
    }
  };

  const updateParticle = (i: number, ctx: CanvasRenderingContext2D) => {
    const canvas = canvasRef.current;
    if (!canvas) return;

    const i2 = 1 + i,
      i3 = 2 + i,
      i4 = 3 + i,
      i5 = 4 + i,
      i6 = 5 + i,
      i7 = 6 + i,
      i8 = 7 + i,
      i9 = 8 + i;
    let n, x, y, vx, vy, life, ttl, speed, x2, y2, radius, hue;

    x = particleProps[i];
    y = particleProps[i2];
    n = noise3D(x * xOff, y * yOff, tick * zOff) * noiseSteps * TAU;
    vx = lerp(particleProps[i3], Math.cos(n), 0.5);
    vy = lerp(particleProps[i4], Math.sin(n), 0.5);
    life = particleProps[i5];
    ttl = particleProps[i6];
    speed = particleProps[i7];
    x2 = x + vx * speed;
    y2 = y + vy * speed;
    radius = particleProps[i8];
    hue = particleProps[i9];

    drawParticle(x, y, x2, y2, life, ttl, radius, hue, ctx);

    life++;

    particleProps[i] = x2;
    particleProps[i2] = y2;
    particleProps[i3] = vx;
    particleProps[i4] = vy;
    particleProps[i5] = life;

    (checkBounds(x, y, canvas) || life > ttl) && initParticle(i);
  };

  const drawParticle = (
    x: number,
    y: number,
    x2: number,
    y2: number,
    life: number,
    ttl: number,
    radius: number,
    hue: number,
    ctx: CanvasRenderingContext2D
  ) => {
    ctx.save();
    ctx.lineCap = "round";
    ctx.lineWidth = radius;
    ctx.strokeStyle = `hsla(${hue},100%,60%,${fadeInOut(life, ttl)})`;
    ctx.beginPath();
    ctx.moveTo(x, y);
    ctx.lineTo(x2, y2);
    ctx.stroke();
    ctx.closePath();
    ctx.restore();
  };

  const checkBounds = (x: number, y: number, canvas: HTMLCanvasElement) => {
    return x > canvas.width || x < 0 || y > canvas.height || y < 0;
  };

  const resize = (canvas: HTMLCanvasElement) => {
    const { innerWidth, innerHeight } = window;
    canvas.width = innerWidth;
    canvas.height = innerHeight;
    center[0] = 0.5 * canvas.width;
    center[1] = 0.5 * canvas.height;
  };

  const renderGlow = (
    canvas: HTMLCanvasElement,
    ctx: CanvasRenderingContext2D
  ) => {
    ctx.save();
    ctx.filter = "blur(8px) brightness(200%)";
    ctx.globalCompositeOperation = "lighter";
    ctx.drawImage(canvas, 0, 0);
    ctx.restore();

    ctx.save();
    ctx.filter = "blur(4px) brightness(200%)";
    ctx.globalCompositeOperation = "lighter";
    ctx.drawImage(canvas, 0, 0);
    ctx.restore();
  };

  const renderToScreen = (
    canvas: HTMLCanvasElement,
    ctx: CanvasRenderingContext2D
  ) => {
    ctx.save();
    ctx.globalCompositeOperation = "lighter";
    ctx.drawImage(canvas, 0, 0);
    ctx.restore();
  };

  useEffect(() => {
    setup();
    
    const handleResize = () => {
      const canvas = canvasRef.current;
      if (canvas) {
        resize(canvas);
      }
    };
    
    window.addEventListener("resize", handleResize);
    
    return () => {
      window.removeEventListener("resize", handleResize);
      if (animationIdRef.current) {
        window.cancelAnimationFrame(animationIdRef.current);
      }
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  return (
    <div className={cn("relative h-full w-full", props.containerClassName)}>
      <motion.div
        initial={{ opacity: 0 }}
        animate={{ opacity: 1 }}
        ref={containerRef}
        className="absolute h-full w-full inset-0 z-0 bg-transparent flex items-center justify-center"
      >
        <canvas ref={canvasRef}></canvas>
      </motion.div>

      <div className={cn("relative z-10", props.className)}>
        {props.children}
      </div>
    </div>
  );
};

--- FILE: frontend-web/registry/backgrounds/VortexFullPage.tsx ---

import React, { useEffect, useRef } from "react";
import { createNoise3D } from "simplex-noise";
import { motion } from "framer-motion";
import { cn } from "../core/utils";

export interface VortexFullPageProps {
  children?: React.ReactNode;
  className?: string;
  containerClassName?: string;
  particleCount?: number;
  rangeY?: number;
  baseHue?: number;
  baseSpeed?: number;
  rangeSpeed?: number;
  baseRadius?: number;
  rangeRadius?: number;
  backgroundColor?: string;
}

export const VortexFullPage = (props: VortexFullPageProps) => {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const containerRef = useRef<HTMLDivElement>(null);
  const animationIdRef = useRef<number>(0);
  
  const particleCount = props.particleCount || 700;
  const particlePropCount = 9;
  const particlePropsLength = particleCount * particlePropCount;
  const rangeY = props.rangeY || 100;
  const baseTTL = 50;
  const rangeTTL = 150;
  const baseSpeed = props.baseSpeed || 0.0;
  const rangeSpeed = props.rangeSpeed || 1.5;
  const baseRadius = props.baseRadius || 1;
  const rangeRadius = props.rangeRadius || 2;
  const baseHue = props.baseHue || 220;
  const rangeHue = 100;
  const noiseSteps = 3;
  const xOff = 0.00125;
  const yOff = 0.00125;
  const zOff = 0.0005;
  const backgroundColor = props.backgroundColor || "#000000";
  
  let tick = 0;
  const noise3D = createNoise3D();
  let particleProps = new Float32Array(particlePropsLength);
  const center: [number, number] = [0, 0];

  const TAU: number = 2 * Math.PI;
  const rand = (n: number): number => n * Math.random();
  const randRange = (n: number): number => n - rand(2 * n);
  const fadeInOut = (t: number, m: number): number => {
    const hm = 0.5 * m;
    return Math.abs(((t + hm) % m) - hm) / hm;
  };
  const lerp = (n1: number, n2: number, speed: number): number =>
    (1 - speed) * n1 + speed * n2;

  const setup = () => {
    const canvas = canvasRef.current;
    const container = containerRef.current;
    if (canvas && container) {
      const ctx = canvas.getContext("2d");
      if (ctx) {
        resize(canvas);
        initParticles();
        draw(canvas, ctx);
      }
    }
  };

  const initParticles = () => {
    tick = 0;
    particleProps = new Float32Array(particlePropsLength);

    for (let i = 0; i < particlePropsLength; i += particlePropCount) {
      initParticle(i);
    }
  };

  const initParticle = (i: number) => {
    const canvas = canvasRef.current;
    if (!canvas) return;

    let x, y, vx, vy, life, ttl, speed, radius, hue;

    x = rand(canvas.width);
    y = center[1] + randRange(rangeY);
    vx = 0;
    vy = 0;
    life = 0;
    ttl = baseTTL + rand(rangeTTL);
    speed = baseSpeed + rand(rangeSpeed);
    radius = baseRadius + rand(rangeRadius);
    hue = baseHue + rand(rangeHue);

    particleProps.set([x, y, vx, vy, life, ttl, speed, radius, hue], i);
  };

  const draw = (canvas: HTMLCanvasElement, ctx: CanvasRenderingContext2D) => {
    tick++;

    ctx.clearRect(0, 0, canvas.width, canvas.height);

    ctx.fillStyle = backgroundColor;
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    drawParticles(ctx);
    renderGlow(canvas, ctx);
    renderToScreen(canvas, ctx);

    animationIdRef.current = window.requestAnimationFrame(() => draw(canvas, ctx));
  };

  const drawParticles = (ctx: CanvasRenderingContext2D) => {
    for (let i = 0; i < particlePropsLength; i += particlePropCount) {
      updateParticle(i, ctx);
    }
  };

  const updateParticle = (i: number, ctx: CanvasRenderingContext2D) => {
    const canvas = canvasRef.current;
    if (!canvas) return;

    const i2 = 1 + i,
      i3 = 2 + i,
      i4 = 3 + i,
      i5 = 4 + i,
      i6 = 5 + i,
      i7 = 6 + i,
      i8 = 7 + i,
      i9 = 8 + i;
    let n, x, y, vx, vy, life, ttl, speed, x2, y2, radius, hue;

    x = particleProps[i];
    y = particleProps[i2];
    n = noise3D(x * xOff, y * yOff, tick * zOff) * noiseSteps * TAU;
    vx = lerp(particleProps[i3], Math.cos(n), 0.5);
    vy = lerp(particleProps[i4], Math.sin(n), 0.5);
    life = particleProps[i5];
    ttl = particleProps[i6];
    speed = particleProps[i7];
    x2 = x + vx * speed;
    y2 = y + vy * speed;
    radius = particleProps[i8];
    hue = particleProps[i9];

    drawParticle(x, y, x2, y2, life, ttl, radius, hue, ctx);

    life++;

    particleProps[i] = x2;
    particleProps[i2] = y2;
    particleProps[i3] = vx;
    particleProps[i4] = vy;
    particleProps[i5] = life;

    (checkBounds(x, y, canvas) || life > ttl) && initParticle(i);
  };

  const drawParticle = (
    x: number,
    y: number,
    x2: number,
    y2: number,
    life: number,
    ttl: number,
    radius: number,
    hue: number,
    ctx: CanvasRenderingContext2D
  ) => {
    ctx.save();
    ctx.lineCap = "round";
    ctx.lineWidth = radius;
    ctx.strokeStyle = `hsla(${hue},100%,60%,${fadeInOut(life, ttl)})`;
    ctx.beginPath();
    ctx.moveTo(x, y);
    ctx.lineTo(x2, y2);
    ctx.stroke();
    ctx.closePath();
    ctx.restore();
  };

  const checkBounds = (x: number, y: number, canvas: HTMLCanvasElement) => {
    return x > canvas.width || x < 0 || y > canvas.height || y < 0;
  };

  const resize = (canvas: HTMLCanvasElement) => {
    const { innerWidth, innerHeight } = window;
    canvas.width = innerWidth;
    canvas.height = innerHeight;
    center[0] = 0.5 * canvas.width;
    center[1] = 0.5 * canvas.height;
  };

  const renderGlow = (
    canvas: HTMLCanvasElement,
    ctx: CanvasRenderingContext2D
  ) => {
    ctx.save();
    ctx.filter = "blur(8px) brightness(200%)";
    ctx.globalCompositeOperation = "lighter";
    ctx.drawImage(canvas, 0, 0);
    ctx.restore();

    ctx.save();
    ctx.filter = "blur(4px) brightness(200%)";
    ctx.globalCompositeOperation = "lighter";
    ctx.drawImage(canvas, 0, 0);
    ctx.restore();
  };

  const renderToScreen = (
    canvas: HTMLCanvasElement,
    ctx: CanvasRenderingContext2D
  ) => {
    ctx.save();
    ctx.globalCompositeOperation = "lighter";
    ctx.drawImage(canvas, 0, 0);
    ctx.restore();
  };

  useEffect(() => {
    setup();
    
    const handleResize = () => {
      const canvas = canvasRef.current;
      if (canvas) {
        resize(canvas);
      }
    };
    
    window.addEventListener("resize", handleResize);
    
    return () => {
      window.removeEventListener("resize", handleResize);
      if (animationIdRef.current) {
        window.cancelAnimationFrame(animationIdRef.current);
      }
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  return (
    <div className={cn("relative h-screen w-screen overflow-hidden", props.containerClassName)}>
      <motion.div
        initial={{ opacity: 0 }}
        animate={{ opacity: 1 }}
        ref={containerRef}
        className="absolute h-full w-full inset-0 z-0 bg-transparent flex items-center justify-center"
      >
        <canvas ref={canvasRef}></canvas>
      </motion.div>

      <div className={cn("relative z-10 w-full h-full", props.className)}>
        {props.children}
      </div>
    </div>
  );
};

--- FILE: frontend-web/registry/backgrounds/Waves.tsx ---

import * as React from 'react';
import { useEffect, useRef } from 'react';
import { createNoise2D } from 'simplex-noise';

interface Point {
    x: number;
    y: number;
    wave: { x: number; y: number };
    cursor: {
        x: number;
        y: number;
        vx: number;
        vy: number;
    };
}

export interface WavesProps {
    className?: string;
    strokeColor?: string;
    backgroundColor?: string;
    pointerSize?: number;
}

export function Waves({
    className = "",
    strokeColor = "#ffffff",  // White lines
    backgroundColor = "#000000",  // Black background
    pointerSize = 0.5
}: WavesProps) {
    const containerRef = useRef<HTMLDivElement>(null);
    const svgRef = useRef<SVGSVGElement>(null);
    const mouseRef = useRef({
        x: -10,
        y: 0,
        lx: 0,
        ly: 0,
        sx: 0,
        sy: 0,
        v: 0,
        vs: 0,
        a: 0,
        set: false,
    });
    const pathsRef = useRef<SVGPathElement[]>([]);
    const linesRef = useRef<Point[][]>([]);  
    const noiseRef = useRef<((x: number, y: number) => number) | null>(null);  
    const rafRef = useRef<number | null>(null);
    const boundingRef = useRef<DOMRect | null>(null);

    // Initialization
    useEffect(() => {
        if (!containerRef.current || !svgRef.current) return;

        // Initialize noise generator
        noiseRef.current = createNoise2D();

        // Initialize size and lines
        setSize();
        setLines();

        // Bind events
        window.addEventListener('resize', onResize);
        window.addEventListener('mousemove', onMouseMove);
        containerRef.current.addEventListener('touchmove', onTouchMove, { passive: false });

        // Start animation
        rafRef.current = requestAnimationFrame(tick);

        return () => {
            if (rafRef.current) cancelAnimationFrame(rafRef.current);
            window.removeEventListener('resize', onResize);
            window.removeEventListener('mousemove', onMouseMove);
            containerRef.current?.removeEventListener('touchmove', onTouchMove);
        };
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, []);

    // Set SVG size
    const setSize = () => {
        if (!containerRef.current || !svgRef.current) return;

        boundingRef.current = containerRef.current.getBoundingClientRect();
        const { width, height } = boundingRef.current;

        svgRef.current.style.width = `${width}px`;
        svgRef.current.style.height = `${height}px`;
    };

    // Setup lines - more points for smoother curves
    const setLines = () => {
        if (!svgRef.current || !boundingRef.current) return;

        const { width, height } = boundingRef.current;
        linesRef.current = [];

        // Clear existing paths
        pathsRef.current.forEach(path => {
            path.remove();
        });
        pathsRef.current = [];

        // Use smaller spacing to generate more lines and points for smoother results
        const xGap = 8;  // Reduced horizontal spacing
        const yGap = 8;  // Reduced vertical spacing for denser points

        const oWidth = width + 200;
        const oHeight = height + 30;

        const totalLines = Math.ceil(oWidth / xGap);
        const totalPoints = Math.ceil(oHeight / yGap);

        const xStart = (width - xGap * totalLines) / 2;
        const yStart = (height - yGap * totalPoints) / 2;

        // Create vertical lines
        for (let i = 0; i < totalLines; i++) {
            const points: Point[] = [];

            for (let j = 0; j < totalPoints; j++) {
                const point: Point = {
                    x: xStart + xGap * i,
                    y: yStart + yGap * j,
                    wave: { x: 0, y: 0 },
                    cursor: { x: 0, y: 0, vx: 0, vy: 0 },
                };

                points.push(point);
            }

            // Create SVG path
            const path = document.createElementNS(
                'http://www.w3.org/2000/svg',
                'path'
            );
            path.classList.add('a__line');
            path.classList.add('js-line');
            path.setAttribute('fill', 'none');
            path.setAttribute('stroke', strokeColor);
            path.setAttribute('stroke-width', '1');

            svgRef.current.appendChild(path);
            pathsRef.current.push(path);

            // Add points
            linesRef.current.push(points);
        }
    };

    // Resize handler
    const onResize = () => {
        setSize();
        setLines();
    };

    // Mouse handler
    const onMouseMove = (e: MouseEvent) => {
        updateMousePosition(e.pageX, e.pageY);
    };

    // Touch handler
    const onTouchMove = (e: TouchEvent) => {
        e.preventDefault();
        const touch = e.touches[0];
        updateMousePosition(touch.clientX, touch.clientY);
    };

    // Update mouse position
    const updateMousePosition = (x: number, y: number) => {
        if (!boundingRef.current) return;

        const mouse = mouseRef.current;
        mouse.x = x - boundingRef.current.left;
        mouse.y = y - boundingRef.current.top + window.scrollY;

        if (!mouse.set) {
            mouse.sx = mouse.x;
            mouse.sy = mouse.y;
            mouse.lx = mouse.x;
            mouse.ly = mouse.y;

            mouse.set = true;
        }

        // Update CSS variables
        if (containerRef.current) {
            containerRef.current.style.setProperty('--x', `${mouse.sx}px`);
            containerRef.current.style.setProperty('--y', `${mouse.sy}px`);
        }
    };

    // Move points - smoother wave motion
    const movePoints = (time: number) => {
        const { current: lines } = linesRef;
        const { current: mouse } = mouseRef;
        const { current: noise } = noiseRef;

        if (!noise) return;

        lines.forEach((points) => {
            points.forEach((p: Point) => {
                // Wave movement - reduced amplitude for smoother waves
                const move = noise(
                    (p.x + time * 0.008) * 0.003,  // Adjusted frequency
                    (p.y + time * 0.003) * 0.002   // Adjusted frequency
                ) * 8;  // Reduced amplitude for smoother waves

                p.wave.x = Math.cos(move) * 12;  // Reduced horizontal amplitude
                p.wave.y = Math.sin(move) * 6;   // Reduced vertical amplitude

                // Mouse effect - smoother response
                const dx = p.x - mouse.sx;
                const dy = p.y - mouse.sy;
                const d = Math.hypot(dx, dy);
                const l = Math.max(175, mouse.vs);

                if (d < l) {
                    const s = 1 - d / l;
                    const f = Math.cos(d * 0.001) * s;

                    p.cursor.vx += Math.cos(mouse.a) * f * l * mouse.vs * 0.00035;  // Reduced influence
                    p.cursor.vy += Math.sin(mouse.a) * f * l * mouse.vs * 0.00035;  // Reduced influence
                }

                p.cursor.vx += (0 - p.cursor.x) * 0.01;   // Increased restoration force
                p.cursor.vy += (0 - p.cursor.y) * 0.01;   // Increased restoration force

                p.cursor.vx *= 0.95;  // Increased smoothness
                p.cursor.vy *= 0.95;  // Increased smoothness

                p.cursor.x += p.cursor.vx;
                p.cursor.y += p.cursor.vy;

                p.cursor.x = Math.min(50, Math.max(-50, p.cursor.x));  // Limited deformation range
                p.cursor.y = Math.min(50, Math.max(-50, p.cursor.y));  // Limited deformation range
            });
        });
    };

    // Get moved point coordinates
    const moved = (point: Point, withCursorForce = true) => {
        const coords = {
            x: point.x + point.wave.x + (withCursorForce ? point.cursor.x : 0),
            y: point.y + point.wave.y + (withCursorForce ? point.cursor.y : 0),
        };

        return coords;
    };

    // Draw lines - using line segments
    const drawLines = () => {
        const { current: lines } = linesRef;
        const { current: paths } = pathsRef;

        lines.forEach((points, lIndex) => {
            if (points.length < 2 || !paths[lIndex]) return;

            // First point
            const firstPoint = moved(points[0], false);
            let d = `M ${firstPoint.x} ${firstPoint.y}`;

            // Connect points with lines
            for (let i = 1; i < points.length; i++) {
                const current = moved(points[i]);
                d += `L ${current.x} ${current.y}`;
            }

            paths[lIndex].setAttribute('d', d);
        });
    };

    // Animation logic
    const tick = (time: number) => {
        const { current: mouse } = mouseRef;

        // Smooth mouse movement
        mouse.sx += (mouse.x - mouse.sx) * 0.1;
        mouse.sy += (mouse.y - mouse.sy) * 0.1;

        // Mouse velocity
        const dx = mouse.x - mouse.lx;
        const dy = mouse.y - mouse.ly;
        const d = Math.hypot(dx, dy);

        mouse.v = d;
        mouse.vs += (d - mouse.vs) * 0.1;
        mouse.vs = Math.min(100, mouse.vs);

        // Previous mouse position
        mouse.lx = mouse.x;
        mouse.ly = mouse.y;

        // Mouse angle
        mouse.a = Math.atan2(dy, dx);

        // Animation
        if (containerRef.current) {
            containerRef.current.style.setProperty('--x', `${mouse.sx}px`);
            containerRef.current.style.setProperty('--y', `${mouse.sy}px`);
        }

        movePoints(time);
        drawLines();

        rafRef.current = requestAnimationFrame(tick);
    };

    return (
        <div
            ref={containerRef}
            className={`waves-component relative overflow-hidden ${className}`}
            style={{
                backgroundColor,
                position: 'absolute',
                top: 0,
                left: 0,
                margin: 0,
                padding: 0,
                width: '100%',
                height: '100%',
                overflow: 'hidden',
                '--x': '-0.5rem',
                '--y': '50%',
            } as React.CSSProperties}
        >
            <svg
                ref={svgRef}
                className="block w-full h-full js-svg"
                xmlns="http://www.w3.org/2000/svg"
            />
            <div
                className="pointer-dot"
                style={{
                    position: 'absolute',
                    top: 0,
                    left: 0,
                    width: `${pointerSize}rem`,
                    height: `${pointerSize}rem`,
                    background: strokeColor,
                    borderRadius: '50%',
                    transform: 'translate3d(calc(var(--x) - 50%), calc(var(--y) - 50%), 0)',
                    willChange: 'transform',
                    pointerEvents: 'none'
                }}
            />
        </div>
    );
}

--- FILE: frontend-web/registry/cards/AIGenCard.tsx ---

import React, { useState, useEffect } from "react";
import {
  MessageCircle,
  Sparkles,
  Wand2,
  Loader2,
  Play,
  Pause,
  RotateCw,
  History,
  AlertCircle,
  Palette,
  ImageIcon,
  Sun,
  User,
  Monitor,
  Cpu,
  RatioIcon as AspectRatio,
  Film,
  CuboidIcon as Cube,
  ArrowLeft,
  Clock,
  Search,
} from "lucide-react";

import { cn } from "../core/utils";

export type GenerationMode = "image" | "video" | "avatar";

export interface GenerationSettings {
  style: string;
  backgroundColor: string;
  lighting: string;
  pose: string;
  aspectRatio: string;
  aiModel: string;
  resolution: string;
  prompt: string;
  negativePrompt: string;
  seed?: number;
  steps?: number;
}

export interface HistoryItem {
  id: string;
  type: GenerationMode;
  url: string;
  prompt: string;
  timestamp: Date;
}

export function AIGenCard({ className }: { className?: string }) {
  const [mode, setMode] = useState<GenerationMode>("image");
  const [showForm, setShowForm] = useState(true);
  const [showHistory, setShowHistory] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [isLoading, setIsLoading] = useState(false);
  const [advancedMode, setAdvancedMode] = useState(false);
  const [promptSuggestions, setPromptSuggestions] = useState<string[]>([]);
  const [isSuggestionsOpen, setIsSuggestionsOpen] = useState(false);
  const [searchQuery, setSearchQuery] = useState("");
  const [isPlaying, setIsPlaying] = useState(false);
  const [isRotating, setIsRotating] = useState(false);
  const [currentTextIndex, setCurrentTextIndex] = useState(0);
  const [progress, setProgress] = useState(0);

  const [generatedItems, setGeneratedItems] = useState<HistoryItem[]>([
    {
      id: "1",
      type: "image",
      url: "https://images.unsplash.com/photo-1620641788421-7a1c342ea42e?q=80&w=400&auto=format&fit=crop",
      prompt: "Portrait of a woman with orange background",
      timestamp: new Date(Date.now() - 1000 * 60 * 5),
    },
    {
      id: "2",
      type: "image",
      url: "https://images.unsplash.com/photo-1618005182384-a83a8bd57fbe?q=80&w=400&auto=format&fit=crop",
      prompt: "Professional headshot with blue background",
      timestamp: new Date(Date.now() - 1000 * 60 * 30),
    },
  ]);

  const [settings, setSettings] = useState<GenerationSettings>({
    style: "artistic",
    backgroundColor: "studio",
    lighting: "studio",
    pose: "profile",
    aspectRatio: "4:5",
    aiModel: "stable-diffusion-xl",
    resolution: "1024x1024",
    prompt: "",
    negativePrompt: "blurry, low quality, distorted features",
  });

  const placeholderPrompts = {
    image: "Professional portrait with blue background, studio lighting",
    video: "Short video of a person walking in a park, cinematic lighting",
    avatar: "3D avatar of a young professional with glasses, detailed face",
  };

  const loadingTexts = {
    image: ["Creating your masterpiece...", "Finding the perfect colors...", "Adding the final touches..."],
    video: ["Generating video frames...", "Applying motion effects...", "Rendering your video..."],
    avatar: ["Building 3D mesh...", "Applying textures...", "Finalizing your avatar..."],
  };

  const aiModels = {
    image: [
      { value: "stable-diffusion-xl", label: "Stable Diffusion XL" },
      { value: "midjourney-v5", label: "Midjourney v5" },
      { value: "dalle-3", label: "DALL-E 3" },
      { value: "imagen", label: "Imagen" },
    ],
    video: [
      { value: "gen-2", label: "Gen-2" },
      { value: "runway-gen-2", label: "Runway Gen-2" },
      { value: "pika-labs", label: "Pika Labs" },
      { value: "sora", label: "Sora" },
    ],
    avatar: [
      { value: "dreamshaper-3d", label: "DreamShaper 3D" },
      { value: "3d-diffusion", label: "3D Diffusion" },
      { value: "meshy", label: "Meshy" },
      { value: "luma", label: "Luma AI" },
    ],
  };

  const resolutions = {
    image: [
      { value: "512x512", label: "512×512" },
      { value: "768x768", label: "768×768" },
      { value: "1024x1024", label: "1024×1024" },
      { value: "1536x1536", label: "1536×1536" },
    ],
    video: [
      { value: "512x512", label: "512×512" },
      { value: "768x768", label: "768×768" },
      { value: "1024x576", label: "1024×576 (16:9)" },
      { value: "1280x720", label: "1280×720 (HD)" },
    ],
    avatar: [
      { value: "512x512", label: "512×512" },
      { value: "768x768", label: "768×768" },
      { value: "1024x1024", label: "1024×1024" },
      { value: "2048x2048", label: "2048×2048" },
    ],
  };

  useEffect(() => {
    if (mode === "image") {
      setPromptSuggestions([
        "Professional headshot with neutral background",
        "Artistic portrait with dramatic lighting",
        "Casual portrait in natural outdoor setting",
      ]);
    } else if (mode === "video") {
      setPromptSuggestions([
        "Person walking in urban environment, cinematic lighting",
        "Close-up of face with changing expressions",
        "Rotating view of subject in studio setting",
      ]);
    } else {
      setPromptSuggestions([
        "Realistic 3D avatar with professional attire",
        "Stylized cartoon character with expressive features",
        "Detailed 3D bust with photorealistic textures",
      ]);
    }
  }, [mode]);

  useEffect(() => {
    if (!isLoading) {
      setProgress(0);
      return;
    }
    const interval = setInterval(() => {
      setProgress((prev) => {
        if (prev >= 100) {
          clearInterval(interval);
          return 100;
        }
        return prev + (mode === "image" ? 1.5 : mode === "video" ? 0.8 : 0.5);
      });
    }, 30);
    return () => clearInterval(interval);
  }, [isLoading, mode]);

  useEffect(() => {
    if (!isLoading) return;
    const interval = setInterval(() => {
      setCurrentTextIndex((prev) => (prev + 1) % loadingTexts[mode].length);
    }, 1500);
    return () => clearInterval(interval);
  }, [isLoading, mode]);

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    setShowForm(false);
    setIsLoading(true);
    setError(null);

    try {
      const loadingTime = mode === "image" ? 3000 : mode === "video" ? 5000 : 7000;
      await new Promise((resolve) => setTimeout(resolve, loadingTime));

      const newItem = {
        id: Date.now().toString(),
        type: mode,
        url: "https://images.unsplash.com/photo-1675426513753-2da9fb6786cc?q=80&w=400&auto=format&fit=crop",
        prompt: settings.prompt || "AI generated content",
        timestamp: new Date(),
      };

      setGeneratedItems((prev) => [newItem, ...prev]);
      setShowForm(false);
    } catch (err) {
      setError(`Failed to generate ${mode}. Please try again.`);
    } finally {
      setIsLoading(false);
    }
  };

  const handleBackToSettings = () => {
    setShowForm(true);
    setShowHistory(false);
    setError(null);
  };

  const handleModeChange = (newMode: GenerationMode) => {
    setMode(newMode);
    setShowForm(true);
    setShowHistory(false);
    setError(null);
  };

  const handleViewHistory = () => {
    setShowForm(false);
    setShowHistory(true);
  };

  const handleSelectHistoryItem = (id: string) => {
    const item = generatedItems.find((item) => item.id === id);
    if (item) {
      setMode(item.type);
      setShowHistory(false);
      setShowForm(false);
    }
  };

  const applyPromptSuggestion = (suggestion: string) => {
    setSettings({ ...settings, prompt: suggestion });
    setIsSuggestionsOpen(false);
  };

  const formatDate = (date: Date) => {
    const now = new Date();
    const diffMs = now.getTime() - date.getTime();
    const diffMins = Math.round(diffMs / 60000);

    if (diffMins < 1) return "Just now";
    if (diffMins < 60) return `${diffMins}m ago`;

    const diffHours = Math.floor(diffMins / 60);
    if (diffHours < 24) return `${diffHours}h ago`;

    return date.toLocaleDateString();
  };

  const filteredItems = generatedItems.filter((item) =>
    item.prompt.toLowerCase().includes(searchQuery.toLowerCase())
  );

  const renderHeader = () => (
    <div className="p-4 flex items-center justify-between border-b border-zinc-200 dark:border-zinc-800">
      <div className="flex items-center gap-3">
        <div>
          <h3 className="text-sm font-medium text-zinc-900 dark:text-zinc-100">AI Creation Engine</h3>
          <p className="text-xs text-zinc-500 dark:text-zinc-400">Generate multi-modal content</p>
        </div>
      </div>
      <button
        onClick={handleViewHistory}
        className="p-2 rounded-lg hover:bg-zinc-100 dark:hover:bg-zinc-800 transition-colors"
      >
        <History className="w-4 h-4 text-zinc-500" />
      </button>
    </div>
  );

  const renderError = () =>
    error && (
      <div className="m-4 px-4 py-3 flex items-center gap-2 text-sm text-red-600 dark:text-red-400 bg-red-50 dark:bg-red-900/10 rounded-xl">
        <AlertCircle className="w-4 h-4 flex-shrink-0" />
        <p>{error}</p>
      </div>
    );

  const renderForm = () => (
    <form onSubmit={handleSubmit} className="flex flex-col gap-3 flex-1 p-4 justify-between overflow-y-auto">
      <div className="space-y-3">
        <div className="space-y-2">
          <div className="flex items-center justify-between">
            <div className="flex items-center gap-2">
              <MessageCircle className="w-4 h-4 text-zinc-500" />
              <span className="text-sm text-zinc-500">Prompt</span>
            </div>
            <div className="relative">
              <button 
                type="button" 
                onClick={() => setIsSuggestionsOpen(!isSuggestionsOpen)}
                className="h-7 px-2 rounded-md hover:bg-zinc-100 dark:hover:bg-zinc-800 transition-colors"
              >
                <Wand2 className="w-3.5 h-3.5 text-zinc-500" />
              </button>
              {isSuggestionsOpen && (
                <div className="absolute right-0 top-full mt-1 w-72 p-2 bg-white dark:bg-zinc-900 border border-zinc-200 dark:border-zinc-800 rounded-lg shadow-xl z-50">
                  <h4 className="text-xs font-medium text-zinc-500 mb-1 px-2">Suggestions</h4>
                  <div className="space-y-1">
                    {promptSuggestions.map((suggestion, index) => (
                      <button
                        key={index}
                        type="button"
                        onClick={() => applyPromptSuggestion(suggestion)}
                        className="w-full text-left p-2 text-xs hover:bg-zinc-100 dark:hover:bg-zinc-800 rounded-md transition-colors text-zinc-700 dark:text-zinc-300"
                      >
                        {suggestion}
                      </button>
                    ))}
                  </div>
                </div>
              )}
            </div>
          </div>
          <textarea
            value={settings.prompt}
            onChange={(e) => setSettings({ ...settings, prompt: e.target.value })}
            placeholder={placeholderPrompts[mode]}
            className="w-full min-h-[80px] p-3 bg-zinc-100 dark:bg-zinc-800/50 text-sm text-zinc-900 dark:text-zinc-100 placeholder:text-zinc-500 rounded-xl focus:outline-none focus:ring-2 focus:ring-fuchsia-500/50 border border-transparent focus:border-fuchsia-500/50 transition-all resize-none"
          />
        </div>

        <div className="flex items-center space-x-2">
          <button
            type="button"
            role="switch"
            aria-checked={advancedMode}
            onClick={() => setAdvancedMode(!advancedMode)}
            className="w-9 h-5 bg-zinc-200 dark:bg-zinc-700 aria-checked:bg-fuchsia-500 rounded-full relative transition-colors"
          >
            <span className={cn("absolute top-0.5 left-0.5 bg-white w-4 h-4 rounded-full transition-transform", advancedMode ? "translate-x-4" : "")} />
          </button>
          <label className="text-xs text-zinc-500 cursor-pointer" onClick={() => setAdvancedMode(!advancedMode)}>
            Advanced Mode
          </label>
        </div>

        {advancedMode && (
          <div className="space-y-3 p-3 bg-zinc-50 dark:bg-zinc-800/30 rounded-xl">
            <div className="space-y-2">
              <label className="text-xs text-zinc-500">Negative Prompt</label>
              <textarea
                value={settings.negativePrompt}
                onChange={(e) => setSettings({ ...settings, negativePrompt: e.target.value })}
                placeholder="Elements to avoid in generation"
                className="w-full min-h-[60px] p-2 bg-white dark:bg-zinc-900 border border-zinc-200 dark:border-zinc-700 text-xs text-zinc-900 dark:text-zinc-100 placeholder:text-zinc-500 rounded-xl focus:outline-none focus:ring-1 focus:ring-fuchsia-500 transition-all resize-none"
              />
            </div>

            <div className="space-y-1">
              <div className="flex items-center justify-between">
                <label className="text-xs text-zinc-500">Seed</label>
                <span className="text-xs text-zinc-700 dark:text-zinc-300">{settings.seed || 0}</span>
              </div>
              <input
                type="range"
                value={settings.seed || 0}
                max={1000000}
                onChange={(e) => setSettings({ ...settings, seed: Number(e.target.value) })}
                className="w-full accent-fuchsia-500 h-1.5 bg-zinc-200 dark:bg-zinc-700 rounded-lg appearance-none cursor-pointer"
              />
            </div>

            <div className="space-y-1">
              <div className="flex items-center justify-between">
                <label className="text-xs text-zinc-500">Steps</label>
                <span className="text-xs text-zinc-700 dark:text-zinc-300">{settings.steps || 30}</span>
              </div>
              <input
                type="range"
                value={settings.steps || 30}
                min={10}
                max={150}
                onChange={(e) => setSettings({ ...settings, steps: Number(e.target.value) })}
                className="w-full accent-fuchsia-500 h-1.5 bg-zinc-200 dark:bg-zinc-700 rounded-lg appearance-none cursor-pointer"
              />
            </div>
          </div>
        )}
      </div>

      <div className="space-y-3 mt-4">
        {renderSettings()}

        <button
          type="submit"
          className="w-full h-10 flex items-center justify-center gap-2 bg-gradient-to-r from-fuchsia-500 to-violet-500 hover:from-fuchsia-600 hover:to-violet-600 text-white text-sm font-medium rounded-xl transition-colors shadow-md shadow-fuchsia-500/20"
        >
          <Sparkles className="w-4 h-4" />
          Generate {mode === "image" ? "Portrait" : mode === "video" ? "Video" : "Avatar"}
        </button>
      </div>
    </form>
  );

  const renderSettings = () => (
    <div className="space-y-3 p-4 rounded-xl bg-zinc-50 dark:bg-zinc-800/50">
      <div className="flex items-center justify-between gap-4">
        <div className="flex items-center gap-2">
          <Cpu className="w-4 h-4 text-zinc-500" />
          <span className="text-sm text-zinc-500">AI Model</span>
        </div>
        <select 
          value={settings.aiModel} 
          onChange={(e) => setSettings({ ...settings, aiModel: e.target.value })}
          className="w-[160px] h-8 bg-white dark:bg-zinc-900 border border-zinc-200 dark:border-zinc-700 rounded-md text-xs px-2 text-zinc-700 dark:text-zinc-300 focus:outline-none focus:ring-1 focus:ring-fuchsia-500"
        >
          {aiModels[mode].map((m) => (
            <option key={m.value} value={m.value}>{m.label}</option>
          ))}
        </select>
      </div>

      <div className="flex items-center justify-between gap-4">
        <div className="flex items-center gap-2">
          <Monitor className="w-4 h-4 text-zinc-500" />
          <span className="text-sm text-zinc-500">Resolution</span>
        </div>
        <select 
          value={settings.resolution} 
          onChange={(e) => setSettings({ ...settings, resolution: e.target.value })}
          className="w-[160px] h-8 bg-white dark:bg-zinc-900 border border-zinc-200 dark:border-zinc-700 rounded-md text-xs px-2 text-zinc-700 dark:text-zinc-300 focus:outline-none focus:ring-1 focus:ring-fuchsia-500"
        >
          {resolutions[mode].map((r) => (
            <option key={r.value} value={r.value}>{r.label}</option>
          ))}
        </select>
      </div>

      <div className="flex items-center justify-between gap-4">
        <div className="flex items-center gap-2">
          <Palette className="w-4 h-4 text-zinc-500" />
          <span className="text-sm text-zinc-500">Style</span>
        </div>
        <select 
          value={settings.style} 
          onChange={(e) => setSettings({ ...settings, style: e.target.value })}
          className="w-[160px] h-8 bg-white dark:bg-zinc-900 border border-zinc-200 dark:border-zinc-700 rounded-md text-xs px-2 text-zinc-700 dark:text-zinc-300 focus:outline-none focus:ring-1 focus:ring-fuchsia-500"
        >
            <option value="professional">Professional</option>
            <option value="artistic">Artistic</option>
            <option value="casual">Casual</option>
            <option value="vintage">Vintage</option>
            {mode === "avatar" && <option value="cartoon">Cartoon</option>}
            {mode === "avatar" && <option value="anime">Anime</option>}
            {mode === "video" && <option value="cinematic">Cinematic</option>}
        </select>
      </div>

      <div className="flex items-center justify-between gap-4">
        <div className="flex items-center gap-2">
          <ImageIcon className="w-4 h-4 text-zinc-500" />
          <span className="text-sm text-zinc-500">Background</span>
        </div>
        <select 
          value={settings.backgroundColor} 
          onChange={(e) => setSettings({ ...settings, backgroundColor: e.target.value })}
          className="w-[160px] h-8 bg-white dark:bg-zinc-900 border border-zinc-200 dark:border-zinc-700 rounded-md text-xs px-2 text-zinc-700 dark:text-zinc-300 focus:outline-none focus:ring-1 focus:ring-fuchsia-500"
        >
            <option value="studio">Studio</option>
            <option value="gradient">Gradient</option>
            <option value="solid">Solid Color</option>
            <option value="transparent">Transparent</option>
            {mode !== "avatar" && <option value="outdoor">Outdoor</option>}
            {mode !== "avatar" && <option value="office">Office</option>}
        </select>
      </div>

      <div className="flex items-center justify-between gap-4">
        <div className="flex items-center gap-2">
          <Sun className="w-4 h-4 text-zinc-500" />
          <span className="text-sm text-zinc-500">Lighting</span>
        </div>
        <select 
          value={settings.lighting} 
          onChange={(e) => setSettings({ ...settings, lighting: e.target.value })}
          className="w-[160px] h-8 bg-white dark:bg-zinc-900 border border-zinc-200 dark:border-zinc-700 rounded-md text-xs px-2 text-zinc-700 dark:text-zinc-300 focus:outline-none focus:ring-1 focus:ring-fuchsia-500"
        >
            <option value="soft">Soft</option>
            <option value="dramatic">Dramatic</option>
            <option value="natural">Natural</option>
            <option value="studio">Studio</option>
            {mode === "video" && <option value="cinematic">Cinematic</option>}
            {mode === "video" && <option value="golden-hour">Golden Hour</option>}
        </select>
      </div>

      <div className="flex items-center justify-between gap-4">
        <div className="flex items-center gap-2">
          <AspectRatio className="w-4 h-4 text-zinc-500" />
          <span className="text-sm text-zinc-500">Aspect Ratio</span>
        </div>
        <select 
          value={settings.aspectRatio} 
          onChange={(e) => setSettings({ ...settings, aspectRatio: e.target.value })}
          className="w-[160px] h-8 bg-white dark:bg-zinc-900 border border-zinc-200 dark:border-zinc-700 rounded-md text-xs px-2 text-zinc-700 dark:text-zinc-300 focus:outline-none focus:ring-1 focus:ring-fuchsia-500"
        >
            <option value="1:1">1:1 Square</option>
            <option value="4:5">4:5 Portrait</option>
            <option value="3:4">3:4 Portrait</option>
            <option value="16:9">16:9 Landscape</option>
            {mode === "video" && <option value="9:16">9:16 Vertical</option>}
        </select>
      </div>

      {mode !== "video" && (
        <div className="flex items-center justify-between gap-4">
          <div className="flex items-center gap-2">
            <User className="w-4 h-4 text-zinc-500" />
            <span className="text-sm text-zinc-500">Pose</span>
          </div>
          <select 
            value={settings.pose} 
            onChange={(e) => setSettings({ ...settings, pose: e.target.value })}
            className="w-[160px] h-8 bg-white dark:bg-zinc-900 border border-zinc-200 dark:border-zinc-700 rounded-md text-xs px-2 text-zinc-700 dark:text-zinc-300 focus:outline-none focus:ring-1 focus:ring-fuchsia-500"
          >
              <option value="headshot">Headshot</option>
              <option value="half-body">Half Body</option>
              <option value="full-body">Full Body</option>
              <option value="profile">Profile</option>
              {mode === "avatar" && <option value="bust">Bust</option>}
          </select>
        </div>
      )}
    </div>
  );

  const renderPreview = () => (
    <div className="p-4">
      <div className="rounded-xl mb-4 flex items-center justify-center">
        {isLoading ? (
          <div className="w-full max-w-md flex flex-col items-center gap-4 p-6 bg-zinc-50 dark:bg-zinc-800/20 rounded-xl">
            <div className="relative w-16 h-16">
              <Loader2 className="w-full h-full animate-spin text-fuchsia-500" />
              <div className="absolute inset-0 bg-gradient-to-tr from-transparent via-transparent to-fuchsia-500/10 rounded-full animate-[spin_3s_linear_infinite]" />
            </div>
            <div className="space-y-1 text-center">
              <p className="text-sm font-medium text-zinc-700 dark:text-zinc-300">
                {loadingTexts[mode][currentTextIndex]}
              </p>
              <p className="text-xs text-zinc-500 dark:text-zinc-400">
                {mode === "image"
                  ? "This usually takes 10-15 seconds"
                  : mode === "video"
                    ? "This usually takes 20-30 seconds"
                    : "This usually takes 30-45 seconds"}
              </p>
            </div>
            <div className="w-full h-2 bg-zinc-200 dark:bg-zinc-700 rounded-full overflow-hidden">
              <div
                className="h-full bg-gradient-to-r from-fuchsia-500 to-violet-500 transition-all duration-300 ease-linear"
                style={{ width: `${progress}%` }}
              />
            </div>
          </div>
        ) : (
          <div className="flex flex-col items-center gap-2 w-full">
            <div className="relative w-full rounded-xl overflow-hidden aspect-square sm:aspect-auto sm:h-[300px]">
              <img
                src={generatedItems[0]?.url || "https://images.unsplash.com/photo-1620641788421-7a1c342ea42e?q=80&w=400&auto=format&fit=crop"}
                alt={`AI generated ${mode}`}
                className={cn("rounded-xl object-cover w-full h-full", isRotating ? "animate-[spin_10s_linear_infinite]" : "")}
              />

              {mode !== "image" && (
                <div className="absolute inset-0 flex items-center justify-center bg-black/30">
                  <button
                    onClick={() => setIsPlaying(!isPlaying)}
                    className="w-12 h-12 flex items-center justify-center rounded-full bg-white/20 backdrop-blur-sm hover:bg-white/30 transition-colors"
                  >
                    {isPlaying ? (
                      <Pause className="w-6 h-6 text-white" />
                    ) : (
                      <Play className="w-6 h-6 text-white ml-1" />
                    )}
                  </button>
                </div>
              )}

              {mode === "avatar" && (
                <button
                  onClick={() => setIsRotating(!isRotating)}
                  className="absolute bottom-3 right-3 w-8 h-8 flex items-center justify-center rounded-full bg-white/20 backdrop-blur-sm hover:bg-white/30 transition-colors"
                >
                  <RotateCw className="w-4 h-4 text-white" />
                </button>
              )}
            </div>
          </div>
        )}
      </div>

      {!isLoading && (
        <div className="space-y-4">
          <div className="p-3 space-y-2 bg-zinc-50 dark:bg-zinc-800/50 rounded-xl">
            <div className="flex justify-between text-sm">
              <span className="text-zinc-500">Quality</span>
              <span className="text-zinc-900 dark:text-zinc-100">{settings.resolution}</span>
            </div>
            <div className="flex justify-between text-sm">
              <span className="text-zinc-500">Model</span>
              <span className="text-zinc-900 dark:text-zinc-100">{settings.aiModel}</span>
            </div>
            {mode === "video" && (
              <div className="flex justify-between text-sm">
                <span className="text-zinc-500">Duration</span>
                <span className="text-zinc-900 dark:text-zinc-100">00:07</span>
              </div>
            )}
          </div>

          {renderGallery()}

          <div className="flex items-center justify-between gap-2">
            <button
              type="button"
              onClick={handleBackToSettings}
              className="w-full h-9 flex items-center justify-center gap-2 border border-zinc-200 dark:border-zinc-700 text-zinc-900 dark:text-zinc-100 text-sm font-medium rounded-xl hover:bg-zinc-50 dark:hover:bg-zinc-800 transition-colors"
            >
              Back to Settings
            </button>
            <button
              type="button"
              className="w-full h-9 flex items-center justify-center gap-2 bg-zinc-900 hover:bg-zinc-800 dark:bg-white dark:hover:bg-zinc-100 dark:text-zinc-900 text-white text-sm font-medium rounded-xl transition-colors shadow-sm"
            >
              Download
            </button>
          </div>
        </div>
      )}
    </div>
  );

  const renderGallery = () => {
    const items = generatedItems.slice(0, 3);
    if (items.length === 0) return null;

    return (
      <div className="space-y-2">
        <h4 className="text-xs font-medium text-zinc-500">Recent Generations</h4>
        <div className="grid grid-cols-4 gap-2">
          {items.map((item) => (
            <div key={item.id} className="relative group aspect-square rounded-lg overflow-hidden border border-zinc-200 dark:border-zinc-800">
              <img
                src={item.url}
                alt={item.prompt}
                className="object-cover w-full h-full"
              />
              <div className="absolute inset-0 bg-gradient-to-t from-black/60 to-transparent opacity-0 group-hover:opacity-100 transition-opacity flex items-end p-1.5">
                <div className="flex items-center gap-1">
                  {item.type === "image" && <ImageIcon className="w-3 h-3 text-white" />}
                  {item.type === "video" && <Film className="w-3 h-3 text-white" />}
                  {item.type === "avatar" && <Cube className="w-3 h-3 text-white" />}
                  <span className="text-[10px] text-white truncate">
                    {new Date(item.timestamp).toLocaleDateString()}
                  </span>
                </div>
              </div>
            </div>
          ))}
        </div>
      </div>
    );
  };

  const renderHistory = () => (
    <div className="flex flex-col h-full p-4 space-y-4">
      <div className="flex items-center gap-2">
        <button
          onClick={handleBackToSettings}
          className="p-1.5 rounded-lg hover:bg-zinc-100 dark:hover:bg-zinc-800 transition-colors"
        >
          <ArrowLeft className="w-4 h-4 text-zinc-500" />
        </button>
        <h3 className="text-sm font-medium text-zinc-900 dark:text-zinc-100">Generation History</h3>
      </div>

      <div className="relative">
        <Search className="absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-zinc-500" />
        <input
          type="text"
          placeholder="Search by prompt..."
          value={searchQuery}
          onChange={(e) => setSearchQuery(e.target.value)}
          className="w-full h-9 pl-9 pr-3 bg-zinc-100 dark:bg-zinc-800 border-none rounded-lg text-sm text-zinc-900 dark:text-zinc-100 placeholder-zinc-500 focus:outline-none focus:ring-2 focus:ring-fuchsia-500/50"
        />
      </div>

      <div className="flex-1 overflow-y-auto space-y-2 pr-1">
        {filteredItems.length === 0 ? (
          <div className="flex flex-col items-center justify-center h-full text-center p-4">
            <Clock className="w-8 h-8 text-zinc-400 mb-2" />
            <p className="text-sm text-zinc-500">No generations found</p>
            {searchQuery && <p className="text-xs text-zinc-400 mt-1">Try a different search term</p>}
          </div>
        ) : (
          filteredItems.map((item) => (
            <div
              key={item.id}
              onClick={() => handleSelectHistoryItem(item.id)}
              className="flex items-center gap-3 p-2 rounded-lg hover:bg-zinc-100 dark:hover:bg-zinc-800 cursor-pointer transition-colors border border-transparent hover:border-zinc-200 dark:hover:border-zinc-700"
            >
              <div className="relative w-12 h-12 rounded-md overflow-hidden flex-shrink-0 bg-zinc-200 dark:bg-zinc-800">
                <img
                  src={item.url}
                  alt={item.prompt}
                  className="object-cover w-full h-full"
                />
              </div>
              <div className="flex-1 min-w-0">
                <p className="text-xs font-medium text-zinc-900 dark:text-zinc-100 truncate">{item.prompt}</p>
                <div className="flex items-center gap-1 mt-1">
                  <span className="text-[10px] text-zinc-500">{formatDate(item.timestamp)}</span>
                  <span className="text-[10px] text-zinc-400">•</span>
                  <span className="text-[10px] text-zinc-500 capitalize">{item.type}</span>
                </div>
              </div>
            </div>
          ))
        )}
      </div>
    </div>
  );

  return (
    <div className={cn("group relative overflow-hidden w-full max-w-sm mx-auto bg-white dark:bg-zinc-950 border border-zinc-200 dark:border-zinc-800 rounded-2xl transition-all duration-300 hover:shadow-xl dark:hover:shadow-2xl dark:hover:shadow-black/50 min-h-[600px] flex flex-col justify-between", className)}>
      {renderHeader()}

      <div className="px-4 py-2 border-b border-zinc-200 dark:border-zinc-800">
        <div className="flex w-full p-1 bg-zinc-100 dark:bg-zinc-900 rounded-lg">
          {(["image", "video", "avatar"] as GenerationMode[]).map((m) => (
            <button
              key={m}
              onClick={() => handleModeChange(m)}
              className={cn(
                "flex-1 flex items-center justify-center gap-2 py-1.5 text-xs font-medium rounded-md transition-all",
                mode === m
                  ? "bg-white dark:bg-zinc-800 text-zinc-900 dark:text-zinc-100 shadow-sm"
                  : "text-zinc-500 hover:text-zinc-900 dark:hover:text-zinc-300"
              )}
            >
              {m === "image" && <ImageIcon className="w-3.5 h-3.5" />}
              {m === "video" && <Film className="w-3.5 h-3.5" />}
              {m === "avatar" && <Cube className="w-3.5 h-3.5" />}
              <span className="capitalize">{m}</span>
            </button>
          ))}
        </div>
      </div>

      <div className="flex-1 overflow-hidden flex flex-col">
        {showHistory ? renderHistory() : showForm ? renderForm() : renderPreview()}
      </div>
    </div>
  );
}

--- FILE: frontend-web/registry/cards/AnimatedBanner.tsx ---

import React, { useEffect, useState } from "react";
import { cn } from "../core/utils";

export type AnimatedBannerProps = {
  title: string;
  subtitle?: string;
  ctaLabel?: string;
  href?: string;
  videoSrc: string;
  posterSrc?: string;
  /** Countdown target. Renders a DD:HH:MM:SS timer that ticks down to it. */
  deadline?: Date | number | string;
  /** Solid color faded from the text side of the banner. */
  overlayColor?: string;
  className?: string;
};

type TimeParts = { days: number; hours: number; minutes: number; seconds: number };

function getTimeParts(target: number): TimeParts {
  const diff = Math.max(0, target - Date.now());
  const totalSeconds = Math.floor(diff / 1000);
  return {
    days: Math.floor(totalSeconds / 86400),
    hours: Math.floor((totalSeconds % 86400) / 3600),
    minutes: Math.floor((totalSeconds % 3600) / 60),
    seconds: totalSeconds % 60,
  };
}

function pad(value: number) {
  return value.toString().padStart(2, "0");
}

function Countdown({ target }: { target: number }) {
  const [parts, setParts] = useState<TimeParts>(() => getTimeParts(target));

  useEffect(() => {
    setParts(getTimeParts(target));
    const timer = window.setInterval(() => {
      setParts(getTimeParts(target));
    }, 1000);
    return () => window.clearInterval(timer);
  }, [target]);

  const segments = [parts.days, parts.hours, parts.minutes, parts.seconds];

  return (
    <div
      aria-hidden="true"
      className="flex shrink-0 items-center gap-1 font-mono text-sm font-medium tabular-nums text-white/90"
    >
      {segments.map((segment, index) => (
        <span className="flex items-center gap-1" key={index}>
          <span className="rounded-md bg-white/10 px-1.5 py-1 backdrop-blur-sm">
            {pad(segment)}
          </span>
          {index < segments.length - 1 ? (
            <span className="text-white/40">:</span>
          ) : null}
        </span>
      ))}
    </div>
  );
}

export function AnimatedBanner({
  title,
  subtitle,
  ctaLabel = "Explore",
  href = "#",
  videoSrc,
  posterSrc,
  deadline,
  overlayColor = "oklch(0.15 0 0)",
  className,
}: AnimatedBannerProps) {
  const target =
    deadline === undefined ? undefined : new Date(deadline).getTime();

  return (
    <a
      className={cn(
        "group relative block aspect-[5/2] w-full overflow-hidden rounded-2xl [--banner-overlay:var(--overlay)]",
        className,
      )}
      href={href}
      style={{ "--overlay": overlayColor } as React.CSSProperties}
    >
      <video
        aria-hidden="true"
        autoPlay
        className="absolute inset-0 h-full w-full object-cover"
        loop
        muted
        playsInline
        poster={posterSrc}
        src={videoSrc}
      />

      {/* gradient overlay: solid on the text side, transparent over the image */}
      <div
        aria-hidden="true"
        className="absolute inset-0 bg-gradient-to-r from-[var(--banner-overlay)] via-[var(--banner-overlay)]/70 to-transparent"
      />

      {/* interaction depth: strengthen the text side on hover/focus */}
      <div
        aria-hidden="true"
        className="absolute inset-0 bg-gradient-to-r from-[var(--banner-overlay)] to-transparent opacity-0 transition-opacity duration-300 group-hover:opacity-40 group-focus-visible:opacity-40"
      />

      {/* content layer */}
      <div className="relative z-10 flex h-full items-end justify-between gap-4 p-5 text-white">
        <div className="min-w-0 max-w-xs">
          <h3 className="text-balance text-lg font-semibold leading-tight">
            {title}
          </h3>
          {subtitle ? (
            <p className="mt-1 text-pretty text-sm leading-snug text-white/80">
              {subtitle}
            </p>
          ) : null}
          <span className="mt-3 inline-flex items-center gap-1 text-sm font-medium text-white transition-transform duration-200 group-hover:gap-1.5">
            {ctaLabel}
            <svg
              aria-hidden="true"
              className="size-4"
              fill="none"
              stroke="currentColor"
              strokeWidth="2"
              viewBox="0 0 24 24"
            >
              <path d="M5 12h14M13 6l6 6-6 6" strokeLinecap="round" strokeLinejoin="round" />
            </svg>
          </span>
        </div>
        {target !== undefined ? <Countdown target={target} /> : null}
      </div>
    </a>
  );
}

--- FILE: frontend-web/registry/cards/HoverPlayCard.tsx ---

import React, { useRef, useState, useEffect } from "react";
import { Play, Pause } from "lucide-react";
import { motion, AnimatePresence } from "framer-motion";
import { cn } from "../core/utils";

export type HoverPlayCardProps = {
  src: string;
  poster?: string;
  className?: string;
  loop?: boolean;
  mutedOnHover?: boolean; // default true to satisfy autoplay policy
};

export function HoverPlayCard({
  src,
  poster,
  className,
  loop = false,
  mutedOnHover = true,
}: HoverPlayCardProps) {
  const videoRef = useRef<HTMLVideoElement | null>(null);
  const [isHovering, setIsHovering] = useState(false);
  const [isPlaying, setIsPlaying] = useState(false);
  const [userStarted, setUserStarted] = useState(false); // true when user clicked play
  const [prevMuted, setPrevMuted] = useState<boolean | null>(null);

  // Play muted on hover (if allowed). Pause on leave.
  useEffect(() => {
    const video = videoRef.current;
    if (!video) return;

    let ignore = false;

    const doPlayMuted = async () => {
      if (!video) return;
      // Save previous muted state first time
      if (prevMuted === null) setPrevMuted(video.muted);

      if (mutedOnHover) {
        video.muted = true;
      }
      try {
        await video.play();
        if (!ignore) setIsPlaying(true);
      } catch {
        // autoplay blocked (shouldn't if muted) — ignore
        if (!ignore) setIsPlaying(false);
      }
    };

    const doPause = () => {
      if (!video) return;
      video.pause();
      setIsPlaying(false);
      // restore mute state only if user didn't start playback manually
      if (!userStarted && prevMuted !== null) {
        video.muted = prevMuted;
      }
    };

    if (isHovering && !userStarted) {
      // only auto play on hover when user hasn't manually started playback
      void doPlayMuted();
    } else if (!isHovering && !userStarted) {
      doPause();
    }

    return () => {
      ignore = true;
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [isHovering, mutedOnHover, userStarted]);

  // If user clicks play icon: toggle playback and treat as user gesture
  const handleIconClick = async () => {
    const video = videoRef.current;
    if (!video) return;

    // If not playing, user-initiated play: unmute (restore prevMuted false) so user hears audio
    if (!isPlaying) {
      // Mark that user started explicit playback
      setUserStarted(true);
      // restore to unmuted so clicking plays with sound
      video.muted = false;
      setPrevMuted(false);
      try {
        await video.play();
        setIsPlaying(true);
      } catch (err) {
        // if play fails, keep state consistent
        console.error("Play failed:", err);
        setIsPlaying(false);
      }
    } else {
      // pause on click
      video.pause();
      setIsPlaying(false);
    }
  };

  // keep visual play state in sync with native events (in case video ends or is paused externally)
  useEffect(() => {
    const video = videoRef.current;
    if (!video) return;
    const onPlay = () => setIsPlaying(true);
    const onPause = () => setIsPlaying(false);
    const onEnded = () => {
      setIsPlaying(false);
      setUserStarted(false); // allow hover autoplay after end if desired
    };

    video.addEventListener("play", onPlay);
    video.addEventListener("pause", onPause);
    video.addEventListener("ended", onEnded);

    return () => {
      video.removeEventListener("play", onPlay);
      video.removeEventListener("pause", onPause);
      video.removeEventListener("ended", onEnded);
    };
  }, []);

  return (
    <div
      className={cn(
        "relative rounded-xl overflow-hidden shadow-sm group",
        className,
      )}
      onMouseEnter={() => setIsHovering(true)}
      onMouseLeave={() => setIsHovering(false)}
    >
      <video
        ref={videoRef}
        src={src}
        poster={poster}
        loop={loop}
        playsInline
        // do not set autoplay here — we control playback on hover/click
        className="w-full h-full max-w-xl object-cover"
      />

      {/* Overlay: Play/Pause button (always visible but subtle) */}
      <AnimatePresence>
        {/* show when not playing OR when hovered (to allow pause by clicking) */}
        {(isHovering || !isPlaying) && (
          <motion.div
            key="overlay"
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 }}
            exit={{ opacity: 0 }}
            className="absolute inset-0 flex items-center justify-center pointer-events-none"
          >
            <button
              onClick={(e) => {
                e.stopPropagation();
                handleIconClick();
              }}
              className="inline-flex items-center justify-center transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 pointer-events-auto bg-black/20 hover:bg-black/40 text-white rounded-full w-16 h-16"
              aria-label={isPlaying ? "Pause video" : "Play video"}
            >
              {isPlaying ? <Pause className="w-8 h-8" /> : <Play className="w-8 h-8 ml-1" />}
            </button>
          </motion.div>
        )}
      </AnimatePresence>

      {/* small subtle status badge bottom-left */}
      <div className="absolute left-3 bottom-3 text-xs text-white/70 bg-black/40 backdrop-blur-md px-3 py-1 rounded-full">
        {isPlaying ? "Playing" : "Paused"}
      </div>
    </div>
  );
}

--- FILE: frontend-web/registry/cards/InfoCard.tsx ---

import React, {
  useState,
  useRef,
  useEffect,
  createContext,
  useContext,
  useMemo,
  useCallback,
} from "react";
import { motion, AnimatePresence } from "framer-motion";
import { cn } from "../core/utils";

interface InfoCardTitleProps extends React.HTMLAttributes<HTMLDivElement> {
  children: React.ReactNode;
}

interface InfoCardDescriptionProps
  extends React.HTMLAttributes<HTMLDivElement> {
  children: React.ReactNode;
}

export const InfoCardTitle = React.memo(
  ({ children, className, ...props }: InfoCardTitleProps) => {
    return (
      <div className={cn("font-medium mb-1 dark:text-white", className)} {...props}>
        {children}
      </div>
    );
  }
);
InfoCardTitle.displayName = "InfoCardTitle";

export const InfoCardDescription = React.memo(
  ({ children, className, ...props }: InfoCardDescriptionProps) => {
    return (
      <div
        className={cn("text-slate-500 dark:text-slate-400 leading-4", className)}
        {...props}
      >
        {children}
      </div>
    );
  }
);
InfoCardDescription.displayName = "InfoCardDescription";

interface CommonCardProps extends React.HTMLAttributes<HTMLDivElement> {
  children: React.ReactNode;
}

export interface InfoCardProps extends React.HTMLAttributes<HTMLDivElement> {
  children: React.ReactNode;
  storageKey?: string;
  dismissType?: "once" | "forever";
}

type InfoCardContentProps = CommonCardProps;
type InfoCardFooterProps = CommonCardProps;
type InfoCardDismissProps = React.HTMLAttributes<HTMLDivElement> & {
  children: React.ReactNode;
  onDismiss?: () => void;
};
type InfoCardActionProps = CommonCardProps;

export const InfoCardContent = React.memo(
  ({ children, className, ...props }: InfoCardContentProps) => {
    return (
      <div className={cn("flex flex-col gap-1 text-xs", className)} {...props}>
        {children}
      </div>
    );
  }
);
InfoCardContent.displayName = "InfoCardContent";

// eslint-disable-next-line @typescript-eslint/no-explicit-any
interface MediaItem extends Record<string, any> {
  type?: "image" | "video";
  src: string;
  alt?: string;
  className?: string;
}

export interface InfoCardMediaProps extends React.HTMLAttributes<HTMLDivElement> {
  media: MediaItem[];
  loading?: "eager" | "lazy";
  shrinkHeight?: number;
  expandHeight?: number;
}

const InfoCardImageContext = createContext<{
  handleMediaLoad: (mediaSrc: string) => void;
  setAllImagesLoaded: (loaded: boolean) => void;
}>({
  handleMediaLoad: () => {},
  setAllImagesLoaded: () => {},
});

const InfoCardContext = createContext<{
  isHovered: boolean;
  onDismiss: () => void;
}>({
  isHovered: false,
  onDismiss: () => {},
});

export function InfoCard({
  children,
  className,
  storageKey,
  dismissType = "once",
}: InfoCardProps) {
  if (dismissType === "forever" && !storageKey) {
    throw new Error(
      'A storageKey must be provided when using dismissType="forever"'
    );
  }

  const [isHovered, setIsHovered] = useState(false);
  const [allImagesLoaded, setAllImagesLoaded] = useState(true);
  const [isDismissed, setIsDismissed] = useState(() => {
    if (typeof window === "undefined" || dismissType === "once") return false;
    return dismissType === "forever"
      ? localStorage.getItem(storageKey!) === "dismissed"
      : false;
  });

  const handleDismiss = useCallback(() => {
    setIsDismissed(true);
    if (dismissType === "forever") {
      localStorage.setItem(storageKey!, "dismissed");
    }
  }, [storageKey, dismissType]);

  const imageContextValue = useMemo(
    () => ({
      handleMediaLoad: () => {},
      setAllImagesLoaded,
    }),
    [setAllImagesLoaded]
  );

  const cardContextValue = useMemo(
    () => ({
      isHovered,
      onDismiss: handleDismiss,
    }),
    [isHovered, handleDismiss]
  );

  return (
    <InfoCardContext.Provider value={cardContextValue}>
      <InfoCardImageContext.Provider value={imageContextValue}>
        <AnimatePresence>
          {!isDismissed && (
            <motion.div
              initial={{ opacity: 0, y: 10 }}
              animate={{
                opacity: allImagesLoaded ? 1 : 0,
                y: allImagesLoaded ? 0 : 10,
              }}
              exit={{
                opacity: 0,
                y: 10,
                transition: { duration: 0.2 },
              }}
              transition={{ duration: 0.3, delay: 0 }}
              className={cn("group rounded-xl border border-slate-200 dark:border-slate-800 bg-white dark:bg-slate-900 p-4 shadow-sm", className)}
              onMouseEnter={() => setIsHovered(true)}
              onMouseLeave={() => setIsHovered(false)}
            >
              {children}
            </motion.div>
          )}
        </AnimatePresence>
      </InfoCardImageContext.Provider>
    </InfoCardContext.Provider>
  );
}

export const InfoCardFooter = ({ children, className }: InfoCardFooterProps) => {
  const { isHovered } = useContext(InfoCardContext);

  return (
    <motion.div
      className={cn(
        "flex justify-between items-center text-xs text-slate-500 dark:text-slate-400 mt-2 overflow-hidden",
        className
      )}
      initial={{ opacity: 0, height: "0px" }}
      animate={{
        opacity: isHovered ? 1 : 0,
        height: isHovered ? "auto" : "0px",
      }}
      transition={{
        type: "spring",
        stiffness: 300,
        damping: 30,
        duration: 0.3,
      }}
    >
      {children}
    </motion.div>
  );
};

export const InfoCardDismiss = React.memo(
  ({ children, className, onDismiss, ...props }: InfoCardDismissProps) => {
    const { onDismiss: contextDismiss } = useContext(InfoCardContext);

    const handleClick = (e: React.MouseEvent) => {
      e.preventDefault();
      onDismiss?.();
      contextDismiss();
    };

    return (
      <div
        className={cn("cursor-pointer hover:text-slate-800 dark:hover:text-slate-200 transition-colors", className)}
        onClick={handleClick}
        {...props}
      >
        {children}
      </div>
    );
  }
);
InfoCardDismiss.displayName = "InfoCardDismiss";

export const InfoCardAction = React.memo(
  ({ children, className, ...props }: InfoCardActionProps) => {
    return (
      <div className={cn("hover:text-blue-500 transition-colors cursor-pointer font-medium", className)} {...props}>
        {children}
      </div>
    );
  }
);
InfoCardAction.displayName = "InfoCardAction";

export const InfoCardMedia = ({
  media = [],
  className,
  loading = undefined,
  shrinkHeight = 75,
  expandHeight = 150,
}: InfoCardMediaProps) => {
  const { isHovered } = useContext(InfoCardContext);
  const { setAllImagesLoaded } = useContext(InfoCardImageContext);
  const [isOverflowVisible, setIsOverflowVisible] = useState(false);
  const loadedMedia = useRef(new Set());

  const handleMediaLoad = (mediaSrc: string) => {
    loadedMedia.current.add(mediaSrc);
    if (loadedMedia.current.size === Math.min(3, media.slice(0, 3).length)) {
      setAllImagesLoaded(true);
    }
  };

  const processedMedia = useMemo(
    () =>
      media.map((item) => ({
        ...item,
        type: item.type || "image",
      })),
    [media]
  );

  const displayMedia = useMemo(
    () => processedMedia.slice(0, 3),
    [processedMedia]
  );

  useEffect(() => {
    if (media.length > 0) {
      setAllImagesLoaded(false);
      loadedMedia.current.clear();
    } else {
      setAllImagesLoaded(true); // No media to load
    }
  }, [media.length, setAllImagesLoaded]);

  useEffect(() => {
    let timeoutId: NodeJS.Timeout;
    if (isHovered) {
      timeoutId = setTimeout(() => {
        setIsOverflowVisible(true);
      }, 100);
    } else {
      setIsOverflowVisible(false);
    }
    return () => clearTimeout(timeoutId);
  }, [isHovered]);

  const mediaCount = displayMedia.length;

  const getRotation = (index: number) => {
    if (!isHovered || mediaCount === 1) return 0;
    return (index - (mediaCount === 2 ? 0.5 : 1)) * 5;
  };

  const getTranslateX = (index: number) => {
    if (!isHovered || mediaCount === 1) return 0;
    return (index - (mediaCount === 2 ? 0.5 : 1)) * 20;
  };

  const getTranslateY = (index: number) => {
    if (!isHovered) return 0;
    if (mediaCount === 1) return -5;
    return index === 0 ? -10 : index === 1 ? -5 : 0;
  };

  const getScale = (index: number) => {
    if (!isHovered) return 1;
    return mediaCount === 1 ? 1 : 0.95 + index * 0.02;
  };

  return (
    <InfoCardImageContext.Provider
      value={{
        handleMediaLoad,
        setAllImagesLoaded,
      }}
    >
      <motion.div
        className={cn("relative mt-3 rounded-md", className)}
        animate={{
          height:
            media.length > 0
              ? isHovered
                ? expandHeight
                : shrinkHeight
              : "auto",
        }}
        style={{
          overflow: isOverflowVisible ? "visible" : "hidden",
        }}
        transition={{
          type: "spring",
          stiffness: 300,
          damping: 30,
          duration: 0.3,
        }}
      >
        <div
          className={cn(
            "relative",
            media.length > 0 ? { height: shrinkHeight } : "h-auto"
          )}
        >
          {displayMedia.map((item, index) => {
            const {
              type,
              src,
              alt,
              className: itemClassName,
              ...mediaProps
            } = item;

            return (
              <motion.div
                key={src}
                className="absolute w-full"
                animate={{
                  rotateZ: getRotation(index),
                  x: getTranslateX(index),
                  y: getTranslateY(index),
                  scale: getScale(index),
                }}
                transition={{
                  type: "spring",
                  stiffness: 300,
                  damping: 30,
                }}
              >
                {type === "video" ? (
                  <video
                    src={src}
                    className={cn(
                      "w-full h-full rounded-md border border-slate-200 dark:border-slate-800 object-cover shadow-lg",
                      itemClassName
                    )}
                    onLoadedData={() => handleMediaLoad(src)}
                    preload="metadata"
                    muted
                    playsInline
                    {...mediaProps}
                  />
                ) : (
                  <img
                    src={src}
                    alt={alt}
                    className={cn(
                      "w-full h-full rounded-md border border-slate-200 dark:border-slate-800 object-cover shadow-lg",
                      itemClassName
                    )}
                    onLoad={() => handleMediaLoad(src)}
                    loading={loading}
                    {...mediaProps}
                  />
                )}
              </motion.div>
            );
          })}
        </div>

        <motion.div
          className="absolute right-0 bottom-0 left-0 h-10 bg-gradient-to-b from-transparent to-white dark:to-slate-900 pointer-events-none"
          animate={{ opacity: isHovered ? 0 : 1 }}
          transition={{
            type: "spring",
            stiffness: 300,
            damping: 30,
            duration: 0.3,
          }}
        />
      </motion.div>
    </InfoCardImageContext.Provider>
  );
};

--- FILE: frontend-web/registry/cards/VideoGeneratorCard.tsx ---

import * as React from "react"
import { cn } from "../core/utils"
import { X, Plus, Zap, Image as ImageIcon, Mic, ArrowUp, Loader2 } from "lucide-react"

export interface StoryboardImage {
  src: string;
  alt: string;
}

export interface VideoGeneratorCardProps {
  storyboardImages: StoryboardImage[];
  initialPrompt?: string;
  onClose?: () => void;
  onGenerate?: (prompt: string) => void;
  isLoading?: boolean;
  className?: string;
}

/**
 * A component that provides a user interface for generating video content
 * from a storyboard and a text prompt, inspired by modern AI tools.
 */
const VideoGeneratorCard = React.forwardRef<HTMLDivElement, VideoGeneratorCardProps>(
  ({ storyboardImages, initialPrompt = "", onClose, onGenerate, isLoading = false, className }, ref) => {
    // State to manage the prompt text
    const [prompt, setPrompt] = React.useState(initialPrompt);

    const handleGenerateClick = () => {
      if (onGenerate) {
        onGenerate(prompt);
      }
    };

    return (
      <div 
        ref={ref} 
        className={cn(
          "w-full max-w-md mx-auto bg-white/80 dark:bg-zinc-950/80 backdrop-blur-sm border border-slate-200/40 dark:border-zinc-800/40 rounded-xl overflow-hidden shadow-2xl animate-fade-in", 
          className
        )}
      >
        {/* Header with Close button and Drafts label */}
        <div className="flex flex-row items-center justify-between p-3 border-b border-slate-200/40 dark:border-zinc-800/40">
          <button 
            className="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors hover:bg-slate-100 hover:text-slate-900 dark:hover:bg-zinc-800 dark:hover:text-slate-50 focus-visible:outline-none h-8 w-8 text-slate-500 dark:text-slate-400" 
            onClick={onClose} 
            aria-label="Close"
          >
            <X className="h-4 w-4" />
          </button>
          <span className="text-sm font-medium text-slate-500 dark:text-slate-400">Drafts</span>
        </div>

        <div className="p-4 space-y-4">
          {/* Storyboard Image Thumbnails */}
          <div className="flex items-center gap-2">
            {storyboardImages.map((image, index) => (
              <div key={index} className="relative w-20 h-20 rounded-lg overflow-hidden transition-transform duration-300 hover:scale-105 cursor-pointer">
                <img src={image.src} alt={image.alt} className="w-full h-full object-cover" />
              </div>
            ))}
          </div>

          {/* Prompt Input Area */}
          <textarea
            value={prompt}
            onChange={(e) => setPrompt(e.target.value)}
            placeholder="Use the storyboard to create a video..."
            className="flex w-full rounded-md px-3 py-2 text-sm shadow-sm placeholder:text-slate-500 dark:placeholder:text-slate-400 disabled:cursor-not-allowed disabled:opacity-50 text-slate-900 dark:text-slate-100 bg-slate-50/50 dark:bg-zinc-900/50 border border-slate-200/40 dark:border-zinc-800/40 min-h-[80px] resize-none focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-slate-400 dark:focus-visible:ring-slate-600"
          />

          {/* Bottom Toolbar */}
          <div className="flex items-center justify-between gap-2">
            <div className="flex items-center gap-1">
              <button className="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors hover:bg-slate-100 hover:text-slate-900 dark:hover:bg-zinc-800 dark:hover:text-slate-50 h-9 w-9 text-slate-500 dark:text-slate-400" aria-label="Add content">
                <Plus className="h-4 w-4" />
              </button>
              <button className="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors hover:bg-slate-100 hover:text-slate-900 dark:hover:bg-zinc-800 dark:hover:text-slate-50 h-9 w-9 text-slate-500 dark:text-slate-400" aria-label="Quick edit">
                <Zap className="h-4 w-4" />
              </button>
              {/* Media Type Toggle */}
              <div className="flex items-center gap-1 bg-slate-100 dark:bg-zinc-800 p-1 rounded-md">
                <button className="inline-flex items-center justify-center rounded-md font-medium transition-colors hover:bg-slate-200 dark:hover:bg-zinc-700 h-7 px-2 text-xs text-slate-500 dark:text-slate-400">
                  <ImageIcon className="h-4 w-4 mr-1.5" />
                  Image
                </button>
                <button className="inline-flex items-center justify-center rounded-md font-medium transition-colors bg-white dark:bg-zinc-950 text-slate-900 dark:text-slate-100 h-7 px-2 text-xs shadow-sm">
                  <svg viewBox="0 0 24 24" fill="currentColor" className="h-4 w-4 mr-1.5"><path d="M17 10.5V7c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h12c.55 0 1-.45 1-1v-3.5l4 4v-11l-4 4z"></path></svg>
                  Video
                </button>
              </div>
            </div>
            
            <div className="flex items-center gap-1">
              <button className="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors hover:bg-slate-100 hover:text-slate-900 dark:hover:bg-zinc-800 dark:hover:text-slate-50 h-9 w-9 text-slate-500 dark:text-slate-400" aria-label="Use microphone">
                <Mic className="h-4 w-4" />
              </button>
              <button 
                className="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none disabled:opacity-50 h-9 w-9 bg-slate-900 text-white hover:bg-slate-900/90 dark:bg-slate-50 dark:text-slate-900 dark:hover:bg-slate-50/90" 
                onClick={handleGenerateClick} 
                disabled={isLoading} 
                aria-label="Generate video"
              >
                {isLoading ? <Loader2 className="h-4 w-4 animate-spin" /> : <ArrowUp className="h-4 w-4" />}
              </button>
            </div>
          </div>
        </div>
      </div>
    );
  }
);
VideoGeneratorCard.displayName = "VideoGeneratorCard";

export { VideoGeneratorCard };

--- FILE: frontend-web/registry/cards/VideoUploadCard.tsx ---

import React, { useState, useEffect, useCallback, useRef } from "react";
import { motion, AnimatePresence } from "framer-motion";
import { cn } from "../core/utils";
import { Upload, X, Play, Pause } from "lucide-react";

interface VideoUploadCardProps {
  className?: string;
  triggerAnimation?: boolean;
  onAnimationComplete?: () => void;
  title?: string;
  description?: string;
}

interface VideoComponentProps {
  isAnimating: boolean;
  onAnimationComplete?: () => void;
  filename?: string;
  onRemove?: () => void;
  videoUrl?: string;
}

interface UploadCardBaseProps {
  children: React.ReactNode;
  className?: string;
  isDragOver?: boolean;
  isUploading?: boolean;
}

// Utility function to truncate filename
const truncateFilename = (filename: string, maxLength: number = 30) => {
  if (filename.length <= maxLength) return filename;
  const extension = filename.split(".").pop();
  const nameWithoutExt = filename.replace(`.${extension}`, "");
  const truncatedName = nameWithoutExt.substring(
    0,
    maxLength - 3 - extension!.length
  );
  return `${truncatedName}...${extension}`;
};

const VideoComponent = ({
  isAnimating,
  onAnimationComplete,
  filename = "video.mp4",
  onRemove,
  videoUrl,
}: VideoComponentProps) => {
  const [isRemoving, setIsRemoving] = useState(false);
  const [shouldShow, setShouldShow] = useState(false);
  const [isPlaying, setIsPlaying] = useState(false);
  const [videoLoaded, setVideoLoaded] = useState(false);
  const videoRef = useRef<HTMLVideoElement>(null);

  // Update shouldShow when isAnimating changes
  useEffect(() => {
    if (isAnimating) {
      setShouldShow(true);
    }
  }, [isAnimating]);

  // Reset video loaded state when video URL changes
  useEffect(() => {
    if (videoUrl) {
      setVideoLoaded(false);
    }
  }, [videoUrl]);

  // Don't render if we shouldn't show and we're not removing
  if (!shouldShow && !isRemoving) return null;

  const displayName = truncateFilename(filename);

  const handleRemove = () => {
    setIsRemoving(true);
    setIsPlaying(false);
  };

  const handleRemoveComplete = () => {
    setShouldShow(false);
    setIsRemoving(false);
    onRemove?.();
  };

  const handlePlayClick = () => {
    if (videoRef.current) {
      if (isPlaying) {
        videoRef.current.pause();
        setIsPlaying(false);
      } else {
        videoRef.current.play();
        setIsPlaying(true);
      }
    }
  };

  // Handle video loading
  const handleVideoLoadedData = () => {
    setVideoLoaded(true);
    if (videoRef.current) {
      videoRef.current.addEventListener("ended", handleVideoEnd);
      // Pause immediately to show first frame
      videoRef.current.pause();
      // Set to a small time offset to show first frame
      videoRef.current.currentTime = 0.01;
    }
  };

  const handleVideoEnd = () => {
    setIsPlaying(false);
  };

  return (
    <AnimatePresence>
      {shouldShow && (
        <motion.div
          className="absolute z-10" // Between border (z-20) and upload area (z-0)
          initial={{
            // Start way above the screen so you first see the bottom edge
            left: "50%",
            top: "-300px", // Way above the screen
            x: "-50%",
            y: 0,
            opacity: 1, // Fully visible from start
          }}
          animate={
            isRemoving
              ? {
                  scale: 0,
                  opacity: 0,
                  filter: "blur(8px)",
                  transition: {
                    duration: 0.4,
                    ease: [0.23, 1, 0.32, 1],
                  },
                }
              : {
                  // Vending machine drop - slow start, fast finish
                  left: "50%",
                  top: "calc(50% - 0px)", // Center of upload area
                  x: "-50%",
                  y: "-50%",
                  opacity: 1,
                  transition: {
                    duration: 1.2, // Slightly longer for dramatic effect
                    ease: [0.55, 0.055, 0.675, 0.19], // Vending machine gravity curve - slow start, fast finish
                  },
                }
          }
          exit={{
            scale: 0,
            opacity: 0,
            filter: "blur(8px)",
            transition: {
              duration: 0.4,
              ease: [0.23, 1, 0.32, 1],
            },
          }}
          style={{
            transformOrigin: "center",
          }}
          onAnimationComplete={
            isRemoving ? handleRemoveComplete : onAnimationComplete
          }
        >
          <motion.div
            initial={{ scale: 0.9 }}
            animate={
              isRemoving
                ? {
                    scale: 0,
                    transition: { duration: 0.4 },
                  }
                : {
                    scale: 1.0,
                    transition: {
                      type: "spring",
                      stiffness: 250,
                      damping: 15, // Less damping for more bounce on landing
                      mass: 1.2,
                      delay: 0.7, // Delay until the drop is almost complete
                    },
                  }
            }
            className="rounded-lg bg-muted backdrop-blur-sm shadow-lg relative group min-w-[400px]"
          >
            {/* X button */}
            <button
              onClick={handleRemove}
              className="absolute -top-2 -right-2 w-5 h-5 bg-destructive text-destructive-foreground rounded-full flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity duration-200 hover:scale-110 z-30"
            >
              <X size={12} />
            </button>

            {/* Video Preview or Video Player */}
            <div className="relative">
              {videoUrl ? (
                <div className="relative">
                  <video
                    ref={videoRef}
                    src={videoUrl}
                    className="w-full aspect-video object-cover rounded-md shadow-md border-t border-l border-r border-border/30"
                    onEnded={handleVideoEnd}
                    onLoadedData={handleVideoLoadedData}
                    controls={false}
                    muted
                    playsInline
                  />
                  {/* Loading overlay - shows until video loads */}
                  {!videoLoaded && (
                    <div className="absolute inset-0 bg-muted rounded-md flex items-center justify-center">
                      <div className="w-8 h-8 border-2 border-primary border-t-transparent rounded-full animate-spin"></div>
                    </div>
                  )}
                  {/* Play button in bottom left corner */}
                  <button
                    onClick={handlePlayClick}
                    className="absolute bottom-0 left-0 w-8 h-8 rounded-full flex items-center justify-center transition-colors duration-200 group"
                  >
                    {isPlaying ? (
                      <Pause size={14} className="text-white ml-0.5" />
                    ) : (
                      <Play size={14} className="text-white ml-0.5" />
                    )}
                  </button>
                </div>
              ) : (
                <div className="w-full aspect-[21/9] bg-gradient-to-br from-primary/20 to-secondary/20 rounded-md flex items-center justify-center cursor-pointer hover:from-primary/30 hover:to-secondary/30 transition-colors duration-200">
                  <div className="w-20 h-20 bg-primary/30 rounded-full flex items-center justify-center hover:bg-primary/40 transition-colors duration-200">
                    <Play size={28} className="text-primary ml-1" />
                  </div>
                </div>
              )}
            </div>

            <div className="mt-2 px-2 pb-2">
              <span className="text-xs text-foreground/60 font-medium text-left block">
                {displayName}
              </span>
            </div>
          </motion.div>
        </motion.div>
      )}
    </AnimatePresence>
  );
};

const UploadCardBase = ({
  children,
  className,
  isDragOver = false,
  isUploading = false,
}: UploadCardBaseProps) => {
  const hasChildren = React.Children.count(children) > 0;

  return (
    <div className="relative">
      {/* Background upload area - z-0 */}
      <div
        className={cn(
          "rounded-xl min-h-[310px] flex items-center justify-center relative transition-colors duration-200 z-0",
          // Add cursor pointer when clickable and not uploading
          !isUploading && "cursor-pointer hover:bg-accent/20",
          // Background color changes based on state
          isUploading
            ? "bg-primary/20"
            : isDragOver
            ? "bg-accent/40 shadow-inner"
            : "bg-card",
          className
        )}
      >
        {/* Upload icon in background - only shows when no children */}
        {!hasChildren && (
          <div className="absolute inset-0 flex items-center justify-center pointer-events-none">
            <Upload
              size={48}
              className={cn(
                "transition-colors duration-200",
                isDragOver ? "text-primary" : "text-muted",
                isUploading && "text-primary"
              )}
            />
          </div>
        )}

        {/* Content layer - above the background icon */}
        <div className="relative z-10 w-full">{children}</div>
      </div>

      {/* Dashed border overlay - z-20, sits above video component */}
      <div
        className={cn(
          "absolute inset-0 rounded-xl border-2 border-dashed pointer-events-none z-20",
          isUploading
            ? "border-primary/60"
            : isDragOver
            ? "border-accent/80"
            : "border-border"
        )}
      />
    </div>
  );
};

export function VideoUploadCard({
  className,
  triggerAnimation = false,
  onAnimationComplete,
  title = "Upload Your Video",
  description = "Drop in your videos and start playing instantly.",
}: VideoUploadCardProps) {
  const [isAnimating, setIsAnimating] = useState(false);
  const [isDragOver, setIsDragOver] = useState(false);
  const [isUploading, setIsUploading] = useState(false);
  const [uploadedFile, setUploadedFile] = useState<File | null>(null);
  const [videoUrl, setVideoUrl] = useState<string | null>(null);
  const fileInputRef = React.useRef<HTMLInputElement>(null);

  useEffect(() => {
    if (triggerAnimation) {
      setIsAnimating(true);
    }
  }, [triggerAnimation]);

  const handleAnimationComplete = () => {
    // Don't automatically stop the animation - keep it visible
    onAnimationComplete?.();
  };

  const handleDragOver = useCallback((e: React.DragEvent) => {
    e.preventDefault();
    e.stopPropagation();
    setIsDragOver(true);
  }, []);

  const handleDragLeave = useCallback((e: React.DragEvent) => {
    e.preventDefault();
    e.stopPropagation();
    setIsDragOver(false);
  }, []);

  const handleDrop = useCallback((e: React.DragEvent) => {
    e.preventDefault();
    e.stopPropagation();
    setIsDragOver(false);

    const files = Array.from(e.dataTransfer.files);
    const videoFile = files.find((file) => file.type.startsWith("video/"));

    if (videoFile) {
      setUploadedFile(videoFile);
      setIsUploading(true);

      // Create object URL for video preview
      const url = URL.createObjectURL(videoFile);
      setVideoUrl(url);

      // Simulate upload process
      setTimeout(() => {
        setIsUploading(false);
        setIsAnimating(true); // Trigger animation after upload
      }, 200); // Much faster upload simulation
    }
  }, []);

  const handleFileSelect = useCallback(
    (e: React.ChangeEvent<HTMLInputElement>) => {
      const file = e.target.files?.[0];
      if (file && file.type.startsWith("video/")) {
        setUploadedFile(file);
        setIsUploading(true);

        // Create object URL for video preview
        const url = URL.createObjectURL(file);
        setVideoUrl(url);

        // Simulate upload process
        setTimeout(() => {
          setIsUploading(false);
          setIsAnimating(true); // Trigger animation after upload
        }, 200); // Much faster upload simulation
      }
    },
    []
  );

  const handleRemoveFile = useCallback(() => {
    setUploadedFile(null);
    setIsAnimating(false);
    if (videoUrl) {
      URL.revokeObjectURL(videoUrl);
      setVideoUrl(null);
    }
    // Reset the file input so it can trigger onChange again for the same file
    if (fileInputRef.current) {
      fileInputRef.current.value = "";
    }
  }, [videoUrl]);

  const handleBaseClick = useCallback(() => {
    if (!isUploading && !uploadedFile) {
      fileInputRef.current?.click();
    }
  }, [isUploading, uploadedFile]);

  return (
    <motion.div
      className={cn("relative w-full max-w-lg mx-auto", className)}
      initial={{ opacity: 0, y: 20 }}
      animate={{ opacity: 1, y: 0 }}
      transition={{ type: "spring", stiffness: 300, damping: 30 }}
    >
      <div
        className={cn(
          "relative overflow-hidden rounded-xl border border-border/50 bg-card text-center"
        )}
      >
        {/* Top masking area - z-30, covers video until it reaches upload area */}
        <div 
          className="absolute top-0 left-0 right-0 bg-card pointer-events-none z-30"
          style={{ 
            height: '24px', // Covers area above upload zone
            borderRadius: '12px 12px 0 0' 
          }}
        />

        <div className="flex flex-col justify-center space-y-8 p-6">
          <div className="relative w-full mx-auto">
            <div
              className="relative"
              onDragOver={handleDragOver}
              onDragLeave={handleDragLeave}
              onDrop={handleDrop}
              onClick={handleBaseClick}
            >
              <UploadCardBase
                isDragOver={isDragOver}
                isUploading={isUploading}
              />

              {/* Video Component - positioned relative to upload area */}
              <VideoComponent
                isAnimating={isAnimating}
                onAnimationComplete={handleAnimationComplete}
                filename={uploadedFile?.name}
                onRemove={handleRemoveFile}
                videoUrl={videoUrl || undefined}
              />

              {/* Hidden file input for click-to-upload */}
              <input
                ref={fileInputRef}
                type="file"
                accept="video/*"
                onChange={handleFileSelect}
                className="sr-only"
              />
            </div>
          </div>

          <div className="flex flex-col items-start">
            <h2 className="text-lg font-semibold text-foreground text-left">
              {title}
            </h2>

            <p className="text-sm text-muted-foreground text-left">
              {description}
            </p>
          </div>
        </div>
      </div>
    </motion.div>
  );
}

--- FILE: frontend-web/registry/core/utils.ts ---

import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs));
}

--- FILE: frontend-web/registry/effects/BorderBeam.tsx ---

import React from "react";
import { cn } from "../core/utils";

export interface BorderBeamProps {
  className?: string;
  size?: number;
  duration?: number;
  borderWidth?: number;
  anchor?: number;
  colorFrom?: string;
  colorTo?: string;
  delay?: number;
}

export const BorderBeam = ({
  className,
  size = 200,
  duration = 15,
  anchor = 90,
  borderWidth = 1.5,
  colorFrom = "#ffaa40",
  colorTo = "#9c40ff",
  delay = 0,
}: BorderBeamProps) => {
  return (
    <>
      <style>
        {`
          @keyframes border-beam-anim {
            100% {
              offset-distance: 100%;
            }
          }
          .animate-border-beam {
            animation: border-beam-anim calc(var(--duration)*1s) infinite linear;
          }
        `}
      </style>
      <div
        style={
          {
            "--size": size,
            "--duration": duration,
            "--anchor": anchor,
            "--border-width": borderWidth,
            "--color-from": colorFrom,
            "--color-to": colorTo,
            "--delay": `-${delay}s`,
          } as React.CSSProperties
        }
        className={cn(
          "pointer-events-none absolute inset-0 rounded-[inherit] [border:calc(var(--border-width)*1px)_solid_transparent]",
          // mask styles
          "![mask-clip:padding-box,border-box] ![mask-composite:intersect] [mask:linear-gradient(transparent,transparent),linear-gradient(white,white)]",
          // pseudo styles
          "after:absolute after:aspect-square after:w-[calc(var(--size)*1px)] after:animate-border-beam after:[animation-delay:var(--delay)] after:[background:linear-gradient(to_left,var(--color-from),var(--color-to),transparent)] after:[offset-anchor:calc(var(--anchor)*1%)_50%] after:[offset-path:rect(0_auto_auto_0_round_calc(var(--size)*1px))]",
          className
        )}
      />
    </>
  );
};

--- FILE: frontend-web/registry/effects/Glow.tsx ---

// @ts-nocheck
import React from "react";
import { cn } from "../core/utils";

type GlowVariant = "top" | "above" | "bottom" | "below" | "center";

interface GlowProps extends React.HTMLAttributes<HTMLDivElement> {
  variant?: GlowVariant;
}

const variantClasses: Record<GlowVariant, string> = {
  top: "top-0",
  above: "-top-[128px]",
  bottom: "bottom-0",
  below: "-bottom-[128px]",
  center: "top-[50%]",
};

const Glow = React.forwardRef<HTMLDivElement, GlowProps>(
  ({ className, variant = "top", ...props }, ref) => (
    <div
      ref={ref}
      className={cn("absolute w-full pointer-events-none z-0", variantClasses[variant], className)}
      {...props}
    >
      <div
        className={cn(
          "absolute left-1/2 h-[256px] w-[60%] -translate-x-1/2 scale-[2.5] rounded-[50%] sm:h-[512px]",
          "bg-[radial-gradient(ellipse_at_center,_rgba(0,0,0,0.05)_10%,_transparent_60%)]",
          "dark:bg-[radial-gradient(ellipse_at_center,_rgba(255,255,255,0.1)_10%,_transparent_60%)]",
          variant === "center" && "-translate-y-1/2"
        )}
      />
      <div
        className={cn(
          "absolute left-1/2 h-[128px] w-[40%] -translate-x-1/2 scale-[2] rounded-[50%] sm:h-[256px]",
          "bg-[radial-gradient(ellipse_at_center,_rgba(0,0,0,0.03)_10%,_transparent_60%)]",
          "dark:bg-[radial-gradient(ellipse_at_center,_rgba(255,255,255,0.05)_10%,_transparent_60%)]",
          variant === "center" && "-translate-y-1/2"
        )}
      />
    </div>
  )
);

Glow.displayName = "Glow";

export { Glow };

--- FILE: frontend-web/registry/effects/GooeyFilter.tsx ---

// @ts-nocheck
const GooeyFilter = ({
  id = "goo-filter",
  strength = 10,
}: {
  id?: string
  strength?: number
}) => {
  return (
    <svg className="hidden absolute">
      <defs>
        <filter id={id}>
          <feGaussianBlur
            in="SourceGraphic"
            stdDeviation={strength}
            result="blur"
          />
          <feColorMatrix
            in="blur"
            type="matrix"
            values="1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 19 -9"
            result="goo"
          />
          <feComposite in="SourceGraphic" in2="goo" operator="atop" />
        </filter>
      </defs>
    </svg>
  )
}

export { GooeyFilter }

--- FILE: frontend-web/registry/effects/Magnetic.tsx ---

import React, { useState, useEffect, useRef } from 'react';
import {
  motion,
  useMotionValue,
  useSpring,
  type SpringOptions,
} from 'framer-motion';

const SPRING_CONFIG = { stiffness: 26.7, damping: 4.1, mass: 0.2 };

export type MagneticProps = {
  children: React.ReactNode;
  intensity?: number;
  range?: number;
  actionArea?: 'self' | 'parent' | 'global';
  springOptions?: SpringOptions;
  className?: string;
};

export function Magnetic({
  children,
  intensity = 0.6,
  range = 100,
  actionArea = 'self',
  springOptions = SPRING_CONFIG,
  className,
}: MagneticProps) {
  const [isHovered, setIsHovered] = useState(false);
  const ref = useRef<HTMLDivElement>(null);

  const x = useMotionValue(0);
  const y = useMotionValue(0);

  const springX = useSpring(x, springOptions);
  const springY = useSpring(y, springOptions);

  useEffect(() => {
    const calculateDistance = (e: MouseEvent) => {
      if (ref.current) {
        const rect = ref.current.getBoundingClientRect();
        const centerX = rect.left + rect.width / 2;
        const centerY = rect.top + rect.height / 2;
        const distanceX = e.clientX - centerX;
        const distanceY = e.clientY - centerY;

        const absoluteDistance = Math.sqrt(distanceX ** 2 + distanceY ** 2);

        if (isHovered && absoluteDistance <= range) {
          const scale = 1 - absoluteDistance / range;
          x.set(distanceX * intensity * scale);
          y.set(distanceY * intensity * scale);
        } else {
          x.set(0);
          y.set(0);
        }
      }
    };

    document.addEventListener('mousemove', calculateDistance);

    return () => {
      document.removeEventListener('mousemove', calculateDistance);
    };
  }, [isHovered, intensity, range, x, y]);

  useEffect(() => {
    if (actionArea === 'parent' && ref.current?.parentElement) {
      const parent = ref.current.parentElement;

      const handleParentEnter = () => setIsHovered(true);
      const handleParentLeave = () => setIsHovered(false);

      parent.addEventListener('mouseenter', handleParentEnter);
      parent.addEventListener('mouseleave', handleParentLeave);

      return () => {
        parent.removeEventListener('mouseenter', handleParentEnter);
        parent.removeEventListener('mouseleave', handleParentLeave);
      };
    } else if (actionArea === 'global') {
      setIsHovered(true);
    }
  }, [actionArea]);

  const handleMouseEnter = () => {
    if (actionArea === 'self') {
      setIsHovered(true);
    }
  };

  const handleMouseLeave = () => {
    if (actionArea === 'self') {
      setIsHovered(false);
      x.set(0);
      y.set(0);
    }
  };

  return (
    <motion.div
      ref={ref}
      className={className}
      onMouseEnter={actionArea === 'self' ? handleMouseEnter : undefined}
      onMouseLeave={actionArea === 'self' ? handleMouseLeave : undefined}
      style={{
        x: springX,
        y: springY,
      }}
    >
      {children}
    </motion.div>
  );
}

--- FILE: frontend-web/registry/effects/ShineBorder.tsx ---

import React from "react";
import { cn } from "../core/utils";

export type TColorProp = string | string[];

export interface ShineBorderProps {
  borderRadius?: number;
  borderWidth?: number;
  duration?: number;
  color?: TColorProp;
  className?: string;
  children: React.ReactNode;
}

export function ShineBorder({
  borderRadius = 8,
  borderWidth = 1,
  duration = 14,
  color = "#000000",
  className,
  children,
}: ShineBorderProps) {
  return (
    <div
      style={
        {
          "--border-radius": `${borderRadius}px`,
        } as React.CSSProperties
      }
      className={cn(
        "relative min-h-[60px] w-full min-w-[250px] place-items-center rounded-[var(--border-radius)] bg-white p-3 text-black dark:bg-black dark:text-white",
        className
      )}
    >
      <style>
        {`
          @keyframes shine-border-anim {
            0% {
              background-position: 0% 0%;
            }
            50% {
              background-position: 100% 100%;
            }
            100% {
              background-position: 0% 0%;
            }
          }
          .animate-shine-border::before {
            animation: shine-border-anim var(--duration) infinite linear;
          }
        `}
      </style>
      <div
        style={
          {
            "--border-width": `${borderWidth}px`,
            "--border-radius": `${borderRadius}px`,
            "--duration": `${duration}s`,
            "--mask-linear-gradient": `linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)`,
            "--background-radial-gradient": `radial-gradient(transparent,transparent, ${
              color instanceof Array ? color.join(",") : color
            },transparent,transparent)`,
          } as React.CSSProperties
        }
        className={`pointer-events-none animate-shine-border before:absolute before:inset-0 before:size-full before:rounded-[var(--border-radius)] before:p-[var(--border-width)] before:will-change-[background-position] before:content-[""] before:![-webkit-mask-composite:xor] before:![mask-composite:exclude] before:[background-image:var(--background-radial-gradient)] before:[background-size:300%_300%] before:[mask:var(--mask-linear-gradient)]`}
      ></div>
      <div className="relative z-10 w-full h-full">
        {children}
      </div>
    </div>
  );
}

--- FILE: frontend-web/registry/elements/AnimatedLink.tsx ---

import * as React from "react";
import { cn } from "../core/utils";

export type AnimatedLinkVariant = "left" | "right" | "center";

const underlineVariants: Record<AnimatedLinkVariant, string> = {
  // underline wipes in from the left edge
  left: "before:origin-right before:scale-x-0 hover:before:origin-left hover:before:scale-x-100",
  // underline wipes in from the right edge
  right:
    "before:origin-left before:scale-x-0 hover:before:origin-right hover:before:scale-x-100",
  // underline grows outward from the center
  center: "before:origin-center before:scale-x-0 hover:before:scale-x-100",
};

export interface AnimatedLinkProps extends React.ComponentPropsWithoutRef<"a"> {
  /** Direction the underline reveals from on hover. */
  variant?: AnimatedLinkVariant;
  /** Show the diagonal arrow that lifts in on hover. */
  showArrow?: boolean;
}

const AnimatedLink = React.forwardRef<HTMLAnchorElement, AnimatedLinkProps>(
  ({ variant = "left", showArrow = true, className, children, ...props }, ref) => {
    return (
      <a
        ref={ref}
        className={cn(
          "group relative inline-flex w-fit items-center text-slate-900 dark:text-white font-medium cursor-pointer",
          "before:pointer-events-none before:absolute before:left-0 before:top-[1.25em] before:h-[0.08em] before:w-full before:bg-current before:content-['']",
          "before:transition-transform before:duration-300 before:ease-[cubic-bezier(0.4,0,0.2,1)] motion-reduce:before:transition-none",
          underlineVariants[variant],
          className
        )}
        {...props}
      >
        {children}
        {showArrow && (
          <svg
            className="ml-[0.3em] size-[0.65em] transition-none"
            fill="none"
            viewBox="0 0 10 10"
            xmlns="http://www.w3.org/2000/svg"
            aria-hidden="true"
          >
            <path
              d="M1.004 9.166 9.337.833m0 0v8.333m0-8.333H1.004"
              stroke="currentColor"
              strokeWidth="1.25"
              strokeLinecap="round"
              strokeLinejoin="round"
              className="[stroke-dasharray:32] [stroke-dashoffset:32] transition-[stroke-dashoffset] duration-300 ease-[cubic-bezier(0.4,0,0.2,1)] group-hover:[stroke-dashoffset:0] motion-reduce:transition-none"
            />
          </svg>
        )}
      </a>
    );
  }
);

AnimatedLink.displayName = "AnimatedLink";

export { AnimatedLink };

--- FILE: frontend-web/registry/elements/Counter.tsx ---

import React, { useState } from "react";
import { cn } from "../core/utils";

export interface CounterProps extends React.HTMLAttributes<HTMLDivElement> {
  title?: string;
  initialValue?: number;
}

export const Counter = ({ 
  title = "Component Example", 
  initialValue = 0,
  className,
  ...props 
}: CounterProps) => {
  const [count, setCount] = useState(initialValue);

  return (
    <div className={cn("flex flex-col items-center gap-4 p-6 rounded-xl border border-slate-200 dark:border-zinc-800 bg-white dark:bg-zinc-950 shadow-sm w-max mx-auto", className)} {...props}>
      <h1 className="text-xl font-bold text-slate-900 dark:text-white">{title}</h1>
      <h2 className="text-4xl font-semibold tabular-nums text-slate-800 dark:text-slate-200">{count}</h2>
      <div className="flex gap-3">
        <button 
          onClick={() => setCount((prev) => prev - 1)}
          className="flex h-10 w-10 items-center justify-center rounded-full bg-slate-100 dark:bg-zinc-800 hover:bg-slate-200 dark:hover:bg-zinc-700 text-slate-900 dark:text-white transition-colors focus:outline-none focus:ring-2 focus:ring-slate-400"
        >
          -
        </button>
        <button 
          onClick={() => setCount((prev) => prev + 1)}
          className="flex h-10 w-10 items-center justify-center rounded-full bg-slate-100 dark:bg-zinc-800 hover:bg-slate-200 dark:hover:bg-zinc-700 text-slate-900 dark:text-white transition-colors focus:outline-none focus:ring-2 focus:ring-slate-400"
        >
          +
        </button>
      </div>
    </div>
  );
};

--- FILE: frontend-web/registry/elements/SocialLinks.tsx ---

import * as React from "react"
import { motion, AnimatePresence } from "framer-motion"
import { cn } from "../core/utils"

export interface Social {
  name: string
  image: string
}

export interface SocialLinksProps extends React.HTMLAttributes<HTMLDivElement> {
  socials?: Social[]
}

const DEFAULT_SOCIALS: Social[] = [
  {
    name: "Twitter",
    image: "https://images.unsplash.com/photo-1611162617213-7d7a39e9b1d7?w=128&h=128&fit=crop",
  },
  {
    name: "Dribbble",
    image: "https://images.unsplash.com/photo-1611162618828-bc409f073cbf?w=128&h=128&fit=crop",
  },
  {
    name: "LinkedIn",
    image: "https://images.unsplash.com/photo-1611162616475-46b635cb6868?w=128&h=128&fit=crop",
  },
];

export function SocialLinks({ socials = DEFAULT_SOCIALS, className, ...props }: SocialLinksProps) {
  const [hoveredSocial, setHoveredSocial] = React.useState<string | null>(null)
  const [rotation, setRotation] = React.useState<number>(0)
  const [clicked, setClicked] = React.useState<boolean>(false)

  const animation = {
    scale: clicked ? [1, 1.3, 1] : 1,
    transition: { duration: 0.3 },
  }

  React.useEffect(() => {
    const handleClick = () => {
      setClicked(true)
      setTimeout(() => {
        setClicked(false)
      }, 200)
    }
    window.addEventListener("click", handleClick)
    return () => window.removeEventListener("click", handleClick)
  }, [clicked])

  return (
    <div
      className={cn("flex items-center justify-center gap-0", className)}
      {...props}
    >
      {socials.map((social, index) => (
        <div
          className={cn(
            "relative cursor-pointer px-5 py-2 transition-opacity duration-200",
            hoveredSocial && hoveredSocial !== social.name
              ? "opacity-50"
              : "opacity-100"
          )}
          key={index}
          onMouseEnter={() => {
            setHoveredSocial(social.name)
            setRotation(Math.random() * 20 - 10)
          }}
          onMouseLeave={() => setHoveredSocial(null)}
          onClick={() => {
            setClicked(true)
          }}
        >
          <span className="block text-lg font-medium text-slate-900 dark:text-white">{social.name}</span>
          <AnimatePresence>
            {hoveredSocial === social.name && (
              <motion.div
                className="absolute bottom-0 left-0 right-0 flex h-full w-full items-center justify-center pointer-events-none"
                animate={animation}
              >
                <motion.img
                  key={social.name}
                  src={social.image}
                  alt={social.name}
                  className="size-16 rounded-xl object-cover shadow-lg border border-slate-200 dark:border-zinc-800"
                  initial={{
                    y: -40,
                    rotate: rotation,
                    opacity: 0,
                    filter: "blur(2px)",
                  }}
                  animate={{ y: -50, opacity: 1, filter: "blur(0px)" }}
                  exit={{ y: -40, opacity: 0, filter: "blur(2px)" }}
                  transition={{ duration: 0.2 }}
                />
              </motion.div>
            )}
          </AnimatePresence>
        </div>
      ))}
    </div>
  )
}

--- FILE: frontend-web/registry/elements/Timestamp.tsx ---

import React from 'react';
import { cn } from '../core/utils';

export interface TimestampProps extends React.HTMLAttributes<HTMLDivElement> {
  seconds: number;
  className?: string;
}

export function Timestamp({ seconds, className, ...props }: TimestampProps) {
  const formatTime = (totalSeconds: number): string => {
    if (isNaN(totalSeconds) || totalSeconds < 0) {
      return '0:00';
    }

    const hours = Math.floor(totalSeconds / 3600);
    const minutes = Math.floor((totalSeconds % 3600) / 60);
    const secs = Math.floor(totalSeconds % 60);

    if (hours > 0) {
      return `${hours}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
    } else {
      return `${minutes}:${secs.toString().padStart(2, '0')}`;
    }
  };

  return (
    <div 
      className={cn(
        "inline-flex items-center justify-center bg-neutral-950/75 text-white text-xs font-extrabold px-1.5 h-5 rounded-sm tabular-nums tracking-tight", 
        className
      )}
      {...props}
    >
      {formatTime(seconds)}
    </div>
  );
}

--- FILE: frontend-web/registry/elements/TopBanner.tsx ---

import React, { type HTMLAttributes, useCallback, useEffect, useState } from 'react';
import { X } from 'lucide-react';
import { cn } from '../core/utils';

export interface TopBannerProps extends HTMLAttributes<HTMLDivElement> {
  /**
   * Defines the visual style of the banner.
   * @defaultValue 'normal'
   */
  variant?: 'rainbow' | 'normal';
  /**
   * If true, injects a CSS variable `--banner-height` to the root so other elements can offset.
   * @defaultValue true
   */
  changeLayout?: boolean;
  /**
   * Banner message content.
   */
  message?: React.ReactNode;
  /**
   * The height of the banner.
   * @defaultValue '3rem'
   */
  height?: string;
  /**
   * A unique ID. If provided, the banner's closed state is saved to localStorage.
   */
  id?: string;
}

export function TopBanner({
  id,
  variant = 'normal',
  changeLayout = true,
  message,
  height = '3rem',
  className,
  children,
  ...props
}: TopBannerProps): React.ReactElement {
  const [open, setOpen] = useState(true);
  const globalKey = id ? `banner-${id}` : undefined;

  useEffect(() => {
    if (globalKey) {
      setOpen(localStorage.getItem(globalKey) !== 'true');
    }
  }, [globalKey]);

  const onClick = useCallback(() => {
    setOpen(false);
    if (globalKey) localStorage.setItem(globalKey, 'true');
  }, [globalKey]);

  return (
    <>
      <style>{`
        @keyframes rainbow-pan {
          0% { background-position: 0% 50%; }
          100% { background-position: 100% 50%; }
        }
        .rainbow-banner-gradient-1 {
          background: linear-gradient(
            90deg,
            rgba(255, 0, 0, 0.15),
            rgba(255, 154, 0, 0.15),
            rgba(208, 222, 33, 0.15),
            rgba(79, 220, 74, 0.15),
            rgba(63, 218, 216, 0.15),
            rgba(47, 201, 226, 0.15),
            rgba(28, 127, 238, 0.15),
            rgba(95, 21, 242, 0.15),
            rgba(186, 12, 248, 0.15),
            rgba(251, 7, 217, 0.15),
            rgba(255, 0, 0, 0.15)
          );
          background-size: 200% 100%;
          animation: rainbow-pan 5s linear infinite;
        }
        .rainbow-banner-gradient-2 {
          background: linear-gradient(
            90deg,
            rgba(255, 0, 0, 0.1),
            rgba(255, 154, 0, 0.1),
            rgba(208, 222, 33, 0.1),
            rgba(79, 220, 74, 0.1),
            rgba(63, 218, 216, 0.1),
            rgba(47, 201, 226, 0.1),
            rgba(28, 127, 238, 0.1),
            rgba(95, 21, 242, 0.1),
            rgba(186, 12, 248, 0.1),
            rgba(251, 7, 217, 0.1),
            rgba(255, 0, 0, 0.1)
          );
          background-size: 200% 100%;
          animation: rainbow-pan 10s linear infinite reverse;
        }
      `}</style>
      
      <div
        id={id}
        style={{ height: open ? height : '0' }}
        className={cn(
          'sticky top-0 z-50 flex flex-row items-center justify-center px-4 text-center text-sm font-medium transition-all duration-300 overflow-hidden',
          variant === 'rainbow' ? 'bg-white dark:bg-black text-slate-900 dark:text-white' : 'bg-slate-100 dark:bg-zinc-900 text-slate-900 dark:text-white border-b border-slate-200 dark:border-zinc-800',
          !open && 'hidden',
          className
        )}
        {...props}
      >
        {changeLayout && open ? (
          <style>{`
          :root:not(.${globalKey ?? 'banner-never'}) { --banner-height: ${height}; }
          `}</style>
        ) : null}
        
        {globalKey ? (
          <style>{`.${globalKey} #${id} { display: none; }`}</style>
        ) : null}

        {variant === 'rainbow' && (
          <>
            <div className="absolute inset-0 z-[-1] rainbow-banner-gradient-1" />
            <div className="absolute inset-0 z-[-1] rainbow-banner-gradient-2" />
            <div className="absolute inset-x-0 bottom-0 h-px bg-slate-200 dark:bg-zinc-800" />
          </>
        )}

        <div className="relative z-10 w-full flex items-center justify-center">
          {message || children}
        </div>

        {id && (
          <button
            type="button"
            aria-label="Close Banner"
            onClick={onClick}
            className="absolute right-2 top-1/2 -translate-y-1/2 flex h-8 w-8 items-center justify-center rounded-md text-slate-500 hover:bg-slate-200 hover:text-slate-900 dark:text-slate-400 dark:hover:bg-zinc-800 dark:hover:text-white transition-colors"
          >
            <X className="h-4 w-4" />
          </button>
        )}
      </div>
    </>
  );
}

--- FILE: frontend-web/registry/footers/AnimatedSubscribeFooter.tsx ---

import React, { useState } from 'react';
import { Facebook, Instagram, Twitter, Hexagon } from 'lucide-react';
import { motion, AnimatePresence } from 'framer-motion';
import { cn } from '../core/utils';

export interface FooterLink {
  label: string;
  href: string;
}

export interface SocialLink {
  label: string;
  href: string;
  icon: React.ReactNode;
}

export interface AnimatedSubscribeFooterProps {
  logo?: React.ReactNode;
  brandName?: string;
  description?: string;
  usefulLinks?: FooterLink[];
  socialLinks?: SocialLink[];
  newsletterTitle?: string;
  onSubscribe?: (email: string) => Promise<boolean>;
  className?: string;
}

const DEFAULT_USEFUL_LINKS: FooterLink[] = [
  { label: 'Products', href: '#' },
  { label: 'Careers', href: '#' },
  { label: 'Contact Us', href: '#' },
  { label: 'Privacy Policy', href: '#' },
];

const DEFAULT_SOCIAL_LINKS: SocialLink[] = [
  { label: 'Facebook', href: '#', icon: <Facebook className="w-4 h-4" /> },
  { label: 'Instagram', href: '#', icon: <Instagram className="w-4 h-4" /> },
  { label: 'Twitter (X)', href: '#', icon: <Twitter className="w-4 h-4" /> },
];

export function AnimatedSubscribeFooter({
  logo = <Hexagon className="h-8 w-8 text-indigo-600 dark:text-indigo-400" />,
  brandName = 'Datally Inc.',
  description = 'Empowering businesses with intelligent financial solutions, designed for the future of finance.',
  usefulLinks = DEFAULT_USEFUL_LINKS,
  socialLinks = DEFAULT_SOCIAL_LINKS,
  newsletterTitle = 'Subscribe to our newsletter',
  onSubscribe,
  className,
}: AnimatedSubscribeFooterProps) {
  const [email, setEmail] = useState('');
  const [isSubmitting, setIsSubmitting] = useState(false);
  const [subscriptionStatus, setSubscriptionStatus] = useState<'idle' | 'success' | 'error'>('idle');

  const handleSubscribe = async (event: React.FormEvent) => {
    event.preventDefault();
    if (!email || isSubmitting) return;

    setIsSubmitting(true);
    
    let success = true;
    
    // If no custom handler is provided, simulate a network request
    if (!onSubscribe) {
      await new Promise((resolve) => setTimeout(resolve, 1500));
    } else {
      success = await onSubscribe(email);
    }

    setSubscriptionStatus(success ? 'success' : 'error');
    setIsSubmitting(false);

    if (success) {
      setEmail('');
    }

    // Reset the status message after 3 seconds
    setTimeout(() => {
      setSubscriptionStatus('idle');
    }, 3000);
  };

  return (
    <footer className={cn('bg-slate-50 dark:bg-zinc-900/50 text-slate-900 dark:text-white border-t border-slate-200 dark:border-zinc-800', className)}>
      <div className="container mx-auto grid grid-cols-1 gap-10 px-6 py-16 md:grid-cols-2 lg:grid-cols-4 lg:gap-12 max-w-7xl">
        
        {/* Company Info */}
        <div className="flex flex-col items-start gap-4">
          <div className="flex items-center gap-3">
            {logo}
            <span className="text-xl font-bold tracking-tight">{brandName}</span>
          </div>
          <p className="text-sm text-slate-500 dark:text-slate-400 leading-relaxed pr-4">
            {description}
          </p>
        </div>

        {/* Useful Links */}
        <div className="lg:justify-self-center">
          <h3 className="mb-5 text-sm font-bold uppercase tracking-wider text-slate-900 dark:text-slate-100">
            Useful Links
          </h3>
          <ul className="space-y-3">
            {usefulLinks.map((link) => (
              <li key={link.label}>
                <a
                  href={link.href}
                  className="text-sm font-medium text-slate-500 dark:text-slate-400 transition-colors hover:text-indigo-600 dark:hover:text-indigo-400"
                >
                  {link.label}
                </a>
              </li>
            ))}
          </ul>
        </div>

        {/* Follow Us */}
        <div className="lg:justify-self-center">
          <h3 className="mb-5 text-sm font-bold uppercase tracking-wider text-slate-900 dark:text-slate-100">
            Follow Us
          </h3>
          <ul className="space-y-3">
            {socialLinks.map((link) => (
              <li key={link.label}>
                <a
                  href={link.href}
                  aria-label={link.label}
                  className="flex items-center gap-3 text-sm font-medium text-slate-500 dark:text-slate-400 transition-colors hover:text-indigo-600 dark:hover:text-indigo-400"
                >
                  {link.icon}
                  <span>{link.label}</span>
                </a>
              </li>
            ))}
          </ul>
        </div>

        {/* Newsletter */}
        <div className="lg:justify-self-end w-full">
          <h3 className="mb-5 text-sm font-bold uppercase tracking-wider text-slate-900 dark:text-slate-100">
            {newsletterTitle}
          </h3>
          <form onSubmit={handleSubscribe} className="relative w-full max-w-sm">
            <div className="relative flex">
              <input
                type="email"
                placeholder="Your email address"
                value={email}
                onChange={(e) => setEmail(e.target.value)}
                disabled={isSubmitting || subscriptionStatus !== 'idle'}
                required
                aria-label="Email for newsletter"
                className="flex h-10 w-full rounded-md border border-slate-300 dark:border-zinc-700 bg-white dark:bg-zinc-900 px-3 py-2 text-sm placeholder:text-slate-400 dark:placeholder:text-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 disabled:opacity-50 pr-[100px]"
              />
              <button
                type="submit"
                disabled={isSubmitting || subscriptionStatus !== 'idle'}
                className="absolute right-0 top-0 h-10 rounded-r-md px-4 bg-slate-900 dark:bg-white text-white dark:text-slate-900 text-sm font-medium transition-colors hover:bg-slate-800 dark:hover:bg-slate-200 disabled:opacity-80"
              >
                {isSubmitting ? (
                  <span className="flex items-center gap-2">
                    <svg className="animate-spin h-4 w-4" viewBox="0 0 24 24">
                      <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" fill="none" />
                      <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" />
                    </svg>
                  </span>
                ) : (
                  'Subscribe'
                )}
              </button>
            </div>

            {/* Advanced Animation Overlay */}
            <AnimatePresence mode="wait">
              {(subscriptionStatus === 'success' || subscriptionStatus === 'error') && (
                <motion.div
                  key={subscriptionStatus}
                  initial={{ opacity: 0, scale: 0.95 }}
                  animate={{ opacity: 1, scale: 1 }}
                  exit={{ opacity: 0, scale: 0.95 }}
                  className="absolute inset-0 flex items-center justify-center rounded-md bg-white/90 dark:bg-zinc-900/90 backdrop-blur-sm border border-slate-200 dark:border-zinc-800 z-10"
                >
                  {subscriptionStatus === 'success' ? (
                    <span className="font-semibold text-emerald-600 dark:text-emerald-400 flex items-center gap-2 text-sm">
                      Subscribed! <span className="text-lg">🎉</span>
                    </span>
                  ) : (
                    <span className="font-semibold text-red-600 dark:text-red-400 text-sm">
                      Failed. Try again.
                    </span>
                  )}
                </motion.div>
              )}
            </AnimatePresence>
          </form>
        </div>
      </div>
      
      {/* Copyright Bar */}
      <div className="border-t border-slate-200 dark:border-zinc-800">
        <div className="container mx-auto px-6 py-6 text-center text-sm font-medium text-slate-500 dark:text-slate-400">
          © {new Date().getFullYear()} {brandName} All rights reserved.
        </div>
      </div>
    </footer>
  );
}

--- FILE: frontend-web/registry/footers/AnimatedWaveFooter.tsx ---

import React, { useEffect, useRef, useState } from "react";
import { cn } from "../core/utils";

export interface LinkItem {
  href: string;
  label: string;
}

export interface AnimatedWaveFooterProps {
  leftLinks?: LinkItem[];
  rightLinks?: LinkItem[];
  copyrightText?: string;
  barCount?: number; 
  className?: string;
}

const DEFAULT_LEFT_LINKS = [
  { href: "#", label: "About" },
  { href: "#", label: "Careers" },
  { href: "#", label: "Privacy" },
];

const DEFAULT_RIGHT_LINKS = [
  { href: "#", label: "Twitter" },
  { href: "#", label: "GitHub" },
  { href: "#", label: "Discord" },
];

export const AnimatedWaveFooter: React.FC<AnimatedWaveFooterProps> = ({
  leftLinks = DEFAULT_LEFT_LINKS,
  rightLinks = DEFAULT_RIGHT_LINKS,
  copyrightText = "© 2025 NOVA UI. All rights reserved.",
  barCount = 23, 
  className
}) => {
  const waveRefs = useRef<(HTMLDivElement | null)[]>([]);
  const footerRef = useRef<HTMLDivElement | null>(null);
  const [isVisible, setIsVisible] = useState(false);
  const animationFrameRef = useRef<number | null>(null);

  useEffect(() => {
    const observer = new IntersectionObserver(
      (entries) => {
        const [entry] = entries;
        setIsVisible(entry.isIntersecting);
      },
      { threshold: 0.2 } 
    );

    if (footerRef.current) {
      observer.observe(footerRef.current);
    }

    return () => {
      if (footerRef.current) {
        observer.unobserve(footerRef.current);
      }
    };
  }, []);

  useEffect(() => {
    let t = 0; 

    const animateWave = () => {
      const waveElements = waveRefs.current;
      let offset = 0;

      waveElements.forEach((element, index) => {
        if (element) {
          offset += Math.max(0, 20 * Math.sin((t + index) * 0.3)); 
          element.style.transform = `translateY(${index + offset}px)`;
        }
      });

      t += 0.1;
      animationFrameRef.current = requestAnimationFrame(animateWave);
    };

    if (isVisible) {
      animateWave();
    } else if (animationFrameRef.current) {
      cancelAnimationFrame(animationFrameRef.current);
      animationFrameRef.current = null;
    }

    return () => {
      if (animationFrameRef.current) {
        cancelAnimationFrame(animationFrameRef.current);
        animationFrameRef.current = null;
      }
    };
  }, [isVisible]);

  const scrollToTop = () => {
    window.scrollTo({ top: 0, behavior: 'smooth' });
  };

  return (
    <footer
      ref={footerRef}
      className={cn("bg-white dark:bg-black text-slate-900 dark:text-white relative flex flex-col w-full h-full justify-between lg:h-screen select-none", className)}
    >
      <div className="container mx-auto flex flex-col md:flex-row justify-between w-full gap-4 pb-24 pt-8 px-4 md:px-6">
        <div className="space-y-2">
          <ul className="flex flex-wrap gap-4">
            {leftLinks.map((link, index) => (
              <li key={index}>
                <a href={link.href} className="text-sm font-medium hover:text-blue-500 dark:hover:text-sky-400 transition-colors">
                  {link.label}
                </a>
              </li>
            ))}
          </ul>
          <p className="text-sm mt-4 flex items-center gap-x-1.5 font-medium text-slate-500 dark:text-slate-400">
            <svg className="size-4" viewBox="0 0 80 80">
              <path
                fillRule="evenodd"
                clipRule="evenodd"
                fill="currentColor"
                d="M67.4307 11.5693C52.005 -3.85643 26.995 -3.85643 11.5693 11.5693C-3.85643 26.995 -3.85643 52.005 11.5693 67.4307C26.995 82.8564 52.005 82.8564 67.4307 67.4307C82.8564 52.005 82.8564 26.995 67.4307 11.5693ZM17.9332 17.9332C29.8442 6.02225 49.1558 6.02225 61.0668 17.9332C72.9777 29.8442 72.9777 49.1558 61.0668 61.0668C59.7316 62.4019 58.3035 63.5874 56.8032 64.6232L56.8241 64.6023C46.8657 54.6439 46.8657 38.4982 56.8241 28.5398L58.2383 27.1256L51.8744 20.7617L50.4602 22.1759C40.5018 32.1343 24.3561 32.1343 14.3977 22.1759L14.3768 22.1968C15.4126 20.6965 16.5981 19.2684 17.9332 17.9332ZM34.0282 38.6078C25.6372 38.9948 17.1318 36.3344 10.3131 30.6265C7.56889 39.6809 9.12599 49.76 14.9844 57.6517L34.0282 38.6078ZM21.3483 64.0156C29.24 69.874 39.3191 71.4311 48.3735 68.6869C42.6656 61.8682 40.0052 53.3628 40.3922 44.9718L21.3483 64.0156Z"
              />
            </svg>
            {copyrightText}
          </p>
        </div>
        <div className="space-y-4">
          <ul className="flex flex-wrap gap-4 md:justify-end">
            {rightLinks.map((link, index) => (
              <li key={index}>
                <a href={link.href} className="text-sm font-medium hover:text-blue-500 dark:hover:text-sky-400 transition-colors">
                  {link.label}
                </a>
              </li>
            ))}
          </ul>
          <div className="md:text-right mt-4">
            <button onClick={scrollToTop} className="text-sm font-medium hover:underline inline-flex items-center text-slate-500 dark:text-slate-400 hover:text-slate-900 dark:hover:text-white transition-colors">
              Back to top
            </button>
          </div>
        </div>
      </div>
      <div
        id="waveContainer"
        aria-hidden="true"
        style={{ overflow: "hidden", height: 200 }}
      >
        <div style={{ marginTop: 0 }}>
          {Array.from({ length: barCount }).map((_, index) => (
            <div
              key={index}
              ref={(el) => { waveRefs.current[index] = el; }}
              className="bg-slate-900 dark:bg-white"
              style={{
                height: `${index + 1}px`,
                transition: "transform 0.1s ease",
                willChange: "transform",
                marginTop: "-2px",
              }}
            />
          ))}
        </div>
      </div>
    </footer>
  );
};

--- FILE: frontend-web/registry/footers/AppDownloadFooter.tsx ---

import React from "react";
import {
  FacebookIcon,
  InstagramIcon,
  LinkedinIcon,
  TwitterIcon,
  Apple,
  Play,
} from "lucide-react";
import { cn } from "../core/utils";

export interface FooterLink {
  label: string;
  href: string;
}

export interface FooterColumn {
  title: string;
  links: FooterLink[];
}

export interface SocialLink {
  icon: React.ElementType;
  href: string;
  label: string;
}

export interface AppDownloadFooterProps {
  brandName?: string;
  columns?: FooterColumn[];
  socialLinks?: SocialLink[];
  showAppStore?: boolean;
  appStoreLink?: string;
  showPlayStore?: boolean;
  playStoreLink?: string;
  copyright?: string;
  className?: string;
}

const DEFAULT_COLUMNS: FooterColumn[] = [
  {
    title: "Company",
    links: [
      { href: "#", label: "Blog" },
      { href: "#", label: "Engineering" },
      { href: "#", label: "Marketplace" },
      { href: "#", label: "What's New" },
      { href: "#", label: "About" },
      { href: "#", label: "Press" },
      { href: "#", label: "Careers" },
    ],
  },
  {
    title: "Community",
    links: [
      { href: "#", label: "Enterprise" },
      { href: "#", label: "Creator Report" },
      { href: "#", label: "Charities" },
      { href: "#", label: "What's Trending" },
      { href: "#", label: "Directory" },
      { href: "#", label: "Templates" },
    ],
  },
  {
    title: "Support",
    links: [
      { href: "#", label: "Help Topics" },
      { href: "#", label: "Getting Started" },
      { href: "#", label: "Pro Features" },
      { href: "#", label: "How-tos" },
      { href: "#", label: "FAQs" },
      { href: "#", label: "Report a Violation" },
    ],
  },
  {
    title: "Legal",
    links: [
      { href: "#", label: "Terms & Conditions" },
      { href: "#", label: "Privacy Notice" },
      { href: "#", label: "Cookie Notice" },
      { href: "#", label: "Trust Center" },
      { href: "#", label: "Cookie Preferences" },
      { href: "#", label: "Transparency" },
    ],
  },
];

const DEFAULT_SOCIALS: SocialLink[] = [
  { icon: FacebookIcon, href: "#", label: "Facebook" },
  { icon: InstagramIcon, href: "#", label: "Instagram" },
  { icon: LinkedinIcon, href: "#", label: "LinkedIn" },
  { icon: TwitterIcon, href: "#", label: "Twitter" },
];

export function AppDownloadFooter({
  brandName = "NOVA UI",
  columns = DEFAULT_COLUMNS,
  socialLinks = DEFAULT_SOCIALS,
  showAppStore = true,
  appStoreLink = "#",
  showPlayStore = true,
  playStoreLink = "#",
  copyright,
  className,
}: AppDownloadFooterProps) {
  const copyText = copyright || `© ${new Date().getFullYear()} ${brandName}. All rights reserved.`;

  return (
    <footer className={cn("bg-white dark:bg-zinc-950 border-t border-slate-200 dark:border-zinc-800 text-slate-900 dark:text-white", className)}>
      <div className="max-w-6xl mx-auto px-4 lg:px-6 pt-12 pb-6">
        
        {/* Link Grid */}
        <div className="grid grid-cols-2 md:grid-cols-4 gap-8 py-8">
          {columns.map((item, i) => (
            <div key={i}>
              <h3 className="mb-5 text-sm font-semibold tracking-wider uppercase text-slate-900 dark:text-white">
                {item.title}
              </h3>
              <ul className="space-y-3 text-slate-500 dark:text-slate-400 text-sm">
                {item.links.map((link) => (
                  <li key={link.label}>
                    <a
                      href={link.href}
                      className="hover:text-indigo-600 dark:hover:text-indigo-400 font-medium transition-colors"
                    >
                      {link.label}
                    </a>
                  </li>
                ))}
              </ul>
            </div>
          ))}
        </div>

        <div className="h-px bg-slate-200 dark:bg-zinc-800 w-full my-4" />

        {/* Social Buttons + App Links */}
        <div className="py-6 flex flex-col md:flex-row items-center justify-between gap-6">
          <div className="flex gap-3 items-center">
            {socialLinks.map((social, i) => {
              const Icon = social.icon;
              return (
                <a
                  key={i}
                  href={social.href}
                  aria-label={social.label}
                  className="inline-flex items-center justify-center rounded-lg border border-slate-200 dark:border-zinc-800 h-10 w-10 text-slate-500 hover:text-slate-900 dark:text-slate-400 dark:hover:text-white hover:bg-slate-100 dark:hover:bg-zinc-800 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500"
                >
                  <Icon className="size-4" />
                </a>
              );
            })}
          </div>

          <div className="flex flex-wrap items-center justify-center gap-4">
            {showAppStore && (
              <a
                href={appStoreLink}
                className="inline-flex items-center justify-center bg-black dark:bg-white text-white dark:text-black rounded-xl px-4 py-2 hover:opacity-90 transition-opacity min-w-[140px]"
              >
                <Apple className="w-6 h-6 mr-2 fill-current" />
                <div className="flex flex-col items-start leading-none">
                  <span className="text-[10px] uppercase font-medium">Download on the</span>
                  <span className="text-sm font-bold">App Store</span>
                </div>
              </a>
            )}

            {showPlayStore && (
              <a
                href={playStoreLink}
                className="inline-flex items-center justify-center bg-black dark:bg-white text-white dark:text-black rounded-xl px-4 py-2 hover:opacity-90 transition-opacity min-w-[140px]"
              >
                <Play className="w-5 h-5 mr-2 fill-current" />
                <div className="flex flex-col items-start leading-none">
                  <span className="text-[10px] uppercase font-medium">GET IT ON</span>
                  <span className="text-sm font-bold">Google Play</span>
                </div>
              </a>
            )}
          </div>
        </div>

        <div className="h-px bg-slate-200 dark:bg-zinc-800 w-full my-2" />

        {/* Copyright */}
        <div className="text-center text-xs font-medium text-slate-500 dark:text-slate-400 py-6">
          <p>{copyText}</p>
        </div>
      </div>
    </footer>
  );
}

--- FILE: frontend-web/registry/footers/BadgeFooter.tsx ---

import React from "react";
import { Instagram, Twitter, Linkedin, Hexagon } from "lucide-react";
import { cn } from "../core/utils";

export interface FooterLink {
  label: string;
  href: string;
  badge?: string; 
}

export interface FooterColumn {
  title: string;
  links: FooterLink[];
}

export interface SocialLink {
  icon: React.ElementType;
  href: string;
  label: string;
}

export interface BadgeFooterProps {
  logo?: React.ReactNode;
  brandName?: string;
  description?: string;
  columns?: FooterColumn[];
  socialLinks?: SocialLink[];
  copyright?: string;
  bottomLinks?: Array<{ label: string; href: string }>;
  className?: string;
}

const DEFAULT_COLUMNS: FooterColumn[] = [
  {
    title: "Product",
    links: [
      { label: "Features", href: "#" },
      { label: "Integrations", href: "#" },
      { label: "Pricing", href: "#" },
      { label: "Changelog", href: "#", badge: "New" },
    ],
  },
  {
    title: "Company",
    links: [
      { label: "About Us", href: "#" },
      { label: "Careers", href: "#", badge: "Hiring" },
      { label: "Blog", href: "#" },
      { label: "Contact", href: "#" },
    ],
  },
  {
    title: "Resources",
    links: [
      { label: "Documentation", href: "#" },
      { label: "Community", href: "#" },
      { label: "Support", href: "#" },
      { label: "API Reference", href: "#", badge: "Pro" },
    ],
  },
];

const DEFAULT_SOCIALS: SocialLink[] = [
  { icon: Twitter, href: "#", label: "Twitter" },
  { icon: Linkedin, href: "#", label: "LinkedIn" },
  { icon: Instagram, href: "#", label: "Instagram" },
];

export function BadgeFooter({
  logo = <Hexagon className="h-8 w-8 text-indigo-600 dark:text-indigo-400" />,
  brandName = "NOVA UI",
  description = "Empowering developers to build incredible web applications faster than ever before. Open source, customizable, and perfectly crafted.",
  columns = DEFAULT_COLUMNS,
  socialLinks = DEFAULT_SOCIALS,
  copyright,
  bottomLinks = [
    { label: "Privacy Policy", href: "#" },
    { label: "Terms of Service", href: "#" },
    { label: "Cookie Settings", href: "#" },
  ],
  className,
}: BadgeFooterProps) {
  const currentYear = new Date().getFullYear();
  const copyText = copyright || `© ${currentYear} ${brandName}. All Rights Reserved.`;

  return (
    <footer className={cn("w-full bg-white dark:bg-zinc-950 border-t border-slate-200 dark:border-zinc-800", className)}>
      <div className="max-w-7xl mx-auto py-16 px-6 lg:px-8">
        
        {/* Top Section */}
        <div className="flex flex-col lg:flex-row lg:justify-between lg:items-start gap-12 lg:gap-8">
          
          {/* Brand Info & Socials */}
          <div className="flex flex-col gap-6 lg:w-1/3">
            <a href="/" className="flex items-center gap-2 text-xl font-bold text-slate-900 dark:text-white">
              {logo}
              <span>{brandName}</span>
            </a>
            <p className="text-slate-500 dark:text-slate-400 text-sm leading-relaxed max-w-sm">
              {description}
            </p>
            <div className="flex space-x-5 mt-2">
              {socialLinks.map(({ icon: Icon, href, label }) => (
                <a
                  key={label}
                  href={href}
                  target="_blank"
                  rel="noopener noreferrer"
                  aria-label={label}
                  className="text-slate-400 hover:text-indigo-600 dark:text-slate-500 dark:hover:text-indigo-400 transition-colors"
                >
                  <Icon className="w-5 h-5" />
                </a>
              ))}
            </div>
          </div>

          {/* Link Columns */}
          <div className="grid grid-cols-2 sm:grid-cols-3 gap-8 lg:w-2/3 lg:justify-items-end">
            {columns.map((col) => (
              <div key={col.title} className="flex flex-col space-y-4 lg:min-w-[140px]">
                <h4 className="text-slate-900 dark:text-white font-semibold text-sm">
                  {col.title}
                </h4>
                <ul className="space-y-3">
                  {col.links.map(({ label, href, badge }) => (
                    <li key={label}>
                      <a
                        href={href}
                        className="text-slate-500 dark:text-slate-400 hover:text-indigo-600 dark:hover:text-indigo-400 transition-colors text-sm flex items-center gap-2 font-medium w-max"
                      >
                        {label}
                        {badge && (
                          <span className="bg-indigo-100 text-indigo-700 dark:bg-indigo-500/20 dark:text-indigo-300 text-[10px] uppercase tracking-wider font-bold px-1.5 py-0.5 rounded-sm">
                            {badge}
                          </span>
                        )}
                      </a>
                    </li>
                  ))}
                </ul>
              </div>
            ))}
          </div>
        </div>

        {/* Bottom Section */}
        <div className="mt-16 border-t border-slate-200 dark:border-zinc-800 pt-8 flex flex-col md:flex-row justify-between items-center text-sm font-medium text-slate-500 dark:text-slate-400 gap-4">
          <p>{copyText}</p>
          <div className="flex flex-wrap justify-center space-x-6 mt-2 md:mt-0">
            {bottomLinks.map((link) => (
              <a key={link.label} href={link.href} className="hover:text-slate-900 dark:hover:text-white transition-colors">
                {link.label}
              </a>
            ))}
          </div>
        </div>
      </div>
    </footer>
  );
}

--- FILE: frontend-web/registry/footers/BorderedGridFooter.tsx ---

import React from "react";
import { ArrowRight } from "lucide-react";
import { cn } from "../core/utils";

export interface FooterLink {
  title: string;
  href: string;
}

export interface FooterColumn {
  social: {
    title: string;
    href: string;
  };
  title: string;
  links: FooterLink[];
}

export interface BorderedGridFooterProps {
  brandName?: string;
  columns?: FooterColumn[];
  copyright?: string;
  className?: string;
}

const DEFAULT_COLUMNS: FooterColumn[] = [
  {
    social: { title: "Facebook", href: "#" },
    title: "About Us",
    links: [
      { title: "Pricing", href: "#" },
      { title: "Testimonials", href: "#" },
      { title: "FAQs", href: "#" },
      { title: "Contact Us", href: "#" },
      { title: "Blog", href: "#" },
    ],
  },
  {
    social: { title: "Youtube", href: "#" },
    title: "Support",
    links: [
      { title: "Help Center", href: "#" },
      { title: "Terms", href: "#" },
      { title: "Privacy", href: "#" },
      { title: "Security", href: "#" },
      { title: "Cookie Policy", href: "#" },
    ],
  },
  {
    social: { title: "Twitter", href: "#" },
    title: "Community",
    links: [
      { title: "Forum", href: "#" },
      { title: "Events", href: "#" },
      { title: "Partners", href: "#" },
      { title: "Affiliates", href: "#" },
      { title: "Career", href: "#" },
    ],
  },
  {
    social: { title: "Instagram", href: "#" },
    title: "Press",
    links: [
      { title: "Investors", href: "#" },
      { title: "Terms of Use", href: "#" },
      { title: "Privacy Policy", href: "#" },
      { title: "Cookie Policy", href: "#" },
      { title: "Legal", href: "#" },
    ],
  },
];

export function BorderedGridFooter({
  brandName = "Acme",
  columns = DEFAULT_COLUMNS,
  copyright,
  className,
}: BorderedGridFooterProps) {
  const currentYear = new Date().getFullYear();
  const copyText = copyright || `© ${currentYear} ${brandName}. All rights reserved.`;

  return (
    <footer
      className={cn(
        "border-t border-slate-200 dark:border-zinc-800 bg-white dark:bg-zinc-950",
        "bg-[radial-gradient(35%_128px_at_50%_0%,rgba(0,0,0,0.03),transparent)] dark:bg-[radial-gradient(35%_128px_at_50%_0%,rgba(255,255,255,0.08),transparent)]",
        className
      )}
    >
      <div className="relative mx-auto max-w-5xl px-4 py-12">
        <div className="relative grid grid-cols-1 border-x border-slate-200 dark:border-zinc-800 md:grid-cols-4 md:divide-x md:divide-slate-200 dark:md:divide-zinc-800">
          {columns.map((col, idx) => (
            <div key={idx}>
              <SocialCard title={col.social.title} href={col.social.href} />
              <LinksGroup title={col.title} links={col.links} />
            </div>
          ))}
        </div>
      </div>
      <div className="flex justify-center border-t border-slate-200 dark:border-zinc-800 p-4">
        <p className="text-slate-500 dark:text-slate-400 text-xs font-medium">
          {copyText}
        </p>
      </div>
    </footer>
  );
}

function LinksGroup({ title, links }: { title: string; links: FooterLink[] }) {
  return (
    <div className="p-4 md:p-6">
      <h3 className="text-slate-900 dark:text-slate-100 mt-2 mb-6 text-xs font-bold tracking-wider uppercase">
        {title}
      </h3>
      <ul className="space-y-3">
        {links.map((link) => (
          <li key={link.title}>
            <a
              href={link.href}
              className="text-slate-500 hover:text-slate-900 dark:text-slate-400 dark:hover:text-white text-sm font-medium transition-colors"
            >
              {link.title}
            </a>
          </li>
        ))}
      </ul>
    </div>
  );
}

function SocialCard({ title, href }: { title: string; href: string }) {
  return (
    <a
      href={href}
      className="hover:bg-slate-50 hover:text-slate-900 dark:hover:bg-zinc-900/50 dark:hover:text-white text-slate-700 dark:text-slate-300 flex items-center justify-between border-t border-b border-slate-200 dark:border-zinc-800 p-4 md:p-6 text-sm md:border-t-0 transition-colors"
    >
      <span className="font-semibold">{title}</span>
      <ArrowRight className="h-4 w-4" />
    </a>
  );
}

--- FILE: frontend-web/registry/footers/BoxedMinimalFooter.tsx ---

import React from 'react';
import {
  FacebookIcon,
  GithubIcon,
  Grid2X2Plus,
  InstagramIcon,
  LinkedinIcon,
  TwitterIcon,
  YoutubeIcon,
} from 'lucide-react';
import { cn } from '../core/utils';

export interface FooterLink {
  title: string;
  href: string;
}

export interface SocialLink {
  icon: React.ElementType;
  href: string;
  label: string;
}

export interface BoxedMinimalFooterProps {
  brandName?: string;
  logo?: React.ReactNode;
  description?: string;
  companyLinks?: FooterLink[];
  resourceLinks?: FooterLink[];
  socialLinks?: SocialLink[];
  copyright?: string;
  className?: string;
}

const DEFAULT_COMPANY_LINKS: FooterLink[] = [
  { title: 'About Us', href: '#' },
  { title: 'Careers', href: '#' },
  { title: 'Brand assets', href: '#' },
  { title: 'Privacy Policy', href: '#' },
  { title: 'Terms of Service', href: '#' },
];

const DEFAULT_RESOURCE_LINKS: FooterLink[] = [
  { title: 'Blog', href: '#' },
  { title: 'Help Center', href: '#' },
  { title: 'Contact Support', href: '#' },
  { title: 'Community', href: '#' },
  { title: 'Security', href: '#' },
];

const DEFAULT_SOCIAL_LINKS: SocialLink[] = [
  { icon: FacebookIcon, href: '#', label: 'Facebook' },
  { icon: GithubIcon, href: '#', label: 'GitHub' },
  { icon: InstagramIcon, href: '#', label: 'Instagram' },
  { icon: LinkedinIcon, href: '#', label: 'LinkedIn' },
  { icon: TwitterIcon, href: '#', label: 'Twitter' },
  { icon: YoutubeIcon, href: '#', label: 'YouTube' },
];

export function BoxedMinimalFooter({
  brandName = "NOVA UI",
  logo = <Grid2X2Plus className="size-8" />,
  description = "A comprehensive financial technology platform.",
  companyLinks = DEFAULT_COMPANY_LINKS,
  resourceLinks = DEFAULT_RESOURCE_LINKS,
  socialLinks = DEFAULT_SOCIAL_LINKS,
  copyright,
  className,
}: BoxedMinimalFooterProps) {
  const year = new Date().getFullYear();
  const copyText = copyright || `© ${year} ${brandName}. All rights reserved.`;

  return (
    <footer className={cn("relative bg-white dark:bg-zinc-950 text-slate-900 dark:text-white pt-16", className)}>
      <div className="bg-[radial-gradient(35%_80%_at_30%_0%,rgba(0,0,0,0.05),transparent)] dark:bg-[radial-gradient(35%_80%_at_30%_0%,rgba(255,255,255,0.1),transparent)] mx-auto max-w-4xl border-x border-slate-200 dark:border-zinc-800">
        
        {/* Top border line */}
        <div className="bg-slate-200 dark:bg-zinc-800 absolute inset-x-0 h-px w-full" />
        
        <div className="grid max-w-4xl grid-cols-6 gap-6 p-6 md:p-8">
          
          {/* Brand & Socials (Spans left side) */}
          <div className="col-span-6 flex flex-col gap-5 md:col-span-4">
            <a href="/" className="w-max opacity-80 hover:opacity-100 transition-opacity text-indigo-600 dark:text-indigo-400" aria-label={brandName}>
              {logo}
            </a>
            <p className="text-slate-500 dark:text-slate-400 max-w-sm font-mono text-sm leading-relaxed">
              {description}
            </p>
            <div className="flex flex-wrap gap-2 mt-2">
              {socialLinks.map((item, i) => {
                const Icon = item.icon;
                return (
                  <a
                    key={i}
                    aria-label={item.label}
                    className="hover:bg-slate-100 dark:hover:bg-zinc-800 text-slate-400 hover:text-slate-900 dark:text-slate-500 dark:hover:text-white transition-colors duration-200 rounded-md border border-slate-200 dark:border-zinc-800 p-2"
                    target="_blank"
                    rel="noopener noreferrer"
                    href={item.href}
                  >
                    <Icon className="size-4" />
                  </a>
                );
              })}
            </div>
          </div>

          {/* Resources Column */}
          <div className="col-span-3 w-full md:col-span-1">
            <span className="text-slate-500 dark:text-slate-400 mb-3 block text-xs font-semibold uppercase tracking-wider">
              Resources
            </span>
            <div className="flex flex-col gap-2.5">
              {resourceLinks.map(({ href, title }, i) => (
                <a
                  key={i}
                  className="w-max text-sm font-medium text-slate-600 dark:text-slate-300 hover:text-indigo-600 dark:hover:text-indigo-400 duration-200 hover:underline underline-offset-4"
                  href={href}
                >
                  {title}
                </a>
              ))}
            </div>
          </div>

          {/* Company Column */}
          <div className="col-span-3 w-full md:col-span-1">
            <span className="text-slate-500 dark:text-slate-400 mb-3 block text-xs font-semibold uppercase tracking-wider">
              Company
            </span>
            <div className="flex flex-col gap-2.5">
              {companyLinks.map(({ href, title }, i) => (
                <a
                  key={i}
                  className="w-max text-sm font-medium text-slate-600 dark:text-slate-300 hover:text-indigo-600 dark:hover:text-indigo-400 duration-200 hover:underline underline-offset-4"
                  href={href}
                >
                  {title}
                </a>
              ))}
            </div>
          </div>
        </div>

        {/* Bottom border line */}
        <div className="bg-slate-200 dark:bg-zinc-800 absolute inset-x-0 h-px w-full" />
        
        {/* Copyright */}
        <div className="flex max-w-4xl flex-col justify-center items-center py-6 px-4">
          <p className="text-slate-500 dark:text-slate-400 text-center text-sm font-medium">
            {copyText}
          </p>
        </div>
      </div>
    </footer>
  );
}

--- FILE: frontend-web/registry/footers/CenteredFooter.tsx ---

import React from 'react';
import { Facebook, Twitter, Instagram, Linkedin, Github, Hexagon } from 'lucide-react';
import { cn } from '../core/utils';

export interface FooterLink {
  title: string;
  href: string;
}

export interface SocialLink {
  icon: React.ElementType;
  href: string;
  label: string;
}

export interface CenteredFooterProps {
  logo?: React.ReactNode;
  links?: FooterLink[];
  socialLinks?: SocialLink[];
  copyright?: string;
  className?: string;
}

const DEFAULT_LINKS: FooterLink[] = [
  { title: 'Features', href: '#' },
  { title: 'Solutions', href: '#' },
  { title: 'Customers', href: '#' },
  { title: 'Pricing', href: '#' },
  { title: 'Help', href: '#' },
  { title: 'About Us', href: '#' },
];

const DEFAULT_SOCIALS: SocialLink[] = [
  { icon: Twitter, label: 'Twitter', href: '#' },
  { icon: Facebook, label: 'Facebook', href: '#' },
  { icon: Instagram, label: 'Instagram', href: '#' },
  { icon: Linkedin, label: 'LinkedIn', href: '#' },
  { icon: Github, label: 'GitHub', href: '#' },
];

export function CenteredFooter({
  logo = <Hexagon className="w-10 h-10 text-indigo-600 dark:text-indigo-400" />,
  links = DEFAULT_LINKS,
  socialLinks = DEFAULT_SOCIALS,
  copyright = `© ${new Date().getFullYear()} NOVA UI. All rights reserved.`,
  className,
}: CenteredFooterProps) {
  return (
    <footer className={cn("py-16 md:py-24 bg-white dark:bg-zinc-950 text-slate-900 dark:text-white", className)}>
      <div className="mx-auto max-w-5xl px-6">
        {logo && (
          <a href="/" aria-label="Home" className="mx-auto flex justify-center w-fit">
            {logo}
          </a>
        )}

        <div className="my-8 flex flex-wrap justify-center gap-6 text-sm font-medium">
          {links.map((link, index) => (
            <a
              key={index}
              href={link.href}
              className="text-slate-500 hover:text-slate-900 dark:text-slate-400 dark:hover:text-white transition-colors duration-200"
            >
              {link.title}
            </a>
          ))}
        </div>

        <div className="my-8 flex flex-wrap justify-center gap-6 text-sm">
          {socialLinks.map((social, index) => {
            const Icon = social.icon;
            return (
              <a
                key={index}
                href={social.href}
                target="_blank"
                rel="noopener noreferrer"
                aria-label={social.label}
                className="text-slate-400 hover:text-indigo-600 dark:text-slate-500 dark:hover:text-indigo-400 transition-colors duration-200"
              >
                <Icon className="size-6" />
              </a>
            );
          })}
        </div>
        
        <span className="block text-center text-sm text-slate-500 dark:text-slate-400">
          {copyright}
        </span>
      </div>
    </footer>
  );
}

--- FILE: frontend-web/registry/footers/CinematicFooter.tsx ---

import React, { useEffect, useRef } from "react";
import { gsap } from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
import { cn } from "../core/utils";

// Register ScrollTrigger safely for React
if (typeof window !== "undefined") {
  gsap.registerPlugin(ScrollTrigger);
}

// --- CSS STYLES ---
const STYLES = `
.cinematic-footer-wrapper {
  /* Dynamic Variables using standard tailwind tokens wrapped in hsl() */
  --pill-bg-1: color-mix(in srgb, hsl(var(--foreground)) 3%, transparent);
  --pill-bg-2: color-mix(in srgb, hsl(var(--foreground)) 1%, transparent);
  --pill-shadow: color-mix(in srgb, hsl(var(--background)) 50%, transparent);
  --pill-highlight: color-mix(in srgb, hsl(var(--foreground)) 10%, transparent);
  --pill-inset-shadow: color-mix(in srgb, hsl(var(--background)) 80%, transparent);
  --pill-border: color-mix(in srgb, hsl(var(--foreground)) 8%, transparent);
  
  --pill-bg-1-hover: color-mix(in srgb, hsl(var(--foreground)) 8%, transparent);
  --pill-bg-2-hover: color-mix(in srgb, hsl(var(--foreground)) 2%, transparent);
  --pill-border-hover: color-mix(in srgb, hsl(var(--foreground)) 20%, transparent);
  --pill-shadow-hover: color-mix(in srgb, hsl(var(--background)) 70%, transparent);
  --pill-highlight-hover: color-mix(in srgb, hsl(var(--foreground)) 20%, transparent);
}

@keyframes footer-breathe {
  0% { transform: translate(-50%, -50%) scale(1); opacity: 0.6; }
  100% { transform: translate(-50%, -50%) scale(1.1); opacity: 1; }
}

@keyframes footer-scroll-marquee {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}

@keyframes footer-heartbeat {
  0%, 100% { transform: scale(1); filter: drop-shadow(0 0 5px color-mix(in srgb, hsl(var(--destructive, 0 84% 60%)) 50%, transparent)); }
  15%, 45% { transform: scale(1.2); filter: drop-shadow(0 0 10px color-mix(in srgb, hsl(var(--destructive, 0 84% 60%)) 80%, transparent)); }
  30% { transform: scale(1); }
}

.animate-footer-breathe {
  animation: footer-breathe 8s ease-in-out infinite alternate;
}

.animate-footer-scroll-marquee {
  animation: footer-scroll-marquee 40s linear infinite;
}

.animate-footer-heartbeat {
  animation: footer-heartbeat 2s cubic-bezier(0.25, 1, 0.5, 1) infinite;
}

.footer-bg-grid {
  background-size: 60px 60px;
  background-image: 
    linear-gradient(to right, color-mix(in srgb, hsl(var(--foreground)) 3%, transparent) 1px, transparent 1px),
    linear-gradient(to bottom, color-mix(in srgb, hsl(var(--foreground)) 3%, transparent) 1px, transparent 1px);
  mask-image: linear-gradient(to bottom, transparent, black 30%, black 70%, transparent);
  -webkit-mask-image: linear-gradient(to bottom, transparent, black 30%, black 70%, transparent);
}

.footer-aurora {
  background: radial-gradient(
    circle at 50% 50%, 
    color-mix(in srgb, hsl(var(--primary, 222 47% 11%)) 15%, transparent) 0%, 
    color-mix(in srgb, hsl(var(--secondary, 210 40% 96%)) 15%, transparent) 40%, 
    transparent 70%
  );
}

.footer-glass-pill {
  background: linear-gradient(145deg, var(--pill-bg-1) 0%, var(--pill-bg-2) 100%);
  box-shadow: 
      0 10px 30px -10px var(--pill-shadow), 
      inset 0 1px 1px var(--pill-highlight), 
      inset 0 -1px 2px var(--pill-inset-shadow);
  border: 1px solid var(--pill-border);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  transition: all 0.4s cubic-bezier(0.16, 1, 0.3, 1);
}

.footer-glass-pill:hover {
  background: linear-gradient(145deg, var(--pill-bg-1-hover) 0%, var(--pill-bg-2-hover) 100%);
  border-color: var(--pill-border-hover);
  box-shadow: 
      0 20px 40px -10px var(--pill-shadow-hover), 
      inset 0 1px 1px var(--pill-highlight-hover);
  color: hsl(var(--foreground));
}

.footer-giant-bg-text {
  font-size: 26vw;
  line-height: 0.75;
  font-weight: 900;
  letter-spacing: -0.05em;
  color: transparent;
  -webkit-text-stroke: 1px color-mix(in srgb, hsl(var(--foreground)) 5%, transparent);
  background: linear-gradient(180deg, color-mix(in srgb, hsl(var(--foreground)) 10%, transparent) 0%, transparent 60%);
  -webkit-background-clip: text;
  background-clip: text;
}

.footer-text-glow {
  background: linear-gradient(180deg, hsl(var(--foreground)) 0%, color-mix(in srgb, hsl(var(--foreground)) 40%, transparent) 100%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  filter: drop-shadow(0px 0px 20px color-mix(in srgb, hsl(var(--foreground)) 15%, transparent));
}
`;

// --- MAGNETIC BUTTON ---
export type MagneticButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> & 
  React.AnchorHTMLAttributes<HTMLAnchorElement> & {
    as?: React.ElementType;
  };

const MagneticButton = React.forwardRef<HTMLElement, MagneticButtonProps>(
  ({ className, children, as: Component = "button", ...props }, forwardedRef) => {
    const localRef = useRef<HTMLElement>(null);

    useEffect(() => {
      if (typeof window === "undefined") return;
      const element = localRef.current;
      if (!element) return;

      const ctx = gsap.context(() => {
        const handleMouseMove = (e: MouseEvent) => {
          const rect = element.getBoundingClientRect();
          const h = rect.width / 2;
          const w = rect.height / 2;
          const x = e.clientX - rect.left - h;
          const y = e.clientY - rect.top - w;

          gsap.to(element, {
            x: x * 0.4,
            y: y * 0.4,
            rotationX: -y * 0.15,
            rotationY: x * 0.15,
            scale: 1.05,
            ease: "power2.out",
            duration: 0.4,
          });
        };

        const handleMouseLeave = () => {
          gsap.to(element, {
            x: 0,
            y: 0,
            rotationX: 0,
            rotationY: 0,
            scale: 1,
            ease: "elastic.out(1, 0.3)",
            duration: 1.2,
          });
        };

        element.addEventListener("mousemove", handleMouseMove as EventListener);
        element.addEventListener("mouseleave", handleMouseLeave);

        return () => {
          element.removeEventListener("mousemove", handleMouseMove as EventListener);
          element.removeEventListener("mouseleave", handleMouseLeave);
        };
      }, element);

      return () => ctx.revert();
    }, []);

    return (
      <Component
        ref={(node: HTMLElement) => {
          // eslint-disable-next-line @typescript-eslint/no-explicit-any
          (localRef as any).current = node;
          if (typeof forwardedRef === "function") forwardedRef(node);
          // eslint-disable-next-line @typescript-eslint/no-explicit-any
          else if (forwardedRef) (forwardedRef as any).current = node;
        }}
        className={cn("cursor-pointer", className)}
        {...props}
      >
        {children}
      </Component>
    );
  }
);
MagneticButton.displayName = "MagneticButton";

// --- MAIN COMPONENT ---

export interface CinematicFooterProps {
  brandName?: string;
  heading?: string;
  marqueeItems?: string[];
  primaryLinks?: Array<{ label: string; href: string; icon?: React.ReactNode }>;
  secondaryLinks?: Array<{ label: string; href: string }>;
  creatorName?: string;
  copyrightYear?: number;
  className?: string;
}

const DEFAULT_MARQUEE = [
  "Accountability Redefined",
  "Transparent Tracking",
  "12-Step Progress",
  "Sponsor Connection",
  "Absolute Privacy"
];

const DEFAULT_PRIMARY = [
  {
    label: "Download iOS",
    href: "#",
    icon: (
      <svg className="w-6 h-6 text-slate-500 dark:text-slate-400 group-hover:text-slate-900 dark:group-hover:text-white transition-colors" viewBox="0 0 24 24" fill="currentColor">
        <path d="M17.05 20.28c-.98.95-2.05.8-3.08.35-1.09-.46-2.09-.48-3.24 0-1.44.62-2.2.44-3.06-.35C2.79 15.25 3.51 7.59 9.05 7.31c1.35.07 2.29.74 3.08.8 1.18-.04 2.26-.79 3.59-.76 1.56.04 2.87.67 3.55 1.76-3.13 1.77-2.62 5.92.35 7.14-.65 1.58-1.57 3.1-2.57 4.03zm-3.21-14.7c-.55 1.4-1.89 2.37-3.25 2.28.09-1.5 1.05-2.82 2.38-3.4 1.25-.57 2.66-.41 3.25.04-.15.35-.26.72-.38 1.08z" />
      </svg>
    )
  },
  {
    label: "Download Android",
    href: "#",
    icon: (
      <svg className="w-6 h-6 text-slate-500 dark:text-slate-400 group-hover:text-slate-900 dark:group-hover:text-white transition-colors" viewBox="0 0 24 24" fill="currentColor">
        <path d="M17.523 15.3414c-.5511 0-.9993-.4486-.9993-.9997s.4482-.9993.9993-.9993c.5511 0 .9993.4482.9993.9993.0004.5511-.4482.9997-.9993.9997m-11.046 0c-.5511 0-.9993-.4486-.9993-.9997s.4482-.9993.9993-.9993c.5511 0 .9993.4482.9993.9993.0004.5511-.4482.9997-.9993.9997m11.4045-6.02l1.9973-3.4592a.416.416 0 00-.1521-.5676.416.416 0 00-.5676.1521l-2.0222 3.503C15.5902 8.242 13.8533 7.85 12 7.85c-1.8533 0-3.5902.392-5.1369 1.1004L4.841 5.4475a.416.416 0 00-.5676-.1521.416.416 0 00-.1521.5676l1.9973 3.4592C2.6889 11.1867.3432 14.6589 0 18.761h24c-.3436-4.1021-2.6893-7.5743-6.1185-9.4396" />
      </svg>
    )
  }
];

const DEFAULT_SECONDARY = [
  { label: "Privacy Policy", href: "#" },
  { label: "Terms of Service", href: "#" },
  { label: "Support", href: "#" },
];

export function CinematicFooter({
  brandName = "NOVA",
  heading = "Ready to begin?",
  marqueeItems = DEFAULT_MARQUEE,
  primaryLinks = DEFAULT_PRIMARY,
  secondaryLinks = DEFAULT_SECONDARY,
  creatorName = "NOVA UI",
  copyrightYear = new Date().getFullYear(),
  className
}: CinematicFooterProps) {
  const wrapperRef = useRef<HTMLDivElement>(null);
  const giantTextRef = useRef<HTMLDivElement>(null);
  const headingRef = useRef<HTMLHeadingElement>(null);
  const linksRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    if (typeof window === "undefined") return;
    if (!wrapperRef.current) return;

    const ctx = gsap.context(() => {
      // Background Parallax
      gsap.fromTo(
        giantTextRef.current,
        { y: "10vh", scale: 0.8, opacity: 0 },
        {
          y: "0vh",
          scale: 1,
          opacity: 1,
          ease: "power1.out",
          scrollTrigger: {
            trigger: wrapperRef.current,
            start: "top 80%",
            end: "bottom bottom",
            scrub: 1,
          },
        }
      );

      // Staggered Content Reveal
      gsap.fromTo(
        [headingRef.current, linksRef.current],
        { y: 50, opacity: 0 },
        {
          y: 0,
          opacity: 1,
          stagger: 0.15,
          ease: "power3.out",
          scrollTrigger: {
            trigger: wrapperRef.current,
            start: "top 40%",
            end: "bottom bottom",
            scrub: 1,
          },
        }
      );
    }, wrapperRef);

    return () => ctx.revert();
  }, []);

  const scrollToTop = () => {
    window.scrollTo({ top: 0, behavior: "smooth" });
  };

  const MarqueeBlock = () => (
    <div className="flex items-center space-x-12 px-6">
      {marqueeItems.map((item, idx) => (
        <React.Fragment key={idx}>
          <span>{item}</span> 
          <span className={idx % 2 === 0 ? "text-indigo-500/60" : "text-purple-500/60"}>✦</span>
        </React.Fragment>
      ))}
    </div>
  );

  return (
    <>
      <style dangerouslySetInnerHTML={{ __html: STYLES }} />
      
      <div
        ref={wrapperRef}
        className={cn("relative h-screen w-full", className)}
        style={{ clipPath: "polygon(0% 0, 100% 0%, 100% 100%, 0 100%)" }}
      >
        <footer className="fixed bottom-0 left-0 flex h-screen w-full flex-col justify-between overflow-hidden bg-white dark:bg-zinc-950 text-slate-900 dark:text-white cinematic-footer-wrapper">
          
          <div className="footer-aurora absolute left-1/2 top-1/2 h-[60vh] w-[80vw] -translate-x-1/2 -translate-y-1/2 animate-footer-breathe rounded-[50%] blur-[80px] pointer-events-none z-0" />
          <div className="footer-bg-grid absolute inset-0 z-0 pointer-events-none" />

          <div
            ref={giantTextRef}
            className="footer-giant-bg-text absolute -bottom-[5vh] left-1/2 -translate-x-1/2 whitespace-nowrap z-0 pointer-events-none select-none uppercase"
          >
            {brandName}
          </div>

          <div className="absolute top-12 left-0 w-full overflow-hidden border-y border-slate-200/50 dark:border-zinc-800/50 bg-white/60 dark:bg-zinc-950/60 backdrop-blur-md py-4 z-10 -rotate-2 scale-110 shadow-2xl">
            <div className="flex w-max animate-footer-scroll-marquee text-xs md:text-sm font-bold tracking-[0.3em] text-slate-500 dark:text-slate-400 uppercase">
              <MarqueeBlock />
              <MarqueeBlock />
            </div>
          </div>

          <div className="relative z-10 flex flex-1 flex-col items-center justify-center px-6 mt-20 w-full max-w-5xl mx-auto">
            <h2
              ref={headingRef}
              className="text-5xl md:text-8xl font-black footer-text-glow tracking-tighter mb-12 text-center"
            >
              {heading}
            </h2>

            <div ref={linksRef} className="flex flex-col items-center gap-6 w-full">
              <div className="flex flex-wrap justify-center gap-4 w-full">
                {primaryLinks.map((link, idx) => (
                  <MagneticButton key={idx} as="a" href={link.href} className="footer-glass-pill px-10 py-5 rounded-full font-bold text-sm md:text-base flex items-center gap-3 group">
                    {link.icon}
                    {link.label}
                  </MagneticButton>
                ))}
              </div>

              <div className="flex flex-wrap justify-center gap-3 md:gap-6 w-full mt-2">
                {secondaryLinks.map((link, idx) => (
                  <MagneticButton key={idx} as="a" href={link.href} className="footer-glass-pill px-6 py-3 rounded-full text-slate-500 dark:text-slate-400 font-medium text-xs md:text-sm hover:text-slate-900 dark:hover:text-white">
                    {link.label}
                  </MagneticButton>
                ))}
              </div>
            </div>
          </div>

          <div className="relative z-20 w-full pb-8 px-6 md:px-12 flex flex-col md:flex-row items-center justify-between gap-6">
            
            <div className="text-slate-500 dark:text-slate-400 text-[10px] md:text-xs font-bold tracking-widest uppercase order-2 md:order-1">
              © {copyrightYear} {creatorName}. All rights reserved.
            </div>

            <div className="footer-glass-pill px-6 py-3 rounded-full flex items-center gap-2 order-1 md:order-2 cursor-default border-slate-200/50 dark:border-zinc-800/50">
              <span className="text-slate-500 dark:text-slate-400 text-[10px] md:text-xs font-bold uppercase tracking-widest">Crafted with</span>
              <span className="animate-footer-heartbeat text-sm md:text-base text-rose-500">❤</span>
              <span className="text-slate-500 dark:text-slate-400 text-[10px] md:text-xs font-bold uppercase tracking-widest">by</span>
              <span className="font-black text-xs md:text-sm tracking-normal ml-1">{creatorName}</span>
            </div>

            <MagneticButton
              as="button"
              onClick={scrollToTop}
              className="w-12 h-12 rounded-full footer-glass-pill flex items-center justify-center text-slate-500 dark:text-slate-400 hover:text-slate-900 dark:hover:text-white group order-3"
            >
              <svg className="w-5 h-5 transform group-hover:-translate-y-1.5 transition-transform duration-300" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M5 10l7-7m0 0l7 7m-7-7v18"></path>
              </svg>
            </MagneticButton>

          </div>
        </footer>
      </div>
    </>
  );
}

--- FILE: frontend-web/registry/footers/CorporateFooter.tsx ---

import React from "react";
import { Hexagon } from "lucide-react";
import { cn } from "../core/utils";

export interface FooterLink {
  text: string;
  url: string;
}

export interface FooterMenuSection {
  title: string;
  links: FooterLink[];
}

export interface CorporateFooterProps {
  brandName?: string;
  logo?: React.ReactNode;
  description?: string;
  menuItems?: FooterMenuSection[];
  bottomLinks?: FooterLink[];
  copyright?: string;
  className?: string;
}

const DEFAULT_MENU_ITEMS: FooterMenuSection[] = [
  {
    title: "Product",
    links: [
      { text: "Overview", url: "#" },
      { text: "Features", url: "#" },
      { text: "Pricing", url: "#" },
      { text: "Changelog", url: "#" },
      { text: "Marketplace", url: "#" },
    ],
  },
  {
    title: "Company",
    links: [
      { text: "About", url: "#" },
      { text: "Team", url: "#" },
      { text: "Careers", url: "#" },
      { text: "Blog", url: "#" },
      { text: "Press", url: "#" },
    ],
  },
  {
    title: "Resources",
    links: [
      { text: "Docs", url: "#" },
      { text: "API Reference", url: "#" },
      { text: "Help Center", url: "#" },
      { text: "Guides", url: "#" },
      { text: "Community", url: "#" },
    ],
  },
  {
    title: "Developers",
    links: [
      { text: "CLI Tools", url: "#" },
      { text: "SDKs", url: "#" },
      { text: "GitHub", url: "#" },
      { text: "Code Samples", url: "#" },
      { text: "Open Source", url: "#" },
    ],
  },
  {
    title: "Solutions",
    links: [
      { text: "Startups", url: "#" },
      { text: "Enterprise", url: "#" },
      { text: "E-commerce", url: "#" },
      { text: "Agencies", url: "#" },
      { text: "Education", url: "#" },
    ],
  },
  {
    title: "Partners",
    links: [
      { text: "Technology", url: "#" },
      { text: "Agencies", url: "#" },
      { text: "Integrations", url: "#" },
      { text: "Resellers", url: "#" },
      { text: "Affiliates", url: "#" },
    ],
  },
  {
    title: "Social",
    links: [
      { text: "Twitter", url: "#" },
      { text: "LinkedIn", url: "#" },
      { text: "GitHub", url: "#" },
      { text: "YouTube", url: "#" },
      { text: "Discord", url: "#" },
    ],
  },
];

const DEFAULT_BOTTOM_LINKS: FooterLink[] = [
  { text: "Terms", url: "#" },
  { text: "Privacy", url: "#" },
  { text: "Security", url: "#" },
  { text: "Cookies", url: "#" },
];

export function CorporateFooter({
  brandName = "NOVA UI",
  logo = <Hexagon className="h-10 w-10 text-indigo-600 dark:text-indigo-400 mb-4" />,
  description = "Pioneering modern developer experiences with a platform built for scalability, reliability, and speed. From startups to global enterprises, we empower teams to ship better products faster with open source tools and AI-driven integrations.",
  menuItems = DEFAULT_MENU_ITEMS,
  bottomLinks = DEFAULT_BOTTOM_LINKS,
  copyright = `© ${new Date().getFullYear()} NOVA UI. All rights reserved.`,
  className,
}: CorporateFooterProps) {
  return (
    <footer className={cn("bg-white dark:bg-zinc-950 py-16 border-t border-slate-200 dark:border-zinc-800", className)}>
      <div className="container mx-auto px-6">
        <div className="flex flex-col xl:flex-row xl:justify-between xl:items-start gap-12">
          
          {/* Branding & Description */}
          <div className="max-w-sm text-center xl:text-left mx-auto xl:mx-0">
            <div className="flex justify-center xl:justify-start">
              {logo}
            </div>
            <div>
              <h3 className="mb-3 text-sm font-bold text-slate-900 dark:text-white uppercase tracking-wider">
                About {brandName}
              </h3>
              <p className="text-sm text-slate-500 dark:text-slate-400 leading-relaxed">
                {description}
              </p>
            </div>
          </div>

          {/* Mega Menu Links */}
          <div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-7 gap-8 flex-1">
            {menuItems.map((section, sectionIdx) => (
              <div key={sectionIdx}>
                <h3 className="mb-4 text-sm font-bold text-slate-900 dark:text-white">
                  {section.title}
                </h3>
                <ul className="space-y-3 text-sm text-slate-500 dark:text-slate-400">
                  {section.links.map((link, linkIdx) => (
                    <li
                      key={linkIdx}
                      className="hover:text-indigo-600 dark:hover:text-indigo-400 transition-colors font-medium"
                    >
                      <a href={link.url}>{link.text}</a>
                    </li>
                  ))}
                </ul>
              </div>
            ))}
          </div>
        </div>

        {/* Bottom Legal Bar */}
        <div className="border-t border-slate-200 dark:border-zinc-800 mt-16 pt-8 flex flex-col md:flex-row justify-between items-center text-sm font-medium text-slate-500 dark:text-slate-400 gap-4">
          <p>{copyright}</p>
          <ul className="flex flex-wrap justify-center gap-6">
            {bottomLinks.map((link, linkIdx) => (
              <li
                key={linkIdx}
                className="hover:text-slate-900 dark:hover:text-white transition-colors"
              >
                <a href={link.url}>{link.text}</a>
              </li>
            ))}
          </ul>
        </div>
      </div>
    </footer>
  );
}

--- FILE: frontend-web/registry/footers/FadeInFooter.tsx ---

import React from "react";
import { motion } from "framer-motion";
import { cn } from "../core/utils";
import { Hexagon } from "lucide-react";

interface ContainerProps {
  className?: string;
  children: React.ReactNode;
  delay?: number;
  reverse?: boolean;
  simple?: boolean;
}

const Container = ({ children, className, delay = 0.2, reverse, simple }: ContainerProps) => {
  return (
    <motion.div
      className={cn("w-full h-full", className)}
      initial={{ opacity: 0, y: reverse ? -20 : 20 }}
      whileInView={{ opacity: 1, y: 0 }}
      viewport={{ once: true }}
      transition={{
        delay: delay,
        duration: simple ? 0.2 : 0.4,
        type: simple ? "keyframes" : "spring",
        stiffness: simple ? 100 : undefined,
      }}
    >
      {children}
    </motion.div>
  );
};

export interface FooterLink {
  name: string;
  href: string;
}

export interface FooterSection {
  title: string;
  links: FooterLink[];
}

export interface FadeInFooterProps {
  brandName?: string;
  logo?: React.ReactNode;
  description?: string;
  sections?: FooterSection[];
  copyright?: string;
  className?: string;
}

const DEFAULT_SECTIONS: FooterSection[] = [
  {
    title: "Product",
    links: [
      { name: "Components", href: "#" },
      { name: "Pricing", href: "#" },
      { name: "Use Cases", href: "#" },
      { name: "Language Support", href: "#" },
    ],
  },
  {
    title: "Solutions",
    links: [
      { name: "Developers", href: "#" },
      { name: "Design Teams", href: "#" },
      { name: "Startups", href: "#" },
      { name: "Enterprises", href: "#" },
    ],
  },
  {
    title: "Resources",
    links: [
      { name: "Documentation", href: "#" },
      { name: "Component Guides", href: "#" },
      { name: "Support Center", href: "#" },
    ],
  },
  {
    title: "Company",
    links: [
      { name: "Our Story", href: "#" },
      { name: "Privacy Policy", href: "#" },
      { name: "Terms of Service", href: "#" },
    ],
  },
];

export function FadeInFooter({
  brandName = "NOVA UI",
  logo = <Hexagon className="h-8 w-8 text-indigo-600 dark:text-indigo-400" />,
  description = "Build better UIs faster with our AI-enhanced component library for modern teams.",
  sections = DEFAULT_SECTIONS,
  copyright = "© 2025 NOVA UI. Built for UI excellence.",
  className,
}: FadeInFooterProps) {
  return (
    <footer
      className={cn(
        "flex flex-col relative items-center justify-center border-t border-slate-200 dark:border-zinc-800 pt-16 pb-8 px-6 lg:px-8 w-full max-w-6xl mx-auto lg:pt-32 bg-white dark:bg-zinc-950",
        className
      )}
    >
      <div className="grid gap-8 xl:grid-cols-3 xl:gap-8 w-full">
        <Container>
          <div className="flex flex-col items-start justify-start md:max-w-[250px]">
            <div className="flex items-center gap-2 text-slate-900 dark:text-white font-bold text-xl">
              {logo}
              <span>{brandName}</span>
            </div>
            <p className="text-slate-500 dark:text-slate-400 mt-4 text-sm text-start leading-relaxed">
              {description}
            </p>
          </div>
        </Container>

        <div className="grid-cols-2 gap-8 grid mt-16 xl:col-span-2 xl:mt-0">
          <div className="md:grid md:grid-cols-2 md:gap-8">
            {sections.slice(0, 2).map((section, idx) => (
              <Container key={section.title} delay={0.1 + idx * 0.1} className="h-auto">
                <h3 className="text-base font-semibold text-slate-900 dark:text-white mt-10 md:mt-0">
                  {section.title}
                </h3>
                <ul className="mt-4 text-sm text-slate-500 dark:text-slate-400 space-y-4">
                  {section.links.map((link) => (
                    <li key={link.name}>
                      <a
                        href={link.href}
                        className="hover:text-slate-900 dark:hover:text-white transition-colors duration-300"
                      >
                        {link.name}
                      </a>
                    </li>
                  ))}
                </ul>
              </Container>
            ))}
          </div>
          <div className="md:grid md:grid-cols-2 md:gap-8">
            {sections.slice(2, 4).map((section, idx) => (
              <Container key={section.title} delay={0.3 + idx * 0.1} className="h-auto">
                <h3 className="text-base font-semibold text-slate-900 dark:text-white mt-10 md:mt-0">
                  {section.title}
                </h3>
                <ul className="mt-4 text-sm text-slate-500 dark:text-slate-400 space-y-4">
                  {section.links.map((link) => (
                    <li key={link.name}>
                      <a
                        href={link.href}
                        className="hover:text-slate-900 dark:hover:text-white transition-colors duration-300"
                      >
                        {link.name}
                      </a>
                    </li>
                  ))}
                </ul>
              </Container>
            ))}
          </div>
        </div>
      </div>

      <Container delay={0.5} className="w-full relative mt-12 lg:mt-20">
        <div className="mt-8 md:flex md:items-center justify-center w-full">
          <p className="text-sm text-slate-500 dark:text-slate-400 mt-8 md:mt-0">
            {copyright}
          </p>
        </div>
      </Container>
    </footer>
  );
}

--- FILE: frontend-web/registry/footers/FlickeringGridFooter.tsx ---

import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { ChevronRightIcon } from "lucide-react";
import { cn } from "../core/utils";

// --- Utility Functions ---

export const getRGBA = (
  cssColor: React.CSSProperties["color"],
  fallback: string = "rgba(180, 180, 180)"
): string => {
  if (typeof window === "undefined") return fallback;
  if (!cssColor) return fallback;

  try {
    if (typeof cssColor === "string" && cssColor.startsWith("var(")) {
      const element = document.createElement("div");
      element.style.color = cssColor;
      document.body.appendChild(element);
      const computedColor = window.getComputedStyle(element).color;
      document.body.removeChild(element);
      return computedColor;
    }
    
    // Quick hex to rgba converter for canvas
    if (typeof cssColor === "string" && cssColor.startsWith("#")) {
        const hex = cssColor.replace("#", "");
        const r = parseInt(hex.substring(0, 2), 16);
        const g = parseInt(hex.substring(2, 4), 16);
        const b = parseInt(hex.substring(4, 6), 16);
        return `rgba(${r}, ${g}, ${b})`;
    }

    return cssColor as string;
  } catch (e) {
    return fallback;
  }
};

export const colorWithOpacity = (colorString: string, opacity: number): string => {
  if (colorString.startsWith("rgba")) {
      return colorString.replace(/[\d.]+\)$/g, `${opacity})`);
  }
  if (colorString.startsWith("rgb")) {
      return colorString.replace(")", `, ${opacity})`).replace("rgb", "rgba");
  }
  return colorString;
};

export function useMediaQuery(query: string) {
  const [value, setValue] = useState(false);

  useEffect(() => {
    function checkQuery() {
      setValue(window.matchMedia(query).matches);
    }
    checkQuery();
    window.addEventListener("resize", checkQuery);
    const mediaQuery = window.matchMedia(query);
    mediaQuery.addEventListener("change", checkQuery);

    return () => {
      window.removeEventListener("resize", checkQuery);
      mediaQuery.removeEventListener("change", checkQuery);
    };
  }, [query]);

  return value;
}

// --- Icons ---

const Icons = {
  logo: ({ className }: { className?: string }) => (
    <svg width="42" height="24" viewBox="0 0 42 24" fill="none" className={cn("size-6 fill-indigo-600 dark:fill-indigo-400", className)}>
      <g clipPath="url(#clip0_322_9172)">
        <path d="M22.3546 0.96832C22.9097 0.390834 23.6636 0.0664062 24.4487 0.0664062C27.9806 0.0664062 31.3091 0.066408 34.587 0.0664146C41.1797 0.0664284 44.481 8.35854 39.8193 13.2082L29.6649 23.7718C29.1987 24.2568 28.4016 23.9133 28.4016 23.2274V13.9234L29.5751 12.7025C30.5075 11.7326 29.8472 10.0742 28.5286 10.0742H13.6016L22.3546 0.96832Z" fill="current" />
        <path d="M19.6469 23.0305C19.0919 23.608 18.338 23.9324 17.5529 23.9324C14.021 23.9324 10.6925 23.9324 7.41462 23.9324C0.821896 23.9324 -2.47942 15.6403 2.18232 10.7906L12.3367 0.227022C12.8029 -0.257945 13.6 0.0855283 13.6 0.771372L13.6 10.0754L12.4265 11.2963C11.4941 12.2662 12.1544 13.9246 13.473 13.9246L28.4001 13.9246L19.6469 23.0305Z" fill="current" />
      </g>
    </svg>
  ),
  soc2: ({ className }: { className?: string }) => (
    <div className={cn("flex flex-col items-center justify-center p-2 border border-slate-200 dark:border-zinc-800 rounded-lg bg-slate-50 dark:bg-zinc-900/50", className)}>
        <span className="text-[10px] font-bold text-slate-500 uppercase tracking-widest">SOC 2</span>
        <span className="text-[8px] font-medium text-slate-400">CERTIFIED</span>
    </div>
  ),
  hipaa: ({ className }: { className?: string }) => (
    <div className={cn("flex flex-col items-center justify-center p-2 border border-slate-200 dark:border-zinc-800 rounded-lg bg-slate-50 dark:bg-zinc-900/50", className)}>
        <span className="text-[10px] font-bold text-slate-500 uppercase tracking-widest">HIPAA</span>
        <span className="text-[8px] font-medium text-slate-400">COMPLIANT</span>
    </div>
  ),
  gdpr: ({ className }: { className?: string }) => (
    <div className={cn("flex flex-col items-center justify-center p-2 border border-slate-200 dark:border-zinc-800 rounded-lg bg-slate-50 dark:bg-zinc-900/50", className)}>
        <span className="text-[10px] font-bold text-slate-500 uppercase tracking-widest">GDPR</span>
        <span className="text-[8px] font-medium text-slate-400">READY</span>
    </div>
  ),
};

// --- Flickering Grid Sub-Component ---

interface FlickeringGridProps extends React.HTMLAttributes<HTMLDivElement> {
  squareSize?: number;
  gridGap?: number;
  flickerChance?: number;
  color?: string; 
  width?: number;
  height?: number;
  className?: string;
  maxOpacity?: number;
  text?: string;
  fontSize?: number;
  fontWeight?: number | string;
}

const FlickeringGrid: React.FC<FlickeringGridProps> = ({
  squareSize = 3,
  gridGap = 3,
  flickerChance = 0.2,
  color = "#B4B4B4",
  width,
  height,
  className,
  maxOpacity = 0.15,
  text = "",
  fontSize = 140,
  fontWeight = 600,
  ...props
}) => {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const containerRef = useRef<HTMLDivElement>(null);
  const [isInView, setIsInView] = useState(false);
  const [canvasSize, setCanvasSize] = useState({ width: 0, height: 0 });

  const memoizedColor = useMemo(() => getRGBA(color), [color]);

  const drawGrid = useCallback(
    (
      ctx: CanvasRenderingContext2D,
      w: number,
      h: number,
      cols: number,
      rows: number,
      squares: Float32Array,
      dpr: number,
    ) => {
      ctx.clearRect(0, 0, w, h);

      const maskCanvas = document.createElement("canvas");
      maskCanvas.width = w;
      maskCanvas.height = h;
      const maskCtx = maskCanvas.getContext("2d", { willReadFrequently: true });
      if (!maskCtx) return;

      if (text) {
        maskCtx.save();
        maskCtx.scale(dpr, dpr);
        maskCtx.fillStyle = "white";
        maskCtx.font = `${fontWeight} ${fontSize}px sans-serif`;
        maskCtx.textAlign = "center";
        maskCtx.textBaseline = "middle";
        maskCtx.fillText(text, w / (2 * dpr), h / (2 * dpr));
        maskCtx.restore();
      }

      for (let i = 0; i < cols; i++) {
        for (let j = 0; j < rows; j++) {
          const x = i * (squareSize + gridGap) * dpr;
          const y = j * (squareSize + gridGap) * dpr;
          const squareWidth = squareSize * dpr;
          const squareHeight = squareSize * dpr;

          const maskData = maskCtx.getImageData(x, y, squareWidth, squareHeight).data;
          const hasText = maskData.some((val, index) => index % 4 === 0 && val > 0);

          const opacity = squares[i * rows + j];
          const finalOpacity = hasText ? Math.min(1, opacity * 3 + 0.4) : opacity;

          ctx.fillStyle = colorWithOpacity(memoizedColor, finalOpacity);
          ctx.fillRect(x, y, squareWidth, squareHeight);
        }
      }
    },
    [memoizedColor, squareSize, gridGap, text, fontSize, fontWeight],
  );

  const setupCanvas = useCallback(
    (canvas: HTMLCanvasElement, w: number, h: number) => {
      const dpr = window.devicePixelRatio || 1;
      canvas.width = w * dpr;
      canvas.height = h * dpr;
      canvas.style.width = `${w}px`;
      canvas.style.height = `${h}px`;
      const cols = Math.ceil(w / (squareSize + gridGap));
      const rows = Math.ceil(h / (squareSize + gridGap));

      const squares = new Float32Array(cols * rows);
      for (let i = 0; i < squares.length; i++) {
        squares[i] = Math.random() * maxOpacity;
      }

      return { cols, rows, squares, dpr };
    },
    [squareSize, gridGap, maxOpacity],
  );

  const updateSquares = useCallback(
    (squares: Float32Array, deltaTime: number) => {
      for (let i = 0; i < squares.length; i++) {
        if (Math.random() < flickerChance * deltaTime) {
          squares[i] = Math.random() * maxOpacity;
        }
      }
    },
    [flickerChance, maxOpacity],
  );

  useEffect(() => {
    const canvas = canvasRef.current;
    const container = containerRef.current;
    if (!canvas || !container) return;

    const ctx = canvas.getContext("2d");
    if (!ctx) return;

    let animationFrameId: number;
    let gridParams: ReturnType<typeof setupCanvas>;

    const updateCanvasSize = () => {
      const newWidth = width || container.clientWidth;
      const newHeight = height || container.clientHeight;
      setCanvasSize({ width: newWidth, height: newHeight });
      gridParams = setupCanvas(canvas, newWidth, newHeight);
    };

    updateCanvasSize();

    let lastTime = 0;
    const animate = (time: number) => {
      if (!isInView) return;

      const deltaTime = (time - lastTime) / 1000;
      lastTime = time;

      updateSquares(gridParams.squares, deltaTime);
      drawGrid(
        ctx,
        canvas.width,
        canvas.height,
        gridParams.cols,
        gridParams.rows,
        gridParams.squares,
        gridParams.dpr,
      );
      animationFrameId = requestAnimationFrame(animate);
    };

    const resizeObserver = new ResizeObserver(() => updateCanvasSize());
    resizeObserver.observe(container);

    const intersectionObserver = new IntersectionObserver(([entry]) => setIsInView(entry.isIntersecting), { threshold: 0 });
    intersectionObserver.observe(canvas);

    if (isInView) {
      animationFrameId = requestAnimationFrame(animate);
    }

    return () => {
      cancelAnimationFrame(animationFrameId);
      resizeObserver.disconnect();
      intersectionObserver.disconnect();
    };
  }, [setupCanvas, updateSquares, drawGrid, width, height, isInView]);

  return (
    <div ref={containerRef} className={cn("h-full w-full", className)} {...props}>
      <canvas ref={canvasRef} className="pointer-events-none" style={{ width: canvasSize.width, height: canvasSize.height }} />
    </div>
  );
};

// --- Main Footer Component ---

export interface FooterLink {
  id: number;
  title: string;
  url: string;
}

export interface FooterColumn {
  title: string;
  links: FooterLink[];
}

export interface FlickeringGridFooterProps {
  brandName?: string;
  logo?: React.ReactNode;
  description?: string;
  columns?: FooterColumn[];
  flickerTextDesktop?: string;
  flickerTextMobile?: string;
  className?: string;
}

const DEFAULT_COLUMNS: FooterColumn[] = [
  {
    title: "Company",
    links: [
      { id: 1, title: "About", url: "#" },
      { id: 2, title: "Contact", url: "#" },
      { id: 3, title: "Blog", url: "#" },
      { id: 4, title: "Story", url: "#" },
    ],
  },
  {
    title: "Products",
    links: [
      { id: 5, title: "Enterprise", url: "#" },
      { id: 6, title: "Platform", url: "#" },
      { id: 7, title: "Security", url: "#" },
      { id: 8, title: "Pricing", url: "#" },
    ],
  },
  {
    title: "Resources",
    links: [
      { id: 9, title: "Documentation", url: "#" },
      { id: 10, title: "Careers", url: "#" },
      { id: 11, title: "Newsletters", url: "#" },
      { id: 12, title: "Help Center", url: "#" },
    ],
  },
];

export function FlickeringGridFooter({
  brandName = "NOVA UI",
  logo = <Icons.logo />,
  description = "An intelligent assistant designed to streamline your digital workflows and handle mundane tasks, so you can focus on what truly matters.",
  columns = DEFAULT_COLUMNS,
  flickerTextDesktop = "Streamline your workflow",
  flickerTextMobile = "NOVA UI",
  className,
}: FlickeringGridFooterProps) {
  const isTablet = useMediaQuery("(max-width: 1024px)");

  return (
    <footer className={cn("w-full pb-0 bg-white dark:bg-zinc-950", className)}>
      <div className="flex flex-col md:flex-row md:items-center md:justify-between p-10 max-w-7xl mx-auto">
        
        {/* Left Side: Brand & Badges */}
        <div className="flex flex-col items-start justify-start gap-y-6 max-w-sm mx-0">
          <a href="/" className="flex items-center gap-3">
            {logo}
            <p className="text-xl font-bold text-slate-900 dark:text-white">{brandName}</p>
          </a>
          <p className="tracking-tight text-slate-500 dark:text-slate-400 font-medium leading-relaxed">
            {description}
          </p>
          <div className="flex items-center gap-3 mt-2">
            <Icons.soc2 className="w-16 h-12" />
            <Icons.hipaa className="w-16 h-12" />
            <Icons.gdpr className="w-16 h-12" />
          </div>
        </div>

        {/* Right Side: Link Columns */}
        <div className="pt-10 md:pt-0 md:w-1/2">
          <div className="flex flex-col items-start justify-start md:flex-row md:items-start md:justify-between gap-y-10 lg:pl-10">
            {columns.map((column, columnIndex) => (
              <ul key={columnIndex} className="flex flex-col gap-y-3">
                <li className="mb-2 text-sm font-bold uppercase tracking-wider text-slate-900 dark:text-white">
                  {column.title}
                </li>
                {column.links.map((link) => (
                  <li
                    key={link.id}
                    className="group inline-flex cursor-pointer items-center justify-start gap-1 text-sm font-medium text-slate-500 dark:text-slate-400 hover:text-indigo-600 dark:hover:text-indigo-400 transition-colors"
                  >
                    <a href={link.url}>{link.title}</a>
                    <div className="flex size-4 items-center justify-center border border-slate-200 dark:border-zinc-700 rounded translate-x-0 transform opacity-0 transition-all duration-300 ease-out group-hover:translate-x-1 group-hover:opacity-100">
                      <ChevronRightIcon className="h-3 w-3" />
                    </div>
                  </li>
                ))}
              </ul>
            ))}
          </div>
        </div>
      </div>

      {/* Bottom Flickering Grid Area */}
      <div className="w-full h-48 md:h-64 relative mt-16 z-0 overflow-hidden border-t border-slate-200 dark:border-zinc-800">
        <div className="absolute inset-0 bg-gradient-to-t from-white to-transparent dark:from-zinc-950 z-10 from-20%" />
        <div className="absolute inset-0 mx-6">
          <FlickeringGrid
            text={isTablet ? flickerTextMobile : flickerTextDesktop}
            fontSize={isTablet ? 60 : 100}
            className="h-full w-full opacity-60 dark:opacity-100"
            squareSize={3}
            gridGap={isTablet ? 2 : 3}
            color="#6366f1" // Indigo-500 base color for the flicker
            maxOpacity={0.4}
            flickerChance={0.2}
          />
        </div>
      </div>
    </footer>
  );
}

--- FILE: frontend-web/registry/footers/FloatingLogoFooter.tsx ---

import React from "react";
import {
  NotepadTextDashed,
  Twitter,
  Linkedin,
  Github,
  Mail,
} from "lucide-react";
import { cn } from "../core/utils";

export interface FooterLink {
  label: string;
  href: string;
}

export interface SocialLink {
  icon: React.ReactNode;
  href: string;
  label: string;
}

export interface FloatingLogoFooterProps {
  brandName?: string;
  brandDescription?: string;
  socialLinks?: SocialLink[];
  navLinks?: FooterLink[];
  creatorName?: string;
  creatorUrl?: string;
  brandIcon?: React.ReactNode;
  className?: string;
}

const DEFAULT_NAV_LINKS: FooterLink[] = [
  { label: "Components", href: "#" },
  { label: "Pricing", href: "#" },
  { label: "Documentation", href: "#" },
  { label: "Showcase", href: "#" },
  { label: "Blog", href: "#" },
  { label: "Contact", href: "#" },
];

const DEFAULT_SOCIAL_LINKS: SocialLink[] = [
  { icon: <Twitter className="w-full h-full" />, href: "#", label: "Twitter" },
  { icon: <Github className="w-full h-full" />, href: "#", label: "GitHub" },
  { icon: <Linkedin className="w-full h-full" />, href: "#", label: "LinkedIn" },
  { icon: <Mail className="w-full h-full" />, href: "#", label: "Email" },
];

export function FloatingLogoFooter({
  brandName = "NOVA UI",
  brandDescription = "Empowering developers to build stunning user interfaces faster with highly polished, production-ready components.",
  socialLinks = DEFAULT_SOCIAL_LINKS,
  navLinks = DEFAULT_NAV_LINKS,
  creatorName = "NOVA Team",
  creatorUrl = "#",
  brandIcon,
  className,
}: FloatingLogoFooterProps) {
  return (
    <section className={cn("relative w-full mt-0 overflow-hidden", className)}>
      <footer className="border-t border-slate-200 dark:border-zinc-800 bg-white dark:bg-zinc-950 mt-20 relative">
        <div className="max-w-7xl flex flex-col justify-between mx-auto min-h-[30rem] sm:min-h-[35rem] md:min-h-[40rem] relative p-4 py-10">
          <div className="flex flex-col mb-12 sm:mb-20 md:mb-0 w-full z-20">
            <div className="w-full flex flex-col items-center">
              <div className="space-y-4 flex flex-col items-center flex-1">
                <div className="flex items-center gap-2">
                  <span className="text-slate-900 dark:text-white text-3xl font-bold tracking-tight">
                    {brandName}
                  </span>
                </div>
                <p className="text-slate-500 dark:text-slate-400 font-medium text-center w-full max-w-sm sm:w-96 px-4 sm:px-0">
                  {brandDescription}
                </p>
              </div>

              {socialLinks.length > 0 && (
                <div className="flex mb-8 mt-6 gap-5">
                  {socialLinks.map((link, index) => (
                    <a
                      key={index}
                      href={link.href}
                      className="text-slate-400 hover:text-slate-900 dark:text-slate-500 dark:hover:text-white transition-colors"
                      target="_blank"
                      rel="noopener noreferrer"
                    >
                      <div className="w-6 h-6 hover:scale-110 duration-300">
                        {link.icon}
                      </div>
                      <span className="sr-only">{link.label}</span>
                    </a>
                  ))}
                </div>
              )}

              {navLinks.length > 0 && (
                <div className="flex flex-wrap justify-center gap-6 text-sm font-medium text-slate-500 dark:text-slate-400 max-w-full px-4">
                  {navLinks.map((link, index) => (
                    <a
                      key={index}
                      className="hover:text-slate-900 dark:hover:text-white transition-colors duration-300"
                      href={link.href}
                    >
                      {link.label}
                    </a>
                  ))}
                </div>
              )}
            </div>
          </div>

          <div className="mt-20 md:mt-24 flex flex-col gap-2 md:gap-1 items-center justify-center md:flex-row md:items-center md:justify-between px-4 md:px-0 z-20">
            <p className="text-sm font-medium text-slate-500 dark:text-slate-400 text-center md:text-left">
              © {new Date().getFullYear()} {brandName}. All rights reserved.
            </p>
            {creatorName && creatorUrl && (
              <nav className="flex gap-4">
                <a
                  href={creatorUrl}
                  target="_blank"
                  rel="noopener noreferrer"
                  className="text-sm font-medium text-slate-500 dark:text-slate-400 hover:text-slate-900 dark:hover:text-white transition-colors duration-300"
                >
                  Crafted by {creatorName}
                </a>
              </nav>
            )}
          </div>
        </div>

        {/* Large background text */}
        <div 
          className="bg-gradient-to-b from-slate-900/10 via-slate-900/5 dark:from-white/10 dark:via-white/5 to-transparent bg-clip-text text-transparent leading-none absolute left-1/2 -translate-x-1/2 bottom-40 md:bottom-32 font-extrabold tracking-tighter pointer-events-none select-none text-center px-4"
          style={{
            fontSize: 'clamp(3rem, 12vw, 10rem)',
            maxWidth: '95vw'
          }}
        >
          {brandName.toUpperCase()}
        </div>

        {/* Bottom floating logo */}
        <div className="absolute hover:border-slate-400 dark:hover:border-slate-600 duration-400 drop-shadow-[0_0px_20px_rgba(0,0,0,0.1)] dark:drop-shadow-[0_0px_20px_rgba(255,255,255,0.15)] bottom-24 md:bottom-20 backdrop-blur-sm rounded-3xl bg-white/60 dark:bg-zinc-950/60 left-1/2 border-2 border-slate-200 dark:border-zinc-800 flex items-center justify-center p-3 -translate-x-1/2 z-20">
          <div className="w-12 sm:w-16 md:w-24 h-12 sm:h-16 md:h-24 bg-gradient-to-br from-slate-900 to-slate-800 dark:from-white dark:to-slate-200 rounded-2xl flex items-center justify-center shadow-lg">
            {brandIcon || (
              <NotepadTextDashed className="w-8 sm:w-10 md:w-14 h-8 sm:h-10 md:h-14 text-white dark:text-slate-900 drop-shadow-lg" />
            )}
          </div>
        </div>

        {/* Bottom line */}
        <div className="absolute bottom-32 sm:bottom-34 backdrop-blur-sm h-[1px] bg-gradient-to-r from-transparent via-slate-200 dark:via-zinc-800 to-transparent w-full left-1/2 -translate-x-1/2 z-10"></div>

        {/* Bottom shadow blend */}
        <div className="bg-gradient-to-t from-white via-white/80 to-white/40 dark:from-zinc-950 dark:via-zinc-950/80 dark:to-zinc-950/40 absolute bottom-28 w-full h-24 pointer-events-none z-10"></div>
      </footer>
    </section>
  );
}

--- FILE: frontend-web/registry/footers/Footer1.tsx ---

import React from 'react';
import { cn } from '../core/utils';
import { Twitter, Linkedin, Facebook, Instagram } from 'lucide-react';

export interface FooterLink {
  title: string;
  href: string;
}

export interface SocialLink {
  icon: React.ElementType | React.FC<React.SVGProps<SVGSVGElement>>;
  href: string;
  label: string;
}

export interface Footer1Props {
  links?: FooterLink[];
  socialLinks?: SocialLink[];
  copyright?: string;
  className?: string;
}

const ThreadsIcon = (props: React.SVGProps<SVGSVGElement>) => (
  <svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" {...props}>
    <path
      fill="none"
      stroke="currentColor"
      strokeLinecap="round"
      strokeLinejoin="round"
      strokeWidth="1.5"
      d="M19.25 8.505c-1.577-5.867-7-5.5-7-5.5s-7.5-.5-7.5 8.995s7.5 8.996 7.5 8.996s4.458.296 6.5-3.918c.667-1.858.5-5.573-6-5.573c0 0-3 0-3 2.5c0 .976 1 2 2.5 2s3.171-1.027 3.5-3c1-6-4.5-6.5-6-4"
      color="currentColor"
    ></path>
  </svg>
);

const TikTokIcon = (props: React.SVGProps<SVGSVGElement>) => (
  <svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" {...props}>
    <path
      fill="currentColor"
      d="M16.6 5.82s.51.5 0 0A4.28 4.28 0 0 1 15.54 3h-3.09v12.4a2.59 2.59 0 0 1-2.59 2.5c-1.42 0-2.6-1.16-2.6-2.6c0-1.72 1.66-3.01 3.37-2.48V9.66c-3.45-.46-6.47 2.22-6.47 5.64c0 3.33 2.76 5.7 5.69 5.7c3.14 0 5.69-2.55 5.69-5.7V9.01a7.35 7.35 0 0 0 4.3 1.38V7.3s-1.88.09-3.24-1.48"
    ></path>
  </svg>
);

const DEFAULT_LINKS: FooterLink[] = [
  { title: 'Features', href: '#' },
  { title: 'Solution', href: '#' },
  { title: 'Customers', href: '#' },
  { title: 'Pricing', href: '#' },
  { title: 'Help', href: '#' },
  { title: 'About', href: '#' },
];

const DEFAULT_SOCIALS: SocialLink[] = [
  { icon: Twitter, label: 'X/Twitter', href: '#' },
  { icon: Linkedin, label: 'LinkedIn', href: '#' },
  { icon: Facebook, label: 'Facebook', href: '#' },
  { icon: ThreadsIcon, label: 'Threads', href: '#' },
  { icon: Instagram, label: 'Instagram', href: '#' },
  { icon: TikTokIcon, label: 'TikTok', href: '#' },
];

export function Footer1({
  links = DEFAULT_LINKS,
  socialLinks = DEFAULT_SOCIALS,
  copyright = `© ${new Date().getFullYear()} NOVA UI, All rights reserved`,
  className,
}: Footer1Props) {
  return (
    <footer className={cn("bg-slate-100 dark:bg-zinc-900 py-16", className)}>
      <div className="mx-auto max-w-5xl px-6">
        <a href="/" aria-label="go home" className="mx-auto block size-fit" />

        <div className="my-8 flex flex-wrap justify-center gap-6">
          {links.map((link, index) => (
            <a
              key={index}
              href={link.href}
              className="text-slate-500 hover:text-slate-900 dark:text-slate-400 dark:hover:text-white block transition-colors duration-150"
            >
              <span>{link.title}</span>
            </a>
          ))}
        </div>

        <div className="my-8 flex flex-wrap justify-center gap-6 text-sm">
          {socialLinks.map((social, index) => {
            const Icon = social.icon;
            return (
              <a
                key={index}
                href={social.href}
                target="_blank"
                rel="noopener noreferrer"
                aria-label={social.label}
                className="text-slate-500 hover:text-slate-900 dark:text-slate-400 dark:hover:text-white block transition-colors duration-150"
              >
                <Icon className="size-6" />
              </a>
            );
          })}
        </div>

        <span className="text-slate-500 dark:text-slate-400 block text-center text-sm">
          {copyright}
        </span>
      </div>
    </footer>
  );
}

--- FILE: frontend-web/registry/footers/Footer2.tsx ---

import React from "react";
import { cn } from "../core/utils";

export interface FooterMenuItem {
  title: string;
  links: {
    text: string;
    url: string;
  }[];
}

export interface Footer2Props {
  logo?: {
    url: string;
    src: string;
    alt: string;
    title: string;
  };
  tagline?: string;
  menuItems?: FooterMenuItem[];
  copyright?: string;
  bottomLinks?: {
    text: string;
    url: string;
  }[];
  className?: string;
}

const DEFAULT_MENU_ITEMS: FooterMenuItem[] = [
  {
    title: "Product",
    links: [
      { text: "Overview", url: "#" },
      { text: "Pricing", url: "#" },
      { text: "Marketplace", url: "#" },
      { text: "Features", url: "#" },
      { text: "Integrations", url: "#" },
    ],
  },
  {
    title: "Company",
    links: [
      { text: "About", url: "#" },
      { text: "Team", url: "#" },
      { text: "Blog", url: "#" },
      { text: "Careers", url: "#" },
      { text: "Contact", url: "#" },
      { text: "Privacy", url: "#" },
    ],
  },
  {
    title: "Resources",
    links: [
      { text: "Help", url: "#" },
      { text: "Sales", url: "#" },
      { text: "Advertise", url: "#" },
    ],
  },
  {
    title: "Social",
    links: [
      { text: "Twitter", url: "#" },
      { text: "Instagram", url: "#" },
      { text: "LinkedIn", url: "#" },
    ],
  },
];

export function Footer2({
  logo = {
    src: "https://www.shadcnblocks.com/images/block/block-1.svg",
    alt: "Brand Logo",
    title: "NOVA UI",
    url: "#",
  },
  tagline = "Components made easy.",
  menuItems = DEFAULT_MENU_ITEMS,
  copyright = "© 2024 Copyright. All rights reserved.",
  bottomLinks = [
    { text: "Terms and Conditions", url: "#" },
    { text: "Privacy Policy", url: "#" },
  ],
  className,
}: Footer2Props) {
  return (
    <section className={cn("py-16 md:py-24 lg:py-32 bg-white dark:bg-zinc-950 text-slate-900 dark:text-white", className)}>
      <div className="container mx-auto px-4 md:px-6">
        <footer>
          <div className="grid grid-cols-2 gap-8 lg:grid-cols-6">
            <div className="col-span-2 mb-8 lg:mb-0">
              <div className="flex items-center gap-2 lg:justify-start">
                <a href={logo.url}>
                  <img
                    src={logo.src}
                    alt={logo.alt}
                    title={logo.title}
                    className="h-10 dark:invert"
                  />
                </a>
                <p className="text-xl font-semibold">{logo.title}</p>
              </div>
              <p className="mt-4 font-bold">{tagline}</p>
            </div>
            {menuItems.map((section, sectionIdx) => (
              <div key={sectionIdx}>
                <h3 className="mb-4 font-bold">{section.title}</h3>
                <ul className="space-y-4 text-slate-500 dark:text-slate-400">
                  {section.links.map((link, linkIdx) => (
                    <li
                      key={linkIdx}
                      className="font-medium hover:text-slate-900 dark:hover:text-white transition-colors"
                    >
                      <a href={link.url}>{link.text}</a>
                    </li>
                  ))}
                </ul>
              </div>
            ))}
          </div>
          <div className="mt-24 flex flex-col justify-between gap-4 border-t border-slate-200 dark:border-zinc-800 pt-8 text-sm font-medium text-slate-500 dark:text-slate-400 md:flex-row md:items-center">
            <p>{copyright}</p>
            <ul className="flex gap-4">
              {bottomLinks.map((link, linkIdx) => (
                <li key={linkIdx} className="underline hover:text-slate-900 dark:hover:text-white transition-colors">
                  <a href={link.url}>{link.text}</a>
                </li>
              ))}
            </ul>
          </div>
        </footer>
      </div>
    </section>
  );
}

--- FILE: frontend-web/registry/footers/Footer4Col.tsx ---

import React from 'react';
import {
  Dribbble,
  Facebook,
  Github,
  Instagram,
  Mail,
  MapPin,
  Phone,
  Twitter,
  Hexagon
} from 'lucide-react';
import { cn } from "../core/utils";

export interface FooterSocialLink {
  icon: React.ElementType;
  label: string;
  href: string;
}

export interface FooterTextLink {
  text: string;
  href: string;
  hasIndicator?: boolean;
}

export interface FooterContactItem {
  icon: React.ElementType;
  text: string;
  isAddress?: boolean;
}

export interface Footer4ColProps {
  company?: {
    name: string;
    description: string;
    logo?: React.ReactNode;
  };
  socialLinks?: FooterSocialLink[];
  aboutLinks?: FooterTextLink[];
  serviceLinks?: FooterTextLink[];
  helpfulLinks?: FooterTextLink[];
  contactInfo?: FooterContactItem[];
  className?: string;
}

const DEFAULT_COMPANY = {
  name: 'NOVA UI',
  description:
    'Building beautiful and functional web experiences with modern technologies. We help startups and businesses create their digital presence.',
  logo: <Hexagon className="w-8 h-8 text-indigo-600 dark:text-indigo-400" />
};

const DEFAULT_SOCIALS = [
  { icon: Facebook, label: 'Facebook', href: '#' },
  { icon: Instagram, label: 'Instagram', href: '#' },
  { icon: Twitter, label: 'Twitter', href: '#' },
  { icon: Github, label: 'GitHub', href: '#' },
  { icon: Dribbble, label: 'Dribbble', href: '#' },
];

const DEFAULT_ABOUT = [
  { text: 'Company History', href: '#' },
  { text: 'Meet the Team', href: '#' },
  { text: 'Employee Handbook', href: '#' },
  { text: 'Careers', href: '#' },
];

const DEFAULT_SERVICES = [
  { text: 'Web Development', href: '#' },
  { text: 'Web Design', href: '#' },
  { text: 'Marketing', href: '#' },
  { text: 'Google Ads', href: '#' },
];

const DEFAULT_HELP = [
  { text: 'FAQs', href: '#' },
  { text: 'Support', href: '#' },
  { text: 'Live Chat', href: '#', hasIndicator: true },
];

const DEFAULT_CONTACT = [
  { icon: Mail, text: 'hello@novaui.com' },
  { icon: Phone, text: '+1 (555) 123-4567' },
  { icon: MapPin, text: 'New York City, NY', isAddress: true },
];

export function Footer4Col({
  company = DEFAULT_COMPANY,
  socialLinks = DEFAULT_SOCIALS,
  aboutLinks = DEFAULT_ABOUT,
  serviceLinks = DEFAULT_SERVICES,
  helpfulLinks = DEFAULT_HELP,
  contactInfo = DEFAULT_CONTACT,
  className
}: Footer4ColProps) {
  return (
    <footer className={cn("bg-slate-50 dark:bg-zinc-900/50 mt-16 w-full place-self-end rounded-t-3xl border-t border-slate-200 dark:border-zinc-800 text-slate-900 dark:text-white", className)}>
      <div className="mx-auto max-w-screen-xl px-4 pt-16 pb-6 sm:px-6 lg:px-8 lg:pt-24">
        <div className="grid grid-cols-1 gap-8 lg:grid-cols-3">
          <div>
            <div className="text-slate-900 dark:text-white flex justify-center items-center gap-2 sm:justify-start">
              {company.logo}
              <span className="text-2xl font-semibold">
                {company.name}
              </span>
            </div>

            <p className="text-slate-500 dark:text-slate-400 mt-6 max-w-md text-center leading-relaxed sm:max-w-xs sm:text-left">
              {company.description}
            </p>

            <ul className="mt-8 flex justify-center gap-6 sm:justify-start md:gap-8">
              {socialLinks.map(({ icon: Icon, label, href }) => (
                <li key={label}>
                  <a
                    href={href}
                    className="text-slate-400 hover:text-indigo-600 dark:hover:text-indigo-400 transition-colors"
                  >
                    <span className="sr-only">{label}</span>
                    <Icon className="size-6" />
                  </a>
                </li>
              ))}
            </ul>
          </div>

          <div className="grid grid-cols-1 gap-8 sm:grid-cols-2 md:grid-cols-4 lg:col-span-2">
            <div className="text-center sm:text-left">
              <p className="text-lg font-medium text-slate-900 dark:text-white">About Us</p>
              <ul className="mt-8 space-y-4 text-sm">
                {aboutLinks.map(({ text, href }) => (
                  <li key={text}>
                    <a
                      className="text-slate-500 dark:text-slate-400 hover:text-slate-900 dark:hover:text-white transition-colors"
                      href={href}
                    >
                      {text}
                    </a>
                  </li>
                ))}
              </ul>
            </div>

            <div className="text-center sm:text-left">
              <p className="text-lg font-medium text-slate-900 dark:text-white">Our Services</p>
              <ul className="mt-8 space-y-4 text-sm">
                {serviceLinks.map(({ text, href }) => (
                  <li key={text}>
                    <a
                      className="text-slate-500 dark:text-slate-400 hover:text-slate-900 dark:hover:text-white transition-colors"
                      href={href}
                    >
                      {text}
                    </a>
                  </li>
                ))}
              </ul>
            </div>

            <div className="text-center sm:text-left">
              <p className="text-lg font-medium text-slate-900 dark:text-white">Helpful Links</p>
              <ul className="mt-8 space-y-4 text-sm">
                {helpfulLinks.map(({ text, href, hasIndicator }) => (
                  <li key={text}>
                    <a
                      href={href}
                      className={cn(
                        hasIndicator
                          ? 'group flex justify-center gap-1.5 sm:justify-start items-center'
                          : 'text-slate-500 dark:text-slate-400 hover:text-slate-900 dark:hover:text-white transition-colors'
                      )}
                    >
                      <span className="text-slate-500 dark:text-slate-400 group-hover:text-slate-900 dark:group-hover:text-white transition-colors">
                        {text}
                      </span>
                      {hasIndicator && (
                        <span className="relative flex size-2">
                          <span className="bg-indigo-600 dark:bg-indigo-400 absolute inline-flex h-full w-full animate-ping rounded-full opacity-75" />
                          <span className="bg-indigo-600 dark:bg-indigo-400 relative inline-flex size-2 rounded-full" />
                        </span>
                      )}
                    </a>
                  </li>
                ))}
              </ul>
            </div>

            <div className="text-center sm:text-left">
              <p className="text-lg font-medium text-slate-900 dark:text-white">Contact Us</p>
              <ul className="mt-8 space-y-4 text-sm">
                {contactInfo.map(({ icon: Icon, text, isAddress }, idx) => (
                  <li key={idx}>
                    <a
                      className="flex items-start justify-center gap-2 sm:justify-start group"
                      href="#"
                    >
                      <Icon className="text-indigo-600 dark:text-indigo-400 size-5 shrink-0" />
                      {isAddress ? (
                        <address className="text-slate-500 dark:text-slate-400 group-hover:text-slate-900 dark:group-hover:text-white flex-1 not-italic transition-colors text-left">
                          {text}
                        </address>
                      ) : (
                        <span className="text-slate-500 dark:text-slate-400 group-hover:text-slate-900 dark:group-hover:text-white flex-1 transition-colors text-left">
                          {text}
                        </span>
                      )}
                    </a>
                  </li>
                ))}
              </ul>
            </div>
          </div>
        </div>

        <div className="mt-12 border-t border-slate-200 dark:border-zinc-800 pt-6">
          <div className="text-center sm:flex sm:justify-between sm:text-left text-slate-500 dark:text-slate-400">
            <p className="text-sm">
              <span className="block sm:inline">All rights reserved.</span>
            </p>

            <p className="mt-4 text-sm transition-colors sm:order-first sm:mt-0">
              &copy; {new Date().getFullYear()} {company.name}
            </p>
          </div>
        </div>
      </div>
    </footer>
  );
}

--- FILE: frontend-web/registry/footers/Footer7.tsx ---

import React from "react";
import { Facebook, Instagram, Linkedin, Twitter, Hexagon } from "lucide-react";
import { cn } from "../core/utils";

export interface Footer7Props {
  logo?: {
    url: string;
    icon: React.ReactNode;
    title: string;
  };
  sections?: Array<{
    title: string;
    links: Array<{ name: string; href: string }>;
  }>;
  description?: string;
  socialLinks?: Array<{
    icon: React.ReactElement;
    href: string;
    label: string;
  }>;
  copyright?: string;
  legalLinks?: Array<{
    name: string;
    href: string;
  }>;
  className?: string;
}

const defaultSections = [
  {
    title: "Product",
    links: [
      { name: "Overview", href: "#" },
      { name: "Pricing", href: "#" },
      { name: "Marketplace", href: "#" },
      { name: "Features", href: "#" },
    ],
  },
  {
    title: "Company",
    links: [
      { name: "About", href: "#" },
      { name: "Team", href: "#" },
      { name: "Blog", href: "#" },
      { name: "Careers", href: "#" },
    ],
  },
  {
    title: "Resources",
    links: [
      { name: "Help", href: "#" },
      { name: "Sales", href: "#" },
      { name: "Advertise", href: "#" },
      { name: "Privacy", href: "#" },
    ],
  },
];

const defaultSocialLinks = [
  { icon: <Instagram className="w-5 h-5" />, href: "#", label: "Instagram" },
  { icon: <Facebook className="w-5 h-5" />, href: "#", label: "Facebook" },
  { icon: <Twitter className="w-5 h-5" />, href: "#", label: "Twitter" },
  { icon: <Linkedin className="w-5 h-5" />, href: "#", label: "LinkedIn" },
];

const defaultLegalLinks = [
  { name: "Terms and Conditions", href: "#" },
  { name: "Privacy Policy", href: "#" },
];

export const Footer7 = ({
  logo = {
    url: "#",
    icon: <Hexagon className="h-8 w-8 text-slate-900 dark:text-white" />,
    title: "NOVA UI",
  },
  sections = defaultSections,
  description = "A collection of premium components for your startup business or next big side project.",
  socialLinks = defaultSocialLinks,
  copyright = "© 2025 NOVA UI. All rights reserved.",
  legalLinks = defaultLegalLinks,
  className,
}: Footer7Props) => {
  return (
    <section className={cn("py-16 md:py-24 lg:py-32 bg-white dark:bg-zinc-950", className)}>
      <div className="container mx-auto px-4 md:px-6">
        <div className="flex w-full flex-col justify-between gap-10 lg:flex-row lg:items-start lg:text-left">
          <div className="flex w-full max-w-sm flex-col justify-between gap-6 lg:items-start">
            {/* Logo */}
            <div className="flex items-center gap-2 lg:justify-start">
              <a href={logo.url} className="flex items-center gap-2">
                {logo.icon}
                <h2 className="text-xl font-semibold text-slate-900 dark:text-white">{logo.title}</h2>
              </a>
            </div>
            <p className="text-sm text-slate-500 dark:text-slate-400 leading-relaxed">
              {description}
            </p>
            <ul className="flex items-center space-x-6 text-slate-500 dark:text-slate-400">
              {socialLinks.map((social, idx) => (
                <li key={idx} className="font-medium hover:text-slate-900 dark:hover:text-white transition-colors">
                  <a href={social.href} aria-label={social.label}>
                    {social.icon}
                  </a>
                </li>
              ))}
            </ul>
          </div>
          <div className="grid w-full gap-6 md:grid-cols-3 lg:gap-20">
            {sections.map((section, sectionIdx) => (
              <div key={sectionIdx}>
                <h3 className="mb-4 font-bold text-slate-900 dark:text-white">{section.title}</h3>
                <ul className="space-y-3 text-sm text-slate-500 dark:text-slate-400">
                  {section.links.map((link, linkIdx) => (
                    <li
                      key={linkIdx}
                      className="font-medium hover:text-slate-900 dark:hover:text-white transition-colors"
                    >
                      <a href={link.href}>{link.name}</a>
                    </li>
                  ))}
                </ul>
              </div>
            ))}
          </div>
        </div>
        <div className="mt-16 flex flex-col justify-between gap-4 border-t border-slate-200 dark:border-zinc-800 py-8 text-xs font-medium text-slate-500 dark:text-slate-400 md:flex-row md:items-center md:text-left">
          <p className="order-2 lg:order-1">{copyright}</p>
          <ul className="order-1 flex flex-col gap-2 md:order-2 md:flex-row md:gap-6">
            {legalLinks.map((link, idx) => (
              <li key={idx} className="hover:text-slate-900 dark:hover:text-white transition-colors">
                <a href={link.href}>{link.name}</a>
              </li>
            ))}
          </ul>
        </div>
      </div>
    </section>
  );
};

--- FILE: frontend-web/registry/footers/FooterNewsletter.tsx ---

import React, { useState, useEffect } from "react";
import { Facebook, Instagram, Linkedin, Moon, Send, Sun, Twitter } from "lucide-react";
import { cn } from "../core/utils";

export interface FooterNewsletterProps {
  brandName?: string;
  newsletterTitle?: string;
  newsletterDescription?: string;
  contactInfo?: {
    address1: string;
    address2: string;
    phone: string;
    email: string;
  };
  className?: string;
}

export function FooterNewsletter({
  brandName = "Your Company",
  newsletterTitle = "Stay Connected",
  newsletterDescription = "Join our newsletter for the latest updates and exclusive offers.",
  contactInfo = {
    address1: "123 Innovation Street",
    address2: "Tech City, TC 12345",
    phone: "(123) 456-7890",
    email: "hello@example.com",
  },
  className,
}: FooterNewsletterProps) {
  const [isDarkMode, setIsDarkMode] = useState(false);

  // Initialize theme based on document class
  useEffect(() => {
    if (typeof window !== "undefined") {
      setIsDarkMode(document.documentElement.classList.contains("dark"));
    }
  }, []);

  const toggleTheme = () => {
    const htmlEl = document.documentElement;
    if (htmlEl.classList.contains("dark")) {
      htmlEl.classList.remove("dark");
      setIsDarkMode(false);
    } else {
      htmlEl.classList.add("dark");
      setIsDarkMode(true);
    }
  };

  return (
    <footer className={cn("relative border-t border-slate-200 dark:border-zinc-800 bg-white dark:bg-zinc-950 text-slate-900 dark:text-zinc-50 transition-colors duration-300", className)}>
      <div className="container mx-auto px-4 py-12 md:px-6 lg:px-8">
        <div className="grid gap-12 md:grid-cols-2 lg:grid-cols-4">
          <div className="relative">
            <h2 className="mb-4 text-3xl font-bold tracking-tight">{newsletterTitle}</h2>
            <p className="mb-6 text-slate-500 dark:text-zinc-400">
              {newsletterDescription}
            </p>
            <form className="relative" onSubmit={(e) => e.preventDefault()}>
              <input
                type="email"
                placeholder="Enter your email"
                className="flex h-10 w-full rounded-md border border-slate-200 dark:border-zinc-800 bg-transparent px-3 py-2 text-sm placeholder:text-slate-500 dark:placeholder:text-zinc-400 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-slate-400 dark:focus-visible:ring-zinc-600 pr-12 backdrop-blur-sm"
              />
              <button
                type="submit"
                className="absolute right-1 top-1 h-8 w-8 inline-flex items-center justify-center rounded-full bg-slate-900 text-white dark:bg-white dark:text-slate-900 transition-transform hover:scale-105 focus-visible:outline-none"
                title="Subscribe"
              >
                <Send className="h-4 w-4 ml-[-2px]" />
                <span className="sr-only">Subscribe</span>
              </button>
            </form>
            <div className="absolute -right-4 top-0 h-24 w-24 rounded-full bg-blue-500/10 dark:bg-blue-500/20 blur-2xl pointer-events-none" />
          </div>
          <div>
            <h3 className="mb-4 text-lg font-semibold">Quick Links</h3>
            <nav className="space-y-2 text-sm">
              <a href="#" className="block transition-colors text-slate-500 hover:text-slate-900 dark:text-zinc-400 dark:hover:text-white">
                Home
              </a>
              <a href="#" className="block transition-colors text-slate-500 hover:text-slate-900 dark:text-zinc-400 dark:hover:text-white">
                About Us
              </a>
              <a href="#" className="block transition-colors text-slate-500 hover:text-slate-900 dark:text-zinc-400 dark:hover:text-white">
                Services
              </a>
              <a href="#" className="block transition-colors text-slate-500 hover:text-slate-900 dark:text-zinc-400 dark:hover:text-white">
                Products
              </a>
              <a href="#" className="block transition-colors text-slate-500 hover:text-slate-900 dark:text-zinc-400 dark:hover:text-white">
                Contact
              </a>
            </nav>
          </div>
          <div>
            <h3 className="mb-4 text-lg font-semibold">Contact Us</h3>
            <address className="space-y-2 text-sm not-italic text-slate-500 dark:text-zinc-400">
              <p>{contactInfo.address1}</p>
              <p>{contactInfo.address2}</p>
              <p>Phone: {contactInfo.phone}</p>
              <p>Email: {contactInfo.email}</p>
            </address>
          </div>
          <div className="relative">
            <h3 className="mb-4 text-lg font-semibold">Follow Us</h3>
            <div className="mb-6 flex space-x-4">
              <a href="#" title="Follow us on Facebook" className="inline-flex h-10 w-10 items-center justify-center rounded-full border border-slate-200 dark:border-zinc-800 hover:bg-slate-100 dark:hover:bg-zinc-800 transition-colors">
                <Facebook className="h-4 w-4" />
                <span className="sr-only">Facebook</span>
              </a>
              <a href="#" title="Follow us on Twitter" className="inline-flex h-10 w-10 items-center justify-center rounded-full border border-slate-200 dark:border-zinc-800 hover:bg-slate-100 dark:hover:bg-zinc-800 transition-colors">
                <Twitter className="h-4 w-4" />
                <span className="sr-only">Twitter</span>
              </a>
              <a href="#" title="Follow us on Instagram" className="inline-flex h-10 w-10 items-center justify-center rounded-full border border-slate-200 dark:border-zinc-800 hover:bg-slate-100 dark:hover:bg-zinc-800 transition-colors">
                <Instagram className="h-4 w-4" />
                <span className="sr-only">Instagram</span>
              </a>
              <a href="#" title="Connect with us on LinkedIn" className="inline-flex h-10 w-10 items-center justify-center rounded-full border border-slate-200 dark:border-zinc-800 hover:bg-slate-100 dark:hover:bg-zinc-800 transition-colors">
                <Linkedin className="h-4 w-4" />
                <span className="sr-only">LinkedIn</span>
              </a>
            </div>
            
            {/* Theme Toggle */}
            <div className="flex items-center space-x-2">
              <Sun className="h-4 w-4 text-slate-500 dark:text-zinc-400" />
              <button
                type="button"
                role="switch"
                aria-checked={isDarkMode}
                onClick={toggleTheme}
                className={cn(
                  "peer inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-slate-400 focus-visible:ring-offset-2 focus-visible:ring-offset-white dark:focus-visible:ring-zinc-600 dark:focus-visible:ring-offset-zinc-950",
                  isDarkMode ? "bg-white" : "bg-slate-900"
                )}
              >
                <span
                  className={cn(
                    "pointer-events-none block h-5 w-5 rounded-full shadow-lg ring-0 transition-transform",
                    isDarkMode ? "translate-x-5 bg-slate-900" : "translate-x-0 bg-white"
                  )}
                />
              </button>
              <Moon className="h-4 w-4 text-slate-500 dark:text-zinc-400" />
            </div>
          </div>
        </div>
        <div className="mt-12 flex flex-col items-center justify-between gap-4 border-t border-slate-200 dark:border-zinc-800 pt-8 text-center md:flex-row">
          <p className="text-sm text-slate-500 dark:text-zinc-400">
            © {new Date().getFullYear()} {brandName}. All rights reserved.
          </p>
          <nav className="flex gap-4 text-sm text-slate-500 dark:text-zinc-400">
            <a href="#" className="transition-colors hover:text-slate-900 dark:hover:text-white">
              Privacy Policy
            </a>
            <a href="#" className="transition-colors hover:text-slate-900 dark:hover:text-white">
              Terms of Service
            </a>
            <a href="#" className="transition-colors hover:text-slate-900 dark:hover:text-white">
              Cookie Settings
            </a>
          </nav>
        </div>
      </div>
    </footer>
  );
}

--- FILE: frontend-web/registry/footers/GradientCenteredFooter.tsx ---

import React from "react";
import { cn } from "../core/utils";

export interface GradientCenteredFooterProps {
  logoSrc?: string;
  logoAlt?: string;
  description?: string;
  copyrightYear?: number;
  brandName?: string;
  brandLink?: string;
  className?: string;
}

export function GradientCenteredFooter({
  logoSrc = "https://raw.githubusercontent.com/prebuiltui/prebuiltui/main/assets/dummyLogo/prebuiltuiLogoSquareShape.svg",
  logoAlt = "Brand Logo",
  description = "Empowering creators worldwide with the most advanced AI content creation tools. Transform your ideas into reality.",
  copyrightYear = new Date().getFullYear(),
  brandName = "NOVA UI",
  brandLink = "/",
  className,
}: GradientCenteredFooterProps) {
  return (
    <footer className={cn("w-full bg-gradient-to-b from-[#1B004D] to-[#2E0A6F] text-white", className)}>
      <div className="max-w-7xl mx-auto px-6 py-16 flex flex-col items-center">
        <div className="flex items-center space-x-3 mb-6">
          <img 
            alt={logoAlt} 
            className="h-11 object-contain" 
            src={logoSrc} 
          />
        </div>
        <p className="text-center max-w-xl text-sm font-normal leading-relaxed text-white/90">
          {description}
        </p>
      </div>
      <div className="border-t border-[#3B1A7A]">
        <div className="max-w-7xl mx-auto px-6 py-6 text-center text-sm font-normal text-white/70">
          <a href={brandLink} className="text-white hover:text-white/80 transition-colors font-medium">
            {brandName}
          </a>{" "}
          ©{copyrightYear}. All rights reserved.
        </div>
      </div>
    </footer>
  );
}

--- FILE: frontend-web/registry/footers/HoverTextFooter.tsx ---

import React, { useRef, useEffect, useState } from "react";
import { motion } from "framer-motion";
import { cn } from "../core/utils";
import { Github, Twitter, Linkedin } from "lucide-react";

export interface HoverTextFooterProps {
  text?: string;
  duration?: number;
  className?: string;
  copyright?: string;
  socialLinks?: Array<{ icon: React.ElementType; href: string }>;
}

const DEFAULT_SOCIALS = [
  { icon: Twitter, href: "#" },
  { icon: Github, href: "#" },
  { icon: Linkedin, href: "#" },
];

export const HoverTextFooter = ({
  text = "NOVA UI",
  duration = 0,
  className,
  copyright,
  socialLinks = DEFAULT_SOCIALS,
}: HoverTextFooterProps) => {
  const svgRef = useRef<SVGSVGElement>(null);
  const [cursor, setCursor] = useState({ x: 0, y: 0 });
  const [hovered, setHovered] = useState(false);
  const [maskPosition, setMaskPosition] = useState({ cx: "50%", cy: "50%" });

  useEffect(() => {
    if (svgRef.current && cursor.x !== null && cursor.y !== null) {
      const svgRect = svgRef.current.getBoundingClientRect();
      const cxPercentage = ((cursor.x - svgRect.left) / svgRect.width) * 100;
      const cyPercentage = ((cursor.y - svgRect.top) / svgRect.height) * 100;
      setMaskPosition({
        cx: `${cxPercentage}%`,
        cy: `${cyPercentage}%`,
      });
    }
  }, [cursor]);

  const copyText = copyright || `© ${new Date().getFullYear()} ${text}. All rights reserved.`;

  return (
    <footer className={cn("relative w-full overflow-hidden bg-black text-white", className)}>
      
      {/* Background Gradient */}
      <div
        className="absolute inset-0 z-0 pointer-events-none"
        style={{
          background: "radial-gradient(125% 125% at 50% 10%, #0F0F11 50%, #3ca2fa33 100%)",
        }}
      />

      <div className="relative z-10 flex flex-col items-center justify-between min-h-[400px] md:min-h-[500px] pt-12 pb-6 px-4">
        
        {/* Navigation links (optional extension space) */}
        <div className="w-full max-w-6xl mx-auto flex justify-between items-center z-20">
          <div className="flex gap-4 sm:gap-8 text-sm font-medium text-white/50">
            <a href="#" className="hover:text-white transition-colors">About</a>
            <a href="#" className="hover:text-white transition-colors">Pricing</a>
            <a href="#" className="hover:text-white transition-colors">Contact</a>
          </div>
          <div className="flex gap-4">
            {socialLinks.map((social, idx) => {
              const Icon = social.icon;
              return (
                <a key={idx} href={social.href} className="text-white/50 hover:text-white transition-colors">
                  <Icon className="w-5 h-5" />
                </a>
              );
            })}
          </div>
        </div>

        {/* Hover Text SVG Effect */}
        <div className="flex-1 w-full max-w-7xl mx-auto flex items-center justify-center -mt-10 sm:-mt-0">
          <svg
            ref={svgRef}
            width="100%"
            height="100%"
            viewBox="0 0 300 100"
            xmlns="http://www.w3.org/2000/svg"
            onMouseEnter={() => setHovered(true)}
            onMouseLeave={() => setHovered(false)}
            onMouseMove={(e) => setCursor({ x: e.clientX, y: e.clientY })}
            className="select-none uppercase cursor-pointer w-full h-auto"
          >
            <defs>
              <linearGradient
                id="textGradient"
                gradientUnits="userSpaceOnUse"
                cx="50%"
                cy="50%"
                r="25%"
              >
                {hovered && (
                  <>
                    <stop offset="0%" stopColor="#eab308" />
                    <stop offset="25%" stopColor="#ef4444" />
                    <stop offset="50%" stopColor="#80eeb4" />
                    <stop offset="75%" stopColor="#06b6d4" />
                    <stop offset="100%" stopColor="#8b5cf6" />
                  </>
                )}
              </linearGradient>

              <motion.radialGradient
                id="revealMask"
                gradientUnits="userSpaceOnUse"
                r="20%"
                initial={{ cx: "50%", cy: "50%" }}
                animate={maskPosition}
                transition={{ duration: duration ?? 0, ease: "easeOut" }}
              >
                <stop offset="0%" stopColor="white" />
                <stop offset="100%" stopColor="black" />
              </motion.radialGradient>
              <mask id="textMask">
                <rect
                  x="0"
                  y="0"
                  width="100%"
                  height="100%"
                  fill="url(#revealMask)"
                />
              </mask>
            </defs>
            
            {/* Background hidden text (opacity transition on hover) */}
            <text
              x="50%"
              y="50%"
              textAnchor="middle"
              dominantBaseline="middle"
              strokeWidth="0.3"
              className="fill-transparent stroke-neutral-800 font-sans text-7xl font-bold tracking-tighter"
              style={{ opacity: hovered ? 0.7 : 0 }}
            >
              {text}
            </text>

            {/* Glowing animated stroke */}
            <motion.text
              x="50%"
              y="50%"
              textAnchor="middle"
              dominantBaseline="middle"
              strokeWidth="0.3"
              className="fill-transparent stroke-[#3ca2fa99] font-sans text-7xl font-bold tracking-tighter"
              initial={{ strokeDashoffset: 1000, strokeDasharray: 1000 }}
              animate={{
                strokeDashoffset: 0,
                strokeDasharray: 1000,
              }}
              transition={{
                duration: 4,
                ease: "easeInOut",
              }}
            >
              {text}
            </motion.text>

            {/* Masked full-color gradient text */}
            <text
              x="50%"
              y="50%"
              textAnchor="middle"
              dominantBaseline="middle"
              stroke="url(#textGradient)"
              strokeWidth="0.3"
              mask="url(#textMask)"
              className="fill-transparent font-sans text-7xl font-bold tracking-tighter"
            >
              {text}
            </text>
          </svg>
        </div>

        {/* Footer Bottom */}
        <div className="w-full text-center border-t border-white/10 pt-6 mt-4">
          <p className="text-xs font-medium text-white/40 tracking-wider">
            {copyText}
          </p>
        </div>
      </div>
    </footer>
  );
};

--- FILE: frontend-web/registry/footers/IconFooter.tsx ---

import * as React from "react";
import { cn } from "../core/utils";
import { LucideIcon, FileText, Blocks, Zap, HelpCircle, Phone, FileSignature, ShieldAlert } from "lucide-react";

export interface SocialLink {
  name: string;
  href: string;
}

export interface FooterLink {
  name: string;
  Icon: LucideIcon | React.FC<React.SVGProps<SVGSVGElement>>;
  href?: string;
}

export interface FooterColumn {
  title: string;
  links: FooterLink[];
}

export interface IconFooterProps extends React.HTMLAttributes<HTMLDivElement> {
  brand?: {
    name: string;
    description: string;
  };
  socialLinks?: SocialLink[];
  columns?: FooterColumn[];
  copyright?: string;
}

const DEFAULT_BRAND = {
  name: "NOVA UI",
  description: "Crafting exceptional digital experiences through modern, reusable components. Built for speed, designed for scale.",
};

const DEFAULT_SOCIALS = [
  { name: "Twitter", href: "#" },
  { name: "GitHub", href: "#" },
  { name: "Discord", href: "#" },
];

const DEFAULT_COLUMNS: FooterColumn[] = [
  {
    title: "Product",
    links: [
      { name: "Documentation", Icon: FileText, href: "#" },
      { name: "Components", Icon: Blocks, href: "#" },
      { name: "Integrations", Icon: Zap, href: "#" },
    ],
  },
  {
    title: "Company",
    links: [
      { name: "Help Center", Icon: HelpCircle, href: "#" },
      { name: "Contact Us", Icon: Phone, href: "#" },
    ],
  },
  {
    title: "Legal",
    links: [
      { name: "Terms of Service", Icon: FileSignature, href: "#" },
      { name: "Privacy Policy", Icon: ShieldAlert, href: "#" },
    ],
  },
];

export const IconFooter = React.forwardRef<HTMLDivElement, IconFooterProps>(
  ({ className, brand = DEFAULT_BRAND, socialLinks = DEFAULT_SOCIALS, columns = DEFAULT_COLUMNS, copyright = "© 2025 NOVA UI. All rights reserved.", ...props }, ref) => {
    return (
      <div
        ref={ref}
        className={cn("pt-24 bg-white dark:bg-zinc-950 text-slate-900 dark:text-white", className)}
        {...props}
      >
        <div className="max-w-screen-xl mx-auto px-4 lg:px-8">
          <div className="grid grid-cols-1 lg:grid-cols-12">
            <div className="lg:col-span-4">
              <a href="#" className="text-xl font-semibold text-slate-900 dark:text-white">
                {brand.name}
              </a>
              <p className="text-sm text-slate-500 dark:text-slate-400 mt-2">
                {brand.description}
              </p>

              <p className="text-sm font-light text-slate-500 dark:text-slate-400 mt-3.5">
                {socialLinks.map((link, index) => (
                  <React.Fragment key={link.name}>
                    <a
                      className="hover:text-slate-900 dark:hover:text-white transition-colors"
                      target="_blank"
                      href={link.href}
                      rel="noopener noreferrer"
                    >
                      {link.name}
                    </a>
                    {index < socialLinks.length - 1 && " • "}
                  </React.Fragment>
                ))}
              </p>
            </div>

            <div className="grid grid-cols-2 mt-16 md:grid-cols-3 lg:col-span-8 lg:justify-items-end lg:mt-0">
              {columns.map(({ title, links }) => (
                <div key={title} className="last:mt-12 md:last:mt-0">
                  <h3 className="text-sm font-semibold text-slate-900 dark:text-white">{title}</h3>
                  <ul className="mt-4 space-y-2.5">
                    {links.map(({ name, Icon, href }) => (
                      <li key={name}>
                        <a
                          href={href || "#"}
                          className="text-sm transition-all text-slate-500 dark:text-slate-400 hover:text-slate-900 dark:hover:text-white group flex items-center"
                        >
                          <Icon className="stroke-2 h-4 w-4 mr-1.5 transition-all text-slate-400 group-hover:text-slate-900 dark:text-slate-500 dark:group-hover:text-white" />
                          {name}
                        </a>
                      </li>
                    ))}
                  </ul>
                </div>
              ))}
            </div>
          </div>

          {copyright && (
            <div className="mt-20 border-t border-slate-200 dark:border-zinc-800 pt-6 pb-8">
              <p className="text-xs text-slate-500 dark:text-slate-400">{copyright}</p>
            </div>
          )}
        </div>
      </div>
    );
  }
);

IconFooter.displayName = "IconFooter";

--- FILE: frontend-web/registry/footers/LargeNameFooter.tsx ---

import React from "react";
import { Hexagon, Twitter } from "lucide-react";
import { cn } from "../core/utils";

export interface FooterColumn {
  title: string;
  links: Array<{
    label: string;
    href: string;
  }>;
}

export interface LargeNameFooterProps {
  brandName?: string;
  largeText?: string;
  builtByText?: string;
  authorName?: string;
  authorLink?: string;
  tweetUrl?: string;
  columns?: FooterColumn[];
  logo?: React.ReactNode;
  className?: string;
}

const DEFAULT_COLUMNS: FooterColumn[] = [
  {
    title: "Pages",
    links: [
      { label: "Docs", href: "#" },
      { label: "Components", href: "#" },
      { label: "Examples", href: "#" },
      { label: "Pricing", href: "#" },
      { label: "Blog", href: "#" },
    ],
  },
  {
    title: "Socials",
    links: [
      { label: "Github", href: "#" },
      { label: "LinkedIn", href: "#" },
      { label: "X", href: "#" },
    ],
  },
  {
    title: "Legal",
    links: [
      { label: "Privacy Policy", href: "#" },
      { label: "Terms of Service", href: "#" },
    ],
  },
];

export function LargeNameFooter({
  brandName = "NOVA UI",
  largeText = "nova/ui",
  builtByText = "Built by",
  authorName = "@novateam",
  authorLink = "#",
  tweetUrl = "#",
  columns = DEFAULT_COLUMNS,
  logo = <Hexagon className="w-8 h-8 text-slate-900 dark:text-white" />,
  className,
}: LargeNameFooterProps) {
  return (
    <footer className={cn("py-12 px-4 md:px-6 bg-white dark:bg-zinc-950 text-slate-900 dark:text-white", className)}>
      <div className="container mx-auto">
        <div className="flex flex-col md:flex-row justify-between">
          <div className="mb-8 md:mb-0">
            <a href="/" className="flex items-center gap-2">
              {logo}
              <h2 className="text-lg font-bold">{brandName}</h2>
            </a>

            <h1 className="text-slate-700 dark:text-gray-300 mt-4">
              {builtByText}{" "}
              <span className="text-blue-500 dark:text-[#039ee4]">
                <a href={authorLink}>{authorName}</a>
              </span>
            </h1>
            <div className="mt-2">
              <a
                href={tweetUrl}
                target="_blank"
                rel="noopener noreferrer"
                className="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-slate-400 bg-slate-100 text-slate-900 hover:bg-slate-200 dark:bg-zinc-800 dark:text-zinc-50 dark:hover:bg-zinc-700 h-9 px-4 py-2"
              >
                Share Your Thoughts On
                <Twitter className="ml-2 w-3.5 h-3.5" />
              </a>
            </div>
            <p className="text-sm text-slate-500 dark:text-gray-400 mt-5">
              © {new Date().getFullYear()} {brandName}. All rights reserved.
            </p>
          </div>
          
          <div className="grid grid-cols-2 md:grid-cols-4 gap-8">
            {columns.map((col, idx) => (
              <div key={idx}>
                <h3 className="font-semibold mb-4 text-slate-900 dark:text-white">{col.title}</h3>
                <ul className="space-y-2">
                  {col.links.map((link, linkIdx) => (
                    <li key={linkIdx}>
                      <a
                        href={link.href}
                        className="text-gray-600 hover:text-black dark:text-gray-400 dark:hover:text-white transition-colors"
                      >
                        {link.label}
                      </a>
                    </li>
                  ))}
                </ul>
              </div>
            ))}
          </div>
        </div>
        
        <div className="w-full flex mt-4 items-center justify-center">
          <h1 className="text-center text-3xl md:text-5xl lg:text-[10rem] font-bold bg-clip-text text-transparent bg-gradient-to-b from-neutral-700 to-neutral-900 dark:from-neutral-200 dark:to-neutral-500 select-none">
            {largeText}
          </h1>
        </div>
      </div>
    </footer>
  );
}


--- FILE: frontend-web/registry/footers/MinimalFooter.tsx ---

import React from "react";
import { cn } from "../core/utils";
import { Twitter, Github, Linkedin, Hexagon } from "lucide-react";

export interface MinimalFooterProps {
  logo?: React.ReactNode;
  brandName?: string;
  socialLinks?: Array<{
    icon: React.ReactNode;
    href: string;
    label: string;
  }>;
  mainLinks?: Array<{
    href: string;
    label: string;
  }>;
  legalLinks?: Array<{
    href: string;
    label: string;
  }>;
  copyright?: {
    text: string;
    license?: string;
  };
  className?: string;
}

const DEFAULT_SOCIAL_LINKS = [
  { icon: <Twitter className="h-4 w-4" />, href: "#", label: "Twitter" },
  { icon: <Github className="h-4 w-4" />, href: "#", label: "GitHub" },
  { icon: <Linkedin className="h-4 w-4" />, href: "#", label: "LinkedIn" },
];

const DEFAULT_MAIN_LINKS = [
  { href: "#", label: "About" },
  { href: "#", label: "Blog" },
  { href: "#", label: "Careers" },
  { href: "#", label: "Contact" },
];

const DEFAULT_LEGAL_LINKS = [
  { href: "#", label: "Privacy Policy" },
  { href: "#", label: "Terms of Service" },
  { href: "#", label: "Cookie Policy" },
];

export function MinimalFooter({
  logo = <Hexagon className="h-6 w-6 text-slate-900 dark:text-white" />,
  brandName = "NOVA UI",
  socialLinks = DEFAULT_SOCIAL_LINKS,
  mainLinks = DEFAULT_MAIN_LINKS,
  legalLinks = DEFAULT_LEGAL_LINKS,
  copyright = {
    text: "© 2025 NOVA UI Inc.",
    license: "All rights reserved.",
  },
  className,
}: MinimalFooterProps) {
  return (
    <footer className={cn("pb-6 pt-16 lg:pb-8 lg:pt-24 bg-white dark:bg-zinc-950", className)}>
      <div className="px-4 lg:px-8 max-w-7xl mx-auto">
        <div className="md:flex md:items-start md:justify-between">
          <a
            href="/"
            className="flex items-center gap-x-2 text-slate-900 dark:text-white"
            aria-label={brandName}
          >
            {logo}
            <span className="font-bold text-xl">{brandName}</span>
          </a>
          <ul className="flex list-none mt-6 md:mt-0 space-x-3">
            {socialLinks.map((link, i) => (
              <li key={i}>
                <a
                  href={link.href}
                  target="_blank"
                  rel="noopener noreferrer"
                  aria-label={link.label}
                  className="inline-flex items-center justify-center h-10 w-10 rounded-full bg-slate-100 hover:bg-slate-200 text-slate-900 dark:bg-zinc-900 dark:hover:bg-zinc-800 dark:text-white transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-slate-400"
                >
                  {link.icon}
                </a>
              </li>
            ))}
          </ul>
        </div>
        <div className="border-t border-slate-200 dark:border-zinc-800 mt-6 pt-6 md:mt-4 md:pt-8 lg:grid lg:grid-cols-10">
          <nav className="lg:mt-0 lg:col-[4/11]">
            <ul className="list-none flex flex-wrap -my-1 -mx-2 lg:justify-end">
              {mainLinks.map((link, i) => (
                <li key={i} className="my-1 mx-2 shrink-0">
                  <a
                    href={link.href}
                    className="text-sm font-medium text-slate-900 dark:text-white underline-offset-4 hover:underline transition-all"
                  >
                    {link.label}
                  </a>
                </li>
              ))}
            </ul>
          </nav>
          <div className="mt-6 lg:mt-0 lg:col-[4/11]">
            <ul className="list-none flex flex-wrap -my-1 -mx-3 lg:justify-end">
              {legalLinks.map((link, i) => (
                <li key={i} className="my-1 mx-3 shrink-0">
                  <a
                    href={link.href}
                    className="text-sm text-slate-500 dark:text-slate-400 underline-offset-4 hover:underline transition-all hover:text-slate-900 dark:hover:text-white"
                  >
                    {link.label}
                  </a>
                </li>
              ))}
            </ul>
          </div>
          <div className="mt-6 text-sm leading-6 text-slate-500 dark:text-slate-400 whitespace-nowrap lg:mt-0 lg:row-[1/3] lg:col-[1/4]">
            <div>{copyright.text}</div>
            {copyright.license && <div>{copyright.license}</div>}
          </div>
        </div>
      </div>
    </footer>
  );
}

--- FILE: frontend-web/registry/footers/RadialGlowFooter.tsx ---

import React from 'react';
import type { ComponentProps, ReactNode } from 'react';
import { motion, useReducedMotion } from 'framer-motion';
import { FacebookIcon, FrameIcon, InstagramIcon, LinkedinIcon, YoutubeIcon } from 'lucide-react';
import { cn } from '../core/utils';

export interface FooterLink {
  title: string;
  href: string;
  icon?: React.ComponentType<{ className?: string }>;
}

export interface FooterSection {
  label: string;
  links: FooterLink[];
}

export interface RadialGlowFooterProps {
  brandName?: string;
  logo?: ReactNode;
  sections?: FooterSection[];
  className?: string;
}

const DEFAULT_SECTIONS: FooterSection[] = [
  {
    label: 'Product',
    links: [
      { title: 'Features', href: '#features' },
      { title: 'Pricing', href: '#pricing' },
      { title: 'Testimonials', href: '#testimonials' },
      { title: 'Integration', href: '/' },
    ],
  },
  {
    label: 'Company',
    links: [
      { title: 'FAQs', href: '/faqs' },
      { title: 'About Us', href: '/about' },
      { title: 'Privacy Policy', href: '/privacy' },
      { title: 'Terms of Services', href: '/terms' },
    ],
  },
  {
    label: 'Resources',
    links: [
      { title: 'Blog', href: '/blog' },
      { title: 'Changelog', href: '/changelog' },
      { title: 'Brand', href: '/brand' },
      { title: 'Help', href: '/help' },
    ],
  },
  {
    label: 'Social Links',
    links: [
      { title: 'Facebook', href: '#', icon: FacebookIcon },
      { title: 'Instagram', href: '#', icon: InstagramIcon },
      { title: 'Youtube', href: '#', icon: YoutubeIcon },
      { title: 'LinkedIn', href: '#', icon: LinkedinIcon },
    ],
  },
];

export function RadialGlowFooter({
  brandName = "Acme",
  logo = <FrameIcon className="size-8 text-slate-900 dark:text-white" />,
  sections = DEFAULT_SECTIONS,
  className
}: RadialGlowFooterProps) {
  return (
    <footer className={cn("relative w-full max-w-6xl mx-auto flex flex-col items-center justify-center md:rounded-t-[3rem] rounded-t-[2rem] border-t border-slate-200 dark:border-zinc-800 bg-[radial-gradient(35%_128px_at_50%_0%,rgba(0,0,0,0.05),transparent)] dark:bg-[radial-gradient(35%_128px_at_50%_0%,rgba(255,255,255,0.08),transparent)] px-6 py-12 lg:py-16 bg-white dark:bg-zinc-950", className)}>
      <div className="absolute top-0 right-1/2 left-1/2 h-px w-1/3 -translate-x-1/2 -translate-y-1/2 rounded-full bg-slate-900/20 dark:bg-white/20 blur" />

      <div className="grid w-full gap-8 xl:grid-cols-3 xl:gap-8">
        <AnimatedContainer className="space-y-4">
          {logo}
          <p className="text-slate-500 dark:text-slate-400 mt-8 text-sm md:mt-0 font-medium">
            © {new Date().getFullYear()} {brandName}. All rights reserved.
          </p>
        </AnimatedContainer>

        <div className="mt-10 grid grid-cols-2 gap-8 md:grid-cols-4 xl:col-span-2 xl:mt-0">
          {sections.map((section, index) => (
            <AnimatedContainer key={section.label} delay={0.1 + index * 0.1}>
              <div className="mb-10 md:mb-0">
                <h3 className="text-xs font-semibold text-slate-900 dark:text-white uppercase tracking-wider">{section.label}</h3>
                <ul className="text-slate-500 dark:text-slate-400 mt-4 space-y-2 text-sm">
                  {section.links.map((link) => (
                    <li key={link.title}>
                      <a
                        href={link.href}
                        className="hover:text-slate-900 dark:hover:text-white inline-flex items-center transition-all duration-300 font-medium"
                      >
                        {link.icon && <link.icon className="me-1.5 size-4" />}
                        {link.title}
                      </a>
                    </li>
                  ))}
                </ul>
              </div>
            </AnimatedContainer>
          ))}
        </div>
      </div>
    </footer>
  );
}

type ViewAnimationProps = {
  delay?: number;
  className?: ComponentProps<typeof motion.div>['className'];
  children: ReactNode;
};

function AnimatedContainer({ className, delay = 0.1, children }: ViewAnimationProps) {
  const shouldReduceMotion = useReducedMotion();

  if (shouldReduceMotion) {
    return <div className={className}>{children}</div>;
  }

  return (
    <motion.div
      initial={{ filter: 'blur(4px)', translateY: -8, opacity: 0 }}
      whileInView={{ filter: 'blur(0px)', translateY: 0, opacity: 1 }}
      viewport={{ once: true }}
      transition={{ delay, duration: 0.8, ease: "easeOut" }}
      className={className}
    >
      {children}
    </motion.div>
  );
}

--- FILE: frontend-web/registry/footers/StackedCircularFooter.tsx ---

import React from "react";
import { Facebook, Instagram, Linkedin, Twitter, Hexagon } from "lucide-react";
import { cn } from "../core/utils";

export interface StackedCircularFooterProps {
  brandName?: string;
  logo?: React.ReactNode;
  navLinks?: Array<{ label: string; href: string }>;
  socialLinks?: Array<{ icon: React.ReactNode; href: string; label: string }>;
  className?: string;
}

const DEFAULT_NAV_LINKS = [
  { label: "Home", href: "#" },
  { label: "About", href: "#" },
  { label: "Services", href: "#" },
  { label: "Products", href: "#" },
  { label: "Contact", href: "#" },
];

const DEFAULT_SOCIAL_LINKS = [
  { icon: <Facebook className="h-4 w-4" />, href: "#", label: "Facebook" },
  { icon: <Twitter className="h-4 w-4" />, href: "#", label: "Twitter" },
  { icon: <Instagram className="h-4 w-4" />, href: "#", label: "Instagram" },
  { icon: <Linkedin className="h-4 w-4" />, href: "#", label: "LinkedIn" },
];

export function StackedCircularFooter({
  brandName = "Your Company",
  logo = <Hexagon className="w-8 h-8 text-blue-500 dark:text-blue-400" />,
  navLinks = DEFAULT_NAV_LINKS,
  socialLinks = DEFAULT_SOCIAL_LINKS,
  className,
}: StackedCircularFooterProps) {
  return (
    <footer className={cn("bg-white dark:bg-zinc-950 py-12 text-slate-900 dark:text-zinc-50", className)}>
      <div className="container mx-auto px-4 md:px-6">
        <div className="flex flex-col items-center">
          
          <div className="mb-8 rounded-full bg-blue-500/10 dark:bg-blue-500/20 p-8 flex items-center justify-center">
            {logo}
          </div>
          
          <nav className="mb-8 flex flex-wrap justify-center gap-6">
            {navLinks.map((link, idx) => (
              <a
                key={idx}
                href={link.href}
                className="text-slate-600 dark:text-slate-400 hover:text-slate-900 dark:hover:text-white transition-colors font-medium"
              >
                {link.label}
              </a>
            ))}
          </nav>
          
          <div className="mb-8 flex space-x-4">
            {socialLinks.map((social, idx) => (
              <a
                key={idx}
                href={social.href}
                target="_blank"
                rel="noopener noreferrer"
                title={social.label}
                className="inline-flex h-10 w-10 items-center justify-center rounded-full border border-slate-200 dark:border-zinc-800 hover:bg-slate-100 dark:hover:bg-zinc-800 transition-colors focus:outline-none focus:ring-2 focus:ring-slate-400"
              >
                {social.icon}
                <span className="sr-only">{social.label}</span>
              </a>
            ))}
          </div>
          
          <div className="mb-8 w-full max-w-md">
            <form className="flex space-x-2" onSubmit={(e) => e.preventDefault()}>
              <div className="flex-grow">
                <label htmlFor="email-subscribe" className="sr-only">
                  Email
                </label>
                <input
                  id="email-subscribe"
                  placeholder="Enter your email"
                  type="email"
                  className="flex h-10 w-full rounded-full border border-slate-200 dark:border-zinc-800 bg-transparent px-4 py-2 text-sm placeholder:text-slate-500 focus:outline-none focus:ring-2 focus:ring-slate-400 dark:focus:ring-zinc-600"
                />
              </div>
              <button
                type="submit"
                className="inline-flex h-10 items-center justify-center rounded-full bg-slate-900 px-6 text-sm font-medium text-white transition-colors hover:bg-slate-900/90 dark:bg-white dark:text-slate-900 dark:hover:bg-white/90 focus:outline-none focus:ring-2 focus:ring-slate-400"
              >
                Subscribe
              </button>
            </form>
          </div>
          
          <div className="text-center">
            <p className="text-sm text-slate-500 dark:text-zinc-400">
              © {new Date().getFullYear()} {brandName}. All rights reserved.
            </p>
          </div>
          
        </div>
      </div>
    </footer>
  );
}

--- FILE: frontend-web/registry/footers/StatusFooter.tsx ---

import React, { useState, useEffect, useRef } from "react";
import { 
  ChevronDown, 
  ExternalLink, 
  Monitor, 
  Moon, 
  Sun, 
  Github, 
  Linkedin, 
  Twitter, 
  Youtube,
  Triangle
} from "lucide-react";
import { cn } from "../core/utils";

export interface FooterLink {
  title: string;
  href: string;
  external?: boolean;
}

export interface FooterDropdown {
  title: string;
  items: FooterLink[];
}

export interface FooterColumnData {
  group: string;
  items: FooterLink[];
  dropdown?: FooterDropdown;
  bottomLink?: FooterLink;
}

export interface StatusFooterProps {
  logo?: React.ReactNode;
  productLinks?: FooterColumnData;
  resourceLinks?: FooterColumnData;
  companyLinks?: FooterColumnData;
  socialLinks?: Array<{ title: string; href: string; icon: React.ElementType }>;
  statusText?: string;
  statusColor?: string;
  className?: string;
}

// --- Lightweight Custom Dropdown ---
function SimpleDropdown({ title, items }: { title: string; items: FooterLink[] }) {
  const [isOpen, setIsOpen] = useState(false);
  const ref = useRef<HTMLDivElement>(null);

  useEffect(() => {
    const handleClickOutside = (e: MouseEvent) => {
      if (ref.current && !ref.current.contains(e.target as Node)) {
        setIsOpen(false);
      }
    };
    document.addEventListener("mousedown", handleClickOutside);
    return () => document.removeEventListener("mousedown", handleClickOutside);
  }, []);

  return (
    <div className="relative" ref={ref}>
      <button
        onClick={() => setIsOpen(!isOpen)}
        className="text-slate-500 dark:text-slate-400 flex gap-1 items-center hover:text-slate-900 dark:hover:text-white text-sm transition-colors"
      >
        {title} <ChevronDown strokeWidth={2} size={16} />
      </button>
      {isOpen && (
        <div className="absolute bottom-full mb-2 right-0 md:left-0 w-60 bg-white dark:bg-zinc-900 border border-slate-200 dark:border-zinc-800 rounded-lg shadow-lg p-1 z-50">
          {items.map((item, idx) => (
            <a
              key={idx}
              href={item.href}
              className="flex items-center justify-between px-4 py-2.5 text-sm text-slate-600 dark:text-slate-300 hover:bg-slate-100 dark:hover:bg-zinc-800 hover:text-slate-900 dark:hover:text-white rounded-md transition-colors"
            >
              {item.title}
              {item.external && <ExternalLink strokeWidth={2} size={14} />}
            </a>
          ))}
        </div>
      )}
    </div>
  );
}

// --- Zero-Dependency Theme Switcher ---
type Theme = "light" | "dark" | "system";

const themes = [
  { key: "system", icon: Monitor, label: "System theme" },
  { key: "light", icon: Sun, label: "Light theme" },
  { key: "dark", icon: Moon, label: "Dark theme" },
];

function ThemeSwitcher({ className }: { className?: string }) {
  const [theme, setTheme] = useState<Theme>("system");
  const [mounted, setMounted] = useState(false);

  useEffect(() => {
    setMounted(true);
    // Check current class on html
    const isDark = document.documentElement.classList.contains("dark");
    // Highly simplified detection for demo
    if (isDark) setTheme("dark");
    else setTheme("light");
  }, []);

  const handleThemeClick = (themeKey: Theme) => {
    setTheme(themeKey);
    const htmlEl = document.documentElement;
    if (themeKey === "dark") {
      htmlEl.classList.add("dark");
    } else if (themeKey === "light") {
      htmlEl.classList.remove("dark");
    } else {
      // System
      if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
        htmlEl.classList.add("dark");
      } else {
        htmlEl.classList.remove("dark");
      }
    }
  };

  if (!mounted) return null;

  return (
    <div className={cn("relative isolate flex h-8 rounded-full bg-slate-100 dark:bg-zinc-900 p-1 ring-1 ring-slate-200 dark:ring-zinc-800", className)}>
      {themes.map(({ key, icon: Icon, label }) => {
        const isActive = theme === key;
        return (
          <button
            key={key}
            aria-label={label}
            className="relative h-6 w-7 rounded-full flex items-center justify-center transition-colors"
            onClick={() => handleThemeClick(key as Theme)}
            type="button"
          >
            {isActive && (
              <div className="absolute inset-0 rounded-full bg-white dark:bg-zinc-700 shadow-sm" />
            )}
            <Icon
              className={cn(
                "relative z-10 size-3.5",
                isActive ? "text-slate-900 dark:text-white" : "text-slate-500 dark:text-slate-400"
              )}
            />
          </button>
        );
      })}
    </div>
  );
}

// --- Default Data ---
const DEFAULT_PRODUCT = {
  group: "Product",
  items: [
    { title: "AI", href: "#" },
    { title: "Enterprise", href: "#" },
    { title: "Compute", href: "#" },
    { title: "Observability", href: "#" },
    { title: "Security", href: "#" },
  ],
  bottomLink: { title: "v0", href: "#", external: true }
};

const DEFAULT_RESOURCES = {
  group: "Resources",
  items: [
    { title: "Docs", href: "#" },
    { title: "Guides", href: "#" },
    { title: "Help", href: "#" },
    { title: "Pricing", href: "#" },
  ],
  dropdown: {
    title: "SDKs by Brand",
    items: [
      { title: "AI SDK", href: "#", external: true },
      { title: "Flags SDK", href: "#", external: true },
      { title: "Chat SDK", href: "#", external: true },
    ]
  }
};

const DEFAULT_COMPANY = {
  group: "Company",
  items: [
    { title: "About", href: "#" },
    { title: "Blog", href: "#" },
    { title: "Careers", href: "#" },
    { title: "Contact Us", href: "#" },
    { title: "Customers", href: "#" },
  ],
  dropdown: {
    title: "Legal",
    items: [
      { title: "Privacy Policy", href: "#" },
      { title: "Terms of Service", href: "#" },
      { title: "Cookie Preferences", href: "#" },
    ]
  }
};

const DEFAULT_SOCIALS = [
  { title: "GitHub", href: "#", icon: Github },
  { title: "LinkedIn", href: "#", icon: Linkedin },
  { title: "Twitter", href: "#", icon: Twitter },
  { title: "YouTube", href: "#", icon: Youtube },
];

export function StatusFooter({
  logo = <Triangle className="size-6 text-slate-900 dark:text-white fill-slate-900 dark:fill-white" />,
  productLinks = DEFAULT_PRODUCT,
  resourceLinks = DEFAULT_RESOURCES,
  companyLinks = DEFAULT_COMPANY,
  socialLinks = DEFAULT_SOCIALS,
  statusText = "All systems normal.",
  statusColor = "bg-blue-500",
  className
}: StatusFooterProps) {
  
  const renderColumn = (col: FooterColumnData) => (
    <div className="space-y-4 text-sm">
      <span className="block font-medium text-slate-900 dark:text-white">{col.group}</span>
      <div className="space-y-3">
        {col.items.map((item, idx) => (
          <a
            key={idx}
            href={item.href}
            className="text-slate-500 dark:text-slate-400 hover:text-slate-900 dark:hover:text-white block transition-colors duration-150"
          >
            {item.title}
          </a>
        ))}
        {col.bottomLink && (
          <a
            href={col.bottomLink.href}
            className="text-slate-500 dark:text-slate-400 flex gap-1 items-center text-sm hover:text-slate-900 dark:hover:text-white transition-colors duration-150"
          >
            {col.bottomLink.title}
            {col.bottomLink.external && <ExternalLink strokeWidth={2} size={14} />}
          </a>
        )}
        {col.dropdown && (
          <SimpleDropdown title={col.dropdown.title} items={col.dropdown.items} />
        )}
      </div>
    </div>
  );

  return (
    <footer className={cn("py-16 bg-white dark:bg-zinc-950 border-t border-slate-200 dark:border-zinc-800", className)}>
      <div className="mx-auto max-w-6xl px-6">
        <div className="grid gap-14 grid-cols-2 md:grid-cols-3 lg:grid-cols-5">
          
          <div className="grid gap-3">
            {renderColumn(productLinks)}
          </div>
          
          <div className="grid gap-3">
            {renderColumn(resourceLinks)}
          </div>
          
          <div className="grid gap-3">
            {renderColumn(companyLinks)}
          </div>

          <div className="grid gap-3">
            <div className="space-y-4 text-sm">
              <span className="block font-medium text-slate-900 dark:text-white">Social</span> 
              <div className="space-y-3">
                {socialLinks.map((social, idx) => {
                  const Icon = social.icon;
                  return (
                    <a
                      key={idx}
                      href={social.href}
                      className="text-slate-500 dark:text-slate-400 hover:text-slate-900 dark:hover:text-white block transition-colors duration-150"
                    >
                      <span className="flex gap-2 items-center">
                        <Icon size={14} className="opacity-80" />
                        {social.title}
                      </span>
                    </a>
                  )
                })}
              </div>
            </div>
          </div>

          <div className="flex justify-start lg:justify-end">
            <div className="h-fit">
              {logo}
            </div>
          </div>

        </div>
       
        <div className="mt-16 flex flex-wrap items-center justify-between gap-6 py-6 border-t border-slate-200 dark:border-zinc-800">
          <button className="flex items-center gap-2 text-sm font-medium text-blue-600 dark:text-blue-400 hover:text-blue-700 dark:hover:text-blue-300 transition-colors focus:outline-none">
            <span className={cn("block size-3 rounded-full border border-white dark:border-zinc-950", statusColor)} />
            {statusText}
          </button>
          
          <ThemeSwitcher />
        </div>
      </div>
    </footer>
  );
}

--- FILE: frontend-web/registry/footers/StickyFooter.tsx ---

import React from "react";
import { motion } from "framer-motion";
import { cn } from "../core/utils";

// Animation variants for reusability
const containerVariants = {
  hidden: { opacity: 0, y: 50 },
  visible: {
    opacity: 1,
    y: 0,
    transition: {
      duration: 0.8,
      ease: "easeOut",
      staggerChildren: 0.1,
    },
  },
};

const itemVariants = {
  hidden: { opacity: 0, x: -20 },
  visible: {
    opacity: 1,
    x: 0,
    transition: { duration: 0.6, ease: "easeOut" },
  },
};

const linkVariants = {
  hidden: { opacity: 0, y: 10 },
  visible: {
    opacity: 1,
    y: 0,
    transition: { duration: 0.4, ease: "easeOut" },
  },
};

const socialVariants = {
  hidden: { opacity: 0, scale: 0 },
  visible: {
    opacity: 1,
    scale: 1,
    transition: {
      type: "spring",
      stiffness: 200,
      damping: 10,
    },
  },
};

const backgroundVariants = {
  hidden: { opacity: 0, scale: 0.8 },
  visible: {
    opacity: 1,
    scale: 1,
    transition: {
      duration: 2,
      ease: "easeOut",
    },
  },
};

// Reusable components
const NavSection = ({ title, links, index }: { title: string; links: string[]; index: number }) => (
  <motion.div variants={itemVariants} custom={index} className="flex flex-col gap-2">
    <motion.h3
      initial={{ opacity: 0, y: -10 }}
      animate={{ opacity: 1, y: 0 }}
      transition={{ delay: 0.3 + index * 0.1, duration: 0.5 }}
      className="mb-2 uppercase text-slate-500 dark:text-slate-400 text-xs font-semibold tracking-wider border-b border-slate-200 dark:border-zinc-800 pb-1 hover:text-slate-900 dark:hover:text-white transition-colors duration-300"
    >
      {title}
    </motion.h3>
    {links.map((link, linkIndex) => (
      <motion.a
        key={linkIndex}
        variants={linkVariants}
        custom={linkIndex}
        href="#"
        whileHover={{
          x: 8,
          transition: { type: "spring", stiffness: 300, damping: 20 },
        }}
        className="text-slate-500 dark:text-slate-400 hover:text-slate-900 dark:hover:text-white transition-colors duration-300 font-sans text-xs md:text-sm group relative"
      >
        <span className="relative">
          {link}
          <motion.span
            className="absolute bottom-0 left-0 h-0.5 bg-indigo-500"
            initial={{ width: 0 }}
            whileHover={{ width: "100%" }}
            transition={{ duration: 0.3 }}
          />
        </span>
      </motion.a>
    ))}
  </motion.div>
);

const SocialLink = ({ href, label, icon, index }: { href: string; label: string; icon: React.ReactNode | string; index: number }) => (
  <motion.a
    variants={socialVariants}
    custom={index}
    href={href}
    whileHover={{
      scale: 1.2,
      rotate: 12,
      transition: { type: "spring", stiffness: 300, damping: 15 },
    }}
    whileTap={{ scale: 0.9 }}
    className="w-6 h-6 md:w-8 md:h-8 rounded-full bg-slate-200 dark:bg-zinc-800 hover:bg-gradient-to-r hover:from-indigo-500 hover:to-purple-500 flex items-center justify-center transition-colors duration-300 group"
    aria-label={label}
  >
    <motion.span
      className="text-xs md:text-sm font-bold text-slate-500 dark:text-slate-400 group-hover:text-white"
      whileHover={{ scale: 1.1 }}
    >
      {icon}
    </motion.span>
  </motion.a>
);

export interface StickyFooterProps {
  sections?: Array<{ title: string; links: string[] }>;
  social?: Array<{ href: string; label: string; icon: string | React.ReactNode }>;
  title?: string;
  subtitle?: string;
  copyright?: string;
  className?: string;
}

const DEFAULT_SECTIONS = [
  { title: "About", links: ["Home", "Projects", "Our Mission", "Contact Us"] },
  { title: "Education", links: ["News", "Learn", "Certification", "Publications"] },
  { title: "Services", links: ["Web Design", "Development", "Consulting", "Support"] },
  { title: "Resources", links: ["Blog", "Documentation", "Community", "Help Center"] },
];

const DEFAULT_SOCIAL = [
  { href: "#", label: "Twitter", icon: "T" },
  { href: "#", label: "GitHub", icon: "G" },
  { href: "#", label: "LinkedIn", icon: "L" },
];

export function StickyFooter({
  sections = DEFAULT_SECTIONS,
  social = DEFAULT_SOCIAL,
  title = "Sticky Footer",
  subtitle = "Scroll-triggered design",
  copyright = "©2025 All rights reserved",
  className
}: StickyFooterProps) {
  return (
    <div className={cn("relative h-[70vh]", className)} style={{ clipPath: "polygon(0% 0, 100% 0%, 100% 100%, 0 100%)" }}>
      <div className="relative h-[calc(100vh+70vh)] -top-[100vh]">
        <div className="h-[70vh] sticky top-[calc(100vh-70vh)]">
          <motion.div
            initial="hidden"
            animate="visible"
            variants={containerVariants}
            className="bg-gradient-to-br from-white via-slate-50 to-white dark:from-zinc-950 dark:via-zinc-900 dark:to-zinc-950/90 py-6 md:py-12 px-4 md:px-12 h-full w-full flex flex-col justify-between relative overflow-hidden"
          >
            {/* Animated Background Elements */}
            <div className="absolute inset-0 bg-gradient-to-t from-black/5 dark:from-white/5 to-transparent pointer-events-none" />

            <motion.div
              variants={backgroundVariants}
              className="absolute top-0 right-0 w-48 h-48 md:w-96 md:h-96 bg-indigo-500/10 rounded-full blur-3xl"
              animate={{
                scale: [1, 1.1, 1],
                opacity: [0.3, 0.6, 0.3],
              }}
              transition={{
                duration: 4,
                repeat: Number.POSITIVE_INFINITY,
                ease: "easeInOut",
              }}
            />

            <motion.div
              variants={backgroundVariants}
              className="absolute bottom-0 left-0 w-48 h-48 md:w-96 md:h-96 bg-purple-500/10 rounded-full blur-3xl"
              animate={{
                scale: [1, 1.2, 1],
                opacity: [0.2, 0.5, 0.2],
              }}
              transition={{
                duration: 5,
                repeat: Number.POSITIVE_INFINITY,
                ease: "easeInOut",
                delay: 1,
              }}
            />

            {/* Navigation Section */}
            <motion.div variants={containerVariants} className="relative z-10">
              <div className="grid grid-cols-2 md:grid-cols-4 gap-6 md:gap-12 lg:gap-20">
                {sections.map((section, index) => (
                  <NavSection key={section.title} title={section.title} links={section.links} index={index} />
                ))}
              </div>
            </motion.div>

            {/* Footer Bottom Section */}
            <motion.div
              initial={{ opacity: 0, y: 30 }}
              animate={{ opacity: 1, y: 0 }}
              transition={{ delay: 0.8, duration: 0.8, ease: "easeOut" }}
              className="flex flex-col md:flex-row justify-between items-start md:items-end relative z-10 gap-4 md:gap-6 mt-6"
            >
              <div className="flex-1">
                <motion.h1
                  initial={{ opacity: 0, x: -50 }}
                  animate={{ opacity: 1, x: 0 }}
                  transition={{ delay: 1, duration: 0.8, ease: "easeOut" }}
                  whileHover={{
                    scale: 1.02,
                    transition: { type: "spring", stiffness: 300, damping: 20 },
                  }}
                  className="text-[12vw] md:text-[10vw] lg:text-[8vw] xl:text-[6vw] leading-[0.8] font-serif bg-gradient-to-r from-slate-900 via-slate-600 to-slate-900/60 dark:from-white dark:via-slate-300 dark:to-white/60 bg-clip-text text-transparent cursor-default"
                >
                  {title}
                </motion.h1>

                <motion.div
                  initial={{ opacity: 0, width: 0 }}
                  animate={{ opacity: 1, width: "auto" }}
                  transition={{ delay: 1.2, duration: 0.6 }}
                  className="flex items-center gap-3 md:gap-4 mt-3 md:mt-4"
                >
                  <motion.div
                    className="w-8 md:w-12 h-0.5 bg-gradient-to-r from-indigo-500 to-purple-500"
                    animate={{
                      scaleX: [1, 1.2, 1],
                    }}
                    transition={{
                      duration: 2,
                      repeat: Number.POSITIVE_INFINITY,
                      ease: "easeInOut",
                    }}
                  />
                  <motion.p
                    initial={{ opacity: 0 }}
                    animate={{ opacity: 1 }}
                    transition={{ delay: 1.4, duration: 0.5 }}
                    className="text-slate-500 dark:text-slate-400 text-xs md:text-sm font-sans hover:text-slate-900 dark:hover:text-white transition-colors duration-300"
                  >
                    {subtitle}
                  </motion.p>
                </motion.div>
              </div>

              <motion.div
                initial={{ opacity: 0, x: 50 }}
                animate={{ opacity: 1, x: 0 }}
                transition={{ delay: 1.6, duration: 0.6 }}
                className="text-left md:text-right"
              >
                <motion.p
                  initial={{ opacity: 0 }}
                  animate={{ opacity: 1 }}
                  transition={{ delay: 1.8, duration: 0.5 }}
                  className="text-slate-500 dark:text-slate-400 text-xs md:text-sm mb-2 md:mb-3 hover:text-slate-900 dark:hover:text-white transition-colors duration-300"
                >
                  {copyright}
                </motion.p>

                <motion.div
                  variants={containerVariants}
                  initial="hidden"
                  animate="visible"
                  transition={{ delay: 2, staggerChildren: 0.1 }}
                  className="flex gap-2 md:gap-3"
                >
                  {social.map((s, index) => (
                    <SocialLink
                      key={s.label}
                      href={s.href}
                      label={s.label}
                      icon={s.icon}
                      index={index}
                    />
                  ))}
                </motion.div>
              </motion.div>
            </motion.div>
          </motion.div>
        </div>
      </div>
    </div>
  );
}

--- FILE: frontend-web/registry/footers/StickyRevealFooter.tsx ---

import React from 'react';
import { motion, useReducedMotion } from 'framer-motion';
import {
  FacebookIcon,
  FrameIcon,
  InstagramIcon,
  LinkedinIcon,
  YoutubeIcon,
} from 'lucide-react';
import { cn } from '../core/utils';

export interface FooterLink {
  title: string;
  href: string;
  icon?: React.ComponentType<{ className?: string }>;
}

export interface FooterLinkGroup {
  label: string;
  links: FooterLink[];
}

export interface StickyRevealFooterProps {
  brandName?: string;
  logo?: React.ReactNode;
  description?: string;
  socialLinks?: Array<{ title: string; href: string; icon: React.ElementType }>;
  footerLinkGroups?: FooterLinkGroup[];
  copyright?: string;
  className?: string;
}

const DEFAULT_SOCIALS = [
  { title: 'Facebook', href: '#', icon: FacebookIcon },
  { title: 'Instagram', href: '#', icon: InstagramIcon },
  { title: 'Youtube', href: '#', icon: YoutubeIcon },
  { title: 'LinkedIn', href: '#', icon: LinkedinIcon },
];

const DEFAULT_LINK_GROUPS: FooterLinkGroup[] = [
  {
    label: 'Product',
    links: [
      { title: 'Payments', href: '#' },
      { title: 'Cards & Issuing', href: '#' },
      { title: 'Lending & Credit', href: '#' },
      { title: 'Wealth Management', href: '#' },
      { title: 'Insurance', href: '#' },
      { title: 'Crypto Wallets', href: '#' },
      { title: 'FX & Currency Exchange', href: '#' },
      { title: 'Treasury Management', href: '#' },
    ],
  },
  {
    label: 'Solutions',
    links: [
      { title: 'Startups', href: '#' },
      { title: 'Enterprises', href: '#' },
      { title: 'Marketplaces', href: '#' },
      { title: 'Freelancers', href: '#' },
      { title: 'E-commerce', href: '#' },
      { title: 'Banks & Credit Unions', href: '#' },
      { title: 'Investment Platforms', href: '#' },
    ],
  },
  {
    label: 'Resources',
    links: [
      { title: 'Blog', href: '#' },
      { title: 'Case Studies', href: '#' },
      { title: 'Documentation', href: '#' },
      { title: 'API Reference', href: '#' },
      { title: 'Developer Tools', href: '#' },
      { title: 'Guides & Tutorials', href: '#' },
      { title: 'Whitepapers', href: '#' },
    ],
  },
  {
    label: 'Company',
    links: [
      { title: 'About Us', href: '#' },
      { title: 'Leadership', href: '#' },
      { title: 'Careers', href: '#' },
      { title: 'Press', href: '#' },
      { title: 'Sustainability', href: '#' },
      { title: 'Diversity & Inclusion', href: '#' },
      { title: 'Legal & Compliance', href: '#' },
    ],
  },
];

type AnimatedContainerProps = React.ComponentProps<typeof motion.div> & {
  children?: React.ReactNode;
  delay?: number;
};

function AnimatedContainer({
  delay = 0.1,
  children,
  ...props
}: AnimatedContainerProps) {
  const shouldReduceMotion = useReducedMotion();

  if (shouldReduceMotion) {
    return <div {...props}>{children}</div>;
  }

  return (
    <motion.div
      initial={{ filter: 'blur(4px)', translateY: -8, opacity: 0 }}
      whileInView={{ filter: 'blur(0px)', translateY: 0, opacity: 1 }}
      viewport={{ once: true }}
      transition={{ delay, duration: 0.8 }}
      {...props}
    >
      {children}
    </motion.div>
  );
}

export function StickyRevealFooter({
  brandName = "NOVA UI",
  logo = <FrameIcon className="size-8 text-indigo-600 dark:text-indigo-400" />,
  description = "Innovative fintech empowering businesses with seamless payments, lending, and financial infrastructure worldwide.",
  socialLinks = DEFAULT_SOCIALS,
  footerLinkGroups = DEFAULT_LINK_GROUPS,
  copyright,
  className,
}: StickyRevealFooterProps) {
  return (
    <footer
      className={cn('relative h-[720px] w-full bg-white dark:bg-zinc-950', className)}
      style={{ clipPath: 'polygon(0% 0, 100% 0%, 100% 100%, 0 100%)' }}
    >
      <div className="fixed bottom-0 h-[720px] w-full">
        <div className="sticky top-[calc(100vh-720px)] h-full overflow-y-auto overflow-x-hidden">
          <div className="relative flex size-full flex-col justify-between gap-5 border-t border-slate-200 dark:border-zinc-800 px-4 py-8 md:px-12 bg-white dark:bg-zinc-950 text-slate-900 dark:text-white">
            
            {/* Background Glows */}
            <div
              aria-hidden
              className="absolute inset-0 isolate z-0 overflow-hidden pointer-events-none"
            >
              <div className="absolute top-0 left-0 h-[80rem] w-[35rem] -translate-y-[22rem] -rotate-45 rounded-full bg-[radial-gradient(68.54%_68.72%_at_55.02%_31.46%,rgba(0,0,0,0.06)_0,rgba(0,0,0,0.02)_50%,transparent_80%)] dark:bg-[radial-gradient(68.54%_68.72%_at_55.02%_31.46%,rgba(255,255,255,0.06)_0,rgba(255,255,255,0.02)_50%,transparent_80%)]" />
              <div className="absolute top-0 left-0 h-[80rem] w-[15rem] translate-x-[5%] -translate-y-[50%] -rotate-45 rounded-full bg-[radial-gradient(50%_50%_at_50%_50%,rgba(0,0,0,0.04)_0,rgba(0,0,0,0.01)_80%,transparent_100%)] dark:bg-[radial-gradient(50%_50%_at_50%_50%,rgba(255,255,255,0.04)_0,rgba(255,255,255,0.01)_80%,transparent_100%)]" />
              <div className="absolute top-0 left-0 h-[80rem] w-[15rem] -translate-y-[22rem] -rotate-45 rounded-full bg-[radial-gradient(50%_50%_at_50%_50%,rgba(0,0,0,0.04)_0,rgba(0,0,0,0.01)_80%,transparent_100%)] dark:bg-[radial-gradient(50%_50%_at_50%_50%,rgba(255,255,255,0.04)_0,rgba(255,255,255,0.01)_80%,transparent_100%)]" />
            </div>

            {/* Main Content */}
            <div className="mt-10 flex flex-col gap-8 md:flex-row xl:mt-0 relative z-10">
              <AnimatedContainer className="w-full max-w-sm min-w-[200px] space-y-4">
                <div className="flex items-center gap-2">
                  {logo}
                  <span className="font-bold text-xl">{brandName}</span>
                </div>
                <p className="text-slate-500 dark:text-slate-400 mt-8 text-sm md:mt-0 leading-relaxed">
                  {description}
                </p>
                <div className="flex gap-2 pt-4">
                  {socialLinks.map((link) => {
                    const Icon = link.icon;
                    return (
                      <a
                        key={link.title}
                        href={link.href}
                        title={link.title}
                        className="flex h-9 w-9 items-center justify-center rounded-md border border-slate-200 dark:border-zinc-800 bg-transparent hover:bg-slate-100 dark:hover:bg-zinc-800 transition-colors text-slate-600 dark:text-slate-300 hover:text-slate-900 dark:hover:text-white"
                      >
                        <Icon className="h-4 w-4" />
                        <span className="sr-only">{link.title}</span>
                      </a>
                    );
                  })}
                </div>
              </AnimatedContainer>

              <div className="flex-1 grid grid-cols-2 md:grid-cols-4 gap-8">
                {footerLinkGroups.map((group, index) => (
                  <AnimatedContainer
                    key={group.label}
                    delay={0.1 + index * 0.1}
                    className="w-full"
                  >
                    <div className="mb-10 md:mb-0">
                      <h3 className="text-sm font-semibold uppercase tracking-wider text-slate-900 dark:text-white">
                        {group.label}
                      </h3>
                      <ul className="text-slate-500 dark:text-slate-400 mt-4 space-y-3 text-sm">
                        {group.links.map((link) => (
                          <li key={link.title}>
                            <a
                              href={link.href}
                              className="hover:text-indigo-600 dark:hover:text-indigo-400 inline-flex items-center transition-colors duration-300 font-medium"
                            >
                              {link.icon && <link.icon className="mr-2 h-4 w-4" />}
                              {link.title}
                            </a>
                          </li>
                        ))}
                      </ul>
                    </div>
                  </AnimatedContainer>
                ))}
              </div>
            </div>

            <div className="relative z-10 text-slate-500 dark:text-slate-400 flex flex-col items-center justify-between gap-4 border-t border-slate-200 dark:border-zinc-800 pt-6 mt-8 text-sm md:flex-row">
              <p>{copyright || `© ${new Date().getFullYear()} ${brandName}. All rights reserved.`}</p>
              <div className="flex gap-6">
                <a href="#" className="hover:text-slate-900 dark:hover:text-white transition-colors">Privacy Policy</a>
                <a href="#" className="hover:text-slate-900 dark:hover:text-white transition-colors">Terms of Service</a>
              </div>
            </div>

          </div>
        </div>
      </div>
    </footer>
  );
}

--- FILE: frontend-web/registry/footers/TapedFooter.tsx ---

import React from "react";
import { Linkedin, Twitter } from "lucide-react";
import { cn } from "../core/utils";

export interface FooterLink {
  label: string;
  href: string;
  isSoon?: boolean;
}

export interface FooterColumn {
  title: string;
  isSoon?: boolean;
  links: FooterLink[];
}

export interface TapedFooterProps {
  brandName?: string;
  description?: string;
  columns?: FooterColumn[];
  legalLinks?: Array<{ label: string; href: string }>;
  socialLinks?: Array<{ icon: React.ReactNode; href: string; label: string }>;
  className?: string;
}

const TAPE_SVG = (
  <svg xmlns="http://www.w3.org/2000/svg" width="95" height="80" viewBox="0 0 95 80" fill="none">
    <path d="M1 45L70.282 5L88.282 36.1769L19 76.1769L1 45Z" fill="currentColor" className="text-slate-900 dark:text-slate-100" />
    <path d="M69.6829 39.997C74.772 36.9233 80.2799 35.022 85.4464 32.0415C85.5584 31.9769 85.6703 31.912 85.782 31.8468L83.9519 38.6769C80.2833 32.3886 75.7064 26.4975 72.2275 20.0846C70.0007 15.9783 67.7966 11.8425 65.6183 7.69261L72.9746 9.66373C70.566 10.9281 68.1526 12.1837 65.7375 13.4301C59.1543 16.828 52.5477 20.1634 45.9059 23.4675C39.2779 26.7637 32.6138 30.0293 25.946 33.2683C21.417 35.4683 16.8774 37.6611 12.3408 39.8468C10.3494 40.8065 8.36335 41.7623 6.37228 42.7203C4.88674 43.4348 3.40117 44.1492 1.91563 44.8637C1.70897 44.9628 1.48389 45.0108 1.28779 44.994C1.0916 44.977 0.940536 44.8975 0.866099 44.7681C0.791689 44.6386 0.798739 44.4674 0.882816 44.289C0.966978 44.111 1.12195 43.9408 1.31146 43.8119C2.68692 42.8791 4.06239 41.9462 5.43785 41.0134C6.96571 39.9774 8.49068 38.9427 10.0185 37.9078C10.5758 38.2934 11.1526 38.4968 11.9006 38.3019C12.2823 38.2024 12.7844 37.9628 13.0812 37.66C13.3477 37.388 13.4958 37.092 13.6361 36.8103C13.7828 36.5157 13.922 36.236 14.1819 36.0157C14.6227 35.6416 14.9608 35.1461 15.3159 34.6256C15.4451 34.4362 15.5766 34.2432 15.7162 34.0517C17.1755 33.0653 18.6355 32.0797 20.0958 31.0952C20.7161 30.8123 21.2829 30.546 21.7287 30.2596C22.1286 30.0027 22.4405 29.6732 22.7349 29.3173C22.9611 29.1651 23.1873 29.0128 23.4135 28.8606C24.8734 27.8785 26.3349 26.8977 27.7969 25.9178C29.0653 25.3742 30.3884 24.7936 32.0404 23.9203C32.7524 23.544 33.4842 23.2235 34.1877 22.9153C35.2267 22.4601 36.204 22.0318 36.9653 21.4906C37.4742 21.1289 38.0837 20.8769 38.6916 20.6256C39.507 20.2886 40.3209 19.9521 40.8884 19.3523C41.2452 18.9751 41.5509 18.5904 41.8339 18.234C42.2841 17.6669 42.6773 17.1712 43.1308 16.8909C43.9827 16.3643 44.6366 15.763 45.2128 15.2329C45.9058 14.5954 46.4871 14.0607 47.1661 13.8832C47.2691 13.8563 47.3895 13.83 47.5253 13.8008C48.2409 13.6467 49.3854 13.4004 50.6721 12.4297C51.1302 12.084 51.5022 11.6584 51.8663 11.2413C52.3964 10.634 52.9113 10.0444 53.6546 9.74536C53.7656 9.70072 53.9081 9.70004 54.0379 9.69961C54.203 9.69906 54.3472 9.69852 54.3802 9.60751C54.4771 9.34055 54.6749 8.99305 54.8896 8.61527C55.0473 8.33772 55.2144 8.04348 55.3576 7.75325C57.0866 6.63773 58.8181 5.52571 60.5527 4.41789C61.3473 3.91034 62.1427 3.40353 62.9389 2.89753C63.4939 2.89483 64.0449 2.86301 64.5895 2.76514C65.3015 2.63711 66.1031 2.26098 67.1366 1.7766C67.4515 1.62902 67.788 1.47135 68.1502 1.30751C70.2985 0.211054 72.8781 0.719848 73.9745 2.86814C74.2063 3.38051 74.4505 3.94413 74.6959 4.57024C75.4715 6.54841 76.6121 8.38172 77.451 9.4943C77.6285 9.72958 77.8088 9.965 78.0022 10.2164C78.7359 11.1701 79.6521 12.3598 81.2553 14.6987C82.7718 16.9111 83.9554 18.8538 84.8446 20.3132C85.2985 21.0581 85.6753 21.6776 85.981 22.1424C86.5039 22.9378 87.13 23.9238 87.7583 24.9138C88.7415 26.463 89.7306 28.0221 90.3417 28.8752C90.5592 29.1788 90.7935 29.4941 91.046 29.8348C91.6954 30.711 92.4701 31.7564 93.4198 33.2106C94.9454 36.1998 94.2374 39.789 91.2483 41.3146C91.1356 41.3882 91.0205 41.4628 90.9029 41.5385C89.1849 42.6436 88.0561 43.2181 86.8458 43.7492C86.3539 43.965 85.8291 43.9984 85.2883 44.0321C84.5207 44.08 83.72 44.1298 82.9316 44.7081C82.7476 44.8431 82.5657 45.0123 82.3757 45.1895C82.0265 45.5149 81.649 45.8671 81.1774 46.0805C81.0129 46.1549 80.8442 46.1792 80.6788 46.2029C80.4969 46.229 80.3186 46.2548 80.1526 46.3463C79.5326 46.6883 78.9438 47.0464 78.4208 47.3647C77.7463 47.7753 77.1806 48.1194 76.7972 48.2768C76.1137 48.5573 75.4647 49.0342 74.8076 49.5175C74.3056 49.8867 73.7989 50.2601 73.2678 50.5517C71.7504 51.3848 69.7735 52.7209 67.7901 54.1904C67.0396 54.7464 66.2862 55.0138 65.3207 55.3561C64.7201 55.569 64.0372 55.8105 63.2221 56.1693C62.76 56.3726 62.4565 56.6971 62.1754 56.9973C61.9165 57.2738 61.6763 57.5299 61.3489 57.6526C61.0599 57.7608 60.7846 57.6688 60.5231 57.5815C60.2321 57.4843 59.9583 57.3929 59.702 57.5895C59.5657 57.6942 59.4406 57.8919 59.2918 58.1269C59.233 58.2198 59.1699 58.3187 59.1013 58.4201C59.0842 58.3791 59.0657 58.3442 59.0508 58.3184C58.9457 58.1356 58.6072 58.2028 58.2752 58.2689C58.1427 58.2953 58.0108 58.3219 57.8957 58.3319C57.4719 58.3686 56.8253 58.708 56.3466 58.9941C56.144 59.1151 55.9262 59.1653 55.672 59.224C55.4463 59.2761 55.1919 59.3347 54.894 59.4553C54.7241 59.5242 54.5728 59.541 54.4474 59.5545C54.3567 59.5642 54.2794 59.5724 54.2182 59.5982C54.1652 59.6205 54.1556 59.6959 54.1448 59.7807C54.137 59.8418 54.1285 59.908 54.1028 59.9628C54.0412 60.0939 53.9214 60.1919 53.8153 60.2225C53.7663 60.2366 53.7206 60.2358 53.6753 60.2349C53.6225 60.234 53.5698 60.2326 53.5113 60.2553C53.2429 60.3595 53.0377 60.5575 52.8246 60.7633C52.5903 60.9894 52.3457 61.225 51.9975 61.3556C51.8879 61.3967 51.7593 61.42 51.6348 61.4426C51.5045 61.4661 51.378 61.4893 51.2831 61.5308C50.8977 61.6994 50.6327 62.0265 50.389 62.3273C50.2269 62.5274 50.0737 62.716 49.9013 62.8385C49.5852 63.063 49.4962 63.3233 49.4307 63.5155C49.3967 63.615 49.3692 63.6966 49.3191 63.7453C49.2628 63.772 49.2053 63.7983 49.1487 63.8235C49.093 63.8403 49.0355 63.8576 48.9902 63.8888C48.9867 63.8912 48.9836 63.8939 48.9802 63.8963C48.6593 64.0309 48.3345 64.1466 48.0116 64.2613C47.2865 64.519 46.5701 64.7733 45.9244 65.2359C45.7853 65.3355 45.6724 65.487 45.5575 65.641C45.4167 65.8297 45.2727 66.0228 45.0741 66.1295C44.6008 66.3839 44.0696 66.5483 43.5464 66.7102C42.7594 66.9536 41.9904 67.1916 41.4633 67.722C41.2894 67.897 41.142 68.1064 40.9944 68.3169C40.9122 68.4342 40.8296 68.5523 40.7422 68.6643C40.7169 68.5646 40.6833 68.4767 40.652 68.3947C40.5875 68.2257 40.5324 68.081 40.5769 67.9054C40.6823 67.4901 40.7644 66.9549 40.5779 66.7069C40.5272 66.6396 40.4878 66.5548 40.4487 66.4691C40.3507 66.254 40.2505 66.0344 39.9558 66.0791C39.7572 66.1092 39.2569 66.204 39.082 66.5127C39.044 66.5799 39.0478 66.6675 39.0518 66.7648C39.0592 66.9397 39.0675 67.1471 38.838 67.329C38.7994 67.3596 38.7566 67.3917 38.7122 67.4244C38.5349 67.5546 38.3363 67.7 38.3194 67.8538C38.3 68.0309 38.4017 68.1621 38.5204 68.3152C38.6749 68.5145 38.8585 68.7512 38.8407 69.1745C38.8371 69.2583 38.7749 69.3221 38.728 69.3705C38.695 69.4045 38.6699 69.4309 38.6775 69.4511C38.6864 69.4742 38.7244 69.511 38.7726 69.5575C38.9428 69.7213 39.2396 70.008 38.8369 70.2599C38.7279 70.328 38.5912 70.3851 38.4686 70.4362C38.2879 70.5115 38.1379 70.5742 38.1516 70.6412C38.1569 70.6665 38.1652 70.6925 38.175 70.7189C38.0372 70.7894 37.8994 70.8599 37.7617 70.9305C37.5513 70.9626 37.3136 71.1075 37.017 71.2886C36.9451 71.3326 36.8691 71.3787 36.7896 71.4258C36.5175 71.5644 36.2453 71.7032 35.973 71.8416C35.7472 71.9341 35.4976 72.0165 35.2199 72.0788C34.6635 72.2038 34.1132 72.1978 33.5754 72.1917C33.3488 72.1891 33.1241 72.1864 32.9021 72.1937C32.9618 72.1444 33.0138 72.0968 33.0493 72.0522C33.292 71.7467 33.2773 71.4299 33.2636 71.1383C33.2545 70.9444 33.246 70.7614 33.3141 70.6009C33.4387 70.3069 33.3041 70.125 33.2048 69.9903C33.1532 69.9205 33.1115 69.863 33.1199 69.8097C33.1268 69.7669 33.1736 69.7216 33.2219 69.6748C33.264 69.6341 33.3074 69.5918 33.3263 69.5495C33.5565 69.0365 33.3423 68.9396 33.0306 68.7984C32.8587 68.7205 32.6575 68.6289 32.4843 68.4469C32.3112 68.2483 32.2881 68.1742 32.4435 67.9656C32.2185 67.9481 31.9934 67.9305 31.7683 67.913C31.7092 67.9567 31.7012 68.0535 31.7002 68.2073C31.6983 68.482 31.3496 68.7833 31.0772 69.0187C30.951 69.1277 30.8413 69.2227 30.7898 69.2944C30.5158 69.6756 30.7581 69.8463 30.9714 69.9966C31.0888 70.0793 31.1972 70.1559 31.206 70.2579C31.2099 70.3014 31.2524 70.3223 31.2955 70.3438C31.3288 70.3604 31.3629 70.3772 31.3798 70.4049C31.5026 70.6062 31.3709 70.8843 31.2487 71.1425C31.1788 71.2903 31.1123 71.4317 31.098 71.5486C31.0936 71.5842 31.0933 71.6181 31.0936 71.6508C31.0939 71.6984 31.0938 71.7441 31.0797 71.7913C31.0475 71.899 30.9277 72.0281 30.7962 72.1694C30.7288 72.2419 30.6585 72.3175 30.5954 72.3951C30.5137 72.4957 30.5226 72.5982 30.5314 72.7056C30.5377 72.7814 30.5436 72.8599 30.5186 72.9418C30.4732 73.0899 30.294 73.2374 30.1276 73.3743C30.0552 73.434 29.9853 73.492 29.9298 73.5468C29.9072 73.5691 29.9025 73.5904 29.9107 73.611C29.6455 73.8494 29.3946 74.0812 29.1507 74.3073C27.928 75.4406 26.8699 76.422 24.9338 77.2712C24.5678 77.4317 24.2027 77.6527 23.847 77.8987C22.8466 78.3902 21.8448 78.8802 20.8427 79.3685C18.9858 80.3162 16.7561 79.8764 15.8084 78.0196C15.6912 77.779 15.5741 77.5385 15.4571 77.2979C15.5046 76.9554 15.4922 76.5771 15.4159 76.1649C15.2724 75.3908 14.9393 74.7016 14.5464 73.8883C14.2558 73.287 13.9326 72.6178 13.6287 71.7959C13.1181 70.415 12.555 69.0197 11.8089 67.5091C11.066 66.0051 10.1771 64.3053 9.52376 63.1169C9.16763 62.469 8.944 61.7017 8.73537 60.9866C8.44191 59.9808 8.17835 59.0784 7.61958 58.7572C7.44108 58.6546 7.19967 58.5953 6.96499 58.5373C6.79786 58.496 6.63406 58.4547 6.49825 58.4001C6.36908 58.1203 6.23948 57.8403 6.11042 57.5602C6.02416 56.9799 5.8002 56.13 5.18227 55.5402C5.04958 55.251 4.91666 54.9617 4.78958 54.6817C4.50993 54.0719 4.23819 53.4743 3.96388 52.8713C3.87458 52.6744 3.78424 52.4755 3.69373 52.2762C3.69291 52.2743 3.69208 52.2724 3.69126 52.2705C3.50907 51.8692 3.32548 51.4649 3.14577 51.0668C3.06874 50.8964 2.99171 50.7259 2.91467 50.5554C2.71886 50.1222 2.52147 49.686 2.32862 49.2567C2.22665 49.0294 2.12332 48.8001 2.02011 48.5702C1.85267 48.1974 1.68389 47.8217 1.5164 47.4477C1.2455 46.843 0.976827 46.2405 0.707979 45.6366C0.664122 45.5378 0.643515 45.4304 0.652618 45.3375C0.661818 45.2445 0.699512 45.1734 0.760479 45.1383C0.821487 45.1032 0.902318 45.1064 0.987373 45.1452C1.07223 45.1841 1.15414 45.256 1.21749 45.3435C1.60461 45.8796 1.99066 46.4153 2.37757 46.9536C2.6167 47.2863 2.85707 47.6205 3.09529 47.9526C3.24216 48.1573 3.38828 48.3616 3.53359 48.564C3.80784 48.9465 4.08653 49.3367 4.3626 49.7236C4.47129 49.8757 4.57998 50.0279 4.68867 50.1801C4.94315 50.5364 5.20093 50.8992 5.4569 51.2592C5.45844 51.2614 5.45998 51.2636 5.46152 51.2658C5.58745 51.4429 5.71324 51.6197 5.83773 51.7946C6.22127 52.3348 6.60139 52.8703 6.98805 53.4185C7.18905 53.7011 7.39667 53.9966 7.60327 54.2896C7.7183 54.4528 7.83322 54.6155 7.94616 54.7753C8.00768 54.8628 8.06986 54.9515 8.13237 55.0408C9.57264 57.0858 10.9968 59.12 12.4247 61.1784C13.848 63.2287 15.2661 65.2871 16.6737 67.3431C18.0842 69.4042 19.4854 71.4657 20.8812 73.5327C21.1336 73.9063 21.3858 74.2801 21.6379 74.6539L17.477 73.539C30.2295 64.9403 43.1287 56.4797 56.1947 48.2951C58.1128 47.093 60.086 45.8684 62.0158 44.6777C63.9671 43.4745 65.8814 42.3014 67.8458 41.1091C68.4422 40.7466 69.0543 40.3763 69.6829 39.997Z" fill="currentColor" className="text-slate-900 dark:text-slate-100" />
  </svg>
);

export function TapedFooter({
  brandName = "ActivationLed",
  description = "Behavioral Designed Activation Journeys for PLG SaaS to lift Aha! moments by 23%.",
  columns = [
    {
      title: "Resources",
      links: [
        { label: "Freebies & Audits", href: "/resources/freebies" },
        { label: "Tools", href: "/resources/tools" },
        { label: "Psychology", href: "/resources/behavior-principles" },
        { label: "Blog", href: "/resources/blog", isSoon: true },
        { label: "Components", href: "/resources/components", isSoon: true },
        { label: "Playbooks", href: "/resources/playbooks", isSoon: true },
      ]
    },
    {
      title: "Company",
      isSoon: true,
      links: [
        { label: "Mission", href: "/company/mission" },
        { label: "SaaS Ecosystem", href: "/company/ecosystem" },
        { label: "Affiliate Program", href: "/company/affiliates" },
        { label: "Referral Program", href: "/company/referrals" },
        { label: "Partners", href: "/company/partners" },
        { label: "About Us", href: "/company/about-us" },
      ]
    },
    {
      title: "Compare",
      isSoon: true,
      links: [
        { label: "DaaS", href: "/legal/privacy-policy" },
        { label: "PLG Boutique", href: "/legal/tos" },
        { label: "ProductLed", href: "/legal/tos" },
        { label: "Vulnabyl", href: "/legal/tos" },
        { label: "GrowthMates", href: "/pricing" },
        { label: "DelightPath", href: "/pricing" },
      ]
    }
  ],
  legalLinks = [
    { label: "Privacy Policy", href: "/legal/privacy-policy" },
    { label: "Terms & Co", href: "/legal/tos" },
    { label: "Radu Popescu", href: "https://www.linkedin.com/in/radu-a-popescu/" },
  ],
  socialLinks = [
    { icon: <Linkedin className="w-5 h-5 text-slate-500 hover:text-slate-900 dark:hover:text-white transition-colors" />, href: "https://www.linkedin.com/in/radu-a-popescu/", label: "LinkedIn" },
    { icon: <Twitter className="w-5 h-5 text-slate-500 hover:text-slate-900 dark:hover:text-white transition-colors" />, href: "https://x.com/activation_guy", label: "Twitter" }
  ],
  className
}: TapedFooterProps) {
  const currentYear = new Date().getFullYear();

  return (
   <footer className={cn("my-8 px-4 max-w-5xl mx-auto text-slate-900 dark:text-white", className)}>
      <div className="relative bg-white dark:bg-zinc-950 border border-slate-200 dark:border-zinc-800 rounded-3xl max-w-5xl mx-auto px-4 py-10 flex flex-col md:flex-row justify-between items-center gap-6 shadow-sm">
        <div className="hidden md:block absolute -top-4 -left-8 w-[80px] h-[36px] scale-75">
          {TAPE_SVG}
        </div>
        <div className="hidden md:block absolute -top-4 -right-8 rotate-90 w-[80px] h-[36px] scale-75">
          {TAPE_SVG}
        </div>
        <div className="flex flex-col md:flex-row items-start justify-between gap-4 md:gap-10 px-2 md:px-8 flex-1 w-full">
          <div className='flex flex-col items-start gap-2 max-w-xs'>
            <a
              href="/"
              className="flex flex-row gap-1 items-center justify-start text-2xl font-extrabold text-slate-900 dark:text-white"
            >
              {brandName}
            </a>
            <p className='text-slate-500 dark:text-slate-400 font-medium text-base w-full'>
              {description}
            </p>
          </div>

          <div className='flex flex-col md:mx-4 md:flex-row gap-8 md:gap-16 items-start md:items-start'>
            {columns.map((col, idx) => (
              <div key={idx} className={cn("flex flex-col gap-2 md:gap-4", idx > 0 && "hidden md:flex")}>
                <h4 className='uppercase text-sm text-slate-900 dark:text-white font-semibold flex items-center'>
                  {col.title}
                  {col.isSoon && <span className='inline-flex ml-2 py-0.5 px-2 bg-slate-100 dark:bg-zinc-800 text-xs rounded-xl rotate-3 text-slate-500'>soon</span>}
                </h4>
                <div className="flex flex-wrap md:flex-col gap-2.5 text-sm items-start">
                  {col.links.map((link, lIdx) => (
                    <a key={lIdx} className={cn('text-slate-500 dark:text-slate-400 whitespace-nowrap font-medium hover:text-slate-900 dark:hover:text-white transition-colors flex items-center', link.isSoon && 'pointer-events-none opacity-60')} href={link.href}>
                      {link.label}
                      {link.isSoon && <span className={cn('inline-flex ml-2 py-0.5 px-2 bg-slate-100 dark:bg-zinc-800 text-xs rounded-xl', lIdx % 2 === 0 ? '-rotate-3' : 'rotate-3')}>soon</span>}
                    </a>
                  ))}
                </div>
              </div>
            ))}
          </div>
        </div>
      </div>
      
      <div className="my-6 px-4 md:px-8 flex flex-col md:flex-row justify-between items-start md:items-center gap-4 text-sm text-slate-500 dark:text-slate-400 font-medium">
        <div className="flex flex-col sm:flex-row gap-2 sm:gap-8 items-start sm:items-center">
          <p className="whitespace-nowrap">
            ©{currentYear} {brandName}. All rights reserved.
          </p>
          <div className="flex flex-row gap-4">
            {legalLinks.map((link, idx) => (
              <a key={idx} href={link.href} className="hover:text-slate-900 dark:hover:text-white transition-colors">{link.label}</a>
            ))}
          </div>
        </div>

        <div className="flex gap-4 items-center mt-4 md:mt-0">
          {socialLinks.map((social, idx) => (
            <a
              key={idx}
              href={social.href}
              target="_blank"
              rel="nofollow noopener"
              aria-label={social.label}
            >
              {social.icon}
            </a>
          ))}
        </div>
      </div>
    </footer>
  );
}

--- FILE: frontend-web/registry/footers/TerminalFooter.tsx ---

import React from "react";
import { Github, Twitter, Linkedin, ArrowRight, Hexagon } from "lucide-react";
import { cn } from "../core/utils";

export interface FooterLink {
  title: string;
  href: string;
}

export interface FooterSection {
  title: string;
  links: FooterLink[];
}

export interface SocialLink {
  icon: React.ElementType;
  href: string;
  label: string;
}

export interface TerminalFooterProps {
  brandName?: string;
  logo?: React.ReactNode;
  description?: string;
  inputPlaceholder?: string;
  onSubscribe?: (email: string) => void;
  sections?: FooterSection[];
  publishText?: string;
  statusText?: string;
  socialLinks?: SocialLink[];
  className?: string;
}

const DEFAULT_SECTIONS: FooterSection[] = [
  {
    title: "Product",
    links: [
      { title: "Components", href: "#" },
      { title: "Templates", href: "#" },
      { title: "Pricing", href: "#" },
      { title: "Features", href: "#" },
    ],
  },
  {
    title: "Company",
    links: [
      { title: "About", href: "#" },
      { title: "Careers", href: "#" },
      { title: "Legal", href: "#" },
      { title: "Blog", href: "#" },
    ],
  },
  {
    title: "Connect",
    links: [
      { title: "Twitter", href: "#" },
      { title: "GitHub", href: "#" },
      { title: "Discord", href: "#" },
      { title: "Whatsapp", href: "#" },
    ],
  },
];

const DEFAULT_SOCIAL_LINKS: SocialLink[] = [
  { icon: Github, href: "#", label: "GitHub" },
  { icon: Twitter, href: "#", label: "Twitter" },
  { icon: Linkedin, href: "#", label: "LinkedIn" },
];

export function TerminalFooter({
  brandName = "SEEKER",
  logo = <Hexagon className="text-cyan-600 dark:text-cyan-500 fill-cyan-600/10 dark:fill-cyan-500/10 animate-pulse" size={24} />,
  description = "Next-generation interface primitives for the modern web. Built for speed, designed for awe.",
  inputPlaceholder = "Enter your signal...",
  onSubscribe,
  sections = DEFAULT_SECTIONS,
  publishText = "// PUBLISHED_BY_NOVA",
  statusText = "All Systems Normal",
  socialLinks = DEFAULT_SOCIALS,
  className,
}: TerminalFooterProps) {
  
  const handleSubscribe = (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    const formData = new FormData(e.currentTarget);
    const email = formData.get("email") as string;
    if (email && onSubscribe) {
      onSubscribe(email);
    }
  };

  return (
    <footer className={cn("w-full bg-white dark:bg-zinc-950 border-t border-slate-200 dark:border-zinc-800 pt-16 pb-8 relative overflow-hidden", className)}>
      
      {/* Background Tech Pattern */}
      <div className="absolute inset-0 bg-[linear-gradient(rgba(0,0,0,0.03)_1px,transparent_1px),linear-gradient(90deg,rgba(0,0,0,0.03)_1px,transparent_1px)] dark:bg-[linear-gradient(rgba(255,255,255,0.02)_1px,transparent_1px),linear-gradient(90deg,rgba(255,255,255,0.02)_1px,transparent_1px)] bg-[size:40px_40px] [mask-image:radial-gradient(circle_at_center,black,transparent_80%)] pointer-events-none" />

      <div className="max-w-7xl mx-auto px-6 relative z-10">
        <div className="grid grid-cols-1 md:grid-cols-12 gap-12 md:gap-8 mb-16">
          
          {/* Brand Column */}
          <div className="col-span-1 md:col-span-5 flex flex-col gap-6">
            <div className="flex items-center gap-2">
                {logo}
                <h2 className="text-2xl font-bold tracking-tighter text-slate-900 dark:text-white">
                    {brandName}
                </h2>
            </div>
            <p className="text-sm text-slate-500 dark:text-slate-400 leading-relaxed max-w-sm">
                {description}
            </p>
            
            {/* Minimal Input */}
            <form onSubmit={handleSubscribe} className="flex items-center gap-2 mt-2 group">
                <div className="relative flex-1 max-w-xs">
                    <input 
                        name="email"
                        type="email" 
                        required
                        placeholder={inputPlaceholder} 
                        className="w-full bg-slate-100 dark:bg-white/5 border border-slate-300 dark:border-zinc-800/80 rounded-lg px-4 py-2.5 text-sm text-slate-900 dark:text-white placeholder:text-slate-400 dark:placeholder:text-zinc-500 focus:outline-none focus:border-cyan-600/50 dark:focus:border-cyan-500/50 transition-colors"
                    />
                </div>
                <button type="submit" className="p-2.5 bg-cyan-600 dark:bg-cyan-500 rounded-lg text-white dark:text-zinc-950 hover:bg-cyan-700 dark:hover:bg-cyan-400 transition-colors focus:outline-none focus:ring-2 focus:ring-cyan-500 focus:ring-offset-2 dark:focus:ring-offset-zinc-950">
                    <ArrowRight size={18} />
                </button>
            </form>
          </div>

          {/* Links Columns */}
          {sections.map((section, idx) => (
             <div key={idx} className="col-span-6 md:col-span-2 flex flex-col gap-4">
                <h4 className="text-xs font-mono font-bold text-slate-900 dark:text-white uppercase tracking-widest">
                    {section.title}
                </h4>
                <ul className="flex flex-col gap-3">
                    {section.links.map((link) => (
                        <li key={link.title}>
                            <a href={link.href} className="text-sm font-mono text-slate-500 dark:text-slate-400 hover:text-cyan-600 dark:hover:text-cyan-400 transition-colors flex items-center gap-2 group w-fit">
                                <span className="w-2 h-2 rounded-full bg-slate-200 dark:bg-zinc-800 group-hover:bg-cyan-600 dark:group-hover:bg-cyan-400 transition-all group-hover:w-4 duration-200" />
                                {link.title}
                            </a>
                        </li>
                    ))}
                </ul>
             </div>
          ))}
        </div>

        {/* Bottom Bar */}
        <div className="flex flex-col md:flex-row items-center justify-between gap-6 pt-8 border-t border-slate-200 dark:border-zinc-800">
            <p className="text-xs text-slate-500 dark:text-slate-500 font-mono font-medium tracking-tight">
                {publishText}
            </p>

            <div className="flex items-center gap-6">
                 {/* Socials */}
                 <div className="flex gap-4 border-r border-slate-200 dark:border-zinc-800 pr-6 mr-2">
                    {socialLinks.map((social, i) => {
                        const Icon = social.icon;
                        return (
                          <a key={i} href={social.href} aria-label={social.label} className="text-slate-400 hover:text-slate-900 dark:text-slate-500 dark:hover:text-white transition-colors">
                              <Icon size={18} />
                          </a>
                        )
                    })}
                 </div>
                 
                 {/* Status */}
                 <div className="flex items-center gap-2 px-3 py-1 rounded-full bg-emerald-100 dark:bg-emerald-500/10 border border-emerald-200 dark:border-emerald-500/20">
                    <div className="w-1.5 h-1.5 rounded-full bg-emerald-600 dark:bg-emerald-500 animate-pulse" />
                    <span className="text-[10px] uppercase font-bold text-emerald-700 dark:text-emerald-500 tracking-wider">{statusText}</span>
                 </div>
            </div>
        </div>
      </div>
    </footer>
  )
}

--- FILE: frontend-web/registry/footers/ThemeToggleFooter.tsx ---

import React, { useState, useEffect } from "react";
import { Sun, Moon, ArrowUp } from "lucide-react";
import { cn } from "../core/utils";

function handleScrollTop() {
  window.scroll({
    top: 0,
    behavior: "smooth",
  });
}

export interface ThemeToggleFooterProps extends React.HTMLAttributes<HTMLDivElement> {}

export function ThemeToggleFooter({ className, ...props }: ThemeToggleFooterProps) {
  const [isDark, setIsDark] = useState(false);

  useEffect(() => {
    if (typeof window !== "undefined") {
      setIsDark(document.documentElement.classList.contains("dark"));
    }
  }, []);

  const setTheme = (theme: "light" | "dark") => {
    if (theme === "dark") {
      document.documentElement.classList.add("dark");
      setIsDark(true);
    } else {
      document.documentElement.classList.remove("dark");
      setIsDark(false);
    }
  };

  return (
    <div className={cn("flex items-center justify-center py-8", className)} {...props}>
      <div className="flex items-center rounded-full border border-dotted border-slate-300 dark:border-zinc-800 p-1">
        <button
          onClick={() => setTheme("light")}
          className={cn(
            "mr-3 rounded-full p-2 transition-colors focus:outline-none",
            !isDark
              ? "bg-black text-white dark:bg-white dark:text-black"
              : "bg-transparent text-slate-500 hover:text-slate-900 dark:text-slate-400 dark:hover:text-white"
          )}
        >
          <Sun className="h-4 w-4" strokeWidth={2} />
          <span className="sr-only">Light Theme</span>
        </button>

        <button 
          type="button" 
          onClick={handleScrollTop}
          className="p-2 text-slate-400 hover:text-slate-900 dark:text-slate-500 dark:hover:text-white transition-colors focus:outline-none"
        >
          <ArrowUp className="h-4 w-4" strokeWidth={2} />
          <span className="sr-only">Top</span>
        </button>

        <button
          onClick={() => setTheme("dark")}
          className={cn(
            "ml-3 rounded-full p-2 transition-colors focus:outline-none",
            isDark
              ? "bg-slate-900 text-white dark:bg-zinc-800 dark:text-white"
              : "bg-transparent text-slate-500 hover:text-slate-900"
          )}
        >
          <Moon className="h-4 w-4" strokeWidth={2} />
          <span className="sr-only">Dark Theme</span>
        </button>
      </div>
    </div>
  );
}

--- FILE: frontend-web/registry/footers/WordmarkFooter.tsx ---

import React, { useState, useRef, useEffect, useCallback } from "react";
import { motion } from "framer-motion";
import { cn } from "../core/utils";

export interface WordmarkFooterProps {
  brandName?: string;
  href?: string;
  className?: string;
}

// Radial shine gradient — follows cursor
function makeShine(x: number, y: number): string {
  return `radial-gradient(ellipse 100% 100% at ${x.toFixed(1)}% ${y.toFixed(1)}%, rgba(255,255,255,.88) 0%, rgba(255,255,255,.62) 24%, rgba(255,255,255,.34) 50%, rgba(255,255,255,.16) 100%)`;
}

// Vertical mask — dims bottom for the half-cut, independent of shine
const VMASK = "linear-gradient(to bottom, black 0%, black 38%, rgba(0,0,0,.55) 76%, rgba(0,0,0,.30) 100%)";

export function WordmarkFooter({
  brandName = "NOVA UI",
  href = "/",
  className,
}: WordmarkFooterProps) {
  const [inView, setInView] = useState(false);
  const sectionRef = useRef<HTMLAnchorElement>(null);
  const textRef = useRef<HTMLSpanElement>(null);

  // Cursor-tracking state — refs only, zero re-renders
  const hovering = useRef(false);
  const curX = useRef(50);
  const curY = useRef(30);
  const tgtX = useRef(50);
  const tgtY = useRef(30);
  const raf = useRef(0);

  // Per-frame lerp loop — direct DOM writes
  const paint = useCallback(() => {
    curX.current += (tgtX.current - curX.current) * 0.1;
    curY.current += (tgtY.current - curY.current) * 0.1;

    const grad = makeShine(curX.current, curY.current);

    if (textRef.current) {
      textRef.current.style.backgroundImage = grad;
    }

    const dx = Math.abs(tgtX.current - curX.current);
    const dy = Math.abs(tgtY.current - curY.current);

    if (hovering.current || dx > 0.05 || dy > 0.05) {
      raf.current = requestAnimationFrame(paint);
    }
  }, []);

  const onMove = useCallback(
    (e: React.MouseEvent) => {
      const r = sectionRef.current?.getBoundingClientRect();
      if (!r) return;
      tgtX.current = ((e.clientX - r.left) / r.width) * 100;
      tgtY.current = ((e.clientY - r.top) / r.height) * 100;

      if (!hovering.current) {
        hovering.current = true;
        raf.current = requestAnimationFrame(paint);
      }
    },
    [paint]
  );

  const onLeave = useCallback(() => {
    hovering.current = false;
    tgtX.current = 50;
    tgtY.current = 30;
    raf.current = requestAnimationFrame(paint);
  }, [paint]);

  // Cleanup
  useEffect(() => () => cancelAnimationFrame(raf.current), []);

  // IntersectionObserver
  useEffect(() => {
    const el = sectionRef.current;
    if (!el || typeof IntersectionObserver === "undefined") {
      setInView(true);
      return;
    }
    const obs = new IntersectionObserver(
      ([entry]) => {
        if (entry.isIntersecting) {
          setInView(true);
          obs.disconnect();
        }
      },
      { threshold: 0.1 }
    );
    obs.observe(el);
    return () => obs.disconnect();
  }, []);

  return (
    <a
      ref={sectionRef}
      href={href}
      className={cn(
        "relative w-full overflow-hidden flex items-center justify-center cursor-pointer",
        "bg-[#161618] dark:bg-black",
        className
      )}
      onMouseMove={onMove}
      onMouseLeave={onLeave}
      style={{
        height: "clamp(100px, 15.5vw, 215px)",
        fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
      }}
    >
      <motion.div
        initial={{ opacity: 0, y: 16 }}
        animate={inView ? { opacity: 1, y: 0 } : {}}
        transition={{ type: "spring", stiffness: 260, damping: 28 }}
        className="absolute inset-0 flex items-center justify-center pointer-events-none"
        style={{
          gap: "clamp(10px, 2vw, 24px)",
          padding: "clamp(20px, 3vw, 40px) clamp(24px, 4vw, 56px)",
        }}
      >
        <span
          ref={textRef}
          className="font-bold tracking-tighter leading-none whitespace-nowrap select-none"
          style={{
            fontSize: "clamp(64px, 17vw, 240px)",
            backgroundImage: makeShine(50, 30),
            WebkitBackgroundClip: "text",
            backgroundClip: "text",
            WebkitTextFillColor: "transparent",
            maskImage: VMASK,
            WebkitMaskImage: VMASK,
          }}
        >
          {brandName}
        </span>
      </motion.div>

      {/* Hairline — just above the clip edge */}
      <div
        className="absolute left-0 right-0 pointer-events-none bg-white/5 dark:bg-white/10"
        style={{
          bottom: "clamp(10px, 1.5vw, 22px)",
          height: "1px",
        }}
      />
    </a>
  );
}

export default WordmarkFooter;

--- FILE: frontend-web/registry/hero/BackgroundCircles.tsx ---

// @ts-nocheck
import { motion } from "framer-motion";
import { useState } from "react";
import { cn } from "../core/utils";

interface BackgroundCirclesProps {
    title?: string;
    description?: string;
    className?: string;
    variant?: keyof typeof COLOR_VARIANTS;
}

const COLOR_VARIANTS = {
    primary: {
        border: ["border-emerald-500/60", "border-cyan-400/50", "border-slate-600/30"],
        gradient: "from-emerald-500/30",
    },
    secondary: {
        border: ["border-violet-500/60", "border-fuchsia-400/50", "border-slate-600/30"],
        gradient: "from-violet-500/30",
    },
    tertiary: {
        border: ["border-orange-500/60", "border-yellow-400/50", "border-slate-600/30"],
        gradient: "from-orange-500/30",
    },
    quaternary: {
        border: ["border-purple-500/60", "border-pink-400/50", "border-slate-600/30"],
        gradient: "from-purple-500/30",
    },
    quinary: {
        border: ["border-red-500/60", "border-rose-400/50", "border-slate-600/30"],
        gradient: "from-red-500/30",
    },
    senary: {
        border: ["border-blue-500/60", "border-sky-400/50", "border-slate-600/30"],
        gradient: "from-blue-500/30",
    },
    septenary: {
        border: ["border-gray-500/60", "border-gray-400/50", "border-slate-600/30"],
        gradient: "from-gray-500/30",
    },
    octonary: {
        border: ["border-red-500/60", "border-rose-400/50", "border-slate-600/30"],
        gradient: "from-red-500/30",
    },
} as const;

const AnimatedGrid = () => (
    <motion.div
        className="absolute inset-0 [mask-image:radial-gradient(ellipse_at_center,transparent_30%,black)]"
        animate={{
            backgroundPosition: ["0% 0%", "100% 100%"],
        }}
        transition={{
            duration: 40,
            repeat: Number.POSITIVE_INFINITY,
            ease: "linear",
        }}
    >
        <div className="h-full w-full [background-image:repeating-linear-gradient(100deg,#64748B_0%,#64748B_1px,transparent_1px,transparent_4%)] opacity-20" />
    </motion.div>
);

export function BackgroundCircles({
    title = "Background Circles",
    description = "Optional Description",
    className,
    variant = "octonary",
}: BackgroundCirclesProps) {
    const variantStyles = COLOR_VARIANTS[variant];

    return (
        <div
            className={cn(
                "relative flex h-screen w-full items-center justify-center overflow-hidden",
                "bg-white dark:bg-black/5",
                className
            )}
        >
            <AnimatedGrid />
            <motion.div className="absolute h-[480px] w-[480px]">
                {[0, 1, 2].map((i) => (
                    <motion.div
                        key={i}
                        className={cn(
                            "absolute inset-0 rounded-full",
                            "border-2 bg-gradient-to-br to-transparent",
                            variantStyles.border[i],
                            variantStyles.gradient
                        )}
                        animate={{
                            rotate: 360,
                            scale: [1, 1.05 + i * 0.05, 1],
                            opacity: [0.8, 1, 0.8],
                        }}
                        transition={{
                            duration: 5,
                            repeat: Number.POSITIVE_INFINITY,
                            ease: "easeInOut",
                        }}
                    >
                        <div
                            className={cn(
                                "absolute inset-0 rounded-full mix-blend-screen",
                                `bg-[radial-gradient(ellipse_at_center,${variantStyles.gradient.replace(
                                    "from-",
                                    ""
                                )}/10%,transparent_70%)]`
                            )}
                        />
                    </motion.div>
                ))}
            </motion.div>

            <motion.div
                className="relative z-10 text-center"
                initial={{ opacity: 0, y: 20 }}
                animate={{ opacity: 1, y: 0 }}
                transition={{ duration: 0.8, ease: "easeOut" }}
            >
                <h1
                    className={cn(
                        "text-5xl font-bold tracking-tight md:text-7xl",
                        "bg-gradient-to-b from-slate-950 to-slate-700 dark:from-slate-100 dark:to-slate-300 bg-clip-text text-transparent",
                        "drop-shadow-[0_0_32px_rgba(94,234,212,0.4)]"
                    )}
                >
                    {title}
                </h1>

                <motion.p
                    className="mt-6 text-lg md:text-xl dark:text-white text-slate-950"
                    initial={{ opacity: 0 }}
                    animate={{ opacity: 1 }}
                    transition={{ delay: 0.2 }}
                >
                    {description}
                </motion.p>
            </motion.div>

            <div className="absolute inset-0 [mask-image:radial-gradient(90%_60%_at_50%_50%,#000_40%,transparent)]">
                <div className="absolute inset-0 bg-[radial-gradient(ellipse_at_center,#0F766E/30%,transparent_70%)] blur-[120px]" />
                <div className="absolute inset-0 bg-[radial-gradient(ellipse_at_center,#2DD4BF/15%,transparent)] blur-[80px]" />
            </div>
        </div>
    );
}

export function DemoCircles() {
    const [currentVariant, setCurrentVariant] =
        useState<keyof typeof COLOR_VARIANTS>("octonary");

    const variants = Object.keys(
        COLOR_VARIANTS
    ) as (keyof typeof COLOR_VARIANTS)[];

    function getNextVariant() {
        const currentIndex = variants.indexOf(currentVariant);
        const nextVariant = variants[(currentIndex + 1) % variants.length];
        return nextVariant;
    }

    return (
        <>
            <BackgroundCircles variant={currentVariant} />
            <div className="absolute top-12 right-12">
                <button
                    type="button"
                    className="bg-slate-950 dark:bg-white text-white dark:text-slate-950 px-4 py-1 rounded-md z-10 text-sm font-medium"
                    onClick={() => setCurrentVariant(getNextVariant())}
                >
                    Change Variant
                </button>
            </div>
        </>
    );
}

--- FILE: frontend-web/registry/hero/BackgroundPaths.tsx ---

// @ts-nocheck
import { motion } from "framer-motion";

function FloatingPaths({ position }: { position: number }) {
    const paths = Array.from({ length: 36 }, (_, i) => ({
        id: i,
        d: `M-${380 - i * 5 * position} -${189 + i * 6}C-${
            380 - i * 5 * position
        } -${189 + i * 6} -${312 - i * 5 * position} ${216 - i * 6} ${
            152 - i * 5 * position
        } ${343 - i * 6}C${616 - i * 5 * position} ${470 - i * 6} ${
            684 - i * 5 * position
        } ${875 - i * 6} ${684 - i * 5 * position} ${875 - i * 6}`,
        color: `rgba(15,23,42,${0.1 + i * 0.03})`,
        width: 0.5 + i * 0.03,
    }));

    return (
        <div className="absolute inset-0 pointer-events-none">
            <svg
                className="w-full h-full text-slate-950 dark:text-white"
                viewBox="0 0 696 316"
                fill="none"
            >
                <title>Background Paths</title>
                {paths.map((path) => (
                    <motion.path
                        key={path.id}
                        d={path.d}
                        stroke="currentColor"
                        strokeWidth={path.width}
                        strokeOpacity={0.1 + path.id * 0.03}
                        initial={{ pathLength: 0.3, opacity: 0.6 }}
                        animate={{
                            pathLength: 1,
                            opacity: [0.3, 0.6, 0.3],
                            pathOffset: [0, 1, 0],
                        }}
                        transition={{
                            duration: 20 + Math.random() * 10,
                            repeat: Number.POSITIVE_INFINITY,
                            ease: "linear",
                        }}
                    />
                ))}
            </svg>
        </div>
    );
}

export function BackgroundPaths({
    title = "Background Paths",
}: {
    title?: string;
}) {
    const words = title.split(" ");

    return (
        <div className="relative min-h-screen w-full flex items-center justify-center overflow-hidden bg-white dark:bg-neutral-950">
            <div className="absolute inset-0">
                <FloatingPaths position={1} />
                <FloatingPaths position={-1} />
            </div>

            <div className="relative z-10 container mx-auto px-4 md:px-6 text-center">
                <motion.div
                    initial={{ opacity: 0 }}
                    animate={{ opacity: 1 }}
                    transition={{ duration: 2 }}
                    className="max-w-4xl mx-auto"
                >
                    <h1 className="text-5xl sm:text-7xl md:text-8xl font-bold mb-8 tracking-tighter">
                        {words.map((word, wordIndex) => (
                            <span
                                key={wordIndex}
                                className="inline-block mr-4 last:mr-0"
                            >
                                {word.split("").map((letter, letterIndex) => (
                                    <motion.span
                                        key={`${wordIndex}-${letterIndex}`}
                                        initial={{ y: 100, opacity: 0 }}
                                        animate={{ y: 0, opacity: 1 }}
                                        transition={{
                                            delay: wordIndex * 0.1 + letterIndex * 0.03,
                                            type: "spring",
                                            stiffness: 150,
                                            damping: 25,
                                        }}
                                        className="inline-block text-transparent bg-clip-text bg-gradient-to-r from-neutral-900 to-neutral-700/80 dark:from-white dark:to-white/80"
                                    >
                                        {letter}
                                    </motion.span>
                                ))}
                            </span>
                        ))}
                    </h1>

                    <div className="inline-block group relative bg-gradient-to-b from-black/10 to-white/10 dark:from-white/10 dark:to-black/10 p-px rounded-2xl backdrop-blur-lg overflow-hidden shadow-lg hover:shadow-xl transition-shadow duration-300">
                        <button className="rounded-[1.15rem] px-8 py-6 text-lg font-semibold backdrop-blur-md bg-white/95 hover:bg-white/100 dark:bg-black/95 dark:hover:bg-black/100 text-black dark:text-white transition-all duration-300 group-hover:-translate-y-0.5 border border-black/10 dark:border-white/10 hover:shadow-md dark:hover:shadow-neutral-800/50">
                            <span className="opacity-90 group-hover:opacity-100 transition-opacity">
                                Discover Excellence
                            </span>
                            <span className="inline-block ml-3 opacity-70 group-hover:opacity-100 group-hover:translate-x-1.5 transition-all duration-300">
                                →
                            </span>
                        </button>
                    </div>
                </motion.div>
            </div>
        </div>
    );
}

--- FILE: frontend-web/registry/hero/HeroGeometric.tsx ---

// @ts-nocheck
import { motion } from "framer-motion";
import { Circle } from "lucide-react";
import { cn } from "../core/utils";

function ElegantShape({
    className,
    delay = 0,
    width = 400,
    height = 100,
    rotate = 0,
    gradient = "from-white/[0.08]",
}: {
    className?: string;
    delay?: number;
    width?: number;
    height?: number;
    rotate?: number;
    gradient?: string;
}) {
    return (
        <motion.div
            initial={{ opacity: 0, y: -150, rotate: rotate - 15 }}
            animate={{ opacity: 1, y: 0, rotate: rotate }}
            transition={{
                duration: 2.4,
                delay,
                ease: [0.23, 0.86, 0.39, 0.96],
                opacity: { duration: 1.2 },
            }}
            className={cn("absolute", className)}
        >
            <motion.div
                animate={{ y: [0, 15, 0] }}
                transition={{
                    duration: 12,
                    repeat: Number.POSITIVE_INFINITY,
                    ease: "easeInOut",
                }}
                style={{ width, height }}
                className="relative"
            >
                <div
                    className={cn(
                        "absolute inset-0 rounded-full",
                        "bg-gradient-to-r to-transparent",
                        gradient,
                        "backdrop-blur-[2px] border-2 border-white/[0.15]",
                        "shadow-[0_8px_32px_0_rgba(255,255,255,0.1)]",
                        "after:absolute after:inset-0 after:rounded-full",
                        "after:bg-[radial-gradient(circle_at_50%_50%,rgba(255,255,255,0.2),transparent_70%)]"
                    )}
                />
            </motion.div>
        </motion.div>
    );
}

function HeroGeometric({
    badge = "Design Collective",
    title1 = "Elevate Your Digital Vision",
    title2 = "Crafting Exceptional Websites",
}: {
    badge?: string;
    title1?: string;
    title2?: string;
}) {
    const fadeUpVariants = {
        hidden: { opacity: 0, y: 30 },
        visible: (i: number) => ({
            opacity: 1,
            y: 0,
            transition: {
                duration: 1,
                delay: 0.5 + i * 0.2,
                ease: [0.25, 0.4, 0.25, 1],
            },
        }),
    };

    return (
        <div className="relative min-h-screen w-full flex items-center justify-center overflow-hidden bg-[#030303]">
            <div className="absolute inset-0 bg-gradient-to-br from-indigo-500/[0.05] via-transparent to-rose-500/[0.05] blur-3xl" />

            <div className="absolute inset-0 overflow-hidden">
                <ElegantShape delay={0.3} width={600} height={140} rotate={12} gradient="from-indigo-500/[0.15]" className="left-[-10%] md:left-[-5%] top-[15%] md:top-[20%]" />
                <ElegantShape delay={0.5} width={500} height={120} rotate={-15} gradient="from-rose-500/[0.15]" className="right-[-5%] md:right-[0%] top-[70%] md:top-[75%]" />
                <ElegantShape delay={0.4} width={300} height={80} rotate={-8} gradient="from-violet-500/[0.15]" className="left-[5%] md:left-[10%] bottom-[5%] md:bottom-[10%]" />
                <ElegantShape delay={0.6} width={200} height={60} rotate={20} gradient="from-amber-500/[0.15]" className="right-[15%] md:right-[20%] top-[10%] md:top-[15%]" />
                <ElegantShape delay={0.7} width={150} height={40} rotate={-25} gradient="from-cyan-500/[0.15]" className="left-[20%] md:left-[25%] top-[5%] md:top-[10%]" />
            </div>

            <div className="relative z-10 container mx-auto px-4 md:px-6">
                <div className="max-w-3xl mx-auto text-center">
                    <motion.div custom={0} variants={fadeUpVariants} initial="hidden" animate="visible" className="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-white/[0.03] border border-white/[0.08] mb-8 md:mb-12">
                        <Circle className="h-2 w-2 fill-rose-500/80" />
                        <span className="text-sm text-white/60 tracking-wide">{badge}</span>
                    </motion.div>

                    <motion.div custom={1} variants={fadeUpVariants} initial="hidden" animate="visible">
                        <h1 className="text-4xl sm:text-6xl md:text-8xl font-bold mb-6 md:mb-8 tracking-tight">
                            <span className="bg-clip-text text-transparent bg-gradient-to-b from-white to-white/80">{title1}</span>
                            <br />
                            <span className="bg-clip-text text-transparent bg-gradient-to-r from-indigo-300 via-white/90 to-rose-300">{title2}</span>
                        </h1>
                    </motion.div>

                    <motion.div custom={2} variants={fadeUpVariants} initial="hidden" animate="visible">
                        <p className="text-base sm:text-lg md:text-xl text-white/40 mb-8 leading-relaxed font-light tracking-wide max-w-xl mx-auto px-4">
                            Crafting exceptional digital experiences through innovative design and cutting-edge technology.
                        </p>
                    </motion.div>
                </div>
            </div>

            <div className="absolute inset-0 bg-gradient-to-t from-[#030303] via-transparent to-[#030303]/80 pointer-events-none" />
        </div>
    );
}

export { HeroGeometric }

--- FILE: frontend-web/registry/hero/HeroHighlight.tsx ---

// @ts-nocheck
import { cn } from "../core/utils";
import { useMotionValue, motion, useMotionTemplate } from "framer-motion";
import React from "react";

export const HeroHighlight = ({
  children,
  className,
  containerClassName,
}: {
  children: React.ReactNode;
  className?: string;
  containerClassName?: string;
}) => {
  let mouseX = useMotionValue(0);
  let mouseY = useMotionValue(0);

  function handleMouseMove({
    currentTarget,
    clientX,
    clientY,
  }: React.MouseEvent<HTMLDivElement>) {
    if (!currentTarget) return;
    let { left, top } = currentTarget.getBoundingClientRect();

    mouseX.set(clientX - left);
    mouseY.set(clientY - top);
  }

  const dotPattern = (color: string) => ({
    backgroundImage: `radial-gradient(circle, ${color} 1px, transparent 1px)`,
    backgroundSize: '16px 16px',
  });

  return (
    <div
      className={cn(
        "relative min-h-[40rem] flex items-center bg-white dark:bg-black justify-center w-full group",
        containerClassName
      )}
      onMouseMove={handleMouseMove}
    >
      <div 
        className="absolute inset-0 pointer-events-none opacity-70" 
        style={dotPattern('rgb(212 212 212)')} // neutral-300 for light mode
      />
      <div 
        className="absolute inset-0 dark:opacity-70 opacity-0 pointer-events-none" 
        style={dotPattern('rgb(38 38 38)')} // neutral-800 for dark mode
      />
      <motion.div
        className="pointer-events-none absolute inset-0 opacity-0 transition duration-300 group-hover:opacity-100"
        style={{
          ...dotPattern('rgb(99 102 241)'), // indigo-500
          WebkitMaskImage: useMotionTemplate`
            radial-gradient(
              200px circle at ${mouseX}px ${mouseY}px,
              black 0%,
              transparent 100%
            )
          `,
          maskImage: useMotionTemplate`
            radial-gradient(
              200px circle at ${mouseX}px ${mouseY}px,
              black 0%,
              transparent 100%
            )
          `,
        }}
      />

      <div className={cn("relative z-20 w-full h-full", className)}>{children}</div>
    </div>
  );
};

export const Highlight = ({
  children,
  className,
}: {
  children: React.ReactNode;
  className?: string;
}) => {
  return (
    <motion.span
      initial={{
        backgroundSize: "0% 100%",
      }}
      animate={{
        backgroundSize: "100% 100%",
      }}
      transition={{
        duration: 2,
        ease: "linear",
        delay: 0.5,
      }}
      style={{
        backgroundRepeat: "no-repeat",
        backgroundPosition: "left center",
        display: "inline",
      }}
      className={cn(
        `relative inline-block pb-1 px-1 rounded-lg bg-gradient-to-r from-indigo-300 to-purple-300 dark:from-indigo-500 dark:to-purple-500`,
        className
      )}
    >
      {children}
    </motion.span>
  );
};

--- FILE: frontend-web/registry/hero/HeroSection.tsx ---

import React from 'react'
import { Menu, X, ChevronRight } from 'lucide-react'
import { useScroll, motion } from 'framer-motion'
import { cn } from '../core/utils'

export function HeroSection() {
    return (
        <div className="w-full bg-white dark:bg-zinc-950 text-zinc-950 dark:text-zinc-50 font-sans min-h-screen">
            <HeroHeader />
            <main className="overflow-x-hidden">
                <section>
                    <div className="py-24 md:pb-32 lg:pb-36 lg:pt-48">
                        <div className="relative z-10 mx-auto flex max-w-7xl flex-col px-6 lg:block lg:px-12">
                            <div className="mx-auto max-w-lg text-center lg:ml-0 lg:max-w-full lg:text-left">
                                <h1 className="mt-8 max-w-2xl text-balance text-5xl md:text-6xl lg:mt-16 xl:text-7xl font-bold tracking-tight">
                                    Build 10x Faster with NOVA
                                </h1>
                                <p className="mt-8 max-w-2xl text-balance text-lg text-zinc-600 dark:text-zinc-400">
                                    Highly customizable components for building modern websites and applications. Zero config, pure velocity.
                                </p>

                                <div className="mt-12 flex flex-col items-center justify-center gap-4 sm:flex-row lg:justify-start">
                                    <button
                                        className="inline-flex items-center justify-center whitespace-nowrap font-medium transition-colors focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50 h-12 rounded-full pl-6 pr-4 text-base bg-zinc-900 text-zinc-50 hover:bg-zinc-900/90 dark:bg-zinc-50 dark:text-zinc-900 dark:hover:bg-zinc-50/90"
                                    >
                                        <a href="#start" className="flex items-center">
                                            <span>Start Building</span>
                                            <ChevronRight className="ml-1 h-5 w-5" />
                                        </a>
                                    </button>
                                    <button
                                        className="inline-flex items-center justify-center whitespace-nowrap font-medium transition-colors focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50 h-12 rounded-full px-6 text-base hover:bg-zinc-100 dark:hover:bg-zinc-800 text-zinc-900 dark:text-zinc-50"
                                    >
                                        <a href="#demo">
                                            <span>Request a demo</span>
                                        </a>
                                    </button>
                                </div>
                            </div>
                        </div>
                        <div className="relative mx-auto mt-16 max-w-7xl px-6 lg:px-12">
                            <div className="aspect-[2/3] sm:aspect-video w-full overflow-hidden rounded-3xl border border-zinc-200 dark:border-zinc-800 lg:rounded-[3rem] shadow-2xl">
                                <video
                                    autoPlay
                                    loop
                                    muted
                                    playsInline
                                    className="size-full object-cover"
                                    src="https://ik.imagekit.io/lrigu76hy/tailark/dna-video.mp4?updatedAt=1745736251477"
                                />
                                <div className="absolute inset-0 bg-black/10 dark:bg-black/30 pointer-events-none" />
                            </div>
                        </div>
                    </div>
                </section>
                
                {/* Standardized Logo Strip without external dependencies */}
                <section className="pb-24 pt-12">
                    <div className="m-auto max-w-7xl px-6 lg:px-12">
                        <div className="flex flex-col items-center md:flex-row gap-8">
                            <div className="md:max-w-44 md:border-r border-zinc-200 dark:border-zinc-800 md:pr-6 shrink-0">
                                <p className="text-center md:text-end text-sm text-zinc-500 dark:text-zinc-400 font-medium">Powering the best teams</p>
                            </div>
                            <div className="w-full flex flex-wrap justify-center md:justify-around items-center gap-8 opacity-60 grayscale hover:grayscale-0 transition-all duration-500">
                                <img className="h-6 w-auto dark:invert" src="https://html.tailus.io/blocks/customers/nvidia.svg" alt="Nvidia" />
                                <img className="h-5 w-auto dark:invert" src="https://html.tailus.io/blocks/customers/github.svg" alt="GitHub" />
                                <img className="h-6 w-auto dark:invert" src="https://html.tailus.io/blocks/customers/nike.svg" alt="Nike" />
                                <img className="h-6 w-auto dark:invert" src="https://html.tailus.io/blocks/customers/openai.svg" alt="OpenAI" />
                            </div>
                        </div>
                    </div>
                </section>
            </main>
        </div>
    )
}

const menuItems = [
    { name: 'Features', href: '#features' },
    { name: 'Solutions', href: '#solutions' },
    { name: 'Pricing', href: '#pricing' },
    { name: 'About', href: '#about' },
]

const HeroHeader = () => {
    const [menuState, setMenuState] = React.useState(false)
    const [scrolled, setScrolled] = React.useState(false)
    const { scrollYProgress } = useScroll()

    React.useEffect(() => {
        const unsubscribe = scrollYProgress.on('change', (latest) => {
            setScrolled(latest > 0.05)
        })
        return () => unsubscribe()
    }, [scrollYProgress])

    return (
        <header>
            <nav
                data-state={menuState ? 'active' : 'inactive'}
                className="group fixed z-50 w-full pt-4 transition-all duration-300">
                <div className={cn('mx-auto max-w-7xl rounded-3xl px-6 transition-all duration-300 lg:px-12', scrolled && 'bg-white/80 dark:bg-zinc-950/80 backdrop-blur-xl border border-zinc-200 dark:border-zinc-800 shadow-sm py-2 mx-4 lg:mx-auto')}>
                    <motion.div
                        className={cn('relative flex flex-wrap items-center justify-between gap-6 py-2 duration-200 lg:gap-0')}>
                        <div className="flex w-full items-center justify-between gap-12 lg:w-auto">
                            <a href="/" aria-label="home" className="flex items-center space-x-2">
                                <Logo className="text-zinc-950 dark:text-white" />
                            </a>

                            <button
                                onClick={() => setMenuState(!menuState)}
                                aria-label={menuState ? 'Close Menu' : 'Open Menu'}
                                className="relative z-20 block cursor-pointer p-2 lg:hidden text-zinc-950 dark:text-zinc-50">
                                {menuState ? <X className="size-6" /> : <Menu className="size-6" />}
                            </button>

                            <div className="hidden lg:block">
                                <ul className="flex gap-8 text-sm font-medium">
                                    {menuItems.map((item, index) => (
                                        <li key={index}>
                                            <a href={item.href} className="text-zinc-600 hover:text-zinc-950 dark:text-zinc-400 dark:hover:text-zinc-50 transition-colors">
                                                {item.name}
                                            </a>
                                        </li>
                                    ))}
                                </ul>
                            </div>
                        </div>

                        <div className={cn(
                            "w-full lg:w-auto lg:flex items-center gap-4 flex-col lg:flex-row",
                            menuState ? "flex pb-4" : "hidden"
                        )}>
                            <div className="lg:hidden w-full border-t border-zinc-200 dark:border-zinc-800 pt-4 mb-4">
                                <ul className="flex flex-col space-y-4 text-base font-medium">
                                    {menuItems.map((item, index) => (
                                        <li key={index}>
                                            <a href={item.href} className="text-zinc-600 hover:text-zinc-950 dark:text-zinc-400 dark:hover:text-zinc-50 transition-colors block">
                                                {item.name}
                                            </a>
                                        </li>
                                    ))}
                                </ul>
                            </div>
                            <div className="flex w-full flex-col sm:flex-row gap-3 lg:w-fit">
                                <button className="inline-flex items-center justify-center whitespace-nowrap font-medium transition-colors focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50 h-9 rounded-md px-4 text-sm border border-zinc-200 dark:border-zinc-800 hover:bg-zinc-100 dark:hover:bg-zinc-800 w-full sm:w-auto">
                                    Login
                                </button>
                                <button className="inline-flex items-center justify-center whitespace-nowrap font-medium transition-colors focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50 h-9 rounded-md px-4 text-sm bg-zinc-900 text-zinc-50 hover:bg-zinc-900/90 dark:bg-zinc-50 dark:text-zinc-900 dark:hover:bg-zinc-50/90 w-full sm:w-auto">
                                    Sign Up
                                </button>
                            </div>
                        </div>
                    </motion.div>
                </div>
            </nav>
        </header>
    )
}

const Logo = ({ className }: { className?: string }) => {
    return (
        <svg
            viewBox="0 0 78 18"
            fill="none"
            xmlns="http://www.w3.org/2000/svg"
            className={cn('h-6 w-auto', className)}>
            <path
                d="M3 0H5V18H3V0ZM13 0H15V18H13V0ZM18 3V5H0V3H18ZM0 15V13H18V15H0Z"
                fill="currentColor"
            />
            <path
                d="M27.06 7.054V12.239C27.06 12.5903 27.1393 12.8453 27.298 13.004C27.468 13.1513 27.7513 13.225 28.148 13.225H29.338V14.84H27.808C26.9353 14.84 26.2667 14.636 25.802 14.228C25.3373 13.82 25.105 13.157 25.105 12.239V7.054H24V5.473H25.105V3.144H27.06V5.473H29.338V7.054H27.06ZM30.4782 10.114C30.4782 9.17333 30.6709 8.34033 31.0562 7.615C31.4529 6.88967 31.9855 6.32867 32.6542 5.932C33.3342 5.524 34.0822 5.32 34.8982 5.32C35.6349 5.32 36.2752 5.46733 36.8192 5.762C37.3745 6.04533 37.8165 6.40233 38.1452 6.833V5.473H40.1002V14.84H38.1452V13.446C37.8165 13.888 37.3689 14.2563 36.8022 14.551C36.2355 14.8457 35.5895 14.993 34.8642 14.993C34.0595 14.993 33.3229 14.789 32.6542 14.381C31.9855 13.9617 31.4529 13.3837 31.0562 12.647C30.6709 11.899 30.4782 11.0547 30.4782 10.114ZM38.1452 10.148C38.1452 9.502 38.0092 8.941 37.7372 8.465C37.4765 7.989 37.1309 7.62633 36.7002 7.377C36.2695 7.12767 35.8049 7.003 35.3062 7.003C34.8075 7.003 34.3429 7.12767 33.9122 7.377C33.4815 7.615 33.1302 7.972 32.8582 8.448C32.5975 8.91267 32.4672 9.468 32.4672 10.114C32.4672 10.76 32.5975 11.3267 32.8582 11.814C33.1302 12.3013 33.4815 12.6753 33.9122 12.936C34.3542 13.1853 34.8189 13.31 35.3062 13.31C35.8049 13.31 36.2695 13.1853 36.7002 12.936C37.1309 12.6867 37.4765 12.324 37.7372 11.848C38.0092 11.3607 38.1452 10.794 38.1452 10.148ZM43.6317 4.232C43.2803 4.232 42.9857 4.113 42.7477 3.875C42.5097 3.637 42.3907 3.34233 42.3907 2.991C42.3907 2.63967 42.5097 2.345 42.7477 2.107C42.9857 1.869 43.2803 1.75 43.6317 1.75C43.9717 1.75 44.2607 1.869 44.4987 2.107C44.7367 2.345 44.8557 2.63967 44.8557 2.991C44.8557 3.34233 44.7367 3.637 44.4987 3.875C44.2607 4.113 43.9717 4.232 43.6317 4.232ZM44.5837 5.473V14.84H42.6457V5.473H44.5837ZM49.0661 2.26V14.84H47.1281V2.26H49.0661ZM50.9645 10.114C50.9645 9.17333 51.1572 8.34033 51.5425 7.615C51.9392 6.88967 52.4719 6.32867 53.1405 5.932C53.8205 5.524 54.5685 5.32 55.3845 5.32C56.1212 5.32 56.7615 5.46733 57.3055 5.762C57.8609 6.04533 58.3029 6.40233 58.6315 6.833V5.473H60.5865V14.84H58.6315V13.446C58.3029 13.888 57.8552 14.2563 57.2885 14.551C56.7219 14.8457 56.0759 14.993 55.3505 14.993C54.5459 14.993 53.8092 14.789 53.1405 14.381C52.4719 13.9617 51.9392 13.3837 51.5425 12.647C51.1572 11.899 50.9645 11.0547 50.9645 10.114ZM58.6315 10.148C58.6315 9.502 58.4955 8.941 58.2235 8.465C57.9629 7.989 57.6172 7.62633 57.1865 7.377C56.7559 7.12767 56.2912 7.003 55.7925 7.003C55.2939 7.003 54.8292 7.12767 54.3985 7.377C53.9679 7.615 53.6165 7.972 53.3445 8.448C53.0839 8.91267 52.9535 9.468 52.9535 10.114C52.9535 10.76 53.0839 11.3267 53.3445 11.814C53.6165 12.3013 53.9679 12.6753 54.3985 12.936C54.8405 13.1853 55.3052 13.31 55.7925 13.31C56.2912 13.31 56.7559 13.1853 57.1865 12.936C57.6172 12.6867 57.9629 12.324 58.2235 11.848C58.4955 11.3607 58.6315 10.794 58.6315 10.148ZM65.07 6.833C65.3533 6.357 65.7273 5.98867 66.192 5.728C66.668 5.456 67.229 5.32 67.875 5.32V7.326H67.382C66.6227 7.326 66.0447 7.51867 65.648 7.904C65.2627 8.28933 65.07 8.958 65.07 9.91V14.84H63.132V5.473H65.07V6.833ZM73.3624 10.165L77.6804 14.84H75.0624L71.5944 10.811V14.84H69.6564V2.26H71.5944V9.57L74.9944 5.473H77.6804L73.3624 10.165Z"
                fill="currentColor"
            />
        </svg>
    )
}

--- FILE: frontend-web/registry/hero/HeroWithVideo.tsx ---

import React, { useState, useRef, useEffect } from 'react';
import { Play, Pause, Mail, ArrowRight, Menu, ChevronDown, Sun, Moon } from 'lucide-react';
import { cn } from '../core/utils';

export interface NavbarHeroProps {
  brandName?: string;
  heroTitle?: string;
  heroSubtitle?: string;
  heroDescription?: string;
  backgroundImage?: string;
  videoUrl?: string;
  emailPlaceholder?: string;
  className?: string;
}

// Inlined zero-config dark mode hook to replace next-themes dependency
function useDarkMode() {
  const [isDark, setIsDark] = useState(false);

  useEffect(() => {
    const htmlEl = document.documentElement;
    const checkTheme = () => setIsDark(htmlEl.classList.contains('dark'));
    
    checkTheme();

    const observer = new MutationObserver(checkTheme);
    observer.observe(htmlEl, { attributes: true, attributeFilter: ['class'] });

    return () => observer.disconnect();
  }, []);

  const toggleTheme = () => {
    const htmlEl = document.documentElement;
    if (htmlEl.classList.contains('dark')) {
      htmlEl.classList.remove('dark');
      setIsDark(false);
    } else {
      htmlEl.classList.add('dark');
      setIsDark(true);
    }
  };

  return { isDark, toggleTheme };
}

export const HeroWithVideo: React.FC<NavbarHeroProps> = ({
  brandName = "nexus",
  heroTitle = "Innovation Meets Simplicity",
  heroSubtitle = "Join the community",
  heroDescription = "Discover cutting-edge solutions designed for the modern digital landscape.",
  backgroundImage = "https://images.unsplash.com/photo-1446776811953-b23d57bd21aa?ixlib=rb-4.0.3&auto=format&fit=crop&w=2072&q=80",
  videoUrl = "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4",
  emailPlaceholder = "enter@email.com",
  className
}) => {
  const [email, setEmail] = useState('');
  const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
  const [openDropdown, setOpenDropdown] = useState<string | null>(null);
  const [isVideoPlaying, setIsVideoPlaying] = useState(false);
  const [isVideoPaused, setIsVideoPaused] = useState(false);
  const videoRef = useRef<HTMLVideoElement>(null);
  
  const { isDark, toggleTheme } = useDarkMode();
  const [mounted, setMounted] = useState(false);

  useEffect(() => {
    setMounted(true);
  }, []);

  const handleEmailSubmit = () => {
    console.log('Email submitted:', email);
  };

  const toggleDropdown = (dropdownName: string) => {
    setOpenDropdown(openDropdown === dropdownName ? null : dropdownName);
  };

  const handlePlayVideo = () => {
    if (videoRef.current) {
      videoRef.current.play();
      setIsVideoPlaying(true);
      setIsVideoPaused(false);
    }
  };

  const handlePauseVideo = () => {
    if (videoRef.current) {
      videoRef.current.pause();
      setIsVideoPaused(true);
    }
  };
  
  const handleResumeVideo = () => {
    if (videoRef.current) {
      videoRef.current.play();
      setIsVideoPaused(false);
    }
  };

  const handleVideoEnded = () => {
    setIsVideoPlaying(false);
    setIsVideoPaused(false);
  };

  const ThemeToggleButton = () => {
    if (!mounted) return <div className="w-10 h-10" />;
    return (
      <button
        onClick={toggleTheme}
        className="bg-slate-100 hover:bg-slate-200 dark:bg-slate-800 dark:hover:bg-slate-700 flex-shrink-0 p-2.5 rounded-full transition-colors"
        aria-label="Toggle theme"
      >
        {!isDark ? <Moon className="h-5 w-5 text-slate-900" /> : <Sun className="h-5 w-5 text-slate-100" />}
      </button>
    );
  };

  return (
    <div className={cn("relative w-full bg-white dark:bg-slate-950", className)}>
      <div className="w-full max-w-7xl mx-auto p-4 sm:p-6 lg:p-8">
        
        {/* --- Navbar --- */}
        <div className="py-2 relative z-20 flex items-center justify-between gap-4">
          <div className="flex items-center gap-6">
            <a href="#" className="font-bold text-2xl pb-1 text-slate-900 dark:text-white cursor-pointer flex-shrink-0">
              {brandName}
            </a>
            <nav className="hidden lg:flex text-slate-500 dark:text-slate-400 font-medium">
              <ul className="flex items-center space-x-2">
                <li><a href="#" className="hover:text-slate-900 dark:hover:text-white px-3 py-2 text-sm transition-colors rounded-lg">About</a></li>
                <li className="relative">
                  <button onClick={() => toggleDropdown('desktop-resources')} className="flex items-center hover:text-slate-900 dark:hover:text-white px-3 py-2 text-sm transition-colors rounded-lg">
                    Resources<ChevronDown className={`h-4 w-4 ml-1 transition-transform ${openDropdown === 'desktop-resources' ? 'rotate-180' : ''}`} />
                  </button>
                  {openDropdown === 'desktop-resources' && (
                    <ul className="absolute top-full left-0 mt-2 p-2 bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 shadow-lg rounded-xl z-20 w-48">
                      <li><a href="#" className="block px-3 py-2 text-sm text-slate-500 dark:text-slate-400 hover:text-slate-900 dark:hover:text-white hover:bg-slate-100 dark:hover:bg-slate-800 rounded-lg">Submenu 1</a></li>
                      <li><a href="#" className="block px-3 py-2 text-sm text-slate-500 dark:text-slate-400 hover:text-slate-900 dark:hover:text-white hover:bg-slate-100 dark:hover:bg-slate-800 rounded-lg">Submenu 2</a></li>
                    </ul>
                  )}
                </li>
                <li><a href="#" className="hover:text-slate-900 dark:hover:text-white px-3 py-2 text-sm transition-colors rounded-lg">Blog</a></li>
                <li className="relative">
                  <button onClick={() => toggleDropdown('desktop-pricing')} className="flex items-center hover:text-slate-900 dark:hover:text-white px-3 py-2 text-sm transition-colors rounded-lg">
                    Plans & Pricing<ChevronDown className={`h-4 w-4 ml-1 transition-transform ${openDropdown === 'desktop-pricing' ? 'rotate-180' : ''}`} />
                  </button>
                  {openDropdown === 'desktop-pricing' && (
                    <ul className="absolute top-full left-0 mt-2 p-2 bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 shadow-lg rounded-xl z-20 w-48">
                      <li><a href="#" className="block px-3 py-2 text-sm text-slate-500 dark:text-slate-400 hover:text-slate-900 dark:hover:text-white hover:bg-slate-100 dark:hover:bg-slate-800 rounded-lg">Plan A</a></li>
                      <li><a href="#" className="block px-3 py-2 text-sm text-slate-500 dark:text-slate-400 hover:text-slate-900 dark:hover:text-white hover:bg-slate-100 dark:hover:bg-slate-800 rounded-lg">Plan B</a></li>
                    </ul>
                  )}
                </li>
              </ul>
            </nav>
          </div>

          <div className="flex items-center gap-3">
            <div className="hidden lg:flex items-center gap-3">
              <a href="#" className="text-slate-900 dark:text-white hover:text-slate-500 dark:hover:text-slate-400 cursor-pointer py-2 px-4 text-sm capitalize font-medium transition-colors rounded-xl">Login</a>
              <button className="bg-slate-900 dark:bg-white hover:bg-slate-800 dark:hover:bg-slate-200 text-white dark:text-slate-900 py-2.5 px-5 text-sm rounded-xl capitalize font-medium transition-colors flex items-center gap-2">
                Get Started<ArrowRight className="h-4 w-4" />
              </button>
            </div>
            <ThemeToggleButton />
            <div className="lg:hidden relative">
              <button onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)} className="bg-transparent hover:bg-slate-100 dark:hover:bg-slate-800 border-none p-2 rounded-xl transition-colors">
                <Menu className="h-6 w-6 text-slate-900 dark:text-white" />
              </button>
              {isMobileMenuOpen && (
                <ul className="absolute top-full right-0 mt-2 p-2 shadow-lg bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 rounded-xl w-56 z-30">
                  <li><a href="#" className="block px-3 py-2 text-sm text-slate-900 dark:text-white hover:bg-slate-100 dark:hover:bg-slate-800 rounded-lg">About</a></li>
                  <li>
                    <button onClick={() => toggleDropdown('mobile-resources')} className="w-full flex items-center justify-between px-3 py-2 text-sm text-slate-900 dark:text-white hover:bg-slate-100 dark:hover:bg-slate-800 rounded-lg">
                      Resources<ChevronDown className={`h-4 w-4 transition-transform ${openDropdown === 'mobile-resources' ? 'rotate-180' : ''}`} />
                    </button>
                    {openDropdown === 'mobile-resources' && (
                      <ul className="ml-4 mt-1 border-l border-slate-200 dark:border-slate-800 pl-3">
                        <li><a href="#" className="block px-3 py-1.5 text-sm text-slate-500 dark:text-slate-400 hover:bg-slate-100 dark:hover:bg-slate-800 hover:text-slate-900 dark:hover:text-white rounded-lg">Submenu 1</a></li>
                        <li><a href="#" className="block px-3 py-1.5 text-sm text-slate-500 dark:text-slate-400 hover:bg-slate-100 dark:hover:bg-slate-800 hover:text-slate-900 dark:hover:text-white rounded-lg">Submenu 2</a></li>
                      </ul>
                    )}
                  </li>
                  <li><a href="#" className="block px-3 py-2 text-sm text-slate-900 dark:text-white hover:bg-slate-100 dark:hover:bg-slate-800 rounded-lg">Blog</a></li>
                  <li>
                    <button onClick={() => toggleDropdown('mobile-pricing')} className="w-full flex items-center justify-between px-3 py-2 text-sm text-slate-900 dark:text-white hover:bg-slate-100 dark:hover:bg-slate-800 rounded-lg">
                      Plans & Pricing<ChevronDown className={`h-4 w-4 transition-transform ${openDropdown === 'mobile-pricing' ? 'rotate-180' : ''}`} />
                    </button>
                    {openDropdown === 'mobile-pricing' && (
                      <ul className="ml-4 mt-1 border-l border-slate-200 dark:border-slate-800 pl-3">
                        <li><a href="#" className="block px-3 py-1.5 text-sm text-slate-500 dark:text-slate-400 hover:bg-slate-100 dark:hover:bg-slate-800 hover:text-slate-900 dark:hover:text-white rounded-lg">Plan A</a></li>
                        <li><a href="#" className="block px-3 py-1.5 text-sm text-slate-500 dark:text-slate-400 hover:bg-slate-100 dark:hover:bg-slate-800 hover:text-slate-900 dark:hover:text-white rounded-lg">Plan B</a></li>
                      </ul>
                    )}
                  </li>
                  <li className="border-t border-slate-200 dark:border-slate-800 mt-2 pt-2 space-y-2">
                    <a href="#" className="block w-full text-center px-3 py-2 text-sm text-slate-900 dark:text-white hover:bg-slate-100 dark:hover:bg-slate-800 rounded-lg">Login</a>
                    <button className="w-full bg-slate-900 dark:bg-white text-white dark:text-slate-900 hover:bg-slate-800 dark:hover:bg-slate-200 px-3 py-2.5 text-sm rounded-lg flex items-center justify-center gap-2 font-medium">
                      Get Started<ArrowRight className="h-4 w-4" />
                    </button>
                  </li>
                </ul>
              )}
            </div>
          </div>
        </div>

        {/* --- Hero Section --- */}
        <div className="pt-10 pb-12 sm:pt-16 sm:pb-16 text-center">
          <div className="max-w-3xl mx-auto">
            <h1 className="text-4xl sm:text-5xl md:text-6xl text-slate-900 dark:text-white font-bold tracking-tight leading-tight">{heroTitle}</h1>
            <p className="mt-6 text-lg sm:text-xl text-slate-500 dark:text-slate-400 max-w-2xl mx-auto leading-relaxed">{heroDescription}</p>
            <div className="mt-10 flex items-center justify-center gap-3 sm:gap-4 flex-wrap">
              <div className="relative w-full max-w-xs">
                <Mail className="absolute left-4 top-1/2 transform -translate-y-1/2 h-5 w-5 text-slate-400" />
                <input 
                  type="email" 
                  placeholder={emailPlaceholder} 
                  value={email} 
                  onChange={(e) => setEmail(e.target.value)} 
                  className="w-full bg-slate-100 dark:bg-slate-900 border border-slate-200 dark:border-slate-800 text-slate-900 dark:text-white placeholder-slate-400 dark:placeholder-slate-500 font-medium pl-11 pr-4 py-3 text-sm sm:text-base rounded-full focus:outline-none focus:ring-2 focus:ring-blue-500" 
                />
              </div>
              <button onClick={handleEmailSubmit} className="bg-blue-600 hover:bg-blue-700 text-white px-6 py-3 text-sm sm:text-base rounded-full normal-case font-medium transition-colors flex items-center gap-2 shadow-sm shadow-blue-500/20">
                Join Now<ArrowRight className="h-4 w-4" />
              </button>
            </div>
          </div>
        </div>

        {/* --- Media Header --- */}
        <header className="relative w-full aspect-video rounded-3xl overflow-hidden shadow-2xl border border-slate-200 dark:border-slate-800">
          <img src={backgroundImage} alt="Hero background" className={`w-full h-full absolute inset-0 object-cover transition-opacity duration-500 ${isVideoPlaying ? 'opacity-0' : 'opacity-100'}`} />
          <video ref={videoRef} src={videoUrl} className={`w-full h-full absolute inset-0 object-cover transition-opacity duration-500 ${isVideoPlaying ? 'opacity-100' : 'opacity-0'}`} onEnded={handleVideoEnded} playsInline muted />
          <div className="absolute inset-0 bg-black/10 pointer-events-none" />
          <div className="absolute bottom-6 right-6 z-10">
            {!isVideoPlaying ? (
              <button onClick={handlePlayVideo} className="w-16 h-16 rounded-full bg-white/20 backdrop-blur-md border border-white/30 flex items-center justify-center hover:bg-white/30 transition-all duration-300 shadow-xl group">
                <Play className="h-8 w-8 text-white fill-white ml-1 group-hover:scale-110 transition-transform" />
              </button>
            ) : (
              <button onClick={isVideoPaused ? handleResumeVideo : handlePauseVideo} className="w-16 h-16 rounded-full bg-white/20 backdrop-blur-md border border-white/30 flex items-center justify-center hover:bg-white/30 transition-all duration-300 shadow-xl group">
                {isVideoPaused ? <Play className="h-8 w-8 text-white fill-white ml-1 group-hover:scale-110 transition-transform" /> : <Pause className="h-8 w-8 text-white fill-white group-hover:scale-110 transition-transform" />}
              </button>
            )}
          </div>
        </header>
      </div>
    </div>
  );
};

--- FILE: frontend-web/registry/hero/VHSHero.tsx ---

import { gsap } from "gsap"
import { useFrame, Canvas } from "@react-three/fiber"
import type { Points, ShaderMaterial } from "three"
import * as THREE from "three"
import React, { useEffect, useRef, useState, useCallback, useMemo } from "react"
import { cn } from "../core/utils"

interface DistortionBackgroundProps {
  mousePosition: { x: number; y: number }
}

function DistortionBackground({ mousePosition }: DistortionBackgroundProps) {
  const meshRef = useRef<THREE.Mesh>(null)
  const materialRef = useRef<ShaderMaterial>(null)

  const uniforms = useMemo(
    () => ({
      uTime: { value: 0 },
      uMouse: { value: [0, 0] },
      uResolution: { value: [window.innerWidth, window.innerHeight] },
      uNoiseScale: { value: 8.0 },
      uDistortionStrength: { value: 0.3 },
    }),
    [],
  )

  const vertexShader = `
    varying vec2 vUv;
    uniform float uTime;
    uniform float uDistortionStrength;
    
    // Noise function
    float noise(vec2 st) {
      return fract(sin(dot(st.xy, vec2(12.9898,78.233))) * 43758.5453123);
    }
    
    void main() {
      vUv = uv;
      
      vec3 pos = position;
      
      // Add vertex distortion
      float n1 = noise(uv * 10.0 + uTime * 0.5);
      float n2 = noise(uv * 20.0 - uTime * 0.3);
      
      pos.z += sin(pos.x * 5.0 + uTime * 2.0) * uDistortionStrength * n1;
      pos.z += cos(pos.y * 8.0 + uTime * 1.5) * uDistortionStrength * n2;
      
      gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
    }
  `

  const fragmentShader = `
    uniform float uTime;
    uniform vec2 uMouse;
    uniform vec2 uResolution;
    uniform float uNoiseScale;
    uniform float uDistortionStrength;
    varying vec2 vUv;

    // Enhanced noise functions
    float random(vec2 st) {
      return fract(sin(dot(st.xy, vec2(12.9898,78.233))) * 43758.5453123);
    }

    float noise(vec2 st) {
      vec2 i = floor(st);
      vec2 f = fract(st);
      
      float a = random(i);
      float b = random(i + vec2(1.0, 0.0));
      float c = random(i + vec2(0.0, 1.0));
      float d = random(i + vec2(1.0, 1.0));
      
      vec2 u = f * f * (3.0 - 2.0 * f);
      
      return mix(a, b, u.x) + (c - a) * u.y * (1.0 - u.x) + (d - b) * u.x * u.y;
    }

    float fbm(vec2 st) {
      float value = 0.0;
      float amplitude = 0.5;
      float frequency = 0.0;
      
      for (int i = 0; i < 6; i++) {
        value += amplitude * noise(st);
        st *= 2.0;
        amplitude *= 0.5;
      }
      return value;
    }

    vec3 distortedNoise(vec2 uv) {
      vec2 st = uv * uNoiseScale;
      
      // Create complex distortion
      float time = uTime * 0.5;
      vec2 q = vec2(fbm(st + vec2(0.0, 0.0)),
                    fbm(st + vec2(5.2, 1.3)));
      
      vec2 r = vec2(fbm(st + 4.0 * q + vec2(1.7 - time * 0.15, 9.2)),
                    fbm(st + 4.0 * q + vec2(8.3 - time * 0.126, 2.8)));
      
      float f = fbm(st + r);
      
      // Mouse interaction distortion
      vec2 mouseInfluence = (uMouse - 0.5) * 2.0;
      float mouseDistance = length(uv - (uMouse * 0.5 + 0.5));
      float mouseEffect = 1.0 - smoothstep(0.0, 0.6, mouseDistance);
      
      // Add glitch effect
      float glitch = step(0.98, random(vec2(floor(uTime * 10.0), floor(uv.y * 50.0))));
      f += glitch * 0.5;
      
      // Color mapping with distortion
      vec3 color = vec3(0.0);
      
      color.r = f * f * f + 0.6 * f * f + 0.5 * f;
      color.g = f * f * f * f + 0.4 * f * f + 0.2 * f;
      color.b = f * f * f * f * f * f + 0.7 * f * f + 0.5 * f;
      
      // Add noise texture
      float noiseTexture = random(uv * 100.0 + time);
      color += noiseTexture * 0.1;
      
      // Mouse interaction color shift
      color += mouseEffect * vec3(0.3, 0.1, 0.2);
      
      // Scanline effect
      float scanline = sin(uv.y * 800.0) * 0.04;
      color += scanline;
      
      return color;
    }

    void main() {
      vec2 uv = vUv;
      
      // Add chromatic aberration
      float aberration = 0.005;
      vec3 color;
      color.r = distortedNoise(uv + vec2(aberration, 0.0)).r;
      color.g = distortedNoise(uv).g;
      color.b = distortedNoise(uv - vec2(aberration, 0.0)).b;
      
      // Add film grain
      float grain = random(uv + uTime) * 0.1;
      color += grain;
      
      // Vignette effect
      float vignette = 1.0 - length(uv - 0.5) * 1.2;
      color *= vignette;
      
      // Contrast and saturation boost
      color = pow(color, vec3(1.2));
      color *= 1.3;
      
      gl_FragColor = vec4(color, 0.95);
    }
  `

  useFrame((state) => {
    if (materialRef.current) {
      materialRef.current.uniforms.uTime.value = state.clock.elapsedTime
      materialRef.current.uniforms.uMouse.value = [mousePosition.x, mousePosition.y]

      // Dynamic distortion based on time
      const distortion = 0.2 + Math.sin(state.clock.elapsedTime * 0.5) * 0.1
      materialRef.current.uniforms.uDistortionStrength.value = distortion
    }
  })

  return (
    <mesh ref={meshRef} position={[0, 0, -1]}>
      <planeGeometry args={[25, 25, 100, 100]} />
      <shaderMaterial
        ref={materialRef}
        uniforms={uniforms}
        vertexShader={vertexShader}
        fragmentShader={fragmentShader}
        transparent
      />
    </mesh>
  )
}

interface NoiseParticlesProps {
  count: number
  mousePosition: { x: number; y: number }
}

function NoiseParticles({ count, mousePosition }: NoiseParticlesProps) {
  const pointsRef = useRef<Points>(null)

  const particles = useMemo(() => {
    const positions = new Float32Array(count * 3)
    const colors = new Float32Array(count * 3)
    const sizes = new Float32Array(count)

    for (let i = 0; i < count; i++) {
      const i3 = i * 3

      // Random positions
      positions[i3] = (Math.random() - 0.5) * 20
      positions[i3 + 1] = (Math.random() - 0.5) * 20
      positions[i3 + 2] = (Math.random() - 0.5) * 10

      // Noise-based colors (red, white, cyan)
      const colorChoice = Math.random()
      if (colorChoice < 0.33) {
        colors[i3] = 1.0 // Red
        colors[i3 + 1] = 0.0
        colors[i3 + 2] = 0.0
      } else if (colorChoice < 0.66) {
        colors[i3] = 1.0 // White
        colors[i3 + 1] = 1.0
        colors[i3 + 2] = 1.0
      } else {
        colors[i3] = 0.0 // Cyan
        colors[i3 + 1] = 1.0
        colors[i3 + 2] = 1.0
      }

      sizes[i] = Math.random() * 0.03 + 0.01
    }

    return { positions, colors, sizes }
  }, [count])

  useFrame((state) => {
    if (pointsRef.current) {
      const positions = pointsRef.current.geometry.attributes.position.array as Float32Array

      for (let i = 0; i < count; i++) {
        const i3 = i * 3

        // Chaotic movement
        positions[i3] += (Math.random() - 0.5) * 0.02
        positions[i3 + 1] += (Math.random() - 0.5) * 0.02
        positions[i3 + 2] += Math.sin(state.clock.elapsedTime * 3 + i * 0.1) * 0.01

        // Mouse repulsion
        const mouseInfluence =
          1 / (1 + Math.abs(positions[i3] - mousePosition.x * 10) + Math.abs(positions[i3 + 1] - mousePosition.y * 10))
        if (mouseInfluence > 0.1) {
          positions[i3] += (Math.random() - 0.5) * 0.1
          positions[i3 + 1] += (Math.random() - 0.5) * 0.1
        }

        // Boundary wrapping
        if (Math.abs(positions[i3]) > 10) positions[i3] *= -0.8
        if (Math.abs(positions[i3 + 1]) > 10) positions[i3 + 1] *= -0.8
      }

      pointsRef.current.geometry.attributes.position.needsUpdate = true
    }
  })

  return (
    <points ref={pointsRef}>
      <bufferGeometry>
        <bufferAttribute attach="attributes-position" count={count} array={particles.positions} itemSize={3} />
        <bufferAttribute attach="attributes-color" count={count} array={particles.colors} itemSize={3} />
        <bufferAttribute attach="attributes-size" count={count} array={particles.sizes} itemSize={1} />
      </bufferGeometry>
      <pointsMaterial size={0.02} vertexColors transparent opacity={0.8} sizeAttenuation blending={2} />
    </points>
  )
}

interface GlitchTextProps {
  text: string
  className?: string
  fontSize?: string
  fontFamily?: string
  fontWeight?: string
  color?: string
  glitchIntensity?: number
  glitchFrequency?: number
}

export function GlitchText({
  text,
  className = "",
  fontSize = "4rem",
  fontFamily = "inherit",
  fontWeight = "900",
  color = "#ffffff",
  glitchIntensity = 0.8,
  glitchFrequency = 100,
}: GlitchTextProps) {
  const textRef = useRef<HTMLHeadingElement>(null)

  useEffect(() => {
    if (!textRef.current) return

    const element = textRef.current
    const originalText = text

    // Create glitch effect
    const glitchChars = "!@#$%^&*()_+-=[]{}|;:,.<>?"

    const glitchAnimation = () => {
      if (Math.random() > 1 - glitchIntensity * 0.05) {
        // Random glitch based on intensity
        const glitchedText = originalText
          .split("")
          .map((char) => {
            if (Math.random() > 1 - glitchIntensity * 0.2) {
              return glitchChars[Math.floor(Math.random() * glitchChars.length)]
            }
            return char
          })
          .join("")

        element.textContent = glitchedText

        setTimeout(
          () => {
            element.textContent = originalText
          },
          50 + Math.random() * (100 * glitchIntensity),
        )
      }
    }

    const interval = setInterval(glitchAnimation, glitchFrequency)

    // GSAP glitch effects with intensity
    gsap.to(element, {
      textShadow: `${2 * glitchIntensity}px 0 #ff0000, ${-2 * glitchIntensity}px 0 #00ffff`,
      duration: 0.1,
      repeat: -1,
      yoyo: true,
      ease: "power2.inOut",
    })

    return () => {
      clearInterval(interval)
    }
  }, [text, glitchIntensity, glitchFrequency])

  return (
    <h1
      ref={textRef}
      className={cn("relative", className)}
      style={{
        fontSize,
        fontFamily,
        fontWeight,
        color,
        textShadow: `2px 0 #ff0000, -2px 0 #00ffff, 0 0 20px rgba(255, 255, 255, 0.5)`,
      }}
    >
      {text}
    </h1>
  )
}

export interface VHSHeroProps {
  title?: string;
  badge?: string;
  subtitle?: React.ReactNode;
  ctaText?: string;
}

export function VHSHero({
  title = "VHS HERO SECTION",
  badge = "WITH NOISE",
  subtitle = (
    <>
      {">"} REALITY.CORRUPTED {"<"}
      <br />
      {">"} NOISE.AMPLIFIED {"<"}
    </>
  ),
  ctaText = "> ENTER_CHAOS <"
}: VHSHeroProps) {
  const heroRef = useRef<HTMLDivElement>(null)
  const titleRef = useRef<HTMLDivElement>(null)
  const subtitleRef = useRef<HTMLParagraphElement>(null)
  const buttonRef = useRef<HTMLDivElement>(null)
  const canvasRef = useRef<HTMLDivElement>(null)

  const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 })
  const [isLoaded, setIsLoaded] = useState(false)

  const handleMouseMove = useCallback((event: MouseEvent) => {
    const x = (event.clientX / window.innerWidth - 0.5) * 2
    const y = (event.clientY / window.innerHeight - 0.5) * 2
    setMousePosition({ x, y })
  }, [])

  useEffect(() => {
    window.addEventListener("mousemove", handleMouseMove)
    return () => window.removeEventListener("mousemove", handleMouseMove)
  }, [handleMouseMove])

  useEffect(() => {
    const timer = setTimeout(() => setIsLoaded(true), 1000)
    return () => clearTimeout(timer)
  }, [])

  useEffect(() => {
    if (!isLoaded) return

    const ctx = gsap.context(() => {
      // Set initial states
      gsap.set([titleRef.current, subtitleRef.current, buttonRef.current], {
        opacity: 0,
        y: 100,
        scale: 0.8,
        filter: "blur(10px)",
      })

      gsap.set(canvasRef.current, {
        opacity: 0,
        scale: 1.2,
      })

      // Create aggressive timeline
      const tl = gsap.timeline({ delay: 0.2 })

      // Canvas entrance with distortion
      tl.to(canvasRef.current, {
        opacity: 1,
        scale: 1,
        duration: 2,
        ease: "power4.out",
      })

      // Aggressive text entrance
      tl.to(
        titleRef.current,
        {
          opacity: 1,
          y: 0,
          scale: 1,
          filter: "blur(0px)",
          duration: 1.5,
          ease: "back.out(2)",
        },
        "-=1.5",
      )
        .to(
          subtitleRef.current,
          {
            opacity: 1,
            y: 0,
            scale: 1,
            filter: "blur(0px)",
            duration: 1.2,
            ease: "power3.out",
          },
          "-=1",
        )
        .to(
          buttonRef.current,
          {
            opacity: 1,
            y: 0,
            scale: 1,
            filter: "blur(0px)",
            duration: 1,
            ease: "power3.out",
          },
          "-=0.6",
        )

      // Glitch effects
      const glitchTl = gsap.timeline({ repeat: -1, repeatDelay: 2 })
      glitchTl
        .to(heroRef.current, {
          filter: "hue-rotate(180deg) saturate(2)",
          duration: 0.1,
        })
        .to(heroRef.current, {
          filter: "none",
          duration: 0.1,
        })
        .to(heroRef.current, {
          x: 5,
          duration: 0.05,
        })
        .to(heroRef.current, {
          x: -5,
          duration: 0.05,
        })
        .to(heroRef.current, {
          x: 0,
          duration: 0.05,
        })

      // Mouse interaction chaos
      const handleMouseMove = (e: MouseEvent) => {
        const x = (e.clientX / window.innerWidth - 0.5) * 30
        const y = (e.clientY / window.innerHeight - 0.5) * 30

        gsap.to(titleRef.current, {
          x: x * 0.1,
          y: y * 0.05,
          rotationX: y * 0.02,
          rotationY: x * 0.02,
          duration: 0.3,
          ease: "power2.out",
        })
      }

      window.addEventListener("mousemove", handleMouseMove)

      return () => {
        window.removeEventListener("mousemove", handleMouseMove)
      }
    }, heroRef)

    return () => ctx.revert()
  }, [isLoaded])

  return (
    <div className="relative min-h-screen w-full overflow-hidden bg-black">
      {/* Distorted WebGL Background */}
      <div ref={canvasRef} className="absolute inset-0 z-0">
        <Canvas
          camera={{ position: [0, 0, 5], fov: 75 }}
          style={{ background: "linear-gradient(135deg, #000000 0%, #1a0000 50%, #000000 100%)" }}
        >
          <DistortionBackground mousePosition={mousePosition} />
          <NoiseParticles count={800} mousePosition={mousePosition} />
        </Canvas>
      </div>

      {/* Noise overlay */}
      <div
        className="absolute inset-0 z-10 opacity-20 pointer-events-none"
        style={{
          backgroundImage: `url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E")`,
        }}
      />

      {/* Hero Content */}
      <div ref={heroRef} className="relative z-20 flex min-h-screen items-center justify-center px-6">
        <div className="text-center max-w-5xl mx-auto pointer-events-auto">
          <div ref={titleRef}>
            <GlitchText
              text={title}
              fontSize="clamp(4rem, 12vw, 12rem)"
              fontFamily="'Courier New', monospace"
              fontWeight="900"
              color="#ffffff"
              glitchIntensity={0.9}
              glitchFrequency={80}
              className="leading-none tracking-tighter"
            />
          </div>

          <div className="mt-4">
            <GlitchText
              text={badge}
              fontSize="clamp(1.5rem, 4vw, 3rem)"
              fontFamily="'Courier New', monospace"
              fontWeight="400"
              color="#ff0000"
              glitchIntensity={0.6}
              glitchFrequency={150}
              className="tracking-widest opacity-80"
            />
          </div>

          <p
            ref={subtitleRef}
            className="text-xl md:text-2xl lg:text-3xl text-red-400 mb-12 max-w-3xl mx-auto leading-relaxed font-mono tracking-wider uppercase"
            style={{
              textShadow: "0 0 10px rgba(255, 0, 0, 0.5), 2px 0 #00ffff, -2px 0 #ff0000",
            }}
          >
            {subtitle}
          </p>

          <div ref={buttonRef}>
            <button
              className="inline-flex items-center justify-center focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-red-500 disabled:pointer-events-none disabled:opacity-50 group relative overflow-hidden bg-red-600/20 backdrop-blur-sm border-2 border-red-500 text-red-400 hover:bg-red-600/40 hover:text-white px-10 py-4 text-lg font-mono uppercase tracking-wider transition-all duration-300 transform hover:scale-105"
            >
              <span className="relative z-10">
                {ctaText}
              </span>
              <div className="absolute inset-0 bg-gradient-to-r from-transparent via-red-500/20 to-transparent transform -translate-x-full group-hover:translate-x-full transition-transform duration-500" />
            </button>
          </div>
        </div>
      </div>

      {/* Glitch UI Elements */}
      <div className="absolute top-8 left-8 z-30 pointer-events-none">
        <div className="text-red-400 font-mono text-xs tracking-wider">{">"} SYSTEM.CORRUPTED</div>
      </div>

      <div className="absolute top-8 right-8 z-30 pointer-events-none">
        <div className="text-cyan-400 font-mono text-xs tracking-wider">ERROR_404 {"<"}</div>
      </div>

      <div className="absolute bottom-8 left-1/2 transform -translate-x-1/2 z-30 pointer-events-none">
        <div className="w-px h-16 bg-gradient-to-b from-red-500/60 to-transparent animate-pulse" />
      </div>

      {/* Scanlines */}
      <div
        className="absolute inset-0 z-15 pointer-events-none opacity-10"
        style={{
          background:
            "repeating-linear-gradient(0deg, transparent, transparent 2px, rgba(255, 255, 255, 0.1) 2px, rgba(255, 255, 255, 0.1) 4px)",
        }}
      />
    </div>
  )
}

--- FILE: frontend-web/registry/hero/VideoScrollHero.tsx ---

import React, { useRef, useEffect, useState } from "react";
import { motion, useReducedMotion } from "framer-motion";
import { cn } from "../core/utils";

export interface VideoScrollHeroProps {
  videoSrc?: string;
  title?: string;
  subtitle?: string;
  enableAnimations?: boolean;
  className?: string;
  startScale?: number;
}

export function VideoScrollHero({
  videoSrc = "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4",
  title = "Scroll to Scale",
  subtitle = "Watch as the video expands with your scroll",
  enableAnimations = true,
  className = "",
  startScale = 0.25,
}: VideoScrollHeroProps) {
  const containerRef = useRef<HTMLDivElement>(null);
  const shouldReduceMotion = useReducedMotion();
  const [scrollScale, setScrollScale] = useState(startScale);

  useEffect(() => {
    if (!enableAnimations || shouldReduceMotion) return;

    const handleScroll = () => {
      if (!containerRef.current) return;

      const rect = containerRef.current.getBoundingClientRect();
      const containerHeight = containerRef.current.offsetHeight;
      const windowHeight = window.innerHeight;
      
      // Calculate scroll progress based on container position
      const scrolled = Math.max(0, -rect.top);
      const maxScroll = containerHeight - windowHeight;
      const progress = Math.min(scrolled / maxScroll, 1);
      
      // Scale from startScale to 1
      const newScale = startScale + (progress * (1 - startScale));
      setScrollScale(newScale);
    };

    window.addEventListener('scroll', handleScroll);
    handleScroll(); // Initial calculation

    return () => window.removeEventListener('scroll', handleScroll);
  }, [enableAnimations, shouldReduceMotion, startScale]);

  const shouldAnimate = enableAnimations && !shouldReduceMotion;

  return (
    <div className={cn("relative", className)}>
      {/* Hero Section with Video */}
      <div
        ref={containerRef}
        className="relative h-[200vh] bg-white dark:bg-zinc-950"
      >
        {/* Fixed Video Container */}
        <div className="sticky top-0 w-full h-screen flex items-center justify-center z-10">
          <div
            className="relative flex items-center justify-center will-change-transform"
            style={{
              transform: shouldAnimate ? `scale(${scrollScale})` : 'scale(1)',
              transformOrigin: "center center",
            }}
          >
            <video
              autoPlay
              loop
              muted
              playsInline
              className="w-[80vw] max-w-4xl h-[60vh] object-cover shadow-2xl rounded-2xl"
            >
              <source src={videoSrc} type="video/mp4" />
              Your browser does not support the video tag.
            </video>

            {/* Video Overlay Content */}
            <motion.div
              className="absolute inset-0 bg-black/20 backdrop-blur-[1px] flex items-center justify-center rounded-2xl"
              initial={{ opacity: 0 }}
              animate={{ opacity: 1 }}
              transition={{ delay: 0.5, duration: 0.8 }}
            >
              <div className="text-center text-white">
                <motion.h1
                  className="text-2xl md:text-4xl lg:text-6xl font-bold mb-4"
                  initial={{ opacity: 0, y: 30 }}
                  animate={{ opacity: 1, y: 0 }}
                  transition={{
                    delay: 0.8,
                    duration: 0.8,
                    type: "spring",
                    stiffness: 200,
                    damping: 25,
                  }}
                >
                  {title}
                </motion.h1>
                <motion.p
                  className="text-sm md:text-lg lg:text-xl text-white/80 max-w-2xl px-4 mx-auto"
                  initial={{ opacity: 0, y: 20 }}
                  animate={{ opacity: 1, y: 0 }}
                  transition={{
                    delay: 1.0,
                    duration: 0.8,
                    type: "spring",
                    stiffness: 200,
                    damping: 25,
                  }}
                >
                  {subtitle}
                </motion.p>
              </div>
            </motion.div>
          </div>
        </div>
      </div>
    </div>
  );
}

--- FILE: frontend-web/registry/media/DynamicFrameLayout.tsx ---

import React, { useState, useEffect, useRef } from "react"
import { motion } from "framer-motion"
import { cn } from "../core/utils"

export interface Frame {
  id: number | string
  video: string
  defaultPos: { x: number; y: number; w: number; h: number }
  corner?: string
  edgeHorizontal?: string
  edgeVertical?: string
  mediaSize?: number
  borderThickness?: number
  borderSize?: number
}

interface FrameComponentProps {
  video: string
  width: number | string
  height: number | string
  className?: string
  corner?: string
  edgeHorizontal?: string
  edgeVertical?: string
  mediaSize?: number
  borderThickness?: number
  borderSize?: number
  showFrame: boolean
  isHovered: boolean
}

function FrameComponent({
  video,
  width,
  height,
  className = "",
  corner,
  edgeHorizontal,
  edgeVertical,
  mediaSize = 1,
  borderThickness = 0,
  borderSize = 100,
  showFrame,
  isHovered,
}: FrameComponentProps) {
  const videoRef = useRef<HTMLVideoElement>(null)

  useEffect(() => {
    if (isHovered) {
      videoRef.current?.play().catch(() => {})
    } else {
      videoRef.current?.pause()
    }
  }, [isHovered])

  return (
    <div
      className={cn("relative", className)}
      style={{
        width,
        height,
        transition: "width 0.3s ease-in-out, height 0.3s ease-in-out",
      }}
    >
      <div className="relative w-full h-full overflow-hidden">
        <div
          className="absolute inset-0 flex items-center justify-center bg-black"
          style={{
            zIndex: 1,
            transition: "all 0.3s ease-in-out",
            padding: showFrame ? `${borderThickness}px` : "0",
            width: showFrame ? `${borderSize}%` : "100%",
            height: showFrame ? `${borderSize}%` : "100%",
            left: showFrame ? `${(100 - borderSize) / 2}%` : "0",
            top: showFrame ? `${(100 - borderSize) / 2}%` : "0",
          }}
        >
          <div
            className="w-full h-full overflow-hidden"
            style={{
              transform: `scale(${mediaSize})`,
              transformOrigin: "center",
              transition: "transform 0.3s ease-in-out",
            }}
          >
            <video
              className="w-full h-full object-cover"
              src={video}
              loop
              muted
              playsInline
              ref={videoRef}
            />
          </div>
        </div>

        {/* Decorative Frame Overlay */}
        {showFrame && (
          <div className="absolute inset-0 pointer-events-none" style={{ zIndex: 2 }}>
             {/* If images are provided, use them; otherwise, use a CSS border fallback */}
            {(corner && edgeHorizontal && edgeVertical) ? (
                <>
                    <div
                    className="absolute top-0 left-0 w-16 h-16 bg-contain bg-no-repeat"
                    style={{ backgroundImage: `url(${corner})` }}
                    />
                    <div
                    className="absolute top-0 right-0 w-16 h-16 bg-contain bg-no-repeat"
                    style={{ backgroundImage: `url(${corner})`, transform: "scaleX(-1)" }}
                    />
                    <div
                    className="absolute bottom-0 left-0 w-16 h-16 bg-contain bg-no-repeat"
                    style={{ backgroundImage: `url(${corner})`, transform: "scaleY(-1)" }}
                    />
                    <div
                    className="absolute bottom-0 right-0 w-16 h-16 bg-contain bg-no-repeat"
                    style={{ backgroundImage: `url(${corner})`, transform: "scale(-1, -1)" }}
                    />

                    <div
                    className="absolute top-0 left-16 right-16 h-16"
                    style={{
                        backgroundImage: `url(${edgeHorizontal})`,
                        backgroundSize: "auto 64px",
                        backgroundRepeat: "repeat-x",
                    }}
                    />
                    <div
                    className="absolute bottom-0 left-16 right-16 h-16"
                    style={{
                        backgroundImage: `url(${edgeHorizontal})`,
                        backgroundSize: "auto 64px",
                        backgroundRepeat: "repeat-x",
                        transform: "rotate(180deg)",
                    }}
                    />
                    <div
                    className="absolute left-0 top-16 bottom-16 w-16"
                    style={{
                        backgroundImage: `url(${edgeVertical})`,
                        backgroundSize: "64px auto",
                        backgroundRepeat: "repeat-y",
                    }}
                    />
                    <div
                    className="absolute right-0 top-16 bottom-16 w-16"
                    style={{
                        backgroundImage: `url(${edgeVertical})`,
                        backgroundSize: "64px auto",
                        backgroundRepeat: "repeat-y",
                        transform: "scaleX(-1)",
                    }}
                    />
                </>
            ) : (
                <div className="absolute inset-0 border-[8px] border-white/20 dark:border-white/10 m-2 rounded-xl" />
            )}
          </div>
        )}
      </div>
    </div>
  )
}

export interface DynamicFrameLayoutProps {
  frames: Frame[]
  className?: string
  showFrames?: boolean
  hoverSize?: number
  gapSize?: number
}

export function DynamicFrameLayout({ 
  frames: initialFrames, 
  className,
  showFrames = false,
  hoverSize = 6,
  gapSize = 4
}: DynamicFrameLayoutProps) {
  const [frames] = useState<Frame[]>(initialFrames)
  const [hovered, setHovered] = useState<{ row: number; col: number } | null>(null)

  const getRowSizes = () => {
    if (hovered === null) return "4fr 4fr 4fr"
    const { row } = hovered
    const nonHoveredSize = (12 - hoverSize) / 2
    return [0, 1, 2].map((r) => (r === row ? `${hoverSize}fr` : `${nonHoveredSize}fr`)).join(" ")
  }

  const getColSizes = () => {
    if (hovered === null) return "4fr 4fr 4fr"
    const { col } = hovered
    const nonHoveredSize = (12 - hoverSize) / 2
    return [0, 1, 2].map((c) => (c === col ? `${hoverSize}fr` : `${nonHoveredSize}fr`)).join(" ")
  }

  const getTransformOrigin = (x: number, y: number) => {
    const vertical = y === 0 ? "top" : y === 4 ? "center" : "bottom"
    const horizontal = x === 0 ? "left" : x === 4 ? "center" : "right"
    return `${vertical} ${horizontal}`
  }

  return (
    <div
      className={cn("relative w-full h-full", className)}
      style={{
        display: "grid",
        gridTemplateRows: getRowSizes(),
        gridTemplateColumns: getColSizes(),
        gap: `${gapSize}px`,
        transition: "grid-template-rows 0.4s ease, grid-template-columns 0.4s ease",
      }}
    >
      {frames.map((frame) => {
        const row = Math.floor(frame.defaultPos.y / 4)
        const col = Math.floor(frame.defaultPos.x / 4)
        const transformOrigin = getTransformOrigin(frame.defaultPos.x, frame.defaultPos.y)

        return (
          <motion.div
            key={frame.id}
            className="relative"
            style={{
              transformOrigin,
              transition: "transform 0.4s ease",
            }}
            onMouseEnter={() => setHovered({ row, col })}
            onMouseLeave={() => setHovered(null)}
          >
            <FrameComponent
              video={frame.video}
              width="100%"
              height="100%"
              className="absolute inset-0"
              corner={frame.corner}
              edgeHorizontal={frame.edgeHorizontal}
              edgeVertical={frame.edgeVertical}
              mediaSize={frame.mediaSize}
              borderThickness={frame.borderThickness}
              borderSize={frame.borderSize}
              showFrame={showFrames}
              isHovered={hovered?.row === row && hovered?.col === col}
            />
          </motion.div>
        )
      })}
    </div>
  )
}

--- FILE: frontend-web/registry/media/HeroVideo.tsx ---

import * as React from "react"
import {
  HTMLMotionProps,
  MotionValue,
  motion,
  useMotionTemplate,
  useScroll,
  useTransform,
} from "framer-motion"
import { cn } from "../core/utils"

export type AnimateT = "left" | "right" | "top" | "bottom" | "z" | "blur" | undefined

const SPRING_CONFIG = {
  type: "spring",
  stiffness: 100,
  damping: 16,
  mass: 0.75,
  restDelta: 0.005,
  duration: 0.3,
}

const useAnimationVariants = (animate: AnimateT) =>
  React.useMemo(
    () => ({
      hidden: {
        x: animate === "left" ? "-100%" : animate === "right" ? "100%" : 0,
        y: animate === "top" ? "-100%" : animate === "bottom" ? "100%" : 0,
        scale: animate === "z" ? 0 : 1,
        filter: animate === "blur" ? "blur(10px)" : "blur(0px)",
        opacity: 0,
      },
      visible: {
        x: 0,
        y: 0,
        scale: 1,
        filter: "blur(0px)",
        opacity: 1,
      },
    }),
    [animate]
  )

export const ContainerStagger = React.forwardRef<
  HTMLDivElement,
  HTMLMotionProps<"div">
>(({ children, className, ...props }, ref) => {
  return (
    <motion.div
      className={cn("relative", className)}
      ref={ref}
      initial="hidden"
      whileInView={"visible"}
      viewport={{ once: true || props.viewport?.once, ...props.viewport }}
      transition={{
        staggerChildren: props.transition?.staggerChildren || 0.2,
        ...props.transition,
      }}
      {...props}
    >
      {children}
    </motion.div>
  )
})
ContainerStagger.displayName = "ContainerStagger"

export interface ContainerAnimatedProps extends HTMLMotionProps<"div"> {
  animation?: AnimateT
}

interface ContainerScrollValue {
  scrollYProgress: MotionValue<number>
}

const ContainerScrollContext = React.createContext<
  ContainerScrollValue | undefined
>(undefined)

function useContainerScrollContext() {
  const context = React.useContext(ContainerScrollContext)
  if (!context) {
    throw new Error(
      "useContainerScrollContext must be used within <ContainerScroll> component"
    )
  }
  return context
}

export interface ContainerScrollProps extends React.HTMLAttributes<HTMLDivElement> {}

export const ContainerScroll = ({
  children,
  className,
  ...props
}: ContainerScrollProps) => {
  const scrollRef = React.useRef<HTMLDivElement>(null)
  const { scrollYProgress } = useScroll({
    target: scrollRef,
  })

  return (
    <ContainerScrollContext.Provider value={{ scrollYProgress }}>
      <section
        className={cn(
          "relative min-h-[120vh] w-full pb-[30%] pt-8 ",
          className
        )}
        {...props}
        ref={scrollRef}
      >
        {children}
      </section>
    </ContainerScrollContext.Provider>
  )
}
ContainerScroll.displayName = "ContainerScroll"

export const ContainerAnimated = React.forwardRef<
  HTMLDivElement,
  ContainerAnimatedProps
>(({ animation, children, className, ...props }, ref) => {
  const variants = useAnimationVariants(animation)

  return (
    <motion.div
      transition={SPRING_CONFIG || props.transition}
      ref={ref}
      variants={variants}
      className={className}
      {...props}
    >
      {children}
    </motion.div>
  )
})
ContainerAnimated.displayName = "ContainerAnimated"

export interface ContainerInsetProps extends HTMLMotionProps<"div"> {
  translateYRange?: [string, string]
  insetYRange?: [number, number]
  insetXRange?: [number, number]
  roundednessRange?: [number, number]
}

export const ContainerInset = React.forwardRef<HTMLDivElement, ContainerInsetProps>(
  (
    {
      translateYRange = ["-25%", "50%"],
      insetYRange = [35, 0],
      insetXRange = [42, 0],
      roundednessRange = [1000, 16],
      children,
      className,
      ...props
    },
    ref
  ) => {
    const { scrollYProgress } = useContainerScrollContext()
    const y = useTransform(scrollYProgress, [0, 1], translateYRange)

    const insetY = useTransform(scrollYProgress, [0, 1], insetYRange)
    const insetX = useTransform(scrollYProgress, [0, 1], insetXRange)
    const roundedness = useTransform(scrollYProgress, [0, 1], roundednessRange)

    const clipPath = useMotionTemplate`inset(${insetY}% ${insetX}% ${insetY}% ${insetX}% round ${roundedness}px)`

    const style = React.useMemo(
      () => ({ y, clipPath, ...props.style }),
      [y, clipPath, props.style]
    )
    return (
      <motion.div
        transition={SPRING_CONFIG || props.transition}
        ref={ref}
        className={cn("origin-top overflow-hidden", className)}
        style={style}
        {...props}
      >
        {children}
      </motion.div>
    )
  }
)
ContainerInset.displayName = "ContainerInset"

--- FILE: frontend-web/registry/media/HeroVideoDialog.tsx ---

import React, { useState } from "react";
import { AnimatePresence, motion } from "framer-motion";
import { Play, X } from "lucide-react";
import { cn } from "../core/utils";

type AnimationStyle =
  | "from-bottom"
  | "from-center"
  | "from-top"
  | "from-left"
  | "from-right"
  | "fade"
  | "top-in-bottom-out"
  | "left-in-right-out";

export interface HeroVideoProps {
  animationStyle?: AnimationStyle;
  videoSrc: string;
  thumbnailSrc: string;
  thumbnailAlt?: string;
  className?: string;
}

const animationVariants = {
  "from-bottom": {
    initial: { y: "100%", opacity: 0 },
    animate: { y: 0, opacity: 1 },
    exit: { y: "100%", opacity: 0 },
  },
  "from-center": {
    initial: { scale: 0.5, opacity: 0 },
    animate: { scale: 1, opacity: 1 },
    exit: { scale: 0.5, opacity: 0 },
  },
  "from-top": {
    initial: { y: "-100%", opacity: 0 },
    animate: { y: 0, opacity: 1 },
    exit: { y: "-100%", opacity: 0 },
  },
  "from-left": {
    initial: { x: "-100%", opacity: 0 },
    animate: { x: 0, opacity: 1 },
    exit: { x: "-100%", opacity: 0 },
  },
  "from-right": {
    initial: { x: "100%", opacity: 0 },
    animate: { x: 0, opacity: 1 },
    exit: { x: "100%", opacity: 0 },
  },
  fade: {
    initial: { opacity: 0 },
    animate: { opacity: 1 },
    exit: { opacity: 0 },
  },
  "top-in-bottom-out": {
    initial: { y: "-100%", opacity: 0 },
    animate: { y: 0, opacity: 1 },
    exit: { y: "100%", opacity: 0 },
  },
  "left-in-right-out": {
    initial: { x: "-100%", opacity: 0 },
    animate: { x: 0, opacity: 1 },
    exit: { x: "100%", opacity: 0 },
  },
};

export function HeroVideoDialog({
  animationStyle = "from-center",
  videoSrc,
  thumbnailSrc,
  thumbnailAlt = "Video thumbnail",
  className,
}: HeroVideoProps) {
  const [isVideoOpen, setIsVideoOpen] = useState(false);
  const selectedAnimation = animationVariants[animationStyle];

  return (
    <div className={cn("relative", className)}>
      <div
        className="relative cursor-pointer group"
        onClick={() => setIsVideoOpen(true)}
      >
        <img
          src={thumbnailSrc}
          alt={thumbnailAlt}
          width={1920}
          height={1080}
          className="w-full h-auto object-cover transition-all duration-200 group-hover:brightness-[0.8] ease-out rounded-xl shadow-lg border dark:border-neutral-800"
        />
        <div className="absolute inset-0 flex items-center justify-center group-hover:scale-100 scale-[0.9] transition-all duration-200 ease-out rounded-2xl pointer-events-none">
          <div className="bg-indigo-600/10 flex items-center justify-center rounded-full backdrop-blur-md size-28">
            <div
              className={`flex items-center justify-center bg-gradient-to-b from-indigo-500/30 to-indigo-600 shadow-md rounded-full size-20 transition-all ease-out duration-200 relative group-hover:scale-[1.2] scale-100`}
            >
              <Play
                className="size-8 text-white fill-white group-hover:scale-105 scale-100 transition-transform duration-200 ease-out"
                style={{
                  filter:
                    "drop-shadow(0 4px 3px rgb(0 0 0 / 0.07)) drop-shadow(0 2px 2px rgb(0 0 0 / 0.06))",
                }}
              />
            </div>
          </div>
        </div>
      </div>
      <AnimatePresence>
        {isVideoOpen && (
          <motion.div
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 }}
            onClick={() => setIsVideoOpen(false)}
            exit={{ opacity: 0 }}
            className="fixed inset-0 z-50 flex items-center justify-center bg-black/80 backdrop-blur-md"
          >
            <motion.div
              {...selectedAnimation}
              transition={{ type: "spring", damping: 30, stiffness: 300 }}
              className="relative w-full max-w-5xl aspect-video mx-4 md:mx-0"
              onClick={(e) => e.stopPropagation()}
            >
              <motion.button 
                className="absolute -top-16 right-0 text-white text-xl bg-neutral-900/50 ring-1 ring-white/10 backdrop-blur-md rounded-full p-2 hover:bg-neutral-800 transition-colors"
                onClick={() => setIsVideoOpen(false)}
              >
                <X className="size-5" />
              </motion.button>
              <div className="size-full border border-white/20 rounded-2xl overflow-hidden isolate z-[1] relative shadow-2xl bg-black">
                <iframe
                  src={videoSrc}
                  className="size-full rounded-2xl"
                  allowFullScreen
                  allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
                ></iframe>
              </div>
            </motion.div>
          </motion.div>
        )}
      </AnimatePresence>
    </div>
  );
}

--- FILE: frontend-web/registry/media/ScrollExpandMedia.tsx ---

import React, {
  useEffect,
  useRef,
  useState,
  ReactNode,
} from 'react';
import { motion } from 'framer-motion';
import { cn } from '../core/utils';

export interface ScrollExpandMediaProps {
  mediaType?: 'video' | 'image';
  mediaSrc: string;
  posterSrc?: string;
  bgImageSrc: string;
  title?: string;
  date?: string;
  scrollToExpand?: string;
  textBlend?: boolean;
  children?: ReactNode;
  className?: string;
}

export const ScrollExpandMedia = ({
  mediaType = 'video',
  mediaSrc,
  posterSrc,
  bgImageSrc,
  title,
  date,
  scrollToExpand,
  textBlend,
  children,
  className,
}: ScrollExpandMediaProps) => {
  const [scrollProgress, setScrollProgress] = useState<number>(0);
  const [showContent, setShowContent] = useState<boolean>(false);
  const [mediaFullyExpanded, setMediaFullyExpanded] = useState<boolean>(false);
  const [touchStartY, setTouchStartY] = useState<number>(0);
  const [isMobileState, setIsMobileState] = useState<boolean>(false);

  const sectionRef = useRef<HTMLDivElement | null>(null);

  useEffect(() => {
    setScrollProgress(0);
    setShowContent(false);
    setMediaFullyExpanded(false);
  }, [mediaType]);

  useEffect(() => {
    const handleWheel = (e: WheelEvent) => {
      if (mediaFullyExpanded && e.deltaY < 0 && window.scrollY <= 5) {
        setMediaFullyExpanded(false);
        e.preventDefault();
      } else if (!mediaFullyExpanded) {
        e.preventDefault();
        const scrollDelta = e.deltaY * 0.0009;
        const newProgress = Math.min(
          Math.max(scrollProgress + scrollDelta, 0),
          1
        );
        setScrollProgress(newProgress);

        if (newProgress >= 1) {
          setMediaFullyExpanded(true);
          setShowContent(true);
        } else if (newProgress < 0.75) {
          setShowContent(false);
        }
      }
    };

    const handleTouchStart = (e: TouchEvent) => {
      setTouchStartY(e.touches[0].clientY);
    };

    const handleTouchMove = (e: TouchEvent) => {
      if (!touchStartY) return;

      const touchY = e.touches[0].clientY;
      const deltaY = touchStartY - touchY;

      if (mediaFullyExpanded && deltaY < -20 && window.scrollY <= 5) {
        setMediaFullyExpanded(false);
        e.preventDefault();
      } else if (!mediaFullyExpanded) {
        e.preventDefault();
        // Increase sensitivity for mobile, especially when scrolling back
        const scrollFactor = deltaY < 0 ? 0.008 : 0.005; 
        const scrollDelta = deltaY * scrollFactor;
        const newProgress = Math.min(
          Math.max(scrollProgress + scrollDelta, 0),
          1
        );
        setScrollProgress(newProgress);

        if (newProgress >= 1) {
          setMediaFullyExpanded(true);
          setShowContent(true);
        } else if (newProgress < 0.75) {
          setShowContent(false);
        }

        setTouchStartY(touchY);
      }
    };

    const handleTouchEnd = (): void => {
      setTouchStartY(0);
    };

    const handleScroll = (): void => {
      if (!mediaFullyExpanded) {
        window.scrollTo(0, 0);
      }
    };

    const wheelListener = (e: Event) => handleWheel(e as unknown as WheelEvent);
    const touchStartListener = (e: Event) => handleTouchStart(e as unknown as TouchEvent);
    const touchMoveListener = (e: Event) => handleTouchMove(e as unknown as TouchEvent);
    const touchEndListener = () => handleTouchEnd();

    window.addEventListener('wheel', wheelListener, { passive: false });
    window.addEventListener('scroll', handleScroll);
    window.addEventListener('touchstart', touchStartListener, { passive: false });
    window.addEventListener('touchmove', touchMoveListener, { passive: false });
    window.addEventListener('touchend', touchEndListener);

    return () => {
      window.removeEventListener('wheel', wheelListener);
      window.removeEventListener('scroll', handleScroll);
      window.removeEventListener('touchstart', touchStartListener);
      window.removeEventListener('touchmove', touchMoveListener);
      window.removeEventListener('touchend', touchEndListener);
    };
  }, [scrollProgress, mediaFullyExpanded, touchStartY]);

  useEffect(() => {
    const checkIfMobile = (): void => {
      setIsMobileState(window.innerWidth < 768);
    };

    checkIfMobile();
    window.addEventListener('resize', checkIfMobile);

    return () => window.removeEventListener('resize', checkIfMobile);
  }, []);

  const mediaWidth = 300 + scrollProgress * (isMobileState ? 650 : 1250);
  const mediaHeight = 400 + scrollProgress * (isMobileState ? 200 : 400);
  const textTranslateX = scrollProgress * (isMobileState ? 180 : 150);

  const firstWord = title ? title.split(' ')[0] : '';
  const restOfTitle = title ? title.split(' ').slice(1).join(' ') : '';

  return (
    <div
      ref={sectionRef}
      className={cn('transition-colors duration-700 ease-in-out overflow-x-hidden', className)}
    >
      <section className='relative flex flex-col items-center justify-start min-h-[100dvh]'>
        <div className='relative w-full flex flex-col items-center min-h-[100dvh]'>
          <motion.div
            className='absolute inset-0 z-0 h-full'
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 - scrollProgress }}
            transition={{ duration: 0.1 }}
          >
            <img
              src={bgImageSrc}
              alt='Background'
              width={1920}
              height={1080}
              className='w-screen h-screen object-cover object-center'
            />
            <div className='absolute inset-0 bg-black/10' />
          </motion.div>

          <div className='container mx-auto flex flex-col items-center justify-start relative z-10'>
            <div className='flex flex-col items-center justify-center w-full h-[100dvh] relative'>
              <div
                className='absolute z-0 top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 transition-none rounded-2xl'
                style={{
                  width: `${mediaWidth}px`,
                  height: `${mediaHeight}px`,
                  maxWidth: '95vw',
                  maxHeight: '85vh',
                  boxShadow: '0px 0px 50px rgba(0, 0, 0, 0.3)',
                }}
              >
                {mediaType === 'video' ? (
                  mediaSrc.includes('youtube.com') ? (
                    <div className='relative w-full h-full pointer-events-none'>
                      <iframe
                        width='100%'
                        height='100%'
                        src={
                          mediaSrc.includes('embed')
                            ? mediaSrc +
                              (mediaSrc.includes('?') ? '&' : '?') +
                              'autoplay=1&mute=1&loop=1&controls=0&showinfo=0&rel=0&disablekb=1&modestbranding=1'
                            : mediaSrc.replace('watch?v=', 'embed/') +
                              '?autoplay=1&mute=1&loop=1&controls=0&showinfo=0&rel=0&disablekb=1&modestbranding=1&playlist=' +
                              mediaSrc.split('v=')[1]
                        }
                        className='w-full h-full rounded-xl'
                        frameBorder='0'
                        allow='accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture'
                        allowFullScreen
                      />
                      <div
                        className='absolute inset-0 z-10'
                        style={{ pointerEvents: 'none' }}
                      ></div>

                      <motion.div
                        className='absolute inset-0 bg-black/30 rounded-xl'
                        initial={{ opacity: 0.7 }}
                        animate={{ opacity: 0.5 - scrollProgress * 0.3 }}
                        transition={{ duration: 0.2 }}
                      />
                    </div>
                  ) : (
                    <div className='relative w-full h-full pointer-events-none'>
                      <video
                        src={mediaSrc}
                        poster={posterSrc}
                        autoPlay
                        muted
                        loop
                        playsInline
                        preload='auto'
                        className='w-full h-full object-cover rounded-xl'
                        controls={false}
                        disablePictureInPicture
                        disableRemotePlayback
                      />
                      <div
                        className='absolute inset-0 z-10'
                        style={{ pointerEvents: 'none' }}
                      ></div>

                      <motion.div
                        className='absolute inset-0 bg-black/30 rounded-xl'
                        initial={{ opacity: 0.7 }}
                        animate={{ opacity: 0.5 - scrollProgress * 0.3 }}
                        transition={{ duration: 0.2 }}
                      />
                    </div>
                  )
                ) : (
                  <div className='relative w-full h-full'>
                    <img
                      src={mediaSrc}
                      alt={title || 'Media content'}
                      width={1280}
                      height={720}
                      className='w-full h-full object-cover rounded-xl'
                    />

                    <motion.div
                      className='absolute inset-0 bg-black/50 rounded-xl'
                      initial={{ opacity: 0.7 }}
                      animate={{ opacity: 0.7 - scrollProgress * 0.3 }}
                      transition={{ duration: 0.2 }}
                    />
                  </div>
                )}

                <div className='flex flex-col items-center text-center relative z-10 mt-4 transition-none'>
                  {date && (
                    <p
                      className='text-2xl text-blue-200'
                      style={{ transform: `translateX(-${textTranslateX}vw)` }}
                    >
                      {date}
                    </p>
                  )}
                  {scrollToExpand && (
                    <p
                      className='text-blue-200 font-medium text-center'
                      style={{ transform: `translateX(${textTranslateX}vw)` }}
                    >
                      {scrollToExpand}
                    </p>
                  )}
                </div>
              </div>

              <div
                className={`flex items-center justify-center text-center gap-4 w-full relative z-10 transition-none flex-col ${
                  textBlend ? 'mix-blend-difference' : 'mix-blend-normal'
                }`}
              >
                <motion.h2
                  className='text-4xl md:text-5xl lg:text-6xl font-bold text-blue-200 transition-none'
                  style={{ transform: `translateX(-${textTranslateX}vw)` }}
                >
                  {firstWord}
                </motion.h2>
                <motion.h2
                  className='text-4xl md:text-5xl lg:text-6xl font-bold text-center text-blue-200 transition-none'
                  style={{ transform: `translateX(${textTranslateX}vw)` }}
                >
                  {restOfTitle}
                </motion.h2>
              </div>
            </div>

            <motion.section
              className='flex flex-col w-full px-8 py-10 md:px-16 lg:py-20'
              initial={{ opacity: 0 }}
              animate={{ opacity: showContent ? 1 : 0 }}
              transition={{ duration: 0.7 }}
            >
              {children}
            </motion.section>
          </div>
        </div>
      </section>
    </div>
  );
};

--- FILE: frontend-web/registry/media/ThumbnailButton.tsx ---

import React, { useState, useRef, useEffect } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import { Play, X } from 'lucide-react';
import { cn } from '../core/utils';

export interface ThumbnailButtonProps {
  videoUrl?: string;
  youtubeId?: string;
  thumbnailUrl?: string;
  title?: string;
  className?: string;
}

const DEFAULT_VIDEO_FALLBACK_URL = 'https://www.w3schools.com/html/mov_bbb.mp4';
const DEFAULT_VIDEO_THUMBNAIL = 'https://images.unsplash.com/photo-1611162617474-5b21e879e113?q=80&w=640&auto=format&fit=crop';

const getYouTubeThumbnail = (id: string) => `https://img.youtube.com/vi/${id}/maxresdefault.jpg`;
const getYouTubeEmbedUrl = (id: string) => `https://www.youtube.com/embed/${id}?autoplay=1`;

export const ThumbnailButton: React.FC<ThumbnailButtonProps> = ({
  videoUrl,
  youtubeId,
  thumbnailUrl,
  title = 'Play Video',
  className = ''
}) => {
  const [isModalOpen, setIsModalOpen] = useState(false);
  const [buttonRect, setButtonRect] = useState<DOMRect | null>(null);
  const buttonRef = useRef<HTMLButtonElement>(null);

  const isYouTube = !!youtubeId;
  const finalThumbnail = thumbnailUrl || (isYouTube && youtubeId ? getYouTubeThumbnail(youtubeId) : DEFAULT_VIDEO_THUMBNAIL);
  const finalVideoUrl = isYouTube && youtubeId ? getYouTubeEmbedUrl(youtubeId) : videoUrl || DEFAULT_VIDEO_FALLBACK_URL;

  const handleOpenModal = () => {
    if (buttonRef.current) {
      setButtonRect(buttonRef.current.getBoundingClientRect());
    }
    setIsModalOpen(true);
  };

  const handleCloseModal = () => setIsModalOpen(false);

  const getTransformOrigin = () => {
    if (!buttonRect) return 'center center';
    const centerX = buttonRect.left + buttonRect.width / 2;
    const centerY = buttonRect.top + buttonRect.height / 2;
    return `${centerX}px ${centerY}px`;
  };

  useEffect(() => {
    const handleEsc = (e: KeyboardEvent) => {
      if (e.key === 'Escape') handleCloseModal();
    };
    if (isModalOpen) {
      document.addEventListener('keydown', handleEsc);
    }
    return () => document.removeEventListener('keydown', handleEsc);
  }, [isModalOpen]);

  return (
    <>
      <motion.button
        ref={buttonRef}
        initial={{ scale: 1 }}
        whileTap={{ scale: 0.95 }}
        onClick={handleOpenModal}
        className={cn(
          "relative overflow-hidden rounded-2xl bg-slate-100 dark:bg-slate-900 shadow-sm hover:shadow-md transition-all duration-200 group focus:outline-none focus:ring-2 focus:ring-blue-500/50 p-2 w-max border border-slate-200 dark:border-slate-800 hover:cursor-pointer",
          className
        )}
        aria-label={title}
      >
        <div className="flex items-center">
          {/* Thumbnail Image */}
          <div className="relative w-[70px] h-[42px] rounded-lg overflow-hidden flex-shrink-0 bg-black">
            <img 
              src={finalThumbnail} 
              alt="Video thumbnail" 
              className="absolute inset-0 w-full h-full object-cover opacity-80 group-hover:opacity-100 transition-opacity" 
            />

            {/* Play Icon Overlay */}
            <div className="absolute inset-0 flex items-center justify-center">
              <div className="p-1 rounded-full bg-white dark:bg-slate-950 shadow-sm border border-slate-200 dark:border-slate-800">
                <Play size={10} className="fill-slate-900 text-slate-900 dark:fill-white dark:text-white ml-0.5" />
              </div>
            </div>

            {/* YouTube Badge */}
            {isYouTube && (
              <div className="absolute bottom-1 right-1 bg-red-600 text-white text-[8px] font-bold px-1 py-0.5 rounded">
                YT
              </div>
            )}
          </div>

          {/* Button Text */}
          <p className="pl-3 pr-2 text-slate-900 dark:text-white font-medium text-sm sm:text-base">{title}</p>
        </div>
      </motion.button>

      {/* Modal */}
      <AnimatePresence>
        {isModalOpen && (
          <motion.div
            className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-white/80 dark:bg-black/80 backdrop-blur-sm"
            onClick={handleCloseModal}
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 }}
            exit={{ opacity: 0 }}
            role="dialog"
            aria-modal="true"
            aria-label="Video Modal"
          >
            <motion.div
              onClick={(e) => e.stopPropagation()}
              initial={{ opacity: 0, scale: 0.1 }}
              animate={{ opacity: 1, scale: 1 }}
              exit={{ opacity: 0, scale: 0.1 }}
              transition={{ duration: 0.4, ease: [0.25, 0.46, 0.45, 0.94] }}
              className="relative w-full max-w-4xl aspect-video bg-black rounded-2xl overflow-hidden shadow-2xl border border-slate-200 dark:border-slate-800"
              style={{ transformOrigin: getTransformOrigin() }}
            >
              {/* Close Button */}
              <button
                onClick={handleCloseModal}
                className="absolute top-4 right-4 z-10 p-2 rounded-full bg-black/30 hover:bg-black/50 text-white border border-white/20 backdrop-blur-sm transition-all duration-200 hover:cursor-pointer"
                aria-label="Close video"
              >
                <X size={20} />
              </button>

              {/* Video or YouTube */}
              {isYouTube ? (
                <iframe
                  src={finalVideoUrl}
                  className="w-full h-full border-0"
                  allow="autoplay; encrypted-media"
                  allowFullScreen
                  title={title}
                />
              ) : (
                <video src={finalVideoUrl} controls autoPlay className="w-full h-full object-contain" />
              )}
            </motion.div>
          </motion.div>
        )}
      </AnimatePresence>
    </>
  );
};

--- FILE: frontend-web/registry/media/VideoModal.tsx ---

import * as React from 'react'
import { motion, AnimatePresence } from 'framer-motion'
import { createPortal } from 'react-dom'
import { cn } from "../core/utils"

// --- CONTEXT & NATIVE MODAL LOGIC (Replaces Radix) ---
interface VideoModalContextType {
  isOpen: boolean
  setIsOpen: (value: boolean) => void
}

const VideoModalContext = React.createContext<VideoModalContextType | undefined>(undefined)

const useVideoModal = () => {
  const context = React.useContext(VideoModalContext)
  if (!context) {
    throw new Error('useVideoModal must be used within a VideoModal')
  }
  return context
}

const VideoModal: React.FC<{ children: React.ReactNode }> = ({ children }) => {
  const [isOpen, setIsOpen] = React.useState(false)
  return (
    <VideoModalContext.Provider value={{ isOpen, setIsOpen }}>
      {children}
    </VideoModalContext.Provider>
  )
}

const VideoModalTrigger = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
  ({ className, children, ...props }, ref) => {
    const { setIsOpen } = useVideoModal()
    return (
      <div
        ref={ref}
        className={cn('inline-block cursor-pointer', className)}
        onClick={() => setIsOpen(true)}
        {...props}
      >
        {children}
      </div>
    )
  }
)
VideoModalTrigger.displayName = 'VideoModalTrigger'

const VideoModalClose = React.forwardRef<HTMLButtonElement, React.ButtonHTMLAttributes<HTMLButtonElement>>(
  ({ className, ...props }, ref) => {
    const { setIsOpen } = useVideoModal()
    return (
      <button
        ref={ref}
        type="button"
        className={className}
        onClick={() => setIsOpen(false)}
        {...props}
      />
    )
  }
)
VideoModalClose.displayName = 'VideoModalClose'

// --- COMPONENT PARTS ---

const VideoModalContent = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
  ({ className, children, ...props }, ref) => {
    const { isOpen, setIsOpen } = useVideoModal()
    const [mounted, setMounted] = React.useState(false)

    React.useEffect(() => {
      setMounted(true)
    }, [])

    React.useEffect(() => {
      if (isOpen) {
        document.body.style.overflow = 'hidden'
      } else {
        document.body.style.overflow = ''
      }
      return () => {
        document.body.style.overflow = ''
      }
    }, [isOpen])

    React.useEffect(() => {
      const handleKeyDown = (e: KeyboardEvent) => {
        if (e.key === 'Escape') setIsOpen(false)
      }
      if (isOpen) {
        window.addEventListener('keydown', handleKeyDown)
      }
      return () => window.removeEventListener('keydown', handleKeyDown)
    }, [isOpen, setIsOpen])

    if (!mounted) return null

    return createPortal(
      <AnimatePresence>
        {isOpen && (
          <>
            <motion.div
              initial={{ opacity: 0 }}
              animate={{ opacity: 1 }}
              exit={{ opacity: 0 }}
              transition={{ duration: 0.3, ease: 'easeOut' }}
              className={cn(
                'fixed inset-0 z-50 backdrop-blur-xl'
              )}
              onClick={() => setIsOpen(false)}
            />
            <motion.div
              ref={ref}
              initial={{ opacity: 0, scale: 0.95, x: '-50%', y: '-50%' }}
              animate={{ opacity: 1, scale: 1, x: '-50%', y: '-50%' }}
              exit={{ opacity: 0, scale: 0.95, x: '-50%', y: '-50%' }}
              transition={{ duration: 0.3, ease: 'easeOut' }}
              className={cn(
                'fixed left-1/2 top-1/2 z-50 flex h-screen w-screen -translate-x-1/2 -translate-y-1/2 items-center justify-center p-3 transition-all',
                className
              )}
              {...props}
            >
              <div 
                className="relative mx-auto flex size-full items-center justify-center rounded-2xl border border-gray-950/[.1] bg-gray-50/[.2] dark:border-gray-50/[.1] dark:bg-gray-950/[.5]"
                onClick={(e) => e.stopPropagation()} // Prevent clicks inside modal from closing it
              >
                {/* Mobile close button */}
                <CloseIcon isMobile />

                <div className="flex h-4/5 w-full max-w-5xl gap-6">
                  {/* Desktop close button */}
                  <CloseIcon />
                  <div className="flex w-full flex-col max-lg:p-4 max-lg:text-center">
                    {children}
                  </div>
                </div>
              </div>
            </motion.div>
          </>
        )}
      </AnimatePresence>,
      document.body
    )
  }
)
VideoModalContent.displayName = 'VideoModalContent'

const VideoModalTitle = React.forwardRef<HTMLHeadingElement, React.HTMLAttributes<HTMLHeadingElement>>(
  ({ className, ...props }, ref) => (
    <h2
      ref={ref}
      className={cn(
        'mb-4 text-4xl font-bold text-gray-950 dark:text-gray-50',
        className,
      )}
      {...props}
    />
  )
)
VideoModalTitle.displayName = 'VideoModalTitle'

const VideoModalDescription = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLParagraphElement>>(
  ({ className, ...props }, ref) => (
    <p
      ref={ref}
      className={cn(
        'mb-6 text-xl text-gray-950/80 dark:text-gray-50/70',
        className,
      )}
      {...props}
    />
  )
)
VideoModalDescription.displayName = 'VideoModalDescription'

const VideoPreview = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
  ({ className, children, ...props }, ref) => (
    <div
      ref={ref}
      className={cn(
        'absolute inset-0 z-10 transition-opacity duration-500 group-[.playing]:pointer-events-none group-[.playing]:opacity-0',
        className,
      )}
      {...props}
    >
      {children}
    </div>
  )
)
VideoPreview.displayName = 'VideoPreview'

const VideoPlayButton = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
  ({ className, children, ...props }, ref) => (
    <div
      ref={ref}
      className={cn(
        'absolute inset-0 z-20 flex items-center justify-center transition-opacity duration-300 group-[.playing]:pointer-events-none group-[.playing]:opacity-0',
        className,
      )}
      {...props}
    >
      {children}
    </div>
  )
)
VideoPlayButton.displayName = 'VideoPlayButton'

const VideoPlayer = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
  ({ className, children, ...props }, ref) => {
    const [isPlaying, setIsPlaying] = React.useState(false)

    return (
      <div
        ref={ref}
        className={cn(
          'group relative aspect-video max-w-4xl overflow-hidden rounded-xl border border-gray-950/[.1] object-cover dark:border-gray-50/[.1]',
          isPlaying && 'playing',
          className,
        )}
        onClick={() => setIsPlaying(true)}
        {...props}
      >
        {children}
      </div>
    )
  }
)
VideoPlayer.displayName = 'VideoPlayer'

const VideoModalVideo = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
  ({ className, children, ...props }, ref) => (
    <div
      ref={ref}
      className={cn(
        'aspect-video max-w-4xl overflow-hidden rounded-xl border border-gray-950/[.1] object-cover shadow-xl dark:border-gray-50/[.1]',
        className,
      )}
      {...props}
    >
      {children}
    </div>
  )
)
VideoModalVideo.displayName = 'VideoModalVideo'

const CloseIcon = React.forwardRef<
  React.ElementRef<typeof VideoModalClose>,
  React.ComponentPropsWithoutRef<typeof VideoModalClose> & {
    isMobile?: boolean
  }
>(({ className, isMobile = false, ...props }, ref) => (
  <VideoModalClose
    ref={ref}
    className={cn(
      'rounded-full border border-gray-950/[.1] bg-gray-950/[.01] p-2 transition duration-300 hover:bg-gray-950/[.05] dark:border-gray-50/[.1] dark:bg-gray-50/[.10] dark:hover:bg-gray-50/[.15]',
      isMobile
        ? 'absolute right-4 top-4 lg:hidden'
        : 'hidden self-start lg:block',
      className,
    )}
    {...props}
  >
    <svg
      fill="none"
      height="12"
      viewBox="0 0 12 12"
      width="12"
      xmlns="http://www.w3.org/2000/svg"
    >
      <path
        d="M1 1L11 11M11 1L1 11"
        className="stroke-current"
        strokeLinecap="round"
        strokeLinejoin="round"
        strokeWidth="1.5"
      >
      </path>
    </svg>
    <span className="sr-only">Close</span>
  </VideoModalClose>
))

CloseIcon.displayName = 'CloseIcon'

export {
  VideoModal,
  VideoModalTrigger,
  VideoModalContent,
  VideoModalTitle,
  VideoModalDescription,
  VideoModalVideo,
  VideoPreview,
  VideoPlayButton,
  VideoPlayer,
}

--- FILE: frontend-web/registry/media/VideoPlayer.tsx ---

import React, { useRef, useState } from "react";
import { Play, Pause, Volume2, Volume1, VolumeX } from "lucide-react";
import { motion, AnimatePresence } from "framer-motion";
import { cn } from "../core/utils";

const formatTime = (seconds: number) => {
  const minutes = Math.floor(seconds / 60);
  const remainingSeconds = Math.floor(seconds % 60);
  return `${minutes}:${remainingSeconds.toString().padStart(2, "0")}`;
};

const CustomSlider = ({
  value,
  onChange,
  className,
}: {
  value: number;
  onChange: (value: number) => void;
  className?: string;
}) => {
  return (
    <motion.div
      className={cn(
        "relative w-full h-1 bg-white/20 rounded-full cursor-pointer",
        className
      )}
      onClick={(e) => {
        const rect = e.currentTarget.getBoundingClientRect();
        const x = e.clientX - rect.left;
        const percentage = (x / rect.width) * 100;
        onChange(Math.min(Math.max(percentage, 0), 100));
      }}
    >
      <motion.div
        className="absolute top-0 left-0 h-full bg-white rounded-full"
        style={{ width: `${value}%` }}
        initial={{ width: 0 }}
        animate={{ width: `${value}%` }}
        transition={{ type: "spring", stiffness: 300, damping: 30 }}
      />
    </motion.div>
  );
};

export interface VideoPlayerProps {
  src: string;
  className?: string;
}

export const VideoPlayer = ({ src, className }: VideoPlayerProps) => {
  const videoRef = useRef<HTMLVideoElement>(null);
  const [isPlaying, setIsPlaying] = useState(false);
  const [volume, setVolume] = useState(1);
  const [progress, setProgress] = useState(0);
  const [isMuted, setIsMuted] = useState(false);
  const [playbackSpeed, setPlaybackSpeed] = useState(1);
  const [showControls, setShowControls] = useState(false);
  const [currentTime, setCurrentTime] = useState(0);
  const [duration, setDuration] = useState(0);

  const togglePlay = () => {
    if (videoRef.current) {
      if (isPlaying) {
        videoRef.current.pause();
      } else {
        videoRef.current.play();
      }
      setIsPlaying(!isPlaying);
    }
  };

  const handleVolumeChange = (value: number) => {
    if (videoRef.current) {
      const newVolume = value / 100;
      videoRef.current.volume = newVolume;
      setVolume(newVolume);
      setIsMuted(newVolume === 0);
    }
  };

  const handleTimeUpdate = () => {
    if (videoRef.current) {
      const currentProgress =
        (videoRef.current.currentTime / videoRef.current.duration) * 100;
      setProgress(isFinite(currentProgress) ? currentProgress : 0);
      setCurrentTime(videoRef.current.currentTime);
      setDuration(videoRef.current.duration);
    }
  };

  const handleSeek = (value: number) => {
    if (videoRef.current && videoRef.current.duration) {
      const time = (value / 100) * videoRef.current.duration;
      if (isFinite(time)) {
        videoRef.current.currentTime = time;
        setProgress(value);
      }
    }
  };

  const toggleMute = () => {
    if (videoRef.current) {
      videoRef.current.muted = !isMuted;
      setIsMuted(!isMuted);
      if (!isMuted) {
        setVolume(0);
      } else {
        setVolume(1);
        videoRef.current.volume = 1;
      }
    }
  };

  const setSpeed = (speed: number) => {
    if (videoRef.current) {
      videoRef.current.playbackRate = speed;
      setPlaybackSpeed(speed);
    }
  };

  // Standalone button class mimicking Shadcn's ghost+icon variant
  const iconButtonClass = "inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50 h-9 w-9 text-white hover:bg-[#111111d1] hover:text-white";

  return (
    <motion.div
      className={cn(
        "relative w-full max-w-4xl mx-auto rounded-xl overflow-hidden bg-[#11111198] shadow-[0_0_20px_rgba(0,0,0,0.2)] backdrop-blur-sm",
        className
      )}
      initial={{ opacity: 0, y: 20 }}
      animate={{ opacity: 1, y: 0 }}
      transition={{ duration: 0.5 }}
      onMouseEnter={() => setShowControls(true)}
      onMouseLeave={() => setShowControls(false)}
    >
      <video
        ref={videoRef}
        className="w-full h-auto block"
        onTimeUpdate={handleTimeUpdate}
        src={src}
        onClick={togglePlay}
        playsInline
      />

      <AnimatePresence>
        {showControls && (
          <motion.div
            className="absolute bottom-0 mx-auto max-w-xl left-0 right-0 p-4 m-2 bg-[#11111198] backdrop-blur-md rounded-2xl"
            initial={{ y: 20, opacity: 0, filter: "blur(10px)" }}
            animate={{ y: 0, opacity: 1, filter: "blur(0px)" }}
            exit={{ y: 20, opacity: 0, filter: "blur(10px)" }}
            transition={{ duration: 0.6, ease: "circInOut", type: "spring" }}
          >
            <div className="flex items-center gap-2 mb-2">
              <span className="text-white text-sm">
                {formatTime(currentTime)}
              </span>
              <CustomSlider
                value={progress}
                onChange={handleSeek}
                className="flex-1"
              />
              <span className="text-white text-sm">
                {formatTime(duration)}
              </span>
            </div>

            <div className="flex items-center justify-between">
              <div className="flex items-center gap-4">
                <motion.div whileHover={{ scale: 1.1 }} whileTap={{ scale: 0.9 }}>
                  <button
                    type="button"
                    onClick={togglePlay}
                    className={iconButtonClass}
                  >
                    {isPlaying ? (
                      <Pause className="h-5 w-5" />
                    ) : (
                      <Play className="h-5 w-5" />
                    )}
                  </button>
                </motion.div>
                <div className="flex items-center gap-x-1">
                  <motion.div whileHover={{ scale: 1.1 }} whileTap={{ scale: 0.9 }}>
                    <button
                      type="button"
                      onClick={toggleMute}
                      className={iconButtonClass}
                    >
                      {isMuted ? (
                        <VolumeX className="h-5 w-5" />
                      ) : volume > 0.5 ? (
                        <Volume2 className="h-5 w-5" />
                      ) : (
                        <Volume1 className="h-5 w-5" />
                      )}
                    </button>
                  </motion.div>

                  <div className="w-24">
                    <CustomSlider
                      value={volume * 100}
                      onChange={handleVolumeChange}
                    />
                  </div>
                </div>
              </div>

              <div className="flex items-center gap-2">
                {[0.5, 1, 1.5, 2].map((speed) => (
                  <motion.div
                    whileHover={{ scale: 1.1 }}
                    whileTap={{ scale: 0.9 }}
                    key={speed}
                  >
                    <button
                      type="button"
                      onClick={() => setSpeed(speed)}
                      className={cn(
                        iconButtonClass,
                        playbackSpeed === speed && "bg-[#111111d1]"
                      )}
                    >
                      {speed}x
                    </button>
                  </motion.div>
                ))}
              </div>
            </div>
          </motion.div>
        )}
      </AnimatePresence>
    </motion.div>
  );
};

export default VideoPlayer;

--- FILE: frontend-web/registry/media/VideoPlayerPro.tsx ---

import React, { useRef, useState, useEffect } from "react";
import { Play, Pause, Volume2, Volume1, VolumeX, Maximize2, RotateCw, Settings } from "lucide-react";
import { motion, AnimatePresence } from "framer-motion";
import { cn } from "../core/utils";

export interface VideoPlayerProProps {
  src?: string;
  className?: string;
}

const formatTime = (seconds: number) => {
  if (isNaN(seconds)) return "0:00";
  const m = Math.floor(seconds / 60);
  const s = Math.floor(seconds % 60);
  return `${m}:${s.toString().padStart(2, "0")}`;
};

// Zero-dependency Slider replacement
const CustomSlider = ({
  value,
  onChange,
  className,
}: {
  value: number;
  onChange: (value: number) => void;
  className?: string;
}) => {
  return (
    <div
      className={cn(
        "relative w-full h-1.5 bg-white/20 rounded-full cursor-pointer touch-none select-none flex items-center group",
        className
      )}
      onPointerDown={(e) => {
        const rect = e.currentTarget.getBoundingClientRect();
        const update = (clientX: number) => {
          const x = clientX - rect.left;
          const percentage = (x / rect.width) * 100;
          onChange(Math.min(Math.max(percentage, 0), 100));
        };
        update(e.clientX);

        const handlePointerMove = (ev: PointerEvent) => update(ev.clientX);
        const handlePointerUp = () => {
          window.removeEventListener("pointermove", handlePointerMove);
          window.removeEventListener("pointerup", handlePointerUp);
        };
        window.addEventListener("pointermove", handlePointerMove);
        window.addEventListener("pointerup", handlePointerUp);
      }}
    >
      <div
        className="absolute top-0 left-0 h-full bg-white/80 rounded-full"
        style={{ width: `${value}%` }}
      />
      <div
        className="absolute h-3 w-3 rounded-full bg-white shadow-md top-1/2 -translate-y-1/2 -ml-1.5 scale-0 group-hover:scale-100 transition-transform"
        style={{ left: `${value}%` }}
      />
    </div>
  );
};

export const VideoPlayerPro: React.FC<VideoPlayerProProps> = ({ 
  src = "https://www.w3schools.com/html/mov_bbb.mp4",
  className 
}) => {
  const videoRef = useRef<HTMLVideoElement>(null);
  const containerRef = useRef<HTMLDivElement>(null);

  const [isPlaying, setIsPlaying] = useState<boolean>(false);
  const [isEnded, setIsEnded] = useState<boolean>(false);
  const [volume, setVolume] = useState<number>(1);
  const [isMuted, setIsMuted] = useState<boolean>(false);
  const [progress, setProgress] = useState<number>(0);
  const [currentTime, setCurrentTime] = useState<number>(0);
  const [duration, setDuration] = useState<number>(0);
  const [showControls, setShowControls] = useState<boolean>(true);
  const [playbackSpeed, setPlaybackSpeed] = useState<number>(1);

  const [showSettings, setShowSettings] = useState<boolean>(false);
  const [showVolume, setShowVolume] = useState<boolean>(false);

  // Play / Pause / Restart
  const togglePlay = () => {
    if (!videoRef.current) return;
    if (isEnded) {
      videoRef.current.currentTime = 0;
      setIsEnded(false);
    }
    isPlaying ? videoRef.current.pause() : videoRef.current.play();
    setIsPlaying(!isPlaying);
  };

  // Update progress and time
  const handleTimeUpdate = () => {
    if (!videoRef.current) return;
    const prog = (videoRef.current.currentTime / videoRef.current.duration) * 100;
    setProgress(isFinite(prog) ? prog : 0);
    setCurrentTime(videoRef.current.currentTime);
    setDuration(videoRef.current.duration || 0);
  };

  // Video ended
  const handleEnded = () => {
    setIsEnded(true);
    setIsPlaying(false);
  };

  // Seek
  const handleSeek = (percent: number) => {
    if (!videoRef.current) return;
    const time = (percent / 100) * (videoRef.current.duration || 0);
    if (isFinite(time)) videoRef.current.currentTime = time;
    setProgress(percent);
  };

  // Fullscreen
  const toggleFullscreen = () => {
    if (!containerRef.current) return;
    if (!document.fullscreenElement) {
      containerRef.current.requestFullscreen().catch((err) => {
        console.error("Fullscreen request failed:", err);
      });
    } else {
      document.exitFullscreen().catch((err) => {
        console.error("Exit fullscreen failed:", err);
      });
    }
  };

  // Toggle mute
  const toggleMute = () => {
    if (!videoRef.current) return;
    videoRef.current.muted = !isMuted;
    setIsMuted(!isMuted);
    setVolume(!isMuted ? 0 : 1);
  };

  const handleVolumeChange = (newVolumePercent: number) => {
    const newVolume = newVolumePercent / 100;
    if (videoRef.current) videoRef.current.volume = newVolume;
    setVolume(newVolume);
    setIsMuted(newVolume === 0);
  };

  // Close menus when clicking outside
  useEffect(() => {
    const handleClickOutside = (e: MouseEvent) => {
      if (!(e.target as HTMLElement).closest('.video-menu-container')) {
        setShowSettings(false);
        setShowVolume(false);
      }
    };
    document.addEventListener("mousedown", handleClickOutside);
    return () => document.removeEventListener("mousedown", handleClickOutside);
  }, []);

  const buttonClass = "inline-flex items-center justify-center rounded-lg text-white hover:bg-white/20 h-9 w-9 transition-colors focus:outline-none";

  return (
    <motion.div
      ref={containerRef}
      className={cn("relative w-full max-w-5xl mx-auto overflow-hidden rounded-xl bg-black shadow-2xl", className)}
      onMouseEnter={() => setShowControls(true)}
      onMouseLeave={() => {
        setShowControls(false);
        setShowSettings(false);
        setShowVolume(false);
      }}
    >
      <video
        ref={videoRef}
        className="w-full h-full object-cover"
        src={src}
        onTimeUpdate={handleTimeUpdate}
        onEnded={handleEnded}
        onClick={togglePlay}
        playsInline
      />

      {/* Controls */}
      <AnimatePresence>
        {showControls && (
          <motion.div
            className="absolute bottom-4 left-1/2 transform -translate-x-1/2 w-[95%] backdrop-blur-md bg-white/10 border border-white/10 rounded-2xl p-3 flex flex-col gap-3 z-20"
            initial={{ y: 20, opacity: 0 }}
            animate={{ y: 0, opacity: 1 }}
            exit={{ y: 20, opacity: 0 }}
            transition={{ type: "spring", stiffness: 300, damping: 30 }}
          >
            {/* Progress */}
            <div className="px-2">
              <CustomSlider value={progress} onChange={handleSeek} />
            </div>

            {/* Control Row */}
            <div className="flex items-center justify-between px-1">
              <div className="flex items-center gap-2">
                {/* Play / Pause / Restart */}
                <button className={buttonClass} onClick={togglePlay}>
                  {isEnded ? <RotateCw className="w-5 h-5" /> : isPlaying ? <Pause className="w-5 h-5 fill-white" /> : <Play className="w-5 h-5 fill-white ml-0.5" />}
                </button>

                {/* Volume Dropdown */}
                <div className="relative video-menu-container flex items-center">
                  <button 
                    className={buttonClass} 
                    onClick={() => {
                      setShowVolume(!showVolume);
                      setShowSettings(false);
                    }}
                  >
                    {isMuted ? <VolumeX className="w-5 h-5" /> : volume > 0.5 ? <Volume2 className="w-5 h-5" /> : <Volume1 className="w-5 h-5" />}
                  </button>
                  
                  <AnimatePresence>
                    {showVolume && (
                      <motion.div 
                        initial={{ opacity: 0, y: 10, scale: 0.95 }}
                        animate={{ opacity: 1, y: 0, scale: 1 }}
                        exit={{ opacity: 0, y: 10, scale: 0.95 }}
                        className="absolute bottom-full left-0 mb-2 w-32 bg-black/80 backdrop-blur-xl border border-white/10 p-4 rounded-xl flex items-center gap-3"
                      >
                        <button onClick={toggleMute} className="text-white hover:text-blue-400 focus:outline-none">
                          {isMuted || volume === 0 ? <VolumeX className="w-4 h-4" /> : <Volume2 className="w-4 h-4" />}
                        </button>
                        <CustomSlider value={volume * 100} onChange={handleVolumeChange} />
                      </motion.div>
                    )}
                  </AnimatePresence>
                </div>

                {/* Timer */}
                <span className="text-white text-xs font-medium ml-2 tabular-nums tracking-wide">
                  {formatTime(currentTime)} / {formatTime(duration)}
                </span>
              </div>

              <div className="flex items-center gap-2">
                {/* Settings Dropdown */}
                <div className="relative video-menu-container flex items-center">
                  <button 
                    className={buttonClass} 
                    onClick={() => {
                      setShowSettings(!showSettings);
                      setShowVolume(false);
                    }}
                  >
                    <Settings className="w-5 h-5" />
                  </button>
                  
                  <AnimatePresence>
                    {showSettings && (
                      <motion.div 
                        initial={{ opacity: 0, y: 10, scale: 0.95 }}
                        animate={{ opacity: 1, y: 0, scale: 1 }}
                        exit={{ opacity: 0, y: 10, scale: 0.95 }}
                        className="absolute bottom-full right-0 mb-2 w-44 bg-black/80 backdrop-blur-xl border border-white/10 p-3 rounded-xl flex flex-col gap-2"
                      >
                        <span className="text-xs font-semibold text-white/50 uppercase tracking-wider px-2">Speed</span>
                        <div className="grid grid-cols-2 gap-1">
                          {[0.5, 1, 1.5, 2].map((s) => (
                            <button
                              key={s}
                              className={cn(
                                "px-2 py-1.5 rounded-lg text-xs font-medium transition-colors",
                                playbackSpeed === s 
                                  ? "bg-white text-black" 
                                  : "text-white hover:bg-white/20"
                              )}
                              onClick={() => {
                                if (videoRef.current) videoRef.current.playbackRate = s;
                                setPlaybackSpeed(s);
                              }}
                            >
                              {s}x
                            </button>
                          ))}
                        </div>
                      </motion.div>
                    )}
                  </AnimatePresence>
                </div>

                {/* Fullscreen */}
                <button className={buttonClass} onClick={toggleFullscreen}>
                  <Maximize2 className="w-5 h-5" />
                </button>
              </div>
            </div>
          </motion.div>
        )}
      </AnimatePresence>
    </motion.div>
  );
};

export default VideoPlayerPro;

--- FILE: frontend-web/registry/media/VideoThumbnailPlayer.tsx ---

import * as React from "react";
import { cn } from "../core/utils";
import { Play, X } from "lucide-react";
import { motion, AnimatePresence } from "framer-motion";

export interface VideoThumbnailPlayerProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'title'> {
  thumbnailUrl: string;
  videoUrl: string;
  title: string;
  description?: string;
  aspectRatio?: "16/9" | "4/3" | "1/1";
}

export const VideoThumbnailPlayer = React.forwardRef<HTMLDivElement, VideoThumbnailPlayerProps>(
  (
    {
      className,
      thumbnailUrl,
      videoUrl,
      title,
      description,
      aspectRatio = "16/9",
      ...props
    },
    ref
  ) => {
    const [isModalOpen, setIsModalOpen] = React.useState(false);

    React.useEffect(() => {
      const handleEsc = (event: KeyboardEvent) => {
        if (event.key === "Escape") {
          setIsModalOpen(false);
        }
      };
      window.addEventListener("keydown", handleEsc);
      return () => {
        window.removeEventListener("keydown", handleEsc);
      };
    }, []);

    React.useEffect(() => {
        if (isModalOpen) {
            document.body.style.overflow = 'hidden';
        } else {
            document.body.style.overflow = '';
        }
        return () => {
            document.body.style.overflow = '';
        };
    }, [isModalOpen]);

    const aspectRatioClass = 
        aspectRatio === "16/9" ? "aspect-video" : 
        aspectRatio === "4/3" ? "aspect-[4/3]" : "aspect-square";

    return (
      <>
        <div
          ref={ref}
          className={cn(
            "group relative cursor-pointer overflow-hidden rounded-xl shadow-lg",
            "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2",
            aspectRatioClass,
            className
          )}
          onClick={() => setIsModalOpen(true)}
          onKeyDown={(e) => e.key === "Enter" && setIsModalOpen(true)}
          tabIndex={0}
          aria-label={`Play video: ${title}`}
          {...props}
        >
          <img
            src={thumbnailUrl}
            alt={`Thumbnail for ${title}`}
            className="h-full w-full object-cover transition-transform duration-500 group-hover:scale-105"
          />
          <div className="absolute inset-0 bg-gradient-to-t from-black/80 via-black/20 to-transparent opacity-80 group-hover:opacity-100 transition-opacity" />

          <div className="absolute inset-0 flex items-center justify-center">
            <div className="flex h-16 w-16 items-center justify-center rounded-full bg-white/20 backdrop-blur-md transition-all duration-300 group-hover:scale-110 group-hover:bg-white/30 border border-white/20">
              <Play className="h-8 w-8 fill-white text-white ml-1" />
            </div>
          </div>

          <div className="absolute bottom-0 left-0 p-6 w-full">
            <h3 className="text-xl sm:text-2xl font-bold text-white tracking-tight">{title}</h3>
            {description && (
              <p className="mt-2 text-sm text-white/80 line-clamp-2">{description}</p>
            )}
          </div>
        </div>

        <AnimatePresence>
          {isModalOpen && (
            <motion.div
              initial={{ opacity: 0 }}
              animate={{ opacity: 1 }}
              exit={{ opacity: 0 }}
              className="fixed inset-0 z-50 flex items-center justify-center bg-black/90 backdrop-blur-sm"
              aria-modal="true"
              role="dialog"
              onClick={() => setIsModalOpen(false)}
            >
              <button
                onClick={() => setIsModalOpen(false)}
                className="absolute right-4 top-4 z-50 rounded-full bg-white/10 p-2 text-white transition-colors hover:bg-white/20 border border-white/10"
                aria-label="Close video player"
              >
                <X className="h-6 w-6" />
              </button>

              <motion.div 
                initial={{ opacity: 0, scale: 0.95, y: 20 }}
                animate={{ opacity: 1, scale: 1, y: 0 }}
                exit={{ opacity: 0, scale: 0.95, y: 20 }}
                onClick={(e) => e.stopPropagation()}
                className="w-full max-w-5xl aspect-video p-4 sm:p-6"
              >
                 <iframe
                      src={videoUrl}
                      title={title}
                      className="h-full w-full rounded-2xl shadow-2xl bg-black border border-white/10"
                      allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
                      allowFullScreen
                  ></iframe>
              </motion.div>
            </motion.div>
          )}
        </AnimatePresence>
      </>
    );
  }
);
VideoThumbnailPlayer.displayName = "VideoThumbnailPlayer";

--- FILE: frontend-web/registry/modals/AnimatedDialog.tsx ---

import React, { useState, useEffect, useContext, createContext } from "react";
import { createPortal } from "react-dom";
import { motion, AnimatePresence } from "framer-motion";
import { X } from "lucide-react";
import { cn } from "../core/utils";

// --- Context ---
interface DialogContextType {
  isOpen: boolean;
  setIsOpen: (value: boolean) => void;
}

const DialogContext = createContext<DialogContextType | undefined>(undefined);

const useDialog = () => {
  const context = useContext(DialogContext);
  if (!context) throw new Error("Dialog components must be used within a <Dialog>");
  return context;
};

// --- Root ---
export function Dialog({ children, open, onOpenChange }: { children: React.ReactNode, open?: boolean, onOpenChange?: (open: boolean) => void }) {
  const [internalOpen, setInternalOpen] = useState(false);
  const isOpen = open !== undefined ? open : internalOpen;
  
  const setIsOpen = (val: boolean) => {
    setInternalOpen(val);
    onOpenChange?.(val);
  };

  return <DialogContext.Provider value={{ isOpen, setIsOpen }}>{children}</DialogContext.Provider>;
}

// --- Trigger ---
export const DialogTrigger = React.forwardRef<HTMLElement, React.HTMLAttributes<HTMLElement> & { asChild?: boolean }>(
  ({ className, children, asChild, ...props }, ref) => {
    const { setIsOpen } = useDialog();
    
    if (asChild && React.isValidElement(children)) {
      return React.cloneElement(children, {
        ...props,
        ...children.props,
        onClick: (e: any) => {
          setIsOpen(true);
          children.props.onClick?.(e);
          props.onClick?.(e);
        },
        className: cn(className, children.props.className),
        // @ts-ignore
        ref,
      });
    }

    return (
      <button ref={ref as any} className={className} onClick={(e) => { setIsOpen(true); props.onClick?.(e as any); }} {...props as any}>
        {children}
      </button>
    );
  }
);
DialogTrigger.displayName = "DialogTrigger";

// --- Content ---
export const DialogContent = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
  ({ className, children, ...props }, ref) => {
    const { isOpen, setIsOpen } = useDialog();
    const [mounted, setMounted] = useState(false);

    useEffect(() => setMounted(true), []);

    useEffect(() => {
      if (isOpen) document.body.style.overflow = "hidden";
      else document.body.style.overflow = "";
      return () => { document.body.style.overflow = ""; };
    }, [isOpen]);

    useEffect(() => {
      const handleEsc = (e: KeyboardEvent) => { if (e.key === "Escape") setIsOpen(false); };
      if (isOpen) window.addEventListener("keydown", handleEsc);
      return () => window.removeEventListener("keydown", handleEsc);
    }, [isOpen, setIsOpen]);

    if (!mounted) return null;

    return createPortal(
      <AnimatePresence>
        {isOpen && (
          <div className="fixed inset-0 z-[101] flex items-center justify-center p-4 sm:p-0">
            {/* Overlay */}
            <motion.div
              initial={{ opacity: 0 }}
              animate={{ opacity: 1 }}
              exit={{ opacity: 0 }}
              transition={{ duration: 0.2 }}
              onClick={() => setIsOpen(false)}
              className="fixed inset-0 bg-black/80 backdrop-blur-sm"
              aria-hidden="true"
            />

            {/* Modal */}
            <motion.div
              ref={ref}
              initial={{ opacity: 0, scale: 0.95, y: "-48%", x: "-50%" }}
              animate={{ opacity: 1, scale: 1, y: "-50%", x: "-50%" }}
              exit={{ opacity: 0, scale: 0.95, y: "-48%", x: "-50%" }}
              transition={{ type: "spring", damping: 25, stiffness: 300 }}
              className={cn(
                "fixed left-1/2 top-1/2 z-[101] grid w-full max-w-lg -translate-x-1/2 -translate-y-1/2 gap-4 overflow-y-auto border border-slate-200 dark:border-zinc-800 bg-white dark:bg-zinc-950 p-6 shadow-xl sm:rounded-xl",
                className
              )}
              role="dialog"
              aria-modal="true"
              {...props}
            >
              {children}
              <button
                onClick={() => setIsOpen(false)}
                className="absolute right-4 top-4 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-slate-400 focus:ring-offset-2 disabled:pointer-events-none dark:ring-offset-zinc-950 dark:focus:ring-slate-400"
              >
                <X className="h-4 w-4 text-slate-500 dark:text-slate-400" />
                <span className="sr-only">Close</span>
              </button>
            </motion.div>
          </div>
        )}
      </AnimatePresence>,
      document.body
    );
  }
);
DialogContent.displayName = "DialogContent";

// --- Header ---
export const DialogHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
  <div className={cn("flex flex-col space-y-1.5 text-center sm:text-left", className)} {...props} />
);
DialogHeader.displayName = "DialogHeader";

// --- Footer ---
export const DialogFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
  <div className={cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2 mt-4", className)} {...props} />
);
DialogFooter.displayName = "DialogFooter";

// --- Title ---
export const DialogTitle = React.forwardRef<HTMLHeadingElement, React.HTMLAttributes<HTMLHeadingElement>>(
  ({ className, ...props }, ref) => (
    <h2 ref={ref} className={cn("text-lg font-semibold tracking-tight text-slate-900 dark:text-white", className)} {...props} />
  )
);
DialogTitle.displayName = "DialogTitle";

// --- Description ---
export const DialogDescription = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLParagraphElement>>(
  ({ className, ...props }, ref) => (
    <p ref={ref} className={cn("text-sm text-slate-500 dark:text-slate-400", className)} {...props} />
  )
);
DialogDescription.displayName = "DialogDescription";

// --- Close (Alternative Trigger) ---
export const DialogClose = React.forwardRef<HTMLElement, React.HTMLAttributes<HTMLElement> & { asChild?: boolean }>(
  ({ className, children, asChild, ...props }, ref) => {
    const { setIsOpen } = useDialog();
    
    if (asChild && React.isValidElement(children)) {
      return React.cloneElement(children, {
        ...props,
        ...children.props,
        onClick: (e: any) => {
          setIsOpen(false);
          children.props.onClick?.(e);
          props.onClick?.(e);
        },
        className: cn(className, children.props.className),
        // @ts-ignore
        ref,
      });
    }

    return (
      <button ref={ref as any} className={className} onClick={(e) => { setIsOpen(false); props.onClick?.(e as any); }} {...props as any}>
        {children}
      </button>
    );
  }
);
DialogClose.displayName = "DialogClose";

--- FILE: frontend-web/registry/modals/MorphingDialog.tsx ---

import React, {
  useCallback,
  useContext,
  useEffect,
  useId,
  useMemo,
  useRef,
  useState,
} from 'react';
import {
  motion,
  AnimatePresence,
  MotionConfig,
  Transition,
  Variant,
} from 'framer-motion';
import { createPortal } from 'react-dom';
import { cn } from '../core/utils';
import { X } from 'lucide-react'; // Changed XIcon to X for standard Lucide naming

// --- Inlined Hook ---
function useClickOutside(
  ref: React.RefObject<HTMLElement | null>,
  handler: (event: MouseEvent | TouchEvent) => void
) {
  useEffect(() => {
    const listener = (event: MouseEvent | TouchEvent) => {
      if (!ref.current || ref.current.contains(event.target as Node)) {
        return;
      }
      handler(event);
    };
    document.addEventListener('mousedown', listener);
    document.addEventListener('touchstart', listener);
    return () => {
      document.removeEventListener('mousedown', listener);
      document.removeEventListener('touchstart', listener);
    };
  }, [ref, handler]);
}
// -------------------

interface MorphingDialogContextType {
  isOpen: boolean;
  setIsOpen: React.Dispatch<React.SetStateAction<boolean>>;
  uniqueId: string;
  triggerRef: React.RefObject<HTMLDivElement | null>;
}

const MorphingDialogContext =
  React.createContext<MorphingDialogContextType | null>(null);

function useMorphingDialog() {
  const context = useContext(MorphingDialogContext);
  if (!context) {
    throw new Error(
      'useMorphingDialog must be used within a MorphingDialogProvider'
    );
  }
  return context;
}

type MorphingDialogProviderProps = {
  children: React.ReactNode;
  transition?: Transition;
};

function MorphingDialogProvider({
  children,
  transition,
}: MorphingDialogProviderProps) {
  const [isOpen, setIsOpen] = useState(false);
  const uniqueId = useId().replace(/:/g, ''); // Ensure safe ID
  const triggerRef = useRef<HTMLDivElement>(null);

  const contextValue = useMemo(
    () => ({ isOpen, setIsOpen, uniqueId, triggerRef }),
    [isOpen, uniqueId]
  );

  return (
    <MorphingDialogContext.Provider value={contextValue}>
      <MotionConfig transition={transition}>{children}</MotionConfig>
    </MorphingDialogContext.Provider>
  );
}

type MorphingDialogProps = {
  children: React.ReactNode;
  transition?: Transition;
};

function MorphingDialog({ children, transition }: MorphingDialogProps) {
  return (
    <MorphingDialogProvider transition={transition}>
      {children}
    </MorphingDialogProvider>
  );
}

type MorphingDialogTriggerProps = {
  children: React.ReactNode;
  className?: string;
  style?: React.CSSProperties;
  triggerRef?: React.RefObject<HTMLDivElement | null>;
};

function MorphingDialogTrigger({
  children,
  className,
  style,
  triggerRef,
}: MorphingDialogTriggerProps) {
  const { setIsOpen, isOpen, uniqueId, triggerRef: contextTriggerRef } = useMorphingDialog();

  const handleClick = useCallback(() => {
    setIsOpen(!isOpen);
  }, [isOpen, setIsOpen]);

  const handleKeyDown = useCallback(
    (event: React.KeyboardEvent) => {
      if (event.key === 'Enter' || event.key === ' ') {
        event.preventDefault();
        setIsOpen(!isOpen);
      }
    },
    [isOpen, setIsOpen]
  );

  return (
    <motion.div
      ref={triggerRef || contextTriggerRef}
      layoutId={`dialog-${uniqueId}`}
      className={cn('relative cursor-pointer', className)}
      onClick={handleClick}
      onKeyDown={handleKeyDown}
      style={style}
      role='button'
      aria-haspopup='dialog'
      aria-expanded={isOpen}
      aria-controls={`motion-ui-morphing-dialog-content-${uniqueId}`}
    >
      {children}
    </motion.div>
  );
}

type MorphingDialogContentProps = {
  children: React.ReactNode;
  className?: string;
  style?: React.CSSProperties;
};

function MorphingDialogContent({
  children,
  className,
  style,
}: MorphingDialogContentProps) {
  const { setIsOpen, isOpen, uniqueId, triggerRef } = useMorphingDialog();
  const containerRef = useRef<HTMLDivElement>(null);
  const [firstFocusableElement, setFirstFocusableElement] =
    useState<HTMLElement | null>(null);
  const [lastFocusableElement, setLastFocusableElement] =
    useState<HTMLElement | null>(null);

  useEffect(() => {
    const handleKeyDown = (event: KeyboardEvent) => {
      if (event.key === 'Escape') {
        setIsOpen(false);
      }
      if (event.key === 'Tab') {
        if (!firstFocusableElement || !lastFocusableElement) return;

        if (event.shiftKey) {
          if (document.activeElement === firstFocusableElement) {
            event.preventDefault();
            lastFocusableElement.focus();
          }
        } else {
          if (document.activeElement === lastFocusableElement) {
            event.preventDefault();
            firstFocusableElement.focus();
          }
        }
      }
    };

    document.addEventListener('keydown', handleKeyDown);

    return () => {
      document.removeEventListener('keydown', handleKeyDown);
    };
  }, [setIsOpen, firstFocusableElement, lastFocusableElement]);

  useEffect(() => {
    if (isOpen) {
      document.body.classList.add('overflow-hidden');
      const focusableElements = containerRef.current?.querySelectorAll(
        'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
      );
      if (focusableElements && focusableElements.length > 0) {
        setFirstFocusableElement(focusableElements[0] as HTMLElement);
        setLastFocusableElement(
          focusableElements[focusableElements.length - 1] as HTMLElement
        );
        (focusableElements[0] as HTMLElement).focus();
      }
    } else {
      document.body.classList.remove('overflow-hidden');
      triggerRef.current?.focus();
    }
  }, [isOpen, triggerRef]);

  useClickOutside(containerRef, () => {
    if (isOpen) {
      setIsOpen(false);
    }
  });

  return (
    <motion.div
      ref={containerRef}
      layoutId={`dialog-${uniqueId}`}
      className={cn('overflow-hidden', className)}
      style={style}
      role='dialog'
      aria-modal='true'
      aria-labelledby={`motion-ui-morphing-dialog-title-${uniqueId}`}
      aria-describedby={`motion-ui-morphing-dialog-description-${uniqueId}`}
    >
      {children}
    </motion.div>
  );
}

type MorphingDialogContainerProps = {
  children: React.ReactNode;
  className?: string;
  style?: React.CSSProperties;
};

function MorphingDialogContainer({ children }: MorphingDialogContainerProps) {
  const { isOpen, uniqueId } = useMorphingDialog();
  const [mounted, setMounted] = useState(false);

  useEffect(() => {
    setMounted(true);
    return () => setMounted(false);
  }, []);

  if (!mounted) return null;

  return createPortal(
    <AnimatePresence initial={false} mode='sync'>
      {isOpen && (
        <>
          <motion.div
            key={`backdrop-${uniqueId}`}
            className='fixed inset-0 h-full w-full bg-white/40 backdrop-blur-sm dark:bg-black/40 z-40'
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 }}
            exit={{ opacity: 0 }}
          />
          <div className='fixed inset-0 z-50 flex items-center justify-center pointer-events-none'>
            <div className="pointer-events-auto">
              {children}
            </div>
          </div>
        </>
      )}
    </AnimatePresence>,
    document.body
  );
}

type MorphingDialogTitleProps = {
  children: React.ReactNode;
  className?: string;
  style?: React.CSSProperties;
};

function MorphingDialogTitle({
  children,
  className,
  style,
}: MorphingDialogTitleProps) {
  const { uniqueId } = useMorphingDialog();

  return (
    <motion.div
      layoutId={`dialog-title-container-${uniqueId}`}
      className={className}
      style={style}
      layout
    >
      {children}
    </motion.div>
  );
}

type MorphingDialogSubtitleProps = {
  children: React.ReactNode;
  className?: string;
  style?: React.CSSProperties;
};

function MorphingDialogSubtitle({
  children,
  className,
  style,
}: MorphingDialogSubtitleProps) {
  const { uniqueId } = useMorphingDialog();

  return (
    <motion.div
      layoutId={`dialog-subtitle-container-${uniqueId}`}
      className={className}
      style={style}
    >
      {children}
    </motion.div>
  );
}

type MorphingDialogDescriptionProps = {
  children: React.ReactNode;
  className?: string;
  disableLayoutAnimation?: boolean;
  variants?: {
    initial: Variant;
    animate: Variant;
    exit: Variant;
  };
};

function MorphingDialogDescription({
  children,
  className,
  variants,
  disableLayoutAnimation,
}: MorphingDialogDescriptionProps) {
  const { uniqueId } = useMorphingDialog();

  return (
    <motion.div
      key={`dialog-description-${uniqueId}`}
      layoutId={
        disableLayoutAnimation
          ? undefined
          : `dialog-description-content-${uniqueId}`
      }
      variants={variants}
      className={className}
      initial='initial'
      animate='animate'
      exit='exit'
      id={`dialog-description-${uniqueId}`}
    >
      {children}
    </motion.div>
  );
}

type MorphingDialogImageProps = {
  src: string;
  alt: string;
  className?: string;
  style?: React.CSSProperties;
};

function MorphingDialogImage({
  src,
  alt,
  className,
  style,
}: MorphingDialogImageProps) {
  const { uniqueId } = useMorphingDialog();

  return (
    <motion.img
      src={src}
      alt={alt}
      className={cn(className)}
      layoutId={`dialog-img-${uniqueId}`}
      style={style}
    />
  );
}

type MorphingDialogCloseProps = {
  children?: React.ReactNode;
  className?: string;
  variants?: {
    initial: Variant;
    animate: Variant;
    exit: Variant;
  };
};

function MorphingDialogClose({
  children,
  className,
  variants,
}: MorphingDialogCloseProps) {
  const { setIsOpen, uniqueId } = useMorphingDialog();

  const handleClose = useCallback(() => {
    setIsOpen(false);
  }, [setIsOpen]);

  return (
    <motion.button
      onClick={handleClose}
      type='button'
      aria-label='Close dialog'
      key={`dialog-close-${uniqueId}`}
      className={cn('absolute right-6 top-6', className)}
      initial='initial'
      animate='animate'
      exit='exit'
      variants={variants}
    >
      {children || <X size={24} />}
    </motion.button>
  );
}

export {
  MorphingDialog,
  MorphingDialogTrigger,
  MorphingDialogContainer,
  MorphingDialogContent,
  MorphingDialogClose,
  MorphingDialogTitle,
  MorphingDialogSubtitle,
  MorphingDialogDescription,
  MorphingDialogImage,
};

--- FILE: frontend-web/registry/modals/PublishDialog.tsx ---

import React, { useState, useEffect } from 'react';
import { createPortal } from 'react-dom';
import { motion, AnimatePresence } from 'framer-motion';
import { CircleAlertIcon, X } from 'lucide-react';
import { cn } from '../core/utils';

export interface PublishDialogProps {
  triggerText?: string;
  title?: string;
  description?: string;
  cancelText?: string;
  publishText?: string;
  onPublish?: () => void;
  className?: string;
}

export function PublishDialog({
  triggerText = "Publish changes",
  title = "Publish changes?",
  description = "Your draft will go live for all workspace members. You can revert within 30 days from version history.",
  cancelText = "Cancel",
  publishText = "Publish",
  onPublish,
  className,
}: PublishDialogProps) {
  const [isOpen, setIsOpen] = useState(false);
  const [mounted, setMounted] = useState(false);

  useEffect(() => {
    setMounted(true);
  }, []);

  // Handle escape key and body scroll lock
  useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      if (e.key === 'Escape') setIsOpen(false);
    };

    if (isOpen) {
      document.body.style.overflow = 'hidden';
      window.addEventListener('keydown', handleKeyDown);
    } else {
      document.body.style.overflow = '';
    }

    return () => {
      document.body.style.overflow = '';
      window.removeEventListener('keydown', handleKeyDown);
    };
  }, [isOpen]);

  const handlePublish = () => {
    if (onPublish) onPublish();
    setIsOpen(false);
  };

  return (
    <>
      <button
        onClick={() => setIsOpen(true)}
        className={cn(
          "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-slate-400 disabled:pointer-events-none disabled:opacity-50",
          "border border-slate-200 dark:border-zinc-800 bg-white dark:bg-zinc-950 hover:bg-slate-100 dark:hover:bg-zinc-800 text-slate-900 dark:text-white h-9 px-4 py-2 shadow-sm",
          className
        )}
      >
        {triggerText}
      </button>

      {mounted && createPortal(
        <AnimatePresence>
          {isOpen && (
            <div className="fixed inset-0 z-50 flex items-center justify-center p-4 sm:p-0">
              {/* Backdrop */}
              <motion.div
                initial={{ opacity: 0 }}
                animate={{ opacity: 1 }}
                exit={{ opacity: 0 }}
                transition={{ duration: 0.2 }}
                onClick={() => setIsOpen(false)}
                className="fixed inset-0 bg-black/50 backdrop-blur-sm"
                aria-hidden="true"
              />

              {/* Modal Content */}
              <motion.div
                initial={{ opacity: 0, scale: 0.95, y: 10 }}
                animate={{ opacity: 1, scale: 1, y: 0 }}
                exit={{ opacity: 0, scale: 0.95, y: 10 }}
                transition={{ type: "spring", damping: 25, stiffness: 300 }}
                className="relative z-50 w-full max-w-md bg-white dark:bg-zinc-950 border border-slate-200 dark:border-zinc-800 rounded-xl shadow-xl overflow-hidden"
                role="dialog"
                aria-modal="true"
                aria-labelledby="dialog-title"
              >
                {/* Close Button (Hidden but accessible, Radix style) */}
                <button
                  onClick={() => setIsOpen(false)}
                  className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-white transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-slate-400 focus:ring-offset-2 disabled:pointer-events-none dark:ring-offset-zinc-950 dark:focus:ring-zinc-400"
                >
                  <X className="h-4 w-4 text-slate-500 dark:text-slate-400" />
                  <span className="sr-only">Close</span>
                </button>

                <div className="p-6">
                  {/* Header */}
                  <div className="flex flex-col gap-3">
                    <div className="bg-slate-100 dark:bg-zinc-900 flex size-10 items-center justify-center rounded-full text-slate-900 dark:text-white">
                      <CircleAlertIcon className="w-5 h-5" />
                    </div>
                    <div className="flex flex-col gap-2">
                      <h2 id="dialog-title" className="text-lg font-semibold tracking-tight text-slate-900 dark:text-white">
                        {title}
                      </h2>
                      <p className="text-sm text-slate-500 dark:text-slate-400">
                        {description}
                      </p>
                    </div>
                  </div>

                  {/* Footer */}
                  <div className="flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2 mt-6 gap-2 sm:gap-0">
                    <button
                      onClick={() => setIsOpen(false)}
                      className="inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-slate-400 disabled:pointer-events-none disabled:opacity-50 border border-slate-200 dark:border-zinc-800 bg-white dark:bg-zinc-950 hover:bg-slate-100 dark:hover:bg-zinc-800 text-slate-900 dark:text-white h-9 px-4 py-2"
                    >
                      {cancelText}
                    </button>
                    <button
                      onClick={handlePublish}
                      className="inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-slate-400 disabled:pointer-events-none disabled:opacity-50 bg-slate-900 dark:bg-white text-white dark:text-slate-900 hover:bg-slate-900/90 dark:hover:bg-white/90 h-9 px-4 py-2 shadow-sm"
                    >
                      {publishText}
                    </button>
                  </div>
                </div>
              </motion.div>
            </div>
          )}
        </AnimatePresence>,
        document.body
      )}
    </>
  );
}

--- FILE: frontend-web/registry/navigation/AnimatedSidebar.tsx ---

import React, { createContext, useContext, useEffect, useState, useMemo, useCallback } from "react";
import { motion, AnimatePresence } from "framer-motion";
import { PanelLeft, X } from "lucide-react";
import { cn } from "../core/utils";

// --- HOOKS & CONTEXT ---

function useIsMobile() {
  const [isMobile, setIsMobile] = useState(false);
  useEffect(() => {
    const checkIsMobile = () => setIsMobile(window.innerWidth < 768);
    checkIsMobile();
    window.addEventListener("resize", checkIsMobile);
    return () => window.removeEventListener("resize", checkIsMobile);
  }, []);
  return isMobile;
}

type SidebarContextType = {
  state: "expanded" | "collapsed";
  open: boolean;
  setOpen: (open: boolean) => void;
  openMobile: boolean;
  setOpenMobile: (open: boolean) => void;
  isMobile: boolean;
  toggleSidebar: () => void;
};

const SidebarContext = createContext<SidebarContextType | null>(null);

export function useSidebar() {
  const context = useContext(SidebarContext);
  if (!context) throw new Error("useSidebar must be used within a SidebarProvider.");
  return context;
}

// --- PROVIDER ---

export const SidebarProvider = React.forwardRef<
  HTMLDivElement,
  React.ComponentProps<"div"> & {
    defaultOpen?: boolean;
    open?: boolean;
    onOpenChange?: (open: boolean) => void;
  }
>(({ defaultOpen = true, open: openProp, onOpenChange, className, style, children, ...props }, ref) => {
  const isMobile = useIsMobile();
  const [openMobile, setOpenMobile] = useState(false);
  const [_open, _setOpen] = useState(defaultOpen);
  
  const open = openProp ?? _open;
  
  const setOpen = useCallback(
    (value: boolean | ((val: boolean) => boolean)) => {
      const openState = typeof value === "function" ? value(open) : value;
      if (onOpenChange) onOpenChange(openState);
      else _setOpen(openState);
      if (typeof window !== "undefined") {
        localStorage.setItem("sidebar_state", openState ? "true" : "false");
      }
    },
    [onOpenChange, open]
  );

  const toggleSidebar = useCallback(() => {
    return isMobile ? setOpenMobile((o) => !o) : setOpen((o) => !o);
  }, [isMobile, setOpen]);

  useEffect(() => {
    const handleKeyDown = (event: KeyboardEvent) => {
      if (event.key === "b" && (event.metaKey || event.ctrlKey)) {
        event.preventDefault();
        toggleSidebar();
      }
    };
    window.addEventListener("keydown", handleKeyDown);
    return () => window.removeEventListener("keydown", handleKeyDown);
  }, [toggleSidebar]);

  const state = open ? "expanded" : "collapsed";

  const contextValue = useMemo<SidebarContextType>(
    () => ({ state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar }),
    [state, open, setOpen, isMobile, openMobile, toggleSidebar]
  );

  return (
    <SidebarContext.Provider value={contextValue}>
      <div
        style={{
          "--sidebar-width": "16rem",
          "--sidebar-width-icon": "3rem",
          ...style,
        } as React.CSSProperties}
        className={cn("group/sidebar-wrapper flex min-h-screen w-full", className)}
        ref={ref}
        {...props}
      >
        {children}
      </div>
    </SidebarContext.Provider>
  );
});
SidebarProvider.displayName = "SidebarProvider";

// --- SIDEBAR CONTAINER ---

export const Sidebar = React.forwardRef<
  HTMLDivElement,
  React.ComponentProps<"div"> & {
    side?: "left" | "right";
    variant?: "sidebar" | "floating" | "inset";
    collapsible?: "offcanvas" | "icon" | "none";
  }
>(({ side = "left", variant = "sidebar", collapsible = "offcanvas", className, children, ...props }, ref) => {
  const { isMobile, state, openMobile, setOpenMobile } = useSidebar();

  if (collapsible === "none") {
    return (
      <div className={cn("flex h-full w-[var(--sidebar-width)] flex-col bg-white dark:bg-zinc-950 text-slate-900 dark:text-slate-100", className)} ref={ref} {...props}>
        {children}
      </div>
    );
  }

  if (isMobile) {
    return (
      <AnimatePresence>
        {openMobile && (
          <div className="fixed inset-0 z-50 flex" {...props}>
            <motion.div
              initial={{ opacity: 0 }}
              animate={{ opacity: 1 }}
              exit={{ opacity: 0 }}
              transition={{ duration: 0.2 }}
              className="absolute inset-0 bg-black/50 backdrop-blur-sm"
              onClick={() => setOpenMobile(false)}
            />
            <motion.div
              initial={{ x: side === "left" ? "-100%" : "100%" }}
              animate={{ x: 0 }}
              exit={{ x: side === "left" ? "-100%" : "100%" }}
              transition={{ type: "spring", damping: 25, stiffness: 200 }}
              className={cn(
                "relative z-50 flex h-full w-[18rem] flex-col bg-white dark:bg-zinc-950 p-0 text-slate-900 dark:text-slate-100 shadow-2xl",
                side === "right" && "ml-auto"
              )}
            >
              <button
                onClick={() => setOpenMobile(false)}
                className="absolute right-4 top-4 z-50 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:outline-none"
              >
                <X className="h-5 w-5" />
              </button>
              {children}
            </motion.div>
          </div>
        )}
      </AnimatePresence>
    );
  }

  return (
    <div
      ref={ref}
      className="group peer hidden md:block text-slate-900 dark:text-slate-100"
      data-state={state}
      data-collapsible={state === "collapsed" ? collapsible : ""}
      data-variant={variant}
      data-side={side}
    >
      {/* Spacer to push content */}
      <div
        className={cn(
          "duration-200 relative h-screen w-[var(--sidebar-width)] bg-transparent transition-[width] ease-linear",
          "group-data-[collapsible=offcanvas]:w-0",
          "group-data-[side=right]:rotate-180",
          (variant === "floating" || variant === "inset")
            ? "group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+1rem)]"
            : "group-data-[collapsible=icon]:w-[var(--sidebar-width-icon)]"
        )}
      />
      {/* Actual Sidebar */}
      <div
        className={cn(
          "duration-200 fixed inset-y-0 z-10 hidden h-screen w-[var(--sidebar-width)] transition-[left,right,width] ease-linear md:flex",
          side === "left"
            ? "left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]"
            : "right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]",
          (variant === "floating" || variant === "inset")
            ? "p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+1rem)]"
            : "group-data-[collapsible=icon]:w-[var(--sidebar-width-icon)] group-data-[side=left]:border-r group-data-[side=right]:border-l border-slate-200 dark:border-zinc-800",
          className
        )}
        {...props}
      >
        <div
          data-sidebar="sidebar"
          className="flex h-full w-full flex-col bg-white dark:bg-zinc-950 group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:border-slate-200 dark:group-data-[variant=floating]:border-zinc-800 group-data-[variant=floating]:shadow"
        >
          {children}
        </div>
      </div>
    </div>
  );
});
Sidebar.displayName = "Sidebar";

// --- TRIGGER ---

export const SidebarTrigger = React.forwardRef<HTMLButtonElement, React.ComponentProps<"button">>(
  ({ className, onClick, ...props }, ref) => {
    const { toggleSidebar } = useSidebar();
    return (
      <button
        ref={ref}
        data-sidebar="trigger"
        className={cn("inline-flex h-9 w-9 items-center justify-center rounded-md hover:bg-slate-100 dark:hover:bg-zinc-800 text-slate-700 dark:text-slate-300 transition-colors", className)}
        onClick={(e) => { onClick?.(e); toggleSidebar(); }}
        {...props}
      >
        <PanelLeft className="h-5 w-5" />
        <span className="sr-only">Toggle Sidebar</span>
      </button>
    );
  }
);
SidebarTrigger.displayName = "SidebarTrigger";

// --- INSET (Main Content Area Wrapper) ---

export const SidebarInset = React.forwardRef<HTMLDivElement, React.ComponentProps<"main">>(
  ({ className, ...props }, ref) => {
    return (
      <main
        ref={ref}
        className={cn(
          "relative flex min-h-screen flex-1 flex-col bg-white dark:bg-zinc-950",
          "peer-data-[variant=inset]:min-h-[calc(100vh-1rem)] md:peer-data-[variant=inset]:m-2 md:peer-data-[state=collapsed]:peer-data-[variant=inset]:ml-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow md:peer-data-[variant=inset]:border border-slate-200 dark:border-zinc-800",
          className
        )}
        {...props}
      />
    );
  }
);
SidebarInset.displayName = "SidebarInset";

// --- LAYOUT PRIMITIVES ---

export const SidebarHeader = React.forwardRef<HTMLDivElement, React.ComponentProps<"div">>(
  ({ className, ...props }, ref) => (
    <div ref={ref} data-sidebar="header" className={cn("flex flex-col gap-2 p-2", className)} {...props} />
  )
);
SidebarHeader.displayName = "SidebarHeader";

export const SidebarFooter = React.forwardRef<HTMLDivElement, React.ComponentProps<"div">>(
  ({ className, ...props }, ref) => (
    <div ref={ref} data-sidebar="footer" className={cn("flex flex-col gap-2 p-2", className)} {...props} />
  )
);
SidebarFooter.displayName = "SidebarFooter";

export const SidebarContent = React.forwardRef<HTMLDivElement, React.ComponentProps<"div">>(
  ({ className, ...props }, ref) => (
    <div ref={ref} data-sidebar="content" className={cn("flex min-h-0 flex-1 flex-col gap-2 overflow-auto group-data-[collapsible=icon]:overflow-hidden", className)} {...props} />
  )
);
SidebarContent.displayName = "SidebarContent";

export const SidebarGroup = React.forwardRef<HTMLDivElement, React.ComponentProps<"div">>(
  ({ className, ...props }, ref) => (
    <div ref={ref} data-sidebar="group" className={cn("relative flex w-full min-w-0 flex-col p-2", className)} {...props} />
  )
);
SidebarGroup.displayName = "SidebarGroup";

export const SidebarGroupLabel = React.forwardRef<HTMLDivElement, React.ComponentProps<"div">>(
  ({ className, ...props }, ref) => (
    <div
      ref={ref}
      data-sidebar="group-label"
      className={cn(
        "duration-200 flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-semibold text-slate-500 dark:text-slate-400 uppercase tracking-wider outline-none transition-[margin,opacity] ease-linear focus-visible:ring-2",
        "group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0",
        className
      )}
      {...props}
    />
  )
);
SidebarGroupLabel.displayName = "SidebarGroupLabel";

export const SidebarMenu = React.forwardRef<HTMLUListElement, React.ComponentProps<"ul">>(
  ({ className, ...props }, ref) => (
    <ul ref={ref} data-sidebar="menu" className={cn("flex w-full min-w-0 flex-col gap-1", className)} {...props} />
  )
);
SidebarMenu.displayName = "SidebarMenu";

export const SidebarMenuItem = React.forwardRef<HTMLLIElement, React.ComponentProps<"li">>(
  ({ className, ...props }, ref) => (
    <li ref={ref} data-sidebar="menu-item" className={cn("group/menu-item relative", className)} {...props} />
  )
);
SidebarMenuItem.displayName = "SidebarMenuItem";

// --- SIDEBAR MENU BUTTON (Handles active states and tooltips) ---

export const SidebarMenuButton = React.forwardRef<
  HTMLButtonElement | HTMLAnchorElement,
  React.ComponentProps<"button"> & {
    asChild?: boolean;
    isActive?: boolean;
    tooltip?: string;
  }
>(({ asChild = false, isActive = false, tooltip, className, children, ...props }, ref) => {
  const { state, isMobile } = useSidebar();

  const baseClasses = cn(
    "peer/menu-button flex w-full items-center gap-3 overflow-hidden rounded-md p-2 text-left text-sm outline-none transition-colors disabled:pointer-events-none disabled:opacity-50",
    "hover:bg-slate-100 hover:text-slate-900 dark:hover:bg-zinc-800 dark:hover:text-white",
    isActive ? "bg-slate-100 text-blue-600 dark:bg-zinc-800 dark:text-blue-400 font-medium" : "text-slate-700 dark:text-slate-300",
    "group-data-[collapsible=icon]:!size-8 group-data-[collapsible=icon]:!p-2 [&>svg]:size-4 [&>svg]:shrink-0",
    className
  );

  const innerContent = (
    <>
      {children}
      {/* Zero-Dependency CSS Tooltip for Collapsed State */}
      {tooltip && state === "collapsed" && !isMobile && (
        <span className="absolute left-full ml-2 hidden whitespace-nowrap rounded-md bg-slate-900 dark:bg-white px-2 py-1 text-xs text-white dark:text-slate-900 shadow-md group-hover/menu-item:block z-50">
          {tooltip}
        </span>
      )}
    </>
  );

  if (asChild && React.isValidElement(children)) {
    return React.cloneElement(children, {
      ...props,
      ...children.props,
      className: cn(baseClasses, children.props.className),
      "data-sidebar": "menu-button",
      "data-active": isActive,
      // @ts-ignore
      ref,
      children: innerContent,
    });
  }

  return (
    <button
      ref={ref as any}
      data-sidebar="menu-button"
      data-active={isActive}
      className={baseClasses}
      {...(props as any)}
    >
      {innerContent}
    </button>
  );
});
SidebarMenuButton.displayName = "SidebarMenuButton";

// --- SUB MENU ---

export const SidebarMenuSub = React.forwardRef<HTMLUListElement, React.ComponentProps<"ul">>(
  ({ className, ...props }, ref) => (
    <ul
      ref={ref}
      data-sidebar="menu-sub"
      className={cn(
        "mx-3.5 flex min-w-0 translate-x-px flex-col gap-1 border-l border-slate-200 dark:border-zinc-800 px-2.5 py-0.5",
        "group-data-[collapsible=icon]:hidden",
        className
      )}
      {...props}
    />
  )
);
SidebarMenuSub.displayName = "SidebarMenuSub";

export const SidebarMenuSubItem = React.forwardRef<HTMLLIElement, React.ComponentProps<"li">>(
  ({ ...props }, ref) => <li ref={ref} {...props} />
);
SidebarMenuSubItem.displayName = "SidebarMenuSubItem";

export const SidebarMenuSubButton = React.forwardRef<
  HTMLAnchorElement,
  React.ComponentProps<"a"> & { asChild?: boolean; isActive?: boolean }
>(({ asChild = false, isActive, className, children, ...props }, ref) => {
  const baseClasses = cn(
    "flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 text-sm outline-none transition-colors",
    isActive ? "bg-slate-100 text-blue-600 dark:bg-zinc-800 dark:text-blue-400 font-medium" : "text-slate-600 dark:text-slate-400 hover:bg-slate-100 hover:text-slate-900 dark:hover:bg-zinc-800 dark:hover:text-white",
    className
  );

  if (asChild && React.isValidElement(children)) {
    return React.cloneElement(children, {
      ...props,
      ...children.props,
      className: cn(baseClasses, children.props.className),
      "data-active": isActive,
      // @ts-ignore
      ref,
    });
  }

  return (
    <a ref={ref} data-active={isActive} className={baseClasses} {...props}>
      {children}
    </a>
  );
});
SidebarMenuSubButton.displayName = "SidebarMenuSubButton";

--- FILE: frontend-web/registry/navigation/Breadcrumbs.tsx ---

import * as React from "react";
import { ChevronRight, MoreHorizontal } from "lucide-react";
import { cn } from "../core/utils";

// --- Utility for standard asChild functionality without Radix ---
function Slot({ children, ...props }: any) {
  if (React.isValidElement(children)) {
    return React.cloneElement(children, {
      ...props,
      ...children.props,
      className: cn(props.className, children.props.className),
    } as any);
  }
  return null;
}

export const Breadcrumb = React.forwardRef<
  HTMLElement,
  React.ComponentPropsWithoutRef<"nav"> & {
    separator?: React.ReactNode;
  }
>(({ ...props }, ref) => <nav ref={ref} aria-label="breadcrumb" {...props} />);
Breadcrumb.displayName = "Breadcrumb";

export const BreadcrumbList = React.forwardRef<HTMLOListElement, React.ComponentPropsWithoutRef<"ol">>(
  ({ className, ...props }, ref) => (
    <ol
      ref={ref}
      className={cn(
        "flex flex-wrap items-center gap-1.5 break-words text-sm text-slate-500 dark:text-slate-400 sm:gap-2.5",
        className,
      )}
      {...props}
    />
  ),
);
BreadcrumbList.displayName = "BreadcrumbList";

export const BreadcrumbItem = React.forwardRef<HTMLLIElement, React.ComponentPropsWithoutRef<"li">>(
  ({ className, ...props }, ref) => (
    <li ref={ref} className={cn("inline-flex items-center gap-1.5", className)} {...props} />
  ),
);
BreadcrumbItem.displayName = "BreadcrumbItem";

export const BreadcrumbLink = React.forwardRef<
  HTMLAnchorElement,
  React.ComponentPropsWithoutRef<"a"> & {
    asChild?: boolean;
  }
>(({ asChild, className, ...props }, ref) => {
  const Comp = asChild ? Slot : "a";

  return (
    <Comp
      ref={ref}
      className={cn("transition-colors hover:text-slate-900 dark:hover:text-white", className)}
      {...props}
    />
  );
});
BreadcrumbLink.displayName = "BreadcrumbLink";

export const BreadcrumbPage = React.forwardRef<HTMLSpanElement, React.ComponentPropsWithoutRef<"span">>(
  ({ className, ...props }, ref) => (
    <span
      ref={ref}
      role="link"
      aria-disabled="true"
      aria-current="page"
      className={cn("font-medium text-slate-900 dark:text-white", className)}
      {...props}
    />
  ),
);
BreadcrumbPage.displayName = "BreadcrumbPage";

export const BreadcrumbSeparator = ({ children, className, ...props }: React.ComponentProps<"li">) => (
  <li role="presentation" aria-hidden="true" className={className} {...props}>
    {children ?? <ChevronRight className="w-3.5 h-3.5" strokeWidth={2.5} />}
  </li>
);
BreadcrumbSeparator.displayName = "BreadcrumbSeparator";

export const BreadcrumbEllipsis = ({ className, ...props }: React.ComponentProps<"span">) => (
  <span
    role="presentation"
    aria-hidden="true"
    className={cn("flex size-5 items-center justify-center", className)}
    {...props}
  >
    <MoreHorizontal className="w-4 h-4" strokeWidth={2} />
    <span className="sr-only">More</span>
  </span>
);
BreadcrumbEllipsis.displayName = "BreadcrumbEllipsis";

--- FILE: frontend-web/registry/navigation/ExpandableSidebar.tsx ---

import React, { useState, useEffect, useRef } from "react";
import { motion, AnimatePresence } from "framer-motion";
import {
  Blocks,
  ChevronsUpDown,
  FileClock,
  GraduationCap,
  Layout,
  LayoutDashboard,
  LogOut,
  MessageSquareText,
  MessagesSquare,
  Plus,
  Settings,
  UserCircle,
  UserCog,
  UserSearch,
} from "lucide-react";
import { cn } from "../core/utils";

// --- Types ---
export interface SidebarLink {
  name: string;
  href: string;
  icon: React.ElementType;
  badge?: string;
}

export interface ExpandableSidebarProps {
  organizationName?: string;
  organizationInitial?: string;
  user?: {
    name: string;
    email: string;
    initials: string;
  };
  currentPath?: string;
  linkGroups?: SidebarLink[][];
  className?: string;
}

// --- Default Data ---
const DEFAULT_LINK_GROUPS: SidebarLink[][] = [
  [
    { name: "Dashboard", href: "/dashboard", icon: LayoutDashboard },
    { name: "Reports", href: "/reports", icon: FileClock },
    { name: "Chat", href: "/chat", icon: MessagesSquare, badge: "BETA" },
  ],
  [
    { name: "Deals", href: "/deals", icon: Layout },
    { name: "Accounts", href: "/accounts", icon: UserCircle },
    { name: "Competitors", href: "/competitors", icon: UserSearch },
  ],
  [
    { name: "Knowledge Base", href: "/library/knowledge", icon: GraduationCap },
    { name: "Feedback", href: "/feedback", icon: MessageSquareText },
    { name: "Document Review", href: "/review", icon: FileClock },
  ],
];

// --- Simple Custom Dropdown Hook ---
function useDropdown() {
  const [isOpen, setIsOpen] = useState(false);
  const ref = useRef<HTMLDivElement>(null);

  useEffect(() => {
    const handleClickOutside = (e: MouseEvent) => {
      if (ref.current && !ref.current.contains(e.target as Node)) {
        setIsOpen(false);
      }
    };
    document.addEventListener("mousedown", handleClickOutside);
    return () => document.removeEventListener("mousedown", handleClickOutside);
  }, []);

  return { isOpen, setIsOpen, ref };
}

// --- Animation Variants ---
const sidebarVariants = {
  open: { width: "15rem" },
  closed: { width: "3.5rem" },
};

const textVariants = {
  open: { opacity: 1, x: 0, display: "block", transition: { delay: 0.1 } },
  closed: { opacity: 0, x: -10, transition: { duration: 0.1 }, transitionEnd: { display: "none" } },
};

export function ExpandableSidebar({
  organizationName = "Organization",
  organizationInitial = "O",
  user = { name: "Andrew Luo", email: "andrew@usehindsight.com", initials: "AL" },
  currentPath = "/dashboard",
  linkGroups = DEFAULT_LINK_GROUPS,
  className,
}: ExpandableSidebarProps) {
  const [isHovered, setIsHovered] = useState(false);
  
  // Dropdown states
  const orgDropdown = useDropdown();
  const userDropdown = useDropdown();

  // Keep sidebar open if a dropdown is open
  const isExpanded = isHovered || orgDropdown.isOpen || userDropdown.isOpen;

  return (
    <motion.div
      className={cn(
        "fixed left-0 top-0 z-40 h-screen shrink-0 border-r border-slate-200 dark:border-zinc-800 bg-white dark:bg-zinc-950",
        className
      )}
      initial="closed"
      animate={isExpanded ? "open" : "closed"}
      variants={sidebarVariants}
      transition={{ type: "tween", ease: "easeOut", duration: 0.2 }}
      onMouseEnter={() => setIsHovered(true)}
      onMouseLeave={() => setIsHovered(false)}
    >
      <div className="flex h-full w-full flex-col text-slate-500 dark:text-slate-400">
        
        {/* Top: Organization Dropdown */}
        <div className="flex h-[60px] w-full shrink-0 border-b border-slate-200 dark:border-zinc-800 p-3" ref={orgDropdown.ref}>
          <div className="relative w-full">
            <button
              onClick={() => orgDropdown.setIsOpen(!orgDropdown.isOpen)}
              className="flex w-full items-center gap-3 rounded-md px-2 py-1.5 hover:bg-slate-100 dark:hover:bg-zinc-800 transition-colors focus:outline-none"
            >
              <div className="flex size-6 shrink-0 items-center justify-center rounded bg-slate-200 dark:bg-zinc-800 text-xs font-semibold text-slate-700 dark:text-slate-300">
                {organizationInitial}
              </div>
              <motion.div variants={textVariants} className="flex flex-1 items-center justify-between overflow-hidden whitespace-nowrap">
                <p className="text-sm font-medium text-slate-900 dark:text-white">
                  {organizationName}
                </p>
                <ChevronsUpDown className="h-4 w-4 text-slate-400" />
              </motion.div>
            </button>

            <AnimatePresence>
              {orgDropdown.isOpen && (
                <motion.div 
                  initial={{ opacity: 0, y: 5 }} animate={{ opacity: 1, y: 0 }} exit={{ opacity: 0, y: 5 }}
                  className="absolute left-0 top-full mt-2 w-56 rounded-lg border border-slate-200 dark:border-zinc-800 bg-white dark:bg-zinc-900 p-1 shadow-lg z-50"
                >
                  <a href="#" className="flex items-center gap-2 rounded-md px-3 py-2 text-sm text-slate-700 dark:text-slate-300 hover:bg-slate-100 dark:hover:bg-zinc-800">
                    <UserCog className="h-4 w-4" /> Manage members
                  </a>
                  <a href="#" className="flex items-center gap-2 rounded-md px-3 py-2 text-sm text-slate-700 dark:text-slate-300 hover:bg-slate-100 dark:hover:bg-zinc-800">
                    <Blocks className="h-4 w-4" /> Integrations
                  </a>
                  <div className="my-1 h-px bg-slate-200 dark:bg-zinc-800" />
                  <a href="#" className="flex items-center gap-2 rounded-md px-3 py-2 text-sm text-slate-700 dark:text-slate-300 hover:bg-slate-100 dark:hover:bg-zinc-800">
                    <Plus className="h-4 w-4" /> Create or join organization
                  </a>
                </motion.div>
              )}
            </AnimatePresence>
          </div>
        </div>

        {/* Middle: Scrollable Links */}
        <div className="flex-1 overflow-y-auto overflow-x-hidden p-3 custom-scrollbar">
          <div className="flex flex-col gap-1 w-full">
            {linkGroups.map((group, groupIdx) => (
              <React.Fragment key={groupIdx}>
                {groupIdx > 0 && <div className="my-2 h-px w-full bg-slate-200 dark:bg-zinc-800" />}
                {group.map((link) => {
                  const Icon = link.icon;
                  const isActive = currentPath?.includes(link.href);
                  return (
                    <a
                      key={link.name}
                      href={link.href}
                      className={cn(
                        "flex h-9 w-full items-center gap-3 rounded-md px-2 py-1.5 transition-colors",
                        isActive 
                          ? "bg-slate-100 text-blue-600 dark:bg-zinc-800 dark:text-blue-400" 
                          : "hover:bg-slate-100 hover:text-slate-900 dark:hover:bg-zinc-800 dark:hover:text-white text-slate-600 dark:text-slate-400"
                      )}
                    >
                      <Icon className="h-5 w-5 shrink-0" />
                      <motion.div variants={textVariants} className="flex flex-1 items-center overflow-hidden whitespace-nowrap">
                        <span className="text-sm font-medium">{link.name}</span>
                        {link.badge && (
                          <span className="ml-2 rounded bg-blue-50 dark:bg-blue-900/30 px-1.5 py-0.5 text-[10px] font-semibold text-blue-600 dark:text-blue-400 border border-blue-200 dark:border-blue-800">
                            {link.badge}
                          </span>
                        )}
                      </motion.div>
                    </a>
                  );
                })}
              </React.Fragment>
            ))}
          </div>
        </div>

        {/* Bottom: Settings & User Account */}
        <div className="shrink-0 border-t border-slate-200 dark:border-zinc-800 p-3 flex flex-col gap-1">
          <a
            href="/settings"
            className="flex h-9 w-full items-center gap-3 rounded-md px-2 py-1.5 text-slate-600 dark:text-slate-400 hover:bg-slate-100 hover:text-slate-900 dark:hover:bg-zinc-800 dark:hover:text-white transition-colors"
          >
            <Settings className="h-5 w-5 shrink-0" />
            <motion.span variants={textVariants} className="text-sm font-medium whitespace-nowrap overflow-hidden">
              Settings
            </motion.span>
          </a>

          <div className="relative w-full mt-1" ref={userDropdown.ref}>
            <button
              onClick={() => userDropdown.setIsOpen(!userDropdown.isOpen)}
              className="flex w-full items-center gap-3 rounded-md px-2 py-1.5 hover:bg-slate-100 dark:hover:bg-zinc-800 transition-colors focus:outline-none"
            >
              <div className="flex size-6 shrink-0 items-center justify-center rounded-full bg-slate-200 dark:bg-zinc-800 text-xs font-semibold text-slate-700 dark:text-slate-300">
                {user.initials}
              </div>
              <motion.div variants={textVariants} className="flex flex-1 items-center justify-between overflow-hidden whitespace-nowrap">
                <p className="text-sm font-medium text-slate-900 dark:text-white">Account</p>
                <ChevronsUpDown className="h-4 w-4 text-slate-400" />
              </motion.div>
            </button>

            <AnimatePresence>
              {userDropdown.isOpen && (
                <motion.div 
                  initial={{ opacity: 0, y: 5 }} animate={{ opacity: 1, y: 0 }} exit={{ opacity: 0, y: 5 }}
                  className="absolute bottom-full left-0 mb-2 w-56 rounded-lg border border-slate-200 dark:border-zinc-800 bg-white dark:bg-zinc-900 p-1 shadow-lg z-50"
                >
                  <div className="flex items-center gap-3 px-3 py-2">
                    <div className="flex size-8 shrink-0 items-center justify-center rounded-full bg-slate-200 dark:bg-zinc-800 text-xs font-semibold text-slate-700 dark:text-slate-300">
                      {user.initials}
                    </div>
                    <div className="flex flex-col overflow-hidden">
                      <span className="text-sm font-medium text-slate-900 dark:text-white truncate">{user.name}</span>
                      <span className="text-xs text-slate-500 dark:text-slate-400 truncate">{user.email}</span>
                    </div>
                  </div>
                  <div className="my-1 h-px bg-slate-200 dark:bg-zinc-800" />
                  <a href="#" className="flex items-center gap-2 rounded-md px-3 py-2 text-sm text-slate-700 dark:text-slate-300 hover:bg-slate-100 dark:hover:bg-zinc-800">
                    <UserCircle className="h-4 w-4" /> Profile
                  </a>
                  <a href="#" className="flex items-center gap-2 rounded-md px-3 py-2 text-sm text-red-600 hover:bg-red-50 dark:hover:bg-red-900/20">
                    <LogOut className="h-4 w-4" /> Sign out
                  </a>
                </motion.div>
              )}
            </AnimatePresence>
          </div>
        </div>
        
      </div>
    </motion.div>
  );
}

--- FILE: frontend-web/registry/navigation/FloatingHeader.tsx ---

import React, { useState, useEffect } from 'react';
import { Grid2X2PlusIcon, MenuIcon, X } from 'lucide-react';
import { motion, AnimatePresence } from 'framer-motion';
import { cn } from '../core/utils';

export interface NavLink {
  label: string;
  href: string;
}

export interface FloatingHeaderProps {
  brandName?: string;
  logo?: React.ReactNode;
  links?: NavLink[];
  loginText?: string;
  signupText?: string;
  onLoginClick?: () => void;
  onSignupClick?: () => void;
  className?: string;
}

const DEFAULT_LINKS: NavLink[] = [
  { label: 'Features', href: '#' },
  { label: 'Pricing', href: '#' },
  { label: 'About', href: '#' },
];

export function FloatingHeader({
  brandName = "Acme",
  logo = <Grid2X2PlusIcon className="size-5" />,
  links = DEFAULT_LINKS,
  loginText = "Login",
  signupText = "Get Started",
  onLoginClick,
  onSignupClick,
  className
}: FloatingHeaderProps) {
  const [open, setOpen] = useState(false);

  // Lock body scroll when mobile menu is open
  useEffect(() => {
    if (open) {
      document.body.style.overflow = 'hidden';
    } else {
      document.body.style.overflow = '';
    }
    return () => {
      document.body.style.overflow = '';
    };
  }, [open]);

  // Common button classes to replace Shadcn dependencies
  const btnBase = "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-slate-400 disabled:pointer-events-none disabled:opacity-50";
  const btnGhost = "hover:bg-slate-100 hover:text-slate-900 dark:hover:bg-zinc-800 dark:hover:text-slate-50 text-slate-700 dark:text-slate-300";
  const btnOutline = "border border-slate-200 bg-white hover:bg-slate-100 hover:text-slate-900 dark:border-zinc-800 dark:bg-zinc-950 dark:hover:bg-zinc-800 dark:hover:text-slate-50 text-slate-900 dark:text-white";
  const btnPrimary = "bg-slate-900 text-slate-50 hover:bg-slate-900/90 dark:bg-slate-50 dark:text-slate-900 dark:hover:bg-slate-50/90 shadow-sm";
  const btnSm = "h-8 px-3 text-xs";
  const btnDefault = "h-9 px-4 py-2";

  return (
    <>
      <header
        className={cn(
          'sticky top-5 z-40 mx-auto w-full max-w-3xl rounded-xl border border-slate-200 dark:border-zinc-800 shadow-md',
          'bg-white/90 dark:bg-zinc-950/90 backdrop-blur-lg',
          className
        )}
      >
        <nav className="mx-auto flex items-center justify-between p-2">
          {/* Logo & Brand */}
          <a href="/" className="hover:bg-slate-100 dark:hover:bg-zinc-800 text-slate-900 dark:text-white flex cursor-pointer items-center gap-2 rounded-lg px-3 py-1.5 transition-colors duration-200">
            {logo}
            <p className="font-mono text-base font-bold tracking-tight">{brandName}</p>
          </a>
          
          {/* Desktop Links */}
          <div className="hidden items-center gap-1 lg:flex">
            {links.map((link) => (
              <a
                key={link.label}
                className={cn(btnBase, btnGhost, btnSm)}
                href={link.href}
              >
                {link.label}
              </a>
            ))}
          </div>

          {/* Desktop Actions & Mobile Menu Toggle */}
          <div className="flex items-center gap-2 pr-1">
            <button 
              className={cn(btnBase, btnPrimary, btnSm, "hidden lg:inline-flex")}
              onClick={onLoginClick}
            >
              {loginText}
            </button>
            <button
              className={cn(btnBase, btnOutline, "h-8 w-8 px-0 lg:hidden")}
              onClick={() => setOpen(true)}
              aria-label="Open menu"
            >
              <MenuIcon className="size-4" />
            </button>
          </div>
        </nav>
      </header>

      {/* Mobile Drawer */}
      <AnimatePresence>
        {open && (
          <>
            {/* Backdrop */}
            <motion.div
              initial={{ opacity: 0 }}
              animate={{ opacity: 1 }}
              exit={{ opacity: 0 }}
              transition={{ duration: 0.2 }}
              className="fixed inset-0 z-50 bg-black/40 backdrop-blur-sm lg:hidden"
              onClick={() => setOpen(false)}
              aria-hidden="true"
            />

            {/* Sidebar */}
            <motion.div
              initial={{ x: '-100%' }}
              animate={{ x: 0 }}
              exit={{ x: '-100%' }}
              transition={{ type: "spring", damping: 25, stiffness: 200 }}
              className="fixed top-0 left-0 z-50 h-full w-3/4 max-w-sm bg-white/95 dark:bg-zinc-950/95 backdrop-blur-xl border-r border-slate-200 dark:border-zinc-800 shadow-2xl flex flex-col justify-between lg:hidden"
            >
              <div>
                <div className="flex items-center justify-between p-6 border-b border-slate-200 dark:border-zinc-800">
                  <div className="flex items-center gap-2 text-slate-900 dark:text-white">
                    {logo}
                    <p className="font-mono text-base font-bold">{brandName}</p>
                  </div>
                  <button 
                    onClick={() => setOpen(false)}
                    className="p-2 -mr-2 text-slate-500 hover:text-slate-900 dark:text-slate-400 dark:hover:text-white transition-colors rounded-md hover:bg-slate-100 dark:hover:bg-zinc-800"
                  >
                    <X className="size-5" />
                  </button>
                </div>
                
                <div className="grid gap-2 overflow-y-auto p-6">
                  {links.map((link) => (
                    <a
                      key={link.label}
                      className={cn(btnBase, btnGhost, btnDefault, 'justify-start w-full text-base')}
                      href={link.href}
                      onClick={() => setOpen(false)}
                    >
                      {link.label}
                    </a>
                  ))}
                </div>
              </div>

              <div className="p-6 border-t border-slate-200 dark:border-zinc-800 flex flex-col gap-3">
                <button 
                  className={cn(btnBase, btnOutline, btnDefault, "w-full")}
                  onClick={(e) => {
                    setOpen(false);
                    onLoginClick?.();
                  }}
                >
                  {loginText}
                </button>
                <button 
                  className={cn(btnBase, btnPrimary, btnDefault, "w-full")}
                  onClick={(e) => {
                    setOpen(false);
                    onSignupClick?.();
                  }}
                >
                  {signupText}
                </button>
              </div>
            </motion.div>
          </>
        )}
      </AnimatePresence>
    </>
  );
}

--- FILE: frontend-web/registry/navigation/MacDock.tsx ---

import React, { useRef } from "react";
import { motion, useMotionValue, useSpring, useTransform, MotionValue } from "framer-motion";
import { cn } from "../core/utils";

export interface DockProps extends React.HTMLAttributes<HTMLDivElement> {
  className?: string;
  magnification?: number;
  distance?: number;
  direction?: "top" | "middle" | "bottom";
  children: React.ReactNode;
}

const DEFAULT_MAGNIFICATION = 60;
const DEFAULT_DISTANCE = 140;

export const MacDock = React.forwardRef<HTMLDivElement, DockProps>(
  (
    {
      className,
      children,
      magnification = DEFAULT_MAGNIFICATION,
      distance = DEFAULT_DISTANCE,
      direction = "bottom",
      ...props
    },
    ref,
  ) => {
    const mouseX = useMotionValue(Infinity);

    const renderChildren = () => {
      return React.Children.map(children, (child) => {
        if (React.isValidElement(child) && child.type === DockIcon) {
          return React.cloneElement(child, {
            ...child.props,
            mouseX: mouseX,
            magnification: magnification,
            distance: distance,
          } as DockIconProps);
        }
        return child;
      });
    };

    return (
      <motion.div
        ref={ref}
        onMouseMove={(e) => mouseX.set(e.clientX)}
        onMouseLeave={() => mouseX.set(Infinity)}
        {...props}
        className={cn(
          "mx-auto flex h-[58px] w-max gap-2 rounded-2xl border border-slate-200 dark:border-zinc-800 p-2",
          "bg-white/10 dark:bg-black/10 backdrop-blur-md shadow-sm",
          {
            "items-start": direction === "top",
            "items-center": direction === "middle",
            "items-end": direction === "bottom",
          },
          className
        )}
      >
        {renderChildren()}
      </motion.div>
    );
  },
);

MacDock.displayName = "MacDock";

export interface DockIconProps extends React.HTMLAttributes<HTMLDivElement> {
  size?: number;
  magnification?: number;
  distance?: number;
  mouseX?: MotionValue<number>;
  className?: string;
  children?: React.ReactNode;
}

export const DockIcon = ({
  size = 40,
  magnification = DEFAULT_MAGNIFICATION,
  distance = DEFAULT_DISTANCE,
  mouseX,
  className,
  children,
  ...props
}: DockIconProps) => {
  const ref = useRef<HTMLDivElement>(null);

  // If mouseX isn't provided (rendered outside Dock), use a dummy value
  const defaultMouseX = useMotionValue(Infinity);
  const actualMouseX = mouseX || defaultMouseX;

  const distanceCalc = useTransform(actualMouseX, (val: number) => {
    const bounds = ref.current?.getBoundingClientRect() ?? { x: 0, width: 0 };
    return val - bounds.x - bounds.width / 2;
  });

  const widthSync = useTransform(
    distanceCalc,
    [-distance, 0, distance],
    [size, magnification, size],
  );

  const width = useSpring(widthSync, {
    mass: 0.1,
    stiffness: 150,
    damping: 12,
  });

  return (
    <motion.div
      ref={ref}
      style={{ width }}
      className={cn(
        "flex aspect-square cursor-pointer items-center justify-center rounded-full bg-slate-100 dark:bg-zinc-800 text-slate-700 dark:text-slate-300 hover:text-slate-900 dark:hover:text-white transition-colors border border-slate-200 dark:border-zinc-700",
        className,
      )}
      {...props}
    >
      {children}
    </motion.div>
  );
};

DockIcon.displayName = "DockIcon";

--- FILE: frontend-web/registry/navigation/MegaMenuHeader.tsx ---

import React, { useState, useEffect, useRef } from "react";
import { motion, AnimatePresence } from "framer-motion";
import { Menu, MoveRight, X, ChevronDown } from "lucide-react";
import { cn } from "../core/utils";

// --- Types ---
export interface MegaMenuSubItem {
  title: string;
  href: string;
}

export interface MegaMenuItem {
  title: string;
  href?: string;
  description?: string;
  items?: MegaMenuSubItem[];
}

export interface MegaMenuHeaderProps {
  brandName?: string;
  logo?: React.ReactNode;
  menuItems?: MegaMenuItem[];
  ctaPrimaryText?: string;
  ctaSecondaryText?: string;
  ctaTertiaryText?: string;
  onCtaPrimaryClick?: () => void;
  onCtaSecondaryClick?: () => void;
  onCtaTertiaryClick?: () => void;
  className?: string;
}

// --- Default Data ---
const DEFAULT_MENU_ITEMS: MegaMenuItem[] = [
  {
    title: "Home",
    href: "/",
  },
  {
    title: "Product",
    description: "Managing a small business today is already tough. We make it easy.",
    items: [
      { title: "Reports", href: "#" },
      { title: "Statistics", href: "#" },
      { title: "Dashboards", href: "#" },
      { title: "Recordings", href: "#" },
    ],
  },
  {
    title: "Company",
    description: "Learn more about our mission, our team, and our investors.",
    items: [
      { title: "About us", href: "#" },
      { title: "Fundraising", href: "#" },
      { title: "Investors", href: "#" },
      { title: "Contact us", href: "#" },
    ],
  },
];

// --- Subcomponent: Desktop Dropdown ---
const DesktopDropdown = ({ item }: { item: MegaMenuItem }) => {
  const [isOpen, setIsOpen] = useState(false);
  const timeoutRef = useRef<NodeJS.Timeout | null>(null);

  const handleMouseEnter = () => {
    if (timeoutRef.current) clearTimeout(timeoutRef.current);
    setIsOpen(true);
  };

  const handleMouseLeave = () => {
    timeoutRef.current = setTimeout(() => {
      setIsOpen(false);
    }, 150); // slight delay to make moving to the dropdown easier
  };

  return (
    <div 
      className="relative"
      onMouseEnter={handleMouseEnter}
      onMouseLeave={handleMouseLeave}
    >
      <button className="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors hover:bg-slate-100 hover:text-slate-900 dark:hover:bg-zinc-800 dark:hover:text-slate-50 h-9 px-4 py-2 text-slate-700 dark:text-slate-300 gap-1 group">
        {item.title}
        <ChevronDown className={cn("w-4 h-4 transition-transform duration-200", isOpen && "rotate-180")} />
      </button>

      <AnimatePresence>
        {isOpen && (
          <motion.div
            initial={{ opacity: 0, y: 10, scale: 0.95 }}
            animate={{ opacity: 1, y: 0, scale: 1 }}
            exit={{ opacity: 0, y: 10, scale: 0.95 }}
            transition={{ duration: 0.2, ease: "easeOut" }}
            className="absolute top-full left-0 pt-2 z-50"
          >
            <div className="w-[450px] p-4 bg-white dark:bg-zinc-950 border border-slate-200 dark:border-zinc-800 rounded-xl shadow-xl">
              <div className="flex flex-col lg:grid grid-cols-2 gap-4">
                <div className="flex flex-col h-full justify-between bg-slate-50 dark:bg-zinc-900/50 p-4 rounded-lg">
                  <div className="flex flex-col">
                    <p className="text-base font-medium text-slate-900 dark:text-white mb-2">{item.title}</p>
                    <p className="text-slate-500 dark:text-slate-400 text-sm leading-relaxed">
                      {item.description}
                    </p>
                  </div>
                  <button className="mt-6 inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none bg-slate-900 text-slate-50 hover:bg-slate-900/90 dark:bg-white dark:text-slate-900 dark:hover:bg-white/90 h-9 px-4 py-2 w-max">
                    Book a call today
                  </button>
                </div>
                <div className="flex flex-col text-sm h-full justify-center gap-1">
                  {item.items?.map((subItem) => (
                    <a
                      href={subItem.href}
                      key={subItem.title}
                      className="flex flex-row justify-between items-center hover:bg-slate-100 dark:hover:bg-zinc-800 text-slate-700 dark:text-slate-300 hover:text-slate-900 dark:hover:text-white py-2 px-3 rounded-md transition-colors"
                    >
                      <span className="font-medium">{subItem.title}</span>
                      <MoveRight className="w-4 h-4 opacity-50" />
                    </a>
                  ))}
                </div>
              </div>
            </div>
          </motion.div>
        )}
      </AnimatePresence>
    </div>
  );
};

// --- Main Component ---
export function MegaMenuHeader({
  brandName = "NOVA UI",
  logo,
  menuItems = DEFAULT_MENU_ITEMS,
  ctaPrimaryText = "Get started",
  ctaSecondaryText = "Sign in",
  ctaTertiaryText = "Book a demo",
  onCtaPrimaryClick,
  onCtaSecondaryClick,
  onCtaTertiaryClick,
  className,
}: MegaMenuHeaderProps) {
  const [isOpen, setOpen] = useState(false);

  // Common button classes
  const btnBase = "inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50 h-9 px-4 py-2";
  const btnGhost = "hover:bg-slate-100 hover:text-slate-900 dark:hover:bg-zinc-800 dark:hover:text-slate-50 text-slate-700 dark:text-slate-300";
  const btnOutline = "border border-slate-200 bg-white hover:bg-slate-100 hover:text-slate-900 dark:border-zinc-800 dark:bg-zinc-950 dark:hover:bg-zinc-800 dark:hover:text-slate-50 text-slate-900 dark:text-white";
  const btnPrimary = "bg-slate-900 text-slate-50 hover:bg-slate-900/90 dark:bg-white dark:text-slate-900 dark:hover:bg-white/90 shadow-sm";

  return (
    <header className={cn("w-full z-40 fixed top-0 left-0 bg-white dark:bg-zinc-950 border-b border-slate-200 dark:border-zinc-800", className)}>
      <div className="container mx-auto px-4 md:px-6 relative min-h-20 flex gap-4 flex-row lg:grid lg:grid-cols-3 items-center">
        
        {/* Left: Desktop Navigation */}
        <div className="justify-start items-center gap-2 lg:flex hidden flex-row">
          <nav className="flex justify-start items-center gap-2 flex-row">
            {menuItems.map((item) => (
              <React.Fragment key={item.title}>
                {item.href && !item.items ? (
                  <a href={item.href} className={cn(btnBase, btnGhost)}>
                    {item.title}
                  </a>
                ) : (
                  <DesktopDropdown item={item} />
                )}
              </React.Fragment>
            ))}
          </nav>
        </div>

        {/* Center: Brand */}
        <div className="flex lg:justify-center items-center gap-2 w-full lg:w-auto">
          <a href="/" className="flex items-center gap-2 text-slate-900 dark:text-white">
            {logo}
            <p className="font-bold text-lg tracking-tight">{brandName}</p>
          </a>
        </div>

        {/* Right: CTAs */}
        <div className="hidden lg:flex justify-end w-full gap-3">
          <button className={cn(btnBase, btnGhost)} onClick={onCtaTertiaryClick}>
            {ctaTertiaryText}
          </button>
          <div className="w-px h-5 bg-slate-200 dark:bg-zinc-800 self-center mx-1"></div>
          <button className={cn(btnBase, btnOutline)} onClick={onCtaSecondaryClick}>
            {ctaSecondaryText}
          </button>
          <button className={cn(btnBase, btnPrimary)} onClick={onCtaPrimaryClick}>
            {ctaPrimaryText}
          </button>
        </div>

        {/* Mobile Toggle */}
        <div className="flex shrink-0 lg:hidden items-center justify-end">
          <button 
            className={cn(btnBase, btnGhost, "px-2")} 
            onClick={() => setOpen(!isOpen)}
            aria-label="Toggle menu"
          >
            {isOpen ? <X className="w-6 h-6" /> : <Menu className="w-6 h-6" />}
          </button>
        </div>
      </div>

      {/* Mobile Menu Dropdown */}
      <AnimatePresence>
        {isOpen && (
          <motion.div 
            initial={{ height: 0, opacity: 0 }}
            animate={{ height: "auto", opacity: 1 }}
            exit={{ height: 0, opacity: 0 }}
            className="absolute top-full left-0 w-full bg-white dark:bg-zinc-950 border-b border-slate-200 dark:border-zinc-800 shadow-xl overflow-hidden lg:hidden"
          >
            <div className="container mx-auto px-6 py-6 flex flex-col gap-6">
              {menuItems.map((item) => (
                <div key={item.title} className="flex flex-col gap-3">
                  {item.href && !item.items ? (
                    <a
                      href={item.href}
                      className="flex justify-between items-center text-slate-900 dark:text-white font-medium text-lg border-b border-slate-100 dark:border-zinc-900 pb-2"
                    >
                      <span>{item.title}</span>
                      <MoveRight className="w-4 h-4 text-slate-400" />
                    </a>
                  ) : (
                    <>
                      <p className="text-lg font-bold text-slate-900 dark:text-white border-b border-slate-100 dark:border-zinc-900 pb-2">
                        {item.title}
                      </p>
                      <div className="flex flex-col gap-3 pl-2 border-l-2 border-slate-100 dark:border-zinc-900 ml-2">
                        {item.items?.map((subItem) => (
                          <a
                            key={subItem.title}
                            href={subItem.href}
                            className="flex justify-between items-center text-slate-600 dark:text-slate-400 hover:text-slate-900 dark:hover:text-white"
                          >
                            <span className="font-medium">{subItem.title}</span>
                            <MoveRight className="w-4 h-4 opacity-50" />
                          </a>
                        ))}
                      </div>
                    </>
                  )}
                </div>
              ))}
              
              <div className="flex flex-col gap-3 pt-4 border-t border-slate-200 dark:border-zinc-800">
                <button className={cn(btnBase, btnOutline, "w-full justify-center")} onClick={onCtaSecondaryClick}>
                  {ctaSecondaryText}
                </button>
                <button className={cn(btnBase, btnPrimary, "w-full justify-center")} onClick={onCtaPrimaryClick}>
                  {ctaPrimaryText}
                </button>
              </div>
            </div>
          </motion.div>
        )}
      </AnimatePresence>
    </header>
  );
}

--- FILE: frontend-web/registry/sections/AboutGrid.tsx ---

import React from "react";
import { cn } from "../core/utils";

export interface AboutFeature {
  title: string;
  description: string;
  iconUrl: string;
}

export interface AboutGridProps {
  title?: string;
  subtitle?: string;
  features?: AboutFeature[];
  className?: string;
}

const DEFAULT_FEATURES: AboutFeature[] = [
  {
    title: "Lightning-Fast Performance",
    description: "Built with speed — minimal load times and optimized.",
    iconUrl: "https://raw.githubusercontent.com/prebuiltui/prebuiltui/main/assets/aboutSection/flashEmoji.png"
  },
  {
    title: "Beautifully Designed Components",
    description: "Modern, pixel-perfect UI components ready for any project.",
    iconUrl: "https://raw.githubusercontent.com/prebuiltui/prebuiltui/main/assets/aboutSection/colorsEmoji.png"
  },
  {
    title: "Plug-and-Play Integration",
    description: "Simple setup with support for React, Next.js and Tailwind css.",
    iconUrl: "https://raw.githubusercontent.com/prebuiltui/prebuiltui/main/assets/aboutSection/puzzelEmoji.png"
  },
  {
    title: "Clear & Comprehensive",
    description: "Get started fast with usage examples, live previews and code.",
    iconUrl: "https://raw.githubusercontent.com/prebuiltui/prebuiltui/main/assets/aboutSection/bookEmoji.png"
  },
  {
    title: "Fully Customizable",
    description: "Easily adapt styles, colors and layout to match your brand or product.",
    iconUrl: "https://raw.githubusercontent.com/prebuiltui/prebuiltui/main/assets/aboutSection/boxEmoji.png"
  },
  {
    title: "Accessibility First",
    description: "Built with WCAG standards in mind to ensure inclusive user experiences.",
    iconUrl: "https://raw.githubusercontent.com/prebuiltui/prebuiltui/main/assets/aboutSection/brainEmoji.png"
  }
];

export function AboutGrid({
  title = "About our apps",
  subtitle = "A visual collection of our most recent works - each piece crafted with intention, emotion and style.",
  features = DEFAULT_FEATURES,
  className
}: AboutGridProps) {
  return (
    <section className={cn("relative py-16 md:py-24 overflow-hidden", className)}>
      {/* Background glow */}
      <div className="size-[520px] -top-80 left-1/2 -translate-x-1/2 rounded-full absolute blur-[300px] -z-10 bg-[#FBFFE1] dark:bg-yellow-500/10 pointer-events-none" />
      
      <div className="max-w-7xl mx-auto px-4 sm:px-6">
        <h2 className="text-3xl font-semibold text-center mx-auto text-slate-900 dark:text-white tracking-tight">
          {title}
        </h2>
        <p className="text-sm text-slate-500 dark:text-slate-400 text-center mt-2 max-w-lg mx-auto">
          {subtitle}
        </p>
        
        <div className="relative max-w-5xl mx-auto grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-16 lg:gap-20 pt-16">
          {features.map((feature, idx) => (
            <div key={idx} className="flex flex-col">
              <div className="size-10 p-2 bg-indigo-50 dark:bg-indigo-900/30 border border-indigo-200 dark:border-indigo-800/50 rounded flex-shrink-0">
                <img src={feature.iconUrl} alt="" className="w-full h-full object-contain" />
              </div>
              <div className="mt-5 space-y-2">
                <h3 className="text-base font-medium text-slate-800 dark:text-slate-200">
                  {feature.title}
                </h3>
                <p className="text-sm text-slate-500 dark:text-slate-400 leading-relaxed">
                  {feature.description}
                </p>
              </div>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

--- FILE: frontend-web/registry/sections/ClippedVideoTab.tsx ---

import React, { useState } from "react";
import { motion, AnimatePresence } from "framer-motion";
import {
  Database,
  CheckCircle2,
  LoaderCircle,
  Circle,
  Lock,
  Zap,
  Mic,
} from "lucide-react";
import { cn } from "../core/utils";

export interface TaskItem {
  title: string;
  meta: string;
  status: "completed" | "progress" | "pending";
}

export interface TabCard {
  heading: string;
  badge: string;
  goal: string;
  tasks: TaskItem[];
}

export interface TabItem {
  icon: React.ElementType;
  label: string;
  title: string;
  description: string;
  video: string;
  card: TabCard;
}

export interface ClippedVideoTabProps {
  title?: string;
  description?: React.ReactNode;
  items?: TabItem[];
  className?: string;
}

const DEFAULT_ITEMS: TabItem[] = [
  {
    icon: Zap,
    label: "Data Annotation",
    title: "Data Annotation",
    description:
      "Multimodal workflows for image, video, and 3D annotation with high-accuracy quality control.",
    video: "https://res.cloudinary.com/dy4bqxt8p/video/upload/v1779622196/new107_qhrklf.mp4",
    card: {
      heading: "Data Trancription",
      badge: "Live",
      goal: "Sameer Deploy multimodal pipelines across multiple international regions.",
      tasks: [
        {
          title: "Regional onboarding",
          meta: "Completed in 4.2s",
          status: "completed",
        },
        {
          title: "Deploy collection teams",
          meta: "Completed in 8.1s",
          status: "completed",
        },
        {
          title: "Scale infrastructure",
          meta: "In progress... 18s",
          status: "progress",
        },
        {
          title: "Validate datasets",
          meta: "Pending",
          status: "pending",
        },
      ],
    },
  },
  {
    icon: Lock,
    label: "Data Collection",
    title: "Data Collection",
    description:
      "High-speed multimodal data collection pipelines to capture and structure real-world datasets.",
    video: "https://res.cloudinary.com/dy4bqxt8p/video/upload/v1779621768/new105_meaomd.mp4",
    card: {
      heading: "Data Collection",
      badge: "Data-Ready",
      goal: "Prepare large-scale datasets for training multimodal reasoning systems.",
      tasks: [
        {
          title: "Process raw data",
          meta: "Completed in 3.1s",
          status: "completed",
        },
        {
          title: "Generate annotations",
          meta: "Completed in 5.4s",
          status: "completed",
        },
        {
          title: "Train reasoning model",
          meta: "In progress... 24s",
          status: "progress",
        },
        {
          title: "Run evaluation tests",
          meta: "Pending",
          status: "pending",
        },
      ],
    },
  },
  {
    icon: Mic,
    label: "Audio and Speech",
    title: "Audio and Speech",
    description:
      "Automation-first AI systems with human validation and scalable workflows.",
    video: "https://res.cloudinary.com/dy4bqxt8p/video/upload/v1779622220/new108_k1a47m.mp4",
    card: {
      heading: "Audio Transcription",
      badge: "Auto-generated",
      goal: "Build a REST API endpoint for user authentication with JWT tokens.",
      tasks: [
        {
          title: "Gather requirements",
          meta: "Completed in 2.3s",
          status: "completed",
        },
        {
          title: "Research solutions",
          meta: "Completed in 5.1s",
          status: "completed",
        },
        {
          title: "Implement solution",
          meta: "In progress... 12s",
          status: "progress",
        },
        {
          title: "Test and validate",
          meta: "Pending",
          status: "pending",
        },
      ],
    },
  },
  {
    icon: Database,
    label: "Explainable AI",
    title: "Data Engine",
    description:
      "Transparent AI models with interpretable predictions and decision-making insights.",
    video: "https://res.cloudinary.com/dy4bqxt8p/video/upload/v1779622271/02_u2efg7.mp4",
    card: {
      heading: "Pipeline Engine",
      badge: "Optimized",
      goal: "Process and validate multimodal datasets for enterprise deployment.",
      tasks: [
        {
          title: "Upload raw datasets",
          meta: "Completed in 1.9s",
          status: "completed",
        },
        {
          title: "Run QA workflows",
          meta: "Completed in 6.7s",
          status: "completed",
        },
        {
          title: "Generate metadata",
          meta: "In progress... 16s",
          status: "progress",
        },
        {
          title: "Export training package",
          meta: "Pending",
          status: "pending",
        },
      ],
    },
  },
];

export function ClippedVideoTab({
  title = "Our Platforms",
  description = (
    <>
      Crafted interactive UI systems, modern component experiences— designed and
      developed by <span className="font-medium text-black">NOVA</span>.
    </>
  ),
  items = DEFAULT_ITEMS,
  className,
}: ClippedVideoTabProps) {
  const [activeTab, setActiveTab] = useState(0);

  const activeItem = items[activeTab];

  return (
    <section className={cn("bg-[#f5f5f3] py-20 overflow-hidden", className)}>
      {/* TOP */}
      <div className="max-w-7xl mx-auto px-6">
        <div className="grid md:grid-cols-2 gap-14 items-start mb-10">
          {/* LEFT */}
          <div>
            <h2 className="text-[46px] leading-[50px] tracking-tight font-bold text-[#131313] max-w-2xl">
              {title}
            </h2>
          </div>

          {/* RIGHT */}
          <div>
            <p className="text-[18px] leading-[32px] text-[#666] max-w-lg">
              {description}
            </p>
          </div>
        </div>
      </div>

      {/* IMAGE AREA */}
      <div className="max-w-7xl mx-auto px-6 relative">
        {/* FLOATING TABS */}
        <div className="absolute left-2 bottom-16 z-20 hidden md:block">
          <div className="bg-white rounded-[28px] shadow-xl border border-[#e8e8e8] p-3 w-[240px]">
            <div className="flex flex-col gap-2">
              {items.map((tab, index) => {
                const Icon = tab.icon;

                return (
                  <button
                    key={index}
                    onClick={() => setActiveTab(index)}
                    className={`
                      group flex items-center gap-3 px-4 py-3 rounded-xl text-left transition-all duration-300 border
                      ${
                        activeTab === index
                          ? "bg-[#f4fbf7] border-[#266347]"
                          : "border-transparent hover:border-[#266347] hover:bg-[#f8fffb]"
                      }
                    `}
                  >
                    <Icon
                      className={`
                        w-5 h-5 transition-colors duration-300
                        ${
                          activeTab === index
                            ? "text-[#266347]"
                            : "text-[#131313] group-hover:text-[#266347]"
                        }
                      `}
                    />

                    <span
                      className={`
                        text-[15px] font-medium transition-colors duration-300
                        ${
                          activeTab === index
                            ? "text-[#266347]"
                            : "text-[#131313] group-hover:text-[#266347]"
                        }
                      `}
                    >
                      {tab.label}
                    </span>
                  </button>
                );
              })}
            </div>
          </div>
        </div>

        {/* MOBILE TABS (Responsive adaptation) */}
        <div className="md:hidden flex overflow-x-auto gap-2 mb-4 pb-2 snap-x">
            {items.map((tab, index) => {
                const Icon = tab.icon;
                return (
                  <button
                    key={index}
                    onClick={() => setActiveTab(index)}
                    className={`
                      snap-center flex-shrink-0 flex items-center gap-2 px-4 py-2 rounded-full text-left transition-all duration-300 border
                      ${
                        activeTab === index
                          ? "bg-[#f4fbf7] border-[#266347]"
                          : "bg-white border-[#e8e8e8]"
                      }
                    `}
                  >
                    <Icon
                      className={`
                        w-4 h-4 
                        ${activeTab === index ? "text-[#266347]" : "text-[#131313]"}
                      `}
                    />
                    <span
                      className={`
                        text-[14px] font-medium 
                        ${activeTab === index ? "text-[#266347]" : "text-[#131313]"}
                      `}
                    >
                      {tab.label}
                    </span>
                  </button>
                );
              })}
        </div>

        {/* VIDEO CONTAINER */}
        <div
          className="relative overflow-hidden h-[500px] md:h-[690px]"
          style={{
            clipPath:
              "polygon(0 0, 92% 0, 100% 12%, 100% 100%, 30% 100%, 22% 88%, 0 88%)",
            borderRadius: "34px",
          }}
        >
          {/* VIDEO */}
          <AnimatePresence mode="wait">
            <motion.video
              key={activeItem.video}
              src={activeItem.video}
              autoPlay
              muted
              loop
              playsInline
              initial={{ opacity: 0 }}
              animate={{ opacity: 1 }}
              exit={{ opacity: 0 }}
              transition={{ duration: 0.45 }}
              className="absolute inset-0 w-full h-full object-cover"
            />
          </AnimatePresence>

          {/* OVERLAY */}
          <div className="absolute inset-0 bg-black/10" />

          {/* CENTER CARD */}
          <div className="absolute inset-0 flex items-center justify-center p-4">
            <AnimatePresence mode="wait">
              <motion.div
                key={activeItem.card.heading}
                initial={{ opacity: 0, y: 14 }}
                animate={{ opacity: 1, y: 0 }}
                exit={{ opacity: 0, y: 14 }}
                transition={{ duration: 0.35 }}
                className="w-full max-w-[320px] rounded-[26px] border border-white/30 bg-white/80 backdrop-blur-xl shadow-2xl p-5"
              >
                {/* HEADER */}
                <div className="flex items-center justify-between">
                  <h3 className="text-[18px] font-semibold text-[#131313]">
                    {activeItem.card.heading}
                  </h3>

                  <span className="text-[11px] bg-[#eef8f2] text-[#266347] px-2 py-1 rounded-md">
                    {activeItem.card.badge}
                  </span>
                </div>

                {/* GOAL */}
                <div className="mt-4 border border-[#e7e7e7] rounded-xl p-3 bg-white/50">
                  <p className="text-[11px] text-[#777]">Goal</p>
                  <p className="text-[13px] leading-[20px] mt-1 text-[#131313]">
                    {activeItem.card.goal}
                  </p>
                </div>

                {/* TASKS */}
                <div className="mt-4 flex flex-col gap-3">
                  {activeItem.card.tasks.map((task, index) => (
                    <div key={index} className="flex items-start gap-2">
                      {/* ICON */}
                      <div className="mt-[2px]">
                        {task.status === "completed" && (
                          <CheckCircle2 className="w-4 h-4 text-[#266347]" />
                        )}

                        {task.status === "progress" && (
                          <LoaderCircle className="w-4 h-4 text-[#266347] animate-spin" />
                        )}

                        {task.status === "pending" && (
                          <Circle className="w-4 h-4 text-[#bdbdbd]" />
                        )}
                      </div>

                      {/* CONTENT */}
                      <div>
                        <p
                          className={`
                            text-[13px]
                            ${
                              task.status === "completed"
                                ? "line-through text-[#666]"
                                : task.status === "progress"
                                ? "text-[#266347] font-medium"
                                : "text-[#999]"
                            }
                          `}
                        >
                          {task.title}
                        </p>

                        <p className="text-[11px] text-[#999]">{task.meta}</p>
                      </div>
                    </div>
                  ))}
                </div>

                {/* FOOTER */}
                <div className="flex items-center justify-between mt-5 text-[11px] text-[#888]">
                  <span>2/5 tasks complete</span>
                  <span>Est. 45s remaining</span>
                </div>
              </motion.div>
            </AnimatePresence>
          </div>
        </div>
      </div>
    </section>
  );
}

--- FILE: frontend-web/registry/sections/DesignAgencyLanding.tsx ---

import React, { useState, useEffect } from "react"
import { motion } from "framer-motion"
import {
  Menu,
  X,
  ArrowRight,
  ChevronRight,
  Mail,
  MapPin,
  Phone,
  Instagram,
  Twitter,
  Linkedin,
  Facebook,
  Github,
  ArrowUpRight,
  Sparkles,
  Zap,
  Palette,
  Code,
  LineChart,
  MessageSquare,
} from "lucide-react"
import { cn } from "../core/utils"

// Animation variants
const fadeIn = {
  hidden: { opacity: 0, y: 20 },
  visible: {
    opacity: 1,
    y: 0,
    transition: { duration: 0.6 },
  },
}

const staggerContainer = {
  hidden: { opacity: 0 },
  visible: {
    opacity: 1,
    transition: {
      staggerChildren: 0.1,
    },
  },
}

const itemFadeIn = {
  hidden: { opacity: 0, y: 20 },
  visible: {
    opacity: 1,
    y: 0,
    transition: { duration: 0.5 },
  },
}

export function DesignAgencyLanding() {
  const [isMenuOpen, setIsMenuOpen] = useState(false)
  const [scrollY, setScrollY] = useState(0)

  useEffect(() => {
    const handleScroll = () => {
      setScrollY(window.scrollY)
    }

    window.addEventListener("scroll", handleScroll)
    return () => window.removeEventListener("scroll", handleScroll)
  }, [])

  const toggleMenu = () => {
    setIsMenuOpen(!isMenuOpen)
  }

  // Helper classes for standardizing Shadcn components
  const buttonPrimary = "inline-flex items-center justify-center font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500 disabled:pointer-events-none disabled:opacity-50 bg-indigo-600 text-white hover:bg-indigo-700 dark:bg-indigo-500 dark:hover:bg-indigo-600"
  const buttonOutline = "inline-flex items-center justify-center font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500 disabled:pointer-events-none disabled:opacity-50 border border-slate-200 dark:border-zinc-800 bg-transparent hover:bg-slate-100 dark:hover:bg-zinc-800 text-slate-900 dark:text-white"
  const inputBase = "flex w-full border border-slate-200 dark:border-zinc-800 bg-transparent px-3 py-2 text-sm placeholder:text-slate-500 dark:placeholder:text-slate-400 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500 disabled:cursor-not-allowed disabled:opacity-50 text-slate-900 dark:text-white"

  return (
    <div className="flex min-h-screen flex-col bg-gradient-to-br from-white via-white to-slate-100/50 dark:from-zinc-950 dark:via-zinc-950 dark:to-zinc-900/50 text-slate-900 dark:text-white overflow-x-hidden">
      {/* Header */}
      <motion.header
        initial={{ y: -100 }}
        animate={{ y: 0 }}
        transition={{ duration: 0.5 }}
        className={`sticky top-0 z-50 w-full border-b border-slate-200 dark:border-zinc-800 bg-white/95 dark:bg-zinc-950/95 backdrop-blur supports-[backdrop-filter]:bg-white/60 dark:supports-[backdrop-filter]:bg-zinc-950/60 ${scrollY > 50 ? "shadow-md" : ""}`}
      >
        <div className="container mx-auto px-4 flex h-16 items-center justify-between border-x border-slate-200 dark:border-zinc-800">
          <div className="flex items-center gap-3">
            <a href="/" className="flex items-center space-x-3">
              <motion.div
                whileHover={{ rotate: 5, scale: 1.1 }}
                transition={{ type: "spring", stiffness: 400, damping: 10 }}
                className="h-10 w-10 rounded-3xl bg-indigo-600 dark:bg-indigo-500 flex items-center justify-center"
              >
                <Sparkles className="h-5 w-5 text-white" />
              </motion.div>
              <span className="font-bold text-xl">Studio</span>
            </a>
          </div>
          <nav className="hidden md:flex gap-4 lg:gap-6">
            <a href="#services" className="text-sm font-medium transition-colors hover:text-indigo-600 dark:hover:text-indigo-400">
              Services
            </a>
            <a href="#work" className="text-sm font-medium transition-colors hover:text-indigo-600 dark:hover:text-indigo-400">
              Work
            </a>
            <a href="#about" className="text-sm font-medium transition-colors hover:text-indigo-600 dark:hover:text-indigo-400">
              About
            </a>
            <a href="#clients" className="text-sm font-medium transition-colors hover:text-indigo-600 dark:hover:text-indigo-400">
              Clients
            </a>
            <a href="#contact" className="text-sm font-medium transition-colors hover:text-indigo-600 dark:hover:text-indigo-400">
              Contact
            </a>
          </nav>
          <div className="hidden md:flex items-center gap-3">
            <button className={cn(buttonOutline, "h-9 px-4 text-sm rounded-3xl")}>
              Log In
            </button>
            <button className={cn(buttonPrimary, "h-9 px-4 text-sm rounded-3xl")}>
              Get Started
            </button>
          </div>
          <button className="flex md:hidden text-slate-900 dark:text-white" onClick={toggleMenu}>
            <Menu className="h-6 w-6" />
            <span className="sr-only">Toggle menu</span>
          </button>
        </div>
      </motion.header>

      {/* Mobile Menu */}
      {isMenuOpen && (
        <motion.div
          initial={{ opacity: 0 }}
          animate={{ opacity: 1 }}
          exit={{ opacity: 0 }}
          className="fixed inset-0 z-50 bg-white dark:bg-zinc-950 md:hidden"
        >
          <div className="container mx-auto px-4 flex h-16 items-center justify-between">
            <div className="flex items-center gap-3">
              <a href="/" className="flex items-center space-x-3">
                <div className="h-10 w-10 rounded-3xl bg-indigo-600 dark:bg-indigo-500 flex items-center justify-center">
                  <Sparkles className="h-5 w-5 text-white" />
                </div>
                <span className="font-bold text-xl">Studio</span>
              </a>
            </div>
            <button onClick={toggleMenu} className="text-slate-900 dark:text-white">
              <X className="h-6 w-6" />
              <span className="sr-only">Close menu</span>
            </button>
          </div>
          <motion.nav
            variants={staggerContainer}
            initial="hidden"
            animate="visible"
            className="container mx-auto px-4 grid gap-3 pb-8 pt-6"
          >
            {["Services", "Work", "About", "Clients", "Contact"].map((item, index) => (
              <motion.div key={index} variants={itemFadeIn}>
                <a
                  href={`#${item.toLowerCase()}`}
                  className="flex items-center justify-between rounded-3xl px-3 py-2 text-lg font-medium hover:bg-slate-100 dark:hover:bg-zinc-900 transition-colors"
                  onClick={toggleMenu}
                >
                  {item}
                  <ChevronRight className="h-4 w-4" />
                </a>
              </motion.div>
            ))}
            <motion.div variants={itemFadeIn} className="flex flex-col gap-3 pt-4">
              <button className={cn(buttonOutline, "h-11 w-full rounded-3xl")}>
                Log In
              </button>
              <button className={cn(buttonPrimary, "h-11 w-full rounded-3xl")}>
                Get Started
              </button>
            </motion.div>
          </motion.nav>
        </motion.div>
      )}

      <main className="flex-1">
        {/* Hero Section */}
        <section className="w-full py-12 md:py-24 lg:py-32 xl:py-48 overflow-hidden">
          <div className="container mx-auto px-4 md:px-6">
            <div className="border border-slate-200 dark:border-zinc-800 rounded-3xl bg-gradient-to-br from-white dark:from-zinc-950 to-slate-100/50 dark:to-zinc-900/50 p-6 lg:p-10">
              <div className="grid gap-8 lg:grid-cols-[1fr_400px] lg:gap-12 xl:grid-cols-[1fr_600px] items-center">
                <motion.div
                  initial="hidden"
                  whileInView="visible"
                  viewport={{ once: true }}
                  variants={fadeIn}
                  className="flex flex-col justify-center space-y-6"
                >
                  <div className="space-y-4">
                    <motion.div
                      initial={{ opacity: 0, scale: 0.8 }}
                      whileInView={{ opacity: 1, scale: 1 }}
                      transition={{ duration: 0.5 }}
                      className="inline-flex items-center rounded-3xl bg-slate-100 dark:bg-zinc-900 px-3 py-1.5 text-sm font-medium"
                    >
                      <Zap className="mr-2 h-4 w-4 text-indigo-600 dark:text-indigo-400" />
                      Creative Design Studio
                    </motion.div>
                    <motion.h1
                      initial={{ opacity: 0, y: 20 }}
                      whileInView={{ opacity: 1, y: 0 }}
                      transition={{ duration: 0.7, delay: 0.2 }}
                      className="text-4xl font-extrabold tracking-tighter sm:text-5xl xl:text-6xl/none leading-tight"
                    >
                      We design digital experiences that people{" "}
                      <span className="bg-gradient-to-r from-indigo-600 to-purple-500 dark:from-indigo-400 dark:to-purple-400 bg-clip-text text-transparent">
                        love
                      </span>
                    </motion.h1>
                    <motion.p
                      initial={{ opacity: 0, y: 20 }}
                      whileInView={{ opacity: 1, y: 0 }}
                      transition={{ duration: 0.7, delay: 0.4 }}
                      className="max-w-[600px] text-slate-500 dark:text-slate-400 md:text-xl leading-relaxed"
                    >
                      Our award-winning team crafts beautiful, functional designs that drive growth and engagement.
                    </motion.p>
                  </div>
                  <motion.div
                    initial={{ opacity: 0, y: 20 }}
                    whileInView={{ opacity: 1, y: 0 }}
                    transition={{ duration: 0.7, delay: 0.6 }}
                    className="flex flex-col gap-3 sm:flex-row"
                  >
                    <button className={cn(buttonPrimary, "h-12 px-8 text-base rounded-3xl group")}>
                      Get Started
                      <motion.span
                        initial={{ x: 0 }}
                        whileHover={{ x: 5 }}
                        transition={{ type: "spring", stiffness: 400, damping: 10 }}
                      >
                        <ArrowRight className="ml-2 h-4 w-4 transition-transform group-hover:translate-x-1" />
                      </motion.span>
                    </button>
                    <button className={cn(buttonOutline, "h-12 px-8 text-base rounded-3xl")}>
                      View Our Work
                    </button>
                  </motion.div>
                </motion.div>
                <motion.div
                  initial={{ opacity: 0, x: 100 }}
                  whileInView={{ opacity: 1, x: 0 }}
                  transition={{ duration: 0.8 }}
                  className="flex items-center justify-center w-full"
                >
                  <div className="relative h-[350px] w-full md:h-[450px] lg:h-[500px] xl:h-[550px] overflow-hidden rounded-3xl shadow-xl">
                    <img
                      src="https://raw.githubusercontent.com/designali-in/designali/2a5d38f658ab24084e3260cdba2259fdc44ae2cd/apps/www/public/placeholder.svg"
                      alt="Hero Image"
                      className="absolute inset-0 w-full h-full object-cover"
                    />
                  </div>
                </motion.div>
              </div>
            </div>
          </div>
        </section>

        {/* Client Logos */}
        <section id="clients" className="w-full py-12 md:py-16 lg:py-20">
          <div className="container mx-auto px-4 md:px-6">
            <motion.div
              initial="hidden"
              whileInView="visible"
              viewport={{ once: true }}
              variants={fadeIn}
              className="border border-slate-200 dark:border-zinc-800 rounded-3xl bg-slate-50/50 dark:bg-zinc-900/20 p-8 lg:p-12"
            >
              <div className="flex flex-col items-center justify-center space-y-4 text-center pb-8">
                <div className="space-y-3">
                  <motion.div
                    initial={{ opacity: 0, scale: 0.8 }}
                    whileInView={{ opacity: 1, scale: 1 }}
                    transition={{ duration: 0.5 }}
                    className="inline-block rounded-3xl bg-slate-200 dark:bg-zinc-800 px-3 py-1 text-sm font-medium"
                  >
                    Trusted by
                  </motion.div>
                  <motion.h2
                    initial={{ opacity: 0, y: 20 }}
                    whileInView={{ opacity: 1, y: 0 }}
                    transition={{ duration: 0.5, delay: 0.2 }}
                    className="text-3xl font-bold tracking-tighter sm:text-4xl md:text-5xl"
                  >
                    Our Clients
                  </motion.h2>
                  <motion.p
                    initial={{ opacity: 0, y: 20 }}
                    whileInView={{ opacity: 1, y: 0 }}
                    transition={{ duration: 0.5, delay: 0.3 }}
                    className="mx-auto max-w-[700px] text-slate-500 dark:text-slate-400 md:text-lg lg:text-xl/relaxed"
                  >
                    We've had the pleasure of working with some amazing companies
                  </motion.p>
                </div>
              </div>
              <motion.div
                variants={staggerContainer}
                initial="hidden"
                whileInView="visible"
                viewport={{ once: true }}
                className="mx-auto grid grid-cols-2 items-center gap-6 md:grid-cols-3 lg:grid-cols-6"
              >
                {[...Array(6)].map((_, i) => (
                  <motion.div
                    key={i}
                    variants={itemFadeIn}
                    whileHover={{ scale: 1.05 }}
                    className="flex items-center justify-center"
                  >
                    <div className="rounded-2xl border border-slate-200 dark:border-zinc-800 p-6 bg-white/80 dark:bg-zinc-950/80 hover:shadow-md transition-all w-full flex justify-center">
                      <img
                        src={`https://raw.githubusercontent.com/designali-in/designali/2a5d38f658ab24084e3260cdba2259fdc44ae2cd/apps/www/public/placeholder.svg?height=80&width=160`}
                        alt={`Client Logo ${i + 1}`}
                        className="w-[120px] h-[60px] object-contain grayscale transition-all duration-300 hover:grayscale-0 dark:invert"
                      />
                    </div>
                  </motion.div>
                ))}
              </motion.div>
            </motion.div>
          </div>
        </section>

        {/* Services Section */}
        <section id="services" className="w-full py-12 md:py-24 lg:py-32">
          <div className="container mx-auto px-4 md:px-6">
            <motion.div
              initial="hidden"
              whileInView="visible"
              viewport={{ once: true }}
              variants={fadeIn}
              className="border border-slate-200 dark:border-zinc-800 rounded-3xl p-8 lg:p-12"
            >
              <div className="flex flex-col items-center justify-center space-y-4 text-center pb-10">
                <div className="space-y-3">
                  <motion.div
                    initial={{ opacity: 0, scale: 0.8 }}
                    whileInView={{ opacity: 1, scale: 1 }}
                    transition={{ duration: 0.5 }}
                    className="inline-block rounded-3xl bg-slate-100 dark:bg-zinc-900 px-3 py-1 text-sm font-medium"
                  >
                    Services
                  </motion.div>
                  <motion.h2
                    initial={{ opacity: 0, y: 20 }}
                    whileInView={{ opacity: 1, y: 0 }}
                    transition={{ duration: 0.5, delay: 0.2 }}
                    className="text-3xl font-bold tracking-tighter sm:text-4xl md:text-5xl"
                  >
                    What We Do
                  </motion.h2>
                  <motion.p
                    initial={{ opacity: 0, y: 20 }}
                    whileInView={{ opacity: 1, y: 0 }}
                    transition={{ duration: 0.5, delay: 0.3 }}
                    className="mx-auto max-w-[900px] text-slate-500 dark:text-slate-400 md:text-lg lg:text-xl/relaxed"
                  >
                    We offer a comprehensive range of design and development services to help your business thrive
                  </motion.p>
                </div>
              </div>
              <motion.div
                variants={staggerContainer}
                initial="hidden"
                whileInView="visible"
                viewport={{ once: true }}
                className="mx-auto grid max-w-6xl items-center gap-6 md:grid-cols-2 lg:grid-cols-3"
              >
                {[
                  {
                    icon: <Palette className="h-8 w-8 text-indigo-600 dark:text-indigo-400" />,
                    title: "UI/UX Design",
                    description: "We create intuitive, engaging user experiences that delight your customers and drive conversions.",
                  },
                  {
                    icon: <Code className="h-8 w-8 text-indigo-600 dark:text-indigo-400" />,
                    title: "Web Development",
                    description: "Our developers build fast, responsive, and accessible websites that work across all devices.",
                  },
                  {
                    icon: <Sparkles className="h-8 w-8 text-indigo-600 dark:text-indigo-400" />,
                    title: "Brand Identity",
                    description: "We craft distinctive brand identities that communicate your values and resonate with your audience.",
                  },
                  {
                    icon: <Zap className="h-8 w-8 text-indigo-600 dark:text-indigo-400" />,
                    title: "Mobile Apps",
                    description: "We design and develop native and cross-platform mobile applications that users love.",
                  },
                  {
                    icon: <LineChart className="h-8 w-8 text-indigo-600 dark:text-indigo-400" />,
                    title: "Digital Marketing",
                    description: "We help you reach your target audience and grow your business with data-driven marketing strategies.",
                  },
                  {
                    icon: <MessageSquare className="h-8 w-8 text-indigo-600 dark:text-indigo-400" />,
                    title: "Content Creation",
                    description: "We produce engaging content that tells your story and connects with your customers.",
                  },
                ].map((service, index) => (
                  <motion.div
                    key={index}
                    variants={itemFadeIn}
                    whileHover={{ y: -10, transition: { duration: 0.3 } }}
                    className="group relative overflow-hidden rounded-3xl border border-slate-200 dark:border-zinc-800 p-8 shadow-sm transition-all hover:shadow-lg bg-white/80 dark:bg-zinc-950/80"
                  >
                    <div className="absolute -right-20 -top-20 h-40 w-40 rounded-full bg-indigo-600/10 dark:bg-indigo-500/10 group-hover:bg-indigo-600/20 transition-all duration-500"></div>
                    <div className="relative space-y-4">
                      <div className="mb-4 bg-slate-100 dark:bg-zinc-900 w-16 h-16 rounded-2xl flex items-center justify-center">{service.icon}</div>
                      <h3 className="text-xl font-bold">{service.title}</h3>
                      <p className="text-slate-500 dark:text-slate-400 leading-relaxed">{service.description}</p>
                    </div>
                    <div className="mt-8 flex items-center justify-between">
                      <a href="#" className="text-sm font-semibold text-indigo-600 dark:text-indigo-400 underline-offset-4 hover:underline">
                        Learn more
                      </a>
                      <motion.div whileHover={{ x: 5 }} transition={{ type: "spring", stiffness: 400, damping: 10 }}>
                        <ArrowRight className="h-5 w-5 text-indigo-600 dark:text-indigo-400" />
                      </motion.div>
                    </div>
                  </motion.div>
                ))}
              </motion.div>
            </motion.div>
          </div>
        </section>

        {/* Portfolio/Work Bento Grid */}
        <section id="work" className="w-full py-12 md:py-24 lg:py-32">
          <div className="container mx-auto px-4 md:px-6">
            <motion.div
              initial="hidden"
              whileInView="visible"
              viewport={{ once: true }}
              variants={fadeIn}
              className="border border-slate-200 dark:border-zinc-800 rounded-3xl bg-slate-100/50 dark:bg-zinc-900/30 p-8 lg:p-12"
            >
              <div className="flex flex-col items-center justify-center space-y-4 text-center pb-10">
                <div className="space-y-3">
                  <motion.div
                    initial={{ opacity: 0, scale: 0.8 }}
                    whileInView={{ opacity: 1, scale: 1 }}
                    transition={{ duration: 0.5 }}
                    className="inline-block rounded-3xl bg-slate-200 dark:bg-zinc-800 px-3 py-1 text-sm font-medium"
                  >
                    Portfolio
                  </motion.div>
                  <motion.h2
                    initial={{ opacity: 0, y: 20 }}
                    whileInView={{ opacity: 1, y: 0 }}
                    transition={{ duration: 0.5, delay: 0.2 }}
                    className="text-3xl font-bold tracking-tighter sm:text-4xl md:text-5xl"
                  >
                    Our Work
                  </motion.h2>
                  <motion.p
                    initial={{ opacity: 0, y: 20 }}
                    whileInView={{ opacity: 1, y: 0 }}
                    transition={{ duration: 0.5, delay: 0.3 }}
                    className="mx-auto max-w-[900px] text-slate-500 dark:text-slate-400 md:text-lg lg:text-xl/relaxed"
                  >
                    A showcase of our recent projects and collaborations
                  </motion.p>
                </div>
              </div>
              <motion.div
                variants={staggerContainer}
                initial="hidden"
                whileInView="visible"
                viewport={{ once: true }}
                className="mx-auto grid max-w-7xl gap-4 md:grid-cols-4 md:grid-rows-2"
              >
                {/* Bento Grid Items */}
                <motion.div
                  variants={itemFadeIn}
                  whileHover={{ scale: 1.02 }}
                  transition={{ duration: 0.3 }}
                  className="group relative overflow-hidden rounded-3xl md:col-span-2 md:row-span-2 h-[400px] md:h-auto min-h-[400px]"
                >
                  <div className="absolute inset-0 bg-gradient-to-t from-black/80 via-black/20 to-transparent opacity-60 transition-opacity duration-300 group-hover:opacity-80 z-10"></div>
                  <img
                    src="https://raw.githubusercontent.com/designali-in/designali/2a5d38f658ab24084e3260cdba2259fdc44ae2cd/apps/www/public/placeholder.svg?height=800&width=1200"
                    alt="Portfolio Item 1"
                    className="absolute inset-0 w-full h-full object-cover transition-transform duration-700 group-hover:scale-110"
                  />
                  <div className="absolute inset-0 z-20 flex flex-col justify-end p-8 text-white opacity-90 transition-opacity duration-300 group-hover:opacity-100">
                    <h3 className="text-2xl font-bold mb-2 tracking-tight">E-commerce Redesign</h3>
                    <p className="text-sm text-slate-200 max-w-sm">A complete overhaul of an online retail platform improving conversions by 40%.</p>
                    <motion.div
                      initial={{ opacity: 0, y: 20 }}
                      whileInView={{ opacity: 1, y: 0 }}
                      transition={{ delay: 0.2 }}
                      className="mt-6"
                    >
                      <button className="inline-flex items-center justify-center font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500 rounded-3xl bg-white/20 backdrop-blur-md border border-white/40 text-white hover:bg-white/30 h-10 px-6 text-sm">
                        View Project <ArrowUpRight className="ml-2 h-4 w-4" />
                      </button>
                    </motion.div>
                  </div>
                </motion.div>
                
                <motion.div
                  variants={itemFadeIn}
                  whileHover={{ scale: 1.02 }}
                  transition={{ duration: 0.3 }}
                  className="group relative overflow-hidden rounded-3xl h-[250px]"
                >
                  <div className="absolute inset-0 bg-gradient-to-t from-black/80 to-transparent opacity-60 transition-opacity group-hover:opacity-90 z-10"></div>
                  <img
                    src="https://raw.githubusercontent.com/designali-in/designali/2a5d38f658ab24084e3260cdba2259fdc44ae2cd/apps/www/public/placeholder.svg?height=600&width=600"
                    alt="Portfolio Item 2"
                    className="absolute inset-0 w-full h-full object-cover transition-transform duration-700 group-hover:scale-110"
                  />
                  <div className="absolute inset-0 z-20 flex flex-col justify-end p-6 text-white translate-y-4 group-hover:translate-y-0 transition-transform duration-300">
                    <h3 className="text-xl font-bold mb-1">Mobile App Design</h3>
                    <p className="text-sm text-slate-300 opacity-0 group-hover:opacity-100 transition-opacity duration-300">UI/UX for a fitness tracking application</p>
                  </div>
                </motion.div>
                
                <motion.div
                  variants={itemFadeIn}
                  whileHover={{ scale: 1.02 }}
                  transition={{ duration: 0.3 }}
                  className="group relative overflow-hidden rounded-3xl h-[250px]"
                >
                  <div className="absolute inset-0 bg-gradient-to-t from-black/80 to-transparent opacity-60 transition-opacity group-hover:opacity-90 z-10"></div>
                  <img
                    src="https://raw.githubusercontent.com/designali-in/designali/2a5d38f658ab24084e3260cdba2259fdc44ae2cd/apps/www/public/placeholder.svg?height=600&width=600"
                    alt="Portfolio Item 3"
                    className="absolute inset-0 w-full h-full object-cover transition-transform duration-700 group-hover:scale-110"
                  />
                  <div className="absolute inset-0 z-20 flex flex-col justify-end p-6 text-white translate-y-4 group-hover:translate-y-0 transition-transform duration-300">
                    <h3 className="text-xl font-bold mb-1">Brand Identity</h3>
                    <p className="text-sm text-slate-300 opacity-0 group-hover:opacity-100 transition-opacity duration-300">Complete rebrand for a tech startup</p>
                  </div>
                </motion.div>
                
                <motion.div
                  variants={itemFadeIn}
                  whileHover={{ scale: 1.02 }}
                  transition={{ duration: 0.3 }}
                  className="group relative overflow-hidden rounded-3xl h-[250px]"
                >
                  <div className="absolute inset-0 bg-gradient-to-t from-black/80 to-transparent opacity-60 transition-opacity group-hover:opacity-90 z-10"></div>
                  <img
                    src="https://raw.githubusercontent.com/designali-in/designali/2a5d38f658ab24084e3260cdba2259fdc44ae2cd/apps/www/public/placeholder.svg?height=600&width=600"
                    alt="Portfolio Item 4"
                    className="absolute inset-0 w-full h-full object-cover transition-transform duration-700 group-hover:scale-110"
                  />
                  <div className="absolute inset-0 z-20 flex flex-col justify-end p-6 text-white translate-y-4 group-hover:translate-y-0 transition-transform duration-300">
                    <h3 className="text-xl font-bold mb-1">Web Application</h3>
                    <p className="text-sm text-slate-300 opacity-0 group-hover:opacity-100 transition-opacity duration-300">Dashboard design for a SaaS platform</p>
                  </div>
                </motion.div>
                
                <motion.div
                  variants={itemFadeIn}
                  whileHover={{ scale: 1.02 }}
                  transition={{ duration: 0.3 }}
                  className="group relative overflow-hidden rounded-3xl md:col-span-2 h-[250px]"
                >
                  <div className="absolute inset-0 bg-gradient-to-t from-black/80 to-transparent opacity-60 transition-opacity group-hover:opacity-90 z-10"></div>
                  <img
                    src="https://raw.githubusercontent.com/designali-in/designali/2a5d38f658ab24084e3260cdba2259fdc44ae2cd/apps/www/public/placeholder.svg?height=600&width=1200"
                    alt="Portfolio Item 5"
                    className="absolute inset-0 w-full h-full object-cover transition-transform duration-700 group-hover:scale-110"
                  />
                  <div className="absolute inset-0 z-20 flex flex-col justify-end p-6 text-white translate-y-4 group-hover:translate-y-0 transition-transform duration-300">
                    <h3 className="text-xl font-bold mb-1">Marketing Campaign</h3>
                    <p className="text-sm text-slate-300 opacity-0 group-hover:opacity-100 transition-opacity duration-300">Integrated digital campaign for product launch</p>
                  </div>
                </motion.div>
              </motion.div>
              
              <div className="flex justify-center pt-8">
                <motion.div whileHover={{ scale: 1.05 }} whileTap={{ scale: 0.95 }}>
                  <button className={cn(buttonPrimary, "h-12 px-8 text-base rounded-3xl group")}>
                    View All Projects
                    <motion.span
                      initial={{ x: 0 }}
                      whileHover={{ x: 5 }}
                      transition={{ type: "spring", stiffness: 400, damping: 10 }}
                    >
                      <ArrowRight className="ml-2 h-4 w-4 transition-transform group-hover:translate-x-1" />
                    </motion.span>
                  </button>
                </motion.div>
              </div>
            </motion.div>
          </div>
        </section>

        {/* About/Team Section */}
        <section id="about" className="w-full py-12 md:py-24 lg:py-32">
          <div className="container mx-auto px-4 md:px-6">
            <motion.div
              initial="hidden"
              whileInView="visible"
              viewport={{ once: true }}
              variants={fadeIn}
              className="border border-slate-200 dark:border-zinc-800 rounded-3xl p-8 lg:p-12"
            >
              <div className="grid gap-12 lg:grid-cols-2 lg:gap-16 items-center">
                <motion.div
                  initial={{ opacity: 0, x: -50 }}
                  whileInView={{ opacity: 1, x: 0 }}
                  transition={{ duration: 0.6 }}
                  className="space-y-6"
                >
                  <div className="inline-block rounded-3xl bg-slate-100 dark:bg-zinc-900 px-3 py-1 text-sm font-medium">About Us</div>
                  <h2 className="text-3xl font-bold tracking-tighter sm:text-4xl md:text-5xl leading-tight">Our Story</h2>
                  <p className="text-slate-500 dark:text-slate-400 md:text-lg leading-relaxed">
                    Founded in 2015, our design studio has grown from a small team of passionate designers to a
                    full-service creative agency. We believe in the power of design to transform businesses and create
                    meaningful connections with audiences.
                  </p>
                  <p className="text-slate-500 dark:text-slate-400 md:text-lg leading-relaxed">
                    Our approach combines strategic thinking, creative excellence, and technical expertise to deliver
                    solutions that not only look beautiful but also drive results.
                  </p>
                  <div className="flex flex-col gap-3 sm:flex-row pt-4">
                    <button className={cn(buttonOutline, "h-12 px-8 text-base rounded-3xl")}>
                      Our Process
                    </button>
                    <button className={cn(buttonOutline, "h-12 px-8 text-base rounded-3xl")}>
                      Join Our Team
                    </button>
                  </div>
                </motion.div>
                <motion.div
                  initial={{ opacity: 0, x: 50 }}
                  whileInView={{ opacity: 1, x: 0 }}
                  transition={{ duration: 0.6 }}
                  className="flex items-center justify-center w-full"
                >
                  <div className="relative h-[400px] w-full md:h-[500px] overflow-hidden rounded-3xl shadow-xl">
                    <img
                      src="https://raw.githubusercontent.com/designali-in/designali/2a5d38f658ab24084e3260cdba2259fdc44ae2cd/apps/www/public/placeholder.svg"
                      alt="Team Photo"
                      className="absolute inset-0 w-full h-full object-cover"
                    />
                  </div>
                </motion.div>
              </div>
              
              <div className="mt-24 pt-10 border-t border-slate-200 dark:border-zinc-800">
                <motion.h3
                  initial={{ opacity: 0, y: 20 }}
                  whileInView={{ opacity: 1, y: 0 }}
                  transition={{ duration: 0.5 }}
                  className="text-2xl font-bold tracking-tighter sm:text-3xl mb-8"
                >
                  Meet Our Team
                </motion.h3>
                <motion.div
                  variants={staggerContainer}
                  initial="hidden"
                  whileInView="visible"
                  viewport={{ once: true }}
                  className="grid gap-6 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4"
                >
                  {[
                    { name: "Alex Johnson", role: "Creative Director" },
                    { name: "Sam Taylor", role: "Lead Designer" },
                    { name: "Jordan Smith", role: "Senior Developer" },
                    { name: "Casey Brown", role: "Project Manager" },
                  ].map((member, index) => (
                    <motion.div
                      key={index}
                      variants={itemFadeIn}
                      whileHover={{ y: -10 }}
                      className="group relative overflow-hidden rounded-3xl shadow-sm border border-slate-200 dark:border-zinc-800"
                    >
                      <img
                        src="https://raw.githubusercontent.com/designali-in/designali/2a5d38f658ab24084e3260cdba2259fdc44ae2cd/apps/www/public/placeholder.svg"
                        alt={member.name}
                        className="h-[350px] w-full object-cover transition-transform duration-500 group-hover:scale-110"
                      />
                      <div className="absolute inset-0 flex flex-col justify-end bg-gradient-to-t from-black/80 via-black/20 to-transparent p-6 text-white opacity-90 transition-opacity group-hover:opacity-100">
                        <h4 className="font-bold text-xl">{member.name}</h4>
                        <p className="text-sm text-slate-300 font-medium mt-1">{member.role}</p>
                      </div>
                    </motion.div>
                  ))}
                </motion.div>
              </div>
            </motion.div>
          </div>
        </section>

        {/* Testimonials */}
        <section className="w-full py-12 md:py-24 lg:py-32">
          <div className="container mx-auto px-4 md:px-6">
            <motion.div
              initial="hidden"
              whileInView="visible"
              viewport={{ once: true }}
              variants={fadeIn}
              className="border border-slate-200 dark:border-zinc-800 rounded-3xl bg-slate-50 dark:bg-zinc-900/30 p-8 lg:p-12"
            >
              <div className="flex flex-col items-center justify-center space-y-4 text-center pb-10">
                <div className="space-y-3">
                  <motion.div
                    initial={{ opacity: 0, scale: 0.8 }}
                    whileInView={{ opacity: 1, scale: 1 }}
                    transition={{ duration: 0.5 }}
                    className="inline-block rounded-3xl bg-white dark:bg-zinc-950 border border-slate-200 dark:border-zinc-800 px-4 py-1.5 text-sm font-medium shadow-sm"
                  >
                    Testimonials
                  </motion.div>
                  <motion.h2
                    initial={{ opacity: 0, y: 20 }}
                    whileInView={{ opacity: 1, y: 0 }}
                    transition={{ duration: 0.5, delay: 0.2 }}
                    className="text-3xl font-bold tracking-tighter sm:text-4xl md:text-5xl"
                  >
                    What Our Clients Say
                  </motion.h2>
                  <motion.p
                    initial={{ opacity: 0, y: 20 }}
                    whileInView={{ opacity: 1, y: 0 }}
                    transition={{ duration: 0.5, delay: 0.3 }}
                    className="mx-auto max-w-[900px] text-slate-500 dark:text-slate-400 md:text-lg lg:text-xl/relaxed"
                  >
                    Don't just take our word for it - hear from some of our satisfied clients
                  </motion.p>
                </div>
              </div>
              <motion.div
                variants={staggerContainer}
                initial="hidden"
                whileInView="visible"
                viewport={{ once: true }}
                className="mx-auto grid max-w-6xl gap-6 md:grid-cols-2"
              >
                {[
                  {
                    quote:
                      "Working with this team transformed our brand. They understood our vision perfectly and delivered beyond our expectations.",
                    author: "Sarah Johnson",
                    company: "CEO, TechStart",
                  },
                  {
                    quote:
                      "The attention to detail and creative solutions provided by the team helped us increase our conversion rate by 40%.",
                    author: "Michael Chen",
                    company: "Marketing Director, GrowthCo",
                  },
                  {
                    quote:
                      "Their strategic approach to design not only improved our user experience but also strengthened our brand identity.",
                    author: "Emma Rodriguez",
                    company: "Product Manager, InnovateLabs",
                  },
                  {
                    quote:
                      "From concept to execution, the team demonstrated exceptional skill and professionalism. Highly recommended!",
                    author: "David Kim",
                    company: "Founder, NextWave",
                  },
                ].map((testimonial, index) => (
                  <motion.div
                    key={index}
                    variants={itemFadeIn}
                    whileHover={{ y: -5 }}
                    className="flex flex-col justify-between rounded-3xl border border-slate-200 dark:border-zinc-800 bg-white dark:bg-zinc-950 p-8 shadow-sm transition-all hover:shadow-md"
                  >
                    <div>
                      <div className="flex gap-1 text-yellow-400">
                        {[...Array(5)].map((_, i) => (
                          <svg
                            key={i}
                            xmlns="http://www.w3.org/2000/svg"
                            width="24"
                            height="24"
                            viewBox="0 0 24 24"
                            fill="currentColor"
                            className="h-5 w-5"
                          >
                            <path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z" />
                          </svg>
                        ))}
                      </div>
                      <blockquote className="mt-6 text-lg font-medium leading-relaxed text-slate-700 dark:text-slate-300">"{testimonial.quote}"</blockquote>
                    </div>
                    <div className="mt-8 flex items-center">
                      <div className="h-12 w-12 rounded-full bg-slate-200 dark:bg-zinc-800"></div>
                      <div className="ml-4">
                        <p className="font-bold text-slate-900 dark:text-white">{testimonial.author}</p>
                        <p className="text-sm font-medium text-slate-500 dark:text-slate-400">{testimonial.company}</p>
                      </div>
                    </div>
                  </motion.div>
                ))}
              </motion.div>
            </motion.div>
          </div>
        </section>

        {/* Contact Section */}
        <section id="contact" className="w-full py-12 md:py-24 lg:py-32">
          <div className="container mx-auto px-4 md:px-6">
            <motion.div
              initial="hidden"
              whileInView="visible"
              viewport={{ once: true }}
              variants={fadeIn}
              className="grid items-center gap-8 lg:grid-cols-2 border border-slate-200 dark:border-zinc-800 rounded-3xl p-6 lg:p-12 overflow-hidden bg-white dark:bg-zinc-950"
            >
              <motion.div
                initial={{ opacity: 0, x: -50 }}
                whileInView={{ opacity: 1, x: 0 }}
                transition={{ duration: 0.6 }}
                className="space-y-6"
              >
                <div className="inline-block rounded-3xl bg-slate-100 dark:bg-zinc-900 px-3 py-1 text-sm font-medium">Contact</div>
                <h2 className="text-4xl font-extrabold tracking-tighter md:text-5xl/tight">Let's Work Together</h2>
                <p className="max-w-[600px] text-slate-500 dark:text-slate-400 md:text-lg leading-relaxed">
                  Ready to start your next project? Get in touch with us to discuss how we can help bring your vision to
                  life.
                </p>
                <div className="mt-10 space-y-6">
                  <motion.div whileHover={{ x: 5 }} className="flex items-start gap-4">
                    <div className="rounded-2xl bg-indigo-50 dark:bg-indigo-500/10 p-3">
                      <MapPin className="h-6 w-6 text-indigo-600 dark:text-indigo-400" />
                    </div>
                    <div>
                      <h3 className="font-bold text-lg">Our Location</h3>
                      <p className="text-slate-500 dark:text-slate-400 mt-1">123 Design Street, Creative City, 10001</p>
                    </div>
                  </motion.div>
                  <motion.div whileHover={{ x: 5 }} className="flex items-start gap-4">
                    <div className="rounded-2xl bg-indigo-50 dark:bg-indigo-500/10 p-3">
                      <Mail className="h-6 w-6 text-indigo-600 dark:text-indigo-400" />
                    </div>
                    <div>
                      <h3 className="font-bold text-lg">Email Us</h3>
                      <p className="text-slate-500 dark:text-slate-400 mt-1">hello@designstudio.com</p>
                    </div>
                  </motion.div>
                  <motion.div whileHover={{ x: 5 }} className="flex items-start gap-4">
                    <div className="rounded-2xl bg-indigo-50 dark:bg-indigo-500/10 p-3">
                      <Phone className="h-6 w-6 text-indigo-600 dark:text-indigo-400" />
                    </div>
                    <div>
                      <h3 className="font-bold text-lg">Call Us</h3>
                      <p className="text-slate-500 dark:text-slate-400 mt-1">+1 (555) 123-4567</p>
                    </div>
                  </motion.div>
                </div>
                <div className="mt-10 flex space-x-4">
                  {[
                    { icon: <Instagram className="h-5 w-5" />, label: "Instagram" },
                    { icon: <Twitter className="h-5 w-5" />, label: "Twitter" },
                    { icon: <Linkedin className="h-5 w-5" />, label: "LinkedIn" },
                    { icon: <Facebook className="h-5 w-5" />, label: "Facebook" },
                  ].map((social, index) => (
                    <motion.div key={index} whileHover={{ y: -5, scale: 1.1 }} whileTap={{ scale: 0.9 }}>
                      <a
                        href="#"
                        className="flex h-12 w-12 items-center justify-center rounded-full border border-slate-200 dark:border-zinc-800 text-slate-500 dark:text-slate-400 hover:text-indigo-600 dark:hover:text-indigo-400 hover:border-indigo-600 dark:hover:border-indigo-400 hover:bg-indigo-50 dark:hover:bg-indigo-500/10 transition-all"
                      >
                        {social.icon}
                        <span className="sr-only">{social.label}</span>
                      </a>
                    </motion.div>
                  ))}
                </div>
              </motion.div>
              <motion.div
                initial={{ opacity: 0, x: 50 }}
                whileInView={{ opacity: 1, x: 0 }}
                transition={{ duration: 0.6 }}
                className="rounded-3xl border border-slate-200 dark:border-zinc-800 bg-slate-50 dark:bg-zinc-900/50 p-8 shadow-sm"
              >
                <h3 className="text-2xl font-bold">Send Us a Message</h3>
                <p className="text-slate-500 dark:text-slate-400 mt-2 mb-8">
                  Fill out the form below and we'll get back to you shortly.
                </p>
                <form className="space-y-5" onSubmit={(e) => e.preventDefault()}>
                  <div className="grid gap-5 sm:grid-cols-2">
                    <div className="space-y-2">
                      <label
                        htmlFor="first-name"
                        className="text-sm font-semibold leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
                      >
                        First name
                      </label>
                      <input id="first-name" placeholder="Enter your first name" className={cn(inputBase, "rounded-xl h-11 bg-white dark:bg-zinc-950")} />
                    </div>
                    <div className="space-y-2">
                      <label
                        htmlFor="last-name"
                        className="text-sm font-semibold leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
                      >
                        Last name
                      </label>
                      <input id="last-name" placeholder="Enter your last name" className={cn(inputBase, "rounded-xl h-11 bg-white dark:bg-zinc-950")} />
                    </div>
                  </div>
                  <div className="space-y-2">
                    <label
                      htmlFor="email"
                      className="text-sm font-semibold leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
                    >
                      Email
                    </label>
                    <input id="email" type="email" placeholder="Enter your email" className={cn(inputBase, "rounded-xl h-11 bg-white dark:bg-zinc-950")} />
                  </div>
                  <div className="space-y-2">
                    <label
                      htmlFor="message"
                      className="text-sm font-semibold leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
                    >
                      Message
                    </label>
                    <textarea id="message" placeholder="Enter your message" className={cn(inputBase, "min-h-[140px] rounded-xl bg-white dark:bg-zinc-950 resize-y")} />
                  </div>
                  <motion.div whileHover={{ scale: 1.02 }} whileTap={{ scale: 0.98 }} className="pt-2">
                    <button type="submit" className={cn(buttonPrimary, "w-full rounded-xl h-12 text-base")}>
                      Send Message
                    </button>
                  </motion.div>
                </form>
              </motion.div>
            </motion.div>
          </div>
        </section>
      </main>

      {/* Footer */}
      <footer className="w-full border-t border-slate-200 dark:border-zinc-800 bg-white dark:bg-zinc-950">
        <motion.div
          initial="hidden"
          whileInView="visible"
          viewport={{ once: true }}
          variants={fadeIn}
          className="container mx-auto grid gap-10 px-4 py-16 md:px-6 lg:grid-cols-4 lg:gap-8"
        >
          <div className="space-y-6 pr-4">
            <a href="/" className="flex items-center space-x-3">
              <motion.div
                whileHover={{ rotate: 5, scale: 1.1 }}
                transition={{ type: "spring", stiffness: 400, damping: 10 }}
                className="h-10 w-10 rounded-3xl bg-indigo-600 dark:bg-indigo-500 flex items-center justify-center"
              >
                <Sparkles className="h-5 w-5 text-white" />
              </motion.div>
              <span className="font-bold text-xl">Studio</span>
            </a>
            <p className="text-sm text-slate-500 dark:text-slate-400 leading-relaxed">
              We create beautiful, functional designs that help businesses grow and connect with their audience.
            </p>
            <div className="flex space-x-4">
              {[
                { icon: <Instagram className="h-5 w-5" />, label: "Instagram" },
                { icon: <Twitter className="h-5 w-5" />, label: "Twitter" },
                { icon: <Linkedin className="h-5 w-5" />, label: "LinkedIn" },
                { icon: <Github className="h-5 w-5" />, label: "GitHub" },
              ].map((social, index) => (
                <motion.div key={index} whileHover={{ y: -5, scale: 1.1 }} whileTap={{ scale: 0.9 }}>
                  <a href="#" className="text-slate-400 hover:text-indigo-600 dark:hover:text-indigo-400 transition-colors">
                    {social.icon}
                    <span className="sr-only">{social.label}</span>
                  </a>
                </motion.div>
              ))}
            </div>
          </div>
          <div className="grid grid-cols-1 gap-8 sm:grid-cols-2 lg:grid-cols-1">
            <div>
              <h3 className="text-lg font-bold">Company</h3>
              <nav className="mt-6 flex flex-col space-y-3 text-sm">
                <a href="#about" className="text-slate-500 dark:text-slate-400 hover:text-indigo-600 dark:hover:text-indigo-400 transition-colors font-medium">
                  About Us
                </a>
                <a href="#" className="text-slate-500 dark:text-slate-400 hover:text-indigo-600 dark:hover:text-indigo-400 transition-colors font-medium">
                  Careers
                </a>
                <a href="#" className="text-slate-500 dark:text-slate-400 hover:text-indigo-600 dark:hover:text-indigo-400 transition-colors font-medium">
                  Our Process
                </a>
                <a href="#" className="text-slate-500 dark:text-slate-400 hover:text-indigo-600 dark:hover:text-indigo-400 transition-colors font-medium">
                  News & Press
                </a>
              </nav>
            </div>
            <div>
              <h3 className="text-lg font-bold">Services</h3>
              <nav className="mt-6 flex flex-col space-y-3 text-sm">
                <a href="#" className="text-slate-500 dark:text-slate-400 hover:text-indigo-600 dark:hover:text-indigo-400 transition-colors font-medium">
                  UI/UX Design
                </a>
                <a href="#" className="text-slate-500 dark:text-slate-400 hover:text-indigo-600 dark:hover:text-indigo-400 transition-colors font-medium">
                  Web Development
                </a>
                <a href="#" className="text-slate-500 dark:text-slate-400 hover:text-indigo-600 dark:hover:text-indigo-400 transition-colors font-medium">
                  Brand Identity
                </a>
                <a href="#" className="text-slate-500 dark:text-slate-400 hover:text-indigo-600 dark:hover:text-indigo-400 transition-colors font-medium">
                  Digital Marketing
                </a>
              </nav>
            </div>
          </div>
          <div className="grid grid-cols-1 gap-8 sm:grid-cols-2 lg:grid-cols-1">
            <div>
              <h3 className="text-lg font-bold">Resources</h3>
              <nav className="mt-6 flex flex-col space-y-3 text-sm">
                <a href="#" className="text-slate-500 dark:text-slate-400 hover:text-indigo-600 dark:hover:text-indigo-400 transition-colors font-medium">
                  Blog
                </a>
                <a href="#" className="text-slate-500 dark:text-slate-400 hover:text-indigo-600 dark:hover:text-indigo-400 transition-colors font-medium">
                  Case Studies
                </a>
                <a href="#" className="text-slate-500 dark:text-slate-400 hover:text-indigo-600 dark:hover:text-indigo-400 transition-colors font-medium">
                  Guides & Tutorials
                </a>
                <a href="#" className="text-slate-500 dark:text-slate-400 hover:text-indigo-600 dark:hover:text-indigo-400 transition-colors font-medium">
                  FAQ
                </a>
              </nav>
            </div>
            <div>
              <h3 className="text-lg font-bold">Legal</h3>
              <nav className="mt-6 flex flex-col space-y-3 text-sm">
                <a href="#" className="text-slate-500 dark:text-slate-400 hover:text-indigo-600 dark:hover:text-indigo-400 transition-colors font-medium">
                  Privacy Policy
                </a>
                <a href="#" className="text-slate-500 dark:text-slate-400 hover:text-indigo-600 dark:hover:text-indigo-400 transition-colors font-medium">
                  Terms of Service
                </a>
                <a href="#" className="text-slate-500 dark:text-slate-400 hover:text-indigo-600 dark:hover:text-indigo-400 transition-colors font-medium">
                  Cookie Policy
                </a>
              </nav>
            </div>
          </div>
          <div className="space-y-6">
            <h3 className="text-lg font-bold">Subscribe to our newsletter</h3>
            <p className="text-sm text-slate-500 dark:text-slate-400 leading-relaxed">
              Stay updated with our latest projects, design tips, and company news.
            </p>
            <form className="flex flex-col sm:flex-row gap-3" onSubmit={(e) => e.preventDefault()}>
              <input type="email" placeholder="Enter your email" className={cn(inputBase, "max-w-lg flex-1 rounded-full h-11 bg-slate-50 dark:bg-zinc-900")} />
              <button type="submit" className={cn(buttonPrimary, "rounded-full h-11 px-6")}>
                Subscribe
              </button>
            </form>
          </div>
        </motion.div>
        <div className="border-t border-slate-200 dark:border-zinc-800">
          <div className="container mx-auto flex flex-col items-center justify-between gap-4 py-8 md:h-20 md:flex-row md:py-0 px-4 md:px-6">
            <p className="text-sm text-slate-500 dark:text-slate-400 font-medium">
              &copy; {new Date().getFullYear()} Design Studio. All rights reserved.
            </p>
            <p className="text-sm text-slate-500 dark:text-slate-400 font-medium flex items-center gap-1.5">
              Crafted with <span className="text-rose-500">♥</span> in New York City
            </p>
          </div>
        </div>
      </footer>
    </div>
  )
}

--- FILE: frontend-web/registry/sections/FeaturedDemoGrid.tsx ---

import React, { useState } from "react";
import { PlayCircle } from "lucide-react";
import { cn } from "../core/utils";

export interface FeaturedDemoGridProps {
  title?: React.ReactNode;
  videoSrc?: string;
  thumbnailSrc?: string;
  features?: Array<{ title: string; subtitle: string }>;
  integrations?: Array<{ name: string; subtitle: string; domain: string }>;
  className?: string;
}

const DEFAULT_FEATURES = [
  {
    title: "Sales Pipeline Tracking",
    subtitle:
      "Easily monitor every lead from first contact to final closure with a simple, visual pipeline that keeps your entire sales process clear and on track.",
  },
  {
    title: "Automated Follow-ups",
    subtitle:
      "Use AI-powered reminders to send timely, personalized messages, helping you maintain momentum with leads and ensure no opportunity is ever lost.",
  },
  {
    title: "Custom Reports",
    subtitle:
      "Quickly generate tailored, data-rich reports to measure results, uncover new opportunities, and guide your business decisions with precision and clarity.",
  },
  {
    title: "Team Collaboration",
    subtitle:
      "Share updates instantly, assign tasks efficiently, and align your entire team’s efforts so you can close deals faster and deliver consistent results.",
  },
];

const DEFAULT_INTEGRATIONS = [
  { name: "Salesforce", subtitle: "Enterprise CRM platform", domain: "salesforce.com" },
  { name: "HubSpot CRM", subtitle: "Inbound marketing & sales", domain: "hubspot.com" },
  { name: "Zoho CRM", subtitle: "Affordable CRM solution", domain: "zoho.com" },
  { name: "Pipedrive", subtitle: "Sales pipeline management", domain: "pipedrive.com" },
  { name: "Freshsales", subtitle: "Freshworks sales CRM", domain: "freshworks.com" },
  { name: "Microsoft Dynamics", subtitle: "Microsoft business suite", domain: "dynamics.com" },
  { name: "Copper CRM", subtitle: "Google Workspace CRM", domain: "copper.com" },
  { name: "Insightly", subtitle: "Project & CRM management", domain: "insightly.com" },
];

export function FeaturedDemoGrid({
  title = (
    <>
      Empowering developers <br />
      with AI-driven solutions.
    </>
  ),
  videoSrc = "https://pub-940ccf6255b54fa799a9b01050e6c227.r2.dev/crm(1)(1)(1).mp4",
  thumbnailSrc = "https://pub-940ccf6255b54fa799a9b01050e6c227.r2.dev/crm-featured.png",
  features = DEFAULT_FEATURES,
  integrations = DEFAULT_INTEGRATIONS,
  className,
}: FeaturedDemoGridProps) {
  const [isPlaying, setIsPlaying] = useState(false);

  return (
    <div className={cn("max-w-7xl mx-auto bg-white text-black dark:bg-zinc-950 dark:text-white px-4 sm:px-6 lg:px-8", className)}>
      {/* Header */}
      <header className="text-left py-12">
        <h2 className="text-4xl md:text-5xl lg:text-6xl font-semibold tracking-tight">
          {title}
        </h2>
      </header>

      {/* Templates Grid */}
      <section className="grid grid-cols-1 lg:grid-cols-3 gap-4 h-full">
        {/* Main video/image card */}
        <div className="lg:col-span-2 rounded-2xl bg-zinc-200 dark:bg-zinc-900 p-2 overflow-hidden relative mb-4 lg:mb-0 flex flex-col min-h-[400px] lg:min-h-[500px] border border-zinc-200 dark:border-zinc-800 shadow-sm">
          <div className="p-0 relative flex-grow group rounded-xl overflow-hidden">
            {isPlaying ? (
              <video
                src={videoSrc}
                autoPlay
                muted
                loop
                playsInline
                className="w-full h-full object-cover rounded-xl"
              />
            ) : (
              <>
                <img
                  src={thumbnailSrc}
                  alt="Feature Thumbnail"
                  className="w-full h-full object-cover rounded-xl"
                />

                {/* Play button overlay */}
                <button
                  onClick={() => setIsPlaying(true)}
                  className="absolute inset-0 w-full h-full flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity bg-black/10 backdrop-blur-[2px]"
                >
                  <PlayCircle className="w-16 h-16 sm:w-20 sm:h-20 text-white drop-shadow-lg scale-95 group-hover:scale-100 transition-transform duration-300" />
                </button>
              </>
            )}
          </div>
        </div>

        {/* Feature cards */}
        <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-1 xl:grid-cols-2 gap-4 h-full">
          {features.map((feature, i) => (
            <div
              key={i}
              className="flex flex-col border border-zinc-200 dark:border-zinc-800 bg-zinc-50 dark:bg-zinc-900 rounded-2xl p-4 hover:shadow-md cursor-pointer transition-all duration-200 hover:-translate-y-1"
            >
              <div className="bg-zinc-200 dark:bg-zinc-800 flex-grow rounded-lg min-h-[100px] mb-4 overflow-hidden relative" />
              <div className="mt-auto">
                <h3 className="text-sm font-semibold text-zinc-900 dark:text-zinc-100 mb-1.5">
                  {feature.title}
                </h3>
                <p className="text-xs text-zinc-600 dark:text-zinc-400 leading-relaxed">
                  {feature.subtitle}
                </p>
              </div>
            </div>
          ))}
        </div>
      </section>

      {/* Integrations */}
      <section className="mt-12 grid grid-cols-1 sm:grid-cols-2 md:grid-cols-4 gap-2 text-sm border-t border-zinc-200 dark:border-zinc-800 pt-12">
        {integrations.map((integration) => (
          <div
            key={integration.name}
            className="p-3 flex items-center gap-4 hover:bg-zinc-50 dark:hover:bg-zinc-900 rounded-xl transition cursor-pointer border border-transparent hover:border-zinc-200 dark:hover:border-zinc-800"
          >
            <img
              src={`https://logo.clearbit.com/${integration.domain}`}
              alt={integration.name}
              className="w-10 h-10 object-contain rounded-xl bg-white p-1.5 shadow-sm border border-zinc-100 dark:border-zinc-800"
            />
            <div>
              <div className="font-medium text-zinc-900 dark:text-zinc-100">{integration.name}</div>
              <div className="text-xs text-zinc-500 dark:text-zinc-400 mt-0.5">{integration.subtitle}</div>
            </div>
          </div>
        ))}
      </section>

      {/* Footer */}
      <footer className="text-center py-12">
        <p className="text-sm text-zinc-500 dark:text-zinc-400 font-medium">Integrates seamlessly with your favorite tools</p>
      </footer>
    </div>
  );
}

--- FILE: frontend-web/registry/sections/LinkInBioSection.tsx ---

import React, { useRef, useState } from "react";
import { Github, Video, Youtube, Send } from "lucide-react";
import { cn } from "../core/utils";

export interface SocialLink {
  href: string;
  label: string;
  icon: React.ReactNode;
  bgClass: string;
  textClass: string;
}

export interface LinkInBioSectionProps {
  name?: string;
  avatarSrc?: string;
  headline?: string;
  bio?: string;
  aboutText?: React.ReactNode;
  socialLinks?: SocialLink[];
  contactTitle?: string;
  className?: string;
}

const DEFAULT_SOCIAL_LINKS: SocialLink[] = [
  {
    href: "#",
    label: "YouTube",
    icon: <Youtube size={24} />,
    bgClass: "bg-red-500",
    textClass: "text-white",
  },
  {
    href: "#",
    label: "GitHub",
    icon: <Github size={24} />,
    bgClass: "bg-slate-900 dark:bg-zinc-800",
    textClass: "text-white",
  },
  {
    href: "#",
    label: "Self Intro",
    icon: <Video size={24} />,
    bgClass: "bg-white dark:bg-zinc-50",
    textClass: "text-slate-900",
  },
];

export function LinkInBioSection({
  name = "John Doe",
  avatarSrc = "https://api.dicebear.com/8.x/lorelei-neutral/svg?seed=John",
  headline = "Hi, I'm John",
  bio = "I craft beautiful, performant web experiences with React, TypeScript, and modern UI frameworks.",
  aboutText = (
    <>
      Passionate about building elegant, accessible, and high-performance web apps.<br />Always learning, always sharing.
    </>
  ),
  socialLinks = DEFAULT_SOCIAL_LINKS,
  contactTitle = "Interested in collaborating, chatting about tech, or just saying hi? Send me a message below!",
  className,
}: LinkInBioSectionProps) {
  const [message, setMessage] = useState("");
  const [showToast, setShowToast] = useState(false);
  const [error, setError] = useState("");
  const inputRef = useRef<HTMLInputElement>(null);

  const validateMessage = (msg: string) => {
    if (!msg.trim()) return "Message cannot be empty.";
    if (msg.trim().length < 3) return "Message must be at least 3 characters.";
    if (msg.length > 200) return "Message cannot exceed 200 characters.";
    return "";
  };

  const handleSend = (e: React.FormEvent) => {
    e.preventDefault();
    const validationError = validateMessage(message);
    if (validationError) {
      setError(validationError);
      return;
    }
    setShowToast(true);
    setMessage("");
    setError("");
    if (inputRef.current) inputRef.current.blur();
    setTimeout(() => setShowToast(false), 3000);
  };

  const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setMessage(e.target.value);
    if (error) setError("");
  };

  return (
    <div className={cn("min-h-screen w-full flex items-center justify-center bg-gradient-to-br from-slate-50 via-slate-100 to-slate-50 dark:from-zinc-900 dark:via-zinc-950 dark:to-zinc-900 px-4 py-16 text-slate-900 dark:text-zinc-50 relative overflow-hidden", className)}>
      
      {/* Inline Animations */}
      <style>{`
        .link-in-bio-fade-in {
          animation: linkInBioFadeIn 0.3s ease;
        }
        @keyframes linkInBioFadeIn {
          from { opacity: 0; transform: translateY(-10px); }
          to { opacity: 1; transform: translateY(0); }
        }
        @keyframes linkInBioGlow {
          0%, 100% { opacity: 0.4; transform: scale(1); }
          50% { opacity: 0.8; transform: scale(1.1); }
        }
        .animate-bio-glow {
          animation: linkInBioGlow 4s ease-in-out infinite;
        }
      `}</style>

      {/* Animated background blob */}
      <div className="absolute -top-32 -left-32 w-[500px] h-[500px] bg-gradient-to-tr from-pink-500 via-red-500 to-orange-400 opacity-10 dark:opacity-20 rounded-full blur-3xl animate-bio-glow z-0 pointer-events-none" />
      
      <div className="w-full max-w-2xl flex flex-col items-center gap-12 z-10">
        
        {/* --- Hero Section --- */}
        <section className="w-full flex flex-col items-center text-center gap-6">
          <div className="relative mb-2">
            <span className="absolute inset-0 rounded-full bg-gradient-to-tr from-pink-500 via-red-500 to-orange-400 opacity-60 blur-lg animate-bio-glow" />
            <img
              src={avatarSrc}
              alt={`${name} avatar`}
              className="relative size-32 rounded-full border-4 border-white dark:border-zinc-800 shadow-xl z-10 bg-slate-100 dark:bg-zinc-900 object-cover"
            />
          </div>
          <h1 className="text-4xl md:text-6xl font-extrabold leading-tight tracking-tight drop-shadow-sm dark:drop-shadow-lg text-slate-900 dark:text-white">
            {headline}
          </h1>
          <p className="text-lg md:text-2xl text-slate-600 dark:text-zinc-300 max-w-lg mx-auto font-medium leading-relaxed">
            {bio}
          </p>
        </section>

        {/* --- About Block --- */}
        <div className="w-full rounded-2xl border border-slate-200 dark:border-zinc-800 bg-white/80 dark:bg-zinc-950/80 p-7 shadow-lg text-center backdrop-blur-sm">
          <p className="text-base md:text-lg text-slate-700 dark:text-zinc-200 font-medium leading-relaxed">
            {aboutText}
          </p>
        </div>

        {/* --- Socials Block --- */}
        <div className="flex flex-wrap justify-center gap-4 w-full">
          {socialLinks.map((link) => (
            <a
              key={link.label}
              href={link.href}
              aria-label={link.label}
              className={cn(
                'flex items-center justify-center gap-2 rounded-full border border-slate-200 dark:border-zinc-800 px-7 py-3 text-base font-semibold shadow-md transition-all duration-200 hover:scale-105 hover:shadow-xl hover:border-pink-400 dark:hover:border-pink-400 focus:outline-none focus:ring-2 focus:ring-pink-300 bg-opacity-90 dark:bg-opacity-80',
                link.bgClass,
                link.textClass
              )}
              style={{ minWidth: 140, minHeight: 56 }}
              tabIndex={0}
            >
              {link.icon}
              <span>{link.label}</span>
            </a>
          ))}
        </div>

        {/* --- Connect Section --- */}
        <section className="w-full flex flex-col items-center text-center gap-4 mt-4 relative">
          {showToast && (
            <div className="fixed top-6 right-6 z-50 bg-emerald-500 text-white px-6 py-3 rounded-xl shadow-lg font-semibold text-sm link-in-bio-fade-in flex items-center gap-2">
              <Send className="w-4 h-4" /> Message sent!
            </div>
          )}
          <p className="text-base text-slate-600 dark:text-zinc-400 mb-4 max-w-md mx-auto font-medium">
            {contactTitle}
          </p>
          <form onSubmit={handleSend} className="flex w-full max-w-md gap-2 items-center justify-center flex-col sm:flex-row">
            <input
              ref={inputRef}
              type="text"
              value={message}
              onChange={handleInputChange}
              placeholder="Type your message..."
              className={cn(
                "flex-1 w-full rounded-full border px-5 py-3 text-sm text-slate-900 dark:text-zinc-100 placeholder-slate-400 dark:placeholder-zinc-500 transition-colors focus:outline-none shadow-sm",
                error 
                  ? "border-red-500 focus:border-red-500" 
                  : "border-slate-300 dark:border-zinc-700 bg-white dark:bg-zinc-900 focus:border-pink-400 dark:focus:border-pink-400"
              )}
              maxLength={201}
            />
            <button
              type="submit"
              className={cn(
                "inline-flex w-full sm:w-auto items-center justify-center gap-2 rounded-full bg-gradient-to-r from-red-500 via-pink-500 to-orange-400 px-7 py-3 text-sm font-bold text-white shadow-md focus:outline-none focus:ring-2 focus:ring-pink-300 transition-all",
                message.trim() 
                  ? "hover:scale-105 hover:shadow-xl cursor-pointer opacity-100" 
                  : "opacity-50 cursor-not-allowed"
              )}
              disabled={!message.trim()}
              aria-disabled={!message.trim()}
            >
              Send
            </button>
          </form>
          {error && (
            <div className="text-red-500 text-sm mt-1 font-medium">{error}</div>
          )}
        </section>
        
      </div>
    </div>
  );
}

--- FILE: frontend-web/registry/sections/OnboardingChecklist.tsx ---

import * as React from "react";
import { useState, useEffect } from "react";
import { motion, AnimatePresence } from "framer-motion";
import { CheckCircle2, PlayCircle, X } from "lucide-react";
import { cn } from "../core/utils";

export interface ChecklistItem {
  id: number | string;
  text: string;
  helperText?: string;
  helperLink?: {
    href: string;
    text: string;
  };
}

export interface OnboardingChecklistProps {
  title: string;
  description: string;
  items: ChecklistItem[];
  videoThumbnailUrl: string;
  videoUrl: string;
  className?: string;
}

export const OnboardingChecklist = ({
  title,
  description,
  items,
  videoThumbnailUrl,
  videoUrl,
  className,
}: OnboardingChecklistProps) => {
  const [isVideoOpen, setIsVideoOpen] = useState(false);

  // Close modal on Escape key
  useEffect(() => {
    const handleEsc = (e: KeyboardEvent) => {
      if (e.key === "Escape") setIsVideoOpen(false);
    };
    if (isVideoOpen) document.addEventListener("keydown", handleEsc);
    return () => document.removeEventListener("keydown", handleEsc);
  }, [isVideoOpen]);

  // Prevent background scrolling when modal is open
  useEffect(() => {
    if (isVideoOpen) {
      document.body.style.overflow = "hidden";
    } else {
      document.body.style.overflow = "";
    }
    return () => {
      document.body.style.overflow = "";
    };
  }, [isVideoOpen]);

  const containerVariants = {
    hidden: { opacity: 0, y: 20 },
    visible: {
      opacity: 1,
      y: 0,
      transition: {
        duration: 0.5,
        ease: "easeOut",
        when: "beforeChildren",
        staggerChildren: 0.1,
      },
    },
  };

  const itemVariants = {
    hidden: { opacity: 0, x: -20 },
    visible: {
      opacity: 1,
      x: 0,
      transition: {
        duration: 0.4,
        ease: "easeOut",
      },
    },
  };

  return (
    <>
      <motion.div
        initial="hidden"
        animate="visible"
        variants={containerVariants}
        className={cn(
          "w-full max-w-4xl mx-auto bg-white dark:bg-zinc-950 text-slate-950 dark:text-white border border-slate-200 dark:border-zinc-800 rounded-2xl shadow-sm p-8 overflow-hidden",
          className
        )}
      >
        <div className="grid grid-cols-1 md:grid-cols-2 gap-8 items-center">
          {/* Left Side: Title and Checklist */}
          <div className="flex flex-col">
            <h2 className="text-2xl font-bold tracking-tight">{title}</h2>
            <p className="mt-2 text-slate-500 dark:text-slate-400">{description}</p>
            <ul className="mt-6 grid grid-cols-1 sm:grid-cols-2 gap-x-8 gap-y-4">
              {items.map((item) => (
                <motion.li key={item.id} variants={itemVariants} className="flex flex-col">
                  <div className="flex items-start">
                    <CheckCircle2 className="h-5 w-5 text-green-500 mt-0.5 flex-shrink-0" />
                    <span className="ml-3 text-sm font-medium">{item.text}</span>
                  </div>
                  {item.helperText && item.helperLink && (
                    <div className="ml-8 mt-1 text-xs text-slate-500 dark:text-slate-400">
                      {item.helperText}{" "}
                      <a
                        href={item.helperLink.href}
                        className="text-slate-900 dark:text-white font-semibold underline-offset-4 hover:underline focus:outline-none focus:ring-2 focus:ring-slate-950 dark:focus:ring-slate-300 focus:ring-offset-2 rounded-sm transition-colors"
                      >
                        {item.helperLink.text}
                      </a>
                    </div>
                  )}
                </motion.li>
              ))}
            </ul>
          </div>

          {/* Right Side: Video Thumbnail */}
          <motion.div
            variants={itemVariants} // Re-using item variant for a nice slide-in effect
            className="relative group rounded-lg overflow-hidden cursor-pointer w-full aspect-video"
            onClick={() => setIsVideoOpen(true)}
          >
            <div>
              <img
                src={videoThumbnailUrl}
                alt="Video guide thumbnail"
                className="w-full h-full object-cover transition-transform duration-300 group-hover:scale-105"
              />
              <div className="absolute inset-0 bg-black/30 flex items-center justify-center transition-colors group-hover:bg-black/40">
                <PlayCircle className="h-16 w-16 text-white/80 transform transition-all duration-300 group-hover:scale-110 group-hover:text-white" />
              </div>
            </div>
          </motion.div>
        </div>
      </motion.div>

      {/* Custom Modal for Video */}
      <AnimatePresence>
        {isVideoOpen && (
          <motion.div
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 }}
            exit={{ opacity: 0 }}
            className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/80 backdrop-blur-sm"
            onClick={() => setIsVideoOpen(false)}
          >
            <motion.div
              initial={{ scale: 0.95, opacity: 0 }}
              animate={{ scale: 1, opacity: 1 }}
              exit={{ scale: 0.95, opacity: 0 }}
              transition={{ duration: 0.2 }}
              className="relative w-full max-w-3xl bg-black rounded-xl overflow-hidden shadow-2xl"
              onClick={(e) => e.stopPropagation()} // Prevent clicking video from closing modal
            >
              <button
                onClick={() => setIsVideoOpen(false)}
                className="absolute top-4 right-4 z-10 p-2 rounded-full bg-black/50 text-white hover:bg-black/70 transition-colors focus:outline-none focus:ring-2 focus:ring-white/50"
                aria-label="Close video"
              >
                <X className="w-5 h-5" />
              </button>
              <div className="aspect-video w-full">
                <iframe
                  src={videoUrl}
                  title="Onboarding Video Guide"
                  frameBorder="0"
                  allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
                  allowFullScreen
                  className="w-full h-full"
                ></iframe>
              </div>
            </motion.div>
          </motion.div>
        )}
      </AnimatePresence>
    </>
  );
};

--- FILE: frontend-web/registry/sections/WorkspaceWelcome.tsx ---

import * as React from "react";
import { motion } from "framer-motion";
import { PlayCircle } from "lucide-react";
import { cn } from "../core/utils";

export interface ActionItem {
  icon: React.ReactNode;
  label: string;
  isBeta?: boolean;
  onClick?: () => void;
  buttonProps?: React.ButtonHTMLAttributes<HTMLButtonElement>;
}

export interface WorkspaceWelcomeProps {
  /** The name of the user to display in the welcome message. */
  userName: string;
  /** The source URL for the video thumbnail. */
  videoThumbnail: string;
  /** The title of the video, displayed over the thumbnail. */
  videoTitle: string;
  /** The description of the video. */
  videoDescription: string;
  /** An array of action items to be displayed as buttons. */
  actions: ActionItem[];
  /** A callback function to be invoked when the video card is clicked. */
  onPlayVideo?: () => void;
  /** Additional CSS class names for the component container. */
  className?: string;
}

const containerVariants = {
  hidden: { opacity: 0 },
  visible: {
    opacity: 1,
    transition: {
      staggerChildren: 0.1,
    },
  },
};

const itemVariants = {
  hidden: { opacity: 0, y: 20 },
  visible: {
    opacity: 1,
    y: 0,
    transition: {
      type: "spring",
      stiffness: 100,
      damping: 12,
    },
  },
};

export const WorkspaceWelcome = React.forwardRef<HTMLDivElement, WorkspaceWelcomeProps>(
  (
    {
      userName,
      videoThumbnail,
      videoTitle,
      videoDescription,
      actions,
      onPlayVideo,
      className,
    },
    ref
  ) => {
    return (
      <motion.div
        ref={ref}
        className={cn(
          "flex w-full max-w-2xl flex-col items-center gap-8 rounded-lg p-4",
          className
        )}
        variants={containerVariants}
        initial="hidden"
        animate="visible"
      >
        {/* Welcome Header */}
        <motion.h1
          className="text-center text-2xl font-bold tracking-tight text-slate-900 dark:text-white md:text-3xl"
          variants={itemVariants}
        >
          Welcome to your workspace, {userName}! 👋
        </motion.h1>

        {/* Action Buttons */}
        <motion.div
          className="flex flex-wrap items-center justify-center gap-3"
          variants={itemVariants}
        >
          {actions.map((action, index) => (
            <button
              key={index}
              className="inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-slate-950 disabled:pointer-events-none disabled:opacity-50 border border-slate-200 bg-white hover:bg-slate-100 hover:text-slate-900 dark:border-slate-800 dark:bg-slate-950 dark:hover:bg-slate-800 dark:hover:text-slate-50 dark:focus-visible:ring-slate-300 h-9 px-4 py-2 gap-2"
              onClick={action.onClick}
              {...action.buttonProps}
            >
              {action.icon}
              <span className="font-medium">{action.label}</span>
              {action.isBeta && (
                <span className="ml-1 inline-flex items-center rounded-full border border-transparent bg-slate-100 px-1.5 py-0.5 text-xs font-semibold text-slate-900 transition-colors hover:bg-slate-100/80 dark:bg-slate-800 dark:text-slate-50 dark:hover:bg-slate-800/80">
                  BETA
                </span>
              )}
            </button>
          ))}
        </motion.div>

        {/* Video Card */}
        <motion.div
          className="group relative w-full cursor-pointer overflow-hidden rounded-xl shadow-lg"
          onClick={onPlayVideo}
          variants={itemVariants}
          whileHover={{ scale: 1.02 }}
          transition={{ type: "spring", stiffness: 300, damping: 20 }}
        >
          <img
            src={videoThumbnail}
            alt={videoTitle}
            className="aspect-video w-full object-cover transition-transform duration-300 group-hover:scale-105"
          />
          <div className="absolute inset-0 bg-gradient-to-t from-black/70 via-black/30 to-transparent" />
          <div className="absolute bottom-0 left-0 p-6 text-white">
            <h3 className="text-lg font-bold">{videoTitle}</h3>
            <p className="text-sm text-white/80">{videoDescription}</p>
          </div>
          <div className="absolute inset-0 flex items-center justify-center">
            <PlayCircle className="h-16 w-16 text-white/80 transition-all duration-300 group-hover:scale-110 group-hover:text-white" />
          </div>
        </motion.div>
      </motion.div>
    );
  }
);

WorkspaceWelcome.displayName = "WorkspaceWelcome";

--- FILE: frontend-web/registry/text_effects/Blur Text.tsx ---

import { motion, Transition, Easing } from 'motion/react';
import { useEffect, useRef, useState, useMemo } from 'react';

type BlurTextProps = {
  text?: string;
  delay?: number;
  className?: string;
  animateBy?: 'words' | 'letters';
  direction?: 'top' | 'bottom';
  threshold?: number;
  rootMargin?: string;
  animationFrom?: Record<string, string | number>;
  animationTo?: Array<Record<string, string | number>>;
  easing?: Easing | Easing[];
  onAnimationComplete?: () => void;
  stepDuration?: number;
};

const buildKeyframes = (
  from: Record<string, string | number>,
  steps: Array<Record<string, string | number>>
): Record<string, Array<string | number>> => {
  const keys = new Set<string>([...Object.keys(from), ...steps.flatMap(s => Object.keys(s))]);

  const keyframes: Record<string, Array<string | number>> = {};
  keys.forEach(k => {
    keyframes[k] = [from[k], ...steps.map(s => s[k])];
  });
  return keyframes;
};

const BlurText: React.FC<BlurTextProps> = ({
  text = '',
  delay = 200,
  className = '',
  animateBy = 'words',
  direction = 'top',
  threshold = 0.1,
  rootMargin = '0px',
  animationFrom,
  animationTo,
  easing = (t: number) => t,
  onAnimationComplete,
  stepDuration = 0.35
}) => {
  const elements = animateBy === 'words' ? text.split(' ') : text.split('');
  const [inView, setInView] = useState(false);
  const ref = useRef<HTMLParagraphElement>(null);

  useEffect(() => {
    if (!ref.current) return;
    const observer = new IntersectionObserver(
      ([entry]) => {
        if (entry.isIntersecting) {
          setInView(true);
          observer.unobserve(ref.current as Element);
        }
      },
      { threshold, rootMargin }
    );
    observer.observe(ref.current);
    return () => observer.disconnect();
  }, [threshold, rootMargin]);

  const defaultFrom = useMemo(
    () =>
      direction === 'top' ? { filter: 'blur(10px)', opacity: 0, y: -50 } : { filter: 'blur(10px)', opacity: 0, y: 50 },
    [direction]
  );

  const defaultTo = useMemo(
    () => [
      {
        filter: 'blur(5px)',
        opacity: 0.5,
        y: direction === 'top' ? 5 : -5
      },
      { filter: 'blur(0px)', opacity: 1, y: 0 }
    ],
    [direction]
  );

  const fromSnapshot = animationFrom ?? defaultFrom;
  const toSnapshots = animationTo ?? defaultTo;

  const stepCount = toSnapshots.length + 1;
  const totalDuration = stepDuration * (stepCount - 1);
  const times = Array.from({ length: stepCount }, (_, i) => (stepCount === 1 ? 0 : i / (stepCount - 1)));

  return (
    <p ref={ref} className={`blur-text ${className} flex flex-wrap`}>
      {elements.map((segment, index) => {
        const animateKeyframes = buildKeyframes(fromSnapshot, toSnapshots);

        const spanTransition: Transition = {
          duration: totalDuration,
          times,
          delay: (index * delay) / 1000,
          ease: easing
        };

        return (
          <motion.span
            key={index}
            initial={fromSnapshot}
            animate={inView ? animateKeyframes : fromSnapshot}
            transition={spanTransition}
            onAnimationComplete={index === elements.length - 1 ? onAnimationComplete : undefined}
            style={{
              display: 'inline-block',
              willChange: 'transform, filter, opacity'
            }}
          >
            {segment === ' ' ? '\u00A0' : segment}
            {animateBy === 'words' && index < elements.length - 1 && '\u00A0'}
          </motion.span>
        );
      })}
    </p>
  );
};

export default BlurText;


--- FILE: frontend-web/registry/text_effects/GradientText.tsx ---

import { useState, useCallback, useEffect, useRef, ReactNode } from "react";
import {
  motion,
  useMotionValue,
  useAnimationFrame,
  useTransform,
} from "motion/react";

interface GradientTextProps {
  children: ReactNode;
  className?: string;
  colors?: string[];
  animationSpeed?: number;
  showBorder?: boolean;
  direction?: "horizontal" | "vertical" | "diagonal";
  pauseOnHover?: boolean;
  yoyo?: boolean;
}

export default function GradientText({
  children,
  className = "",
  colors = ["#5227FF", "#FF9FFC", "#B497CF"],
  animationSpeed = 8,
  showBorder = false,
  direction = "horizontal",
  pauseOnHover = false,
  yoyo = true,
}: GradientTextProps) {
  const [isPaused, setIsPaused] = useState(false);
  const progress = useMotionValue(0);
  const elapsedRef = useRef(0);
  const lastTimeRef = useRef<number | null>(null);

  const animationDuration = animationSpeed * 1000;

  useAnimationFrame((time) => {
    if (isPaused) {
      lastTimeRef.current = null;
      return;
    }

    if (lastTimeRef.current === null) {
      lastTimeRef.current = time;
      return;
    }

    const deltaTime = time - lastTimeRef.current;
    lastTimeRef.current = time;
    elapsedRef.current += deltaTime;

    if (yoyo) {
      const fullCycle = animationDuration * 2;
      const cycleTime = elapsedRef.current % fullCycle;

      if (cycleTime < animationDuration) {
        progress.set((cycleTime / animationDuration) * 100);
      } else {
        progress.set(
          100 - ((cycleTime - animationDuration) / animationDuration) * 100,
        );
      }
    } else {
      // Continuously increase position for seamless looping
      progress.set((elapsedRef.current / animationDuration) * 100);
    }
  });

  useEffect(() => {
    elapsedRef.current = 0;
    progress.set(0);
  }, [animationSpeed, yoyo]);

  const backgroundPosition = useTransform(progress, (p) => {
    if (direction === "horizontal") {
      return `${p}% 50%`;
    } else if (direction === "vertical") {
      return `50% ${p}%`;
    } else {
      // For diagonal, move only horizontally to avoid interference patterns
      return `${p}% 50%`;
    }
  });

  const handleMouseEnter = useCallback(() => {
    if (pauseOnHover) setIsPaused(true);
  }, [pauseOnHover]);

  const handleMouseLeave = useCallback(() => {
    if (pauseOnHover) setIsPaused(false);
  }, [pauseOnHover]);

  const gradientAngle =
    direction === "horizontal"
      ? "to right"
      : direction === "vertical"
        ? "to bottom"
        : "to bottom right";
  // Duplicate first color at the end for seamless looping
  const gradientColors = [...colors, colors[0]].join(", ");

  const gradientStyle = {
    backgroundImage: `linear-gradient(${gradientAngle}, ${gradientColors})`,
    backgroundSize:
      direction === "horizontal"
        ? "300% 100%"
        : direction === "vertical"
          ? "100% 300%"
          : "300% 300%",
    backgroundRepeat: "repeat",
  };

  return (
    <motion.div
      className={`relative mx-auto flex max-w-fit flex-row items-center justify-center rounded-[1.25rem] font-medium backdrop-blur transition-shadow duration-500 overflow-hidden cursor-pointer ${showBorder ? "py-1 px-2" : ""} ${className}`}
      onMouseEnter={handleMouseEnter}
      onMouseLeave={handleMouseLeave}
    >
      {showBorder && (
        <motion.div
          className="absolute inset-0 z-0 pointer-events-none rounded-[1.25rem]"
          style={{ ...gradientStyle, backgroundPosition }}
        >
          <div
            className="absolute bg-black rounded-[1.25rem] z-[-1]"
            style={{
              width: "calc(100% - 2px)",
              height: "calc(100% - 2px)",
              left: "50%",
              top: "50%",
              transform: "translate(-50%, -50%)",
            }}
          />
        </motion.div>
      )}
      <motion.div
        className="inline-block relative z-2 text-transparent bg-clip-text"
        style={{
          ...gradientStyle,
          backgroundPosition,
          WebkitBackgroundClip: "text",
        }}
      >
        {children}
      </motion.div>
    </motion.div>
  );
}


--- FILE: frontend-web/registry/text_effects/ParticleText.tsx ---

import React, { useEffect, useRef, useState } from "react";
import { cn } from "../core/utils";

interface Vector2D {
  x: number;
  y: number;
}

class Particle {
  pos: Vector2D = { x: 0, y: 0 };
  vel: Vector2D = { x: 0, y: 0 };
  acc: Vector2D = { x: 0, y: 0 };
  target: Vector2D = { x: 0, y: 0 };

  closeEnoughTarget = 100;
  maxSpeed = 1.0;
  maxForce = 0.1;
  particleSize = 10;
  isKilled = false;

  startColor = { r: 0, g: 0, b: 0 };
  targetColor = { r: 0, g: 0, b: 0 };
  colorWeight = 0;
  colorBlendRate = 0.01;

  move() {
    let proximityMult = 1;
    const distance = Math.sqrt(
      Math.pow(this.pos.x - this.target.x, 2) + Math.pow(this.pos.y - this.target.y, 2)
    );

    if (distance < this.closeEnoughTarget) {
      proximityMult = distance / this.closeEnoughTarget;
    }

    const towardsTarget = {
      x: this.target.x - this.pos.x,
      y: this.target.y - this.pos.y,
    };

    const magnitude = Math.sqrt(
      towardsTarget.x * towardsTarget.x + towardsTarget.y * towardsTarget.y
    );
    if (magnitude > 0) {
      towardsTarget.x = (towardsTarget.x / magnitude) * this.maxSpeed * proximityMult;
      towardsTarget.y = (towardsTarget.y / magnitude) * this.maxSpeed * proximityMult;
    }

    const steer = {
      x: towardsTarget.x - this.vel.x,
      y: towardsTarget.y - this.vel.y,
    };

    const steerMagnitude = Math.sqrt(steer.x * steer.x + steer.y * steer.y);
    if (steerMagnitude > 0) {
      steer.x = (steer.x / steerMagnitude) * this.maxForce;
      steer.y = (steer.y / steerMagnitude) * this.maxForce;
    }

    this.acc.x += steer.x;
    this.acc.y += steer.y;

    this.vel.x += this.acc.x;
    this.vel.y += this.acc.y;
    this.pos.x += this.vel.x;
    this.pos.y += this.vel.y;
    this.acc.x = 0;
    this.acc.y = 0;
  }

  draw(ctx: CanvasRenderingContext2D, drawAsPoints: boolean) {
    if (this.colorWeight < 1.0) {
      this.colorWeight = Math.min(this.colorWeight + this.colorBlendRate, 1.0);
    }

    const currentColor = {
      r: Math.round(
        this.startColor.r + (this.targetColor.r - this.startColor.r) * this.colorWeight
      ),
      g: Math.round(
        this.startColor.g + (this.targetColor.g - this.startColor.g) * this.colorWeight
      ),
      b: Math.round(
        this.startColor.b + (this.targetColor.b - this.startColor.b) * this.colorWeight
      ),
    };

    if (drawAsPoints) {
      ctx.fillStyle = `rgb(${currentColor.r}, ${currentColor.g}, ${currentColor.b})`;
      ctx.fillRect(this.pos.x, this.pos.y, 2, 2);
    } else {
      ctx.fillStyle = `rgb(${currentColor.r}, ${currentColor.g}, ${currentColor.b})`;
      ctx.beginPath();
      ctx.arc(this.pos.x, this.pos.y, this.particleSize / 2, 0, Math.PI * 2);
      ctx.fill();
    }
  }

  kill(width: number, height: number) {
    if (!this.isKilled) {
      const randomPos = this.generateRandomPos(
        width / 2,
        height / 2,
        (width + height) / 2
      );
      this.target.x = randomPos.x;
      this.target.y = randomPos.y;

      this.startColor = {
        r:
          this.startColor.r +
          (this.targetColor.r - this.startColor.r) * this.colorWeight,
        g:
          this.startColor.g +
          (this.targetColor.g - this.startColor.g) * this.colorWeight,
        b:
          this.startColor.b +
          (this.targetColor.b - this.startColor.b) * this.colorWeight,
      };
      this.targetColor = { r: 0, g: 0, b: 0 };
      this.colorWeight = 0;

      this.isKilled = true;
    }
  }

  private generateRandomPos(x: number, y: number, mag: number): Vector2D {
    const randomX = Math.random() * 1000;
    const randomY = Math.random() * 500;

    const direction = {
      x: randomX - x,
      y: randomY - y,
    };

    const magnitude = Math.sqrt(
      direction.x * direction.x + direction.y * direction.y
    );
    if (magnitude > 0) {
      direction.x = (direction.x / magnitude) * mag;
      direction.y = (direction.y / magnitude) * mag;
    }

    return {
      x: x + direction.x,
      y: y + direction.y,
    };
  }
}

export interface ParticleTextProps {
  words?: string[];
  className?: string;
}

const DEFAULT_WORDS = ["HELLO", "WORLD", "PARTICLE", "TEXT", "EFFECT"];

export function ParticleText({
  words = DEFAULT_WORDS,
  className,
}: ParticleTextProps) {
  const containerRef = useRef<HTMLDivElement>(null);
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const animationRef = useRef<number>();
  const particlesRef = useRef<Particle[]>([]);
  const frameCountRef = useRef(0);
  const wordIndexRef = useRef(0);
  const mouseRef = useRef({ x: 0, y: 0, isPressed: false, isRightClick: false });

  const pixelSteps = 6;
  const drawAsPoints = true;

  const generateRandomPos = (x: number, y: number, mag: number): Vector2D => {
    const randomX = Math.random() * 1000;
    const randomY = Math.random() * 500;

    const direction = {
      x: randomX - x,
      y: randomY - y,
    };

    const magnitude = Math.sqrt(
      direction.x * direction.x + direction.y * direction.y
    );
    if (magnitude > 0) {
      direction.x = (direction.x / magnitude) * mag;
      direction.y = (direction.y / magnitude) * mag;
    }

    return {
      x: x + direction.x,
      y: y + direction.y,
    };
  };

  const nextWord = (word: string, canvas: HTMLCanvasElement) => {
    const offscreenCanvas = document.createElement("canvas");
    offscreenCanvas.width = canvas.width;
    offscreenCanvas.height = canvas.height;
    const offscreenCtx = offscreenCanvas.getContext("2d")!;

    offscreenCtx.fillStyle = "white";
    // Scale font size down slightly to fit smaller containers better
    const fontSize = Math.min(canvas.width / 5, 120);
    offscreenCtx.font = `bold ${fontSize}px Arial`;
    offscreenCtx.textAlign = "center";
    offscreenCtx.textBaseline = "middle";
    offscreenCtx.fillText(word, canvas.width / 2, canvas.height / 2);

    const imageData = offscreenCtx.getImageData(0, 0, canvas.width, canvas.height);
    const pixels = imageData.data;

    const newColor = {
      r: Math.random() * 255,
      g: Math.random() * 255,
      b: Math.random() * 255,
    };

    const particles = particlesRef.current;
    let particleIndex = 0;

    const coordsIndexes: number[] = [];
    for (let i = 0; i < pixels.length; i += pixelSteps * 4) {
      coordsIndexes.push(i);
    }

    for (let i = coordsIndexes.length - 1; i > 0; i--) {
      const j = Math.floor(Math.random() * (i + 1));
      [coordsIndexes[i], coordsIndexes[j]] = [coordsIndexes[j], coordsIndexes[i]];
    }

    for (const coordIndex of coordsIndexes) {
      const pixelIndex = coordIndex;
      const alpha = pixels[pixelIndex + 3];

      if (alpha > 0) {
        const x = (pixelIndex / 4) % canvas.width;
        const y = Math.floor(pixelIndex / 4 / canvas.width);

        let particle: Particle;

        if (particleIndex < particles.length) {
          particle = particles[particleIndex];
          particle.isKilled = false;
          particleIndex++;
        } else {
          particle = new Particle();

          const randomPos = generateRandomPos(
            canvas.width / 2,
            canvas.height / 2,
            (canvas.width + canvas.height) / 2
          );
          particle.pos.x = randomPos.x;
          particle.pos.y = randomPos.y;

          particle.maxSpeed = Math.random() * 6 + 4;
          particle.maxForce = particle.maxSpeed * 0.05;
          particle.particleSize = Math.random() * 6 + 6;
          particle.colorBlendRate = Math.random() * 0.0275 + 0.0025;

          particles.push(particle);
        }

        particle.startColor = {
          r:
            particle.startColor.r +
            (particle.targetColor.r - particle.startColor.r) * particle.colorWeight,
          g:
            particle.startColor.g +
            (particle.targetColor.g - particle.startColor.g) * particle.colorWeight,
          b:
            particle.startColor.b +
            (particle.targetColor.b - particle.startColor.b) * particle.colorWeight,
        };
        particle.targetColor = newColor;
        particle.colorWeight = 0;

        particle.target.x = x;
        particle.target.y = y;
      }
    }

    for (let i = particleIndex; i < particles.length; i++) {
      particles[i].kill(canvas.width, canvas.height);
    }
  };

  const animate = () => {
    const canvas = canvasRef.current;
    if (!canvas) return;

    const ctx = canvas.getContext("2d")!;
    const particles = particlesRef.current;

    // Use transparent black for motion blur rather than solid black
    ctx.fillStyle = "rgba(0, 0, 0, 0.1)";
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    for (let i = particles.length - 1; i >= 0; i--) {
      const particle = particles[i];
      particle.move();
      particle.draw(ctx, drawAsPoints);

      if (particle.isKilled) {
        if (
          particle.pos.x < 0 ||
          particle.pos.x > canvas.width ||
          particle.pos.y < 0 ||
          particle.pos.y > canvas.height
        ) {
          particles.splice(i, 1);
        }
      }
    }

    if (mouseRef.current.isPressed && mouseRef.current.isRightClick) {
      particles.forEach((particle) => {
        const distance = Math.sqrt(
          Math.pow(particle.pos.x - mouseRef.current.x, 2) +
            Math.pow(particle.pos.y - mouseRef.current.y, 2)
        );
        if (distance < 50) {
          particle.kill(canvas.width, canvas.height);
        }
      });
    }

    frameCountRef.current++;
    if (frameCountRef.current % 240 === 0) {
      wordIndexRef.current = (wordIndexRef.current + 1) % words.length;
      nextWord(words[wordIndexRef.current], canvas);
    }

    animationRef.current = requestAnimationFrame(animate);
  };

  useEffect(() => {
    const container = containerRef.current;
    const canvas = canvasRef.current;
    if (!container || !canvas) return;

    // Handle responsive resizing
    const updateSize = () => {
      const rect = container.getBoundingClientRect();
      canvas.width = rect.width;
      canvas.height = rect.height;
      nextWord(words[wordIndexRef.current], canvas);
    };

    updateSize();
    const resizeObserver = new ResizeObserver(updateSize);
    resizeObserver.observe(container);

    animate();

    const handleMouseDown = (e: MouseEvent) => {
      mouseRef.current.isPressed = true;
      mouseRef.current.isRightClick = e.button === 2;
      const rect = canvas.getBoundingClientRect();
      mouseRef.current.x = e.clientX - rect.left;
      mouseRef.current.y = e.clientY - rect.top;
    };

    const handleMouseUp = () => {
      mouseRef.current.isPressed = false;
      mouseRef.current.isRightClick = false;
    };

    const handleMouseMove = (e: MouseEvent) => {
      const rect = canvas.getBoundingClientRect();
      mouseRef.current.x = e.clientX - rect.left;
      mouseRef.current.y = e.clientY - rect.top;
    };

    const handleContextMenu = (e: MouseEvent) => {
      e.preventDefault();
    };

    canvas.addEventListener("mousedown", handleMouseDown);
    canvas.addEventListener("mouseup", handleMouseUp);
    canvas.addEventListener("mousemove", handleMouseMove);
    canvas.addEventListener("contextmenu", handleContextMenu);

    return () => {
      if (animationRef.current) {
        cancelAnimationFrame(animationRef.current);
      }
      resizeObserver.disconnect();
      canvas.removeEventListener("mousedown", handleMouseDown);
      canvas.removeEventListener("mouseup", handleMouseUp);
      canvas.removeEventListener("mousemove", handleMouseMove);
      canvas.removeEventListener("contextmenu", handleContextMenu);
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [words]);

  return (
    <div ref={containerRef} className={cn("w-full h-full relative", className)}>
      <canvas
        ref={canvasRef}
        className="absolute inset-0 block pointer-events-auto"
      />
    </div>
  );
}

--- FILE: frontend-web/registry/text_effects/Scroll Float.tsx ---

import React, { useEffect, useMemo, useRef, ReactNode, RefObject } from 'react';
import { gsap } from 'gsap';
import { ScrollTrigger } from 'gsap/ScrollTrigger';

gsap.registerPlugin(ScrollTrigger);

interface ScrollFloatProps {
  children: ReactNode;
  scrollContainerRef?: RefObject<HTMLElement>;
  containerClassName?: string;
  textClassName?: string;
  animationDuration?: number;
  ease?: string;
  scrollStart?: string;
  scrollEnd?: string;
  stagger?: number;
}

const ScrollFloat: React.FC<ScrollFloatProps> = ({
  children,
  scrollContainerRef,
  containerClassName = '',
  textClassName = '',
  animationDuration = 1,
  ease = 'back.inOut(2)',
  scrollStart = 'center bottom+=50%',
  scrollEnd = 'bottom bottom-=40%',
  stagger = 0.03
}) => {
  const containerRef = useRef<HTMLHeadingElement>(null);

  const splitText = useMemo(() => {
    const text = typeof children === 'string' ? children : '';
    return text.split('').map((char, index) => (
      <span className="inline-block word" key={index}>
        {char === ' ' ? '\u00A0' : char}
      </span>
    ));
  }, [children]);

  useEffect(() => {
    const el = containerRef.current;
    if (!el) return;

    const scroller = scrollContainerRef && scrollContainerRef.current ? scrollContainerRef.current : window;

    const charElements = el.querySelectorAll('.inline-block');

    gsap.fromTo(
      charElements,
      {
        willChange: 'opacity, transform',
        opacity: 0,
        yPercent: 120,
        scaleY: 2.3,
        scaleX: 0.7,
        transformOrigin: '50% 0%'
      },
      {
        duration: animationDuration,
        ease: ease,
        opacity: 1,
        yPercent: 0,
        scaleY: 1,
        scaleX: 1,
        stagger: stagger,
        scrollTrigger: {
          trigger: el,
          scroller,
          start: scrollStart,
          end: scrollEnd,
          scrub: true
        }
      }
    );
  }, [scrollContainerRef, animationDuration, ease, scrollStart, scrollEnd, stagger]);

  return (
    <h2 ref={containerRef} className={`my-5 overflow-hidden ${containerClassName}`}>
      <span className={`inline-block text-[clamp(1.6rem,4vw,3rem)] leading-[1.5] ${textClassName}`}>{splitText}</span>
    </h2>
  );
};

export default ScrollFloat;


--- FILE: frontend-web/registry/text_effects/Shiny Text.tsx ---

import React, { useState, useCallback, useEffect, useRef } from 'react';
import { motion, useMotionValue, useAnimationFrame, useTransform } from 'motion/react';

interface ShinyTextProps {
  text: string;
  disabled?: boolean;
  speed?: number;
  className?: string;
  color?: string;
  shineColor?: string;
  spread?: number;
  yoyo?: boolean;
  pauseOnHover?: boolean;
  direction?: 'left' | 'right';
  delay?: number;
}

const ShinyText: React.FC<ShinyTextProps> = ({
  text,
  disabled = false,
  speed = 2,
  className = '',
  color = '#b5b5b5',
  shineColor = '#ffffff',
  spread = 120,
  yoyo = false,
  pauseOnHover = false,
  direction = 'left',
  delay = 0
}) => {
  const [isPaused, setIsPaused] = useState(false);
  const progress = useMotionValue(0);
  const elapsedRef = useRef(0);
  const lastTimeRef = useRef<number | null>(null);
  const directionRef = useRef(direction === 'left' ? 1 : -1);

  const animationDuration = speed * 1000;
  const delayDuration = delay * 1000;

  useAnimationFrame(time => {
    if (disabled || isPaused) {
      lastTimeRef.current = null;
      return;
    }

    if (lastTimeRef.current === null) {
      lastTimeRef.current = time;
      return;
    }

    const deltaTime = time - lastTimeRef.current;
    lastTimeRef.current = time;

    elapsedRef.current += deltaTime;

    // Animation goes from 0 to 100
    if (yoyo) {
      const cycleDuration = animationDuration + delayDuration;
      const fullCycle = cycleDuration * 2;
      const cycleTime = elapsedRef.current % fullCycle;

      if (cycleTime < animationDuration) {
        // Forward animation: 0 -> 100
        const p = (cycleTime / animationDuration) * 100;
        progress.set(directionRef.current === 1 ? p : 100 - p);
      } else if (cycleTime < cycleDuration) {
        // Delay at end
        progress.set(directionRef.current === 1 ? 100 : 0);
      } else if (cycleTime < cycleDuration + animationDuration) {
        // Reverse animation: 100 -> 0
        const reverseTime = cycleTime - cycleDuration;
        const p = 100 - (reverseTime / animationDuration) * 100;
        progress.set(directionRef.current === 1 ? p : 100 - p);
      } else {
        // Delay at start
        progress.set(directionRef.current === 1 ? 0 : 100);
      }
    } else {
      const cycleDuration = animationDuration + delayDuration;
      const cycleTime = elapsedRef.current % cycleDuration;

      if (cycleTime < animationDuration) {
        // Animation phase: 0 -> 100
        const p = (cycleTime / animationDuration) * 100;
        progress.set(directionRef.current === 1 ? p : 100 - p);
      } else {
        // Delay phase - hold at end (shine off-screen)
        progress.set(directionRef.current === 1 ? 100 : 0);
      }
    }
  });

  useEffect(() => {
    directionRef.current = direction === 'left' ? 1 : -1;
    elapsedRef.current = 0;
    progress.set(0);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [direction]);

  // Transform: p=0 -> 150% (shine off right), p=100 -> -50% (shine off left)
  const backgroundPosition = useTransform(progress, p => `${150 - p * 2}% center`);

  const handleMouseEnter = useCallback(() => {
    if (pauseOnHover) setIsPaused(true);
  }, [pauseOnHover]);

  const handleMouseLeave = useCallback(() => {
    if (pauseOnHover) setIsPaused(false);
  }, [pauseOnHover]);

  const gradientStyle: React.CSSProperties = {
    backgroundImage: `linear-gradient(${spread}deg, ${color} 0%, ${color} 35%, ${shineColor} 50%, ${color} 65%, ${color} 100%)`,
    backgroundSize: '200% auto',
    WebkitBackgroundClip: 'text',
    backgroundClip: 'text',
    WebkitTextFillColor: 'transparent'
  };

  return (
    <motion.span
      className={`inline-block ${className}`}
      style={{ ...gradientStyle, backgroundPosition }}
      onMouseEnter={handleMouseEnter}
      onMouseLeave={handleMouseLeave}
    >
      {text}
    </motion.span>
  );
};

export default ShinyText;


--- FILE: frontend-web/registry/text_effects/Shuffle.tsx ---

import React, { useRef, useEffect, useState, useMemo } from 'react';
import { gsap } from 'gsap';
import { ScrollTrigger } from 'gsap/ScrollTrigger';
import { SplitText as GSAPSplitText } from 'gsap/SplitText';
import { useGSAP } from '@gsap/react';
import { JSX } from 'react';

gsap.registerPlugin(ScrollTrigger, GSAPSplitText);

export interface ShuffleProps {
  text: string;
  className?: string;
  style?: React.CSSProperties;
  shuffleDirection?: 'left' | 'right' | 'up' | 'down';
  duration?: number;
  maxDelay?: number;
  ease?: string | ((t: number) => number);
  threshold?: number;
  rootMargin?: string;
  tag?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p' | 'span';
  textAlign?: React.CSSProperties['textAlign'];
  onShuffleComplete?: () => void;
  shuffleTimes?: number;
  animationMode?: 'random' | 'evenodd';
  loop?: boolean;
  loopDelay?: number;
  stagger?: number;
  scrambleCharset?: string;
  colorFrom?: string;
  colorTo?: string;
  triggerOnce?: boolean;
  respectReducedMotion?: boolean;
  triggerOnHover?: boolean;
}

const Shuffle: React.FC<ShuffleProps> = ({
  text,
  className = '',
  style = {},
  shuffleDirection = 'right',
  duration = 0.35,
  maxDelay = 0,
  ease = 'power3.out',
  threshold = 0.1,
  rootMargin = '-100px',
  tag = 'p',
  textAlign = 'center',
  onShuffleComplete,
  shuffleTimes = 1,
  animationMode = 'evenodd',
  loop = false,
  loopDelay = 0,
  stagger = 0.03,
  scrambleCharset = '',
  colorFrom,
  colorTo,
  triggerOnce = true,
  respectReducedMotion = true,
  triggerOnHover = true
}) => {
  const ref = useRef<HTMLElement>(null);
  const [fontsLoaded, setFontsLoaded] = useState(false);
  const [ready, setReady] = useState(false);

  const splitRef = useRef<GSAPSplitText | null>(null);
  const wrappersRef = useRef<HTMLElement[]>([]);
  const tlRef = useRef<gsap.core.Timeline | null>(null);
  const playingRef = useRef(false);
  const hoverHandlerRef = useRef<((e: Event) => void) | null>(null);

  useEffect(() => {
    if ('fonts' in document) {
      if (document.fonts.status === 'loaded') setFontsLoaded(true);
      else document.fonts.ready.then(() => setFontsLoaded(true));
    } else setFontsLoaded(true);
  }, []);

  const scrollTriggerStart = useMemo(() => {
    const startPct = (1 - threshold) * 100;
    const mm = /^(-?\d+(?:\.\d+)?)(px|em|rem|%)?$/.exec(rootMargin || '');
    const mv = mm ? parseFloat(mm[1]) : 0;
    const mu = mm ? mm[2] || 'px' : 'px';
    const sign = mv === 0 ? '' : mv < 0 ? `-=${Math.abs(mv)}${mu}` : `+=${mv}${mu}`;
    return `top ${startPct}%${sign}`;
  }, [threshold, rootMargin]);

  useGSAP(
    () => {
      if (!ref.current || !text || !fontsLoaded) return;
      if (respectReducedMotion && window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
        onShuffleComplete?.();
        return;
      }

      const el = ref.current as HTMLElement;
      const start = scrollTriggerStart;

      const removeHover = () => {
        if (hoverHandlerRef.current && ref.current) {
          ref.current.removeEventListener('mouseenter', hoverHandlerRef.current);
          hoverHandlerRef.current = null;
        }
      };

      const teardown = () => {
        if (tlRef.current) {
          tlRef.current.kill();
          tlRef.current = null;
        }
        if (wrappersRef.current.length) {
          wrappersRef.current.forEach(wrap => {
            const inner = wrap.firstElementChild as HTMLElement | null;
            const orig = inner?.querySelector('[data-orig="1"]') as HTMLElement | null;
            if (orig && wrap.parentNode) wrap.parentNode.replaceChild(orig, wrap);
          });
          wrappersRef.current = [];
        }
        try {
          splitRef.current?.revert();
        } catch {}
        splitRef.current = null;
        playingRef.current = false;
      };

      const build = () => {
        teardown();

        const computedFont = getComputedStyle(el).fontFamily;

        splitRef.current = new GSAPSplitText(el, {
          type: 'chars',
          charsClass: 'shuffle-char',
          wordsClass: 'shuffle-word',
          linesClass: 'shuffle-line',
          smartWrap: true,
          reduceWhiteSpace: false
        });

        const chars = (splitRef.current.chars || []) as HTMLElement[];
        wrappersRef.current = [];

        const rolls = Math.max(1, Math.floor(shuffleTimes));
        const rand = (set: string) => set.charAt(Math.floor(Math.random() * set.length)) || '';

        chars.forEach(ch => {
          const parent = ch.parentElement;
          if (!parent) return;

          const w = ch.getBoundingClientRect().width;
          const h = ch.getBoundingClientRect().height;
          if (!w) return;

          const wrap = document.createElement('span');
          wrap.className = 'inline-block overflow-hidden text-left';
          Object.assign(wrap.style, {
            width: w + 'px',
            height: shuffleDirection === 'up' || shuffleDirection === 'down' ? h + 'px' : 'auto',
            verticalAlign: 'bottom'
          });

          const inner = document.createElement('span');
          inner.className =
            'inline-block will-change-transform origin-left transform-gpu ' +
            (shuffleDirection === 'up' || shuffleDirection === 'down' ? 'whitespace-normal' : 'whitespace-nowrap');

          parent.insertBefore(wrap, ch);
          wrap.appendChild(inner);

          const firstOrig = ch.cloneNode(true) as HTMLElement;
          firstOrig.className =
            'text-left ' + (shuffleDirection === 'up' || shuffleDirection === 'down' ? 'block' : 'inline-block');
          Object.assign(firstOrig.style, { width: w + 'px', fontFamily: computedFont });

          ch.setAttribute('data-orig', '1');
          ch.className =
            'text-left ' + (shuffleDirection === 'up' || shuffleDirection === 'down' ? 'block' : 'inline-block');
          Object.assign(ch.style, { width: w + 'px', fontFamily: computedFont });

          inner.appendChild(firstOrig);
          for (let k = 0; k < rolls; k++) {
            const c = ch.cloneNode(true) as HTMLElement;
            if (scrambleCharset) c.textContent = rand(scrambleCharset);
            c.className =
              'text-left ' + (shuffleDirection === 'up' || shuffleDirection === 'down' ? 'block' : 'inline-block');
            Object.assign(c.style, { width: w + 'px', fontFamily: computedFont });
            inner.appendChild(c);
          }
          inner.appendChild(ch);

          const steps = rolls + 1;

          if (shuffleDirection === 'right' || shuffleDirection === 'down') {
            const firstCopy = inner.firstElementChild as HTMLElement | null;
            const real = inner.lastElementChild as HTMLElement | null;
            if (real) inner.insertBefore(real, inner.firstChild);
            if (firstCopy) inner.appendChild(firstCopy);
          }

          let startX = 0;
          let finalX = 0;
          let startY = 0;
          let finalY = 0;

          if (shuffleDirection === 'right') {
            startX = -steps * w;
            finalX = 0;
          } else if (shuffleDirection === 'left') {
            startX = 0;
            finalX = -steps * w;
          } else if (shuffleDirection === 'down') {
            startY = -steps * h;
            finalY = 0;
          } else if (shuffleDirection === 'up') {
            startY = 0;
            finalY = -steps * h;
          }

          if (shuffleDirection === 'left' || shuffleDirection === 'right') {
            gsap.set(inner, { x: startX, y: 0, force3D: true });
            inner.setAttribute('data-start-x', String(startX));
            inner.setAttribute('data-final-x', String(finalX));
          } else {
            gsap.set(inner, { x: 0, y: startY, force3D: true });
            inner.setAttribute('data-start-y', String(startY));
            inner.setAttribute('data-final-y', String(finalY));
          }

          if (colorFrom) (inner.style as any).color = colorFrom;
          wrappersRef.current.push(wrap);
        });
      };

      const inners = () => wrappersRef.current.map(w => w.firstElementChild as HTMLElement);

      const randomizeScrambles = () => {
        if (!scrambleCharset) return;
        wrappersRef.current.forEach(w => {
          const strip = w.firstElementChild as HTMLElement;
          if (!strip) return;
          const kids = Array.from(strip.children) as HTMLElement[];
          for (let i = 1; i < kids.length - 1; i++) {
            kids[i].textContent = scrambleCharset.charAt(Math.floor(Math.random() * scrambleCharset.length));
          }
        });
      };

      const cleanupToStill = () => {
        wrappersRef.current.forEach(w => {
          const strip = w.firstElementChild as HTMLElement;
          if (!strip) return;
          const real = strip.querySelector('[data-orig="1"]') as HTMLElement | null;
          if (!real) return;
          strip.replaceChildren(real);
          strip.style.transform = 'none';
          strip.style.willChange = 'auto';
        });
      };

      const play = () => {
        const strips = inners();
        if (!strips.length) return;

        playingRef.current = true;
        const isVertical = shuffleDirection === 'up' || shuffleDirection === 'down';

        const tl = gsap.timeline({
          smoothChildTiming: true,
          repeat: loop ? -1 : 0,
          repeatDelay: loop ? loopDelay : 0,
          onRepeat: () => {
            if (scrambleCharset) randomizeScrambles();
            if (isVertical) {
              gsap.set(strips, { y: (i, t: HTMLElement) => parseFloat(t.getAttribute('data-start-y') || '0') });
            } else {
              gsap.set(strips, { x: (i, t: HTMLElement) => parseFloat(t.getAttribute('data-start-x') || '0') });
            }
            onShuffleComplete?.();
          },
          onComplete: () => {
            playingRef.current = false;
            if (!loop) {
              cleanupToStill();
              if (colorTo) gsap.set(strips, { color: colorTo });
              onShuffleComplete?.();
              armHover();
            }
          }
        });

        const addTween = (targets: HTMLElement[], at: number) => {
          const vars: any = {
            duration,
            ease,
            force3D: true,
            stagger: animationMode === 'evenodd' ? stagger : 0
          };
          if (isVertical) {
            vars.y = (i: number, t: HTMLElement) => parseFloat(t.getAttribute('data-final-y') || '0');
          } else {
            vars.x = (i: number, t: HTMLElement) => parseFloat(t.getAttribute('data-final-x') || '0');
          }

          tl.to(targets, vars, at);

          if (colorFrom && colorTo) tl.to(targets, { color: colorTo, duration, ease }, at);
        };

        if (animationMode === 'evenodd') {
          const odd = strips.filter((_, i) => i % 2 === 1);
          const even = strips.filter((_, i) => i % 2 === 0);
          const oddTotal = duration + Math.max(0, odd.length - 1) * stagger;
          const evenStart = odd.length ? oddTotal * 0.7 : 0;
          if (odd.length) addTween(odd, 0);
          if (even.length) addTween(even, evenStart);
        } else {
          strips.forEach(strip => {
            const d = Math.random() * maxDelay;
            const vars: any = {
              duration,
              ease,
              force3D: true
            };
            if (isVertical) {
              vars.y = parseFloat(strip.getAttribute('data-final-y') || '0');
            } else {
              vars.x = parseFloat(strip.getAttribute('data-final-x') || '0');
            }
            tl.to(strip, vars, d);
            if (colorFrom && colorTo) tl.fromTo(strip, { color: colorFrom }, { color: colorTo, duration, ease }, d);
          });
        }

        tlRef.current = tl;
      };

      const armHover = () => {
        if (!triggerOnHover || !ref.current) return;
        removeHover();
        const handler = () => {
          if (playingRef.current) return;
          build();
          if (scrambleCharset) randomizeScrambles();
          play();
        };
        hoverHandlerRef.current = handler;
        ref.current.addEventListener('mouseenter', handler);
      };

      const create = () => {
        build();
        if (scrambleCharset) randomizeScrambles();
        play();
        armHover();
        setReady(true);
      };

      const st = ScrollTrigger.create({
        trigger: el,
        start,
        once: triggerOnce,
        onEnter: create
      });

      return () => {
        st.kill();
        removeHover();
        teardown();
        setReady(false);
      };
    },
    {
      dependencies: [
        text,
        duration,
        maxDelay,
        ease,
        scrollTriggerStart,
        fontsLoaded,
        shuffleDirection,
        shuffleTimes,
        animationMode,
        loop,
        loopDelay,
        stagger,
        scrambleCharset,
        colorFrom,
        colorTo,
        triggerOnce,
        respectReducedMotion,
        triggerOnHover,
        onShuffleComplete
      ],
      scope: ref
    }
  );

  const baseTw = 'inline-block whitespace-normal break-words will-change-transform uppercase text-2xl leading-none';
  const userHasFont = useMemo(() => className && /font[-[]/i.test(className), [className]);

  const fallbackFont = useMemo(
    () => (userHasFont ? {} : { fontFamily: `'Press Start 2P', sans-serif` }),
    [userHasFont]
  );

  const commonStyle = useMemo(
    () => ({
      textAlign,
      ...fallbackFont,
      ...style
    }),
    [textAlign, fallbackFont, style]
  );

  const classes = useMemo(
    () => `${baseTw} ${ready ? 'visible' : 'invisible'} ${className}`.trim(),
    [baseTw, ready, className]
  );
  const Tag = (tag || 'p') as keyof JSX.IntrinsicElements;

  return React.createElement(Tag, { ref: ref as any, className: classes, style: commonStyle }, text);
};

export default Shuffle;


--- FILE: frontend-web/registry/text_effects/Split Text.tsx ---

import React, { useRef, useEffect, useState } from 'react';
import { gsap } from 'gsap';
import { ScrollTrigger } from 'gsap/ScrollTrigger';
import { SplitText as GSAPSplitText } from 'gsap/SplitText';
import { useGSAP } from '@gsap/react';

gsap.registerPlugin(ScrollTrigger, GSAPSplitText, useGSAP);

export interface SplitTextProps {
  text: string;
  className?: string;
  delay?: number;
  duration?: number;
  ease?: string | ((t: number) => number);
  splitType?: 'chars' | 'words' | 'lines' | 'words, chars';
  from?: gsap.TweenVars;
  to?: gsap.TweenVars;
  threshold?: number;
  rootMargin?: string;
  tag?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p' | 'span';
  textAlign?: React.CSSProperties['textAlign'];
  onLetterAnimationComplete?: () => void;
}

const SplitText: React.FC<SplitTextProps> = ({
  text,
  className = '',
  delay = 50,
  duration = 1.25,
  ease = 'power3.out',
  splitType = 'chars',
  from = { opacity: 0, y: 40 },
  to = { opacity: 1, y: 0 },
  threshold = 0.1,
  rootMargin = '-100px',
  tag = 'p',
  textAlign = 'center',
  onLetterAnimationComplete
}) => {
  const ref = useRef<HTMLParagraphElement>(null);
  const animationCompletedRef = useRef(false);
  const onCompleteRef = useRef(onLetterAnimationComplete);
  const [fontsLoaded, setFontsLoaded] = useState<boolean>(false);

  // Keep callback ref updated
  useEffect(() => {
    onCompleteRef.current = onLetterAnimationComplete;
  }, [onLetterAnimationComplete]);

  useEffect(() => {
    if (document.fonts.status === 'loaded') {
      setFontsLoaded(true);
    } else {
      document.fonts.ready.then(() => {
        setFontsLoaded(true);
      });
    }
  }, []);

  useGSAP(
    () => {
      if (!ref.current || !text || !fontsLoaded) return;
      // Prevent re-animation if already completed
      if (animationCompletedRef.current) return;
      const el = ref.current as HTMLElement & {
        _rbsplitInstance?: GSAPSplitText;
      };

      if (el._rbsplitInstance) {
        try {
          el._rbsplitInstance.revert();
        } catch (_) {}
        el._rbsplitInstance = undefined;
      }

      const startPct = (1 - threshold) * 100;
      const marginMatch = /^(-?\d+(?:\.\d+)?)(px|em|rem|%)?$/.exec(rootMargin);
      const marginValue = marginMatch ? parseFloat(marginMatch[1]) : 0;
      const marginUnit = marginMatch ? marginMatch[2] || 'px' : 'px';
      const sign =
        marginValue === 0
          ? ''
          : marginValue < 0
            ? `-=${Math.abs(marginValue)}${marginUnit}`
            : `+=${marginValue}${marginUnit}`;
      const start = `top ${startPct}%${sign}`;
      let targets: Element[] = [];
      const assignTargets = (self: GSAPSplitText) => {
        if (splitType.includes('chars') && (self as GSAPSplitText).chars?.length)
          targets = (self as GSAPSplitText).chars;
        if (!targets.length && splitType.includes('words') && self.words.length) targets = self.words;
        if (!targets.length && splitType.includes('lines') && self.lines.length) targets = self.lines;
        if (!targets.length) targets = self.chars || self.words || self.lines;
      };
      const splitInstance = new GSAPSplitText(el, {
        type: splitType,
        smartWrap: true,
        autoSplit: splitType === 'lines',
        linesClass: 'split-line',
        wordsClass: 'split-word',
        charsClass: 'split-char',
        reduceWhiteSpace: false,
        onSplit: (self: GSAPSplitText) => {
          assignTargets(self);
          return gsap.fromTo(
            targets,
            { ...from },
            {
              ...to,
              duration,
              ease,
              stagger: delay / 1000,
              scrollTrigger: {
                trigger: el,
                start,
                once: true,
                fastScrollEnd: true,
                anticipatePin: 0.4
              },
              onComplete: () => {
                animationCompletedRef.current = true;
                onCompleteRef.current?.();
              },
              willChange: 'transform, opacity',
              force3D: true
            }
          );
        }
      });
      el._rbsplitInstance = splitInstance;
      return () => {
        ScrollTrigger.getAll().forEach(st => {
          if (st.trigger === el) st.kill();
        });
        try {
          splitInstance.revert();
        } catch (_) {}
        el._rbsplitInstance = undefined;
      };
    },
    {
      dependencies: [
        text,
        delay,
        duration,
        ease,
        splitType,
        JSON.stringify(from),
        JSON.stringify(to),
        threshold,
        rootMargin,
        fontsLoaded
      ],
      scope: ref
    }
  );

  const renderTag = () => {
    const style: React.CSSProperties = {
      textAlign,
      wordWrap: 'break-word',
      willChange: 'transform, opacity'
    };
    const classes = `split-parent overflow-hidden inline-block whitespace-normal ${className}`;
    const Tag = (tag || 'p') as React.ElementType;

    return (
      <Tag ref={ref} style={style} className={classes}>
        {text}
      </Tag>
    );
  };

  return renderTag();
};

export default SplitText;


--- FILE: frontend-web/registry/text_effects/Text Type.tsx ---

'use client';

import { ElementType, useEffect, useRef, useState, createElement, useMemo, useCallback } from 'react';
import { gsap } from 'gsap';

interface TextTypeProps {
  className?: string;
  showCursor?: boolean;
  hideCursorWhileTyping?: boolean;
  cursorCharacter?: string | React.ReactNode;
  cursorBlinkDuration?: number;
  cursorClassName?: string;
  text: string | string[];
  as?: ElementType;
  typingSpeed?: number;
  initialDelay?: number;
  pauseDuration?: number;
  deletingSpeed?: number;
  loop?: boolean;
  textColors?: string[];
  variableSpeed?: { min: number; max: number };
  onSentenceComplete?: (sentence: string, index: number) => void;
  startOnVisible?: boolean;
  reverseMode?: boolean;
}

const TextType = ({
  text,
  as: Component = 'div',
  typingSpeed = 50,
  initialDelay = 0,
  pauseDuration = 2000,
  deletingSpeed = 30,
  loop = true,
  className = '',
  showCursor = true,
  hideCursorWhileTyping = false,
  cursorCharacter = '|',
  cursorClassName = '',
  cursorBlinkDuration = 0.5,
  textColors = [],
  variableSpeed,
  onSentenceComplete,
  startOnVisible = false,
  reverseMode = false,
  ...props
}: TextTypeProps & React.HTMLAttributes<HTMLElement>) => {
  const [displayedText, setDisplayedText] = useState('');
  const [currentCharIndex, setCurrentCharIndex] = useState(0);
  const [isDeleting, setIsDeleting] = useState(false);
  const [currentTextIndex, setCurrentTextIndex] = useState(0);
  const [isVisible, setIsVisible] = useState(!startOnVisible);
  const cursorRef = useRef<HTMLSpanElement>(null);
  const containerRef = useRef<HTMLElement>(null);

  const textArray = useMemo(() => (Array.isArray(text) ? text : [text]), [text]);

  const getRandomSpeed = useCallback(() => {
    if (!variableSpeed) return typingSpeed;
    const { min, max } = variableSpeed;
    return Math.random() * (max - min) + min;
  }, [variableSpeed, typingSpeed]);

  const getCurrentTextColor = () => {
    if (textColors.length === 0) return 'inherit';
    return textColors[currentTextIndex % textColors.length];
  };

  useEffect(() => {
    if (!startOnVisible || !containerRef.current) return;

    const observer = new IntersectionObserver(
      entries => {
        entries.forEach(entry => {
          if (entry.isIntersecting) {
            setIsVisible(true);
          }
        });
      },
      { threshold: 0.1 }
    );

    observer.observe(containerRef.current);
    return () => observer.disconnect();
  }, [startOnVisible]);

  useEffect(() => {
    if (showCursor && cursorRef.current) {
      gsap.set(cursorRef.current, { opacity: 1 });
      gsap.to(cursorRef.current, {
        opacity: 0,
        duration: cursorBlinkDuration,
        repeat: -1,
        yoyo: true,
        ease: 'power2.inOut'
      });
    }
  }, [showCursor, cursorBlinkDuration]);

  useEffect(() => {
    if (!isVisible) return;

    let timeout: ReturnType<typeof setTimeout>;

    const currentText = textArray[currentTextIndex];
    const processedText = reverseMode ? currentText.split('').reverse().join('') : currentText;

    const executeTypingAnimation = () => {
      if (isDeleting) {
        if (displayedText === '') {
          setIsDeleting(false);
          if (currentTextIndex === textArray.length - 1 && !loop) {
            return;
          }

          if (onSentenceComplete) {
            onSentenceComplete(textArray[currentTextIndex], currentTextIndex);
          }

          setCurrentTextIndex(prev => (prev + 1) % textArray.length);
          setCurrentCharIndex(0);
          timeout = setTimeout(() => {}, pauseDuration);
        } else {
          timeout = setTimeout(() => {
            setDisplayedText(prev => prev.slice(0, -1));
          }, deletingSpeed);
        }
      } else {
        if (currentCharIndex < processedText.length) {
          timeout = setTimeout(
            () => {
              setDisplayedText(prev => prev + processedText[currentCharIndex]);
              setCurrentCharIndex(prev => prev + 1);
            },
            variableSpeed ? getRandomSpeed() : typingSpeed
          );
        } else if (textArray.length >= 1) {
          if (!loop && currentTextIndex === textArray.length - 1) return;
          timeout = setTimeout(() => {
            setIsDeleting(true);
          }, pauseDuration);
        }
      }
    };

    if (currentCharIndex === 0 && !isDeleting && displayedText === '') {
      timeout = setTimeout(executeTypingAnimation, initialDelay);
    } else {
      executeTypingAnimation();
    }

    return () => clearTimeout(timeout);
  }, [
    currentCharIndex,
    displayedText,
    isDeleting,
    typingSpeed,
    deletingSpeed,
    pauseDuration,
    textArray,
    currentTextIndex,
    loop,
    initialDelay,
    isVisible,
    reverseMode,
    variableSpeed,
    onSentenceComplete
  ]);

  const shouldHideCursor =
    hideCursorWhileTyping && (currentCharIndex < textArray[currentTextIndex].length || isDeleting);

  return createElement(
    Component,
    {
      ref: containerRef,
      className: `inline-block whitespace-pre-wrap tracking-tight ${className}`,
      ...props
    },
    <span className="inline" style={{ color: getCurrentTextColor() || 'inherit' }}>
      {displayedText}
    </span>,
    showCursor && (
      <span
        ref={cursorRef}
        className={`ml-1 inline-block opacity-100 ${shouldHideCursor ? 'hidden' : ''} ${cursorClassName}`}
      >
        {cursorCharacter}
      </span>
    )
  );
};

export default TextType;


--- FILE: frontend-web/registry/text_effects/UnderlineAnimation.tsx ---

import React, { useEffect, useRef, useState } from "react";
import { motion, useAnimationControls, type Transition } from "framer-motion";
import { cn } from "../core/utils";

interface UnderlineBaseProps {
  label: string;
  className?: string;
  onClick?: () => void;
  underlineHeightRatio?: number;
  underlinePaddingRatio?: number;
  transition?: Transition;
}

interface DirectionalUnderlineProps extends UnderlineBaseProps {
  direction?: "left" | "right";
}

// Center Underline
export function CenterUnderline({
  label,
  className,
  onClick,
  transition = { duration: 0.25, ease: "easeInOut" },
  underlineHeightRatio = 0.1,
  underlinePaddingRatio = 0.01,
  ...props
}: UnderlineBaseProps) {
  const textRef = useRef<HTMLSpanElement>(null);

  useEffect(() => {
    const updateUnderlineStyles = () => {
      if (textRef.current) {
        const fontSize = parseFloat(getComputedStyle(textRef.current).fontSize);
        const underlineHeight = fontSize * underlineHeightRatio;
        const underlinePadding = fontSize * underlinePaddingRatio;
        textRef.current.style.setProperty(
          "--underline-height",
          `${underlineHeight}px`
        );
        textRef.current.style.setProperty(
          "--underline-padding",
          `${underlinePadding}px`
        );
      }
    };

    updateUnderlineStyles();
    window.addEventListener("resize", updateUnderlineStyles);

    return () => window.removeEventListener("resize", updateUnderlineStyles);
  }, [underlineHeightRatio, underlinePaddingRatio]);

  return (
    <motion.span
      className={cn("relative inline-block cursor-pointer", className)}
      whileHover="visible"
      onClick={onClick}
      ref={textRef}
      {...props}
    >
      <span>{label}</span>
      <motion.div
        className="absolute left-1/2 bg-current -translate-x-1/2"
        style={{
          height: "var(--underline-height)",
          bottom: "calc(-1 * var(--underline-padding))",
        }}
        variants={{
          hidden: {
            width: 0,
            originX: 0.5,
          },
          visible: {
            width: "100%",
            transition: transition as any,
          },
        }}
      />
    </motion.span>
  );
}

// Comes In Goes Out Underline
export function ComesInGoesOutUnderline({
  label,
  direction = "left",
  className,
  onClick,
  underlineHeightRatio = 0.1,
  underlinePaddingRatio = 0.01,
  transition = {
    duration: 0.4,
    ease: "easeInOut",
  },
  ...props
}: DirectionalUnderlineProps) {
  const controls = useAnimationControls();
  const [blocked, setBlocked] = useState(false);
  const textRef = useRef<HTMLSpanElement>(null);

  useEffect(() => {
    const updateUnderlineStyles = () => {
      if (textRef.current) {
        const fontSize = parseFloat(getComputedStyle(textRef.current).fontSize);
        const underlineHeight = fontSize * underlineHeightRatio;
        const underlinePadding = fontSize * underlinePaddingRatio;
        textRef.current.style.setProperty(
          "--underline-height",
          `${underlineHeight}px`
        );
        textRef.current.style.setProperty(
          "--underline-padding",
          `${underlinePadding}px`
        );
      }
    };

    updateUnderlineStyles();
    window.addEventListener("resize", updateUnderlineStyles);

    return () => window.removeEventListener("resize", updateUnderlineStyles);
  }, [underlineHeightRatio, underlinePaddingRatio]);

  const animate = async () => {
    if (blocked) return;

    setBlocked(true);

    await controls.start({
      width: "100%",
      transition,
      transitionEnd: {
        left: direction === "left" ? "auto" : 0,
        right: direction === "left" ? 0 : "auto",
      },
    });

    await controls.start({
      width: 0,
      transition,
      transitionEnd: {
        left: direction === "left" ? 0 : "",
        right: direction === "left" ? "" : 0,
      },
    });

    setBlocked(false);
  };

  return (
    <motion.span
      className={cn("relative inline-block cursor-pointer", className)}
      onHoverStart={animate}
      onClick={onClick}
      ref={textRef}
      {...props}
    >
      <span>{label}</span>
      <motion.span
        className={cn("absolute bg-current w-0", {
          "left-0": direction === "left",
          "right-0": direction === "right",
        })}
        style={{
          height: "var(--underline-height)",
          bottom: "calc(-1 * var(--underline-padding))",
        }}
        animate={controls}
      />
    </motion.span>
  );
}

// Goes Out Comes In Underline
export function GoesOutComesInUnderline({
  label,
  direction = "left",
  className,
  onClick,
  underlineHeightRatio = 0.1,
  underlinePaddingRatio = 0.01,
  transition = {
    duration: 0.5,
    ease: "easeOut",
  },
  ...props
}: DirectionalUnderlineProps) {
  const controls = useAnimationControls();
  const [blocked, setBlocked] = useState(false);
  const textRef = useRef<HTMLSpanElement>(null);

  useEffect(() => {
    const updateUnderlineStyles = () => {
      if (textRef.current) {
        const fontSize = parseFloat(getComputedStyle(textRef.current).fontSize);
        const underlineHeight = fontSize * underlineHeightRatio;
        const underlinePadding = fontSize * underlinePaddingRatio;
        textRef.current.style.setProperty(
          "--underline-height",
          `${underlineHeight}px`
        );
        textRef.current.style.setProperty(
          "--underline-padding",
          `${underlinePadding}px`
        );
      }
    };

    updateUnderlineStyles();
    window.addEventListener("resize", updateUnderlineStyles);

    return () => window.removeEventListener("resize", updateUnderlineStyles);
  }, [underlineHeightRatio, underlinePaddingRatio]);

  const animate = async () => {
    if (blocked) return;

    setBlocked(true);

    await controls.start({
      width: 0,
      transition,
      transitionEnd: {
        left: direction === "left" ? "auto" : 0,
        right: direction === "left" ? 0 : "auto",
      },
    });

    await controls.start({
      width: "100%",
      transition,
      transitionEnd: {
        left: direction === "left" ? 0 : "",
        right: direction === "left" ? "" : 0,
      },
    });

    setBlocked(false);
  };

  return (
    <motion.span
      className={cn("relative inline-block cursor-pointer", className)}
      onHoverStart={animate}
      onClick={onClick}
      ref={textRef}
      {...props}
    >
      <span className="sr-only">{label}</span>
      <span aria-hidden="true">{label}</span>
      <motion.span
        className={cn("absolute bg-current", {
          "left-0": direction === "left",
          "right-0": direction === "right",
        })}
        style={{
          height: "var(--underline-height)",
          bottom: "calc(-1 * var(--underline-padding))",
          width: "100%",
        }}
        animate={controls}
        aria-hidden="true"
      />
    </motion.span>
  );
}

--- FILE: frontend-web/ui-ux-pro-max/scripts/core.py ---

import csv
import os
import math
import re
from collections import Counter

class BM25:
    """Lightweight BM25 Search Engine in pure Python."""
    def __init__(self, corpus, k1=1.5, b=0.75):
        self.corpus = corpus
        self.k1 = k1
        self.b = b
        self.doc_len = [len(doc) for doc in corpus]
        self.avgdl = sum(self.doc_len) / len(corpus) if corpus else 0
        self.df = Counter()
        for doc in corpus:
            self.df.update(set(doc))
        self.idf = {}
        N = len(corpus)
        for word, freq in self.df.items():
            self.idf[word] = math.log(1 + (N - freq + 0.5) / (freq + 0.5))

    def get_scores(self, query):
        scores = [0] * len(self.corpus)
        for q in query:
            if q not in self.df:
                continue
            idf = self.idf[q]
            for i, doc in enumerate(self.corpus):
                tf = doc.count(q)
                if tf == 0:
                    continue
                score = idf * (tf * (self.k1 + 1)) / (tf + self.k1 * (1 - self.b + self.b * self.doc_len[i] / self.avgdl))
                scores[i] += score
        return scores

def tokenize(text):
    if not text:
        return []
    return re.findall(r'\w+', text.lower())

def load_csv(filename):
    base_dir = os.path.dirname(os.path.dirname(__file__))
    filepath = os.path.join(base_dir, "data", filename)
    if not os.path.exists(filepath):
        return []
    with open(filepath, "r", encoding="utf-8") as f:
        reader = csv.DictReader(f)
        return list(reader)

def search_csv(filename, query_text, search_columns):
    rows = load_csv(filename)
    if not rows: return {}
    corpus = []
    for r in rows:
        doc = " ".join(str(r.get(col, "")) for col in search_columns)
        corpus.append(tokenize(doc))
    bm25 = BM25(corpus)
    scores = bm25.get_scores(tokenize(query_text))
    if not scores or max(scores) == 0:
        return rows[0]
    return rows[scores.index(max(scores))]

--- FILE: frontend-web/ui-ux-pro-max/scripts/design_system.py ---

def generate_design_system_md(domain_data, style_data, color_data, typo_data):
    md = []
    domain_name = domain_data.get('Product Type', 'Business').title()
    
    md.append(f"## Authoritative Design System: {domain_name}")
    md.append(f"**Key Considerations**: {domain_data.get('Key Considerations', 'Professional, Clean')}")
    md.append(f"**Aesthetic Style**: {style_data.get('Style Category', 'Minimalist')}")
    
    md.append("\n### 1. Typography System")
    md.append(f"- **Heading Font**: {typo_data.get('Heading Font', 'Inter')}")
    md.append(f"- **Body Font**: {typo_data.get('Body Font', 'Inter')}")
    md.append(f"- **Type Scale & Rules**: {typo_data.get('Notes', 'Use bold headings and legible body text.')}")
    
    md.append("\n### 2. Color Palette (Tailwind / Tokens)")
    md.append(f"- **Primary**: {color_data.get('Primary', '#000000')}")
    md.append(f"- **Secondary**: {color_data.get('Secondary', '#4A4A4A')}")
    md.append(f"- **Accent**: {color_data.get('Accent', '#3B82F6')}")
    md.append(f"- **Background**: {color_data.get('Background', '#FFFFFF')}")
    md.append(f"- **Surface/Cards**: {color_data.get('Card', '#F3F4F6')}")
    md.append(f"- **Text**: {color_data.get('Foreground', '#111827')}")
    
    md.append("\n### 3. Structural & Layout Rules")
    md.append(f"- {style_data.get('Implementation Checklist', '')}")
    
    md.append("\n### 4. Animation & Interaction")
    md.append(f"- {style_data.get('Effects & Animation', 'Smooth, subtle transitions.')}")
    
    md.append("\n### 5. Domain-Specific Anti-Patterns (NEVER DO THESE)")
    md.append(f"- [X] {style_data.get('Do Not Use For', '')}")
                
    return "\n".join(md)

--- FILE: frontend-web/ui-ux-pro-max/scripts/search.py ---

import sys
import argparse
import os

# Force UTF-8 encoding for stdout to prevent Windows cp1252 crash
if hasattr(sys.stdout, 'reconfigure'):
    sys.stdout.reconfigure(encoding='utf-8')

# Add current directory to path so imports work correctly when called as a subprocess
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))

from core import search_csv
from design_system import generate_design_system_md

def main():
    parser = argparse.ArgumentParser(description="UI-UX-PRO-MAX Intelligence Engine")
    parser.add_argument("query", type=str, help="The business domain or description to search for")
    parser.add_argument("--design-system", action="store_true", help="Format output as a full design system")
    parser.add_argument("-f", "--format", type=str, default="markdown", choices=["markdown"], help="Output format")
    
    args = parser.parse_args()
    
    # 1. Product / Industry
    domain_data = search_csv("products.csv", args.query, ["Product Type", "Keywords", "Key Considerations"])
    if not domain_data:
        print("No design intelligence found. Ensure data CSVs exist.", file=sys.stderr)
        sys.exit(1)
        
    # 2. Styles
    style_query = args.query + " " + domain_data.get("Primary Style Recommendation", "")
    style_data = search_csv("styles.csv", style_query, ["Style Category", "Keywords", "Best For"])
    
    # 3. Colors
    color_query = args.query + " " + domain_data.get("Color Palette Focus", "") + " " + domain_data.get("Product Type", "")
    color_data = search_csv("colors.csv", color_query, ["Product Type", "Notes", "Primary"])
    
    # 4. Typography
    typo_query = args.query + " " + domain_data.get("Product Type", "")
    typo_data = search_csv("typography.csv", typo_query, ["Category", "Mood/Style Keywords", "Best For"])
    
    if args.design_system and args.format == "markdown":
        md_output = generate_design_system_md(domain_data, style_data, color_data, typo_data)
        print(md_output)
    else:
        # Fallback raw output
        print(f"Matched Domain: {domain_data.get('domain')}")

if __name__ == "__main__":
    main()

--- FILE: frontend-web/Vite_pipeline/__init__.py ---



--- FILE: frontend-web/Vite_pipeline/pipeline.py ---

import os
import subprocess
import shutil
import sys
import time

# Unix-only imports
if sys.platform != "win32":
    import pty
    import select
    import termios
    import struct
    import fcntl
    import tty

def set_winsize(fd):
    if sys.platform == "win32":
        return
    """Synchronizes the PTY window size with the real terminal."""
    try:
        # Get real terminal size
        h, w, hp, wp = struct.unpack('HHHH', fcntl.ioctl(sys.stdin.fileno(), termios.TIOCGWINSZ, struct.pack('HHHH', 0, 0, 0, 0)))
        # Set PTY slave size
        fcntl.ioctl(fd, termios.TIOCSWINSZ, struct.pack('HHHH', h, w, hp, wp))
    except Exception:
        pass

def run_vite_pipeline(interface):
    # 1. Check Node
    npm_path = shutil.which('npm') or (shutil.which('npm.cmd') if sys.platform == "win32" else None)
    if not npm_path:
        interface.print("[bold red]Error: NPM not found. Please install Node.js.[/bold red]")
        return None

    interface.print("[bold cyan]>> Launching interactive Vite Scaffolding...[/bold cyan]")
    
    # Global warning for all OS types
    interface.print("\n[bold yellow]⚠️ IMPORTANT: If Vite asks 'Install and start now?', select 'No' so NOVA can continue.[/bold yellow]\n")
    
    # --- WINDOWS RUNNER ---
    if sys.platform == "win32":
        try:
            # Windows terminal handles interactive sub-processes naturally
            subprocess.run("npm create vite@latest", shell=True, check=True)
            found_localhost = False
        except KeyboardInterrupt:
            # Catch Ctrl+C here if the user accidentally starts the server, so it doesn't kill NOVA
            interface.print("\n[dim]>> Server interrupted. Resuming NOVA pipeline...[/dim]")
            found_localhost = True
        except Exception as e:
            interface.print(f"[red]Error: Vite scaffolding failed: {e}[/red]")
            return None

    # --- UNIX RUNNER ---
    else:
        cmd = ["npm", "create", "vite@latest"]
        
        # Save original terminal settings to restore later
        old_tty = termios.tcgetattr(sys.stdin)
        interrupted = False
        
        try:
            master_fd, slave_fd = pty.openpty()
            
            # Set the PTY window size before starting the process
            set_winsize(slave_fd)
            
            process = subprocess.Popen(
                cmd,
                stdin=slave_fd,
                stdout=slave_fd,
                stderr=slave_fd,
                text=True,
                close_fds=True
            )
            os.close(slave_fd)

            # Set real terminal to raw mode to pass through all keystrokes (arrows, etc.)
            tty.setraw(sys.stdin.fileno())

            found_localhost = False
            output_buffer = ""

            try:
                while process.poll() is None:
                    r, w, e = select.select([master_fd, sys.stdin], [], [], 0.1)
                    
                    if master_fd in r:
                        data = os.read(master_fd, 1024).decode(errors='ignore')
                        if data:
                            output_buffer += data
                            sys.stdout.write(data)
                            sys.stdout.flush()
                            
                            if "localhost:" in output_buffer or "127.0.0.1:" in output_buffer:
                                found_localhost = True
                                time.sleep(1.0)
                                process.terminate()
                                break
                    
                    if sys.stdin in r:
                        user_input = os.read(sys.stdin.fileno(), 1024)
                        if user_input:
                            os.write(master_fd, user_input)
            except KeyboardInterrupt:
                # Catch Ctrl+C safely inside the raw terminal loop
                interrupted = True
                found_localhost = True
                process.terminate()

        finally:
            # ALWAYS restore terminal settings even if it crashes
            termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_tty)
            try:
                os.close(master_fd)
            except Exception:
                pass
            # Final terminal reset
            os.system('stty sane')
            
        if interrupted:
            interface.print("\n[dim]>> Server interrupted. Resuming NOVA pipeline...[/dim]")

    interface.print("\n[bold yellow]Vite session finished.[/bold yellow]")
    
    print("\033[1;36mConfirm the project folder name created > \033[0m", end="", flush=True)
    project_name = sys.stdin.readline().strip()
    
    if not project_name: 
        return None
    
    target_dir = os.path.abspath(os.path.join(os.getcwd(), project_name))
    
    if not os.path.exists(target_dir):
        interface.print(f"[red]Error: Folder '{project_name}' not found.[/red]")
        return None

    npx_cmd = "npx.cmd" if sys.platform == "win32" else "npx"
    npm_cmd = "npm.cmd" if sys.platform == "win32" else "npm"

    if not found_localhost:
        with interface.create_loader(f"Running npm install in {project_name}..."):
            subprocess.run(f"{npm_cmd} install", cwd=target_dir, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
    
    # Execute Post-Scaffold automated Tailwind steps silently
    try:
        with interface.create_loader("Initializing TailwindCSS + PostCSS (v3 Locked for AI Compatibility)..."):
            # Lock to Tailwind v3.4 to guarantee compatibility with LLM-generated tailwind.config.js
            subprocess.run(f"{npm_cmd} install -D tailwindcss@^3.4.17 postcss autoprefixer", cwd=target_dir, shell=True, check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
            
            # 1. Aggressively wipe out all default CSS and SVG junk across ANY framework
            src_dir = os.path.join(target_dir, "src")
            if os.path.exists(src_dir):
                for file in os.listdir(src_dir):
                    if file.endswith(".css") or file.endswith(".svg"):
                        os.remove(os.path.join(src_dir, file))
            
            assets_dir = os.path.join(src_dir, "assets")
            if os.path.exists(assets_dir):
                for file in os.listdir(assets_dir):
                    if file.endswith(".svg"):
                        os.remove(os.path.join(assets_dir, file))
                        
            public_vite_svg = os.path.join(target_dir, "public", "vite.svg")
            if os.path.exists(public_vite_svg):
                os.remove(public_vite_svg)

            # 2. Unconditionally write the Tailwind base to index.css
            css_path = os.path.join(src_dir, "index.css")
            with open(css_path, "w") as f:
                f.write("@tailwind base;\n@tailwind components;\n@tailwind utilities;\n")
            
            # 3. Create postcss.config.js directly (Standard v3 format)
            postcss_config_path = os.path.join(target_dir, "postcss.config.js")
            with open(postcss_config_path, "w") as f:
                f.write('export default {\n  plugins: {\n    tailwindcss: {},\n    autoprefixer: {},\n  },\n}')
            
            # 4. Create tailwind.config.js directly (covering React, Vue, Svelte, etc.)
            tailwind_config_path = os.path.join(target_dir, "tailwind.config.js")
            with open(tailwind_config_path, "w") as f:
                f.write('''/** @type {import('tailwindcss').Config} */\nexport default {\n  content: [\n    "./index.html",\n    "./src/**/*.{js,ts,jsx,tsx,vue,svelte}",\n  ],\n  theme: {\n    extend: {},\n  },\n  plugins: [],\n}''')
                    
        interface.print("[bold green]✔ Vite + Tailwind Scaffold Complete![/bold green]")
        
    except Exception as e:
        interface.print(f"[red]Error during Tailwind setup: {e}[/red]")

    return target_dir