e.stopPropagation()}>
@@ -90,57 +86,16 @@ export default function EditItemModal({ item, onSave, onCancel }) {
-
Item Classification
-
-
-
-
-
-
- {itemType && (
-
-
-
-
- )}
-
-
-
-
-
+
diff --git a/frontend/src/pages/Login.jsx b/frontend/src/pages/Login.jsx
index 7768c49..7a100bc 100644
--- a/frontend/src/pages/Login.jsx
+++ b/frontend/src/pages/Login.jsx
@@ -1,10 +1,10 @@
import { useContext, useState } from "react";
import { Link } from "react-router-dom";
import { loginRequest } from "../api/auth";
-import ErrorMessage from "../components/ErrorMessage";
-import FormInput from "../components/FormInput";
+import ErrorMessage from "../components/common/ErrorMessage";
+import FormInput from "../components/common/FormInput";
import { AuthContext } from "../context/AuthContext";
-import "../styles/Login.css";
+import "../styles/pages/Login.css";
export default function Login() {
const { login } = useContext(AuthContext);
diff --git a/frontend/src/pages/Register.jsx b/frontend/src/pages/Register.jsx
index 6f42f9e..f39d20c 100644
--- a/frontend/src/pages/Register.jsx
+++ b/frontend/src/pages/Register.jsx
@@ -2,10 +2,10 @@ import { useContext, useEffect, useState } from "react";
import { Link, useNavigate } from "react-router-dom";
import { loginRequest, registerRequest } from "../api/auth";
import { checkIfUserExists } from "../api/users";
-import ErrorMessage from "../components/ErrorMessage";
-import FormInput from "../components/FormInput";
+import ErrorMessage from "../components/common/ErrorMessage";
+import FormInput from "../components/common/FormInput";
import { AuthContext } from "../context/AuthContext";
-import "../styles/Register.css";
+import "../styles/pages/Register.css";
export default function Register() {
const navigate = useNavigate();
diff --git a/frontend/src/styles/THEME_USAGE_EXAMPLES.css b/frontend/src/styles/THEME_USAGE_EXAMPLES.css
new file mode 100644
index 0000000..16d24ea
--- /dev/null
+++ b/frontend/src/styles/THEME_USAGE_EXAMPLES.css
@@ -0,0 +1,130 @@
+/**
+ * Theme Variable Usage Examples
+ *
+ * This file demonstrates how to refactor existing CSS to use theme variables.
+ * Copy these patterns when updating component styles.
+ */
+
+/* ============================================
+ BEFORE: Hardcoded values
+ ============================================ */
+.button-old {
+ background: #007bff;
+ color: white;
+ padding: 0.6em 1.2em;
+ border-radius: 4px;
+ border: none;
+ font-size: 1em;
+ transition: 0.2s;
+}
+
+.button-old:hover {
+ background: #0056b3;
+}
+
+/* ============================================
+ AFTER: Using theme variables
+ ============================================ */
+.button-new {
+ background: var(--color-primary);
+ color: var(--color-text-inverse);
+ padding: var(--button-padding-y) var(--button-padding-x);
+ border-radius: var(--button-border-radius);
+ border: none;
+ font-size: var(--font-size-base);
+ font-weight: var(--button-font-weight);
+ transition: var(--transition-base);
+ cursor: pointer;
+}
+
+.button-new:hover {
+ background: var(--color-primary-hover);
+}
+
+/* ============================================
+ MORE EXAMPLES
+ ============================================ */
+
+/* Input Field */
+.input-field {
+ padding: var(--input-padding-y) var(--input-padding-x);
+ border: var(--border-width-thin) solid var(--input-border-color);
+ border-radius: var(--input-border-radius);
+ font-size: var(--font-size-base);
+ font-family: var(--font-family-base);
+ transition: var(--transition-base);
+}
+
+.input-field:focus {
+ outline: none;
+ border-color: var(--input-focus-border-color);
+ box-shadow: var(--input-focus-shadow);
+}
+
+/* Card Component */
+.card {
+ background: var(--card-bg);
+ padding: var(--card-padding);
+ border-radius: var(--card-border-radius);
+ box-shadow: var(--card-shadow);
+ margin-bottom: var(--spacing-md);
+}
+
+/* Modal */
+.modal-overlay {
+ background: var(--modal-backdrop-bg);
+ position: fixed;
+ inset: 0;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ z-index: var(--z-modal);
+}
+
+.modal-content {
+ background: var(--modal-bg);
+ padding: var(--modal-padding);
+ border-radius: var(--modal-border-radius);
+ max-width: var(--modal-max-width);
+ box-shadow: var(--shadow-xl);
+}
+
+/* Text Styles */
+.heading-primary {
+ font-size: var(--font-size-2xl);
+ font-weight: var(--font-weight-bold);
+ color: var(--color-text-primary);
+ margin-bottom: var(--spacing-md);
+}
+
+.text-muted {
+ color: var(--color-text-secondary);
+ font-size: var(--font-size-sm);
+}
+
+/* Spacing Examples */
+.section {
+ margin-bottom: var(--spacing-xl);
+}
+
+.field-group {
+ margin-bottom: var(--spacing-md);
+}
+
+/* Border Examples */
+.divider {
+ border-bottom: var(--border-width-thin) solid var(--color-border-light);
+ margin: var(--spacing-lg) 0;
+}
+
+/* ============================================
+ BENEFITS OF USING THEME VARIABLES
+ ============================================
+
+ 1. Consistency: All components use the same colors/spacing
+ 2. Maintainability: Change once, update everywhere
+ 3. Theme switching: Easy to implement dark mode
+ 4. Scalability: Add new colors/sizes without touching components
+ 5. Documentation: Variable names are self-documenting
+
+*/
diff --git a/frontend/src/styles/AddItemWithDetailsModal.css b/frontend/src/styles/components/AddItemWithDetailsModal.css
similarity index 100%
rename from frontend/src/styles/AddItemWithDetailsModal.css
rename to frontend/src/styles/components/AddItemWithDetailsModal.css
diff --git a/frontend/src/styles/components/ClassificationSection.css b/frontend/src/styles/components/ClassificationSection.css
new file mode 100644
index 0000000..1b06669
--- /dev/null
+++ b/frontend/src/styles/components/ClassificationSection.css
@@ -0,0 +1,44 @@
+/* Classification Section */
+.classification-section {
+ margin-bottom: 1.5rem;
+}
+
+.classification-title {
+ font-size: 1em;
+ font-weight: 600;
+ margin-bottom: 0.8rem;
+ color: #333;
+}
+
+.classification-field {
+ margin-bottom: 1rem;
+}
+
+.classification-field label {
+ display: block;
+ font-size: 0.9em;
+ font-weight: 500;
+ margin-bottom: 0.4rem;
+ color: #555;
+}
+
+.classification-select {
+ width: 100%;
+ padding: 0.6rem;
+ font-size: 1em;
+ border: 1px solid #ccc;
+ border-radius: 4px;
+ background: white;
+ cursor: pointer;
+ transition: border-color 0.2s;
+}
+
+.classification-select:focus {
+ outline: none;
+ border-color: #007bff;
+ box-shadow: 0 0 0 2px rgba(0, 123, 255, 0.1);
+}
+
+.classification-select:hover {
+ border-color: #999;
+}
diff --git a/frontend/src/styles/EditItemModal.css b/frontend/src/styles/components/EditItemModal.css
similarity index 100%
rename from frontend/src/styles/EditItemModal.css
rename to frontend/src/styles/components/EditItemModal.css
diff --git a/frontend/src/styles/components/ImageUploadSection.css b/frontend/src/styles/components/ImageUploadSection.css
new file mode 100644
index 0000000..79c1378
--- /dev/null
+++ b/frontend/src/styles/components/ImageUploadSection.css
@@ -0,0 +1,86 @@
+/* Image Upload Section */
+.image-upload-section {
+ margin-bottom: 1.5rem;
+}
+
+.image-upload-title {
+ font-size: 1em;
+ font-weight: 600;
+ margin-bottom: 0.8rem;
+ color: #333;
+}
+
+.image-upload-content {
+ border: 2px dashed #ccc;
+ border-radius: 8px;
+ padding: 1rem;
+ background: #f9f9f9;
+}
+
+.image-upload-options {
+ display: flex;
+ flex-direction: column;
+ gap: 0.8rem;
+}
+
+.image-upload-btn {
+ padding: 0.8rem 1rem;
+ font-size: 1em;
+ border: none;
+ border-radius: 6px;
+ cursor: pointer;
+ transition: all 0.2s;
+ font-weight: 500;
+}
+
+.image-upload-btn.camera {
+ background: #007bff;
+ color: white;
+}
+
+.image-upload-btn.camera:hover {
+ background: #0056b3;
+}
+
+.image-upload-btn.gallery {
+ background: #6c757d;
+ color: white;
+}
+
+.image-upload-btn.gallery:hover {
+ background: #545b62;
+}
+
+.image-upload-preview {
+ position: relative;
+ max-width: 300px;
+ margin: 0 auto;
+}
+
+.image-upload-preview img {
+ width: 100%;
+ border-radius: 8px;
+ display: block;
+}
+
+.image-upload-remove {
+ position: absolute;
+ top: 8px;
+ right: 8px;
+ background: rgba(255, 0, 0, 0.8);
+ color: white;
+ border: none;
+ border-radius: 50%;
+ width: 30px;
+ height: 30px;
+ font-size: 1.2em;
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ transition: background 0.2s;
+}
+
+.image-upload-remove:hover {
+ background: rgba(255, 0, 0, 1);
+}
diff --git a/frontend/src/styles/Navbar.css b/frontend/src/styles/components/Navbar.css
similarity index 93%
rename from frontend/src/styles/Navbar.css
rename to frontend/src/styles/components/Navbar.css
index 5bca7aa..30d23a2 100644
--- a/frontend/src/styles/Navbar.css
+++ b/frontend/src/styles/components/Navbar.css
@@ -1,58 +1,58 @@
-.navbar {
- background: #343a40;
- color: white;
- padding: 0.6em 1em;
- display: flex;
- justify-content: space-between;
- align-items: center;
- border-radius: 4px;
- margin-bottom: 1em;
-}
-
-.navbar-links a {
- color: white;
- margin-right: 1em;
- text-decoration: none;
- font-size: 1.1em;
-}
-
-.navbar-links a:hover {
- text-decoration: underline;
-}
-
-.navbar-logout {
- background: #dc3545;
- color: white;
- border: none;
- padding: 0.4em 0.8em;
- border-radius: 4px;
- cursor: pointer;
- width: 100px;
-}
-
-.navbar-idcard {
- display: flex;
- align-items: center;
- align-content: center;
- margin-right: 1em;
- padding: 0.3em 0.6em;
- background: #495057;
- border-radius: 4px;
- color: white;
-}
-
-.navbar-idinfo {
- display: flex;
- flex-direction: column;
- line-height: 1.1;
-}
-
-.navbar-username {
- font-size: 0.95em;
- font-weight: bold;
-}
-
-.navbar-role {
- font-size: 0.75em;
- opacity: 0.8;
-}
+.navbar {
+ background: #343a40;
+ color: white;
+ padding: 0.6em 1em;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ border-radius: 4px;
+ margin-bottom: 1em;
+}
+
+.navbar-links a {
+ color: white;
+ margin-right: 1em;
+ text-decoration: none;
+ font-size: 1.1em;
+}
+
+.navbar-links a:hover {
+ text-decoration: underline;
+}
+
+.navbar-logout {
+ background: #dc3545;
+ color: white;
+ border: none;
+ padding: 0.4em 0.8em;
+ border-radius: 4px;
+ cursor: pointer;
+ width: 100px;
+}
+
+.navbar-idcard {
+ display: flex;
+ align-items: center;
+ align-content: center;
+ margin-right: 1em;
+ padding: 0.3em 0.6em;
+ background: #495057;
+ border-radius: 4px;
+ color: white;
+}
+
+.navbar-idinfo {
+ display: flex;
+ flex-direction: column;
+ line-height: 1.1;
+}
+
+.navbar-username {
+ font-size: 0.95em;
+ font-weight: bold;
+}
+
+.navbar-role {
+ font-size: 0.75em;
+ opacity: 0.8;
+}
diff --git a/frontend/src/styles/GroceryList.css b/frontend/src/styles/pages/GroceryList.css
similarity index 69%
rename from frontend/src/styles/GroceryList.css
rename to frontend/src/styles/pages/GroceryList.css
index b07e1f6..e50c865 100644
--- a/frontend/src/styles/GroceryList.css
+++ b/frontend/src/styles/pages/GroceryList.css
@@ -1,304 +1,323 @@
-/* Container */
-.glist-body {
- font-family: Arial, sans-serif;
- padding: 1em;
- background: #f8f9fa;
-}
-
-.glist-container {
- max-width: 480px;
- margin: auto;
- background: white;
- padding: 1em;
- border-radius: 8px;
- box-shadow: 0 0 10px rgba(0,0,0,0.08);
-}
-
-/* Title */
-.glist-title {
- text-align: center;
- font-size: 1.5em;
- margin-bottom: 0.4em;
-}
-
-.glist-section-title {
- text-align: center;
- font-size: 1.2em;
- margin-top: 2em;
- margin-bottom: 0.5em;
- color: #495057;
- border-top: 2px solid #e0e0e0;
- padding-top: 1em;
-}
-
-/* Classification Groups */
-.glist-classification-group {
- margin-bottom: 2em;
-}
-
-.glist-classification-header {
- font-size: 1.1em;
- font-weight: 600;
- color: #007bff;
- margin: 1em 0 0.5em 0;
- padding: 0.5em 0.8em;
- background: #e7f3ff;
- border-left: 4px solid #007bff;
- border-radius: 4px;
-}
-
-/* Inputs */
-.glist-input {
- font-size: 1em;
- padding: 0.5em;
- margin: 0.3em 0;
- width: 100%;
- box-sizing: border-box;
-}
-
-/* Buttons */
-.glist-btn {
- font-size: 1em;
- padding: 0.55em;
- width: 100%;
- margin-top: 0.4em;
- cursor: pointer;
- border: none;
- background: #007bff;
- color: white;
- border-radius: 4px;
-}
-
-.glist-btn:hover {
- background: #0067d8;
-}
-
-/* Suggestion dropdown */
-.glist-suggest-box {
- background: #fff;
- border: 1px solid #ccc;
- max-height: 150px;
- overflow-y: auto;
- position: absolute;
- z-index: 999;
- border-radius: 8px;
- box-shadow: 0 0 10px rgba(0,0,0,0.08);
- padding: 1em;
- width: calc(100% - 8em);
- max-width: 440px;
- margin: 0 auto;
-}
-
-.glist-suggest-item {
- padding: 0.5em;
- padding-inline: 2em;
- cursor: pointer;
-}
-
-.glist-suggest-item:hover {
- background: #eee;
-}
-
-/* Grocery list items */
-.glist-ul {
- list-style: none;
- padding: 0;
- margin-top: 1em;
-}
-
-.glist-li {
- background: #fff;
- border: 1px solid #e0e0e0;
- border-radius: 8px;
- margin-bottom: 0.8em;
- cursor: pointer;
- transition: box-shadow 0.2s, transform 0.2s;
- overflow: hidden;
-}
-
-.glist-li:hover {
- box-shadow: 0 2px 8px rgba(0,0,0,0.1);
- transform: translateY(-2px);
-}
-
-.glist-item-layout {
- display: flex;
- gap: 1em;
- padding: 0em;
- align-items: center;
-}
-
-.glist-item-image {
- width: 50px;
- height: 50px;
- min-width: 50px;
- background: #f5f5f5;
- border: 2px solid #e0e0e0;
- border-radius: 8px;
- display: flex;
- align-items: center;
- justify-content: center;
- font-size: 2em;
- color: #ccc;
- overflow: hidden;
- position: relative;
-}
-
-.glist-item-image.has-image {
- border-color: #007bff;
- background: #fff;
-}
-
-.glist-item-image img {
- width: 100%;
- height: 100%;
- object-fit: cover;
-}
-
-.glist-item-image.has-image:hover {
- opacity: 0.8;
- box-shadow: 0 0 8px rgba(0, 123, 255, 0.3);
-}
-
-.glist-item-content {
- display: flex;
- flex-direction: column;
- gap: 0.4em;
- flex: 1;
- min-width: 0;
-}
-
-.glist-item-header {
- display: flex;
- align-items: baseline;
- gap: 0.5em;
- flex-wrap: wrap;
-}
-
-.glist-item-name {
- font-weight: 800;
- font-size: 0.8em;
- color: #333;
-}
-
-.glist-item-quantity {
- position: absolute;
- top: 0;
- right: 0;
- background: rgba(0, 123, 255, 0.9);
- color: white;
- font-weight: 700;
- font-size: 0.3em;
- padding: 0.2em 0.4em;
- border-radius: 0 6px 0 4px;
- min-width: 20%;
- text-align: center;
- box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
-}
-
-.glist-item-users {
- font-size: 0.7em;
- color: #888;
- font-style: italic;
-}
-
-/* Sorting dropdown */
-.glist-sort {
- width: 100%;
- margin: 0.3em 0;
- padding: 0.5em;
- font-size: 1em;
- border-radius: 4px;
-}
-
-/* Image upload */
-.glist-image-upload {
- margin: 0.5em 0;
-}
-
-.glist-image-label {
- display: block;
- padding: 0.6em;
- background: #f0f0f0;
- border: 2px dashed #ccc;
- border-radius: 4px;
- text-align: center;
- cursor: pointer;
- transition: all 0.2s;
-}
-
-.glist-image-label:hover {
- background: #e8e8e8;
- border-color: #007bff;
-}
-
-.glist-image-preview {
- position: relative;
- margin-top: 0.5em;
- display: inline-block;
-}
-
-.glist-image-preview img {
- max-width: 150px;
- max-height: 150px;
- border-radius: 8px;
- border: 2px solid #ddd;
-}
-
-.glist-remove-image {
- position: absolute;
- top: -8px;
- right: -8px;
- width: 28px;
- height: 28px;
- border-radius: 50%;
- background: #ff4444;
- color: white;
- border: 2px solid white;
- font-size: 1.2rem;
- line-height: 1;
- cursor: pointer;
- display: flex;
- align-items: center;
- justify-content: center;
-}
-
-.glist-remove-image:hover {
- background: #cc0000;
-}
-
-/* Floating Action Button (FAB) */
-.glist-fab {
- position: fixed;
- bottom: 20px;
- right: 20px;
- background: #28a745;
- color: white;
- border: none;
- border-radius: 50%;
- width: 62px;
- height: 62px;
- font-size: 2em;
- line-height: 0;
- display: flex;
- align-items: center;
- justify-content: center;
- box-shadow: 0 3px 10px rgba(0,0,0,0.2);
- cursor: pointer;
-}
-
-.glist-fab:hover {
- background: #218838;
-}
-
-/* Mobile tweaks */
-@media (max-width: 480px) {
- .glist-container {
- padding: 1em 0.8em;
- }
-
- .glist-fab {
- bottom: 16px;
- right: 16px;
- }
-}
+/* Container */
+.glist-body {
+ font-family: var(--font-family-base);
+ padding: var(--spacing-md);
+ background: var(--color-bg-body);
+}
+
+.glist-container {
+ max-width: var(--container-max-width);
+ margin: auto;
+ background: var(--color-bg-surface);
+ padding: var(--spacing-md);
+ border-radius: var(--border-radius-lg);
+ box-shadow: var(--shadow-card);
+}
+
+/* Title */
+.glist-title {
+ text-align: center;
+ font-size: var(--font-size-2xl);
+ margin-bottom: var(--spacing-sm);
+}
+
+.glist-section-title {
+ text-align: center;
+ font-size: var(--font-size-xl);
+ margin-top: var(--spacing-xl);
+ margin-bottom: var(--spacing-sm);
+ color: var(--color-gray-700);
+ border-top: var(--border-width-medium) solid var(--color-border-light);
+ padding-top: var(--spacing-md);
+}
+
+/* Classification Groups */
+.glist-classification-group {
+ margin-bottom: var(--spacing-xl);
+}
+
+.glist-classification-header {
+ font-size: var(--font-size-lg);
+ font-weight: var(--font-weight-semibold);
+ color: var(--color-primary);
+ margin: var(--spacing-md) 0 var(--spacing-sm) 0;
+ padding: var(--spacing-sm) var(--spacing-md);
+ background: var(--color-primary-light);
+ border-left: var(--border-width-thick) solid var(--color-primary);
+ border-radius: var(--border-radius-sm);
+}
+
+/* Inputs */
+.glist-input {
+ font-size: 1em;
+ padding: 0.5em;
+ margin: 0.3em 0;
+ width: 100%;
+ box-sizing: border-box;
+}
+
+/* Buttons */
+.glist-btn {
+ font-size: var(--font-size-base);
+ padding: var(--button-padding-y);
+ width: 100%;
+ margin-top: var(--spacing-sm);
+ cursor: pointer;
+ border: none;
+ background: var(--color-primary);
+ color: var(--color-text-inverse);
+ border-radius: var(--button-border-radius);
+ font-weight: var(--button-font-weight);
+ transition: var(--transition-base);
+}
+
+.glist-btn:hover {
+ background: var(--color-primary-dark);
+}
+
+.glist-show-more-btn {
+ font-size: var(--font-size-sm);
+ padding: var(--spacing-sm) var(--spacing-lg);
+ cursor: pointer;
+ border: var(--border-width-thin) solid var(--color-primary);
+ background: var(--color-bg-surface);
+ color: var(--color-primary);
+ border-radius: var(--button-border-radius);
+ transition: var(--transition-base);
+ font-weight: var(--button-font-weight);
+}
+
+.glist-show-more-btn:hover {
+ background: var(--color-primary);
+ color: var(--color-text-inverse);
+}
+
+/* Suggestion dropdown */
+.glist-suggest-box {
+ background: #fff;
+ border: 1px solid #ccc;
+ max-height: 150px;
+ overflow-y: auto;
+ position: absolute;
+ z-index: 999;
+ border-radius: 8px;
+ box-shadow: 0 0 10px rgba(0,0,0,0.08);
+ padding: 1em;
+ width: calc(100% - 8em);
+ max-width: 440px;
+ margin: 0 auto;
+}
+
+.glist-suggest-item {
+ padding: 0.5em;
+ padding-inline: 2em;
+ cursor: pointer;
+}
+
+.glist-suggest-item:hover {
+ background: #eee;
+}
+
+/* Grocery list items */
+.glist-ul {
+ list-style: none;
+ padding: 0;
+ margin-top: 1em;
+}
+
+.glist-li {
+ background: #fff;
+ border: 1px solid #e0e0e0;
+ border-radius: 8px;
+ margin-bottom: 0.8em;
+ cursor: pointer;
+ transition: box-shadow 0.2s, transform 0.2s;
+ overflow: hidden;
+}
+
+.glist-li:hover {
+ box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+ transform: translateY(-2px);
+}
+
+.glist-item-layout {
+ display: flex;
+ gap: 1em;
+ padding: 0em;
+ align-items: center;
+}
+
+.glist-item-image {
+ width: 50px;
+ height: 50px;
+ min-width: 50px;
+ background: #f5f5f5;
+ border: 2px solid #e0e0e0;
+ border-radius: 8px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 2em;
+ color: #ccc;
+ overflow: hidden;
+ position: relative;
+}
+
+.glist-item-image.has-image {
+ border-color: #007bff;
+ background: #fff;
+}
+
+.glist-item-image img {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+}
+
+.glist-item-image.has-image:hover {
+ opacity: 0.8;
+ box-shadow: 0 0 8px rgba(0, 123, 255, 0.3);
+}
+
+.glist-item-content {
+ display: flex;
+ flex-direction: column;
+ gap: 0.4em;
+ flex: 1;
+ min-width: 0;
+}
+
+.glist-item-header {
+ display: flex;
+ align-items: baseline;
+ gap: 0.5em;
+ flex-wrap: wrap;
+}
+
+.glist-item-name {
+ font-weight: 800;
+ font-size: 0.8em;
+ color: #333;
+}
+
+.glist-item-quantity {
+ position: absolute;
+ top: 0;
+ right: 0;
+ background: rgba(0, 123, 255, 0.9);
+ color: white;
+ font-weight: 700;
+ font-size: 0.3em;
+ padding: 0.2em 0.4em;
+ border-radius: 0 6px 0 4px;
+ min-width: 20%;
+ text-align: center;
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
+}
+
+.glist-item-users {
+ font-size: 0.7em;
+ color: #888;
+ font-style: italic;
+}
+
+/* Sorting dropdown */
+.glist-sort {
+ width: 100%;
+ margin: 0.3em 0;
+ padding: 0.5em;
+ font-size: 1em;
+ border-radius: 4px;
+}
+
+/* Image upload */
+.glist-image-upload {
+ margin: 0.5em 0;
+}
+
+.glist-image-label {
+ display: block;
+ padding: 0.6em;
+ background: #f0f0f0;
+ border: 2px dashed #ccc;
+ border-radius: 4px;
+ text-align: center;
+ cursor: pointer;
+ transition: all 0.2s;
+}
+
+.glist-image-label:hover {
+ background: #e8e8e8;
+ border-color: #007bff;
+}
+
+.glist-image-preview {
+ position: relative;
+ margin-top: 0.5em;
+ display: inline-block;
+}
+
+.glist-image-preview img {
+ max-width: 150px;
+ max-height: 150px;
+ border-radius: 8px;
+ border: 2px solid #ddd;
+}
+
+.glist-remove-image {
+ position: absolute;
+ top: -8px;
+ right: -8px;
+ width: 28px;
+ height: 28px;
+ border-radius: 50%;
+ background: #ff4444;
+ color: white;
+ border: 2px solid white;
+ font-size: 1.2rem;
+ line-height: 1;
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.glist-remove-image:hover {
+ background: #cc0000;
+}
+
+/* Floating Action Button (FAB) */
+.glist-fab {
+ position: fixed;
+ bottom: 20px;
+ right: 20px;
+ background: #28a745;
+ color: white;
+ border: none;
+ border-radius: 50%;
+ width: 62px;
+ height: 62px;
+ font-size: 2em;
+ line-height: 0;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ box-shadow: 0 3px 10px rgba(0,0,0,0.2);
+ cursor: pointer;
+}
+
+.glist-fab:hover {
+ background: #218838;
+}
+
+/* Mobile tweaks */
+@media (max-width: 480px) {
+ .glist-container {
+ padding: 1em 0.8em;
+ }
+
+ .glist-fab {
+ bottom: 16px;
+ right: 16px;
+ }
+}
diff --git a/frontend/src/styles/Login.css b/frontend/src/styles/pages/Login.css
similarity index 100%
rename from frontend/src/styles/Login.css
rename to frontend/src/styles/pages/Login.css
diff --git a/frontend/src/styles/Register.css b/frontend/src/styles/pages/Register.css
similarity index 100%
rename from frontend/src/styles/Register.css
rename to frontend/src/styles/pages/Register.css
diff --git a/frontend/src/styles/theme.css b/frontend/src/styles/theme.css
new file mode 100644
index 0000000..a8d4f5c
--- /dev/null
+++ b/frontend/src/styles/theme.css
@@ -0,0 +1,268 @@
+/**
+ * Global Theme Variables
+ *
+ * This file defines the design system for the entire application.
+ * All colors, spacing, typography, and other design tokens are centralized here.
+ *
+ * Usage: var(--variable-name)
+ * Example: color: var(--color-primary);
+ */
+
+:root {
+ /* ============================================
+ COLOR PALETTE
+ ============================================ */
+
+ /* Primary Colors */
+ --color-primary: #007bff;
+ --color-primary-hover: #0056b3;
+ --color-primary-light: #e7f3ff;
+ --color-primary-dark: #0067d8;
+
+ /* Secondary Colors */
+ --color-secondary: #6c757d;
+ --color-secondary-hover: #545b62;
+ --color-secondary-light: #f8f9fa;
+
+ /* Semantic Colors */
+ --color-success: #28a745;
+ --color-success-hover: #218838;
+ --color-success-light: #d4edda;
+
+ --color-danger: #dc3545;
+ --color-danger-hover: #c82333;
+ --color-danger-light: #f8d7da;
+
+ --color-warning: #ffc107;
+ --color-warning-hover: #e0a800;
+ --color-warning-light: #fff3cd;
+
+ --color-info: #17a2b8;
+ --color-info-hover: #138496;
+ --color-info-light: #d1ecf1;
+
+ /* Neutral Colors */
+ --color-white: #ffffff;
+ --color-black: #000000;
+ --color-gray-50: #f9f9f9;
+ --color-gray-100: #f8f9fa;
+ --color-gray-200: #e9ecef;
+ --color-gray-300: #dee2e6;
+ --color-gray-400: #ced4da;
+ --color-gray-500: #adb5bd;
+ --color-gray-600: #6c757d;
+ --color-gray-700: #495057;
+ --color-gray-800: #343a40;
+ --color-gray-900: #212529;
+
+ /* Text Colors */
+ --color-text-primary: #212529;
+ --color-text-secondary: #6c757d;
+ --color-text-muted: #adb5bd;
+ --color-text-inverse: #ffffff;
+
+ /* Background Colors */
+ --color-bg-body: #f8f9fa;
+ --color-bg-surface: #ffffff;
+ --color-bg-hover: #f5f5f5;
+ --color-bg-disabled: #e9ecef;
+
+ /* Border Colors */
+ --color-border-light: #e0e0e0;
+ --color-border-medium: #ccc;
+ --color-border-dark: #999;
+
+ /* ============================================
+ SPACING
+ ============================================ */
+ --spacing-xs: 0.25rem; /* 4px */
+ --spacing-sm: 0.5rem; /* 8px */
+ --spacing-md: 1rem; /* 16px */
+ --spacing-lg: 1.5rem; /* 24px */
+ --spacing-xl: 2rem; /* 32px */
+ --spacing-2xl: 3rem; /* 48px */
+ --spacing-3xl: 4rem; /* 64px */
+
+ /* ============================================
+ TYPOGRAPHY
+ ============================================ */
+ --font-family-base: Arial, sans-serif;
+ --font-family-heading: Arial, sans-serif;
+ --font-family-mono: 'Courier New', monospace;
+
+ /* Font Sizes */
+ --font-size-xs: 0.75rem; /* 12px */
+ --font-size-sm: 0.875rem; /* 14px */
+ --font-size-base: 1rem; /* 16px */
+ --font-size-lg: 1.125rem; /* 18px */
+ --font-size-xl: 1.25rem; /* 20px */
+ --font-size-2xl: 1.5rem; /* 24px */
+ --font-size-3xl: 2rem; /* 32px */
+
+ /* Font Weights */
+ --font-weight-normal: 400;
+ --font-weight-medium: 500;
+ --font-weight-semibold: 600;
+ --font-weight-bold: 700;
+
+ /* Line Heights */
+ --line-height-tight: 1.2;
+ --line-height-normal: 1.5;
+ --line-height-relaxed: 1.75;
+
+ /* ============================================
+ BORDERS & RADIUS
+ ============================================ */
+ --border-width-thin: 1px;
+ --border-width-medium: 2px;
+ --border-width-thick: 4px;
+
+ --border-radius-sm: 4px;
+ --border-radius-md: 6px;
+ --border-radius-lg: 8px;
+ --border-radius-xl: 12px;
+ --border-radius-full: 50%;
+
+ /* ============================================
+ SHADOWS
+ ============================================ */
+ --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
+ --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
+ --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
+ --shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1);
+ --shadow-card: 0 0 10px rgba(0, 0, 0, 0.08);
+
+ /* ============================================
+ TRANSITIONS
+ ============================================ */
+ --transition-fast: 0.15s ease;
+ --transition-base: 0.2s ease;
+ --transition-slow: 0.3s ease;
+
+ /* ============================================
+ Z-INDEX LAYERS
+ ============================================ */
+ --z-dropdown: 100;
+ --z-sticky: 200;
+ --z-fixed: 300;
+ --z-modal-backdrop: 900;
+ --z-modal: 1000;
+ --z-tooltip: 1100;
+
+ /* ============================================
+ LAYOUT
+ ============================================ */
+ --container-max-width: 480px;
+ --container-padding: var(--spacing-md);
+
+ /* ============================================
+ COMPONENT-SPECIFIC
+ ============================================ */
+
+ /* Buttons */
+ --button-padding-y: 0.6rem;
+ --button-padding-x: 1.5rem;
+ --button-border-radius: var(--border-radius-sm);
+ --button-font-weight: var(--font-weight-medium);
+
+ /* Inputs */
+ --input-padding-y: 0.6rem;
+ --input-padding-x: 0.75rem;
+ --input-border-color: var(--color-border-medium);
+ --input-border-radius: var(--border-radius-sm);
+ --input-focus-border-color: var(--color-primary);
+ --input-focus-shadow: 0 0 0 2px rgba(0, 123, 255, 0.1);
+
+ /* Cards */
+ --card-bg: var(--color-bg-surface);
+ --card-padding: var(--spacing-md);
+ --card-border-radius: var(--border-radius-lg);
+ --card-shadow: var(--shadow-card);
+
+ /* Modals */
+ --modal-backdrop-bg: rgba(0, 0, 0, 0.5);
+ --modal-bg: var(--color-white);
+ --modal-border-radius: var(--border-radius-lg);
+ --modal-padding: var(--spacing-lg);
+ --modal-max-width: 500px;
+}
+
+/* ============================================
+ DARK MODE SUPPORT (Future Implementation)
+ ============================================ */
+@media (prefers-color-scheme: dark) {
+ /* Uncomment to enable dark mode
+ :root {
+ --color-text-primary: #f8f9fa;
+ --color-text-secondary: #adb5bd;
+ --color-bg-body: #212529;
+ --color-bg-surface: #343a40;
+ --color-border-light: #495057;
+ --color-border-medium: #6c757d;
+ }
+ */
+}
+
+/* Manual dark mode class override */
+.dark-mode {
+ --color-text-primary: #f8f9fa;
+ --color-text-secondary: #adb5bd;
+ --color-bg-body: #212529;
+ --color-bg-surface: #343a40;
+ --color-border-light: #495057;
+ --color-border-medium: #6c757d;
+}
+
+/* ============================================
+ UTILITY CLASSES
+ ============================================ */
+
+/* Spacing Utilities */
+.m-0 { margin: 0 !important; }
+.mt-1 { margin-top: var(--spacing-xs) !important; }
+.mt-2 { margin-top: var(--spacing-sm) !important; }
+.mt-3 { margin-top: var(--spacing-md) !important; }
+.mt-4 { margin-top: var(--spacing-lg) !important; }
+
+.mb-1 { margin-bottom: var(--spacing-xs) !important; }
+.mb-2 { margin-bottom: var(--spacing-sm) !important; }
+.mb-3 { margin-bottom: var(--spacing-md) !important; }
+.mb-4 { margin-bottom: var(--spacing-lg) !important; }
+
+.p-0 { padding: 0 !important; }
+.p-1 { padding: var(--spacing-xs) !important; }
+.p-2 { padding: var(--spacing-sm) !important; }
+.p-3 { padding: var(--spacing-md) !important; }
+.p-4 { padding: var(--spacing-lg) !important; }
+
+/* Text Utilities */
+.text-center { text-align: center !important; }
+.text-left { text-align: left !important; }
+.text-right { text-align: right !important; }
+
+.text-primary { color: var(--color-primary) !important; }
+.text-secondary { color: var(--color-text-secondary) !important; }
+.text-muted { color: var(--color-text-muted) !important; }
+.text-danger { color: var(--color-danger) !important; }
+.text-success { color: var(--color-success) !important; }
+
+.font-weight-normal { font-weight: var(--font-weight-normal) !important; }
+.font-weight-medium { font-weight: var(--font-weight-medium) !important; }
+.font-weight-semibold { font-weight: var(--font-weight-semibold) !important; }
+.font-weight-bold { font-weight: var(--font-weight-bold) !important; }
+
+/* Display Utilities */
+.d-none { display: none !important; }
+.d-block { display: block !important; }
+.d-flex { display: flex !important; }
+.d-inline-block { display: inline-block !important; }
+
+/* Flex Utilities */
+.flex-column { flex-direction: column !important; }
+.flex-row { flex-direction: row !important; }
+.justify-center { justify-content: center !important; }
+.justify-between { justify-content: space-between !important; }
+.align-center { align-items: center !important; }
+.gap-1 { gap: var(--spacing-xs) !important; }
+.gap-2 { gap: var(--spacing-sm) !important; }
+.gap-3 { gap: var(--spacing-md) !important; }