@danhachuel/prodmaker 0.1.10 → 0.1.12
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/CHANGELOG.md +40 -0
- package/app/api/contas.py +45 -0
- package/app/api/guias.py +34 -0
- package/app/api/invest.py +37 -0
- package/app/api/logs.py +42 -0
- package/app/api/pins.py +80 -0
- package/app/main.py +12 -2
- package/app/services/database.py +220 -183
- package/app/services/dbengine.py +195 -0
- package/app/services/invest.py +52 -0
- package/app/services/oauth_google.py +108 -0
- package/app/services/pinterest.py +174 -0
- package/frontend/dist/assets/index-B4wxnTCs.css +1 -0
- package/frontend/dist/assets/index-C8sX5Mkf.js +74 -0
- package/frontend/dist/index.html +2 -2
- package/package.json +1 -1
- package/requirements.txt +7 -0
- package/scripts/cli.mjs +1 -1
- package/seed/references/pixel-e-tuneis.md +39 -0
- package/seed/references/webhooks-de-venda.md +38 -0
- package/frontend/dist/assets/index-B88UVmZI.css +0 -1
- package/frontend/dist/assets/index-EOri3RlA.js +0 -74
package/frontend/dist/index.html
CHANGED
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
rel="stylesheet"
|
|
16
16
|
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0..1,0&display=block"
|
|
17
17
|
/>
|
|
18
|
-
<script type="module" crossorigin src="/assets/index-
|
|
19
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
18
|
+
<script type="module" crossorigin src="/assets/index-C8sX5Mkf.js"></script>
|
|
19
|
+
<link rel="stylesheet" crossorigin href="/assets/index-B4wxnTCs.css">
|
|
20
20
|
</head>
|
|
21
21
|
<body>
|
|
22
22
|
<div id="root"></div>
|
package/package.json
CHANGED
package/requirements.txt
CHANGED
|
@@ -11,3 +11,10 @@ xhtml2pdf
|
|
|
11
11
|
# AdsPages (clonagem + verificação de domínios)
|
|
12
12
|
beautifulsoup4
|
|
13
13
|
dnspython
|
|
14
|
+
# Notificações (apprise) e Pinterest (py3-pinterest) — imports são preguiçosos:
|
|
15
|
+
# o servidor sobe sem eles; a ação que os usa informa se faltar instalar.
|
|
16
|
+
apprise
|
|
17
|
+
py3-pinterest
|
|
18
|
+
# PostgreSQL/Supabase — SÓ usado quando DATABASE_URL estiver definida (import preguiçoso).
|
|
19
|
+
# Sem DATABASE_URL o sistema continua 100% SQLite local.
|
|
20
|
+
psycopg[binary]
|
package/scripts/cli.mjs
CHANGED
|
@@ -14,7 +14,7 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
|
14
14
|
const PKG_ROOT = path.resolve(__dirname, "..");
|
|
15
15
|
const APP_DIR = path.join(PKG_ROOT, "app");
|
|
16
16
|
const REQUIREMENTS = path.join(PKG_ROOT, "requirements.txt");
|
|
17
|
-
const APP_VERSION = "0.1.
|
|
17
|
+
const APP_VERSION = "0.1.12";
|
|
18
18
|
const DEFAULT_PORT = 8188;
|
|
19
19
|
|
|
20
20
|
const STORAGE_FOLDERS = ["state", "pages", "produtos", "artifacts", "downloads", "logs"];
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Pixel de Rastreamento (/track) e túneis
|
|
2
|
+
|
|
3
|
+
O ProdMaker rastreia visitas das suas páginas com um **pixel próprio** — sem scripts de terceiros.
|
|
4
|
+
|
|
5
|
+
## Como funciona
|
|
6
|
+
|
|
7
|
+
1. Ao gerar uma página (AdsPages), o pixel do ProdMaker é embutido automaticamente **quando**
|
|
8
|
+
houver uma "URL pública do /track" configurada em Chaves de API → Pixel de Rastreamento.
|
|
9
|
+
2. O pixel envia `sendBeacon` com: evento (pageview, clique em CTA, unload), página, gclid,
|
|
10
|
+
utm_source, utm_medium, utm_campaign e referrer. O backend grava na tabela `visitas`.
|
|
11
|
+
3. As visitas aparecem em AdsTracking → Minhas Visitas, e vendas com GCLID são cruzadas
|
|
12
|
+
automaticamente com a visita de origem (matching 🎯).
|
|
13
|
+
|
|
14
|
+
## URL pública em máquina local
|
|
15
|
+
|
|
16
|
+
Como o ProdMaker roda localmente (127.0.0.1), plataformas e visitantes externos não o alcançam.
|
|
17
|
+
Use um túnel:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
# cloudflared (recomendado)
|
|
21
|
+
cloudflared tunnel --url http://localhost:8188
|
|
22
|
+
# copie a URL gerada (ex.: https://nome-aleatorio.trycloudflare.com)
|
|
23
|
+
# → configure no card Pixel de Rastreamento: https://nome-aleatorio.trycloudflare.com/track
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Alternativas: ngrok, localhost.run, serveo.
|
|
27
|
+
|
|
28
|
+
## Eventos
|
|
29
|
+
|
|
30
|
+
| Evento | Quando | Dados capturados |
|
|
31
|
+
|---|---|---|
|
|
32
|
+
| pageview | carregamento da página | gclid, utm_*, referrer |
|
|
33
|
+
| cta_click | clique em link/CTA | href do link |
|
|
34
|
+
| unload | saída da página | segundos na página |
|
|
35
|
+
|
|
36
|
+
## Drenagem de orçamento
|
|
37
|
+
|
|
38
|
+
Visitantes com 4+ cliques em CTA aparecem no alerta de POSSÍVEL DRENAGEM — use a lista
|
|
39
|
+
para negativar no Google Ads (critério: campanha → lista de exclusão de IPs).
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Webhooks de Venda (plataformas de afiliados)
|
|
2
|
+
|
|
3
|
+
O ProdMaker recebe vendas por webhook público e registra em Minhas Vendas.
|
|
4
|
+
|
|
5
|
+
## URLs de postback
|
|
6
|
+
|
|
7
|
+
Configure no painel de cada plataforma (**AdsTracking → Minhas Vendas → 🔗 Webhooks**
|
|
8
|
+
tem as URLs prontas para copiar):
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
POST https://SEU-TUNEL-OU-DOMINIO/api/webhook/sale/hotmart
|
|
12
|
+
POST https://SEU-TUNEL-OU-DOMINIO/api/webhook/sale/clickbank
|
|
13
|
+
POST https://SEU-TUNEL-OU-DOMINIO/api/webhook/sale/digistore24
|
|
14
|
+
POST https://SEU-TUNEL-OU-DOMINIO/api/webhook/sale/kiify
|
|
15
|
+
POST https://SEU-TUNEL-OU-DOMINIO/api/webhook/sale/cakto
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Como o ProdMaker é local, use um túnel (cloudflared/ngrok) apontando para a porta 8188.
|
|
19
|
+
Alternativa sem túnel: adição manual de vendas ou importação de CSV.
|
|
20
|
+
|
|
21
|
+
## Formato aceito
|
|
22
|
+
|
|
23
|
+
- **JSON** (Hotmart, Digistore24, Kiify, Cakto): qualquer formato — o parser é tolerante e
|
|
24
|
+
procura valor, comissão, e-mail, transação, produto, status e **gclid** em qualquer nível do JSON.
|
|
25
|
+
- **Form-urlencoded** (ClickBank Instant Notification): pares `chave=valor`.
|
|
26
|
+
|
|
27
|
+
## Dica para capturar GCLID
|
|
28
|
+
|
|
29
|
+
No link de afiliado/checkout, mantenha os parâmetros da campanha (`gclid`, `utm_*`) até a
|
|
30
|
+
página de obrigado. No postback da plataforma, envie o `gclid` (parâmetro de rastreamento).
|
|
31
|
+
O ProdMaker cruza o GCLID com a visita correspondente e habilita o upload de conversão
|
|
32
|
+
offline ao Google Ads (se configurado em Chaves de API).
|
|
33
|
+
|
|
34
|
+
## Status
|
|
35
|
+
|
|
36
|
+
- `PURCHASE_APPROVED`/`approved`/`complete` → aprovada
|
|
37
|
+
- `PURCHASE_REFUNDED`/`refunded`/`chargeback` → reembolsada
|
|
38
|
+
- demais (ex.: `billet_printed`, `pending`) → pendente
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.block{display:block}.flex{display:flex}.table{display:table}.border{border-width:1px}.outline{outline-style:solid}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}:root{--primary: #8b5cf6;--primary-hover: #7c3aed;--primary-light: #f3e8ff;--success: #10b981;--warning: #f59e0b;--danger: #ef4444;--bg-body: #f8fafc;--bg-card: #ffffff;--bg-sidebar: #ffffff;--text-main: #1e293b;--text-muted: #64748b;--border: #e2e8f0;--hover-bg: #f1f5f9;--input-bg: #f1f5f9;--toast-bg: #10b981;--warning-bg: #fffbeb;--warning-border: #fde68a;--code-bg: #f1f5f9}[data-theme=dark]{--bg-body: #121212;--bg-card: #1e1e1e;--bg-sidebar: #181818;--text-main: #f8fafc;--text-muted: #a1a1aa;--border: #333333;--hover-bg: #2a2a2a;--input-bg: #2a2a2a;--primary-light: #2d1b4e;--toast-bg: #059669;--warning-bg: #2d2000;--warning-border: #78350f;--code-bg: #000000}*{margin:0;padding:0;box-sizing:border-box}html,body{height:100%}body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;background-color:var(--bg-body);color:var(--text-main);transition:background .3s,color .3s}.app-shell{display:flex;height:100vh;overflow:hidden}aside.sidebar{width:260px;background-color:var(--bg-sidebar);border-right:1px solid var(--border);display:flex;flex-direction:column;height:100%;overflow-y:auto;flex-shrink:0}.logo-area{padding:20px;font-size:22px;font-weight:800;display:flex;align-items:center;gap:10px;color:var(--text-main);border-bottom:1px solid var(--border)}.logo-area span.badge{font-size:10px;border:1px solid var(--border);padding:4px 8px;border-radius:6px;color:var(--text-muted);display:flex;align-items:center;gap:4px;font-weight:600}nav ul{list-style:none;padding:0;margin:0}nav li.nav-item{padding:12px 20px;cursor:pointer;display:flex;align-items:center;gap:12px;color:var(--text-muted);font-size:14px;font-weight:500;transition:all .2s;-webkit-user-select:none;-moz-user-select:none;user-select:none}nav li.nav-item:hover{background-color:var(--hover-bg);color:var(--primary)}nav li.nav-item.active{background-color:var(--primary-light);color:var(--primary);font-weight:600}nav li.has-submenu{flex-direction:column;align-items:flex-start;padding:0}nav li.has-submenu>div{padding:12px 20px;width:100%;display:flex;align-items:center;gap:12px;cursor:pointer;color:var(--text-muted);font-weight:500;font-size:14px;-webkit-user-select:none;-moz-user-select:none;user-select:none}nav li.has-submenu>div:hover{background-color:var(--hover-bg);color:var(--primary)}nav li.has-submenu>div .submenu-arrow{font-size:10px;margin-left:auto;transition:transform .2s}nav li.has-submenu.expanded>div .submenu-arrow{transform:rotate(180deg)}nav li.has-submenu ul{display:none;width:100%;padding-left:10px;margin-bottom:10px}nav li.has-submenu.expanded ul{display:block}nav li.has-submenu ul li{padding:10px 20px;font-size:13px;color:var(--text-muted);cursor:pointer;display:flex;gap:8px;font-weight:500}nav li.has-submenu ul li:hover{color:var(--primary)}nav li.has-submenu ul li.active{color:var(--primary);font-weight:600}.divider{height:1px;background:var(--border);margin:15px 20px}.sidebar-bottom{margin-top:auto;padding:16px;border-top:1px solid var(--border)}.btn-logout{width:100%;border:none;padding:12px;border-radius:8px;font-weight:600;font-size:14px;cursor:pointer;color:#fff;background-image:linear-gradient(to right,#6366f1,#a855f7);display:flex;align-items:center;justify-content:center;gap:8px}.btn-logout:hover{opacity:.9}main.main-content{flex:1;display:flex;flex-direction:column;overflow-y:auto;position:relative}header.top-bar{background:var(--bg-card);padding:15px 30px;display:flex;justify-content:space-between;align-items:center;border-bottom:1px solid var(--border);position:sticky;top:0;z-index:10}.promo-banner{background-color:var(--primary-light);color:var(--primary);padding:8px 16px;border-radius:20px;font-size:13px;font-weight:500;cursor:pointer}.user-profile{display:flex;align-items:center;gap:15px;font-size:14px;font-weight:500}.user-profile .avatar{background:var(--primary-light);color:var(--primary);padding:5px 10px;border-radius:50%;font-weight:700;text-transform:uppercase}.theme-toggle{background:none;border:1px solid var(--border);color:var(--text-main);padding:5px 10px;border-radius:20px;cursor:pointer;font-size:16px}.content-wrapper{padding:30px 30px 80px;max-width:1200px;margin:0 auto;width:100%}h1{font-size:24px;margin-bottom:5px;color:var(--text-main)}p.subtitle{font-size:14px;color:var(--text-muted);margin-top:0;margin-bottom:20px}button.btn-primary{background-color:var(--primary);color:#fff;border:none;padding:10px 20px;border-radius:6px;font-weight:600;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;gap:8px;font-size:14px}button.btn-primary:hover{background-color:var(--primary-hover)}button.btn-primary:disabled{background-color:var(--hover-bg);color:var(--text-muted);cursor:not-allowed}button.btn-outline{background:transparent;border:1px solid var(--border);padding:10px 20px;border-radius:6px;font-weight:600;cursor:pointer;color:var(--text-main);font-size:14px}button.btn-outline:hover{background:var(--hover-bg)}table{width:100%;border-collapse:collapse;background:var(--bg-card);border-radius:8px;overflow:hidden;margin-top:15px;border:1px solid var(--border)}th,td{padding:12px 15px;text-align:left;border-bottom:1px solid var(--border);font-size:13px;color:var(--text-main)}th{background-color:var(--hover-bg);color:var(--text-muted);font-weight:600;text-transform:uppercase;font-size:11px}tr.empty-row td{text-align:center;color:var(--text-muted);padding:32px 15px;font-weight:500}.action-icons{display:flex;gap:15px;color:var(--text-muted);cursor:pointer;flex-wrap:wrap}.action-icons span:hover{color:var(--primary)}.form-group{margin-bottom:15px}.form-group label{display:block;font-size:13px;font-weight:600;margin-bottom:5px;color:var(--text-main)}.form-group input,.form-group select,.form-group textarea{width:100%;padding:10px;border:1px solid var(--border);border-radius:6px;font-size:14px;outline:none;background:var(--input-bg);color:var(--text-main)}.form-group input:focus,.form-group select:focus,.form-group textarea:focus{border-color:var(--primary)}.form-row{display:flex;gap:15px}.form-row .form-group{flex:1}.form-card{background:var(--bg-card);border:1px solid var(--border);border-radius:8px;padding:25px;margin-bottom:20px}.tabs{display:flex;gap:20px;border-bottom:1px solid var(--border);margin-bottom:15px}.tab{padding:10px 0;color:var(--text-muted);font-weight:600;font-size:14px;cursor:pointer;position:relative}.tab.active{color:var(--primary)}.tab.active:after{content:"";position:absolute;bottom:-1px;left:0;width:100%;height:2px;background:var(--primary)}.metrics-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:15px;margin-bottom:30px}.metric-card{background:var(--bg-card);padding:20px;border-radius:8px;border:1px solid var(--border);position:relative}.metric-card h3{font-size:13px;color:var(--text-muted);margin:0 0 10px;font-weight:500}.metric-card .value{font-size:24px;font-weight:700;color:var(--text-main)}.metric-card .value.green{color:var(--success)}.metric-card .value.purple{color:var(--primary)}.metrics-note{font-size:13px;color:var(--text-muted);margin-top:-18px;margin-bottom:30px}.modal-overlay{position:fixed;top:0;left:0;width:100vw;height:100vh;background:#0009;display:flex;justify-content:center;align-items:center;z-index:1000;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}.modal-content{background:var(--bg-card);border:1px solid var(--border);border-radius:12px;padding:30px;width:100%;max-width:800px;box-shadow:0 20px 25px -5px #0003;position:relative;color:var(--text-main);max-height:90vh;overflow-y:auto}.modal-content h2{font-size:20px;margin-bottom:18px}.modal-close{background:none;border:none;font-size:20px;cursor:pointer;color:var(--text-muted);position:absolute;top:15px;right:15px}.toast{position:fixed;top:70px;right:20px;background-color:var(--toast-bg);color:#fff;padding:15px 20px;border-radius:8px;display:flex;align-items:flex-start;gap:10px;z-index:2000;max-width:350px;box-shadow:0 4px 12px #0003}.placeholder-list{padding-left:20px;color:var(--text-muted);font-size:14px;margin:12px 0}.placeholder-list li{margin-bottom:6px}.placeholder-note{font-size:13px;color:var(--text-muted);margin-top:14px;font-weight:500}.loading-screen{display:flex;height:100vh;align-items:center;justify-content:center;color:var(--text-muted);font-size:15px}.login-error{color:var(--danger);font-size:13px;margin-bottom:12px;font-weight:500}.api-grid{display:grid;grid-template-columns:1fr 1fr;gap:20px;margin-top:20px}.api-card{background-color:var(--bg-card);border:1px solid var(--border);border-radius:12px;padding:30px 20px;display:flex;flex-direction:column;align-items:center;justify-content:center;cursor:pointer}.api-card:hover{border-color:var(--primary)}.api-logo{font-size:24px;font-weight:700;margin-bottom:15px;color:var(--text-main)}.api-status{font-size:12px;color:var(--text-muted)}.domain-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:20px;margin-top:20px}.domain-card{background:var(--bg-card);border:1px solid var(--border);border-radius:8px;padding:20px;display:flex;flex-direction:column;justify-content:space-between;min-height:350px}.domain-title{font-size:16px;font-weight:600;margin-bottom:15px;color:var(--text-main);word-break:break-all}.status-tag{display:flex;align-items:center;gap:8px;font-size:13px;margin-bottom:20px;font-weight:500}.status-tag.pending{color:var(--text-muted)}.status-tag.online{color:var(--success)}.input-group{display:flex;align-items:center;background:var(--input-bg);border-radius:6px;margin-bottom:10px;border:1px solid var(--border)}.input-group input{border:none;background:transparent;padding:10px;flex:1;font-size:12px;color:var(--text-muted);outline:none;min-width:0}.input-group button{background:none;border:none;padding:0 10px;cursor:pointer;color:var(--text-main)}.domain-list{list-style:none;padding:0;margin-bottom:20px}.domain-list li{display:flex;align-items:center;gap:8px;font-size:13px;margin-bottom:10px;color:var(--text-main)}.domain-actions{display:flex;gap:10px}.domain-actions button{flex:1;padding:8px;font-size:12px}.domain-card-bottom{display:flex;flex-direction:column;gap:10px;margin-top:20px}@media (max-width: 1100px){.domain-grid{grid-template-columns:repeat(2,1fr)}}@media (max-width: 800px){.domain-grid{grid-template-columns:1fr}}.login-page{display:flex;flex-direction:row;height:100vh;width:100%}.login-left{flex:1;position:relative;overflow:hidden;background:#0a0a0a;width:50%;display:flex}.login-left-content{position:relative;z-index:10;display:flex;flex-direction:column;justify-content:center;padding:4rem;height:100%;color:#fff;font-family:Inter,-apple-system,sans-serif;width:100%}.login-left-content *{color:#fff}.login-left-title{font-size:3rem;font-weight:700;line-height:1.2;margin-bottom:1.5rem;font-family:Poppins,sans-serif}.login-left-title .highlight-text{color:#8b5cf6}.login-left-description{font-size:1.25rem;margin-bottom:3rem;max-width:28rem;line-height:1.6;color:#ffffff80!important}.features-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:1.5rem;max-width:44rem;overflow:visible}.feature-step-item{display:flex;flex-direction:column;align-items:center;gap:.75rem;min-width:0;animation:step-card-in .5s ease-out both}.feature-step-item:nth-child(1){animation-delay:.3s}.feature-step-item:nth-child(2){animation-delay:.45s}.feature-step-item:nth-child(3){animation-delay:.6s}.feature-step-item:nth-child(4){animation-delay:.75s}@keyframes step-card-in{0%{opacity:0;transform:translateY(16px)}to{opacity:1;transform:translateY(0)}}.feature-card{display:flex;align-items:flex-start;gap:1rem;background:#7c3aed14;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);border-radius:1.25rem;padding:1.25rem;border:1px solid rgba(124,58,237,.22);position:relative;transition:border-color .3s ease,box-shadow .3s ease}.feature-card:hover{border-color:#7c3aed73;box-shadow:0 0 20px #7c3aed26}.feature-step{width:7rem;height:7rem;padding:0;border-radius:1.25rem;display:flex;align-items:center;justify-content:center;flex-shrink:0;align-self:center}.feature-step-number{position:absolute;top:.6rem;left:.75rem;font-size:.7rem;font-weight:600;line-height:1;color:#8b5cf68c;letter-spacing:.02em}.feature-step-icon{display:flex;align-items:center;justify-content:center}.feature-step-icon i{font-size:3rem;color:#8b5cf6bf;font-family:Material Symbols Outlined,sans-serif!important;font-variation-settings:"FILL" 1,"wght" 400,"GRAD" 0,"opsz" 24!important}.feature-step-arrow{position:absolute;right:-1.25rem;top:50%;transform:translateY(-50%);z-index:1}.feature-step-arrow:after{content:"";position:absolute;right:-7px;top:50%;width:0;height:0;border-left:8px solid rgba(236,72,153,.65);border-top:5px solid transparent;border-bottom:5px solid transparent;transform:translateY(-50%)}.feature-step-last .feature-step-arrow{display:none}.feature-title{font-weight:500;margin:0;font-size:.875rem;line-height:1.25;text-align:center;width:100%;color:#ffffffa6!important}.login-blur-effect{position:absolute;border-radius:50%;filter:blur(80px);opacity:1;pointer-events:none}.blur-effect-center{position:absolute;top:0;right:0;bottom:0;left:0;border-radius:0;filter:none;pointer-events:none;width:100%;height:100%;background:radial-gradient(ellipse 60% 40% at 50% 30%,rgba(124,58,237,.12) 0%,transparent 70%)}.blur-effect-1{width:520px;height:520px;background:radial-gradient(circle,rgba(124,58,237,.22) 0%,transparent 70%);filter:blur(40px);top:-10%;left:-8%;animation:orb-float-1 12s ease-in-out infinite}.blur-effect-2{width:440px;height:440px;background:radial-gradient(circle,rgba(236,72,153,.18) 0%,transparent 70%);filter:blur(40px);bottom:0%;right:-6%;animation:orb-float-2 15s ease-in-out infinite}@keyframes orb-float-1{0%,to{transform:translate(0) scale(1)}33%{transform:translate(40px,-30px) scale(1.08)}66%{transform:translate(-20px,20px) scale(.95)}}@keyframes orb-float-2{0%,to{transform:translate(0) scale(1)}33%{transform:translate(-30px,20px) scale(1.06)}66%{transform:translate(25px,-25px) scale(.97)}}.login-particle{position:absolute;border-radius:50%;pointer-events:none;filter:blur(1px);bottom:-10px;animation:particle-rise ease-in infinite}@keyframes particle-rise{0%{transform:translateY(0) scale(1);opacity:0}10%{opacity:1}90%{opacity:.6}to{transform:translateY(-110vh) scale(.4);opacity:0}}.login-right{flex:1;display:flex;flex-direction:column;justify-content:space-between;align-items:center;background-color:#f8fafc;padding:2rem;position:relative;width:50%;overflow-y:auto}.login-language-toggle{position:absolute;top:1.5rem;right:1.5rem;z-index:10}.language-toggle-wrapper{position:relative}.language-toggle-btn{background:none;border:1px solid #e2e8f0;border-radius:8px;padding:6px 10px;cursor:pointer;display:flex;align-items:center;justify-content:center;color:#64748b}.language-toggle-btn .material-symbols-outlined{font-size:20px}.language-toggle-dropdown{display:none;position:absolute;top:100%;right:0;margin-top:.5rem;background:#fff;border:1px solid #e2e8f0;border-radius:8px;box-shadow:0 4px 12px #0000001a;min-width:120px;overflow:hidden}.language-toggle-wrapper:hover .language-toggle-dropdown,.language-toggle-dropdown:hover{display:block}.language-toggle-item{padding:.5rem 1rem;cursor:pointer;font-size:.875rem}.language-toggle-item:hover{background:#f1f5f9}.language-toggle-item.active{background:#ede9fe;font-weight:600;color:#7c3aed}.login-form{width:100%;max-width:400px;flex:1;display:flex;flex-direction:column;justify-content:center}.login-form h2{font-size:1.75rem;font-weight:700;color:#334155;margin-bottom:.5rem}.login-form .login-subtitle{font-size:1rem;color:#64748b;margin-bottom:2rem}.login-form .form-group label{display:block;margin-bottom:.5rem;font-weight:500;font-size:.9rem;color:#334155}.login-form .form-group input{width:100%;padding:12px 15px;border-radius:4px;font-size:1rem;border:1px solid #e2e8f0;background:transparent;transition:border .3s ease;outline:none}.login-form .form-group input::-moz-placeholder{font-weight:300;font-size:.8rem;color:#94a3b8}.login-form .form-group input::placeholder{font-weight:300;font-size:.8rem;color:#94a3b8}.login-form .form-group input:focus{border-color:#8b5cf6;box-shadow:0 0 5px #8b5cf6}.login-form .form-group{margin-bottom:1.5rem}.email-input-wrapper,.password-input-wrapper{position:relative;width:100%}.email-input-wrapper input{padding-left:2.5rem!important}.password-input-wrapper input{padding-left:2.5rem!important;padding-right:45px}.email-icon,.lock-icon{position:absolute;left:12px;top:50%;transform:translateY(-50%);color:#ced1d6;pointer-events:none;font-size:20px}.password-toggle-btn{position:absolute;right:12px;top:50%;transform:translateY(-50%);background:none;border:none;cursor:pointer;padding:4px;display:flex;align-items:center;justify-content:center;color:#94a3b8;z-index:1}.password-toggle-btn:hover{color:#7c3aed}.login-button{border:none;border-radius:1.25rem;cursor:pointer;text-align:center;font-weight:500;letter-spacing:.5px;display:flex;align-items:center;justify-content:center;gap:.5rem;width:100%;padding:12px;background-color:#7c3aed;color:#fff;font-size:1rem;margin-top:.5rem;transition:background-color .3s ease,box-shadow .3s ease,transform .2s ease}.login-button:hover:not(:disabled){background-color:#6d28d9;transform:translateY(-2px)}.login-button:disabled{background-color:#e2e8f0;color:#94a3b8;cursor:not-allowed}.support-link{margin-top:1.5rem;text-align:center;font-size:.85rem;color:#64748b}.support-link p{margin-bottom:.5rem}.support-link a{color:#7c3aed;text-decoration:none;font-weight:500;cursor:pointer}.support-link a:hover{text-decoration:underline}.login-footer-bottom{padding-bottom:1rem;width:100%;max-width:400px;text-align:center;font-size:.8rem;color:#94a3b8}.login-footer-bottom a{color:#94a3b8;text-decoration:none;margin:0 10px}.login-footer-bottom a:hover{color:#7c3aed;text-decoration:underline}@media (max-width: 1024px){.login-left{display:none!important}.login-right{width:100%!important}}@media (max-width: 900px){.metrics-grid{grid-template-columns:repeat(2,1fr)}}.pixel-header{display:flex;align-items:center;gap:15px;margin-bottom:20px}.pixel-icon{background:var(--primary-light);color:var(--primary);padding:10px;border-radius:8px;font-size:20px}.pixel-top-bar{display:flex;justify-content:space-between;align-items:center;background:var(--bg-card);border:1px solid var(--border);padding:15px;border-radius:8px;margin-bottom:20px;flex-wrap:wrap;gap:10px}.pixel-tags{display:flex;gap:10px}.pixel-tag{background:var(--hover-bg);padding:4px 10px;border-radius:20px;font-size:12px;font-weight:600;color:var(--primary)}.warning-box{background:var(--warning-bg);border:1px solid var(--warning-border);border-radius:8px;padding:20px;display:flex;gap:15px;align-items:flex-start;margin-bottom:20px;position:relative}.warning-box .icon{background:var(--warning);color:#fff;width:30px;height:30px;border-radius:50%;display:flex;justify-content:center;align-items:center;font-weight:700;flex-shrink:0}.warning-box h4{font-size:15px;color:var(--text-main);margin-bottom:5px}.warning-box p{font-size:13px;color:var(--text-muted);margin:0;max-width:70%}.warning-box .btn-dark{position:absolute;right:20px;top:20px;background:#1e293b;color:#fff;border:none;padding:10px 15px;border-radius:6px;font-weight:600;font-size:12px;cursor:pointer}@media (max-width: 800px){.warning-box{flex-direction:column}.warning-box p{max-width:100%}.warning-box .btn-dark{position:static;margin-top:10px}}.visitor-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:15px;margin-bottom:30px}.visitor-card{background:var(--bg-card);border:1px solid var(--border);border-radius:8px;padding:15px;display:flex;flex-direction:column;gap:10px;cursor:pointer;transition:.2s}.visitor-card:hover{border-color:var(--primary);transform:translateY(-2px);box-shadow:0 4px 12px #0000000d}.visitor-card-header{display:flex;justify-content:space-between;align-items:center;gap:8px}.visitor-ip{display:flex;align-items:center;gap:8px;font-weight:600;font-size:14px;word-break:break-all}.visitor-badge{background:var(--warning-bg);color:var(--warning);padding:3px 8px;border-radius:12px;font-size:11px;font-weight:600;white-space:nowrap}.visitor-card-details{font-size:12px;color:var(--text-muted);display:flex;justify-content:space-between;gap:8px;flex-wrap:wrap}.visitor-card-link{font-size:12px;color:var(--primary);text-align:right;cursor:pointer}.charts-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:15px;margin-bottom:20px}.chart-card{background:var(--bg-card);padding:20px;border-radius:8px;border:1px solid var(--border)}.chart-card h3{font-size:15px;margin-bottom:5px}.chart-card p{font-size:12px;color:var(--text-muted);margin-bottom:20px}.donut-chart{width:150px;height:150px;border-radius:50%;margin:0 auto 15px;display:flex;justify-content:center;align-items:center}.donut-inner{width:100px;height:100px;background:var(--bg-card);border-radius:50%}.chart-legend{display:flex;justify-content:center;flex-wrap:wrap;gap:12px;font-size:12px;color:var(--text-muted)}.legend-item{display:flex;align-items:center;gap:6px}.legend-color{width:10px;height:10px;border-radius:50%;display:inline-block}.bottom-grid{display:grid;grid-template-columns:1.5fr 1fr;gap:20px;margin-bottom:20px}.traffic-flow-card{background:var(--bg-card);padding:20px;border-radius:8px;border:1px solid var(--border)}.traffic-flow-card h3{font-size:16px}.traffic-flow-visual{height:200px;background:linear-gradient(to top,var(--primary-light),transparent);border-radius:8px;margin-top:20px;position:relative;border-bottom:2px solid var(--border);overflow:hidden}.traffic-flow-visual svg{width:100%;height:100%;position:absolute;bottom:0;left:0}.funnel-card{background:var(--bg-card);padding:20px;border-radius:8px;border:1px solid var(--border)}.funnel-step{margin-bottom:15px}.funnel-step-header{display:flex;justify-content:space-between;font-size:13px;font-weight:600;margin-bottom:5px;gap:8px}.funnel-step-bar{height:8px;background:var(--hover-bg);border-radius:4px;overflow:hidden}.funnel-step-bar div{height:100%;background:var(--primary);border-radius:4px}.visitor-modal-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:20px}.badge-human{background:#ecfdf5;color:#059669;padding:4px 10px;border-radius:20px;font-size:12px;font-weight:700}[data-theme=dark] .badge-human{background:#052e2b;color:#34d399}.visitor-details-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:15px;margin-bottom:25px}.detail-box{border:1px solid var(--border);border-radius:8px;padding:15px}.detail-box .label{font-size:11px;color:var(--text-muted);text-transform:uppercase;display:flex;align-items:center;gap:5px;margin-bottom:10px;font-weight:700}.detail-box .main-val{font-size:14px;font-weight:600;margin-bottom:4px;word-break:break-all}.detail-box .sub-val{font-size:12px;color:var(--text-muted);word-break:break-all}.badge-origin{background:#e0f2fe;color:#0284c7;padding:2px 8px;border-radius:12px;font-size:11px;font-weight:600;display:inline-block}[data-theme=dark] .badge-origin{background:#082f49;color:#7dd3fc}.modal-tabs{display:flex;gap:20px;border-bottom:1px solid var(--border);margin-bottom:20px}.modal-tab{padding:10px 0;font-size:13px;font-weight:600;color:var(--text-muted);cursor:pointer;border-bottom:2px solid transparent}.modal-tab.active{color:var(--primary);border-bottom-color:var(--primary)}.tracking-id-box{border:1px solid var(--border);border-radius:8px;padding:15px;display:inline-block;min-width:200px;background:var(--hover-bg);margin:0 10px 10px 0}.tracking-id-box .label{font-size:11px;color:var(--text-muted);font-weight:700;margin-bottom:5px}.tracking-id-box .val{font-size:14px;font-weight:600;word-break:break-all}.json-box{background:var(--code-bg);padding:20px;border-radius:8px;font-family:monospace;font-size:13px;color:var(--success);white-space:pre-wrap;border:1px solid var(--border);position:relative}.json-copy-btn{position:absolute;top:10px;right:10px;background:var(--bg-card);border:1px solid var(--border);padding:5px 10px;border-radius:4px;font-size:12px;cursor:pointer;color:var(--text-main)}@media (max-width: 1100px){.visitor-grid,.charts-grid{grid-template-columns:repeat(2,1fr)}.bottom-grid{grid-template-columns:1fr}}@media (max-width: 800px){.visitor-grid,.charts-grid{grid-template-columns:1fr}.visitor-details-grid{grid-template-columns:repeat(2,1fr)}}
|