From daa6ec8b1e8320153cab27c8a2ac77e5035b0a38 Mon Sep 17 00:00:00 2001 From: Cametendo Date: Wed, 13 May 2026 16:06:27 +0200 Subject: [PATCH] Merge feature/marketplace into main --- .gitignore | 4 +- app/Config/Routes.php | 3 + app/Controllers/ThemeStore.php | 127 +++ .../Seeds/MarketplaceThemesSeeder.php | 298 ++++++- app/Views/theme_store.php | 767 ++++++++++++++++++ env.example | 12 +- public/themes/arctic-frost.css | 16 + public/themes/forest-grove.css | 16 + public/themes/midnight-void.css | 16 + public/themes/obsidian-rose.css | 16 + public/themes/ocean-breeze.css | 16 + public/themes/sunset-ember.css | 16 + public/todo-preview | 1 + writable/.htaccess | 0 writable/cache/index.html | 0 writable/debugbar/index.html | 0 writable/index.html | 0 writable/logs/index.html | 0 writable/session/index.html | 0 writable/uploads/index.html | 0 20 files changed, 1283 insertions(+), 25 deletions(-) create mode 100644 app/Controllers/ThemeStore.php create mode 100644 app/Views/theme_store.php create mode 100644 public/themes/arctic-frost.css create mode 100644 public/themes/forest-grove.css create mode 100644 public/themes/midnight-void.css create mode 100644 public/themes/obsidian-rose.css create mode 100644 public/themes/ocean-breeze.css create mode 100644 public/themes/sunset-ember.css create mode 120000 public/todo-preview mode change 100644 => 100755 writable/.htaccess mode change 100644 => 100755 writable/cache/index.html mode change 100644 => 100755 writable/debugbar/index.html mode change 100644 => 100755 writable/index.html mode change 100644 => 100755 writable/logs/index.html mode change 100644 => 100755 writable/session/index.html mode change 100644 => 100755 writable/uploads/index.html diff --git a/.gitignore b/.gitignore index 035d487..4dee025 100644 --- a/.gitignore +++ b/.gitignore @@ -125,4 +125,6 @@ _modules/* /results/ /phpunit*.xml .env -env \ No newline at end of file +env +.claude/ +.claude/* \ No newline at end of file diff --git a/app/Config/Routes.php b/app/Config/Routes.php index 6a9c6e0..d0143f2 100644 --- a/app/Config/Routes.php +++ b/app/Config/Routes.php @@ -6,6 +6,9 @@ use CodeIgniter\Router\RouteCollection; * @var RouteCollection $routes */ $routes->get('/', 'Home::index'); +$routes->get('/themes', 'ThemeStore::index'); +$routes->post('/themes/upload', 'ThemeStore::upload'); +$routes->get('/themes/preview/(:segment)', 'ThemeStore::preview/$1'); // ============================================================================ // API Routes - Version 1.0 diff --git a/app/Controllers/ThemeStore.php b/app/Controllers/ThemeStore.php new file mode 100644 index 0000000..e30ad17 --- /dev/null +++ b/app/Controllers/ThemeStore.php @@ -0,0 +1,127 @@ +where('is_published', 1)->findAll(); + + foreach ($themes as &$theme) { + $meta = json_decode($theme['metadata'] ?? '{}', true); + $theme['colors'] = $meta['colors'] ?? []; + $theme['tags'] = $meta['tags'] ?? []; + $theme['vars'] = $meta['vars'] ?? []; + } + + return view('theme_store', [ + 'themes' => $themes, + 'flash_success' => session()->getFlashdata('success'), + 'flash_error' => session()->getFlashdata('error'), + ]); + } + + public function upload(): Response + { + $file = $this->request->getFile('theme_css'); + $displayName = trim($this->request->getPost('display_name') ?? ''); + $description = trim($this->request->getPost('description') ?? ''); + + if ($displayName === '') { + return redirect()->to('/themes')->with('error', 'Display name is required.'); + } + + if (! $file || ! $file->isValid() || $file->hasMoved()) { + return redirect()->to('/themes')->with('error', 'Please upload a valid CSS file.'); + } + + if (strtolower($file->getExtension()) !== 'css') { + return redirect()->to('/themes')->with('error', 'Only .css files are allowed.'); + } + + $slug = strtolower(preg_replace('/[^a-z0-9]+/i', '-', $displayName)); + $slug = trim($slug, '-'); + $filename = $slug . '-' . substr(bin2hex(random_bytes(3)), 0, 6) . '.css'; + + $file->move(FCPATH . 'themes', $filename, true); + + $model = new MarketplaceThemeModel(); + $model->insert([ + 'id' => $this->uuid4(), + 'name' => $slug, + 'display_name' => $displayName, + 'description' => $description ?: 'Custom community theme.', + 'author' => 'Community', + 'version' => '1.0.0', + 'thumbnail_url' => null, + 'download_url' => '/themes/' . $filename, + 'price' => 0, + 'is_published' => true, + 'metadata' => json_encode(['tags' => ['custom', 'community'], 'colors' => []]), + 'created_at' => date('Y-m-d H:i:s'), + 'updated_at' => date('Y-m-d H:i:s'), + ]); + + return redirect()->to('/themes')->with('success', '"' . esc($displayName) . '" uploaded successfully!'); + } + + public function preview(string $id): Response + { + $model = new MarketplaceThemeModel(); + $theme = $model->find($id); + + if (! $theme) { + return $this->response->setStatusCode(404)->setBody('

Theme not found.

'); + } + + $distIndex = '/home/came/Nextcloud/arch-work/Projects/Todo-App/dist/index.html'; + + if (! file_exists($distIndex)) { + return $this->response->setBody( + '' + . '

Todo app dist not found.

' + ); + } + + $todoHtml = file_get_contents($distIndex); + + // Rewrite asset paths from /assets/ to the public symlink so Apache serves them + $assetBase = rtrim(base_url('todo-preview'), '/'); + $todoHtml = str_replace('="/assets/', '="' . $assetBase . '/assets/', $todoHtml); + + // Build CSS variable overrides from the stored vars map + $meta = json_decode($theme['metadata'] ?? '{}', true); + $vars = $meta['vars'] ?? []; + + $cssVars = ":root {\n"; + foreach ($vars as $prop => $value) { + $cssVars .= " {$prop}: {$value};\n"; + } + $cssVars .= "}\n"; + + // Also inject any raw CSS from the downloaded file (for custom/uploaded themes) + $cssPath = FCPATH . ltrim($theme['download_url'], '/'); + $rawCss = file_exists($cssPath) ? file_get_contents($cssPath) : ''; + + $styleTag = ""; + + $todoHtml = str_replace('', $styleTag . "\n", $todoHtml); + + return $this->response + ->setHeader('Content-Type', 'text/html; charset=utf-8') + ->setBody($todoHtml); + } + + private function uuid4(): string + { + $data = random_bytes(16); + $data[6] = chr(ord($data[6]) & 0x0f | 0x40); + $data[8] = chr(ord($data[8]) & 0x3f | 0x80); + return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4)); + } +} diff --git a/app/Database/Seeds/MarketplaceThemesSeeder.php b/app/Database/Seeds/MarketplaceThemesSeeder.php index 9d26bc3..5933fdb 100644 --- a/app/Database/Seeds/MarketplaceThemesSeeder.php +++ b/app/Database/Seeds/MarketplaceThemesSeeder.php @@ -8,34 +8,296 @@ class MarketplaceThemesSeeder extends Seeder { public function run() { + $this->db->query('SET FOREIGN_KEY_CHECKS=0'); + $this->db->table('marketplace_themes')->truncate(); + $this->db->query('SET FOREIGN_KEY_CHECKS=1'); + $data = [ [ - 'id' => '550e8400-e29b-41d4-a716-446655440010', - 'name' => 'default-light', - 'display_name' => 'Default Light', - 'description' => 'Clean and simple light theme', - 'author' => 'System', - 'version' => '1.0.0', + 'id' => '550e8400-e29b-41d4-a716-446655440010', + 'name' => 'ocean-breeze', + 'display_name' => 'Ocean Breeze', + 'description' => 'A refreshing light theme inspired by the open sea. Soft teals and ocean blues create a calm, productive workspace that\'s easy on the eyes during long work sessions.', + 'author' => 'ThemeForge', + 'version' => '1.2.0', 'thumbnail_url' => null, - 'download_url' => '/themes/default-light.zip', - 'price' => 0, + 'download_url' => '/themes/ocean-breeze.css', + 'price' => 0, 'is_published' => true, - 'metadata' => json_encode(['tags' => ['light', 'clean']]), + 'metadata' => json_encode([ + 'tags' => ['light', 'blue', 'calm', 'minimal'], + 'colors' => [ + 'Primary' => '#0077B6', + 'Secondary' => '#00B4D8', + 'Background' => '#E0F4FF', + 'Surface' => '#FFFFFF', + 'Text' => '#1A2B3C', + 'Accent' => '#48CAE4', + ], + 'vars' => [ + '--bg' => '#E0F4FF', + '--surface' => '#FFFFFF', + '--surface-strong' => '#FFFFFF', + '--surface-muted' => '#F0F9FF', + '--border' => '#BAE0F2', + '--line' => '#90C8E0', + '--text' => '#1A2B3C', + '--text-muted' => '#4A6B7A', + '--text-strong' => '#0D1B26', + '--accent' => '#0077B6', + '--accent-text' => '#FFFFFF', + '--accent-soft' => '#CCE9F5', + '--sidebar-bg' => '#FFFFFF', + '--sidebar-border' => '#BAE0F2', + '--sidebar-text' => '#1A2B3C', + '--sidebar-text-muted' => '#4A6B7A', + '--input-bg' => '#FFFFFF', + '--input-border' => '#BAE0F2', + '--modal-bg' => '#FFFFFF', + '--chip' => '#C8E8F0', + '--success' => '#D4F0E4', + ], + ]), 'created_at' => date('Y-m-d H:i:s'), 'updated_at' => date('Y-m-d H:i:s'), ], [ - 'id' => '550e8400-e29b-41d4-a716-446655440011', - 'name' => 'default-dark', - 'display_name' => 'Default Dark', - 'description' => 'Dark theme for night owls', - 'author' => 'System', - 'version' => '1.0.0', + 'id' => '550e8400-e29b-41d4-a716-446655440011', + 'name' => 'midnight-void', + 'display_name' => 'Midnight Void', + 'description' => 'Deep space dark theme for night owls and late-night coders. Rich dark purples and blues with vibrant neon accents give this theme a premium, modern feel.', + 'author' => 'ThemeForge', + 'version' => '2.0.1', 'thumbnail_url' => null, - 'download_url' => '/themes/default-dark.zip', - 'price' => 0, + 'download_url' => '/themes/midnight-void.css', + 'price' => 0, 'is_published' => true, - 'metadata' => json_encode(['tags' => ['dark', 'night']]), + 'metadata' => json_encode([ + 'tags' => ['dark', 'purple', 'neon', 'night'], + 'colors' => [ + 'Primary' => '#7C3AED', + 'Secondary' => '#A78BFA', + 'Background' => '#0D0D1A', + 'Surface' => '#1A1A2E', + 'Text' => '#E2E8F0', + 'Accent' => '#F472B6', + ], + 'vars' => [ + '--bg' => '#0D0D1A', + '--surface' => '#1A1A2E', + '--surface-strong' => '#222234', + '--surface-muted' => '#121220', + '--border' => '#2A2A44', + '--line' => '#333350', + '--text' => '#E2E8F0', + '--text-muted' => '#94A3B8', + '--text-strong' => '#F1F5F9', + '--accent' => '#7C3AED', + '--accent-text' => '#FFFFFF', + '--accent-soft' => '#2D1A5E', + '--sidebar-bg' => '#16162A', + '--sidebar-border' => '#2A2A44', + '--sidebar-text' => '#E2E8F0', + '--sidebar-text-muted' => '#94A3B8', + '--input-bg' => '#0D0D1A', + '--input-border' => '#2A2A44', + '--modal-bg' => '#1A1A2E', + '--chip' => '#2A2A44', + '--success' => '#0D2A1A', + ], + ]), + 'created_at' => date('Y-m-d H:i:s'), + 'updated_at' => date('Y-m-d H:i:s'), + ], + [ + 'id' => '550e8400-e29b-41d4-a716-446655440012', + 'name' => 'forest-grove', + 'display_name' => 'Forest Grove', + 'description' => 'Earthy greens and warm neutrals bring the tranquility of a woodland retreat to your workspace. A grounding, nature-inspired theme designed for focused productivity.', + 'author' => 'NaturePalette', + 'version' => '1.0.5', + 'thumbnail_url' => null, + 'download_url' => '/themes/forest-grove.css', + 'price' => 0, + 'is_published' => true, + 'metadata' => json_encode([ + 'tags' => ['light', 'green', 'earthy', 'nature'], + 'colors' => [ + 'Primary' => '#2D6A4F', + 'Secondary' => '#52B788', + 'Background' => '#F0F7EE', + 'Surface' => '#FFFFFF', + 'Text' => '#1B2E22', + 'Accent' => '#B7E4C7', + ], + 'vars' => [ + '--bg' => '#F0F7EE', + '--surface' => '#FFFFFF', + '--surface-strong' => '#FFFFFF', + '--surface-muted' => '#F5FAF4', + '--border' => '#C0DACB', + '--line' => '#A0C4B0', + '--text' => '#1B2E22', + '--text-muted' => '#527A62', + '--text-strong' => '#0D1F14', + '--accent' => '#2D6A4F', + '--accent-text' => '#FFFFFF', + '--accent-soft' => '#C0E8D4', + '--sidebar-bg' => '#FFFFFF', + '--sidebar-border' => '#C0DACB', + '--sidebar-text' => '#1B2E22', + '--sidebar-text-muted' => '#527A62', + '--input-bg' => '#FFFFFF', + '--input-border' => '#C0DACB', + '--modal-bg' => '#FFFFFF', + '--chip' => '#B8E0C8', + '--success' => '#CCF0DC', + ], + ]), + 'created_at' => date('Y-m-d H:i:s'), + 'updated_at' => date('Y-m-d H:i:s'), + ], + [ + 'id' => '550e8400-e29b-41d4-a716-446655440013', + 'name' => 'sunset-ember', + 'display_name' => 'Sunset Ember', + 'description' => 'Warm oranges, deep reds, and golden highlights capture the magic of a perfect sunset. This vibrant theme adds energy and warmth to every interaction.', + 'author' => 'ChromaCraft', + 'version' => '1.1.2', + 'thumbnail_url' => null, + 'download_url' => '/themes/sunset-ember.css', + 'price' => 0, + 'is_published' => true, + 'metadata' => json_encode([ + 'tags' => ['warm', 'orange', 'vibrant', 'sunset'], + 'colors' => [ + 'Primary' => '#D62828', + 'Secondary' => '#F77F00', + 'Background' => '#FFF5E4', + 'Surface' => '#FFFFFF', + 'Text' => '#2D1B00', + 'Accent' => '#FCBF49', + ], + 'vars' => [ + '--bg' => '#FFF5E4', + '--surface' => '#FFFFFF', + '--surface-strong' => '#FFFFFF', + '--surface-muted' => '#FFF8F0', + '--border' => '#F0D0A8', + '--line' => '#E0B880', + '--text' => '#2D1B00', + '--text-muted' => '#8A6040', + '--text-strong' => '#1A0A00', + '--accent' => '#D62828', + '--accent-text' => '#FFFFFF', + '--accent-soft' => '#FFE0CC', + '--sidebar-bg' => '#FFFFFF', + '--sidebar-border' => '#F0D0A8', + '--sidebar-text' => '#2D1B00', + '--sidebar-text-muted' => '#8A6040', + '--input-bg' => '#FFFFFF', + '--input-border' => '#F0D0A8', + '--modal-bg' => '#FFFFFF', + '--chip' => '#F8D8B0', + '--success' => '#DDFADC', + ], + ]), + 'created_at' => date('Y-m-d H:i:s'), + 'updated_at' => date('Y-m-d H:i:s'), + ], + [ + 'id' => '550e8400-e29b-41d4-a716-446655440014', + 'name' => 'arctic-frost', + 'display_name' => 'Arctic Frost', + 'description' => 'Ultra-clean whites and icy blues inspired by frozen tundras. A minimalist theme that maximises clarity and focus with crisp contrast and breathable spacing.', + 'author' => 'MinimalStudio', + 'version' => '3.0.0', + 'thumbnail_url' => null, + 'download_url' => '/themes/arctic-frost.css', + 'price' => 0, + 'is_published' => true, + 'metadata' => json_encode([ + 'tags' => ['light', 'minimal', 'clean', 'ice'], + 'colors' => [ + 'Primary' => '#2176AE', + 'Secondary' => '#57C4E5', + 'Background' => '#F8FBFF', + 'Surface' => '#FFFFFF', + 'Text' => '#1C2B3A', + 'Accent' => '#A8DADC', + ], + 'vars' => [ + '--bg' => '#F8FBFF', + '--surface' => '#FFFFFF', + '--surface-strong' => '#FFFFFF', + '--surface-muted' => '#F0F5FC', + '--border' => '#C0D4E8', + '--line' => '#A0BCDA', + '--text' => '#1C2B3A', + '--text-muted' => '#4E6478', + '--text-strong' => '#0D1B2A', + '--accent' => '#2176AE', + '--accent-text' => '#FFFFFF', + '--accent-soft' => '#CCE0F0', + '--sidebar-bg' => '#FFFFFF', + '--sidebar-border' => '#C0D4E8', + '--sidebar-text' => '#1C2B3A', + '--sidebar-text-muted' => '#4E6478', + '--input-bg' => '#FFFFFF', + '--input-border' => '#C0D4E8', + '--modal-bg' => '#FFFFFF', + '--chip' => '#B8D4E8', + '--success' => '#D4F0E4', + ], + ]), + 'created_at' => date('Y-m-d H:i:s'), + 'updated_at' => date('Y-m-d H:i:s'), + ], + [ + 'id' => '550e8400-e29b-41d4-a716-446655440015', + 'name' => 'obsidian-rose', + 'display_name' => 'Obsidian Rose', + 'description' => 'A sophisticated dark theme blending deep charcoal blacks with rose gold accents. Elegant and bold, this theme is built for those who want style without sacrificing readability.', + 'author' => 'ChromaCraft', + 'version' => '1.3.0', + 'thumbnail_url' => null, + 'download_url' => '/themes/obsidian-rose.css', + 'price' => 0, + 'is_published' => true, + 'metadata' => json_encode([ + 'tags' => ['dark', 'elegant', 'rose', 'premium'], + 'colors' => [ + 'Primary' => '#C9184A', + 'Secondary' => '#FF4D6D', + 'Background' => '#0A0A0F', + 'Surface' => '#1C1C28', + 'Text' => '#F1E3E4', + 'Accent' => '#B5838D', + ], + 'vars' => [ + '--bg' => '#0A0A0F', + '--surface' => '#1C1C28', + '--surface-strong' => '#242430', + '--surface-muted' => '#14141E', + '--border' => '#2A2A38', + '--line' => '#383848', + '--text' => '#F1E3E4', + '--text-muted' => '#B5939A', + '--text-strong' => '#FAF0F1', + '--accent' => '#C9184A', + '--accent-text' => '#FFFFFF', + '--accent-soft' => '#3D0A1A', + '--sidebar-bg' => '#161620', + '--sidebar-border' => '#2A2A38', + '--sidebar-text' => '#F1E3E4', + '--sidebar-text-muted' => '#B5939A', + '--input-bg' => '#0A0A0F', + '--input-border' => '#2A2A38', + '--modal-bg' => '#1C1C28', + '--chip' => '#2A2030', + '--success' => '#0A2016', + ], + ]), 'created_at' => date('Y-m-d H:i:s'), 'updated_at' => date('Y-m-d H:i:s'), ], diff --git a/app/Views/theme_store.php b/app/Views/theme_store.php new file mode 100644 index 0000000..b953bbd --- /dev/null +++ b/app/Views/theme_store.php @@ -0,0 +1,767 @@ + + + + + + Theme Store + + + + +
+

Theme Store

+

Beautiful, ready-to-use themes for your application

+
+ free themes + +
+
+ + +
+
+
+ +
+
+
+ + +
+
+ +
+
+ +
+ + +
+ +
+
+
+ + v +
+
by
+

+
+ + + +
+
+ + ⇓ Download + + +
+
+
+ +
+
+ + + + + + + + + + + + + diff --git a/env.example b/env.example index f359ec2..b12e39c 100644 --- a/env.example +++ b/env.example @@ -30,13 +30,13 @@ # DATABASE #-------------------------------------------------------------------- -# database.default.hostname = localhost -# database.default.database = ci4 -# database.default.username = root -# database.default.password = root -# database.default.DBDriver = MySQLi +database.default.hostname = localhost +database.default.database = ci4 +database.default.username = root +database.default.password = root +database.default.DBDriver = MySQLi # database.default.DBPrefix = -# database.default.port = 3306 +database.default.port = 3306 # If you use MySQLi as tests, first update the values of Config\Database::$tests. # database.tests.hostname = localhost diff --git a/public/themes/arctic-frost.css b/public/themes/arctic-frost.css new file mode 100644 index 0000000..8ebf313 --- /dev/null +++ b/public/themes/arctic-frost.css @@ -0,0 +1,16 @@ +/* Arctic Frost Theme — MinimalStudio v3.0.0 */ +:root { + --color-primary: #2176AE; + --color-secondary: #57C4E5; + --color-background: #F8FBFF; + --color-surface: #FFFFFF; + --color-text: #1C2B3A; + --color-accent: #A8DADC; +} + +body { background-color: var(--color-background); color: var(--color-text); font-family: system-ui, sans-serif; } +a, .link { color: var(--color-primary); } +.btn-primary { background: var(--color-primary); color: #fff; border: none; border-radius: 6px; padding: 8px 18px; cursor: pointer; } +.btn-primary:hover { background: var(--color-secondary); } +.card { background: var(--color-surface); border-radius: 10px; box-shadow: 0 1px 6px rgba(33,118,174,0.08); padding: 20px; border: 1px solid #DDE8F0; } +.tag { background: var(--color-accent); color: var(--color-text); border-radius: 4px; padding: 2px 8px; font-size: 0.75rem; } diff --git a/public/themes/forest-grove.css b/public/themes/forest-grove.css new file mode 100644 index 0000000..a953d12 --- /dev/null +++ b/public/themes/forest-grove.css @@ -0,0 +1,16 @@ +/* Forest Grove Theme — NaturePalette v1.0.5 */ +:root { + --color-primary: #2D6A4F; + --color-secondary: #52B788; + --color-background: #F0F7EE; + --color-surface: #FFFFFF; + --color-text: #1B2E22; + --color-accent: #B7E4C7; +} + +body { background-color: var(--color-background); color: var(--color-text); font-family: system-ui, sans-serif; } +a, .link { color: var(--color-primary); } +.btn-primary { background: var(--color-primary); color: #fff; border: none; border-radius: 6px; padding: 8px 18px; cursor: pointer; } +.btn-primary:hover { background: var(--color-secondary); } +.card { background: var(--color-surface); border-radius: 10px; box-shadow: 0 2px 8px rgba(45,106,79,0.12); padding: 20px; } +.tag { background: var(--color-accent); color: var(--color-text); border-radius: 4px; padding: 2px 8px; font-size: 0.75rem; } diff --git a/public/themes/midnight-void.css b/public/themes/midnight-void.css new file mode 100644 index 0000000..c334f3f --- /dev/null +++ b/public/themes/midnight-void.css @@ -0,0 +1,16 @@ +/* Midnight Void Theme — ThemeForge v2.0.1 */ +:root { + --color-primary: #7C3AED; + --color-secondary: #A78BFA; + --color-background: #0D0D1A; + --color-surface: #1A1A2E; + --color-text: #E2E8F0; + --color-accent: #F472B6; +} + +body { background-color: var(--color-background); color: var(--color-text); font-family: system-ui, sans-serif; } +a, .link { color: var(--color-secondary); } +.btn-primary { background: var(--color-primary); color: #fff; border: none; border-radius: 6px; padding: 8px 18px; cursor: pointer; } +.btn-primary:hover { background: var(--color-accent); } +.card { background: var(--color-surface); border-radius: 10px; box-shadow: 0 2px 16px rgba(124,58,237,0.25); padding: 20px; } +.tag { background: var(--color-accent); color: #0D0D1A; border-radius: 4px; padding: 2px 8px; font-size: 0.75rem; } diff --git a/public/themes/obsidian-rose.css b/public/themes/obsidian-rose.css new file mode 100644 index 0000000..7bf09da --- /dev/null +++ b/public/themes/obsidian-rose.css @@ -0,0 +1,16 @@ +/* Obsidian Rose Theme — ChromaCraft v1.3.0 */ +:root { + --color-primary: #C9184A; + --color-secondary: #FF4D6D; + --color-background: #0A0A0F; + --color-surface: #1C1C28; + --color-text: #F1E3E4; + --color-accent: #B5838D; +} + +body { background-color: var(--color-background); color: var(--color-text); font-family: system-ui, sans-serif; } +a, .link { color: var(--color-secondary); } +.btn-primary { background: var(--color-primary); color: #fff; border: none; border-radius: 6px; padding: 8px 18px; cursor: pointer; } +.btn-primary:hover { background: var(--color-secondary); } +.card { background: var(--color-surface); border-radius: 10px; box-shadow: 0 2px 16px rgba(201,24,74,0.2); padding: 20px; } +.tag { background: var(--color-accent); color: #0A0A0F; border-radius: 4px; padding: 2px 8px; font-size: 0.75rem; } diff --git a/public/themes/ocean-breeze.css b/public/themes/ocean-breeze.css new file mode 100644 index 0000000..c79a9da --- /dev/null +++ b/public/themes/ocean-breeze.css @@ -0,0 +1,16 @@ +/* Ocean Breeze Theme — ThemeForge v1.2.0 */ +:root { + --color-primary: #0077B6; + --color-secondary: #00B4D8; + --color-background: #E0F4FF; + --color-surface: #FFFFFF; + --color-text: #1A2B3C; + --color-accent: #48CAE4; +} + +body { background-color: var(--color-background); color: var(--color-text); font-family: system-ui, sans-serif; } +a, .link { color: var(--color-primary); } +.btn-primary { background: var(--color-primary); color: #fff; border: none; border-radius: 6px; padding: 8px 18px; cursor: pointer; } +.btn-primary:hover { background: var(--color-secondary); } +.card { background: var(--color-surface); border-radius: 10px; box-shadow: 0 2px 8px rgba(0,119,182,0.1); padding: 20px; } +.tag { background: var(--color-accent); color: var(--color-text); border-radius: 4px; padding: 2px 8px; font-size: 0.75rem; } diff --git a/public/themes/sunset-ember.css b/public/themes/sunset-ember.css new file mode 100644 index 0000000..3a9791e --- /dev/null +++ b/public/themes/sunset-ember.css @@ -0,0 +1,16 @@ +/* Sunset Ember Theme — ChromaCraft v1.1.2 */ +:root { + --color-primary: #D62828; + --color-secondary: #F77F00; + --color-background: #FFF5E4; + --color-surface: #FFFFFF; + --color-text: #2D1B00; + --color-accent: #FCBF49; +} + +body { background-color: var(--color-background); color: var(--color-text); font-family: system-ui, sans-serif; } +a, .link { color: var(--color-primary); } +.btn-primary { background: var(--color-secondary); color: #fff; border: none; border-radius: 6px; padding: 8px 18px; cursor: pointer; } +.btn-primary:hover { background: var(--color-primary); } +.card { background: var(--color-surface); border-radius: 10px; box-shadow: 0 2px 8px rgba(214,40,40,0.1); padding: 20px; } +.tag { background: var(--color-accent); color: var(--color-text); border-radius: 4px; padding: 2px 8px; font-size: 0.75rem; } diff --git a/public/todo-preview b/public/todo-preview new file mode 120000 index 0000000..ad46dac --- /dev/null +++ b/public/todo-preview @@ -0,0 +1 @@ +/home/came/Nextcloud/arch-work/Projects/Todo-App/dist \ No newline at end of file diff --git a/writable/.htaccess b/writable/.htaccess old mode 100644 new mode 100755 diff --git a/writable/cache/index.html b/writable/cache/index.html old mode 100644 new mode 100755 diff --git a/writable/debugbar/index.html b/writable/debugbar/index.html old mode 100644 new mode 100755 diff --git a/writable/index.html b/writable/index.html old mode 100644 new mode 100755 diff --git a/writable/logs/index.html b/writable/logs/index.html old mode 100644 new mode 100755 diff --git a/writable/session/index.html b/writable/session/index.html old mode 100644 new mode 100755 diff --git a/writable/uploads/index.html b/writable/uploads/index.html old mode 100644 new mode 100755