nodebb-theme-flawless-rp 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/library.js ADDED
@@ -0,0 +1,26 @@
1
+ 'use strict';
2
+
3
+ const theme = module.exports;
4
+
5
+ /**
6
+ * Flawless Roleplay Theme — Library
7
+ * Handles theme initialization and custom hooks
8
+ */
9
+
10
+ theme.onConfigGet = async function (config) {
11
+ // Override default theme settings
12
+ config.theme = config.theme || {};
13
+ config['brand:logo'] = config['brand:logo'] || '';
14
+ config['brand:logo:url'] = config['brand:logo:url'] || '/';
15
+ return config;
16
+ };
17
+
18
+ theme.addCustomCSS = async function (header) {
19
+ // Add Google Fonts preconnect for performance
20
+ header.links = header.links || [];
21
+ header.links.push(
22
+ { rel: 'preconnect', href: 'https://fonts.googleapis.com' },
23
+ { rel: 'preconnect', href: 'https://fonts.gstatic.com', crossorigin: true }
24
+ );
25
+ return header;
26
+ };
package/package.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "nodebb-theme-flawless-rp",
3
+ "type": "theme",
4
+ "version": "1.0.0",
5
+ "description": "Flawless Roleplay — Underground Criminal Empire theme for NodeBB. Dark obsidian backgrounds, gold/amber accents, Barlow Condensed typography.",
6
+ "author": "Flawless Roleplay Team",
7
+ "license": "MIT",
8
+ "keywords": [
9
+ "nodebb-theme",
10
+ "samp",
11
+ "roleplay",
12
+ "dark-theme",
13
+ "gaming"
14
+ ],
15
+ "nbbpm": {
16
+ "compatibility": "^4.0.0"
17
+ },
18
+ "theme": {
19
+ "id": "nodebb-theme-flawless-rp",
20
+ "name": "Flawless Roleplay",
21
+ "baseTheme": "nodebb-theme-harmony",
22
+ "templates": "./templates",
23
+ "screenshot": "./screenshot.png"
24
+ },
25
+ "scripts": {},
26
+ "dependencies": {}
27
+ }
package/plugin.json ADDED
@@ -0,0 +1,16 @@
1
+ {
2
+ "id": "nodebb-theme-flawless-rp",
3
+ "name": "Flawless Roleplay Theme",
4
+ "description": "Underground Criminal Empire — Dark theme with gold/amber accents for SA-MP Roleplay",
5
+ "url": "https://github.com/omerbeqiri1989-beep/NodeBB",
6
+ "library": "./library.js",
7
+ "hooks": [
8
+ { "hook": "filter:config.get", "method": "onConfigGet" },
9
+ { "hook": "filter:header.build", "method": "addCustomCSS" }
10
+ ],
11
+ "staticDirs": {
12
+ "static": "./static"
13
+ },
14
+ "css": ["static/styles/flawless.css"],
15
+ "templates": "./templates"
16
+ }
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Flawless Roleplay — Client-side Theme JavaScript
3
+ * Handles dynamic features: server status, latest topics, timeago, etc.
4
+ */
5
+
6
+ 'use strict';
7
+
8
+ (function () {
9
+ // Wait for DOM ready
10
+ document.addEventListener('DOMContentLoaded', function () {
11
+ initServerStatus();
12
+ initLatestTopics();
13
+ initCategoryHoverEffects();
14
+ initDonatorAvatarEffects();
15
+ });
16
+
17
+ /**
18
+ * Server Status Widget — Polls SA-MP server query API
19
+ */
20
+ function initServerStatus() {
21
+ var statusEl = document.getElementById('server-status-indicator');
22
+ var countEl = document.getElementById('player-count');
23
+ if (!statusEl || !countEl) return;
24
+
25
+ function updateStatus() {
26
+ fetch('/api/flawless-samp/server-status')
27
+ .then(function (r) { return r.json(); })
28
+ .then(function (data) {
29
+ if (data && data.online) {
30
+ statusEl.style.background = '#22C55E';
31
+ statusEl.nextElementSibling && (statusEl.nextElementSibling.textContent = 'SERVER ONLINE');
32
+ countEl.textContent = data.players || '0';
33
+ } else {
34
+ statusEl.style.background = '#EF4444';
35
+ statusEl.nextElementSibling && (statusEl.nextElementSibling.textContent = 'SERVER OFFLINE');
36
+ countEl.textContent = '--';
37
+ }
38
+ })
39
+ .catch(function () {
40
+ statusEl.style.background = '#6B7280';
41
+ countEl.textContent = '--';
42
+ });
43
+ }
44
+
45
+ updateStatus();
46
+ setInterval(updateStatus, 30000); // Update every 30 seconds
47
+ }
48
+
49
+ /**
50
+ * Latest Topics Sidebar Widget
51
+ */
52
+ function initLatestTopics() {
53
+ var container = document.getElementById('frp-latest-topics');
54
+ if (!container) return;
55
+
56
+ fetch('/api/recent?count=10')
57
+ .then(function (r) { return r.json(); })
58
+ .then(function (data) {
59
+ if (!data || !data.topics) return;
60
+ var html = '';
61
+ data.topics.forEach(function (t) {
62
+ html += '<div class="topic-item" style="padding: 8px 0; border-bottom: 1px solid #1e1e24;">';
63
+ html += '<a href="/topic/' + t.slug + '" style="color: #e5e7eb; text-decoration: none; font-size: 0.9rem; display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">' + escapeHtml(t.title) + '</a>';
64
+ html += '<div class="topic-meta" style="font-size: 0.75rem; color: #6B7280; margin-top: 2px;">';
65
+ html += 'by ' + escapeHtml(t.user ? t.user.username : 'Unknown');
66
+ html += ' &middot; <span class="timeago" title="' + (t.timestampISO || '') + '"></span>';
67
+ html += '</div></div>';
68
+ });
69
+ container.innerHTML = html;
70
+
71
+ // Re-initialize timeago for new elements
72
+ if (window.jQuery && window.jQuery.timeago) {
73
+ window.jQuery('.timeago').timeago();
74
+ }
75
+ })
76
+ .catch(function () {
77
+ container.innerHTML = '<p style="color: #6B7280; font-size: 0.85rem;">Unable to load topics.</p>';
78
+ });
79
+ }
80
+
81
+ /**
82
+ * Category hover effects
83
+ */
84
+ function initCategoryHoverEffects() {
85
+ var categories = document.querySelectorAll('.category-item');
86
+ categories.forEach(function (cat) {
87
+ cat.addEventListener('mouseenter', function () {
88
+ this.style.transform = 'translateX(2px)';
89
+ });
90
+ cat.addEventListener('mouseleave', function () {
91
+ this.style.transform = 'translateX(0)';
92
+ });
93
+ });
94
+ }
95
+
96
+ /**
97
+ * Apply donator avatar glow effects based on data attributes
98
+ */
99
+ function initDonatorAvatarEffects() {
100
+ var avatars = document.querySelectorAll('[data-donator-rank]');
101
+ avatars.forEach(function (avatar) {
102
+ var rank = parseInt(avatar.getAttribute('data-donator-rank'), 10);
103
+ if (rank === 1) avatar.classList.add('donator-daisy');
104
+ else if (rank === 2) avatar.classList.add('donator-rose');
105
+ else if (rank >= 3) avatar.classList.add('donator-ivy');
106
+ });
107
+ }
108
+
109
+ /**
110
+ * HTML escape utility
111
+ */
112
+ function escapeHtml(text) {
113
+ var div = document.createElement('div');
114
+ div.appendChild(document.createTextNode(text));
115
+ return div.innerHTML;
116
+ }
117
+ })();
@@ -0,0 +1,1024 @@
1
+ /* ============================================
2
+ FLAWLESS ROLEPLAY — Underground Criminal Empire
3
+ NodeBB Theme Override
4
+ ============================================ */
5
+
6
+ /* Google Fonts Import */
7
+ @import url('https://fonts.googleapis.com/css2?family=Barlow+Condensed:wght@400;600;700&family=Barlow:wght@400;500;600&family=JetBrains+Mono:wght@400;500&display=swap');
8
+
9
+ :root {
10
+ /* ---- Backgrounds ---- */
11
+ --bs-body-bg: #0a0a0b;
12
+ --bs-body-color: #e5e7eb;
13
+ --bs-secondary-bg: #111114;
14
+ --bs-tertiary-bg: #18181c;
15
+
16
+ /* ---- Surfaces ---- */
17
+ --frp-surface: #111114;
18
+ --frp-surface-hover: #18181c;
19
+ --frp-surface-active: #1e1e24;
20
+ --frp-surface-elevated: #1a1a1f;
21
+
22
+ /* ---- Borders ---- */
23
+ --frp-border: #1e1e24;
24
+ --frp-border-subtle: #161619;
25
+ --frp-border-strong: #2a2a32;
26
+
27
+ /* ---- Primary — Gold/Amber (power, money, authority) ---- */
28
+ --frp-primary: #F59E0B;
29
+ --frp-primary-hover: #D97706;
30
+ --frp-primary-light: rgba(245, 158, 11, 0.15);
31
+ --frp-primary-glow: 0 0 20px rgba(245, 158, 11, 0.3);
32
+ --bs-primary: #F59E0B;
33
+ --bs-primary-rgb: 245, 158, 11;
34
+ --bs-link-color: #F59E0B;
35
+ --bs-link-hover-color: #D97706;
36
+
37
+ /* ---- Danger — Red ---- */
38
+ --frp-danger: #EF4444;
39
+ --frp-danger-light: rgba(239, 68, 68, 0.15);
40
+
41
+ /* ---- Success — Green ---- */
42
+ --frp-success: #22C55E;
43
+ --frp-success-light: rgba(34, 197, 94, 0.15);
44
+
45
+ /* ---- Info — Blue (law enforcement) ---- */
46
+ --frp-info: #3B82F6;
47
+ --frp-info-light: rgba(59, 130, 246, 0.15);
48
+
49
+ /* ---- Warning ---- */
50
+ --frp-warning: #F59E0B;
51
+ --frp-warning-light: rgba(245, 158, 11, 0.15);
52
+
53
+ /* ---- Muted ---- */
54
+ --frp-muted: #6B7280;
55
+ --frp-muted-light: #9CA3AF;
56
+
57
+ /* ---- Faction Colors ---- */
58
+ --frp-faction-lspd: #3B82F6;
59
+ --frp-faction-fbi: #1D4ED8;
60
+ --frp-faction-sasd: #92400E;
61
+ --frp-faction-ares: #7C3AED;
62
+ --frp-faction-sanews: #06B6D4;
63
+ --frp-faction-gov: #059669;
64
+ --frp-faction-hitman: #DC2626;
65
+ --frp-faction-medic: #F43F5E;
66
+ --frp-faction-ng: #4B5563;
67
+
68
+ /* ---- Gang Colors (from bandana hex) ---- */
69
+ --frp-gang-ghouls: #F58216;
70
+ --frp-gang-velvet: #636363;
71
+ --frp-gang-baba: #22C55E;
72
+ --frp-gang-rifa: #3B82F6;
73
+ --frp-gang-grove: #16A34A;
74
+ --frp-gang-lcn: #1F2937;
75
+
76
+ /* ---- Typography ---- */
77
+ --frp-font-display: 'Barlow Condensed', sans-serif;
78
+ --frp-font-body: 'Barlow', sans-serif;
79
+ --frp-font-mono: 'JetBrains Mono', monospace;
80
+ --bs-body-font-family: 'Barlow', sans-serif;
81
+ }
82
+
83
+ /* ============================================
84
+ GLOBAL OVERRIDES
85
+ ============================================ */
86
+
87
+ body {
88
+ background-color: #0a0a0b !important;
89
+ color: #e5e7eb;
90
+ font-family: var(--frp-font-body);
91
+ -webkit-font-smoothing: antialiased;
92
+ -moz-osx-font-smoothing: grayscale;
93
+ }
94
+
95
+ a {
96
+ color: var(--frp-primary);
97
+ text-decoration: none;
98
+ transition: color 0.15s ease;
99
+ }
100
+
101
+ a:hover {
102
+ color: var(--frp-primary-hover);
103
+ }
104
+
105
+ h1, h2, h3, h4, h5, h6 {
106
+ font-family: var(--frp-font-display);
107
+ font-weight: 700;
108
+ text-transform: uppercase;
109
+ letter-spacing: 0.5px;
110
+ color: #f3f4f6;
111
+ }
112
+
113
+ code, pre, .monospace {
114
+ font-family: var(--frp-font-mono);
115
+ }
116
+
117
+ ::selection {
118
+ background: rgba(245, 158, 11, 0.3);
119
+ color: #fff;
120
+ }
121
+
122
+ /* Scrollbar */
123
+ ::-webkit-scrollbar {
124
+ width: 8px;
125
+ height: 8px;
126
+ }
127
+
128
+ ::-webkit-scrollbar-track {
129
+ background: #0a0a0b;
130
+ }
131
+
132
+ ::-webkit-scrollbar-thumb {
133
+ background: #2a2a32;
134
+ border-radius: 4px;
135
+ }
136
+
137
+ ::-webkit-scrollbar-thumb:hover {
138
+ background: #3a3a44;
139
+ }
140
+
141
+ /* ============================================
142
+ HEADER / NAVBAR
143
+ ============================================ */
144
+
145
+ .navbar,
146
+ [component="navbar"],
147
+ header .navbar {
148
+ background: #111114 !important;
149
+ border-bottom: 1px solid var(--frp-border) !important;
150
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
151
+ backdrop-filter: blur(12px);
152
+ }
153
+
154
+ .navbar .navbar-brand,
155
+ [component="navbar"] .navbar-brand {
156
+ font-family: var(--frp-font-display) !important;
157
+ font-weight: 700 !important;
158
+ color: var(--frp-primary) !important;
159
+ text-transform: uppercase;
160
+ letter-spacing: 2px;
161
+ font-size: 1.3rem;
162
+ }
163
+
164
+ .navbar .nav-link,
165
+ [component="navbar"] .nav-link {
166
+ color: #9CA3AF !important;
167
+ font-family: var(--frp-font-body);
168
+ font-weight: 500;
169
+ transition: color 0.15s ease;
170
+ }
171
+
172
+ .navbar .nav-link:hover,
173
+ .navbar .nav-link.active,
174
+ [component="navbar"] .nav-link:hover,
175
+ [component="navbar"] .nav-link.active {
176
+ color: var(--frp-primary) !important;
177
+ }
178
+
179
+ .navbar .dropdown-menu,
180
+ [component="navbar"] .dropdown-menu {
181
+ background: var(--frp-surface) !important;
182
+ border: 1px solid var(--frp-border) !important;
183
+ box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5);
184
+ }
185
+
186
+ .navbar .dropdown-item,
187
+ [component="navbar"] .dropdown-item {
188
+ color: #e5e7eb !important;
189
+ }
190
+
191
+ .navbar .dropdown-item:hover,
192
+ [component="navbar"] .dropdown-item:hover {
193
+ background: var(--frp-surface-hover) !important;
194
+ color: var(--frp-primary) !important;
195
+ }
196
+
197
+ /* ============================================
198
+ CATEGORY LIST
199
+ ============================================ */
200
+
201
+ [component="categories/category"] {
202
+ background: var(--frp-surface) !important;
203
+ border: 1px solid var(--frp-border) !important;
204
+ border-left: 3px solid var(--frp-primary) !important;
205
+ border-radius: 4px !important;
206
+ margin-bottom: 8px !important;
207
+ transition: all 0.2s ease;
208
+ }
209
+
210
+ [component="categories/category"]:hover {
211
+ border-left-color: var(--frp-primary-hover) !important;
212
+ background: var(--frp-surface-hover) !important;
213
+ box-shadow: var(--frp-primary-glow);
214
+ }
215
+
216
+ /* Category Headers / Section Headers */
217
+ .category-header,
218
+ .section-header {
219
+ font-family: var(--frp-font-display);
220
+ font-weight: 700;
221
+ text-transform: uppercase;
222
+ letter-spacing: 2px;
223
+ color: var(--frp-primary);
224
+ border-bottom: 2px solid var(--frp-primary);
225
+ padding-bottom: 8px;
226
+ margin-bottom: 16px;
227
+ font-size: 1.1rem;
228
+ }
229
+
230
+ /* Category icons */
231
+ [component="categories/category"] .category-icon {
232
+ color: var(--frp-primary);
233
+ }
234
+
235
+ /* Category stats */
236
+ [component="categories/category"] .category-stat {
237
+ color: var(--frp-muted);
238
+ font-family: var(--frp-font-mono);
239
+ font-size: 0.8rem;
240
+ }
241
+
242
+ /* Category description */
243
+ [component="categories/category"] .category-description {
244
+ color: var(--frp-muted-light);
245
+ font-size: 0.85rem;
246
+ }
247
+
248
+ /* ============================================
249
+ TOPIC LIST
250
+ ============================================ */
251
+
252
+ [component="category/topic"],
253
+ [component="category"] .topic-row,
254
+ .topics-list .topic-row {
255
+ background: var(--frp-surface) !important;
256
+ border: 1px solid var(--frp-border) !important;
257
+ border-radius: 4px !important;
258
+ margin-bottom: 4px !important;
259
+ transition: all 0.15s ease;
260
+ }
261
+
262
+ [component="category/topic"]:hover,
263
+ .topics-list .topic-row:hover {
264
+ background: var(--frp-surface-hover) !important;
265
+ border-color: var(--frp-border-strong) !important;
266
+ }
267
+
268
+ [component="category/topic"] .title,
269
+ .topics-list .topic-title a {
270
+ color: #e5e7eb !important;
271
+ font-weight: 500;
272
+ }
273
+
274
+ [component="category/topic"] .title:hover,
275
+ .topics-list .topic-title a:hover {
276
+ color: var(--frp-primary) !important;
277
+ }
278
+
279
+ /* Pinned topics */
280
+ [component="category/topic"].pinned {
281
+ border-left: 3px solid var(--frp-primary) !important;
282
+ }
283
+
284
+ /* Locked topics */
285
+ [component="category/topic"].locked {
286
+ opacity: 0.7;
287
+ }
288
+
289
+ /* ============================================
290
+ TOPIC VIEW / POST CONTENT
291
+ ============================================ */
292
+
293
+ [component="post"],
294
+ .post-container {
295
+ background: var(--frp-surface) !important;
296
+ border: 1px solid var(--frp-border) !important;
297
+ border-radius: 4px !important;
298
+ margin-bottom: 12px !important;
299
+ }
300
+
301
+ [component="post"] .post-header {
302
+ border-bottom: 1px solid var(--frp-border);
303
+ padding-bottom: 8px;
304
+ }
305
+
306
+ [component="post"] .content,
307
+ .post-content {
308
+ color: #d1d5db;
309
+ line-height: 1.7;
310
+ }
311
+
312
+ [component="post"] .content blockquote {
313
+ border-left: 3px solid var(--frp-primary);
314
+ background: var(--frp-primary-light);
315
+ padding: 12px 16px;
316
+ border-radius: 0 4px 4px 0;
317
+ color: #e5e7eb;
318
+ }
319
+
320
+ [component="post"] .content code {
321
+ background: rgba(245, 158, 11, 0.1);
322
+ color: var(--frp-primary);
323
+ padding: 2px 6px;
324
+ border-radius: 3px;
325
+ font-family: var(--frp-font-mono);
326
+ }
327
+
328
+ [component="post"] .content pre {
329
+ background: #0d0d0f !important;
330
+ border: 1px solid var(--frp-border);
331
+ border-radius: 4px;
332
+ padding: 16px;
333
+ }
334
+
335
+ /* Post actions */
336
+ [component="post"] .post-footer .btn,
337
+ [component="post"] .actions .btn {
338
+ color: var(--frp-muted) !important;
339
+ transition: color 0.15s ease;
340
+ }
341
+
342
+ [component="post"] .post-footer .btn:hover,
343
+ [component="post"] .actions .btn:hover {
344
+ color: var(--frp-primary) !important;
345
+ }
346
+
347
+ /* ============================================
348
+ USER PROFILE / AVATAR
349
+ ============================================ */
350
+
351
+ .avatar {
352
+ border: 2px solid var(--frp-border);
353
+ border-radius: 50%;
354
+ }
355
+
356
+ /* Donator glow effects */
357
+ .avatar.donator-daisy {
358
+ border-color: #A3E635;
359
+ box-shadow: 0 0 8px rgba(163, 230, 53, 0.3);
360
+ }
361
+
362
+ .avatar.donator-rose {
363
+ border-color: #F59E0B;
364
+ box-shadow: 0 0 8px rgba(245, 158, 11, 0.3);
365
+ }
366
+
367
+ .avatar.donator-ivy {
368
+ border-color: #EF4444;
369
+ box-shadow: 0 0 12px rgba(239, 68, 68, 0.4);
370
+ animation: ivyGlow 2s ease-in-out infinite alternate;
371
+ }
372
+
373
+ @keyframes ivyGlow {
374
+ from { box-shadow: 0 0 8px rgba(239, 68, 68, 0.3); }
375
+ to { box-shadow: 0 0 16px rgba(245, 158, 11, 0.5); }
376
+ }
377
+
378
+ /* User profile page */
379
+ [component="account/profile"] {
380
+ background: var(--frp-surface) !important;
381
+ }
382
+
383
+ .profile-header {
384
+ background: linear-gradient(135deg, #111114 0%, #1a1a1f 100%);
385
+ border-bottom: 2px solid var(--frp-primary);
386
+ }
387
+
388
+ /* ============================================
389
+ SIDEBAR & WIDGETS
390
+ ============================================ */
391
+
392
+ .sidebar .widget,
393
+ [widget-area] .widget {
394
+ background: var(--frp-surface) !important;
395
+ border: 1px solid var(--frp-border) !important;
396
+ border-radius: 4px !important;
397
+ margin-bottom: 12px !important;
398
+ }
399
+
400
+ .sidebar .widget .widget-header,
401
+ [widget-area] .widget .widget-header {
402
+ font-family: var(--frp-font-display);
403
+ font-weight: 700;
404
+ text-transform: uppercase;
405
+ letter-spacing: 1px;
406
+ color: var(--frp-primary);
407
+ border-bottom: 2px solid var(--frp-primary);
408
+ padding-bottom: 8px;
409
+ margin-bottom: 12px;
410
+ font-size: 0.95rem;
411
+ }
412
+
413
+ /* ============================================
414
+ BUTTONS
415
+ ============================================ */
416
+
417
+ .btn-primary,
418
+ .btn-primary:focus {
419
+ background-color: var(--frp-primary) !important;
420
+ border-color: var(--frp-primary) !important;
421
+ color: #000 !important;
422
+ font-family: var(--frp-font-display);
423
+ font-weight: 600;
424
+ text-transform: uppercase;
425
+ letter-spacing: 1px;
426
+ transition: all 0.2s ease;
427
+ }
428
+
429
+ .btn-primary:hover {
430
+ background-color: var(--frp-primary-hover) !important;
431
+ border-color: var(--frp-primary-hover) !important;
432
+ box-shadow: var(--frp-primary-glow);
433
+ }
434
+
435
+ .btn-outline-primary {
436
+ border-color: var(--frp-primary) !important;
437
+ color: var(--frp-primary) !important;
438
+ }
439
+
440
+ .btn-outline-primary:hover {
441
+ background-color: var(--frp-primary) !important;
442
+ color: #000 !important;
443
+ }
444
+
445
+ .btn-secondary {
446
+ background-color: var(--frp-surface-active) !important;
447
+ border-color: var(--frp-border) !important;
448
+ color: #e5e7eb !important;
449
+ }
450
+
451
+ .btn-secondary:hover {
452
+ background-color: var(--frp-surface-hover) !important;
453
+ border-color: var(--frp-border-strong) !important;
454
+ }
455
+
456
+ .btn-danger {
457
+ background-color: var(--frp-danger) !important;
458
+ border-color: var(--frp-danger) !important;
459
+ }
460
+
461
+ .btn-success {
462
+ background-color: var(--frp-success) !important;
463
+ border-color: var(--frp-success) !important;
464
+ }
465
+
466
+ /* ============================================
467
+ FORMS & INPUTS
468
+ ============================================ */
469
+
470
+ .form-control,
471
+ .form-select,
472
+ input[type="text"],
473
+ input[type="email"],
474
+ input[type="password"],
475
+ textarea,
476
+ select {
477
+ background-color: #0d0d0f !important;
478
+ border: 1px solid var(--frp-border) !important;
479
+ color: #e5e7eb !important;
480
+ font-family: var(--frp-font-body);
481
+ border-radius: 4px;
482
+ transition: border-color 0.15s ease;
483
+ }
484
+
485
+ .form-control:focus,
486
+ .form-select:focus,
487
+ input:focus,
488
+ textarea:focus,
489
+ select:focus {
490
+ border-color: var(--frp-primary) !important;
491
+ box-shadow: 0 0 0 3px var(--frp-primary-light) !important;
492
+ outline: none;
493
+ }
494
+
495
+ .form-control::placeholder {
496
+ color: var(--frp-muted) !important;
497
+ }
498
+
499
+ /* ============================================
500
+ CARDS & PANELS
501
+ ============================================ */
502
+
503
+ .card {
504
+ background: var(--frp-surface) !important;
505
+ border: 1px solid var(--frp-border) !important;
506
+ border-radius: 4px !important;
507
+ }
508
+
509
+ .card-header {
510
+ background: var(--frp-surface-hover) !important;
511
+ border-bottom: 1px solid var(--frp-border) !important;
512
+ font-family: var(--frp-font-display);
513
+ font-weight: 600;
514
+ text-transform: uppercase;
515
+ letter-spacing: 1px;
516
+ }
517
+
518
+ .card-footer {
519
+ background: var(--frp-surface-hover) !important;
520
+ border-top: 1px solid var(--frp-border) !important;
521
+ }
522
+
523
+ /* ============================================
524
+ MODALS
525
+ ============================================ */
526
+
527
+ .modal-content {
528
+ background: var(--frp-surface) !important;
529
+ border: 1px solid var(--frp-border) !important;
530
+ }
531
+
532
+ .modal-header {
533
+ border-bottom: 1px solid var(--frp-border) !important;
534
+ }
535
+
536
+ .modal-footer {
537
+ border-top: 1px solid var(--frp-border) !important;
538
+ }
539
+
540
+ /* ============================================
541
+ PAGINATION
542
+ ============================================ */
543
+
544
+ .pagination .page-link {
545
+ background: var(--frp-surface) !important;
546
+ border-color: var(--frp-border) !important;
547
+ color: #e5e7eb !important;
548
+ }
549
+
550
+ .pagination .page-link:hover {
551
+ background: var(--frp-surface-hover) !important;
552
+ color: var(--frp-primary) !important;
553
+ }
554
+
555
+ .pagination .page-item.active .page-link {
556
+ background: var(--frp-primary) !important;
557
+ border-color: var(--frp-primary) !important;
558
+ color: #000 !important;
559
+ }
560
+
561
+ /* ============================================
562
+ BREADCRUMBS
563
+ ============================================ */
564
+
565
+ .breadcrumb {
566
+ background: transparent !important;
567
+ padding: 8px 0;
568
+ }
569
+
570
+ .breadcrumb-item a {
571
+ color: var(--frp-muted-light) !important;
572
+ }
573
+
574
+ .breadcrumb-item a:hover {
575
+ color: var(--frp-primary) !important;
576
+ }
577
+
578
+ .breadcrumb-item.active {
579
+ color: var(--frp-primary) !important;
580
+ }
581
+
582
+ .breadcrumb-item + .breadcrumb-item::before {
583
+ color: var(--frp-muted) !important;
584
+ }
585
+
586
+ /* ============================================
587
+ ALERTS & NOTIFICATIONS
588
+ ============================================ */
589
+
590
+ .alert-success {
591
+ background: var(--frp-success-light) !important;
592
+ border-color: var(--frp-success) !important;
593
+ color: var(--frp-success) !important;
594
+ }
595
+
596
+ .alert-danger {
597
+ background: var(--frp-danger-light) !important;
598
+ border-color: var(--frp-danger) !important;
599
+ color: var(--frp-danger) !important;
600
+ }
601
+
602
+ .alert-warning {
603
+ background: var(--frp-warning-light) !important;
604
+ border-color: var(--frp-warning) !important;
605
+ color: var(--frp-warning) !important;
606
+ }
607
+
608
+ .alert-info {
609
+ background: var(--frp-info-light) !important;
610
+ border-color: var(--frp-info) !important;
611
+ color: var(--frp-info) !important;
612
+ }
613
+
614
+ /* ============================================
615
+ BADGES & LABELS
616
+ ============================================ */
617
+
618
+ .badge {
619
+ font-family: var(--frp-font-display);
620
+ font-weight: 600;
621
+ text-transform: uppercase;
622
+ letter-spacing: 0.5px;
623
+ }
624
+
625
+ .badge.badge-primary,
626
+ .badge.bg-primary {
627
+ background: var(--frp-primary) !important;
628
+ color: #000 !important;
629
+ }
630
+
631
+ /* Faction badges */
632
+ .badge-faction-lspd { background: var(--frp-faction-lspd) !important; }
633
+ .badge-faction-fbi { background: var(--frp-faction-fbi) !important; }
634
+ .badge-faction-sasd { background: var(--frp-faction-sasd) !important; }
635
+ .badge-faction-ares { background: var(--frp-faction-ares) !important; }
636
+ .badge-faction-sanews { background: var(--frp-faction-sanews) !important; }
637
+ .badge-faction-gov { background: var(--frp-faction-gov) !important; }
638
+ .badge-faction-hitman { background: var(--frp-faction-hitman) !important; }
639
+ .badge-faction-medic { background: var(--frp-faction-medic) !important; }
640
+ .badge-faction-ng { background: var(--frp-faction-ng) !important; }
641
+
642
+ /* Gang badges */
643
+ .badge-gang-ghouls { background: var(--frp-gang-ghouls) !important; }
644
+ .badge-gang-velvet { background: var(--frp-gang-velvet) !important; }
645
+ .badge-gang-baba { background: var(--frp-gang-baba) !important; }
646
+ .badge-gang-rifa { background: var(--frp-gang-rifa) !important; }
647
+ .badge-gang-grove { background: var(--frp-gang-grove) !important; }
648
+ .badge-gang-lcn { background: var(--frp-gang-lcn) !important; }
649
+
650
+ /* VIP badges */
651
+ .badge-vip-daisy {
652
+ background: linear-gradient(135deg, #A3E635, #65A30D) !important;
653
+ color: #000 !important;
654
+ }
655
+
656
+ .badge-vip-rose {
657
+ background: linear-gradient(135deg, #F59E0B, #D97706) !important;
658
+ color: #000 !important;
659
+ }
660
+
661
+ .badge-vip-ivy {
662
+ background: linear-gradient(135deg, #EF4444, #DC2626) !important;
663
+ color: #fff !important;
664
+ animation: ivyBadgeGlow 2s ease-in-out infinite alternate;
665
+ }
666
+
667
+ @keyframes ivyBadgeGlow {
668
+ from { box-shadow: 0 0 4px rgba(239, 68, 68, 0.3); }
669
+ to { box-shadow: 0 0 12px rgba(245, 158, 11, 0.5); }
670
+ }
671
+
672
+ /* ============================================
673
+ TABLES
674
+ ============================================ */
675
+
676
+ .table,
677
+ table {
678
+ --bs-table-bg: var(--frp-surface);
679
+ --bs-table-border-color: var(--frp-border);
680
+ color: #e5e7eb;
681
+ }
682
+
683
+ .table thead th {
684
+ background: var(--frp-surface-hover) !important;
685
+ border-bottom: 2px solid var(--frp-primary) !important;
686
+ font-family: var(--frp-font-display);
687
+ font-weight: 600;
688
+ text-transform: uppercase;
689
+ letter-spacing: 0.5px;
690
+ color: var(--frp-primary);
691
+ font-size: 0.85rem;
692
+ }
693
+
694
+ .table tbody tr {
695
+ border-bottom: 1px solid var(--frp-border);
696
+ }
697
+
698
+ .table tbody tr:hover {
699
+ background: var(--frp-surface-hover) !important;
700
+ }
701
+
702
+ .table-striped tbody tr:nth-of-type(odd) {
703
+ background: rgba(17, 17, 20, 0.5) !important;
704
+ }
705
+
706
+ /* ============================================
707
+ FOOTER
708
+ ============================================ */
709
+
710
+ footer,
711
+ [component="footer"] {
712
+ background: #0a0a0b !important;
713
+ border-top: 1px solid var(--frp-border) !important;
714
+ color: var(--frp-muted);
715
+ }
716
+
717
+ footer a {
718
+ color: var(--frp-muted-light) !important;
719
+ }
720
+
721
+ footer a:hover {
722
+ color: var(--frp-primary) !important;
723
+ }
724
+
725
+ /* ============================================
726
+ COMPOSER (Post Editor)
727
+ ============================================ */
728
+
729
+ .composer {
730
+ background: var(--frp-surface) !important;
731
+ border: 1px solid var(--frp-border) !important;
732
+ }
733
+
734
+ .composer .title-container input {
735
+ background: #0d0d0f !important;
736
+ border: 1px solid var(--frp-border) !important;
737
+ color: #e5e7eb !important;
738
+ }
739
+
740
+ .composer .write-container textarea,
741
+ .composer .preview-container {
742
+ background: #0d0d0f !important;
743
+ color: #e5e7eb !important;
744
+ }
745
+
746
+ .composer .formatting-bar {
747
+ background: var(--frp-surface-hover) !important;
748
+ border-bottom: 1px solid var(--frp-border) !important;
749
+ }
750
+
751
+ .composer .formatting-bar .btn {
752
+ color: var(--frp-muted-light) !important;
753
+ }
754
+
755
+ .composer .formatting-bar .btn:hover {
756
+ color: var(--frp-primary) !important;
757
+ }
758
+
759
+ /* ============================================
760
+ CHAT
761
+ ============================================ */
762
+
763
+ [component="chat"] {
764
+ background: var(--frp-surface) !important;
765
+ }
766
+
767
+ [component="chat/message"] {
768
+ border-bottom: 1px solid var(--frp-border);
769
+ }
770
+
771
+ /* ============================================
772
+ SEARCH
773
+ ============================================ */
774
+
775
+ .search-results .search-result {
776
+ background: var(--frp-surface) !important;
777
+ border: 1px solid var(--frp-border) !important;
778
+ border-radius: 4px;
779
+ margin-bottom: 8px;
780
+ }
781
+
782
+ .search-results .search-result:hover {
783
+ border-color: var(--frp-primary) !important;
784
+ }
785
+
786
+ /* ============================================
787
+ ADMIN CONTROL PANEL (ACP) — Minimal overrides
788
+ ============================================ */
789
+
790
+ .acp-page {
791
+ background: #0a0a0b;
792
+ }
793
+
794
+ /* ============================================
795
+ LOADING / SPINNER
796
+ ============================================ */
797
+
798
+ .loading-indicator {
799
+ border-color: var(--frp-primary) transparent transparent transparent !important;
800
+ }
801
+
802
+ /* ============================================
803
+ TOOLTIPS & POPOVERS
804
+ ============================================ */
805
+
806
+ .tooltip-inner {
807
+ background: var(--frp-surface-elevated) !important;
808
+ border: 1px solid var(--frp-border);
809
+ color: #e5e7eb;
810
+ }
811
+
812
+ .popover {
813
+ background: var(--frp-surface) !important;
814
+ border: 1px solid var(--frp-border) !important;
815
+ }
816
+
817
+ /* ============================================
818
+ CUSTOM: SERVER STATUS WIDGET
819
+ ============================================ */
820
+
821
+ .frp-server-status {
822
+ background: var(--frp-surface) !important;
823
+ border: 1px solid var(--frp-border) !important;
824
+ border-radius: 4px;
825
+ }
826
+
827
+ .frp-server-status .status-online {
828
+ color: var(--frp-success);
829
+ }
830
+
831
+ .frp-server-status .status-offline {
832
+ color: var(--frp-danger);
833
+ }
834
+
835
+ @keyframes pulse {
836
+ 0%, 100% { opacity: 1; }
837
+ 50% { opacity: 0.5; }
838
+ }
839
+
840
+ /* ============================================
841
+ CUSTOM: GAME STATS PROFILE CARD
842
+ ============================================ */
843
+
844
+ .frp-game-stats {
845
+ background: var(--frp-surface) !important;
846
+ border: 1px solid var(--frp-border) !important;
847
+ border-radius: 4px;
848
+ }
849
+
850
+ .frp-game-stats .card-header {
851
+ font-family: var(--frp-font-display);
852
+ color: var(--frp-primary);
853
+ text-transform: uppercase;
854
+ letter-spacing: 1px;
855
+ }
856
+
857
+ .frp-game-stats .stat-item {
858
+ padding: 8px 0;
859
+ border-bottom: 1px solid var(--frp-border);
860
+ }
861
+
862
+ .frp-game-stats .stat-item:last-child {
863
+ border-bottom: none;
864
+ }
865
+
866
+ .frp-game-stats .stat-label {
867
+ color: var(--frp-muted);
868
+ font-size: 0.8rem;
869
+ text-transform: uppercase;
870
+ letter-spacing: 0.5px;
871
+ display: block;
872
+ }
873
+
874
+ .frp-game-stats .stat-value {
875
+ color: #e5e7eb;
876
+ font-family: var(--frp-font-mono);
877
+ font-size: 1rem;
878
+ font-weight: 500;
879
+ }
880
+
881
+ /* ============================================
882
+ CUSTOM: DONATION STORE
883
+ ============================================ */
884
+
885
+ .frp-store-item {
886
+ background: var(--frp-surface);
887
+ border: 1px solid var(--frp-border);
888
+ border-radius: 4px;
889
+ padding: 20px;
890
+ transition: all 0.2s ease;
891
+ position: relative;
892
+ overflow: hidden;
893
+ }
894
+
895
+ .frp-store-item:hover {
896
+ border-color: var(--frp-primary);
897
+ box-shadow: var(--frp-primary-glow);
898
+ transform: translateY(-2px);
899
+ }
900
+
901
+ .frp-store-item.tier-daisy {
902
+ border-top: 3px solid #A3E635;
903
+ }
904
+
905
+ .frp-store-item.tier-rose {
906
+ border-top: 3px solid #F59E0B;
907
+ }
908
+
909
+ .frp-store-item.tier-ivy {
910
+ border-top: 3px solid #EF4444;
911
+ }
912
+
913
+ .frp-store-item .price {
914
+ font-family: var(--frp-font-display);
915
+ font-size: 1.5rem;
916
+ font-weight: 700;
917
+ color: var(--frp-primary);
918
+ }
919
+
920
+ .frp-store-item .price .currency {
921
+ font-size: 0.9rem;
922
+ color: var(--frp-muted);
923
+ }
924
+
925
+ /* ============================================
926
+ CUSTOM: RECENT THREADS WIDGET
927
+ ============================================ */
928
+
929
+ .frp-latest-widget {
930
+ background: var(--frp-surface);
931
+ border: 1px solid var(--frp-border);
932
+ border-radius: 4px;
933
+ padding: 16px;
934
+ }
935
+
936
+ .frp-latest-widget h4 {
937
+ font-family: var(--frp-font-display);
938
+ color: var(--frp-primary);
939
+ text-transform: uppercase;
940
+ letter-spacing: 1px;
941
+ border-bottom: 2px solid var(--frp-primary);
942
+ padding-bottom: 8px;
943
+ margin-bottom: 12px;
944
+ font-size: 0.95rem;
945
+ }
946
+
947
+ .frp-latest-widget .topic-item {
948
+ padding: 8px 0;
949
+ border-bottom: 1px solid var(--frp-border);
950
+ }
951
+
952
+ .frp-latest-widget .topic-item:last-child {
953
+ border-bottom: none;
954
+ }
955
+
956
+ .frp-latest-widget .topic-item a {
957
+ color: #e5e7eb;
958
+ font-size: 0.9rem;
959
+ }
960
+
961
+ .frp-latest-widget .topic-item a:hover {
962
+ color: var(--frp-primary);
963
+ }
964
+
965
+ .frp-latest-widget .topic-meta {
966
+ font-size: 0.75rem;
967
+ color: var(--frp-muted);
968
+ margin-top: 2px;
969
+ }
970
+
971
+ /* ============================================
972
+ RESPONSIVE ADJUSTMENTS
973
+ ============================================ */
974
+
975
+ @media (max-width: 768px) {
976
+ .navbar .navbar-brand {
977
+ font-size: 1rem;
978
+ letter-spacing: 1px;
979
+ }
980
+
981
+ [component="categories/category"] {
982
+ border-left-width: 2px !important;
983
+ }
984
+
985
+ .frp-store-item {
986
+ padding: 12px;
987
+ }
988
+
989
+ .frp-game-stats .row {
990
+ flex-direction: column;
991
+ }
992
+ }
993
+
994
+ @media (max-width: 480px) {
995
+ h1, h2 {
996
+ font-size: 1.2rem;
997
+ }
998
+
999
+ .frp-store-item .price {
1000
+ font-size: 1.2rem;
1001
+ }
1002
+ }
1003
+
1004
+ /* ============================================
1005
+ UTILITY CLASSES
1006
+ ============================================ */
1007
+
1008
+ .text-gold { color: var(--frp-primary) !important; }
1009
+ .text-danger-frp { color: var(--frp-danger) !important; }
1010
+ .text-success-frp { color: var(--frp-success) !important; }
1011
+ .text-info-frp { color: var(--frp-info) !important; }
1012
+ .text-muted-frp { color: var(--frp-muted) !important; }
1013
+
1014
+ .bg-surface { background: var(--frp-surface) !important; }
1015
+ .bg-surface-hover { background: var(--frp-surface-hover) !important; }
1016
+
1017
+ .border-gold { border-color: var(--frp-primary) !important; }
1018
+ .border-frp { border-color: var(--frp-border) !important; }
1019
+
1020
+ .glow-gold { box-shadow: var(--frp-primary-glow); }
1021
+
1022
+ .font-display { font-family: var(--frp-font-display) !important; }
1023
+ .font-body { font-family: var(--frp-font-body) !important; }
1024
+ .font-mono { font-family: var(--frp-font-mono) !important; }
@@ -0,0 +1,86 @@
1
+ <!-- Flawless Roleplay — Categories Template with Recent Threads -->
2
+ <div class="categories-page" data-widget-area="header">
3
+ {{{ each widgets.header }}}
4
+ {{widgets.header.html}}
5
+ {{{ end }}}
6
+ </div>
7
+
8
+ <!-- IMPORT partials/breadcrumbs.tpl -->
9
+
10
+ <div class="row">
11
+ <div class="col-lg-9 col-md-8" data-widget-area="main">
12
+ {{{ each categories }}}
13
+ {{{ if !categories.isSection }}}
14
+ <div class="category-item" data-cid="{categories.cid}" style="background: var(--frp-surface); border: 1px solid var(--frp-border); border-left: 3px solid {categories.bgColor}; border-radius: 4px; margin-bottom: 8px; padding: 16px; transition: all 0.2s ease;">
15
+ <div class="d-flex align-items-start">
16
+ <div class="category-icon me-3" style="font-size: 1.5rem; color: {categories.bgColor}; min-width: 40px; text-align: center;">
17
+ <i class="fa {categories.icon}"></i>
18
+ </div>
19
+ <div class="flex-grow-1">
20
+ <div class="d-flex justify-content-between align-items-start">
21
+ <div>
22
+ <h3 style="margin: 0 0 4px 0; font-family: 'Barlow Condensed', sans-serif; font-size: 1.1rem;">
23
+ <a href="{config.relative_path}/category/{categories.slug}" style="color: #f3f4f6; text-decoration: none;">{categories.name}</a>
24
+ </h3>
25
+ {{{ if categories.description }}}
26
+ <p style="color: #9CA3AF; font-size: 0.85rem; margin: 0 0 8px 0;">{categories.description}</p>
27
+ {{{ end }}}
28
+ </div>
29
+ <div class="category-stats text-end" style="min-width: 120px;">
30
+ <div style="font-family: 'JetBrains Mono', monospace; font-size: 0.8rem; color: #6B7280;">
31
+ <span style="color: #F59E0B;">{categories.topic_count}</span> threads
32
+ </div>
33
+ <div style="font-family: 'JetBrains Mono', monospace; font-size: 0.8rem; color: #6B7280;">
34
+ <span style="color: #F59E0B;">{categories.post_count}</span> posts
35
+ </div>
36
+ </div>
37
+ </div>
38
+ <!-- Recent Topic Teaser -->
39
+ {{{ if categories.teaser }}}
40
+ <div class="recent-topic d-flex align-items-center mt-2 pt-2" style="border-top: 1px solid var(--frp-border);">
41
+ <a href="{config.relative_path}/user/{categories.teaser.user.userslug}">
42
+ <img src="{categories.teaser.user.picture}" class="avatar-sm rounded-circle me-2" style="width: 24px; height: 24px; border: 1px solid var(--frp-border);" alt="{categories.teaser.user.username}" />
43
+ </a>
44
+ <div style="overflow: hidden;">
45
+ <a href="{config.relative_path}/topic/{categories.teaser.topic.slug}" style="color: #d1d5db; font-size: 0.85rem; text-decoration: none; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: block;">{categories.teaser.topic.title}</a>
46
+ <span style="font-size: 0.75rem; color: #6B7280;">
47
+ by <a href="{config.relative_path}/user/{categories.teaser.user.userslug}" style="color: #9CA3AF;">{categories.teaser.user.username}</a>
48
+ &middot; <span class="timeago" title="{categories.teaser.timestampISO}"></span>
49
+ </span>
50
+ </div>
51
+ </div>
52
+ {{{ end }}}
53
+ <!-- Subcategories -->
54
+ {{{ if categories.children.length }}}
55
+ <div class="subcategories mt-2 pt-2" style="border-top: 1px solid var(--frp-border);">
56
+ {{{ each categories.children }}}
57
+ <a href="{config.relative_path}/category/{categories.children.slug}" class="badge me-1 mb-1" style="background: rgba(245, 158, 11, 0.1); color: #F59E0B; border: 1px solid rgba(245, 158, 11, 0.2); font-size: 0.75rem; font-weight: 500; text-decoration: none;">
58
+ <i class="fa {categories.children.icon} me-1"></i>{categories.children.name}
59
+ </a>
60
+ {{{ end }}}
61
+ </div>
62
+ {{{ end }}}
63
+ </div>
64
+ </div>
65
+ </div>
66
+ {{{ else }}}
67
+ <!-- Section Header -->
68
+ <div class="section-header" style="font-family: 'Barlow Condensed', sans-serif; font-weight: 700; text-transform: uppercase; letter-spacing: 2px; color: #F59E0B; border-bottom: 2px solid #F59E0B; padding: 12px 0 8px 0; margin: 24px 0 12px 0; font-size: 1.1rem;">
69
+ <i class="fa {categories.icon} me-2"></i>{categories.name}
70
+ </div>
71
+ {{{ end }}}
72
+ {{{ end }}}
73
+ </div>
74
+
75
+ <div class="col-lg-3 col-md-4" data-widget-area="sidebar">
76
+ {{{ each widgets.sidebar }}}
77
+ {{widgets.sidebar.html}}
78
+ {{{ end }}}
79
+ </div>
80
+ </div>
81
+
82
+ <div data-widget-area="footer">
83
+ {{{ each widgets.footer }}}
84
+ {{widgets.footer.html}}
85
+ {{{ end }}}
86
+ </div>
@@ -0,0 +1,106 @@
1
+ <!-- Flawless Roleplay — Custom Header Partial -->
2
+ <nav class="navbar navbar-expand-lg" style="background: #111114 !important; border-bottom: 1px solid #1e1e24; box-shadow: 0 1px 3px rgba(0,0,0,0.5);">
3
+ <div class="container">
4
+ <a class="navbar-brand" href="{config.relative_path}/" style="font-family: 'Barlow Condensed', sans-serif; font-weight: 700; color: #F59E0B !important; text-transform: uppercase; letter-spacing: 2px; font-size: 1.3rem;">
5
+ {{{ if config.brand:logo }}}
6
+ <img src="{config.brand:logo}" alt="Flawless RP" style="height: 32px; margin-right: 8px;" />
7
+ {{{ end }}}
8
+ FLAWLESS ROLEPLAY
9
+ </a>
10
+
11
+ <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" style="border-color: #1e1e24;">
12
+ <span class="navbar-toggler-icon" style="filter: invert(1);"></span>
13
+ </button>
14
+
15
+ <div class="collapse navbar-collapse" id="navbarNav">
16
+ <ul class="navbar-nav me-auto">
17
+ <li class="nav-item">
18
+ <a class="nav-link" href="{config.relative_path}/" style="color: #9CA3AF; font-weight: 500;">
19
+ <i class="fa fa-home me-1"></i> Forums
20
+ </a>
21
+ </li>
22
+ <li class="nav-item">
23
+ <a class="nav-link" href="{config.relative_path}/recent" style="color: #9CA3AF; font-weight: 500;">
24
+ <i class="fa fa-clock-o me-1"></i> Recent
25
+ </a>
26
+ </li>
27
+ <li class="nav-item">
28
+ <a class="nav-link" href="{config.relative_path}/store" style="color: #F59E0B; font-weight: 600;">
29
+ <i class="fa fa-shopping-cart me-1"></i> Store
30
+ </a>
31
+ </li>
32
+ <li class="nav-item">
33
+ <a class="nav-link" href="{config.relative_path}/rules" style="color: #9CA3AF; font-weight: 500;">
34
+ <i class="fa fa-gavel me-1"></i> Rules
35
+ </a>
36
+ </li>
37
+ <li class="nav-item">
38
+ <a class="nav-link" href="{config.relative_path}/connect" style="color: #9CA3AF; font-weight: 500;">
39
+ <i class="fa fa-gamepad me-1"></i> Connect
40
+ </a>
41
+ </li>
42
+ </ul>
43
+
44
+ <ul class="navbar-nav">
45
+ <!-- Search -->
46
+ <li class="nav-item">
47
+ <a class="nav-link" href="{config.relative_path}/search" style="color: #9CA3AF;">
48
+ <i class="fa fa-search"></i>
49
+ </a>
50
+ </li>
51
+
52
+ {{{ if config.loggedIn }}}
53
+ <!-- Notifications -->
54
+ <li class="nav-item">
55
+ <a class="nav-link position-relative" href="{config.relative_path}/notifications" style="color: #9CA3AF;">
56
+ <i class="fa fa-bell"></i>
57
+ <span component="notifications/icon" class="position-absolute top-0 start-100 translate-middle badge rounded-pill" style="background: #EF4444; font-size: 0.6rem; display: none;">
58
+ <span component="notifications/count"></span>
59
+ </span>
60
+ </a>
61
+ </li>
62
+
63
+ <!-- Chat -->
64
+ <li class="nav-item">
65
+ <a class="nav-link position-relative" href="{config.relative_path}/chats" style="color: #9CA3AF;">
66
+ <i class="fa fa-comments"></i>
67
+ <span component="chat/icon" class="position-absolute top-0 start-100 translate-middle badge rounded-pill" style="background: #F59E0B; font-size: 0.6rem; display: none;">
68
+ <span component="chat/count"></span>
69
+ </span>
70
+ </a>
71
+ </li>
72
+
73
+ <!-- User Menu -->
74
+ <li class="nav-item dropdown">
75
+ <a class="nav-link dropdown-toggle d-flex align-items-center" href="#" role="button" data-bs-toggle="dropdown" style="color: #e5e7eb;">
76
+ <img component="user/picture" src="{user.picture}" class="rounded-circle me-1" style="width: 28px; height: 28px; border: 1px solid #1e1e24;" alt="{user.username}" />
77
+ <span class="d-none d-md-inline">{user.username}</span>
78
+ </a>
79
+ <ul class="dropdown-menu dropdown-menu-end" style="background: #111114; border: 1px solid #1e1e24;">
80
+ <li><a class="dropdown-item" href="{config.relative_path}/user/{user.userslug}" style="color: #e5e7eb;"><i class="fa fa-user me-2"></i> Profile</a></li>
81
+ <li><a class="dropdown-item" href="{config.relative_path}/user/{user.userslug}/settings" style="color: #e5e7eb;"><i class="fa fa-cog me-2"></i> Settings</a></li>
82
+ {{{ if isAdmin }}}
83
+ <li><hr class="dropdown-divider" style="border-color: #1e1e24;"></li>
84
+ <li><a class="dropdown-item" href="{config.relative_path}/admin" style="color: #EF4444;"><i class="fa fa-shield me-2"></i> Admin Panel</a></li>
85
+ {{{ end }}}
86
+ <li><hr class="dropdown-divider" style="border-color: #1e1e24;"></li>
87
+ <li><a class="dropdown-item" component="user/logout" href="#" style="color: #EF4444;"><i class="fa fa-sign-out me-2"></i> Logout</a></li>
88
+ </ul>
89
+ </li>
90
+ {{{ else }}}
91
+ <!-- Login / Register -->
92
+ <li class="nav-item">
93
+ <a class="nav-link" href="{config.relative_path}/login" style="color: #9CA3AF;">
94
+ <i class="fa fa-sign-in me-1"></i> Login
95
+ </a>
96
+ </li>
97
+ <li class="nav-item">
98
+ <a class="btn btn-sm ms-2" href="{config.relative_path}/register" style="background: #F59E0B; color: #000; font-family: 'Barlow Condensed', sans-serif; font-weight: 600; text-transform: uppercase; letter-spacing: 1px;">
99
+ Register
100
+ </a>
101
+ </li>
102
+ {{{ end }}}
103
+ </ul>
104
+ </div>
105
+ </div>
106
+ </nav>