Skip to content

Commit 74f71c8

Browse files
committed
commit 1a2b3c4d5e6f7g8h9i0jklmnopqrstuvwx
1 parent 750a4fa commit 74f71c8

10,757 files changed

Lines changed: 3122166 additions & 53 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

requirements.txt

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,20 @@ SQLAlchemy
99
pytest
1010
beautifulsoup4
1111
lxml
12-
pytest-cov
12+
pytest-cov
13+
gunicorn
14+
Flask-Login
15+
Flask-WTF
16+
Flask-Migrate
17+
Flask-Bcrypt
18+
Flask-Babel
19+
Flask-Cors
20+
python-dotenv
21+
openai
22+
alembic
23+
marshmallow
24+
python-magic
25+
# Dev / linting tools
26+
black
27+
isort
28+
flake8

static/css/style.css

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,19 @@
1414
--radius:10px;
1515
}
1616

17+
/* Light theme overrides */
18+
body.theme-light{
19+
--bg:#f7fafc;
20+
--panel:#ffffff;
21+
--muted:#475569;
22+
--accent:#5b21b6;
23+
--accent-2:#059669;
24+
--surface:#ffffff;
25+
--card:#ffffff;
26+
--text:#0f1724;
27+
--glass: rgba(15,23,36,0.04);
28+
}
29+
1730
*{box-sizing:border-box}
1831
html,body{height:100%}
1932
body{
@@ -33,23 +46,50 @@ body{
3346
padding:0 1rem;
3447
}
3548

49+
/* Full-width sections that ignore the page max width */
50+
.container.full-width{max-width:100%;padding:0 2rem}
51+
3652
/* Header */
3753
.site-header{
3854
background: linear-gradient(90deg, rgba(255,255,255,0.02), transparent);
3955
border-bottom: 1px solid rgba(255,255,255,0.04);
56+
position: sticky;
57+
top: 0;
58+
z-index: 1100;
59+
backdrop-filter: blur(6px);
4060
}
4161
.header-inner{
4262
display:flex;
4363
align-items:center;
4464
justify-content:space-between;
4565
gap:1rem;
46-
padding:1.125rem 0;
66+
padding:1.125rem 1rem; /* horizontal padding matches .container */
4767
}
4868
.logo{
69+
display:inline-flex;
70+
align-items:center;
71+
gap:0.5rem;
72+
margin-left:1rem;
4973
font-weight:800;
5074
letter-spacing:0.6px;
51-
font-size:1.125rem;
75+
font-size:0.95rem;
5276
color:var(--text);
77+
text-decoration:none;
78+
}
79+
80+
.logo img{width:40px;height:40px;border-radius:8px;display:block}
81+
.logo .brand{font-weight:800;color:var(--text)}
82+
83+
/* Header layout - logo sits left and nav fills remaining space */
84+
.header-inner{display:flex;align-items:center;justify-content:space-between;gap:1rem}
85+
.header-inner > .logo{margin-left:0}
86+
.logo{order:0;margin-right:1rem}
87+
88+
/* Mobile: hide brand text to keep header compact */
89+
@media (max-width:900px){
90+
.logo .brand{display:none}
91+
.logo img{width:36px;height:36px}
92+
.logo{margin-right:0}
5393
}
5494

5595
.nav-toggle{
@@ -59,7 +99,10 @@ body{
5999
color:var(--text);
60100
}
61101

62-
.primary-nav{display:flex;align-items:center;gap:1.25rem}
102+
.theme-toggle{background:transparent;border:0;color:var(--text);padding:0.4rem;border-radius:6px;cursor:pointer}
103+
.theme-toggle:focus{outline:2px solid rgba(124,92,255,0.14);outline-offset:2px}
104+
105+
.primary-nav{display:flex;align-items:center;gap:1.25rem;flex:1}
63106
.nav-list{display:flex;gap:1.5rem;margin:0;padding:0;list-style:none}
64107
.nav-list a{color:var(--muted);text-decoration:none;font-weight:600;padding:0.35rem 0;display:inline-block;border-radius:6px}
65108
.nav-list a:hover{color:var(--text);background:var(--glass)}
@@ -80,7 +123,7 @@ body{
80123
.nav-search input::placeholder{color:var(--muted)}
81124

82125
/* Main */
83-
.site-main{padding:3rem 0}
126+
.site-main{padding:3.5rem 0}
84127
.site-main .card{background:linear-gradient(180deg, rgba(255,255,255,0.02), rgba(255,255,255,0.01));border-radius:var(--radius);padding:1.5rem;border:1px solid rgba(255,255,255,0.03)}
85128

86129
/* Hero */
@@ -128,6 +171,14 @@ body{
128171
.ai-chat-form input{flex:1;padding:0.5rem;border-radius:8px;border:1px solid rgba(255,255,255,0.04);background:transparent;color:var(--text)}
129172
.ai-chat-form button{padding:0.45rem 0.7rem;border-radius:8px;border:0;background:var(--accent);color:white}
130173

174+
/* Chat pop animation */
175+
.ai-chat.pop .ai-chat-toggle{animation:chat-pop 380ms cubic-bezier(.2,1,.2,1)}
176+
@keyframes chat-pop{
177+
0%{transform:scale(0.85)}
178+
60%{transform:scale(1.08)}
179+
100%{transform:scale(1)}
180+
}
181+
131182
/* Form styles */
132183
.form-stacked label{display:block;margin-top:0.75rem;font-weight:600;color:var(--text)}
133184
.form-stacked input, .form-stacked textarea, .form-stacked select{width:100%;padding:0.6rem;border-radius:8px;border:1px solid rgba(255,255,255,0.06);background:rgba(255,255,255,0.02);color:var(--text);margin-top:0.25rem}

static/img/logo.svg

Lines changed: 10 additions & 0 deletions
Loading

static/js/main.js

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,73 @@ document.addEventListener('DOMContentLoaded', function(){
1212
});
1313
}
1414

15+
// Theme toggle
16+
const themeBtn = document.querySelector('.theme-toggle');
17+
const root = document.documentElement;
18+
function setTheme(t){
19+
if(t === 'light'){
20+
document.body.classList.add('theme-light');
21+
themeBtn && (themeBtn.textContent = '☀️');
22+
themeBtn && themeBtn.setAttribute('aria-pressed','true');
23+
} else {
24+
document.body.classList.remove('theme-light');
25+
themeBtn && (themeBtn.textContent = '🌙');
26+
themeBtn && themeBtn.setAttribute('aria-pressed','false');
27+
}
28+
try{ localStorage.setItem('theme', t); }catch(e){}
29+
}
30+
31+
// initialize
32+
try{
33+
const stored = localStorage.getItem('theme');
34+
setTheme(stored === 'light' ? 'light' : 'dark');
35+
}catch(e){ setTheme('dark') }
36+
37+
if(themeBtn){
38+
themeBtn.addEventListener('click', function(){
39+
const isLight = document.body.classList.contains('theme-light');
40+
setTheme(isLight ? 'dark' : 'light');
41+
});
42+
}
43+
44+
// Translation loader
45+
const langSelect = document.querySelector('.lang-select');
46+
async function loadLocale(lang){
47+
try{
48+
const res = await fetch('/static/locales/' + lang + '.json');
49+
const data = await res.json();
50+
applyTranslations(data);
51+
try{ localStorage.setItem('lang', lang); }catch(e){}
52+
}catch(e){ console.warn('Failed to load locale', e) }
53+
}
54+
55+
function applyTranslations(dict){
56+
document.querySelectorAll('[data-i18n]').forEach(function(el){
57+
const key = el.getAttribute('data-i18n');
58+
if(dict[key]) el.textContent = dict[key];
59+
});
60+
// buttons/links by class
61+
const btnPrimary = document.querySelector('.btn-primary');
62+
const btnSecondary = document.querySelector('.btn-secondary');
63+
const uploadBtn = document.querySelector('.cta-group .btn');
64+
if(btnPrimary && dict['get_started']) btnPrimary.textContent = dict['get_started'];
65+
if(btnSecondary && dict['learn_more']) btnSecondary.textContent = dict['learn_more'];
66+
if(uploadBtn && dict['upload_data']) uploadBtn.textContent = dict['upload_data'];
67+
}
68+
69+
// Initialize language
70+
try{
71+
const storedLang = localStorage.getItem('lang') || 'en';
72+
if(langSelect) langSelect.value = storedLang;
73+
loadLocale(storedLang);
74+
}catch(e){ loadLocale('en') }
75+
76+
if(langSelect){
77+
langSelect.addEventListener('change', function(e){
78+
loadLocale(e.target.value);
79+
});
80+
}
81+
1582
// Chat widget
1683
const chat = document.getElementById('ai-chat');
1784
const chatToggle = document.querySelector('.ai-chat-toggle');
@@ -30,8 +97,13 @@ document.addEventListener('DOMContentLoaded', function(){
3097

3198
if(chatToggle && chat){
3299
chatToggle.addEventListener('click', function(){
100+
const opening = !chat.classList.contains('open');
33101
chat.classList.toggle('open');
34102
chat.setAttribute('aria-hidden', chat.classList.contains('open') ? 'false' : 'true');
103+
if(opening){
104+
chat.classList.add('pop');
105+
setTimeout(()=>chat.classList.remove('pop'), 800);
106+
}
35107
});
36108
}
37109

static/locales/en.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"kicker": "Enterprise",
3+
"hero_title": "Welcome to Zclonic by AtonixCorp",
4+
"hero_lead": "AI-Powered Infrastructure for the Enterprise Frontier",
5+
"get_started": "Get Started — It's free",
6+
"learn_more": "Learn more",
7+
"upload_data": "Upload data",
8+
"contact_us": "Contact Us"
9+
}

static/locales/es.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"kicker": "Empresa",
3+
"hero_title": "Bienvenido a Zclonic por AtonixCorp",
4+
"hero_lead": "Infraestructura impulsada por IA para la frontera empresarial",
5+
"get_started": "Comenzar — Es gratis",
6+
"learn_more": "Más información",
7+
"upload_data": "Subir datos",
8+
"contact_us": "Contáctanos"
9+
}

templates/base.html

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
<!-- templates/base.html -->
22
<!DOCTYPE html>
33
<html lang="en">
4-
<head>
4+
<head>
55
<meta charset="UTF-8">
6+
<!-- favicon -->
7+
<link rel="icon" href="{{ url_for('static', filename='img/logo.svg') }}" type="image/svg+xml">
8+
<!-- Management: From ingestion to insight, Zclonic helps enterprises -->
69
<meta name="viewport" content="width=device-width, initial-scale=1">
710
<title>Research AI Portal</title>
811
<link rel="preconnect" href="https://fonts.googleapis.com">
@@ -12,15 +15,20 @@
1215
</head>
1316
<body>
1417
<header class="site-header" role="banner">
15-
<div class="container header-inner">
16-
<div class="logo">xclony</div>
18+
19+
<div class="container full-width header-inner">
1720

1821
<button class="nav-toggle" aria-controls="primary-navigation" aria-expanded="false" aria-label="Toggle navigation">
1922
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" aria-hidden="true">
2023
<path d="M4 6h16M4 12h16M4 18h16" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
2124
</svg>
2225
</button>
2326

27+
<a class="logo" href="{{ url_for('main.dashboard') }}" aria-label="Zclonic home">
28+
<img src="{{ url_for('static', filename='img/logo.svg') }}" alt="Zclonic logo">
29+
<span class="brand">Zclonic</span>
30+
</a>
31+
2432
<nav id="primary-navigation" class="primary-nav" role="navigation" aria-label="Primary">
2533
<ul class="nav-list">
2634
<li><a href="/">Home</a></li>
@@ -37,6 +45,15 @@
3745
</form>
3846

3947
<ul class="nav-actions">
48+
<li>
49+
<button class="theme-toggle" aria-pressed="false" title="Toggle theme">🌙</button>
50+
</li>
51+
<li>
52+
<select class="lang-select" aria-label="Select language">
53+
<option value="en">EN</option>
54+
<option value="es">ES</option>
55+
</select>
56+
</li>
4057
{% if session.get('user_id') %}
4158
<li class="muted">{{ session.get('user_email') }}</li>
4259
<li><a href="{{ url_for('main.dashboard') }}" class="link-muted">Dashboard</a></li>
@@ -47,15 +64,16 @@
4764
{% endif %}
4865
</ul>
4966
</nav>
67+
<!-- logo moved to the left side -->
5068
</div>
5169
</header>
5270

5371
<!-- Hero -->
5472
<section class="hero">
55-
<div class="container">
56-
<span class="kicker">Enterprise</span>
57-
<h1>Welcome to Zclonic by AtonixCorp</h1>
58-
<p class="lead">AI-Powered Infrastructure for the Enterprise Frontier</p>
73+
<div class="container full-width">
74+
<span class="kicker" data-i18n="kicker">Enterprise</span>
75+
<h1 data-i18n="hero_title">Welcome to Zclonic by AtonixCorp</h1>
76+
<p class="lead" data-i18n="hero_lead">AI-Powered Infrastructure for the Enterprise Frontier</p>
5977
<p>Zclonic is your multi-purpose command center—built for enterprises that demand autonomy, resilience, and scale. Whether you're managing sensitive data, deploying secure APIs, or orchestrating IT operations across borders, our platform delivers uncompromising performance and control.</p>
6078

6179
<div class="hero-grid">
@@ -85,8 +103,8 @@ <h3>Autonomous Data Management</h3>
85103
</div>
86104
</section>
87105

88-
<main class="site-main">
89-
<div class="container">
106+
<main class="site-main">
107+
<div class="container full-width">
90108
{% block content %}{% endblock %}
91109
</div>
92110
</main>

templates/complete_profile.html

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
{% extends 'base.html' %}
22

33
{% block content %}
4-
<div class="site-main">
54
<div class="container">
65
<div class="card">
76
<h1>Complete your profile</h1>
@@ -22,5 +21,4 @@ <h1>Complete your profile</h1>
2221
</form>
2322
</div>
2423
</div>
25-
</div>
2624
{% endblock %}

templates/contact.html

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
{% extends "base.html" %}
22

33
{% block content %}
4-
<div class="site-main">
54
<div class="container">
65
<section class="card">
76
<h2>Contact Us</h2>
@@ -17,5 +16,4 @@ <h2>Contact Us</h2>
1716
</form>
1817
</section>
1918
</div>
20-
</div>
2119
{% endblock %}

templates/dashboard.html

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
{% extends 'base.html' %}
22
{% block content %}
3-
<h2>Upload a Document</h2>
4-
<form action="/upload" method="post" enctype="multipart/form-data">
5-
<input type="file" name="document">
6-
<button type="submit">Process</button>
7-
</form>
3+
<h2>Upload a Document</h2>
4+
<form action="/upload" method="post" enctype="multipart/form-data">
5+
<input type="file" name="document">
6+
<button type="submit">Process</button>
7+
</form>
88

9-
{% if result %}
10-
<div class="result">
11-
<h3>AI Output:</h3>
12-
<p>{{ result }}</p>
13-
</div>
14-
{% endif %}
9+
{% if result %}
10+
<div class="result">
11+
<h3>AI Output:</h3>
12+
<p>{{ result }}</p>
13+
</div>
14+
{% endif %}
1515
{% endblock %}

0 commit comments

Comments
 (0)