-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathapp.js
More file actions
358 lines (326 loc) · 11.4 KB
/
Copy pathapp.js
File metadata and controls
358 lines (326 loc) · 11.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
// Theme Management
let currentTheme = 'light';
function initTheme() {
// Set initial theme to light
document.documentElement.setAttribute('data-theme', currentTheme);
}
function toggleTheme() {
currentTheme = currentTheme === 'light' ? 'dark' : 'light';
document.documentElement.setAttribute('data-theme', currentTheme);
}
// Mobile Menu Toggle
function toggleMobileMenu() {
const nav = document.getElementById('nav');
nav.classList.toggle('active');
}
// Risk Level Expansion
function toggleRiskLevel(header) {
const card = header.closest('.risk-level-card');
card.classList.toggle('expanded');
}
// Tab Switching
function switchTab(tabName) {
// Remove active class from all buttons and contents
document.querySelectorAll('.tab-button').forEach(btn => {
btn.classList.remove('active');
});
document.querySelectorAll('.tab-content').forEach(content => {
content.classList.remove('active');
});
// Add active class to clicked button and corresponding content
event.target.classList.add('active');
document.getElementById(`tab-${tabName}`).classList.add('active');
}
// FAQ Toggle
function toggleFaq(question) {
const faqItem = question.closest('.faq-item');
faqItem.classList.toggle('active');
}
// Compliance Checker
const questions = [
{
id: 1,
question: "Does your AI system use subliminal manipulation, exploit vulnerabilities, or perform social scoring?",
answers: [
{ text: "Yes", next: "result_prohibited" },
{ text: "No", next: 2 }
]
},
{
id: 2,
question: "Does your AI system make or significantly influence decisions about:",
subtext: "Employment, credit/lending, education, law enforcement, healthcare, or access to essential services?",
answers: [
{ text: "Yes", next: "result_high_risk" },
{ text: "No", next: 3 }
]
},
{
id: 3,
question: "Does your AI system use biometric identification, emotion recognition, or process sensitive personal data for critical decisions?",
answers: [
{ text: "Yes", next: "result_high_risk" },
{ text: "No", next: 4 }
]
},
{
id: 4,
question: "Does your AI system interact with users (chatbot, content generator, virtual assistant)?",
answers: [
{ text: "Yes", next: "result_limited_risk" },
{ text: "No", next: "result_minimal_risk" }
]
}
];
const results = {
result_prohibited: {
risk_level: "Unacceptable Risk",
classification: "PROHIBITED",
color: "#DC2626",
message: "Your AI system appears to fall under prohibited practices. You CANNOT develop or deploy this system.",
requirements: [
"Immediate cessation of development/deployment required",
"Redesign system to eliminate prohibited features",
"Consult legal expert immediately"
],
penalty: "€35M or 7% global revenue",
deadline: "Already in effect",
gdpr_note: "GDPR compliance is irrelevant if system is prohibited"
},
result_high_risk: {
risk_level: "High-Risk",
classification: "ALLOWED with strict requirements",
color: "#F59E0B",
message: "Your AI system is classified as high-risk. Substantial compliance work required before market entry.",
requirements: [
"Implement risk management system",
"Ensure high-quality, unbiased training data",
"Create comprehensive technical documentation",
"Design human oversight mechanisms",
"Conduct pre-market conformity assessment",
"Register with national authority",
"Establish continuous monitoring"
],
penalty: "€15M or 3% revenue for non-compliance",
deadline: "August 2, 2026",
cost_estimate: "€10,000 - €100,000+ (SME support available)",
timeline_estimate: "6-12 months",
gdpr_note: "If processing personal data, GDPR also applies. DPIAs required. Can leverage GDPR compliance for AI Act.",
next_steps: [
"Apply for regulatory sandbox access",
"Engage AI Act compliance consultant",
"Begin risk assessment documentation",
"Review SME support programs"
]
},
result_limited_risk: {
risk_level: "Limited-Risk",
classification: "ALLOWED with transparency obligations",
color: "#EAB308",
message: "Your AI system has limited risk. Straightforward transparency requirements apply.",
requirements: [
"Inform users they're interacting with AI",
"Label AI-generated content clearly",
"Disclose training data sources (if GPAI)",
"Provide model documentation",
"Implement basic cybersecurity"
],
penalty: "€7.5M or 1% revenue for non-compliance",
deadline: "August 2, 2025 (already in effect)",
cost_estimate: "€2,000 - €10,000",
timeline_estimate: "1-3 months",
gdpr_note: "If processing personal data, GDPR applies. Ensure lawful basis and data minimization.",
next_steps: [
"Implement user disclosure mechanisms",
"Create content labeling system",
"Document training data sources",
"Review GDPR compliance if processing personal data"
]
},
result_minimal_risk: {
risk_level: "Minimal/No Risk",
classification: "ALLOWED - mostly unregulated",
color: "#10B981",
message: "Your AI system has minimal risk. No specific AI Act requirements apply.",
requirements: [
"Follow general best practices (recommended)",
"Consider voluntary documentation",
"Implement basic security measures"
],
penalty: "None",
deadline: "N/A",
cost_estimate: "€0 - €2,000 (optional)",
timeline_estimate: "Immediate deployment possible",
gdpr_note: "If processing personal data, GDPR still applies. Ensure compliance with data protection rules.",
next_steps: [
"Focus on product development",
"Implement voluntary best practices",
"Monitor for future regulatory updates",
"Ensure GDPR compliance if applicable"
]
}
};
let currentQuestion = 1;
function initChecker() {
displayQuestion(1);
updateProgress();
}
function displayQuestion(questionId) {
const question = questions.find(q => q.id === questionId);
if (!question) return;
const container = document.getElementById('questionContainer');
container.innerHTML = `
<div class="question-card">
<h3>${question.question}</h3>
${question.subtext ? `<p class="question-subtext">${question.subtext}</p>` : ''}
<div class="answer-options">
${question.answers.map(answer => `
<button class="answer-btn" onclick="handleAnswer(${typeof answer.next === 'string' ? `'${answer.next}'` : answer.next})">
${answer.text}
</button>
`).join('')}
</div>
</div>
`;
}
function handleAnswer(next) {
if (typeof next === 'string') {
// It's a result
showResult(next);
} else {
// It's another question
currentQuestion = next;
displayQuestion(next);
updateProgress();
}
}
function updateProgress() {
const progress = (currentQuestion / questions.length) * 100;
document.getElementById('progressFill').style.width = `${progress}%`;
document.getElementById('progressText').textContent = `Question ${currentQuestion} of ${questions.length}`;
}
function showResult(resultKey) {
const result = results[resultKey];
const questionContainer = document.getElementById('questionContainer');
const resultContainer = document.getElementById('resultContainer');
const progressBar = document.querySelector('.progress-bar');
const progressText = document.getElementById('progressText');
const restartBtn = document.getElementById('restartBtn');
// Hide question, show result
questionContainer.style.display = 'none';
progressBar.style.display = 'none';
progressText.style.display = 'none';
resultContainer.style.display = 'block';
restartBtn.style.display = 'inline-block';
// Build result HTML
resultContainer.innerHTML = `
<div class="result-header">
<div class="result-classification" style="background: ${result.color};">
${result.risk_level}
</div>
<p class="result-message">${result.message}</p>
</div>
<div class="result-section">
<h4>Classification: ${result.classification}</h4>
</div>
<div class="result-section">
<h4>Requirements:</h4>
<ul>
${result.requirements.map(req => `<li>${req}</li>`).join('')}
</ul>
</div>
${result.next_steps ? `
<div class="result-section">
<h4>Recommended Next Steps:</h4>
<ul>
${result.next_steps.map(step => `<li>${step}</li>`).join('')}
</ul>
</div>
` : ''}
<div class="result-meta">
<div class="result-meta-item">
<strong>Penalty:</strong>
<span>${result.penalty}</span>
</div>
<div class="result-meta-item">
<strong>Deadline:</strong>
<span>${result.deadline}</span>
</div>
${result.cost_estimate ? `
<div class="result-meta-item">
<strong>Cost Estimate:</strong>
<span>${result.cost_estimate}</span>
</div>
` : ''}
${result.timeline_estimate ? `
<div class="result-meta-item">
<strong>Timeline:</strong>
<span>${result.timeline_estimate}</span>
</div>
` : ''}
</div>
<div class="result-section">
<h4>GDPR Connection:</h4>
<p>${result.gdpr_note}</p>
</div>
`;
}
function restartChecker() {
currentQuestion = 1;
document.getElementById('questionContainer').style.display = 'block';
document.getElementById('resultContainer').style.display = 'none';
document.querySelector('.progress-bar').style.display = 'block';
document.getElementById('progressText').style.display = 'block';
document.getElementById('restartBtn').style.display = 'none';
initChecker();
}
// Countdown Timer
function updateCountdown() {
const targetDate = new Date('2026-08-02T00:00:00Z');
const now = new Date();
const diff = targetDate - now;
if (diff > 0) {
const days = Math.floor(diff / (1000 * 60 * 60 * 24));
const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
const countdownEl = document.getElementById('countdown-2026');
if (countdownEl) {
countdownEl.textContent = `Time remaining: ${days} days, ${hours} hours, ${minutes} minutes`;
}
}
}
// Initialize
document.addEventListener('DOMContentLoaded', function() {
initTheme();
initChecker();
updateCountdown();
setInterval(updateCountdown, 60000); // Update every minute
// Theme toggle
document.getElementById('themeToggle').addEventListener('click', toggleTheme);
// Mobile menu
document.getElementById('mobileMenuToggle').addEventListener('click', toggleMobileMenu);
// Close mobile menu when clicking a link
document.querySelectorAll('.nav-list a').forEach(link => {
link.addEventListener('click', () => {
document.getElementById('nav').classList.remove('active');
});
});
// Smooth scroll for anchor links
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function(e) {
const href = this.getAttribute('href');
if (href !== '#' && href.length > 1) {
e.preventDefault();
const target = document.querySelector(href);
if (target) {
const headerHeight = 80;
const targetPosition = target.offsetTop - headerHeight;
window.scrollTo({
top: targetPosition,
behavior: 'smooth'
});
}
}
});
});
});