aiplang 2.7.3 → 2.8.0
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/aiplang-knowledge.md +32 -0
- package/bin/aiplang.js +175 -19
- package/package.json +1 -1
- package/server/server.js +1 -1
package/aiplang-knowledge.md
CHANGED
|
@@ -137,3 +137,35 @@ npx aiplang start app.aip # full-stack
|
|
|
137
137
|
npx aiplang serve # frontend dev
|
|
138
138
|
npx aiplang build pages/ # static build
|
|
139
139
|
```
|
|
140
|
+
|
|
141
|
+
## Customization (v2.8) — React-like props
|
|
142
|
+
|
|
143
|
+
### Block modifiers (apply to any block)
|
|
144
|
+
```
|
|
145
|
+
hero{...} variant:left|minimal|tall|dark-cta
|
|
146
|
+
row3{...} variant:bordered|numbered
|
|
147
|
+
form{...} variant:inline|minimal
|
|
148
|
+
pricing{...} variant:compact
|
|
149
|
+
sect{...} variant:accent|dark|full
|
|
150
|
+
bg:#hexcolor — background color on any block
|
|
151
|
+
style:{padding:2rem,color:red} — inline CSS
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### New blocks
|
|
155
|
+
```
|
|
156
|
+
card{Title|Subtitle|img:url|/path:Label|#Badge}
|
|
157
|
+
cols2{ left content || right content }
|
|
158
|
+
cols3{ col1 || col2 || col3 }
|
|
159
|
+
divider{Optional label}
|
|
160
|
+
hr{}
|
|
161
|
+
badge{Label text}
|
|
162
|
+
spacer{2rem}
|
|
163
|
+
html{<any>HTML with @state interpolation</any>}
|
|
164
|
+
each @list { template with {item.field} }
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Row colors (per card)
|
|
168
|
+
```
|
|
169
|
+
row3{blue|bolt>Fast>Desc|green|shield>Secure>Desc|red|fire>Hot>Desc}
|
|
170
|
+
# colors: red orange yellow green teal blue indigo purple pink cyan lime amber
|
|
171
|
+
```
|
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.
|
|
8
|
+
const VERSION = '2.8.0'
|
|
9
9
|
const RUNTIME_DIR = path.join(__dirname, '..', 'runtime')
|
|
10
10
|
const cmd = process.argv[2]
|
|
11
11
|
const args = process.argv.slice(3)
|
|
@@ -608,6 +608,15 @@ function parseBlock(line) {
|
|
|
608
608
|
if(_cm){extraClass=_cm[1];line=line.replace(_cm[0],'').trim()}
|
|
609
609
|
const _am=line.match(/\banimate:(\S+)/)
|
|
610
610
|
if(_am){animate=_am[1];line=line.replace(_am[0],'').trim()}
|
|
611
|
+
let variant=null
|
|
612
|
+
const _vm=line.match(/\bvariant:(\S+)/)
|
|
613
|
+
if(_vm){variant=_vm[1];line=line.replace(_vm[0],'').trim()}
|
|
614
|
+
let style=null
|
|
615
|
+
const _sm=line.match(/\bstyle:\{([^}]+)\}/)
|
|
616
|
+
if(_sm){style=_sm[1];line=line.replace(_sm[0],'').trim()}
|
|
617
|
+
let bg=null
|
|
618
|
+
const _bgm=line.match(/\bbg:(#[0-9a-fA-F]+|[a-z]+)/)
|
|
619
|
+
if(_bgm){bg=_bgm[1];line=line.replace(_bgm[0],'').trim()}
|
|
611
620
|
|
|
612
621
|
// ── raw{} HTML passthrough ──────────────────────────────────
|
|
613
622
|
if(line.startsWith('raw{')) {
|
|
@@ -623,7 +632,7 @@ function parseBlock(line) {
|
|
|
623
632
|
const em=content.match(/edit\s+(PUT|PATCH)\s+(\S+)/), dm=content.match(/delete\s+(?:DELETE\s+)?(\S+)/)
|
|
624
633
|
const clean=content.replace(/edit\s+(PUT|PATCH)\s+\S+/g,'').replace(/delete\s+(?:DELETE\s+)?\S+/g,'')
|
|
625
634
|
const cols=parseCols(clean)
|
|
626
|
-
return{kind:'table',binding,cols:Array.isArray(cols)?cols:[],empty:parseEmpty(clean),editPath:em?.[2]||null,editMethod:em?.[1]||'PUT',deletePath:dm?.[1]||null,deleteKey:'id',extraClass,animate}
|
|
635
|
+
return{kind:'table',binding,cols:Array.isArray(cols)?cols:[],empty:parseEmpty(clean),editPath:em?.[2]||null,editMethod:em?.[1]||'PUT',deletePath:dm?.[1]||null,deleteKey:'id',extraClass,animate,variant,style,bg}
|
|
627
636
|
}
|
|
628
637
|
|
|
629
638
|
// ── form ────────────────────────────────────────────────────
|
|
@@ -636,7 +645,7 @@ function parseBlock(line) {
|
|
|
636
645
|
const parts=head.trim().split(/\s+/)
|
|
637
646
|
const method=parts[0]&&['GET','POST','PUT','PATCH','DELETE'].includes(parts[0].toUpperCase())?parts[0].toUpperCase():'POST'
|
|
638
647
|
const bpath=parts[method===parts[0].toUpperCase()?1:0]||''
|
|
639
|
-
return{kind:'form',method,bpath,action,fields:parseFields(content)||[],extraClass,animate}
|
|
648
|
+
return{kind:'form',method,bpath,action,fields:parseFields(content)||[],extraClass,animate,variant,style,bg}
|
|
640
649
|
}
|
|
641
650
|
|
|
642
651
|
// ── pricing ─────────────────────────────────────────────────
|
|
@@ -646,7 +655,7 @@ function parseBlock(line) {
|
|
|
646
655
|
const pts=p.trim().split('>').map(x=>x.trim())
|
|
647
656
|
return{name:pts[0],price:pts[1],desc:pts[2],linkRaw:pts[3]}
|
|
648
657
|
}).filter(p=>p.name)
|
|
649
|
-
return{kind:'pricing',plans,extraClass,animate}
|
|
658
|
+
return{kind:'pricing',plans,extraClass,animate,variant,style,bg}
|
|
650
659
|
}
|
|
651
660
|
|
|
652
661
|
// ── faq ─────────────────────────────────────────────────────
|
|
@@ -679,6 +688,43 @@ function parseBlock(line) {
|
|
|
679
688
|
return{kind:'btn',label,method,bpath,action,confirm,extraClass,animate}
|
|
680
689
|
}
|
|
681
690
|
|
|
691
|
+
// ── card{} — standalone card customizável ──────────────────
|
|
692
|
+
if(line.startsWith('card{') || line.startsWith('card ')) {
|
|
693
|
+
const bi=line.indexOf('{'); if(bi===-1) return null
|
|
694
|
+
const body=line.slice(bi+1,line.lastIndexOf('}')).trim()
|
|
695
|
+
const parts=body.split('|').map(x=>x.trim())
|
|
696
|
+
const imgPart=parts.find(p=>p.startsWith('img:'))
|
|
697
|
+
const linkPart=parts.find(p=>p.startsWith('/'))
|
|
698
|
+
const title=parts.find(p=>!p.startsWith('img:')&&!p.startsWith('/')&&!p.startsWith('@')&&!p.startsWith('#'))||''
|
|
699
|
+
const subtitle=parts.filter(p=>!p.startsWith('img:')&&!p.startsWith('/')&&!p.startsWith('@')&&!p.startsWith('#'))[1]||''
|
|
700
|
+
const badge=parts.find(p=>p.startsWith('#'))?.slice(1)||null
|
|
701
|
+
const bind=parts.find(p=>p.startsWith('@'))||null
|
|
702
|
+
return{kind:'card',title,subtitle,img:imgPart?.slice(4)||null,link:linkPart||null,badge,bind,extraClass,animate,variant,style,bg}
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
// ── cols{} — grid de conteúdo livre ─────────────────────────
|
|
706
|
+
if(line.startsWith('cols{') || (line.startsWith('cols ') && line.includes('{'))) {
|
|
707
|
+
const bi=line.indexOf('{'); if(bi===-1) return null
|
|
708
|
+
const head=line.slice(0,bi).trim()
|
|
709
|
+
const m=head.match(/cols(\d+)/)
|
|
710
|
+
const n=m?parseInt(m[1]):2
|
|
711
|
+
const body=line.slice(bi+1,line.lastIndexOf('}')).trim()
|
|
712
|
+
const items=body.split('||').map(col=>col.trim()).filter(Boolean)
|
|
713
|
+
return{kind:'cols',n,items,extraClass,animate,variant,style,bg}
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
// ── divider{} — separador visual ─────────────────────────────
|
|
717
|
+
if(line.startsWith('divider') || line.startsWith('hr{')) {
|
|
718
|
+
const label=line.match(/\{([^}]*)\}/)?.[1]?.trim()||null
|
|
719
|
+
return{kind:'divider',label,extraClass,animate,variant,style}
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
// ── badge{} — label/tag destacado ───────────────────────────
|
|
723
|
+
if(line.startsWith('badge{') || line.startsWith('tag{')) {
|
|
724
|
+
const content=line.slice(line.indexOf('{')+1,line.lastIndexOf('}')).trim()
|
|
725
|
+
return{kind:'badge',content,extraClass,animate,variant,style}
|
|
726
|
+
}
|
|
727
|
+
|
|
682
728
|
// ── select ───────────────────────────────────────────────────
|
|
683
729
|
if(line.startsWith('select ')) {
|
|
684
730
|
const bi=line.indexOf('{')
|
|
@@ -693,12 +739,31 @@ function parseBlock(line) {
|
|
|
693
739
|
return{kind:'if',cond:line.slice(3,bi).trim(),inner:line.slice(bi+1,line.lastIndexOf('}')).trim(),extraClass,animate}
|
|
694
740
|
}
|
|
695
741
|
|
|
742
|
+
// ── each @list { template } — loop como React .map() ────────
|
|
743
|
+
if(line.startsWith('each ')) {
|
|
744
|
+
const bi=line.indexOf('{');if(bi===-1) return null
|
|
745
|
+
const binding=line.slice(5,bi).trim()
|
|
746
|
+
const tpl=line.slice(bi+1,line.lastIndexOf('}')).trim()
|
|
747
|
+
return{kind:'each',binding,tpl,extraClass,animate,variant}
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
// ── spacer{} — espaçamento customizável ──────────────────────
|
|
751
|
+
if(line.startsWith('spacer{') || line.startsWith('spacer ')) {
|
|
752
|
+
const h=line.match(/[{\s](\S+)[}]?/)?.[1]||'3rem'
|
|
753
|
+
return{kind:'spacer',height:h,extraClass,animate}
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
// ── html{} — HTML inline com interpolação de @state ──────────
|
|
757
|
+
if(line.startsWith('html{')) {
|
|
758
|
+
return{kind:'html',content:line.slice(5,line.lastIndexOf('}')),extraClass,animate}
|
|
759
|
+
}
|
|
760
|
+
|
|
696
761
|
// ── regular blocks (nav, hero, stats, rowN, sect, foot) ──────
|
|
697
762
|
const bi=line.indexOf('{');if(bi===-1) return null
|
|
698
763
|
const head=line.slice(0,bi).trim()
|
|
699
764
|
const body=line.slice(bi+1,line.lastIndexOf('}')).trim()
|
|
700
765
|
const m=head.match(/^([a-z]+)(\d+)$/)
|
|
701
|
-
return{kind:m?m[1]:head,cols:m?parseInt(m[2]):3,items:parseItems(body),extraClass,animate}
|
|
766
|
+
return{kind:m?m[1]:head,cols:m?parseInt(m[2]):3,items:parseItems(body),extraClass,animate,variant,style,bg}
|
|
702
767
|
}
|
|
703
768
|
|
|
704
769
|
function parseItems(body) {
|
|
@@ -734,14 +799,22 @@ function renderPage(page, allPages) {
|
|
|
734
799
|
const hydrate=needsJS?`\n<script>window.__AIPLANG_PAGE__=${config};</script>\n<script src="./aiplang-hydrate.js" defer></script>`:''
|
|
735
800
|
const customVars=page.customTheme?genCustomThemeVars(page.customTheme):''
|
|
736
801
|
const themeVarCSS=page.themeVars?genThemeVarCSS(page.themeVars):''
|
|
802
|
+
// Extract app name from nav brand if available
|
|
803
|
+
const _navBlock = page.blocks.find(b=>b.kind==='nav')
|
|
804
|
+
const _brand = _navBlock?.brand || ''
|
|
805
|
+
const _title = _brand ? `${esc(_brand)} — ${esc(page.id.charAt(0).toUpperCase()+page.id.slice(1))}` : esc(page.id.charAt(0).toUpperCase()+page.id.slice(1))
|
|
737
806
|
return `<!DOCTYPE html>
|
|
738
807
|
<html lang="en">
|
|
739
808
|
<head>
|
|
740
809
|
<meta charset="UTF-8">
|
|
741
810
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
742
|
-
<title>${
|
|
811
|
+
<title>${_title}</title>
|
|
743
812
|
<link rel="canonical" href="${esc(page.route)}">
|
|
744
813
|
<meta name="robots" content="index,follow">
|
|
814
|
+
<meta name="description" content="${esc((()=>{const h=page.blocks.find(b=>b.kind==='hero');if(!h)return '';const m=h.rawLine&&h.rawLine.match(/\{([^}]+)\}/);if(!m)return '';const p=m[1].split('>');const s=p[0].split('|')[1];return s?s.trim():''})())}">
|
|
815
|
+
<meta property="og:title" content="${_title}">
|
|
816
|
+
<meta property="og:type" content="website">
|
|
817
|
+
<meta property="og:type" content="website">
|
|
745
818
|
<style>${css(page.theme)}${customVars}${themeVarCSS}</style>
|
|
746
819
|
</head>
|
|
747
820
|
<body>
|
|
@@ -783,13 +856,31 @@ function rNav(b) {
|
|
|
783
856
|
|
|
784
857
|
function rHero(b) {
|
|
785
858
|
let h1='',sub='',img='',ctas=''
|
|
786
|
-
for(const item of b.items) for(const f of item){
|
|
859
|
+
for(const item of (b.items||[])) for(const f of item){
|
|
787
860
|
if(f.isImg) img=`<img src="${esc(f.src)}" class="fx-hero-img" alt="hero" loading="eager">`
|
|
788
861
|
else if(f.isLink) ctas+=`<a href="${esc(f.path)}" class="fx-cta">${esc(f.label)}</a>`
|
|
789
862
|
else if(!h1) h1=`<h1 class="fx-title">${esc(f.text)}</h1>`
|
|
790
863
|
else sub+=`<p class="fx-sub">${esc(f.text)}</p>`
|
|
791
864
|
}
|
|
792
|
-
|
|
865
|
+
const v = b.variant || (img ? 'split' : 'centered')
|
|
866
|
+
const bgStyle = b.bg ? ` style="background:${b.bg}"` : b.style ? ` style="${b.style.replace(/,/g,';')}"` : ''
|
|
867
|
+
const inlineStyle = b.style && !b.bg ? ` style="${b.style.replace(/,/g,';')}"` : ''
|
|
868
|
+
if (v === 'minimal') {
|
|
869
|
+
return `<section class="fx-hero fx-hero-minimal"${bgStyle}><div class="fx-hero-inner">${h1}${sub}${ctas}</div></section>\n`
|
|
870
|
+
}
|
|
871
|
+
if (v === 'tall') {
|
|
872
|
+
return `<section class="fx-hero fx-hero-tall"${bgStyle}><div class="fx-hero-inner">${h1}${sub}${ctas}</div>${img}</section>\n`
|
|
873
|
+
}
|
|
874
|
+
if (v === 'left') {
|
|
875
|
+
return `<section class="fx-hero fx-hero-left"${bgStyle}><div class="fx-hero-inner fx-hero-left-inner">${h1}${sub}${ctas}</div>${img}</section>\n`
|
|
876
|
+
}
|
|
877
|
+
if (v === 'dark-cta') {
|
|
878
|
+
return `<section class="fx-hero fx-hero-dark-cta"${bgStyle}><div class="fx-hero-inner">${h1}${sub}<div class="fx-hero-ctas-dark">${ctas}</div></div></section>\n`
|
|
879
|
+
}
|
|
880
|
+
if (img) {
|
|
881
|
+
return `<section class="fx-hero fx-hero-split"${bgStyle}><div class="fx-hero-inner">${h1}${sub}${ctas}</div>${img}</section>\n`
|
|
882
|
+
}
|
|
883
|
+
return `<section class="fx-hero"${bgStyle}><div class="fx-hero-inner">${h1}${sub}${ctas}</div></section>\n`
|
|
793
884
|
}
|
|
794
885
|
|
|
795
886
|
function rStats(b) {
|
|
@@ -802,27 +893,48 @@ function rStats(b) {
|
|
|
802
893
|
}
|
|
803
894
|
|
|
804
895
|
function rRow(b) {
|
|
896
|
+
const ACCENT_COLORS = {
|
|
897
|
+
red:'#f43f5e',orange:'#fb923c',yellow:'#fbbf24',green:'#22c55e',
|
|
898
|
+
teal:'#14b8a6',blue:'#3b82f6',indigo:'#6366f1',purple:'#a855f7',
|
|
899
|
+
pink:'#ec4899',cyan:'#06b6d4',lime:'#84cc16',amber:'#f59e0b'
|
|
900
|
+
}
|
|
805
901
|
const cards=(b.items||[]).map(item=>{
|
|
806
|
-
|
|
902
|
+
// First token can be color: red|rocket>Title>Body
|
|
903
|
+
let colorStyle='', firstIdx=0
|
|
904
|
+
if(item[0]&&!item[0].isImg&&!item[0].isLink){
|
|
905
|
+
const colorKey=item[0].text?.toLowerCase()
|
|
906
|
+
if(ACCENT_COLORS[colorKey]){
|
|
907
|
+
colorStyle=` style="--card-accent:${ACCENT_COLORS[colorKey]};border-top:2px solid ${ACCENT_COLORS[colorKey]}"`
|
|
908
|
+
firstIdx=1
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
const inner=item.slice(firstIdx).map((f,fi)=>{
|
|
807
912
|
if(f.isImg) return`<img src="${esc(f.src)}" class="fx-card-img" alt="" loading="lazy">`
|
|
808
913
|
if(f.isLink) return`<a href="${esc(f.path)}" class="fx-card-link">${esc(f.label)} →</a>`
|
|
809
|
-
if(fi===0) return`<div class="fx-icon">${ic(f.text)}</div>`
|
|
914
|
+
if(fi===0) return`<div class="fx-icon" style="${ACCENT_COLORS[f.text?.toLowerCase()]?'color:var(--card-accent)':''}">${ic(f.text)}</div>`
|
|
810
915
|
if(fi===1) return`<h3 class="fx-card-title">${esc(f.text)}</h3>`
|
|
811
916
|
return`<p class="fx-card-body">${esc(f.text)}</p>`
|
|
812
917
|
}).join('')
|
|
813
|
-
|
|
918
|
+
const bgStyle=b.bg?` style="background:${b.bg}"`:(b.variant==='bordered'?` style="border:1px solid var(--accent,#2563eb)22"`:colorStyle)
|
|
919
|
+
return`<div class="fx-card"${bgStyle}>${inner}</div>`
|
|
814
920
|
}).join('')
|
|
815
|
-
|
|
921
|
+
const v=b.variant||''
|
|
922
|
+
const wrapStyle=b.style?` style="${b.style.replace(/,/g,';')}"`:''
|
|
923
|
+
return `<div class="fx-grid fx-grid-${b.cols||3}${v?' fx-grid-'+v:''}"${wrapStyle}>${cards}</div>\n`
|
|
816
924
|
}
|
|
817
925
|
|
|
818
926
|
function rSect(b) {
|
|
819
927
|
let inner=''
|
|
820
|
-
b.items
|
|
928
|
+
const items = b.items || []
|
|
929
|
+
items.forEach((item,ii)=>(item||[]).forEach(f=>{
|
|
821
930
|
if(f.isLink) inner+=`<a href="${esc(f.path)}" class="fx-sect-link">${esc(f.label)}</a>`
|
|
822
931
|
else if(ii===0) inner+=`<h2 class="fx-sect-title">${esc(f.text)}</h2>`
|
|
823
932
|
else inner+=`<p class="fx-sect-body">${esc(f.text)}</p>`
|
|
824
933
|
}))
|
|
825
|
-
|
|
934
|
+
const bgStyle=b.bg?` style="background:${b.bg}"`:(b.style?` style="${b.style.replace(/,/g,';')}"`:'' )
|
|
935
|
+
const v = b.variant||''
|
|
936
|
+
const cls = v ? ` fx-sect-${v}` : ''
|
|
937
|
+
return `<section class="fx-sect${cls}"${bgStyle}>${inner}</section>\n`
|
|
826
938
|
}
|
|
827
939
|
|
|
828
940
|
function rFoot(b) {
|
|
@@ -854,8 +966,16 @@ function rForm(b) {
|
|
|
854
966
|
:`<input class="fx-input" type="${esc(f.type||'text')}" name="${esc(f.name)}" placeholder="${esc(f.placeholder)}">`
|
|
855
967
|
return`<div class="fx-field"><label class="fx-label">${esc(f.label)}</label>${inp}</div>`
|
|
856
968
|
}).join('')
|
|
857
|
-
const label=b.submitLabel||'
|
|
858
|
-
|
|
969
|
+
const label=b.submitLabel||'Enviar'
|
|
970
|
+
const bgStyle=b.bg?` style="background:${b.bg}"`:b.style?` style="${b.style.replace(/,/g,';')}"`:''
|
|
971
|
+
const v = b.variant||''
|
|
972
|
+
if(v==='inline') {
|
|
973
|
+
return `<div class="fx-form-inline"><form class="fx-form fx-form-inline-form" data-fx-form="${esc(b.bpath)}" data-fx-method="${esc(b.method)}" data-fx-action="${esc(b.action)}">${fields}<button type="submit" class="fx-btn fx-btn-inline">${esc(label)}</button><div class="fx-form-msg"></div></form></div>\n`
|
|
974
|
+
}
|
|
975
|
+
if(v==='minimal') {
|
|
976
|
+
return `<div class="fx-form-minimal"><form data-fx-form="${esc(b.bpath)}" data-fx-method="${esc(b.method)}" data-fx-action="${esc(b.action)}">${fields}<div class="fx-form-msg"></div><button type="submit" class="fx-btn">${esc(label)}</button></form></div>\n`
|
|
977
|
+
}
|
|
978
|
+
return `<div class="fx-form-wrap"><form class="fx-form"${bgStyle} data-fx-form="${esc(b.bpath)}" data-fx-method="${esc(b.method)}" data-fx-action="${esc(b.action)}">${fields}<div class="fx-form-msg"></div><button type="submit" class="fx-btn">${esc(label)}</button></form></div>\n`
|
|
859
979
|
}
|
|
860
980
|
|
|
861
981
|
function rBtn(b) {
|
|
@@ -870,11 +990,13 @@ function rSelectBlock(b) {
|
|
|
870
990
|
}
|
|
871
991
|
|
|
872
992
|
function rPricing(b) {
|
|
993
|
+
const v = b.variant||''
|
|
873
994
|
const cards=(b.plans||[]).map((p,i)=>{
|
|
874
|
-
let lh='#',ll='
|
|
995
|
+
let lh='#',ll='Começar'
|
|
875
996
|
if(p.linkRaw){const m=p.linkRaw.match(/\/([^:]+):(.+)/);if(m){lh='/'+m[1];ll=m[2]}}
|
|
876
997
|
const f=i===1?' fx-pricing-featured':''
|
|
877
|
-
const badge=i===1?'<div class="fx-pricing-badge">
|
|
998
|
+
const badge=i===1?'<div class="fx-pricing-badge">Mais popular</div>':''
|
|
999
|
+
if(v==='compact') return`<div class="fx-pricing-compact${i===1?' fx-pricing-featured':''}">${badge}<span class="fx-pricing-name">${esc(p.name)}</span><span class="fx-pricing-price fx-pricing-price-sm">${esc(p.price)}</span><p class="fx-pricing-desc">${esc(p.desc)}</p><a href="${esc(lh)}" class="fx-cta fx-pricing-cta">${esc(ll)}</a></div>`
|
|
878
1000
|
return`<div class="fx-pricing-card${f}">${badge}<div class="fx-pricing-name">${esc(p.name)}</div><div class="fx-pricing-price">${esc(p.price)}</div><p class="fx-pricing-desc">${esc(p.desc)}</p><a href="${esc(lh)}" class="fx-cta fx-pricing-cta">${esc(ll)}</a></div>`
|
|
879
1001
|
}).join('')
|
|
880
1002
|
return `<div class="fx-pricing">${cards}</div>\n`
|
|
@@ -920,7 +1042,41 @@ function genThemeVarCSS(t) {
|
|
|
920
1042
|
// ═════════════════════════════════════════════════════════════════
|
|
921
1043
|
|
|
922
1044
|
function css(theme) {
|
|
923
|
-
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}
|
|
1045
|
+
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}
|
|
1046
|
+
.fx-hero-minimal{min-height:50vh!important}
|
|
1047
|
+
.fx-hero-minimal .fx-hero-inner{gap:1rem}
|
|
1048
|
+
.fx-hero-tall{min-height:98vh!important}
|
|
1049
|
+
.fx-hero-left .fx-hero-inner{text-align:left;align-items:flex-start;max-width:none;padding-left:2.5rem}
|
|
1050
|
+
.fx-hero-left{justify-content:flex-start}
|
|
1051
|
+
.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}
|
|
1052
|
+
.fx-spacer{width:100%}
|
|
1053
|
+
.fx-divider{display:flex;align-items:center;gap:1rem;padding:2rem 2.5rem;opacity:.4}
|
|
1054
|
+
.fx-divider::before,.fx-divider::after{content:'';flex:1;height:1px;background:currentColor}
|
|
1055
|
+
.fx-divider-label{font-size:.75rem;font-family:monospace;white-space:nowrap;letter-spacing:.08em;text-transform:uppercase}
|
|
1056
|
+
.fx-hr{border:none;border-top:1px solid rgba(255,255,255,.08);margin:1.5rem 2.5rem}
|
|
1057
|
+
.fx-badge-row{padding:.5rem 2.5rem;display:flex;flex-wrap:wrap;gap:.5rem}
|
|
1058
|
+
.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}
|
|
1059
|
+
.fx-cols{display:grid;gap:1.5rem;padding:1rem 2.5rem}
|
|
1060
|
+
.fx-cols-2{grid-template-columns:1fr 1fr}
|
|
1061
|
+
.fx-cols-3{grid-template-columns:1fr 1fr 1fr}
|
|
1062
|
+
.fx-cols-4{grid-template-columns:repeat(4,1fr)}
|
|
1063
|
+
@media(max-width:640px){.fx-cols-2,.fx-cols-3,.fx-cols-4{grid-template-columns:1fr}}
|
|
1064
|
+
.fx-col{min-width:0}
|
|
1065
|
+
.fx-each{padding:.5rem 2.5rem}
|
|
1066
|
+
.fx-each-list{display:flex;flex-direction:column;gap:.5rem}
|
|
1067
|
+
.fx-each-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:.75rem}
|
|
1068
|
+
.fx-html{padding:.5rem 2.5rem}
|
|
1069
|
+
.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}
|
|
1070
|
+
.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}
|
|
1071
|
+
.fx-form-minimal{padding:.5rem 2.5rem;max-width:24rem}.fx-form-minimal form{background:none;border:none;padding:0}
|
|
1072
|
+
.fx-sect-accent{background:rgba(37,99,235,.06);border-left:3px solid #2563eb;padding-left:2rem}
|
|
1073
|
+
.fx-sect-dark{background:rgba(0,0,0,.4)}
|
|
1074
|
+
.fx-sect-full{padding:6rem 2.5rem}
|
|
1075
|
+
.fx-pricing-compact{border-radius:.875rem;padding:1.25rem;display:flex;align-items:center;gap:1rem;border:1px solid rgba(255,255,255,.08)}
|
|
1076
|
+
.fx-pricing-price-sm{font-size:1.5rem;font-weight:800;letter-spacing:-.04em}
|
|
1077
|
+
.fx-grid-numbered>.fx-card{counter-increment:card-counter}
|
|
1078
|
+
.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}
|
|
1079
|
+
.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}`
|
|
924
1080
|
|
|
925
1081
|
const T={
|
|
926
1082
|
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}`,
|
package/package.json
CHANGED
package/server/server.js
CHANGED
|
@@ -1435,7 +1435,7 @@ async function startServer(aipFile, port = 3000) {
|
|
|
1435
1435
|
|
|
1436
1436
|
// Health
|
|
1437
1437
|
srv.addRoute('GET', '/health', (req, res) => res.json(200, {
|
|
1438
|
-
status:'ok', version:'2.
|
|
1438
|
+
status:'ok', version:'2.8.0',
|
|
1439
1439
|
models: app.models.map(m=>m.name),
|
|
1440
1440
|
routes: app.apis.length, pages: app.pages.length,
|
|
1441
1441
|
admin: app.admin?.prefix || null,
|