Speedofmastery commited on
Commit
f081192
·
verified ·
1 Parent(s): 31b0744

Upload folder using huggingface_hub

Browse files
Files changed (4) hide show
  1. main.py +10 -1
  2. static/index.html +160 -0
  3. static/script.js +240 -0
  4. static/style.css +617 -0
main.py CHANGED
@@ -1,5 +1,7 @@
1
  from fastapi import FastAPI, HTTPException
2
  from fastapi.middleware.cors import CORSMiddleware
 
 
3
  from pydantic import BaseModel
4
  import uvicorn
5
  import torch
@@ -34,6 +36,9 @@ app.add_middleware(
34
  allow_headers=["*"],
35
  )
36
 
 
 
 
37
 
38
  # Request models
39
  class TextRequest(BaseModel):
@@ -47,8 +52,12 @@ class HealthResponse(BaseModel):
47
  cuda_devices: int
48
  device_name: str = None
49
 
 
 
 
 
50
 
51
- @app.get("/", response_model=dict)
52
  async def root():
53
  """Root endpoint with API information"""
54
  return {
 
1
  from fastapi import FastAPI, HTTPException
2
  from fastapi.middleware.cors import CORSMiddleware
3
+ from fastapi.staticfiles import StaticFiles
4
+ from fastapi.responses import FileResponse
5
  from pydantic import BaseModel
6
  import uvicorn
7
  import torch
 
36
  allow_headers=["*"],
37
  )
38
 
39
+ # Mount static files
40
+ app.mount("/static", StaticFiles(directory="static"), name="static")
41
+
42
 
43
  # Request models
44
  class TextRequest(BaseModel):
 
52
  cuda_devices: int
53
  device_name: str = None
54
 
55
+ @app.get("/")
56
+ async def serve_frontend():
57
+ """Serve the frontend HTML"""
58
+ return FileResponse("static/index.html")
59
 
60
+ @app.get("/api", response_model=dict)
61
  async def root():
62
  """Root endpoint with API information"""
63
  return {
static/index.html ADDED
@@ -0,0 +1,160 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Flare.NX & Orynx AI Labs - GPU Accelerated API</title>
7
+ <link rel="stylesheet" href="/static/style.css">
8
+ </head>
9
+ <body>
10
+ <div class="container">
11
+ <!-- Header with Logos -->
12
+ <header class="header">
13
+ <div class="logo-container">
14
+ <div class="logo-section">
15
+ <div class="logo-icon flare-logo">
16
+ <svg viewBox="0 0 100 60" xmlns="http://www.w3.org/2000/svg">
17
+ <path d="M20,45 Q15,40 15,30 Q15,20 20,15 L40,15 Q50,15 55,20 L75,20 Q80,15 90,15"
18
+ fill="#FF9933" stroke="none"/>
19
+ <ellipse cx="25" cy="25" rx="20" ry="15" fill="#FF9933"/>
20
+ <ellipse cx="50" cy="30" rx="15" ry="12" fill="#FFAA55"/>
21
+ </svg>
22
+ </div>
23
+ <h1 class="logo-text">Flare.NX</h1>
24
+ </div>
25
+ <div class="logo-divider">×</div>
26
+ <div class="logo-section">
27
+ <div class="logo-icon orynx-logo">
28
+ <svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
29
+ <path d="M50,20 Q55,15 60,20 L65,30 Q67,35 65,40 L60,60 Q55,65 50,65 Q45,65 40,60 L35,40 Q33,35 35,30 Z"
30
+ fill="#E8F0FF" stroke="#FFFFFF" stroke-width="2"/>
31
+ <ellipse cx="55" cy="35" rx="4" ry="6" fill="#1E3A8A"/>
32
+ <path d="M65,25 Q70,20 75,15 Q80,10 85,15" stroke="#FFFFFF" stroke-width="3" fill="none"/>
33
+ </svg>
34
+ </div>
35
+ <div class="logo-text-group">
36
+ <h1 class="logo-text">ORYNX</h1>
37
+ <p class="logo-subtitle">AI LABS</p>
38
+ </div>
39
+ </div>
40
+ </div>
41
+ <p class="tagline">High-Performance GPU-Accelerated AI Platform</p>
42
+ </header>
43
+
44
+ <!-- System Status -->
45
+ <section class="status-section">
46
+ <h2>🚀 System Status</h2>
47
+ <div class="status-grid">
48
+ <div class="status-card" id="healthCard">
49
+ <div class="status-icon">🏥</div>
50
+ <h3>Health Status</h3>
51
+ <div class="status-value" id="healthStatus">Checking...</div>
52
+ <button class="btn-refresh" onclick="checkHealth()">Refresh</button>
53
+ </div>
54
+ <div class="status-card" id="gpuCard">
55
+ <div class="status-icon">🎮</div>
56
+ <h3>GPU Status</h3>
57
+ <div class="status-value" id="gpuStatus">Loading...</div>
58
+ <button class="btn-refresh" onclick="checkGPU()">Refresh</button>
59
+ </div>
60
+ </div>
61
+ </section>
62
+
63
+ <!-- GPU Information -->
64
+ <section class="gpu-section">
65
+ <h2>💎 GPU Information</h2>
66
+ <div class="gpu-details" id="gpuDetails">
67
+ <div class="loading">Loading GPU specifications...</div>
68
+ </div>
69
+ </section>
70
+
71
+ <!-- Text Processing -->
72
+ <section class="process-section">
73
+ <h2>🔧 Text Processing (GPU Accelerated)</h2>
74
+ <div class="process-container">
75
+ <div class="input-group">
76
+ <label for="textInput">Input Text:</label>
77
+ <textarea id="textInput" rows="4" placeholder="Enter text to process...">Hello from Flare.NX and Orynx AI Labs!</textarea>
78
+ </div>
79
+ <div class="input-group">
80
+ <label for="maxLength">Max Length:</label>
81
+ <input type="number" id="maxLength" value="100" min="1" max="1000">
82
+ </div>
83
+ <button class="btn-process" onclick="processText()">
84
+ <span class="btn-icon">⚡</span>
85
+ Process with GPU
86
+ </button>
87
+ <div class="output-group" id="outputGroup" style="display: none;">
88
+ <h3>Results:</h3>
89
+ <div class="output-content" id="outputContent"></div>
90
+ </div>
91
+ </div>
92
+ </section>
93
+
94
+ <!-- API Endpoints -->
95
+ <section class="api-section">
96
+ <h2>📡 API Endpoints</h2>
97
+ <div class="api-grid">
98
+ <div class="api-card">
99
+ <div class="api-method get">GET</div>
100
+ <div class="api-path">/</div>
101
+ <p>API Information</p>
102
+ <button class="btn-test" onclick="testEndpoint('/')">Test</button>
103
+ </div>
104
+ <div class="api-card">
105
+ <div class="api-method get">GET</div>
106
+ <div class="api-path">/health</div>
107
+ <p>Health Check & GPU Status</p>
108
+ <button class="btn-test" onclick="testEndpoint('/health')">Test</button>
109
+ </div>
110
+ <div class="api-card">
111
+ <div class="api-method get">GET</div>
112
+ <div class="api-path">/gpu-info</div>
113
+ <p>Detailed GPU Specifications</p>
114
+ <button class="btn-test" onclick="testEndpoint('/gpu-info')">Test</button>
115
+ </div>
116
+ <div class="api-card">
117
+ <div class="api-method post">POST</div>
118
+ <div class="api-path">/process</div>
119
+ <p>Text Processing</p>
120
+ <button class="btn-test" onclick="processText()">Test</button>
121
+ </div>
122
+ <div class="api-card">
123
+ <div class="api-method get">GET</div>
124
+ <div class="api-path">/docs</div>
125
+ <p>Interactive API Documentation</p>
126
+ <a href="/docs" target="_blank" class="btn-test">Open</a>
127
+ </div>
128
+ <div class="api-card">
129
+ <div class="api-method get">GET</div>
130
+ <div class="api-path">/redoc</div>
131
+ <p>ReDoc API Documentation</p>
132
+ <a href="/redoc" target="_blank" class="btn-test">Open</a>
133
+ </div>
134
+ </div>
135
+ </section>
136
+
137
+ <!-- Response Viewer -->
138
+ <section class="response-section" id="responseSection" style="display: none;">
139
+ <h2>📋 API Response</h2>
140
+ <div class="response-controls">
141
+ <button class="btn-copy" onclick="copyResponse()">📋 Copy</button>
142
+ <button class="btn-close" onclick="closeResponse()">✕ Close</button>
143
+ </div>
144
+ <pre id="responseContent"></pre>
145
+ </section>
146
+
147
+ <!-- Footer -->
148
+ <footer class="footer">
149
+ <p>Powered by <strong>Flare.NX</strong> & <strong>Orynx AI Labs</strong></p>
150
+ <p>NVIDIA A10G Large GPU • FastAPI • Uvicorn • PyTorch</p>
151
+ <div class="footer-links">
152
+ <a href="/docs" target="_blank">API Docs</a>
153
+ <a href="https://huggingface.co/spaces/Speedofmastery/yyuujhu" target="_blank">HuggingFace Space</a>
154
+ </div>
155
+ </footer>
156
+ </div>
157
+
158
+ <script src="/static/script.js"></script>
159
+ </body>
160
+ </html>
static/script.js ADDED
@@ -0,0 +1,240 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // API Base URL - automatically uses the current host
2
+ const API_BASE = window.location.origin;
3
+
4
+ // Initialize on page load
5
+ document.addEventListener('DOMContentLoaded', () => {
6
+ console.log('🚀 Initializing Flare.NX & Orynx AI Labs Dashboard');
7
+ checkHealth();
8
+ checkGPU();
9
+ loadGPUInfo();
10
+ });
11
+
12
+ // Health Check
13
+ async function checkHealth() {
14
+ const statusEl = document.getElementById('healthStatus');
15
+ const cardEl = document.getElementById('healthCard');
16
+
17
+ try {
18
+ statusEl.innerHTML = '<div class="spinner"></div> Checking...';
19
+ const response = await fetch(`${API_BASE}/health`);
20
+ const data = await response.json();
21
+
22
+ if (data.status === 'healthy' && data.gpu_available) {
23
+ statusEl.innerHTML = `
24
+ <div class="status-ok">✅ Healthy</div>
25
+ <div class="status-detail">GPU: ${data.device_name}</div>
26
+ <div class="status-detail">Devices: ${data.cuda_devices}</div>
27
+ `;
28
+ cardEl.classList.add('status-ok');
29
+ cardEl.classList.remove('status-error');
30
+ } else {
31
+ statusEl.innerHTML = '<div class="status-warning">⚠️ CPU Only</div>';
32
+ cardEl.classList.add('status-warning');
33
+ }
34
+ } catch (error) {
35
+ statusEl.innerHTML = '<div class="status-error">❌ Error</div>';
36
+ cardEl.classList.add('status-error');
37
+ console.error('Health check error:', error);
38
+ }
39
+ }
40
+
41
+ // GPU Status Check
42
+ async function checkGPU() {
43
+ const statusEl = document.getElementById('gpuStatus');
44
+ const cardEl = document.getElementById('gpuCard');
45
+
46
+ try {
47
+ statusEl.innerHTML = '<div class="spinner"></div> Loading...';
48
+ const response = await fetch(`${API_BASE}/gpu-info`);
49
+ const data = await response.json();
50
+
51
+ if (data.cuda_available && data.devices.length > 0) {
52
+ const device = data.devices[0];
53
+ statusEl.innerHTML = `
54
+ <div class="status-ok">✅ Active</div>
55
+ <div class="status-detail">${device.name}</div>
56
+ <div class="status-detail">${device.total_memory_gb} GB VRAM</div>
57
+ `;
58
+ cardEl.classList.add('status-ok');
59
+ cardEl.classList.remove('status-error');
60
+ } else {
61
+ statusEl.innerHTML = '<div class="status-warning">⚠️ No GPU</div>';
62
+ cardEl.classList.add('status-warning');
63
+ }
64
+ } catch (error) {
65
+ statusEl.innerHTML = '<div class="status-error">❌ Error</div>';
66
+ cardEl.classList.add('status-error');
67
+ console.error('GPU check error:', error);
68
+ }
69
+ }
70
+
71
+ // Load GPU Information
72
+ async function loadGPUInfo() {
73
+ const detailsEl = document.getElementById('gpuDetails');
74
+
75
+ try {
76
+ const response = await fetch(`${API_BASE}/gpu-info`);
77
+ const data = await response.json();
78
+
79
+ if (data.cuda_available && data.devices.length > 0) {
80
+ const device = data.devices[0];
81
+ detailsEl.innerHTML = `
82
+ <div class="gpu-card">
83
+ <div class="gpu-header">
84
+ <h3>🎮 ${device.name}</h3>
85
+ <span class="gpu-badge">Device #${device.id}</span>
86
+ </div>
87
+ <div class="gpu-specs">
88
+ <div class="spec-item">
89
+ <span class="spec-label">Total Memory:</span>
90
+ <span class="spec-value">${device.total_memory_gb} GB</span>
91
+ </div>
92
+ <div class="spec-item">
93
+ <span class="spec-label">Compute Capability:</span>
94
+ <span class="spec-value">${device.major}.${device.minor}</span>
95
+ </div>
96
+ <div class="spec-item">
97
+ <span class="spec-label">Multiprocessors:</span>
98
+ <span class="spec-value">${device.multi_processor_count}</span>
99
+ </div>
100
+ <div class="spec-item">
101
+ <span class="spec-label">Total Devices:</span>
102
+ <span class="spec-value">${data.device_count}</span>
103
+ </div>
104
+ </div>
105
+ <div class="gpu-performance">
106
+ <div class="performance-bar">
107
+ <div class="performance-fill" style="width: 95%"></div>
108
+ </div>
109
+ <p class="performance-text">GPU Performance: Optimal</p>
110
+ </div>
111
+ </div>
112
+ `;
113
+ } else {
114
+ detailsEl.innerHTML = `
115
+ <div class="gpu-card gpu-unavailable">
116
+ <p>⚠️ CUDA not available. Running on CPU.</p>
117
+ </div>
118
+ `;
119
+ }
120
+ } catch (error) {
121
+ detailsEl.innerHTML = `
122
+ <div class="gpu-card gpu-error">
123
+ <p>❌ Error loading GPU information.</p>
124
+ </div>
125
+ `;
126
+ console.error('GPU info error:', error);
127
+ }
128
+ }
129
+
130
+ // Process Text
131
+ async function processText() {
132
+ const textInput = document.getElementById('textInput').value;
133
+ const maxLength = parseInt(document.getElementById('maxLength').value);
134
+ const outputGroup = document.getElementById('outputGroup');
135
+ const outputContent = document.getElementById('outputContent');
136
+
137
+ if (!textInput.trim()) {
138
+ alert('Please enter some text to process!');
139
+ return;
140
+ }
141
+
142
+ try {
143
+ outputContent.innerHTML = '<div class="spinner"></div> Processing with GPU...';
144
+ outputGroup.style.display = 'block';
145
+
146
+ const response = await fetch(`${API_BASE}/process`, {
147
+ method: 'POST',
148
+ headers: {
149
+ 'Content-Type': 'application/json',
150
+ },
151
+ body: JSON.stringify({
152
+ text: textInput,
153
+ max_length: maxLength
154
+ })
155
+ });
156
+
157
+ const data = await response.json();
158
+
159
+ outputContent.innerHTML = `
160
+ <div class="result-card">
161
+ <div class="result-item">
162
+ <strong>Input:</strong>
163
+ <div class="result-value">${data.input}</div>
164
+ </div>
165
+ <div class="result-item">
166
+ <strong>Processed:</strong>
167
+ <div class="result-value result-highlight">${data.processed}</div>
168
+ </div>
169
+ <div class="result-item">
170
+ <strong>Length:</strong>
171
+ <span class="result-badge">${data.length} characters</span>
172
+ </div>
173
+ <div class="result-item">
174
+ <strong>Max Length:</strong>
175
+ <span class="result-badge">${data.max_length}</span>
176
+ </div>
177
+ <div class="result-item">
178
+ <strong>GPU Used:</strong>
179
+ <span class="result-badge ${data.gpu_used ? 'badge-success' : 'badge-warning'}">
180
+ ${data.gpu_used ? '✅ Yes' : '⚠️ No'}
181
+ </span>
182
+ </div>
183
+ </div>
184
+ `;
185
+ } catch (error) {
186
+ outputContent.innerHTML = `
187
+ <div class="error-message">
188
+ ❌ Error processing text: ${error.message}
189
+ </div>
190
+ `;
191
+ console.error('Process error:', error);
192
+ }
193
+ }
194
+
195
+ // Test Endpoint
196
+ async function testEndpoint(endpoint) {
197
+ const responseSection = document.getElementById('responseSection');
198
+ const responseContent = document.getElementById('responseContent');
199
+
200
+ try {
201
+ responseContent.textContent = 'Loading...';
202
+ responseSection.style.display = 'block';
203
+ responseSection.scrollIntoView({ behavior: 'smooth' });
204
+
205
+ // Use /api for root endpoint, others as-is
206
+ const url = endpoint === '/' ? `${API_BASE}/api` : `${API_BASE}${endpoint}`;
207
+ const response = await fetch(url);
208
+ const data = await response.json();
209
+
210
+ responseContent.textContent = JSON.stringify(data, null, 2);
211
+ responseContent.classList.add('json-highlight');
212
+ } catch (error) {
213
+ responseContent.textContent = `Error: ${error.message}`;
214
+ console.error('Endpoint test error:', error);
215
+ }
216
+ }
217
+
218
+ // Copy Response
219
+ function copyResponse() {
220
+ const responseContent = document.getElementById('responseContent');
221
+ navigator.clipboard.writeText(responseContent.textContent).then(() => {
222
+ const btn = document.querySelector('.btn-copy');
223
+ const originalText = btn.textContent;
224
+ btn.textContent = '✅ Copied!';
225
+ setTimeout(() => {
226
+ btn.textContent = originalText;
227
+ }, 2000);
228
+ });
229
+ }
230
+
231
+ // Close Response
232
+ function closeResponse() {
233
+ document.getElementById('responseSection').style.display = 'none';
234
+ }
235
+
236
+ // Auto-refresh status every 30 seconds
237
+ setInterval(() => {
238
+ checkHealth();
239
+ checkGPU();
240
+ }, 30000);
static/style.css ADDED
@@ -0,0 +1,617 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Flare.NX & Orynx AI Labs - Color Scheme */
2
+ :root {
3
+ --navy-dark: #1E3A8A;
4
+ --navy-medium: #2563EB;
5
+ --navy-light: #3B82F6;
6
+ --orange-primary: #FF9933;
7
+ --orange-light: #FFAA55;
8
+ --white: #FFFFFF;
9
+ --gray-light: #E8F0FF;
10
+ --gray-medium: #94A3B8;
11
+ --success: #10B981;
12
+ --warning: #F59E0B;
13
+ --error: #EF4444;
14
+ }
15
+
16
+ * {
17
+ margin: 0;
18
+ padding: 0;
19
+ box-sizing: border-box;
20
+ }
21
+
22
+ body {
23
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
24
+ background: linear-gradient(135deg, var(--navy-dark) 0%, #0F172A 100%);
25
+ color: var(--white);
26
+ min-height: 100vh;
27
+ padding: 20px;
28
+ }
29
+
30
+ .container {
31
+ max-width: 1400px;
32
+ margin: 0 auto;
33
+ }
34
+
35
+ /* Header & Logos */
36
+ .header {
37
+ text-align: center;
38
+ padding: 40px 20px;
39
+ background: rgba(255, 255, 255, 0.05);
40
+ border-radius: 20px;
41
+ margin-bottom: 40px;
42
+ backdrop-filter: blur(10px);
43
+ border: 1px solid rgba(255, 255, 255, 0.1);
44
+ }
45
+
46
+ .logo-container {
47
+ display: flex;
48
+ justify-content: center;
49
+ align-items: center;
50
+ gap: 30px;
51
+ flex-wrap: wrap;
52
+ margin-bottom: 20px;
53
+ }
54
+
55
+ .logo-section {
56
+ display: flex;
57
+ align-items: center;
58
+ gap: 15px;
59
+ }
60
+
61
+ .logo-icon {
62
+ width: 80px;
63
+ height: 80px;
64
+ background: rgba(255, 255, 255, 0.1);
65
+ border-radius: 15px;
66
+ display: flex;
67
+ align-items: center;
68
+ justify-content: center;
69
+ padding: 10px;
70
+ }
71
+
72
+ .logo-icon svg {
73
+ width: 100%;
74
+ height: 100%;
75
+ }
76
+
77
+ .logo-text {
78
+ font-size: 2.5rem;
79
+ font-weight: 800;
80
+ letter-spacing: 2px;
81
+ text-transform: uppercase;
82
+ background: linear-gradient(135deg, var(--orange-primary), var(--orange-light));
83
+ -webkit-background-clip: text;
84
+ -webkit-text-fill-color: transparent;
85
+ background-clip: text;
86
+ }
87
+
88
+ .orynx-logo + .logo-text-group .logo-text {
89
+ background: linear-gradient(135deg, var(--white), var(--gray-light));
90
+ -webkit-background-clip: text;
91
+ -webkit-text-fill-color: transparent;
92
+ }
93
+
94
+ .logo-text-group {
95
+ display: flex;
96
+ flex-direction: column;
97
+ align-items: flex-start;
98
+ }
99
+
100
+ .logo-subtitle {
101
+ font-size: 1.2rem;
102
+ font-weight: 600;
103
+ color: var(--gray-light);
104
+ letter-spacing: 3px;
105
+ margin-top: -10px;
106
+ }
107
+
108
+ .logo-divider {
109
+ font-size: 3rem;
110
+ color: var(--orange-primary);
111
+ font-weight: 300;
112
+ }
113
+
114
+ .tagline {
115
+ font-size: 1.2rem;
116
+ color: var(--gray-light);
117
+ margin-top: 15px;
118
+ }
119
+
120
+ /* Sections */
121
+ section {
122
+ background: rgba(255, 255, 255, 0.05);
123
+ border-radius: 20px;
124
+ padding: 30px;
125
+ margin-bottom: 30px;
126
+ backdrop-filter: blur(10px);
127
+ border: 1px solid rgba(255, 255, 255, 0.1);
128
+ }
129
+
130
+ section h2 {
131
+ font-size: 2rem;
132
+ margin-bottom: 25px;
133
+ color: var(--orange-primary);
134
+ display: flex;
135
+ align-items: center;
136
+ gap: 10px;
137
+ }
138
+
139
+ /* Status Section */
140
+ .status-grid {
141
+ display: grid;
142
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
143
+ gap: 20px;
144
+ }
145
+
146
+ .status-card {
147
+ background: rgba(255, 255, 255, 0.08);
148
+ border-radius: 15px;
149
+ padding: 25px;
150
+ text-align: center;
151
+ border: 2px solid rgba(255, 255, 255, 0.1);
152
+ transition: all 0.3s ease;
153
+ }
154
+
155
+ .status-card:hover {
156
+ transform: translateY(-5px);
157
+ border-color: var(--orange-primary);
158
+ box-shadow: 0 10px 30px rgba(255, 153, 51, 0.3);
159
+ }
160
+
161
+ .status-card.status-ok {
162
+ border-color: var(--success);
163
+ }
164
+
165
+ .status-card.status-warning {
166
+ border-color: var(--warning);
167
+ }
168
+
169
+ .status-card.status-error {
170
+ border-color: var(--error);
171
+ }
172
+
173
+ .status-icon {
174
+ font-size: 3rem;
175
+ margin-bottom: 15px;
176
+ }
177
+
178
+ .status-card h3 {
179
+ font-size: 1.3rem;
180
+ margin-bottom: 15px;
181
+ color: var(--white);
182
+ }
183
+
184
+ .status-value {
185
+ font-size: 1.1rem;
186
+ margin-bottom: 15px;
187
+ min-height: 80px;
188
+ }
189
+
190
+ .status-ok {
191
+ color: var(--success);
192
+ font-weight: 600;
193
+ }
194
+
195
+ .status-warning {
196
+ color: var(--warning);
197
+ font-weight: 600;
198
+ }
199
+
200
+ .status-error {
201
+ color: var(--error);
202
+ font-weight: 600;
203
+ }
204
+
205
+ .status-detail {
206
+ color: var(--gray-light);
207
+ font-size: 0.9rem;
208
+ margin-top: 5px;
209
+ }
210
+
211
+ /* GPU Section */
212
+ .gpu-card {
213
+ background: rgba(255, 255, 255, 0.08);
214
+ border-radius: 15px;
215
+ padding: 25px;
216
+ border: 2px solid var(--navy-light);
217
+ }
218
+
219
+ .gpu-header {
220
+ display: flex;
221
+ justify-content: space-between;
222
+ align-items: center;
223
+ margin-bottom: 20px;
224
+ }
225
+
226
+ .gpu-header h3 {
227
+ font-size: 1.5rem;
228
+ color: var(--orange-primary);
229
+ }
230
+
231
+ .gpu-badge {
232
+ background: var(--navy-light);
233
+ padding: 5px 15px;
234
+ border-radius: 20px;
235
+ font-size: 0.9rem;
236
+ }
237
+
238
+ .gpu-specs {
239
+ display: grid;
240
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
241
+ gap: 15px;
242
+ margin-bottom: 20px;
243
+ }
244
+
245
+ .spec-item {
246
+ display: flex;
247
+ justify-content: space-between;
248
+ padding: 10px;
249
+ background: rgba(255, 255, 255, 0.05);
250
+ border-radius: 8px;
251
+ }
252
+
253
+ .spec-label {
254
+ color: var(--gray-medium);
255
+ }
256
+
257
+ .spec-value {
258
+ color: var(--white);
259
+ font-weight: 600;
260
+ }
261
+
262
+ .gpu-performance {
263
+ margin-top: 20px;
264
+ }
265
+
266
+ .performance-bar {
267
+ background: rgba(255, 255, 255, 0.1);
268
+ height: 10px;
269
+ border-radius: 5px;
270
+ overflow: hidden;
271
+ margin-bottom: 10px;
272
+ }
273
+
274
+ .performance-fill {
275
+ background: linear-gradient(90deg, var(--success), var(--navy-light));
276
+ height: 100%;
277
+ border-radius: 5px;
278
+ transition: width 0.5s ease;
279
+ }
280
+
281
+ .performance-text {
282
+ text-align: center;
283
+ color: var(--gray-light);
284
+ }
285
+
286
+ /* Process Section */
287
+ .process-container {
288
+ max-width: 800px;
289
+ margin: 0 auto;
290
+ }
291
+
292
+ .input-group {
293
+ margin-bottom: 20px;
294
+ }
295
+
296
+ .input-group label {
297
+ display: block;
298
+ margin-bottom: 8px;
299
+ color: var(--gray-light);
300
+ font-weight: 600;
301
+ }
302
+
303
+ .input-group textarea,
304
+ .input-group input {
305
+ width: 100%;
306
+ padding: 15px;
307
+ border-radius: 10px;
308
+ border: 2px solid rgba(255, 255, 255, 0.1);
309
+ background: rgba(255, 255, 255, 0.05);
310
+ color: var(--white);
311
+ font-size: 1rem;
312
+ font-family: inherit;
313
+ transition: border-color 0.3s ease;
314
+ }
315
+
316
+ .input-group textarea:focus,
317
+ .input-group input:focus {
318
+ outline: none;
319
+ border-color: var(--orange-primary);
320
+ }
321
+
322
+ .btn-process {
323
+ width: 100%;
324
+ padding: 18px;
325
+ font-size: 1.2rem;
326
+ font-weight: 600;
327
+ background: linear-gradient(135deg, var(--orange-primary), var(--orange-light));
328
+ color: var(--navy-dark);
329
+ border: none;
330
+ border-radius: 12px;
331
+ cursor: pointer;
332
+ display: flex;
333
+ align-items: center;
334
+ justify-content: center;
335
+ gap: 10px;
336
+ transition: all 0.3s ease;
337
+ }
338
+
339
+ .btn-process:hover {
340
+ transform: translateY(-2px);
341
+ box-shadow: 0 10px 30px rgba(255, 153, 51, 0.4);
342
+ }
343
+
344
+ .btn-icon {
345
+ font-size: 1.4rem;
346
+ }
347
+
348
+ .output-group {
349
+ margin-top: 30px;
350
+ padding: 25px;
351
+ background: rgba(255, 255, 255, 0.08);
352
+ border-radius: 15px;
353
+ border: 2px solid var(--success);
354
+ }
355
+
356
+ .output-group h3 {
357
+ margin-bottom: 15px;
358
+ color: var(--success);
359
+ }
360
+
361
+ .result-card {
362
+ display: flex;
363
+ flex-direction: column;
364
+ gap: 15px;
365
+ }
366
+
367
+ .result-item {
368
+ padding: 15px;
369
+ background: rgba(255, 255, 255, 0.05);
370
+ border-radius: 8px;
371
+ }
372
+
373
+ .result-item strong {
374
+ color: var(--orange-primary);
375
+ margin-bottom: 8px;
376
+ display: block;
377
+ }
378
+
379
+ .result-value {
380
+ color: var(--white);
381
+ padding: 10px;
382
+ background: rgba(255, 255, 255, 0.05);
383
+ border-radius: 5px;
384
+ margin-top: 8px;
385
+ }
386
+
387
+ .result-highlight {
388
+ background: rgba(255, 153, 51, 0.1);
389
+ border-left: 3px solid var(--orange-primary);
390
+ font-weight: 600;
391
+ }
392
+
393
+ .result-badge {
394
+ display: inline-block;
395
+ padding: 5px 12px;
396
+ border-radius: 20px;
397
+ background: var(--navy-light);
398
+ font-size: 0.9rem;
399
+ }
400
+
401
+ .badge-success {
402
+ background: var(--success);
403
+ }
404
+
405
+ .badge-warning {
406
+ background: var(--warning);
407
+ }
408
+
409
+ /* API Section */
410
+ .api-grid {
411
+ display: grid;
412
+ grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
413
+ gap: 20px;
414
+ }
415
+
416
+ .api-card {
417
+ background: rgba(255, 255, 255, 0.08);
418
+ border-radius: 12px;
419
+ padding: 20px;
420
+ border: 2px solid rgba(255, 255, 255, 0.1);
421
+ transition: all 0.3s ease;
422
+ }
423
+
424
+ .api-card:hover {
425
+ border-color: var(--orange-primary);
426
+ transform: translateY(-3px);
427
+ }
428
+
429
+ .api-method {
430
+ display: inline-block;
431
+ padding: 5px 12px;
432
+ border-radius: 5px;
433
+ font-weight: 600;
434
+ font-size: 0.85rem;
435
+ margin-bottom: 10px;
436
+ }
437
+
438
+ .api-method.get {
439
+ background: var(--success);
440
+ color: var(--white);
441
+ }
442
+
443
+ .api-method.post {
444
+ background: var(--navy-light);
445
+ color: var(--white);
446
+ }
447
+
448
+ .api-path {
449
+ font-family: 'Courier New', monospace;
450
+ font-size: 1.1rem;
451
+ color: var(--orange-primary);
452
+ margin-bottom: 10px;
453
+ font-weight: 600;
454
+ }
455
+
456
+ .api-card p {
457
+ color: var(--gray-light);
458
+ margin-bottom: 15px;
459
+ font-size: 0.95rem;
460
+ }
461
+
462
+ /* Buttons */
463
+ .btn-refresh,
464
+ .btn-test {
465
+ padding: 10px 20px;
466
+ background: rgba(255, 255, 255, 0.1);
467
+ color: var(--white);
468
+ border: 2px solid var(--orange-primary);
469
+ border-radius: 8px;
470
+ cursor: pointer;
471
+ font-weight: 600;
472
+ transition: all 0.3s ease;
473
+ text-decoration: none;
474
+ display: inline-block;
475
+ text-align: center;
476
+ }
477
+
478
+ .btn-refresh:hover,
479
+ .btn-test:hover {
480
+ background: var(--orange-primary);
481
+ color: var(--navy-dark);
482
+ }
483
+
484
+ /* Response Section */
485
+ .response-section {
486
+ position: relative;
487
+ }
488
+
489
+ .response-controls {
490
+ display: flex;
491
+ gap: 10px;
492
+ margin-bottom: 15px;
493
+ }
494
+
495
+ .btn-copy,
496
+ .btn-close {
497
+ padding: 8px 15px;
498
+ background: var(--navy-light);
499
+ color: var(--white);
500
+ border: none;
501
+ border-radius: 6px;
502
+ cursor: pointer;
503
+ font-weight: 600;
504
+ transition: all 0.3s ease;
505
+ }
506
+
507
+ .btn-copy:hover {
508
+ background: var(--success);
509
+ }
510
+
511
+ .btn-close:hover {
512
+ background: var(--error);
513
+ }
514
+
515
+ #responseContent {
516
+ background: rgba(0, 0, 0, 0.5);
517
+ padding: 20px;
518
+ border-radius: 10px;
519
+ overflow-x: auto;
520
+ color: var(--gray-light);
521
+ font-family: 'Courier New', monospace;
522
+ font-size: 0.95rem;
523
+ line-height: 1.6;
524
+ border: 2px solid var(--navy-light);
525
+ }
526
+
527
+ /* Footer */
528
+ .footer {
529
+ text-align: center;
530
+ padding: 30px;
531
+ color: var(--gray-medium);
532
+ margin-top: 40px;
533
+ }
534
+
535
+ .footer p {
536
+ margin-bottom: 10px;
537
+ }
538
+
539
+ .footer strong {
540
+ color: var(--orange-primary);
541
+ }
542
+
543
+ .footer-links {
544
+ display: flex;
545
+ justify-content: center;
546
+ gap: 20px;
547
+ margin-top: 15px;
548
+ }
549
+
550
+ .footer-links a {
551
+ color: var(--white);
552
+ text-decoration: none;
553
+ padding: 8px 16px;
554
+ border: 1px solid rgba(255, 255, 255, 0.2);
555
+ border-radius: 6px;
556
+ transition: all 0.3s ease;
557
+ }
558
+
559
+ .footer-links a:hover {
560
+ background: var(--orange-primary);
561
+ color: var(--navy-dark);
562
+ border-color: var(--orange-primary);
563
+ }
564
+
565
+ /* Loading Spinner */
566
+ .spinner {
567
+ display: inline-block;
568
+ width: 20px;
569
+ height: 20px;
570
+ border: 3px solid rgba(255, 255, 255, 0.3);
571
+ border-radius: 50%;
572
+ border-top-color: var(--orange-primary);
573
+ animation: spin 1s linear infinite;
574
+ }
575
+
576
+ @keyframes spin {
577
+ to { transform: rotate(360deg); }
578
+ }
579
+
580
+ .loading {
581
+ text-align: center;
582
+ padding: 20px;
583
+ color: var(--gray-medium);
584
+ }
585
+
586
+ .error-message {
587
+ color: var(--error);
588
+ padding: 20px;
589
+ background: rgba(239, 68, 68, 0.1);
590
+ border-radius: 10px;
591
+ border-left: 4px solid var(--error);
592
+ }
593
+
594
+ /* Responsive Design */
595
+ @media (max-width: 768px) {
596
+ .logo-container {
597
+ flex-direction: column;
598
+ gap: 20px;
599
+ }
600
+
601
+ .logo-divider {
602
+ transform: rotate(90deg);
603
+ }
604
+
605
+ .status-grid,
606
+ .api-grid {
607
+ grid-template-columns: 1fr;
608
+ }
609
+
610
+ section {
611
+ padding: 20px;
612
+ }
613
+
614
+ section h2 {
615
+ font-size: 1.5rem;
616
+ }
617
+ }