aiplang 2.11.6 → 2.11.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/aiplang.js CHANGED
@@ -5,7 +5,7 @@ const fs = require('fs')
5
5
  const path = require('path')
6
6
  const http = require('http')
7
7
 
8
- const VERSION = '2.11.6'
8
+ const VERSION = '2.11.8'
9
9
  const RUNTIME_DIR = path.join(__dirname, '..', 'runtime')
10
10
  const cmd = process.argv[2]
11
11
  const args = process.argv.slice(3)
@@ -686,7 +686,7 @@ function generateTypes(app, srcFile) {
686
686
  }
687
687
 
688
688
  lines.push(`// ── aiplang version ──────────────────────────────────────────`)
689
- lines.push(`export const AIPLANG_VERSION = '2.11.6'`)
689
+ lines.push(`export const AIPLANG_VERSION = '2.11.8'`)
690
690
  lines.push(``)
691
691
  return lines.join('\n')
692
692
  }
@@ -1044,6 +1044,11 @@ function parseBlock(line) {
1044
1044
  if(line.startsWith('benchmark{')) { const m=line.match(/^benchmark\{([^}]*)\}/);if(m){const vm=line.match(/variant:(\S+)/);const am=line.match(/animate:(\S+)/);return{kind:'benchmark',items:m[1].split('|').map(it=>{const p=it.trim().split(':');return{num:p[0]?.trim(),label:p[1]?.trim(),vs:p[2]?.trim(),pct:parseInt(p[3])||0}}),variant:vm?.[1],animate:am?.[1]}} }
1045
1045
  if(line.startsWith('install{')) { const m=line.match(/^install\{([^}]*)\}/);if(m){const vm=line.match(/variant:(\S+)/);return{kind:'install',cmds:m[1].split('|').map(c=>c.trim()).filter(Boolean),variant:vm?.[1]}} }
1046
1046
  if(line.startsWith('feature{')) { const b=parseBlock(line.replace(/^feature/,'row3'));if(b){b.variant='feature'};return b }
1047
+ if(line.startsWith('marquee{')) { const m=line.match(/^marquee\{([^}]*)\}/);if(m){const vm=line.match(/variant:(\S+)/);return{kind:'marquee',items:m[1].split('|').map(s=>s.trim()).filter(Boolean),variant:vm?.[1]}} }
1048
+ if(line.startsWith('cta{')) { const m=line.match(/^cta\{([^}]*)\}/);if(m){const pts=m[1].split('|');let t='',s='',links=[];pts.forEach(p=>{const lm=p.match(/^([^>]+)>([^>]+)$/);if(lm)links.push({label:lm[1].trim(),path:lm[2].trim()});else if(!t)t=p.trim();else s=p.trim()});const vm=line.match(/variant:(\S+)/);return{kind:'cta',title:t,sub:s,links,variant:vm?.[1]}} }
1049
+ if(line.startsWith('steps{')) { const m=line.match(/^steps\{([^}]*)\}/);if(m){const vm=line.match(/variant:(\S+)/);return{kind:'steps',items:m[1].split('|').map(it=>{const p=it.trim().split('>');return{num:p[0]?.trim(),title:p[1]?.trim(),desc:p[2]?.trim()}}),variant:vm?.[1]}} }
1050
+ if(line.startsWith('compare{')) { const m=line.match(/^compare\{([^}]*)\}/);if(m){const vm=line.match(/variant:(\S+)/);return{kind:'compare',rows:m[1].split('|').map(r=>r.trim().split(':').map(c=>c.trim())),variant:vm?.[1]}} }
1051
+ if(line.startsWith('video{')) { const m=line.match(/^video\{([^}]*)\}/);if(m){const pts=m[1].split('|');return{kind:'video',url:pts[0]?.trim(),poster:pts[1]?.trim()}} }
1047
1052
  if(line.startsWith('faq{')) {
1048
1053
  const body=line.slice(4,line.lastIndexOf('}')).trim()
1049
1054
  const items=body.split('|').map(i=>{const idx=i.indexOf('>');return{q:i.slice(0,idx).trim(),a:i.slice(idx+1).trim()}}).filter(i=>i.q&&i.a)
@@ -1277,6 +1282,11 @@ function renderBlock(b, page) {
1277
1282
  case 'install': return rInstall(b)
1278
1283
  case 'feature': return rRow(b)
1279
1284
  case 'testimonial': return rTestimonial(b)
1285
+ case 'marquee': return rMarquee(b)
1286
+ case 'cta': return rCta(b)
1287
+ case 'steps': return rSteps(b)
1288
+ case 'compare': return rCompare(b)
1289
+ case 'video': return rVideo(b)
1280
1290
  case 'gallery': return rGallery(b)
1281
1291
  case 'raw': return (b.html||'')+'\n'
1282
1292
  case 'html': return `<div class="fx-html">${b.content||''}</div>\n`
@@ -1400,19 +1410,27 @@ function parseFeature(line) {
1400
1410
 
1401
1411
  function rHero(b) {
1402
1412
  let h1='',sub='',img='',ctas=''
1413
+ let heroBadge = ''
1403
1414
  for(const item of (b.items||[])) for(const f of item){
1415
+ if(f.text?.startsWith('badge:')) { heroBadge=`<div class="fx-hero-badge"><span class="fx-hero-badge-dot"></span>${esc(f.text.slice(6).trim())}</div>`; continue }
1404
1416
  if(f.isImg) img=`<img src="${esc(f.src)}" class="fx-hero-img" alt="hero" loading="eager">`
1405
1417
  else if(f.isLink) ctas+=`<a href="${esc(f.path)}" class="fx-cta">${esc(f.label)}</a>`
1406
- else if(!h1) h1=`<h1 class="fx-title">${esc(f.text)}</h1>`
1418
+ else if(!h1) {
1419
+ // *texto* entre asteriscos = gradient text
1420
+ const gt = f.text.match(/^\*(.*?)\*$/)
1421
+ if(gt) h1=`<h1 class="fx-title"><span class="fx-gradient-text">${esc(gt[1])}</span></h1>`
1422
+ else h1=`<h1 class="fx-title">${esc(f.text)}</h1>`
1423
+ }
1407
1424
  else sub+=`<p class="fx-sub">${esc(f.text)}</p>`
1408
1425
  }
1409
1426
  const v = b.variant || (img ? 'split' : 'centered')
1410
1427
  const bgStyle = b.bg ? ` style="background:${b.bg}"` : b.style ? ` style="${b.style.replace(/,/g,';')}"` : ''
1411
1428
  const inlineStyle = b.style && !b.bg ? ` style="${b.style.replace(/,/g,';')}"` : ''
1412
1429
  if (v === 'landing') {
1413
- return `<section class="fx-hero fx-hero-landing"${bgStyle}><div class="fx-hero-inner">${h1}${sub}${ctas}</div></section>
1430
+ return `<section class="fx-hero fx-hero-landing"${bgStyle}><div class="fx-hero-grid"></div><div class="fx-hero-inner">${h1}${sub}${ctas}</div></section>
1414
1431
  `
1415
1432
  }
1433
+ if (h1) h1 = heroBadge + h1
1416
1434
  if (v === 'minimal') {
1417
1435
  return `<section class="fx-hero fx-hero-minimal"${bgStyle}><div class="fx-hero-inner">${h1}${sub}${ctas}</div></section>\n`
1418
1436
  }
@@ -1468,7 +1486,7 @@ function rRow(b) {
1468
1486
  }).join('')
1469
1487
  const v=b.variant||''
1470
1488
  const wrapStyle=b.style?` style="${b.style.replace(/,/g,';')}"`:''
1471
- return `<div class="fx-grid fx-grid-${b.cols||3}${v?' fx-grid-'+v:''}"${wrapStyle}>${cards}</div>\n`
1489
+ return `<div class="fx-grid fx-grid-${b.cols||3}${v?' fx-grid-'+v:''} fx-animate-stagger"${wrapStyle}>${cards}</div>\n`
1472
1490
  }
1473
1491
 
1474
1492
  function rSect(b) {
@@ -1482,7 +1500,7 @@ function rSect(b) {
1482
1500
  const bgStyle=b.bg?` style="background:${b.bg}"`:(b.style?` style="${b.style.replace(/,/g,';')}"`:'' )
1483
1501
  const v = b.variant||''
1484
1502
  const cls = v ? ` fx-sect-${v}` : ''
1485
- return `<section class="fx-sect${cls}"${bgStyle}>${inner}</section>\n`
1503
+ return `<section class="fx-sect${cls} fx-animate"${bgStyle}>${inner}</section>\n`
1486
1504
  }
1487
1505
 
1488
1506
 
@@ -1525,7 +1543,7 @@ function rBenchmark(b) {
1525
1543
  <div class="fx-bench-bar"><div class="fx-bench-fill" style="width:${isLow?pct+'%':pct+'%'}"></div></div>
1526
1544
  </div>`
1527
1545
  }).join('')
1528
- return `<div class="fx-benchmark">${cards}</div>\n`
1546
+ return `<div class="fx-benchmark fx-animate-stagger">${cards}</div>\n`
1529
1547
  }
1530
1548
 
1531
1549
  // ── rInstall: multi-step code box com botões ──────────────────────
@@ -1552,8 +1570,12 @@ function rStatsUpgraded(b) {
1552
1570
  const lbl = parts[1]?.trim()
1553
1571
  const vs = parts[2]?.trim()
1554
1572
  const bind = isDyn(val) ? ` data-fx-bind="${esc(val)}"` : ''
1573
+ // Números → animados com counter
1574
+ const isNum = !isDyn(val) && /^[\d.,]+[KkMmBb%]?$/.test(val?.replace(/ms|KB|GB|px/,''))
1575
+ const numAttr = isNum && !isDyn(val) ? ` data-to="${val.replace(/[^\d.]/g,'')}" data-dec="${val.includes('.')?val.split('.')[1]?.replace(/[^\d]/g,'').length||0:0}"` : ''
1576
+ const countCls = isNum && !isDyn(val) ? ' fx-count' : ''
1555
1577
  return `<div class="fx-stat">
1556
- <div class="fx-stat-val"${bind}>${esc(val)}</div>
1578
+ <div class="fx-stat-val${countCls}"${bind}${numAttr}>${esc(val)}</div>
1557
1579
  <div class="fx-stat-lbl">${esc(lbl||'')}</div>
1558
1580
  ${vs ? `<div class="fx-stat-vs">${esc(vs)}</div>` : ''}
1559
1581
  </div>`
@@ -1562,6 +1584,88 @@ function rStatsUpgraded(b) {
1562
1584
  }
1563
1585
 
1564
1586
 
1587
+
1588
+ // ── rMarquee: faixa de logos/texto em loop infinito ───────────────
1589
+ function rMarquee(b) {
1590
+ const speed = b.variant === 'fast' ? '15s' : b.variant === 'slow' ? '40s' : '25s'
1591
+ const items = (b.items||[]).map(item =>
1592
+ `<span class="fx-marquee-item">${esc(item)}</span><span class="fx-marquee-sep">·</span>`
1593
+ ).join('')
1594
+ // Duplicar para loop contínuo
1595
+ return `<div class="fx-marquee"><div class="fx-marquee-track" style="animation-duration:${speed}">${items}${items}</div></div>\n`
1596
+ }
1597
+
1598
+ // ── rCta: seção call-to-action com glow ───────────────────────────
1599
+ function rCta(b) {
1600
+ const btns = (b.links||[]).map((l,i) =>
1601
+ `<a href="${esc(l.path)}" class="fx-cta${i===0?'':' fx-cta-outline'}">${esc(l.label)}</a>`
1602
+ ).join('')
1603
+ const v = b.variant || 'default'
1604
+ return `<section class="fx-cta-section fx-cta-${v}">
1605
+ <div class="fx-cta-glow"></div>
1606
+ <div class="fx-cta-inner">
1607
+ ${b.title?`<h2 class="fx-cta-title">${esc(b.title)}</h2>`:''}
1608
+ ${b.sub?`<p class="fx-cta-sub">${esc(b.sub)}</p>`:''}
1609
+ <div class="fx-cta-actions">${btns}</div>
1610
+ </div>
1611
+ </section>\n`
1612
+ }
1613
+
1614
+ // ── rSteps: passos 1-2-3 com linha conectora ──────────────────────
1615
+ function rSteps(b) {
1616
+ const items = (b.items||[]).map((step, i) =>
1617
+ `<div class="fx-step">
1618
+ <div class="fx-step-num">${esc(step.num||String(i+1))}</div>
1619
+ <div class="fx-step-body">
1620
+ <div class="fx-step-title">${esc(step.title||'')}</div>
1621
+ <div class="fx-step-desc">${esc(step.desc||'')}</div>
1622
+ </div>
1623
+ </div>`
1624
+ ).join('')
1625
+ const v = b.variant === 'vertical' ? ' fx-steps-vertical' : ''
1626
+ return `<div class="fx-steps${v} fx-animate-stagger">${items}</div>\n`
1627
+ }
1628
+
1629
+ // ── rCompare: tabela X vs Y ───────────────────────────────────────
1630
+ function rCompare(b) {
1631
+ const rows = b.rows || []
1632
+ if (!rows.length) return ''
1633
+ // Primeira linha = cabeçalho se tiver textos
1634
+ const header = rows[0]
1635
+ const isHeader = header.length > 1 && !header[0].startsWith('✅') && !header[0].startsWith('❌')
1636
+ const headerHtml = isHeader
1637
+ ? `<div class="fx-compare-header">${header.map((h,i) => `<div class="fx-compare-cell${i===0?' fx-compare-feature':i===1?' fx-compare-col-a':' fx-compare-col-b'}">${esc(h)}</div>`).join('')}</div>`
1638
+ : ''
1639
+ const dataRows = isHeader ? rows.slice(1) : rows
1640
+ const bodyHtml = dataRows.map(row => {
1641
+ const feature = row[0] || ''
1642
+ const a = row[1] || ''
1643
+ const b2 = row[2] || ''
1644
+ const checkA = a === '✅' || a === 'sim' || a === 'yes' ? '✅' : a === '❌' || a === 'nao' || a === 'no' ? '❌' : esc(a)
1645
+ const checkB = b2 === '✅' || b2 === 'sim' || b2 === 'yes' ? '✅' : b2 === '❌' || b2 === 'nao' || b2 === 'no' ? '❌' : esc(b2)
1646
+ return `<div class="fx-compare-row">
1647
+ <div class="fx-compare-cell fx-compare-feature">${esc(feature)}</div>
1648
+ <div class="fx-compare-cell fx-compare-col-a">${checkA}</div>
1649
+ <div class="fx-compare-cell fx-compare-col-b">${checkB}</div>
1650
+ </div>`
1651
+ }).join('')
1652
+ return `<div class="fx-compare">${headerHtml}${bodyHtml}</div>\n`
1653
+ }
1654
+
1655
+ // ── rVideo: embed de vídeo ou youtube ─────────────────────────────
1656
+ function rVideo(b) {
1657
+ const url = b.url || ''
1658
+ const poster = b.poster || ''
1659
+ // Detectar YouTube
1660
+ const ytMatch = url.match(/(?:youtube\.com\/watch\?v=|youtu\.be\/)([a-zA-Z0-9_-]{11})/)
1661
+ if (ytMatch) {
1662
+ const id = ytMatch[1]
1663
+ return `<div class="fx-video-wrap"><div class="fx-video-yt"><iframe src="https://www.youtube-nocookie.com/embed/${esc(id)}?rel=0" frameborder="0" allowfullscreen loading="lazy" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"></iframe></div></div>\n`
1664
+ }
1665
+ // Vídeo HTML5
1666
+ return `<div class="fx-video-wrap"><video class="fx-video" controls${poster?` poster="${esc(poster)}"`:''} preload="metadata"><source src="${esc(url)}"></video></div>\n`
1667
+ }
1668
+
1565
1669
  // ── autoYear: substitui © YYYY por © <span data-fx-year></span> ──
1566
1670
  function autoYear(text) {
1567
1671
  // Substitui padrões como "© 2024", "© 2025", "© 2026" ou só "©" pelo ano dinâmico
@@ -1697,6 +1801,24 @@ function genCustomThemeVars(ct) {
1697
1801
 
1698
1802
  function genThemeVarCSS(t) {
1699
1803
  const r=[]
1804
+ // Override CSS custom properties com valores do ~theme
1805
+ const rootVars = []
1806
+ if(t.accent) {
1807
+ // Converter hex para rgb para --aip-accent-rgb
1808
+ const hex = t.accent.replace('#','')
1809
+ const rgb = hex.length===6 ? `${parseInt(hex.slice(0,2),16)},${parseInt(hex.slice(2,4),16)},${parseInt(hex.slice(4,6),16)}` : '255,87,34'
1810
+ rootVars.push(`--aip-accent:${t.accent}`)
1811
+ rootVars.push(`--aip-accent-rgb:${rgb}`)
1812
+ rootVars.push(`--aip-accent-light:${t.accent}cc`)
1813
+ }
1814
+ if(t.bg) {
1815
+ const hex = t.bg.replace('#','')
1816
+ const rgb = hex.length===6 ? `${parseInt(hex.slice(0,2),16)},${parseInt(hex.slice(2,4),16)},${parseInt(hex.slice(4,6),16)}` : '3,7,18'
1817
+ rootVars.push(`--aip-bg:${t.bg}`)
1818
+ rootVars.push(`--aip-bg-rgb:${rgb}`)
1819
+ }
1820
+ if(t.text) rootVars.push(`--aip-text:${t.text}`)
1821
+ if(rootVars.length) r.push(`:root{${rootVars.join(';')}}`)
1700
1822
  if(t.accent) r.push(`.fx-cta,.fx-btn,.fx-pricing-cta{background:${t.accent}!important;color:#fff!important}`)
1701
1823
  if(t.bg) r.push(`body{background:${t.bg}!important}`)
1702
1824
  if(t.text) r.push(`body{color:${t.text}!important}`)
@@ -1711,95 +1833,836 @@ function genThemeVarCSS(t) {
1711
1833
  }
1712
1834
 
1713
1835
  function css(theme) {
1714
- const base=`*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}html{scroll-behavior:smooth}body{font-family:-apple-system,'Segoe UI',system-ui,sans-serif;-webkit-font-smoothing:antialiased;min-height:100vh}a{text-decoration:none;color:inherit}input,button,select{font-family:inherit}img{max-width:100%;height:auto}.fx-nav{display:flex;align-items:center;justify-content:space-between;padding:1rem 2.5rem;position:sticky;top:0;z-index:50;backdrop-filter:blur(12px);flex-wrap:wrap;gap:.5rem}.fx-brand{font-size:1.25rem;font-weight:800;letter-spacing:-.03em}.fx-nav-links{display:flex;align-items:center;gap:1.75rem}.fx-nav-link{font-size:.875rem;font-weight:500;opacity:.65;transition:opacity .15s}.fx-nav-link:hover{opacity:1}.fx-hamburger{display:none;flex-direction:column;gap:5px;background:none;border:none;cursor:pointer;padding:.25rem}.fx-hamburger span{display:block;width:22px;height:2px;background:currentColor;transition:all .2s;border-radius:1px}.fx-hamburger.open span:nth-child(1){transform:rotate(45deg) translate(5px,5px)}.fx-hamburger.open span:nth-child(2){opacity:0}.fx-hamburger.open span:nth-child(3){transform:rotate(-45deg) translate(5px,-5px)}@media(max-width:640px){.fx-hamburger{display:flex}.fx-nav-links{display:none;width:100%;flex-direction:column;align-items:flex-start;gap:.75rem;padding:.75rem 0}.fx-nav-links.open{display:flex}}.fx-hero{display:flex;align-items:center;justify-content:center;min-height:92vh;padding:4rem 1.5rem}.fx-hero-split{display:grid;grid-template-columns:1fr 1fr;gap:3rem;align-items:center;padding:4rem 2.5rem;min-height:70vh}@media(max-width:768px){.fx-hero-split{grid-template-columns:1fr}}.fx-hero-img{width:100%;border-radius:1.25rem;object-fit:cover;max-height:500px}.fx-hero-inner{max-width:56rem;text-align:center;display:flex;flex-direction:column;align-items:center;gap:1.5rem}.fx-hero-split .fx-hero-inner{text-align:left;align-items:flex-start;max-width:none}.fx-title{font-size:clamp(2.5rem,8vw,5.5rem);font-weight:900;letter-spacing:-.04em;line-height:1}.fx-sub{font-size:clamp(1rem,2vw,1.25rem);line-height:1.75;max-width:40rem}.fx-cta{display:inline-flex;align-items:center;padding:.875rem 2.5rem;border-radius:.75rem;font-weight:700;font-size:1rem;letter-spacing:-.01em;transition:transform .15s;margin:.25rem}.fx-cta:hover{transform:translateY(-1px)}.fx-stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:3rem;padding:5rem 2.5rem;text-align:center}.fx-stat-val{font-size:clamp(2.5rem,5vw,4rem);font-weight:900;letter-spacing:-.04em;line-height:1}.fx-stat-lbl{font-size:.75rem;font-weight:600;text-transform:uppercase;letter-spacing:.1em;margin-top:.5rem}.fx-grid{display:grid;gap:1.25rem;padding:1rem 2.5rem 5rem}.fx-grid-2{grid-template-columns:repeat(auto-fit,minmax(280px,1fr))}.fx-grid-3{grid-template-columns:repeat(auto-fit,minmax(240px,1fr))}.fx-grid-4{grid-template-columns:repeat(auto-fit,minmax(200px,1fr))}.fx-card{border-radius:1rem;padding:1.75rem;transition:transform .2s,box-shadow .2s}.fx-card:hover{transform:translateY(-2px)}.fx-card-img{width:100%;border-radius:.75rem;object-fit:cover;height:180px;margin-bottom:1rem}.fx-icon{font-size:2rem;margin-bottom:1rem}.fx-card-title{font-size:1.0625rem;font-weight:700;letter-spacing:-.02em;margin-bottom:.5rem}.fx-card-body{font-size:.875rem;line-height:1.65}.fx-card-link{font-size:.8125rem;font-weight:600;display:inline-block;margin-top:1rem;opacity:.6;transition:opacity .15s}.fx-card-link:hover{opacity:1}.fx-sect{padding:5rem 2.5rem}.fx-sect-title{font-size:clamp(1.75rem,4vw,3rem);font-weight:800;letter-spacing:-.04em;margin-bottom:1.5rem;text-align:center}.fx-sect-body{font-size:1rem;line-height:1.75;text-align:center;max-width:48rem;margin:0 auto}.fx-form-wrap{padding:3rem 2.5rem;display:flex;justify-content:center}.fx-form{width:100%;max-width:28rem;border-radius:1.25rem;padding:2.5rem}.fx-field{margin-bottom:1.25rem}.fx-label{display:block;font-size:.8125rem;font-weight:600;margin-bottom:.5rem}.fx-input{width:100%;padding:.75rem 1rem;border-radius:.625rem;font-size:.9375rem;outline:none;transition:box-shadow .15s}.fx-input:focus{box-shadow:0 0 0 3px rgba(37,99,235,.35)}.fx-btn{width:100%;padding:.875rem 1.5rem;border:none;border-radius:.625rem;font-size:.9375rem;font-weight:700;cursor:pointer;margin-top:.5rem;transition:transform .15s,opacity .15s;letter-spacing:-.01em}.fx-btn:hover{transform:translateY(-1px)}.fx-btn:disabled{opacity:.5;cursor:not-allowed;transform:none}.fx-btn-wrap{padding:0 2.5rem 1.5rem}.fx-standalone-btn{width:auto;padding:.75rem 2rem;margin-top:0}.fx-form-msg{font-size:.8125rem;padding:.5rem 0;min-height:1.5rem;text-align:center}.fx-form-err{color:#f87171}.fx-form-ok{color:#4ade80}.fx-table-wrap{overflow-x:auto;padding:0 2.5rem 4rem}.fx-table{width:100%;border-collapse:collapse;font-size:.875rem}.fx-th{text-align:left;padding:.875rem 1.25rem;font-size:.75rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em}.fx-th-actions{opacity:.6}.fx-tr{transition:background .1s}.fx-td{padding:.875rem 1.25rem}.fx-td-empty{padding:2rem 1.25rem;text-align:center;opacity:.4}.fx-td-actions{white-space:nowrap;padding:.5rem 1rem!important}.fx-action-btn{border:none;cursor:pointer;font-size:.75rem;font-weight:600;padding:.3rem .75rem;border-radius:.375rem;margin-right:.375rem;font-family:inherit;transition:opacity .15s}.fx-action-btn:hover{opacity:.85}.fx-edit-btn{background:#1e40af;color:#93c5fd}.fx-delete-btn{background:#7f1d1d;color:#fca5a5}.fx-select-wrap{padding:.5rem 2.5rem}.fx-select-block{width:auto;min-width:200px;margin-top:0}.fx-pricing{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:1.5rem;padding:2rem 2.5rem 5rem;align-items:start}.fx-pricing-card{border-radius:1.25rem;padding:2rem;position:relative;transition:transform .2s}.fx-pricing-featured{transform:scale(1.03)}.fx-pricing-badge{position:absolute;top:-12px;left:50%;transform:translateX(-50%);background:#2563eb;color:#fff;font-size:.7rem;font-weight:700;padding:.25rem .875rem;border-radius:999px;white-space:nowrap;letter-spacing:.05em}.fx-pricing-name{font-size:.875rem;font-weight:700;text-transform:uppercase;letter-spacing:.1em;margin-bottom:.5rem;opacity:.7}.fx-pricing-price{font-size:3rem;font-weight:900;letter-spacing:-.05em;line-height:1;margin-bottom:.75rem}.fx-pricing-desc{font-size:.875rem;line-height:1.65;margin-bottom:1.5rem;opacity:.7}.fx-pricing-cta{display:block;text-align:center;padding:.75rem;border-radius:.625rem;font-weight:700;font-size:.9rem;transition:opacity .15s}.fx-pricing-cta:hover{opacity:.85}.fx-faq{max-width:48rem;margin:0 auto}.fx-faq-item{border-radius:.75rem;margin-bottom:.625rem;cursor:pointer;overflow:hidden;transition:background .15s}.fx-faq-q{display:flex;justify-content:space-between;align-items:center;padding:1rem 1.25rem;font-size:.9375rem;font-weight:600}.fx-faq-arrow{transition:transform .2s;font-size:.75rem;opacity:.5}.fx-faq-item.open .fx-faq-arrow{transform:rotate(90deg)}.fx-faq-a{max-height:0;overflow:hidden;padding:0 1.25rem;font-size:.875rem;line-height:1.7;transition:max-height .3s,padding .3s}.fx-faq-item.open .fx-faq-a{max-height:300px;padding:.75rem 1.25rem 1.25rem}.fx-testi-wrap{padding:5rem 2.5rem;display:flex;justify-content:center}.fx-testi{max-width:42rem;text-align:center;display:flex;flex-direction:column;align-items:center;gap:1.25rem}.fx-testi-img{width:64px;height:64px;border-radius:50%;object-fit:cover}.fx-testi-avatar{width:64px;height:64px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:1.5rem;font-weight:700;background:#1e293b}.fx-testi-quote{font-size:1.25rem;line-height:1.7;font-style:italic;opacity:.9}.fx-testi-author{font-size:.875rem;font-weight:600;opacity:.5}.fx-gallery{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:.75rem;padding:1rem 2.5rem 4rem}.fx-gallery-item{border-radius:.75rem;overflow:hidden;aspect-ratio:4/3}.fx-gallery-item img{width:100%;height:100%;object-fit:cover;transition:transform .3s}.fx-gallery-item:hover img{transform:scale(1.04)}.fx-if-wrap{display:contents}.fx-footer{padding:3rem 2.5rem;text-align:center}.fx-footer-text{font-size:.8125rem}.fx-footer-link{font-size:.8125rem;margin:0 .75rem;opacity:.5;transition:opacity .15s}.fx-footer-link:hover{opacity:1}
1715
- /* ── code window ── */
1716
- .fx-code-window{border-radius:.875rem;overflow:hidden;border:1px solid rgba(255,255,255,.08);margin:0 2.5rem 2rem}
1717
- .fx-code-bar{display:flex;align-items:center;gap:.75rem;padding:.625rem 1rem;background:rgba(255,255,255,.04);border-bottom:1px solid rgba(255,255,255,.06)}
1836
+ // ════════════════════════════════════════════════════════════════
1837
+ // DESIGN SYSTEM CSS custom properties como fundação
1838
+ // Cada tema define suas variáveis; todos os componentes usam vars
1839
+ // ════════════════════════════════════════════════════════════════
1840
+ const base = `
1841
+ :root{
1842
+ --aip-font-display:-apple-system,BlinkMacSystemFont,'Segoe UI',system-ui,sans-serif;
1843
+ --aip-font-mono:'JetBrains Mono','Fira Code','Cascadia Code','Courier New',monospace;
1844
+ --aip-ease-out:cubic-bezier(.16,1,.3,1);
1845
+ --aip-ease-spring:cubic-bezier(.34,1.56,.64,1);
1846
+ }
1847
+ *,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
1848
+ html{scroll-behavior:smooth;text-size-adjust:100%;-webkit-text-size-adjust:100%}
1849
+ body{
1850
+ font-family:var(--aip-font-display);
1851
+ background:var(--aip-bg);
1852
+ color:var(--aip-text);
1853
+ line-height:1.6;
1854
+ -webkit-font-smoothing:antialiased;
1855
+ -moz-osx-font-smoothing:grayscale;
1856
+ min-height:100vh;
1857
+ overflow-x:hidden;
1858
+ }
1859
+ a{text-decoration:none;color:inherit}
1860
+ img{max-width:100%;height:auto;display:block}
1861
+ input,button,select,textarea{font-family:inherit;font-size:inherit}
1862
+ button{cursor:pointer}
1863
+ code,pre{font-family:var(--aip-font-mono)}
1864
+
1865
+ /* ── NOISE OVERLAY ── */
1866
+ body::before{
1867
+ content:'';
1868
+ position:fixed;
1869
+ inset:0;
1870
+ background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.75' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='300' height='300' filter='url(%23n)' opacity='.04'/%3E%3C/svg%3E");
1871
+ pointer-events:none;
1872
+ z-index:9999;
1873
+ opacity:.6;
1874
+ mix-blend-mode:overlay;
1875
+ }
1876
+
1877
+ /* ═══════════════════════════════════════════
1878
+ NAV
1879
+ ═══════════════════════════════════════════ */
1880
+ .fx-nav{
1881
+ display:flex;
1882
+ align-items:center;
1883
+ justify-content:space-between;
1884
+ padding:0 2rem;
1885
+ height:60px;
1886
+ position:sticky;
1887
+ top:0;
1888
+ z-index:100;
1889
+ background:rgba(var(--aip-bg-rgb),.75);
1890
+ backdrop-filter:blur(20px) saturate(180%);
1891
+ -webkit-backdrop-filter:blur(20px) saturate(180%);
1892
+ border-bottom:1px solid var(--aip-border);
1893
+ transition:border-color .3s;
1894
+ flex-wrap:wrap;
1895
+ gap:.5rem;
1896
+ }
1897
+ .fx-nav.scrolled{border-bottom-color:var(--aip-border-strong)}
1898
+ .fx-brand{
1899
+ font-size:1.125rem;
1900
+ font-weight:800;
1901
+ letter-spacing:-.04em;
1902
+ color:var(--aip-text);
1903
+ }
1904
+ .fx-nav-links{display:flex;align-items:center;gap:.25rem}
1905
+ .fx-nav-link{
1906
+ font-size:.8125rem;
1907
+ font-weight:500;
1908
+ color:var(--aip-text-muted);
1909
+ padding:.375rem .75rem;
1910
+ border-radius:.5rem;
1911
+ transition:background .15s,color .15s;
1912
+ white-space:nowrap;
1913
+ }
1914
+ .fx-nav-link:hover{background:var(--aip-surface-hover);color:var(--aip-text)}
1915
+ .fx-nav-cta{
1916
+ font-size:.8125rem;
1917
+ font-weight:700;
1918
+ padding:.4375rem 1rem;
1919
+ background:var(--aip-accent);
1920
+ color:#fff;
1921
+ border-radius:.5rem;
1922
+ transition:opacity .15s,transform .1s;
1923
+ letter-spacing:-.01em;
1924
+ }
1925
+ .fx-nav-cta:hover{opacity:.88;transform:translateY(-1px)}
1926
+ .fx-hamburger{display:none;flex-direction:column;gap:4px;background:none;border:none;padding:.375rem}
1927
+ .fx-hamburger span{display:block;width:20px;height:1.5px;background:var(--aip-text-muted);border-radius:1px;transition:all .2s}
1928
+ .fx-hamburger.open span:nth-child(1){transform:rotate(45deg) translate(4px,4px)}
1929
+ .fx-hamburger.open span:nth-child(2){opacity:0;transform:translateX(-4px)}
1930
+ .fx-hamburger.open span:nth-child(3){transform:rotate(-45deg) translate(4px,-4px)}
1931
+ @media(max-width:640px){
1932
+ .fx-hamburger{display:flex}
1933
+ .fx-nav-links{display:none;width:100%;flex-direction:column;align-items:stretch;padding:.75rem 0;gap:.125rem;border-top:1px solid var(--aip-border);margin-top:.5rem}
1934
+ .fx-nav-links.open{display:flex}
1935
+ .fx-nav-link{padding:.625rem .75rem}
1936
+ }
1937
+
1938
+ /* ═══════════════════════════════════════════
1939
+ HERO
1940
+ ═══════════════════════════════════════════ */
1941
+ .fx-hero{
1942
+ display:flex;
1943
+ align-items:center;
1944
+ justify-content:center;
1945
+ min-height:calc(100vh - 60px);
1946
+ padding:5rem 1.5rem 4rem;
1947
+ position:relative;
1948
+ }
1949
+ .fx-hero-inner{
1950
+ max-width:60rem;
1951
+ text-align:center;
1952
+ display:flex;
1953
+ flex-direction:column;
1954
+ align-items:center;
1955
+ gap:1.75rem;
1956
+ position:relative;
1957
+ z-index:1;
1958
+ }
1959
+ .fx-hero-split{
1960
+ display:grid;
1961
+ grid-template-columns:1fr 1fr;
1962
+ gap:4rem;
1963
+ align-items:center;
1964
+ padding:4rem 2.5rem;
1965
+ min-height:80vh;
1966
+ }
1967
+ @media(max-width:768px){.fx-hero-split{grid-template-columns:1fr;padding:3rem 1.5rem;min-height:auto}}
1968
+ .fx-hero-split .fx-hero-inner{text-align:left;align-items:flex-start;max-width:none}
1969
+ .fx-hero-img{width:100%;border-radius:1.25rem;border:1px solid var(--aip-border)}
1970
+ .fx-hero-minimal{min-height:52vh!important}
1971
+ .fx-hero-tall{min-height:100vh!important}
1972
+
1973
+ /* Landing variant — grid + glow */
1974
+ .fx-hero-landing{overflow:hidden}
1975
+ .fx-hero-landing::after{
1976
+ content:'';
1977
+ position:absolute;
1978
+ width:900px;height:600px;
1979
+ border-radius:50%;
1980
+ background:radial-gradient(ellipse,rgba(var(--aip-accent-rgb),.14) 0%,transparent 65%);
1981
+ left:50%;top:50%;
1982
+ transform:translate(-50%,-55%);
1983
+ pointer-events:none;
1984
+ animation:fx-breathe 8s ease-in-out infinite;
1985
+ }
1986
+ @keyframes fx-breathe{0%,100%{transform:translate(-50%,-55%) scale(1)}50%{transform:translate(-50%,-55%) scale(1.12)}}
1987
+ .fx-hero-grid{
1988
+ position:absolute;inset:0;
1989
+ background:
1990
+ linear-gradient(var(--aip-grid-line) 1px,transparent 1px),
1991
+ linear-gradient(90deg,var(--aip-grid-line) 1px,transparent 1px);
1992
+ background-size:64px 64px;
1993
+ mask-image:radial-gradient(ellipse 75% 65% at 50% 50%,black 20%,transparent);
1994
+ -webkit-mask-image:radial-gradient(ellipse 75% 65% at 50% 50%,black 20%,transparent);
1995
+ pointer-events:none;
1996
+ }
1997
+
1998
+ /* Badge */
1999
+ .fx-hero-badge{
2000
+ display:inline-flex;align-items:center;gap:.5rem;
2001
+ font-size:.7rem;letter-spacing:.12em;text-transform:uppercase;font-weight:600;
2002
+ padding:.3125rem .875rem;
2003
+ border-radius:999px;
2004
+ border:1px solid var(--aip-border-strong);
2005
+ background:var(--aip-surface);
2006
+ color:var(--aip-text-muted);
2007
+ }
2008
+ .fx-hero-badge-dot{
2009
+ width:6px;height:6px;border-radius:50%;
2010
+ background:var(--aip-accent);
2011
+ animation:fx-pulse 2.5s ease infinite;
2012
+ flex-shrink:0;
2013
+ }
2014
+ @keyframes fx-pulse{0%,100%{opacity:1;box-shadow:0 0 0 0 rgba(var(--aip-accent-rgb),.5)}60%{opacity:.4;box-shadow:0 0 0 6px rgba(var(--aip-accent-rgb),0)}}
2015
+
2016
+ /* Typography */
2017
+ .fx-title{
2018
+ font-size:clamp(2.75rem,7.5vw,6.5rem);
2019
+ font-weight:900;
2020
+ letter-spacing:-.05em;
2021
+ line-height:.92;
2022
+ color:var(--aip-text);
2023
+ }
2024
+ .fx-gradient-text{
2025
+ background:linear-gradient(135deg,var(--aip-accent) 0%,var(--aip-accent-light) 50%,var(--aip-text) 100%);
2026
+ -webkit-background-clip:text;
2027
+ -webkit-text-fill-color:transparent;
2028
+ background-clip:text;
2029
+ }
2030
+ .fx-sub{
2031
+ font-size:clamp(1rem,2vw,1.1875rem);
2032
+ line-height:1.75;
2033
+ color:var(--aip-text-muted);
2034
+ max-width:38rem;
2035
+ }
2036
+ .fx-cta{
2037
+ display:inline-flex;align-items:center;gap:.5rem;
2038
+ padding:.75rem 1.75rem;
2039
+ border-radius:.625rem;
2040
+ font-weight:700;
2041
+ font-size:.9375rem;
2042
+ letter-spacing:-.015em;
2043
+ transition:transform .15s var(--aip-ease-out),box-shadow .15s,opacity .15s;
2044
+ background:var(--aip-accent);
2045
+ color:#fff;
2046
+ }
2047
+ .fx-cta:hover{transform:translateY(-2px);box-shadow:0 8px 24px rgba(var(--aip-accent-rgb),.35)}
2048
+ .fx-cta:active{transform:translateY(0)}
2049
+ .fx-cta-outline{
2050
+ background:transparent!important;
2051
+ border:1px solid var(--aip-border-strong)!important;
2052
+ color:var(--aip-text)!important;
2053
+ box-shadow:none!important;
2054
+ }
2055
+ .fx-cta-outline:hover{background:var(--aip-surface)!important;transform:translateY(-1px)!important}
2056
+
2057
+ /* ═══════════════════════════════════════════
2058
+ STATS BAR
2059
+ ═══════════════════════════════════════════ */
2060
+ .fx-stats{
2061
+ display:grid;
2062
+ grid-template-columns:repeat(auto-fit,minmax(160px,1fr));
2063
+ border-top:1px solid var(--aip-border);
2064
+ border-bottom:1px solid var(--aip-border);
2065
+ }
2066
+ .fx-stat{
2067
+ padding:2.25rem 1.5rem;
2068
+ text-align:center;
2069
+ border-right:1px solid var(--aip-border);
2070
+ position:relative;
2071
+ overflow:hidden;
2072
+ }
2073
+ .fx-stat:last-child{border-right:none}
2074
+ .fx-stat::before{
2075
+ content:'';position:absolute;top:0;left:0;right:0;height:2px;
2076
+ background:linear-gradient(90deg,transparent,var(--aip-accent),transparent);
2077
+ opacity:0;transition:opacity .3s;
2078
+ }
2079
+ .fx-stat:hover::before{opacity:1}
2080
+ .fx-stat-val{
2081
+ font-size:clamp(2rem,4vw,3rem);
2082
+ font-weight:900;
2083
+ letter-spacing:-.05em;
2084
+ line-height:1;
2085
+ color:var(--aip-accent);
2086
+ font-variant-numeric:tabular-nums;
2087
+ }
2088
+ .fx-stat-lbl{
2089
+ font-size:.7rem;
2090
+ font-weight:700;
2091
+ text-transform:uppercase;
2092
+ letter-spacing:.1em;
2093
+ color:var(--aip-text-muted);
2094
+ margin-top:.5rem;
2095
+ }
2096
+ .fx-stat-vs{
2097
+ font-size:.68rem;
2098
+ color:var(--aip-text-dim);
2099
+ margin-top:.3rem;
2100
+ letter-spacing:.01em;
2101
+ }
2102
+ @media(max-width:640px){.fx-stats{grid-template-columns:repeat(2,1fr)}.fx-stat{border-right:none;border-bottom:1px solid var(--aip-border)}.fx-stat:last-child{border-bottom:none}}
2103
+
2104
+ /* ═══════════════════════════════════════════
2105
+ SECTIONS
2106
+ ═══════════════════════════════════════════ */
2107
+ .fx-sect{
2108
+ padding:5rem 2.5rem;
2109
+ position:relative;
2110
+ }
2111
+ .fx-sect-title{
2112
+ font-size:clamp(1.75rem,4vw,3.25rem);
2113
+ font-weight:800;
2114
+ letter-spacing:-.04em;
2115
+ line-height:1.1;
2116
+ margin-bottom:1rem;
2117
+ text-align:center;
2118
+ }
2119
+ .fx-sect-body{
2120
+ font-size:1.0625rem;
2121
+ line-height:1.75;
2122
+ text-align:center;
2123
+ color:var(--aip-text-muted);
2124
+ max-width:44rem;
2125
+ margin:0 auto;
2126
+ }
2127
+ .fx-sect-link{
2128
+ font-size:.875rem;
2129
+ font-weight:600;
2130
+ color:var(--aip-accent);
2131
+ display:inline-block;
2132
+ margin-top:.75rem;
2133
+ }
2134
+ @media(max-width:768px){.fx-sect{padding:4rem 1.5rem}}
2135
+
2136
+ /* ═══════════════════════════════════════════
2137
+ CARDS / GRID
2138
+ ═══════════════════════════════════════════ */
2139
+ .fx-grid{display:grid;gap:.875rem;padding:0 2.5rem 5rem}
2140
+ .fx-grid-2{grid-template-columns:repeat(auto-fit,minmax(280px,1fr))}
2141
+ .fx-grid-3{grid-template-columns:repeat(auto-fit,minmax(240px,1fr))}
2142
+ .fx-grid-4{grid-template-columns:repeat(auto-fit,minmax(200px,1fr))}
2143
+ @media(max-width:640px){.fx-grid{padding:0 1.25rem 3rem}.fx-grid-2,.fx-grid-3,.fx-grid-4{grid-template-columns:1fr}}
2144
+
2145
+ .fx-card{
2146
+ border-radius:.875rem;
2147
+ padding:1.625rem;
2148
+ background:var(--aip-surface);
2149
+ border:1px solid var(--aip-border);
2150
+ transition:border-color .2s,transform .2s var(--aip-ease-out),box-shadow .2s;
2151
+ position:relative;
2152
+ overflow:hidden;
2153
+ }
2154
+ .fx-card::before{
2155
+ content:'';
2156
+ position:absolute;
2157
+ inset:0;
2158
+ background:linear-gradient(135deg,rgba(var(--aip-accent-rgb),.04),transparent 60%);
2159
+ opacity:0;
2160
+ transition:opacity .3s;
2161
+ }
2162
+ .fx-card:hover{
2163
+ border-color:var(--aip-border-strong);
2164
+ transform:translateY(-2px);
2165
+ box-shadow:0 16px 48px rgba(0,0,0,.25);
2166
+ }
2167
+ .fx-card:hover::before{opacity:1}
2168
+ .fx-card-img{width:100%;border-radius:.625rem;height:180px;object-fit:cover;margin-bottom:1rem}
2169
+ .fx-icon{
2170
+ font-size:1.5rem;
2171
+ margin-bottom:1rem;
2172
+ width:48px;height:48px;
2173
+ display:flex;align-items:center;justify-content:center;
2174
+ border-radius:.75rem;
2175
+ background:rgba(var(--aip-accent-rgb),.08);
2176
+ border:1px solid rgba(var(--aip-accent-rgb),.15);
2177
+ }
2178
+ .fx-card-title{
2179
+ font-size:1rem;
2180
+ font-weight:700;
2181
+ letter-spacing:-.025em;
2182
+ margin-bottom:.5rem;
2183
+ color:var(--aip-text);
2184
+ }
2185
+ .fx-card-body{
2186
+ font-size:.8375rem;
2187
+ line-height:1.7;
2188
+ color:var(--aip-text-muted);
2189
+ }
2190
+ .fx-card-link{
2191
+ font-size:.8125rem;
2192
+ font-weight:600;
2193
+ color:var(--aip-accent);
2194
+ display:inline-block;
2195
+ margin-top:1rem;
2196
+ opacity:.8;
2197
+ transition:opacity .15s;
2198
+ }
2199
+ .fx-card-link:hover{opacity:1}
2200
+ .fx-grid-feature .fx-card:hover{border-color:rgba(var(--aip-accent-rgb),.3)}
2201
+
2202
+ /* ═══════════════════════════════════════════
2203
+ FORMS
2204
+ ═══════════════════════════════════════════ */
2205
+ .fx-form-wrap{padding:3rem 2.5rem;display:flex;justify-content:center}
2206
+ .fx-form{
2207
+ width:100%;max-width:28rem;
2208
+ background:var(--aip-surface);
2209
+ border:1px solid var(--aip-border);
2210
+ border-radius:1rem;
2211
+ padding:2.25rem;
2212
+ }
2213
+ .fx-field{margin-bottom:1.125rem}
2214
+ .fx-label{
2215
+ display:block;
2216
+ font-size:.8rem;
2217
+ font-weight:600;
2218
+ color:var(--aip-text-muted);
2219
+ margin-bottom:.4375rem;
2220
+ letter-spacing:.02em;
2221
+ }
2222
+ .fx-input{
2223
+ width:100%;
2224
+ padding:.6875rem 1rem;
2225
+ background:var(--aip-bg);
2226
+ border:1px solid var(--aip-border);
2227
+ border-radius:.5rem;
2228
+ color:var(--aip-text);
2229
+ font-size:.9375rem;
2230
+ outline:none;
2231
+ transition:border-color .15s,box-shadow .15s;
2232
+ -webkit-appearance:none;
2233
+ }
2234
+ .fx-input:focus{
2235
+ border-color:var(--aip-accent);
2236
+ box-shadow:0 0 0 3px rgba(var(--aip-accent-rgb),.15);
2237
+ }
2238
+ .fx-input::placeholder{color:var(--aip-text-dim)}
2239
+ select.fx-input{cursor:pointer}
2240
+ .fx-btn{
2241
+ width:100%;
2242
+ padding:.75rem 1.5rem;
2243
+ border:none;
2244
+ border-radius:.5rem;
2245
+ background:var(--aip-accent);
2246
+ color:#fff;
2247
+ font-size:.9375rem;
2248
+ font-weight:700;
2249
+ cursor:pointer;
2250
+ margin-top:.375rem;
2251
+ transition:transform .15s var(--aip-ease-out),opacity .15s,box-shadow .15s;
2252
+ letter-spacing:-.015em;
2253
+ }
2254
+ .fx-btn:hover{transform:translateY(-1px);box-shadow:0 6px 20px rgba(var(--aip-accent-rgb),.3)}
2255
+ .fx-btn:active{transform:translateY(0)}
2256
+ .fx-btn:disabled{opacity:.45;cursor:not-allowed;transform:none;box-shadow:none}
2257
+ .fx-btn-wrap{padding:0 2.5rem 1.5rem}
2258
+ .fx-standalone-btn{width:auto;padding:.625rem 1.5rem;margin-top:0}
2259
+ .fx-form-msg{font-size:.8125rem;padding:.5rem 0;min-height:1.5rem;text-align:center;font-weight:500}
2260
+ .fx-form-err{color:#f87171}.fx-form-ok{color:#4ade80}
2261
+
2262
+ /* ═══════════════════════════════════════════
2263
+ TABLE
2264
+ ═══════════════════════════════════════════ */
2265
+ .fx-table-wrap{overflow-x:auto;padding:0 2.5rem 4rem}
2266
+ .fx-table{width:100%;border-collapse:collapse;font-size:.875rem}
2267
+ .fx-th{
2268
+ text-align:left;
2269
+ padding:.75rem 1rem;
2270
+ font-size:.7rem;
2271
+ font-weight:700;
2272
+ text-transform:uppercase;
2273
+ letter-spacing:.08em;
2274
+ color:var(--aip-text-dim);
2275
+ border-bottom:1px solid var(--aip-border);
2276
+ background:var(--aip-surface);
2277
+ white-space:nowrap;
2278
+ }
2279
+ .fx-th-actions{opacity:.5}
2280
+ .fx-tr{border-bottom:1px solid var(--aip-border);transition:background .1s}
2281
+ .fx-tr:last-child{border-bottom:none}
2282
+ .fx-tr:hover{background:var(--aip-surface-hover)}
2283
+ .fx-td{padding:.75rem 1rem;color:var(--aip-text-muted);vertical-align:middle}
2284
+ .fx-td:first-child{color:var(--aip-text);font-weight:500}
2285
+ .fx-td-empty{padding:3rem 1rem;text-align:center;color:var(--aip-text-dim);font-size:.875rem}
2286
+ .fx-td-actions{white-space:nowrap;padding:.5rem .75rem!important}
2287
+ .fx-action-btn{
2288
+ border:none;cursor:pointer;
2289
+ font-size:.75rem;font-weight:600;
2290
+ padding:.3rem .75rem;border-radius:.375rem;
2291
+ margin-right:.375rem;font-family:inherit;
2292
+ transition:opacity .15s,transform .1s;
2293
+ }
2294
+ .fx-action-btn:hover{opacity:.85;transform:translateY(-1px)}
2295
+ .fx-edit-btn{background:rgba(59,130,246,.15);color:#60a5fa;border:1px solid rgba(59,130,246,.2)}
2296
+ .fx-delete-btn{background:rgba(239,68,68,.12);color:#f87171;border:1px solid rgba(239,68,68,.2)}
2297
+
2298
+ /* ═══════════════════════════════════════════
2299
+ PRICING
2300
+ ═══════════════════════════════════════════ */
2301
+ .fx-pricing{
2302
+ display:grid;
2303
+ grid-template-columns:repeat(auto-fit,minmax(260px,1fr));
2304
+ gap:1.25rem;
2305
+ padding:2rem 2.5rem 5rem;
2306
+ align-items:start;
2307
+ }
2308
+ .fx-pricing-card{
2309
+ border-radius:1rem;
2310
+ padding:2rem;
2311
+ background:var(--aip-surface);
2312
+ border:1px solid var(--aip-border);
2313
+ position:relative;
2314
+ transition:border-color .2s,transform .2s var(--aip-ease-out);
2315
+ }
2316
+ .fx-pricing-featured{
2317
+ border-color:var(--aip-accent)!important;
2318
+ transform:scale(1.02);
2319
+ box-shadow:0 0 0 1px var(--aip-accent),0 24px 48px rgba(var(--aip-accent-rgb),.15);
2320
+ }
2321
+ .fx-pricing-badge{
2322
+ position:absolute;top:-13px;left:50%;transform:translateX(-50%);
2323
+ background:var(--aip-accent);color:#fff;
2324
+ font-size:.65rem;font-weight:700;
2325
+ padding:.25rem .875rem;border-radius:999px;white-space:nowrap;letter-spacing:.06em;
2326
+ }
2327
+ .fx-pricing-name{font-size:.75rem;font-weight:700;text-transform:uppercase;letter-spacing:.12em;color:var(--aip-text-muted);margin-bottom:.75rem}
2328
+ .fx-pricing-price{font-size:3.25rem;font-weight:900;letter-spacing:-.06em;line-height:1;margin-bottom:.75rem;color:var(--aip-text)}
2329
+ .fx-pricing-price-sm{font-size:2rem}
2330
+ .fx-pricing-desc{font-size:.875rem;line-height:1.65;margin-bottom:1.75rem;color:var(--aip-text-muted)}
2331
+ .fx-pricing-cta{display:block;text-align:center;padding:.75rem;border-radius:.625rem;font-weight:700;font-size:.9rem;transition:opacity .15s,transform .1s;background:var(--aip-accent);color:#fff}
2332
+ .fx-pricing-cta:hover{opacity:.88;transform:translateY(-1px)}
2333
+ .fx-pricing-compact{
2334
+ background:var(--aip-surface);border:1px solid var(--aip-border);
2335
+ border-radius:.875rem;padding:1.5rem;
2336
+ }
2337
+
2338
+ /* ═══════════════════════════════════════════
2339
+ FAQ
2340
+ ═══════════════════════════════════════════ */
2341
+ .fx-faq-wrap{padding:0 2.5rem 4rem}
2342
+ .fx-faq{max-width:48rem;margin:0 auto}
2343
+ .fx-faq-item{
2344
+ border:1px solid var(--aip-border);
2345
+ background:var(--aip-surface);
2346
+ border-radius:.75rem;
2347
+ margin-bottom:.5rem;
2348
+ cursor:pointer;
2349
+ overflow:hidden;
2350
+ transition:border-color .2s;
2351
+ }
2352
+ .fx-faq-item:hover{border-color:var(--aip-border-strong)}
2353
+ .fx-faq-q{
2354
+ display:flex;justify-content:space-between;align-items:center;
2355
+ padding:1rem 1.25rem;
2356
+ font-size:.9375rem;font-weight:600;
2357
+ color:var(--aip-text);
2358
+ }
2359
+ .fx-faq-arrow{transition:transform .25s var(--aip-ease-out);color:var(--aip-text-dim);font-size:.75rem}
2360
+ .fx-faq-item.open .fx-faq-arrow{transform:rotate(180deg)}
2361
+ .fx-faq-a{
2362
+ max-height:0;overflow:hidden;
2363
+ font-size:.875rem;line-height:1.7;
2364
+ color:var(--aip-text-muted);
2365
+ transition:max-height .3s var(--aip-ease-out),padding .3s;
2366
+ padding:0 1.25rem;
2367
+ }
2368
+ .fx-faq-item.open .fx-faq-a{max-height:300px;padding:.75rem 1.25rem 1.25rem}
2369
+
2370
+ /* ═══════════════════════════════════════════
2371
+ CODE WINDOW
2372
+ ═══════════════════════════════════════════ */
2373
+ .fx-code-window{
2374
+ border-radius:.875rem;
2375
+ overflow:hidden;
2376
+ border:1px solid var(--aip-border);
2377
+ background:var(--aip-surface);
2378
+ margin:0 2.5rem 2rem;
2379
+ position:relative;
2380
+ }
2381
+ .fx-code-bar{
2382
+ display:flex;align-items:center;gap:.75rem;
2383
+ padding:.6875rem 1rem;
2384
+ background:var(--aip-surface-hover);
2385
+ border-bottom:1px solid var(--aip-border);
2386
+ }
1718
2387
  .fx-dots{display:flex;gap:.375rem}
1719
- .fx-dots span{width:10px;height:10px;border-radius:50%;background:rgba(255,255,255,.15)}
1720
- .fx-dots span:nth-child(1){background:#ff5f57}.fx-dots span:nth-child(2){background:#febc2e}.fx-dots span:nth-child(3){background:#28c840}
1721
- .fx-code-lang{font-size:.62rem;letter-spacing:.1em;text-transform:uppercase;opacity:.35;font-family:monospace;margin-left:.25rem}
1722
- .fx-code-copy{margin-left:auto;font-family:monospace;font-size:.62rem;letter-spacing:.1em;text-transform:uppercase;background:none;border:1px solid rgba(255,255,255,.15);color:rgba(255,255,255,.4);padding:.2rem .625rem;border-radius:.3rem;cursor:pointer;transition:all .15s}
1723
- .fx-code-copy:hover{border-color:rgba(255,255,255,.3);color:rgba(255,255,255,.7)}
2388
+ .fx-dots span{width:11px;height:11px;border-radius:50%}
2389
+ .fx-dots span:nth-child(1){background:#ff5f57}
2390
+ .fx-dots span:nth-child(2){background:#febc2e}
2391
+ .fx-dots span:nth-child(3){background:#28c840}
2392
+ .fx-code-lang{font-size:.62rem;letter-spacing:.1em;text-transform:uppercase;color:var(--aip-text-dim);margin-left:.25rem;font-family:var(--aip-font-mono)}
2393
+ .fx-code-copy{
2394
+ margin-left:auto;
2395
+ font-family:var(--aip-font-mono);font-size:.62rem;letter-spacing:.08em;text-transform:uppercase;
2396
+ background:none;border:1px solid var(--aip-border-strong);
2397
+ color:var(--aip-text-dim);
2398
+ padding:.2rem .625rem;border-radius:.3rem;cursor:pointer;
2399
+ transition:all .15s;
2400
+ }
2401
+ .fx-code-copy:hover{border-color:var(--aip-accent);color:var(--aip-accent)}
1724
2402
  .fx-code-body{padding:1.375rem 1.5rem;overflow-x:auto}
1725
- .fx-code-line{font-family:"JetBrains Mono","Fira Code","Courier New",monospace;font-size:.8rem;line-height:1.75;color:#8899aa;white-space:pre}
1726
- .fx-kw{color:#c792ea}.fx-st{color:#c3e88d}.fx-fn{color:#82aaff}.fx-nb{color:#f78c6c}.fx-op{color:var(--accent,#ff5722)}.fx-comment{color:#3d5166;font-style:italic}
1727
- /* ── benchmark ── */
1728
- .fx-benchmark{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:1rem;padding:1rem 2.5rem 4rem}
1729
- .fx-bench-card{border-radius:1rem;padding:1.5rem;border:1px solid rgba(255,255,255,.06);background:rgba(255,255,255,.02);position:relative;overflow:hidden}
1730
- .fx-bench-card::before{content:"";position:absolute;top:0;left:0;right:0;height:2px;background:linear-gradient(90deg,transparent,var(--accent,#ff5722),transparent)}
1731
- .fx-bench-label{font-size:.6rem;letter-spacing:.12em;text-transform:uppercase;opacity:.5;margin-bottom:.5rem;font-family:monospace}
1732
- .fx-bench-num{font-size:clamp(2rem,5vw,3.5rem);font-weight:900;letter-spacing:-.04em;line-height:1;color:var(--accent,#ff5722)}
1733
- .fx-bench-vs{font-size:.7rem;opacity:.4;margin-top:.25rem;font-family:monospace}
1734
- .fx-bench-bar{margin-top:1rem;height:5px;background:rgba(255,255,255,.06);border-radius:3px;overflow:hidden}
1735
- .fx-bench-fill{height:100%;border-radius:3px;background:var(--accent,#ff5722);transition:width 1.5s cubic-bezier(.4,0,.2,1)}
1736
- /* ── install ── */
1737
- .fx-install-wrap{border-radius:.875rem;overflow:hidden;border:1px solid rgba(255,255,255,.08);margin:0 2.5rem 2rem;max-width:540px}
1738
- .fx-install-body{padding:1.25rem 1.5rem}
1739
- .fx-install-line{display:flex;gap:.75rem;padding:.25rem 0;font-family:"JetBrains Mono","Courier New",monospace;font-size:.8rem;line-height:1.7}
1740
- .fx-install-prompt{color:var(--accent,#ff5722);flex-shrink:0}
1741
- .fx-install-cmd{color:rgba(255,255,255,.85)}
1742
- .fx-install-comment{font-family:"JetBrains Mono","Courier New",monospace;font-size:.72rem;color:rgba(255,255,255,.25);padding:.25rem 0;font-style:italic}
1743
- /* ── stats upgrade ── */
1744
- .fx-stat-vs{font-size:.65rem;opacity:.35;margin-top:.2rem;letter-spacing:.02em}
1745
- /* ── hero landing (dark variant) grid + glow ── */
1746
- .fx-hero-landing{position:relative;overflow:hidden}
1747
- .fx-hero-landing::before{content:"";position:absolute;inset:0;background:linear-gradient(rgba(255,255,255,.05) 1px,transparent 1px),linear-gradient(90deg,rgba(255,255,255,.05) 1px,transparent 1px);background-size:60px 60px;mask-image:radial-gradient(ellipse 70% 60% at 50% 50%,black,transparent);pointer-events:none}
1748
- .fx-hero-landing::after{content:"";position:absolute;width:700px;height:500px;border-radius:50%;background:radial-gradient(ellipse,rgba(255,87,34,.13) 0%,transparent 70%);left:50%;top:50%;transform:translate(-50%,-50%);pointer-events:none;animation:fx-breathe 6s ease-in-out infinite}
1749
- @keyframes fx-breathe{0%,100%{transform:translate(-50%,-50%) scale(1)}50%{transform:translate(-50%,-50%) scale(1.1)}}
1750
- /* ── feature grid ── */
1751
- .fx-grid-feature{gap:1rem}
1752
- .fx-grid-feature .fx-card{transition:border-color .2s,transform .15s}
1753
- .fx-grid-feature .fx-card:hover{border-color:rgba(255,87,34,.25)}
1754
- .fx-grid-feature .fx-icon{width:44px;height:44px;border-radius:.75rem;display:flex;align-items:center;justify-content:center;background:rgba(255,87,34,.08);border:1px solid rgba(255,87,34,.15)}
1755
- /* ── footer upgrade ── */
1756
- .fx-footer-inner{max-width:1100px;margin:0 auto;display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:1rem}
1757
- .fx-footer-brand{font-size:1rem;font-weight:800;letter-spacing:-.02em}
1758
- .fx-footer-links{display:flex;gap:1.5rem;flex-wrap:wrap}
1759
- .fx-footer-note{font-size:.72rem;opacity:.3;font-family:monospace}
1760
- .fx-year{font-variant-numeric:tabular-nums}
1761
- .fx-hero-minimal{min-height:50vh!important}
1762
- .fx-hero-minimal .fx-hero-inner{gap:1rem}
1763
- .fx-hero-tall{min-height:98vh!important}
1764
- .fx-hero-left .fx-hero-inner{text-align:left;align-items:flex-start;max-width:none;padding-left:2.5rem}
1765
- .fx-hero-left{justify-content:flex-start}
1766
- .fx-hero-dark-cta .fx-hero-ctas-dark{display:flex;gap:.75rem;flex-wrap:wrap;justify-content:center;padding:.75rem;background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.08);border-radius:.875rem;margin-top:.5rem}
1767
- .fx-spacer{width:100%}
1768
- .fx-divider{display:flex;align-items:center;gap:1rem;padding:2rem 2.5rem;opacity:.4}
1769
- .fx-divider::before,.fx-divider::after{content:'';flex:1;height:1px;background:currentColor}
1770
- .fx-divider-label{font-size:.75rem;font-family:monospace;white-space:nowrap;letter-spacing:.08em;text-transform:uppercase}
1771
- .fx-hr{border:none;border-top:1px solid rgba(255,255,255,.08);margin:1.5rem 2.5rem}
1772
- .fx-badge-row{padding:.5rem 2.5rem;display:flex;flex-wrap:wrap;gap:.5rem}
1773
- .fx-badge-tag{display:inline-block;font-size:.75rem;font-weight:600;padding:.3rem .875rem;border-radius:999px;background:rgba(37,99,235,.12);border:1px solid rgba(37,99,235,.25);color:#60a5fa;letter-spacing:.03em}
1774
- .fx-cols{display:grid;gap:1.5rem;padding:1rem 2.5rem}
1775
- .fx-cols-2{grid-template-columns:1fr 1fr}
1776
- .fx-cols-3{grid-template-columns:1fr 1fr 1fr}
1777
- .fx-cols-4{grid-template-columns:repeat(4,1fr)}
1778
- @media(max-width:640px){.fx-cols-2,.fx-cols-3,.fx-cols-4{grid-template-columns:1fr}}
2403
+ .fx-code-line{font-family:var(--aip-font-mono);font-size:.8rem;line-height:1.8;color:var(--aip-text-muted);white-space:pre}
2404
+ .fx-kw{color:#c792ea}.fx-st{color:#c3e88d}.fx-fn{color:#82aaff}.fx-nb{color:#f78c6c}
2405
+ .fx-op{color:var(--aip-accent)}.fx-comment{color:var(--aip-text-dim);font-style:italic}
2406
+
2407
+ /* ═══════════════════════════════════════════
2408
+ INSTALL BLOCK
2409
+ ═══════════════════════════════════════════ */
2410
+ .fx-install-wrap{
2411
+ border-radius:.875rem;overflow:hidden;
2412
+ border:1px solid var(--aip-border);
2413
+ background:var(--aip-surface);
2414
+ margin:0 2.5rem 2rem;max-width:540px;
2415
+ }
2416
+ .fx-install-body{padding:1.375rem 1.5rem}
2417
+ .fx-install-line{display:flex;gap:.875rem;padding:.25rem 0;font-family:var(--aip-font-mono);font-size:.8rem;line-height:1.75}
2418
+ .fx-install-prompt{color:var(--aip-accent);flex-shrink:0;font-weight:700}
2419
+ .fx-install-cmd{color:var(--aip-text)}
2420
+ .fx-install-comment{font-family:var(--aip-font-mono);font-size:.72rem;color:var(--aip-text-dim);padding:.25rem 0;font-style:italic}
2421
+
2422
+ /* ═══════════════════════════════════════════
2423
+ BENCHMARK CARDS
2424
+ ═══════════════════════════════════════════ */
2425
+ .fx-benchmark{
2426
+ display:grid;
2427
+ grid-template-columns:repeat(auto-fit,minmax(220px,1fr));
2428
+ gap:1rem;padding:0 2.5rem 4rem;
2429
+ }
2430
+ .fx-bench-card{
2431
+ border-radius:1rem;padding:1.5rem;
2432
+ background:var(--aip-surface);
2433
+ border:1px solid var(--aip-border);
2434
+ position:relative;overflow:hidden;
2435
+ transition:border-color .2s,transform .15s;
2436
+ }
2437
+ .fx-bench-card::after{
2438
+ content:'';position:absolute;top:0;left:0;right:0;height:2px;
2439
+ background:linear-gradient(90deg,transparent,var(--aip-accent),transparent);
2440
+ }
2441
+ .fx-bench-card:hover{border-color:var(--aip-border-strong);transform:translateY(-2px)}
2442
+ .fx-bench-label{font-size:.62rem;letter-spacing:.12em;text-transform:uppercase;color:var(--aip-text-dim);margin-bottom:.625rem;font-weight:600}
2443
+ .fx-bench-num{font-size:clamp(2rem,5vw,3rem);font-weight:900;letter-spacing:-.05em;line-height:1;color:var(--aip-accent)}
2444
+ .fx-bench-vs{font-size:.7rem;color:var(--aip-text-dim);margin-top:.375rem;font-family:var(--aip-font-mono)}
2445
+ .fx-bench-bar{margin-top:1.125rem;height:4px;background:rgba(var(--aip-accent-rgb),.1);border-radius:2px;overflow:hidden}
2446
+ .fx-bench-fill{height:100%;border-radius:2px;background:var(--aip-accent);transition:width 1.5s cubic-bezier(.4,0,.2,1)}
2447
+
2448
+ /* ═══════════════════════════════════════════
2449
+ MARQUEE
2450
+ ═══════════════════════════════════════════ */
2451
+ .fx-marquee{
2452
+ overflow:hidden;
2453
+ padding:1.375rem 0;
2454
+ border-top:1px solid var(--aip-border);
2455
+ border-bottom:1px solid var(--aip-border);
2456
+ -webkit-mask:linear-gradient(90deg,transparent,black 8%,black 92%,transparent);
2457
+ mask:linear-gradient(90deg,transparent,black 8%,black 92%,transparent);
2458
+ }
2459
+ .fx-marquee-track{display:flex;width:max-content;animation:fx-marquee 28s linear infinite}
2460
+ .fx-marquee:hover .fx-marquee-track{animation-play-state:paused}
2461
+ @keyframes fx-marquee{0%{transform:translateX(0)}100%{transform:translateX(-50%)}}
2462
+ .fx-marquee-item{font-size:.875rem;font-weight:600;color:var(--aip-text-dim);white-space:nowrap;padding:0 1.75rem;transition:color .2s}
2463
+ .fx-marquee-item:hover{color:var(--aip-text-muted)}
2464
+ .fx-marquee-sep{color:var(--aip-border-strong);padding:0 .25rem}
2465
+
2466
+ /* ═══════════════════════════════════════════
2467
+ CTA SECTION
2468
+ ═══════════════════════════════════════════ */
2469
+ .fx-cta-section{
2470
+ position:relative;padding:7rem 2.5rem;text-align:center;overflow:hidden;
2471
+ border-top:1px solid var(--aip-border);
2472
+ }
2473
+ .fx-cta-glow{
2474
+ position:absolute;width:700px;height:400px;border-radius:50%;
2475
+ background:radial-gradient(ellipse,rgba(var(--aip-accent-rgb),.12),transparent 65%);
2476
+ left:50%;top:50%;transform:translate(-50%,-50%);
2477
+ pointer-events:none;
2478
+ }
2479
+ .fx-cta-inner{position:relative;z-index:1;max-width:44rem;margin:0 auto;display:flex;flex-direction:column;align-items:center;gap:1.75rem}
2480
+ .fx-cta-title{font-size:clamp(2rem,5vw,4rem);font-weight:900;letter-spacing:-.05em;line-height:1.05}
2481
+ .fx-cta-sub{font-size:1.0625rem;line-height:1.7;color:var(--aip-text-muted);max-width:36rem}
2482
+ .fx-cta-actions{display:flex;gap:1rem;flex-wrap:wrap;justify-content:center}
2483
+
2484
+ /* ═══════════════════════════════════════════
2485
+ STEPS
2486
+ ═══════════════════════════════════════════ */
2487
+ .fx-steps{
2488
+ display:grid;
2489
+ grid-template-columns:repeat(auto-fit,minmax(220px,1fr));
2490
+ gap:2.5rem;
2491
+ padding:1.5rem 2.5rem 5rem;
2492
+ position:relative;
2493
+ }
2494
+ .fx-steps::before{
2495
+ content:'';position:absolute;top:2.75rem;
2496
+ left:calc(2.5rem + 2rem);right:calc(2.5rem + 2rem);
2497
+ height:1px;
2498
+ background:linear-gradient(90deg,transparent,var(--aip-border-strong),transparent);
2499
+ pointer-events:none;
2500
+ }
2501
+ @media(max-width:640px){.fx-steps::before{display:none}.fx-steps{gap:2rem;padding:1rem 1.5rem 3rem}}
2502
+ .fx-step{display:flex;flex-direction:column;align-items:flex-start;gap:.875rem}
2503
+ .fx-step-num{
2504
+ width:44px;height:44px;border-radius:50%;
2505
+ background:var(--aip-accent);color:#fff;
2506
+ font-weight:900;font-size:1rem;
2507
+ display:flex;align-items:center;justify-content:center;
2508
+ flex-shrink:0;position:relative;z-index:1;
2509
+ box-shadow:0 0 0 4px rgba(var(--aip-accent-rgb),.15),0 0 0 8px rgba(var(--aip-accent-rgb),.05);
2510
+ }
2511
+ .fx-step-title{font-size:.9375rem;font-weight:700;letter-spacing:-.02em;color:var(--aip-text)}
2512
+ .fx-step-desc{font-size:.8375rem;line-height:1.65;color:var(--aip-text-muted)}
2513
+
2514
+ /* ═══════════════════════════════════════════
2515
+ COMPARE
2516
+ ═══════════════════════════════════════════ */
2517
+ .fx-compare{max-width:600px;margin:0 auto 4rem;padding:0 2.5rem;border-radius:1rem;overflow:hidden;border:1px solid var(--aip-border)}
2518
+ .fx-compare-header{
2519
+ display:grid;grid-template-columns:1fr 1fr 1fr;
2520
+ padding:.75rem 1.125rem;
2521
+ background:var(--aip-surface-hover);
2522
+ font-size:.68rem;font-weight:700;text-transform:uppercase;letter-spacing:.1em;color:var(--aip-text-dim);
2523
+ border-bottom:1px solid var(--aip-border);
2524
+ }
2525
+ .fx-compare-row{
2526
+ display:grid;grid-template-columns:1fr 1fr 1fr;
2527
+ padding:.75rem 1.125rem;
2528
+ border-bottom:1px solid var(--aip-border);
2529
+ transition:background .1s;
2530
+ }
2531
+ .fx-compare-row:last-child{border-bottom:none}
2532
+ .fx-compare-row:hover{background:var(--aip-surface-hover)}
2533
+ .fx-compare-feature{font-size:.875rem;color:var(--aip-text-muted)}
2534
+ .fx-compare-col-a{text-align:center;font-size:.875rem;font-weight:600;color:#4ade80}
2535
+ .fx-compare-col-b{text-align:center;font-size:.875rem;color:var(--aip-text-dim)}
2536
+
2537
+ /* ═══════════════════════════════════════════
2538
+ VIDEO
2539
+ ═══════════════════════════════════════════ */
2540
+ .fx-video-wrap{padding:0 2.5rem 3rem}
2541
+ .fx-video-yt{position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:1rem;border:1px solid var(--aip-border);background:var(--aip-surface)}
2542
+ .fx-video-yt iframe{position:absolute;top:0;left:0;width:100%;height:100%}
2543
+ .fx-video{width:100%;border-radius:1rem;border:1px solid var(--aip-border)}
2544
+
2545
+ /* ═══════════════════════════════════════════
2546
+ TESTIMONIAL
2547
+ ═══════════════════════════════════════════ */
2548
+ .fx-testi-wrap{padding:5rem 2.5rem;display:flex;justify-content:center}
2549
+ .fx-testi{max-width:44rem;text-align:center;display:flex;flex-direction:column;align-items:center;gap:1.5rem}
2550
+ .fx-testi-img,.fx-testi-avatar{width:56px;height:56px;border-radius:50%;object-fit:cover}
2551
+ .fx-testi-avatar{display:flex;align-items:center;justify-content:center;font-size:1.25rem;font-weight:800;background:var(--aip-surface);border:1px solid var(--aip-border);color:var(--aip-text)}
2552
+ .fx-testi-quote{font-size:1.1875rem;line-height:1.7;font-style:italic;color:var(--aip-text-muted)}
2553
+ .fx-testi-author{font-size:.8125rem;font-weight:600;color:var(--aip-text-dim)}
2554
+
2555
+ /* ═══════════════════════════════════════════
2556
+ GALLERY
2557
+ ═══════════════════════════════════════════ */
2558
+ .fx-gallery{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:.75rem;padding:1rem 2.5rem 4rem}
2559
+ .fx-gallery-item{border-radius:.75rem;overflow:hidden;aspect-ratio:4/3;border:1px solid var(--aip-border)}
2560
+ .fx-gallery-item img{width:100%;height:100%;object-fit:cover;transition:transform .35s var(--aip-ease-out)}
2561
+ .fx-gallery-item:hover img{transform:scale(1.04)}
2562
+
2563
+ /* ═══════════════════════════════════════════
2564
+ MISC
2565
+ ═══════════════════════════════════════════ */
2566
+ .fx-divider{display:flex;align-items:center;gap:1rem;padding:.875rem 2.5rem;color:var(--aip-text-dim);font-size:.8125rem}
2567
+ .fx-divider::before,.fx-divider::after{content:'';flex:1;height:1px;background:var(--aip-border)}
2568
+ .fx-hr{border:none;height:1px;background:var(--aip-border);margin:0 2.5rem}
2569
+ .fx-badge-row{padding:.5rem 2.5rem}
2570
+ .fx-badge-tag{font-size:.75rem;font-weight:700;padding:.25rem .75rem;border-radius:999px;background:rgba(var(--aip-accent-rgb),.12);color:var(--aip-accent);border:1px solid rgba(var(--aip-accent-rgb),.25);letter-spacing:.04em}
2571
+ .fx-spacer{flex-shrink:0}
2572
+ .fx-html{padding:0 2.5rem}
2573
+ .fx-cols{display:grid;gap:1.5rem;padding:1rem 2.5rem 3rem}
1779
2574
  .fx-col{min-width:0}
1780
- .fx-each{padding:.5rem 2.5rem}
1781
- .fx-each-list{display:flex;flex-direction:column;gap:.5rem}
1782
- .fx-each-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:.75rem}
1783
- .fx-html{padding:.5rem 2.5rem}
1784
- .fx-card-badge{display:inline-block;font-size:.65rem;font-weight:700;padding:.2rem .6rem;border-radius:999px;background:rgba(37,99,235,.15);color:#93c5fd;margin-bottom:.5rem;letter-spacing:.04em}
1785
- .fx-form-inline{padding:.75rem 2.5rem}.fx-form-inline-form{display:flex;align-items:flex-end;gap:.75rem;flex-wrap:wrap;background:none;border:none;padding:0;max-width:none}.fx-form-inline-form .fx-field{flex:1;min-width:160px;margin-bottom:0}.fx-btn-inline{width:auto;margin-top:0;flex-shrink:0}
1786
- .fx-form-minimal{padding:.5rem 2.5rem;max-width:24rem}.fx-form-minimal form{background:none;border:none;padding:0}
1787
- .fx-sect-accent{background:rgba(37,99,235,.06);border-left:3px solid #2563eb;padding-left:2rem}
1788
- .fx-sect-dark{background:rgba(0,0,0,.4)}
1789
- .fx-sect-full{padding:6rem 2.5rem}
1790
- .fx-pricing-compact{border-radius:.875rem;padding:1.25rem;display:flex;align-items:center;gap:1rem;border:1px solid rgba(255,255,255,.08)}
1791
- .fx-pricing-price-sm{font-size:1.5rem;font-weight:800;letter-spacing:-.04em}
1792
- .fx-grid-numbered>.fx-card{counter-increment:card-counter}
1793
- .fx-chart-wrap{padding:1rem 2.5rem;position:relative}.fx-chart-title{font-family:monospace;font-size:.65rem;letter-spacing:.1em;text-transform:uppercase;color:#475569;margin-bottom:.75rem}.fx-chart{max-height:320px}
1794
- .fx-kanban{display:flex;gap:1rem;padding:1rem 2.5rem;overflow-x:auto;align-items:flex-start}.fx-kanban-col{flex:0 0 280px;background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.08);border-radius:.875rem;padding:1rem}.fx-kanban-col-title{font-family:monospace;font-size:.65rem;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:#64748b;margin-bottom:.875rem}.fx-kanban-cards{min-height:80px;display:flex;flex-direction:column;gap:.5rem}.fx-kanban-card{background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.1);border-radius:.5rem;padding:.75rem;cursor:grab;font-size:.8125rem;line-height:1.5;transition:transform .15s,box-shadow .15s}.fx-kanban-card:hover{transform:translateY(-1px);box-shadow:0 4px 12px rgba(0,0,0,.3)}.fx-kanban-card.dragging{opacity:.5;cursor:grabbing}
1795
- .fx-editor-wrap{padding:.75rem 2.5rem}.fx-editor-toolbar{display:flex;gap:.25rem;margin-bottom:.5rem;flex-wrap:wrap}.fx-editor-btn{background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.1);color:#e2e8f0;border-radius:.375rem;padding:.25rem .625rem;cursor:pointer;font-size:.8125rem;font-family:inherit;transition:background .1s}.fx-editor-btn:hover{background:rgba(255,255,255,.12)}.fx-editor{min-height:160px;padding:1rem;background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.1);border-radius:.625rem;color:#e2e8f0;font-size:.875rem;line-height:1.7;outline:none}.fx-editor:empty::before{content:attr(placeholder);color:#475569;pointer-events:none}.fx-editor-save{margin-left:auto}
1796
- .fx-grid-numbered>.fx-card::before{content:counter(card-counter,decimal-leading-zero);font-size:2rem;font-weight:900;opacity:.15;font-family:monospace;line-height:1}
1797
- .fx-grid-bordered>.fx-card{border:1px solid rgba(255,255,255,.08)}@keyframes fx-fade-up{from{opacity:0;transform:translateY(20px)}to{opacity:1;transform:none}}@keyframes fx-fade-in{from{opacity:0}to{opacity:1}}@keyframes fx-slide-left{from{opacity:0;transform:translateX(30px)}to{opacity:1;transform:none}}@keyframes fx-slide-right{from{opacity:0;transform:translateX(-30px)}to{opacity:1;transform:none}}@keyframes fx-zoom-in{from{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}@keyframes fx-blur-in{from{opacity:0;filter:blur(8px)}to{opacity:1;filter:blur(0)}}.fx-anim-fade-up{animation:fx-fade-up .6s cubic-bezier(.4,0,.2,1) both}.fx-anim-fade-in{animation:fx-fade-in .6s ease both}.fx-anim-slide-left{animation:fx-slide-left .6s cubic-bezier(.4,0,.2,1) both}.fx-anim-slide-right{animation:fx-slide-right .6s cubic-bezier(.4,0,.2,1) both}.fx-anim-zoom-in{animation:fx-zoom-in .5s cubic-bezier(.4,0,.2,1) both}.fx-anim-blur-in{animation:fx-blur-in .7s ease both}.fx-anim-stagger>.fx-card:nth-child(1){animation:fx-fade-up .5s 0s both}.fx-anim-stagger>.fx-card:nth-child(2){animation:fx-fade-up .5s .1s both}.fx-anim-stagger>.fx-card:nth-child(3){animation:fx-fade-up .5s .2s both}.fx-anim-stagger>.fx-card:nth-child(4){animation:fx-fade-up .5s .3s both}.fx-anim-stagger>.fx-card:nth-child(5){animation:fx-fade-up .5s .4s both}.fx-anim-stagger>.fx-card:nth-child(6){animation:fx-fade-up .5s .5s both}`
1798
-
1799
- const T={
1800
- dark: `body{background:#030712;color:#f1f5f9}.fx-nav{border-bottom:1px solid #1e293b;background:rgba(3,7,18,.85)}.fx-nav-link{color:#cbd5e1}.fx-sub{color:#94a3b8}.fx-cta{background:#2563eb;color:#fff;box-shadow:0 8px 24px rgba(37,99,235,.35)}.fx-stat-lbl{color:#64748b}.fx-card{background:#0f172a;border:1px solid #1e293b}.fx-card:hover{box-shadow:0 20px 40px rgba(0,0,0,.5)}.fx-card-body{color:#64748b}.fx-sect-body{color:#64748b}.fx-form{background:#0f172a;border:1px solid #1e293b}.fx-label{color:#94a3b8}.fx-input{background:#020617;border:1px solid #1e293b;color:#f1f5f9}.fx-input::placeholder{color:#334155}.fx-btn{background:#2563eb;color:#fff;box-shadow:0 4px 14px rgba(37,99,235,.4)}.fx-th{color:#475569;border-bottom:1px solid #1e293b}.fx-tr:hover{background:#0f172a}.fx-td{border-bottom:1px solid rgba(255,255,255,.03)}.fx-footer{border-top:1px solid #1e293b}.fx-footer-text{color:#334155}.fx-pricing-card{background:#0f172a;border:1px solid #1e293b}.fx-faq-item{background:#0f172a}.fx-faq-item:hover{background:#111827}`,
1801
- light: `body{background:#fff;color:#0f172a}.fx-nav{border-bottom:1px solid #e2e8f0;background:rgba(255,255,255,.85)}.fx-nav-link{color:#475569}.fx-sub{color:#475569}.fx-cta{background:#2563eb;color:#fff}.fx-stat-lbl{color:#94a3b8}.fx-card{background:#f8fafc;border:1px solid #e2e8f0}.fx-card:hover{box-shadow:0 20px 40px rgba(0,0,0,.08)}.fx-card-body{color:#475569}.fx-sect-body{color:#475569}.fx-form{background:#f8fafc;border:1px solid #e2e8f0}.fx-label{color:#475569}.fx-input{background:#fff;border:1px solid #cbd5e1;color:#0f172a}.fx-btn{background:#2563eb;color:#fff}.fx-th{color:#94a3b8;border-bottom:1px solid #e2e8f0}.fx-tr:hover{background:#f8fafc}.fx-footer{border-top:1px solid #e2e8f0}.fx-footer-text{color:#94a3b8}.fx-pricing-card{background:#f8fafc;border:1px solid #e2e8f0}.fx-faq-item{background:#f8fafc}`,
1802
- acid: `body{background:#000;color:#a3e635}.fx-nav{border-bottom:1px solid #1a2e05;background:rgba(0,0,0,.9)}.fx-nav-link{color:#86efac}.fx-sub{color:#4d7c0f}.fx-cta{background:#a3e635;color:#000;font-weight:800}.fx-stat-lbl{color:#365314}.fx-card{background:#0a0f00;border:1px solid #1a2e05}.fx-card-body{color:#365314}.fx-sect-body{color:#365314}.fx-form{background:#0a0f00;border:1px solid #1a2e05}.fx-label{color:#4d7c0f}.fx-input{background:#000;border:1px solid #1a2e05;color:#a3e635}.fx-btn{background:#a3e635;color:#000;font-weight:800}.fx-th{color:#365314;border-bottom:1px solid #1a2e05}.fx-footer{border-top:1px solid #1a2e05}.fx-footer-text{color:#1a2e05}.fx-pricing-card{background:#0a0f00;border:1px solid #1a2e05}.fx-faq-item{background:#0a0f00}`,
1803
- }
1804
- return base+(T[theme]||T.dark)
2575
+ .fx-chart-container{padding:0 2.5rem 3rem}
2576
+ .fx-select-wrap{padding:.5rem 2.5rem}
2577
+ .fx-select-block{width:auto;min-width:200px;margin-top:0}
2578
+ .fx-each{padding:0 2.5rem 2rem}
2579
+ .fx-each-empty{padding:2rem;text-align:center;color:var(--aip-text-dim);font-size:.875rem}
2580
+ .fx-if-wrap{display:contents}
2581
+ .fx-editor-wrap{padding:0 2.5rem 2rem}
2582
+
2583
+ /* ═══════════════════════════════════════════
2584
+ SCROLL ANIMATIONS
2585
+ ═══════════════════════════════════════════ */
2586
+ .fx-animate{
2587
+ opacity:0;
2588
+ transform:translateY(18px);
2589
+ transition:opacity .65s var(--aip-ease-out),transform .65s var(--aip-ease-out);
2590
+ }
2591
+ .fx-animate.fx-visible{opacity:1;transform:none}
2592
+ .fx-animate-stagger>*{
2593
+ opacity:0;transform:translateY(14px);
2594
+ transition:opacity .55s var(--aip-ease-out),transform .55s var(--aip-ease-out);
2595
+ }
2596
+ .fx-animate-stagger.fx-visible>*:nth-child(1){opacity:1;transform:none;transition-delay:.04s}
2597
+ .fx-animate-stagger.fx-visible>*:nth-child(2){opacity:1;transform:none;transition-delay:.12s}
2598
+ .fx-animate-stagger.fx-visible>*:nth-child(3){opacity:1;transform:none;transition-delay:.2s}
2599
+ .fx-animate-stagger.fx-visible>*:nth-child(4){opacity:1;transform:none;transition-delay:.28s}
2600
+ .fx-animate-stagger.fx-visible>*:nth-child(5){opacity:1;transform:none;transition-delay:.36s}
2601
+ .fx-animate-stagger.fx-visible>*:nth-child(6){opacity:1;transform:none;transition-delay:.44s}
2602
+
2603
+ /* Number counter */
2604
+ .fx-count{display:inline-block;font-variant-numeric:tabular-nums}
2605
+ .fx-year{font-variant-numeric:tabular-nums}
2606
+
2607
+ /* Hero badge */
2608
+ .fx-hero-badge{display:inline-flex;align-items:center;gap:.5rem;font-size:.7rem;letter-spacing:.12em;text-transform:uppercase;font-weight:600;padding:.3125rem .875rem;border-radius:999px;border:1px solid var(--aip-border-strong);background:var(--aip-surface);color:var(--aip-text-muted)}
2609
+ .fx-hero-badge-dot{width:6px;height:6px;border-radius:50%;background:var(--aip-accent);animation:fx-pulse 2.5s ease infinite;flex-shrink:0}
2610
+
2611
+ /* Footer */
2612
+ .fx-footer{
2613
+ padding:2.5rem;
2614
+ border-top:1px solid var(--aip-border);
2615
+ }
2616
+ .fx-footer-inner{
2617
+ max-width:1100px;margin:0 auto;
2618
+ display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:1.5rem;
2619
+ }
2620
+ .fx-footer-brand{font-size:.9375rem;font-weight:800;letter-spacing:-.03em;color:var(--aip-text)}
2621
+ .fx-footer-links{display:flex;gap:1.75rem;flex-wrap:wrap}
2622
+ .fx-footer-link{font-size:.8125rem;color:var(--aip-text-dim);transition:color .15s}
2623
+ .fx-footer-link:hover{color:var(--aip-text-muted)}
2624
+ .fx-footer-note{font-size:.75rem;color:var(--aip-text-dim);font-family:var(--aip-font-mono)}
2625
+ .fx-footer-text{font-size:.8125rem;color:var(--aip-text-dim)}
2626
+ @media(max-width:640px){.fx-footer{padding:2rem 1.5rem}.fx-footer-inner{flex-direction:column;align-items:flex-start;gap:1rem}}
2627
+ `
2628
+
2629
+ // ════════════════════════════════════════════════════════════════
2630
+ // TEMAS — CSS custom properties por tema
2631
+ // ════════════════════════════════════════════════════════════════
2632
+ const T = {
2633
+ dark: `
2634
+ :root{
2635
+ --aip-bg:#030712;
2636
+ --aip-bg-rgb:3,7,18;
2637
+ --aip-surface:#0d1117;
2638
+ --aip-surface-hover:#111827;
2639
+ --aip-border:rgba(255,255,255,.07);
2640
+ --aip-border-strong:rgba(255,255,255,.12);
2641
+ --aip-text:#f0f4ff;
2642
+ --aip-text-muted:#8b9ab5;
2643
+ --aip-text-dim:#3d4f68;
2644
+ --aip-accent:#ff5722;
2645
+ --aip-accent-rgb:255,87,34;
2646
+ --aip-accent-light:#ff8a50;
2647
+ --aip-grid-line:rgba(255,255,255,.03);
2648
+ }`,
2649
+ light: `
2650
+ :root{
2651
+ --aip-bg:#ffffff;
2652
+ --aip-bg-rgb:255,255,255;
2653
+ --aip-surface:#f8fafc;
2654
+ --aip-surface-hover:#f1f5f9;
2655
+ --aip-border:rgba(0,0,0,.07);
2656
+ --aip-border-strong:rgba(0,0,0,.12);
2657
+ --aip-text:#0f172a;
2658
+ --aip-text-muted:#475569;
2659
+ --aip-text-dim:#94a3b8;
2660
+ --aip-accent:#ff5722;
2661
+ --aip-accent-rgb:255,87,34;
2662
+ --aip-accent-light:#ff8a50;
2663
+ --aip-grid-line:rgba(0,0,0,.04);
2664
+ }`,
2665
+ }
2666
+ return base + (T[theme] || T.dark)
1805
2667
  }
2668
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aiplang",
3
- "version": "2.11.6",
3
+ "version": "2.11.8",
4
4
  "description": "AI-first web language. One .aip file = complete app. Frontend + backend + database + auth.",
5
5
  "keywords": [
6
6
  "aiplang",
package/server/server.js CHANGED
@@ -2432,7 +2432,7 @@ async function startServer(aipFile, port = 3000) {
2432
2432
  })
2433
2433
 
2434
2434
  srv.addRoute('GET', '/health', (req, res) => res.json(200, {
2435
- status:'ok', version:'2.11.6',
2435
+ status:'ok', version:'2.11.8',
2436
2436
  models: app.models.map(m=>m.name),
2437
2437
  routes: app.apis.length, pages: app.pages.length,
2438
2438
  admin: app.admin?.prefix || null,