From aea07374d984675ddbedabc96606f4f64342d91f Mon Sep 17 00:00:00 2001 From: Nico Date: Fri, 23 Jan 2026 22:23:37 -0800 Subject: [PATCH] update css --- .../src/components/common/UserRoleCard.jsx | 5 +- .../src/components/modals/AddImageModal.jsx | 16 +- .../modals/ConfirmAddExistingModal.jsx | 16 +- frontend/src/components/modals/ImageModal.jsx | 2 +- .../components/modals/SimilarItemModal.jsx | 20 +- frontend/src/main.tsx | 1 + frontend/src/pages/AdminPanel.jsx | 8 +- frontend/src/pages/Login.jsx | 16 +- frontend/src/pages/Register.jsx | 12 +- frontend/src/pages/Settings.jsx | 16 +- frontend/src/styles/AddImageModal.css | 97 +-- frontend/src/styles/ImageModal.css | 39 +- frontend/src/styles/SimilarItemModal.css | 116 +--- frontend/src/styles/UserRoleCard.css | 42 +- .../components/ConfirmAddExistingModal.css | 105 +--- frontend/src/styles/pages/AdminPanel.css | 40 +- frontend/src/styles/pages/Login.css | 72 +-- frontend/src/styles/pages/Register.css | 75 +-- frontend/src/styles/pages/Settings.css | 119 +--- frontend/src/styles/utilities.css | 570 ++++++++++++++++++ 20 files changed, 653 insertions(+), 734 deletions(-) create mode 100644 frontend/src/styles/utilities.css diff --git a/frontend/src/components/common/UserRoleCard.jsx b/frontend/src/components/common/UserRoleCard.jsx index 9a1405b..4e91bed 100644 --- a/frontend/src/components/common/UserRoleCard.jsx +++ b/frontend/src/components/common/UserRoleCard.jsx @@ -2,7 +2,7 @@ import { ROLES } from "../../constants/roles"; export default function UserRoleCard({ user, onRoleChange }) { return ( -
+
{user.name} @{user.username} @@ -10,7 +10,8 @@ export default function UserRoleCard({ user, onRoleChange }) { handleSelectChange("defaultSortMode", e.target.value)} - className="settings-select" + className="form-select mt-2" > @@ -188,7 +188,7 @@ export default function Settings() { {/* Behavior Tab */} {activeTab === "behavior" && (
-

Behavior

+

Behavior

-
-
diff --git a/frontend/src/styles/AddImageModal.css b/frontend/src/styles/AddImageModal.css index 49ea8e0..a0608d4 100644 --- a/frontend/src/styles/AddImageModal.css +++ b/frontend/src/styles/AddImageModal.css @@ -1,44 +1,4 @@ -.add-image-modal-overlay { - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100%; - background: var(--modal-backdrop-bg); - display: flex; - justify-content: center; - align-items: center; - z-index: var(--z-modal); - animation: fadeIn 0.2s ease-out; -} - -.add-image-modal { - background: var(--modal-bg); - padding: var(--spacing-xl); - border-radius: var(--border-radius-xl); - max-width: 500px; - width: 90%; - box-shadow: var(--shadow-xl); - animation: slideUp 0.3s ease-out; -} - -.add-image-modal h2 { - margin: 0 0 var(--spacing-sm) 0; - font-size: var(--font-size-2xl); - color: var(--color-text-primary); - text-align: center; -} - -.add-image-subtitle { - margin: 0 0 var(--spacing-xl) 0; - color: var(--color-text-secondary); - font-size: 0.95em; - text-align: center; -} - -.add-image-subtitle strong { - color: var(--color-primary); -} +/* AddImageModal - custom styles for unique components */ .add-image-options { display: flex; @@ -121,58 +81,3 @@ .add-image-remove:hover { background: rgba(255, 0, 0, 1); } - -.add-image-actions { - display: flex; - gap: 1em; - margin-top: 1.5em; -} - -.add-image-cancel, -.add-image-confirm { - flex: 1; - padding: 0.8em; - border: none; - border-radius: 6px; - font-size: 1em; - cursor: pointer; - transition: all 0.2s; -} - -.add-image-cancel { - background: #f0f0f0; - color: #333; -} - -.add-image-cancel:hover { - background: #e0e0e0; -} - -.add-image-confirm { - background: #28a745; - color: white; -} - -.add-image-confirm:hover { - background: #218838; -} - -@keyframes fadeIn { - from { - opacity: 0; - } - to { - opacity: 1; - } -} - -@keyframes slideUp { - from { - transform: translateY(30px); - opacity: 0; - } - to { - transform: translateY(0); - opacity: 1; - } -} diff --git a/frontend/src/styles/ImageModal.css b/frontend/src/styles/ImageModal.css index ae7b414..fe4fbe7 100644 --- a/frontend/src/styles/ImageModal.css +++ b/frontend/src/styles/ImageModal.css @@ -1,3 +1,5 @@ +/* ImageModal - specialized full-screen image viewer */ + .image-modal-overlay { position: fixed; top: 0; @@ -44,30 +46,6 @@ } } -.image-modal-close { - position: absolute; - top: -15px; - right: -15px; - width: 40px; - height: 40px; - border-radius: 50%; - background: #ff4444; - color: white; - border: 3px solid white; - font-size: 1.5rem; - line-height: 1; - cursor: pointer; - display: flex; - align-items: center; - justify-content: center; - z-index: 1001; - transition: background 0.2s; -} - -.image-modal-close:hover { - background: #cc0000; -} - .image-modal-img { max-width: 100%; max-height: 70vh; @@ -76,14 +54,6 @@ border-radius: 8px; } -.image-modal-caption { - text-align: center; - margin-top: 1rem; - font-size: 1.2rem; - font-weight: 600; - color: #333; -} - @media (max-width: 768px) { .image-modal-overlay { padding: 1rem; @@ -92,8 +62,5 @@ .image-modal-img { max-height: 60vh; } - - .image-modal-caption { - font-size: 1rem; - } } + diff --git a/frontend/src/styles/SimilarItemModal.css b/frontend/src/styles/SimilarItemModal.css index 73c2599..ff34cb2 100644 --- a/frontend/src/styles/SimilarItemModal.css +++ b/frontend/src/styles/SimilarItemModal.css @@ -1,115 +1,3 @@ -.similar-item-modal-overlay { - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100%; - background: var(--modal-backdrop-bg); - display: flex; - justify-content: center; - align-items: center; - z-index: var(--z-modal); - animation: fadeIn 0.2s ease-out; -} +/* SimilarItemModal - uses utility classes from utilities.css */ +/* No custom styles needed - all handled by utilities */ -.similar-item-modal { - background: var(--modal-bg); - padding: var(--spacing-xl); - border-radius: var(--border-radius-xl); - max-width: 500px; - width: 90%; - box-shadow: var(--shadow-xl); - animation: slideUp 0.3s ease-out; -} - -.similar-item-modal h2 { - margin: 0 0 var(--spacing-md) 0; - font-size: var(--font-size-2xl); - color: var(--color-text-primary); - text-align: center; -} - -.similar-item-question { - margin: 0 0 var(--spacing-sm) 0; - font-size: var(--font-size-lg); - color: var(--color-text-primary); - text-align: center; -} - -.similar-item-question strong { - color: var(--color-primary); -} - -.similar-item-clarification { - margin: 0 0 var(--spacing-xl) 0; - font-size: var(--font-size-sm); - color: var(--color-text-secondary); - text-align: center; - font-style: italic; -} - -.similar-item-actions { - display: flex; - gap: 0.8em; - margin-top: 1.5em; -} - -.similar-item-cancel, -.similar-item-no, -.similar-item-yes { - flex: 1; - padding: var(--button-padding-y) var(--button-padding-x); - border: none; - border-radius: var(--button-border-radius); - font-size: var(--font-size-base); - cursor: pointer; - transition: var(--transition-base); - font-weight: var(--button-font-weight); -} - -.similar-item-cancel { - background: var(--color-gray-200); - color: var(--color-text-primary); -} - -.similar-item-cancel:hover { - background: var(--color-gray-300); -} - -.similar-item-no { - background: var(--color-secondary); - color: var(--color-text-inverse); -} - -.similar-item-no:hover { - background: var(--color-secondary-hover); -} - -.similar-item-yes { - background: var(--color-success); - color: var(--color-text-inverse); -} - -.similar-item-yes:hover { - background: var(--color-success-hover); -} - -@keyframes fadeIn { - from { - opacity: 0; - } - to { - opacity: 1; - } -} - -@keyframes slideUp { - from { - transform: translateY(30px); - opacity: 0; - } - to { - transform: translateY(0); - opacity: 1; - } -} diff --git a/frontend/src/styles/UserRoleCard.css b/frontend/src/styles/UserRoleCard.css index b391637..d8aa79f 100644 --- a/frontend/src/styles/UserRoleCard.css +++ b/frontend/src/styles/UserRoleCard.css @@ -1,19 +1,4 @@ -.user-card { - display: flex; - justify-content: space-between; - align-items: center; - padding: var(--spacing-md); - margin: var(--spacing-sm) 0; - background: var(--color-bg-surface); - border-radius: var(--border-radius-lg); - border: var(--border-width-thin) solid var(--color-border-light); - box-shadow: var(--shadow-sm); - transition: var(--transition-base); -} - -.user-card:hover { - box-shadow: var(--shadow-md); -} +/* UserRoleCard - custom styles only */ .user-info { display: flex; @@ -26,28 +11,3 @@ font-size: var(--font-size-sm); } -.user-info h3 { - color: var(--color-text-primary); - margin: 0; -} - -.role-select { - padding: var(--spacing-sm); - border-radius: var(--border-radius-sm); - border: var(--border-width-thin) solid var(--input-border-color); - background: var(--color-bg-surface); - color: var(--color-text-primary); - cursor: pointer; - font-size: var(--font-size-sm); - transition: var(--transition-base); -} - -.role-select:hover { - border-color: var(--color-primary); -} - -.role-select:focus { - outline: none; - border-color: var(--input-focus-border-color); - box-shadow: var(--input-focus-shadow); -} diff --git a/frontend/src/styles/components/ConfirmAddExistingModal.css b/frontend/src/styles/components/ConfirmAddExistingModal.css index 93a1082..96033f9 100644 --- a/frontend/src/styles/components/ConfirmAddExistingModal.css +++ b/frontend/src/styles/components/ConfirmAddExistingModal.css @@ -1,55 +1,4 @@ -/* Confirm Add Existing Modal */ -.confirm-add-existing-overlay { - position: fixed; - top: 0; - left: 0; - right: 0; - bottom: 0; - background: var(--modal-backdrop-bg); - display: flex; - align-items: center; - justify-content: center; - z-index: var(--z-modal); - padding: var(--spacing-md); -} - -.confirm-add-existing-modal { - background: var(--modal-bg); - border-radius: var(--modal-border-radius); - padding: var(--modal-padding); - max-width: 400px; - width: 100%; - box-shadow: var(--shadow-xl); - animation: slideIn 0.2s ease-out; -} - -@keyframes slideIn { - from { - opacity: 0; - transform: translateY(-20px); - } - to { - opacity: 1; - transform: translateY(0); - } -} - -.confirm-add-existing-title { - margin: 0 0 var(--spacing-lg) 0; - font-size: var(--font-size-xl); - color: var(--color-text-primary); - text-align: center; - font-weight: var(--font-weight-normal); -} - -.confirm-add-existing-title strong { - color: var(--color-primary); - font-weight: var(--font-weight-semibold); -} - -.confirm-add-existing-content { - margin-bottom: var(--spacing-lg); -} +/* ConfirmAddExistingModal - quantity breakdown box */ .confirm-add-existing-qty-info { background: var(--color-bg-surface); @@ -90,55 +39,3 @@ font-size: var(--font-size-lg); } -.confirm-add-existing-actions { - display: flex; - gap: var(--spacing-md); - margin-top: var(--spacing-lg); -} - -.confirm-add-existing-btn { - flex: 1; - padding: var(--button-padding-y) var(--button-padding-x); - border: none; - border-radius: var(--button-border-radius); - font-size: var(--font-size-base); - font-weight: var(--button-font-weight); - cursor: pointer; - transition: var(--transition-base); -} - -.confirm-add-existing-btn.cancel { - background: var(--color-bg-surface); - color: var(--color-text-primary); - border: var(--border-width-thin) solid var(--color-border-medium); -} - -.confirm-add-existing-btn.cancel:hover { - background: var(--color-bg-hover); - border-color: var(--color-border-dark); -} - -.confirm-add-existing-btn.confirm { - background: var(--color-primary); - color: var(--color-text-inverse); -} - -.confirm-add-existing-btn.confirm:hover { - background: var(--color-primary-hover); - transform: translateY(-1px); - box-shadow: var(--shadow-md); -} - -.confirm-add-existing-btn.confirm:active { - transform: translateY(0); -} - -@media (max-width: 480px) { - .confirm-add-existing-modal { - max-width: 90%; - } - - .confirm-add-existing-actions { - flex-direction: column; - } -} diff --git a/frontend/src/styles/pages/AdminPanel.css b/frontend/src/styles/pages/AdminPanel.css index e5bd149..0afe84b 100644 --- a/frontend/src/styles/pages/AdminPanel.css +++ b/frontend/src/styles/pages/AdminPanel.css @@ -1,41 +1,9 @@ -/* Admin Panel Page */ -.admin-panel-page { - padding: var(--spacing-lg); - min-height: 100vh; -} +/* Admin Panel - uses utility classes */ +/* Responsive adjustments only */ -.admin-panel-container { - max-width: 800px; - margin: 0 auto; - background: var(--color-bg-surface); - padding: var(--spacing-xl); - border-radius: var(--border-radius-lg); - box-shadow: var(--shadow-card); -} - -.admin-panel-title { - font-size: var(--font-size-3xl); - font-weight: 700; - color: var(--color-text-primary); - margin: 0 0 var(--spacing-xl) 0; - text-align: center; -} - -.admin-panel-users { - margin-top: var(--spacing-xl); -} - -/* Mobile Responsive */ @media (max-width: 768px) { .admin-panel-page { - padding: var(--spacing-md); - } - - .admin-panel-container { - padding: var(--spacing-lg); - } - - .admin-panel-title { - font-size: var(--font-size-2xl); + padding: var(--spacing-md) !important; } } + diff --git a/frontend/src/styles/pages/Login.css b/frontend/src/styles/pages/Login.css index df01ebc..92aa35a 100644 --- a/frontend/src/styles/pages/Login.css +++ b/frontend/src/styles/pages/Login.css @@ -1,37 +1,4 @@ -.login-wrapper { - font-family: Arial, sans-serif; - padding: 1em; - background: #f8f9fa; - min-height: 100vh; - - display: flex; - justify-content: center; - align-items: center; -} - -.login-box { - width: 100%; - max-width: 360px; - background: white; - padding: 1.5em; - border-radius: 8px; - box-shadow: 0 0 10px rgba(0,0,0,0.12); -} - -.login-title { - text-align: center; - font-size: 1.6em; - margin-bottom: 1em; -} - -.login-input { - width: 100%; - padding: 0.6em; - margin: 0.4em 0; - font-size: 1em; - border-radius: 4px; - border: 1px solid #ccc; -} +/* Login page - custom password toggle only */ .login-password-wrapper { display: flex; @@ -40,7 +7,7 @@ margin: 0.4em 0; } -.login-password-wrapper .login-input { +.login-password-wrapper .form-input { flex: 1; width: auto; margin: 0; @@ -67,38 +34,3 @@ background: #e8e8e8; } -.login-button { - width: 100%; - padding: 0.7em; - margin-top: 0.6em; - background: #007bff; - border: none; - color: white; - border-radius: 4px; - cursor: pointer; - font-size: 1em; -} - -.login-button:hover { - background: #0068d1; -} - -.login-error { - color: red; - text-align: center; - margin-bottom: 0.6em; -} - -.login-register { - text-align: center; - margin-top: 1em; -} - -.login-register a { - color: #007bff; - text-decoration: none; -} - -.login-register a:hover { - text-decoration: underline; -} diff --git a/frontend/src/styles/pages/Register.css b/frontend/src/styles/pages/Register.css index 10a57d0..a164ba7 100644 --- a/frontend/src/styles/pages/Register.css +++ b/frontend/src/styles/pages/Register.css @@ -1,18 +1,12 @@ +/* Register page - container only */ + .register-container { max-width: 400px; margin: 50px auto; padding: 2rem; border-radius: 12px; - background: #ffffff; - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); - font-family: Arial, sans-serif; -} - -.register-container h1 { - text-align: center; - margin-bottom: 1.5rem; - font-size: 1.8rem; - font-weight: bold; + background: var(--color-bg-primary); + box-shadow: var(--shadow-lg); } .register-form { @@ -21,64 +15,3 @@ gap: 12px; } -.register-form input { - padding: 12px 14px; - border: 1px solid #ccc; - border-radius: 8px; - font-size: 1rem; - outline: none; - transition: border-color 0.2s ease; -} - -.register-form input:focus { - border-color: #0077ff; -} - -.register-form button { - padding: 12px; - border: none; - background: #0077ff; - color: white; - font-size: 1rem; - border-radius: 8px; - cursor: pointer; - margin-top: 10px; - transition: background 0.2s ease; -} - -.register-form button:hover:not(:disabled) { - background: #005fcc; -} - -.register-form button:disabled { - background: #a8a8a8; - cursor: not-allowed; -} - -.error-message { - height: 15px; - color: red; - text-align: center; - margin-bottom: 10px; -} - -.success-message { - color: green; - text-align: center; - margin-bottom: 10px; -} - -.register-link { - text-align: center; - margin-top: 1rem; -} - -.register-link a { - color: #0077ff; - text-decoration: none; - font-weight: bold; -} - -.register-link a:hover { - text-decoration: underline; -} diff --git a/frontend/src/styles/pages/Settings.css b/frontend/src/styles/pages/Settings.css index 364d7a5..0b5abc4 100644 --- a/frontend/src/styles/pages/Settings.css +++ b/frontend/src/styles/pages/Settings.css @@ -1,4 +1,4 @@ -/* Settings Page Styles */ +/* Settings Page - custom components only */ .settings-page { padding: var(--spacing-lg); @@ -6,24 +6,7 @@ margin: 0 auto; } - -.settings-container { - background: var(--color-bg-surface); - border-radius: var(--border-radius-lg); - padding: var(--spacing-xl); - box-shadow: var(--shadow-sm); -} - - -.settings-title { - font-size: var(--font-size-2xl); - font-weight: 600; - color: var(--color-text-primary); - margin: 0 0 var(--spacing-xl); -} - - -/* === Tabs === */ +/* Tabs */ .settings-tabs { display: flex; gap: var(--spacing-sm); @@ -31,7 +14,6 @@ border-bottom: 2px solid var(--color-border-light); } - .settings-tab { padding: var(--spacing-md) var(--spacing-lg); background: none; @@ -45,30 +27,25 @@ margin-bottom: -2px; } - .settings-tab:hover { color: var(--color-primary); background: var(--color-bg-hover); } - .settings-tab.active { color: var(--color-primary); border-bottom-color: var(--color-primary); } - -/* === Content === */ +/* Content */ .settings-content { min-height: 400px; } - .settings-section { animation: fadeIn 0.2s ease-in; } - @keyframes fadeIn { from { opacity: 0; @@ -80,27 +57,16 @@ } } - -.settings-section-title { - font-size: var(--font-size-xl); - font-weight: 600; - color: var(--color-text-primary); - margin: 0 0 var(--spacing-lg); -} - - .settings-group { margin-bottom: var(--spacing-xl); padding-bottom: var(--spacing-xl); border-bottom: 1px solid var(--color-border-light); } - .settings-group:last-child { border-bottom: none; } - .settings-label { display: flex; align-items: center; @@ -112,14 +78,12 @@ cursor: pointer; } - .settings-label input[type="checkbox"] { width: 20px; height: 20px; cursor: pointer; } - .settings-description { font-size: var(--font-size-sm); color: var(--color-text-secondary); @@ -127,15 +91,13 @@ line-height: 1.5; } - -/* === Theme Buttons === */ +/* Theme Buttons */ .settings-theme-options { display: flex; gap: var(--spacing-md); margin-top: var(--spacing-sm); } - .settings-theme-btn { flex: 1; padding: var(--spacing-md); @@ -149,40 +111,18 @@ transition: all 0.2s; } - .settings-theme-btn:hover { border-color: var(--color-primary); background: var(--color-primary-light); } - .settings-theme-btn.active { border-color: var(--color-primary); background: var(--color-primary); color: var(--color-white); } - -/* === Select & Range === */ -.settings-select { - width: 100%; - padding: var(--spacing-sm) var(--spacing-md); - border: 1px solid var(--color-border-medium); - border-radius: var(--border-radius-md); - background: var(--color-bg-surface); - color: var(--color-text-primary); - font-size: var(--font-size-base); - cursor: pointer; - margin-top: var(--spacing-sm); -} - - -.settings-select:focus { - outline: none; - border-color: var(--color-primary); -} - - +/* Range Slider */ .settings-range { width: 100%; height: 6px; @@ -195,7 +135,6 @@ -webkit-appearance: none; } - .settings-range::-webkit-slider-thumb { appearance: none; -webkit-appearance: none; @@ -207,13 +146,11 @@ transition: all 0.2s; } - .settings-range::-webkit-slider-thumb:hover { background: var(--color-primary-hover); transform: scale(1.1); } - .settings-range::-moz-range-thumb { width: 20px; height: 20px; @@ -224,51 +161,17 @@ transition: all 0.2s; } - .settings-range::-moz-range-thumb:hover { background: var(--color-primary-hover); transform: scale(1.1); } - -/* === Actions === */ -.settings-actions { - margin-top: var(--spacing-2xl); - padding-top: var(--spacing-xl); - border-top: 2px solid var(--color-border-light); - text-align: center; -} - - -.settings-btn-reset { - padding: var(--spacing-md) var(--spacing-xl); - border: 2px solid var(--color-danger); - background: transparent; - color: var(--color-danger); - border-radius: var(--border-radius-md); - font-size: var(--font-size-base); - font-weight: 500; - cursor: pointer; - transition: all 0.2s; -} - - -.settings-btn-reset:hover { - background: var(--color-danger); - color: var(--color-white); -} - - -/* === Responsive === */ +/* Responsive */ @media (max-width: 768px) { .settings-page { padding: var(--spacing-md); } - .settings-container { - padding: var(--spacing-lg); - } - .settings-tabs { flex-wrap: nowrap; overflow-x: auto; @@ -285,13 +188,3 @@ } } - -@media (max-width: 480px) { - .settings-title { - font-size: var(--font-size-xl); - } - - .settings-container { - padding: var(--spacing-md); - } -} diff --git a/frontend/src/styles/utilities.css b/frontend/src/styles/utilities.css new file mode 100644 index 0000000..e02a4e4 --- /dev/null +++ b/frontend/src/styles/utilities.css @@ -0,0 +1,570 @@ +/** + * Reusable Utility Classes + * + * Common patterns extracted from component styles. + * Import this file after theme.css in main.tsx + */ + +/* ============================================ + LAYOUT UTILITIES + ============================================ */ + +/* Containers */ +.container { + max-width: var(--container-max-width); + margin: 0 auto; + padding: var(--container-padding); +} + +.container-full { + width: 100%; + padding: var(--spacing-md); +} + +/* Centering */ +.center-content { + display: flex; + justify-content: center; + align-items: center; + min-height: 100vh; +} + +.flex-center { + display: flex; + justify-content: center; + align-items: center; +} + +.flex-between { + display: flex; + justify-content: space-between; + align-items: center; +} + +.flex-start { + display: flex; + justify-content: flex-start; + align-items: center; +} + +.flex-column { + display: flex; + flex-direction: column; +} + +.flex-1 { + flex: 1; +} + +/* ============================================ + CARD COMPONENTS + ============================================ */ + +.card { + background: var(--color-bg-surface); + border-radius: var(--card-border-radius); + padding: var(--card-padding); + box-shadow: var(--shadow-card); +} + +.card-elevated { + background: var(--color-bg-surface); + border-radius: var(--card-border-radius); + padding: var(--spacing-lg); + box-shadow: var(--shadow-lg); +} + +.card-title { + font-size: var(--font-size-xl); + font-weight: var(--font-weight-semibold); + margin-bottom: var(--spacing-md); + color: var(--color-text-primary); +} + +/* ============================================ + BUTTON COMPONENTS + ============================================ */ + +.btn { + padding: var(--button-padding-y) var(--button-padding-x); + border: none; + border-radius: var(--button-border-radius); + font-size: var(--font-size-base); + font-weight: var(--button-font-weight); + cursor: pointer; + transition: var(--transition-base); + text-align: center; + display: inline-block; +} + +.btn-primary { + background: var(--color-primary); + color: var(--color-text-inverse); +} + +.btn-primary:hover:not(:disabled) { + background: var(--color-primary-hover); + transform: translateY(-1px); + box-shadow: var(--shadow-md); +} + +.btn-secondary { + background: var(--color-secondary); + color: var(--color-text-inverse); +} + +.btn-secondary:hover:not(:disabled) { + background: var(--color-secondary-hover); +} + +.btn-danger { + background: var(--color-danger); + color: var(--color-text-inverse); +} + +.btn-danger:hover:not(:disabled) { + background: var(--color-danger-hover); +} + +.btn-success { + background: var(--color-success); + color: var(--color-text-inverse); +} + +.btn-success:hover:not(:disabled) { + background: var(--color-success-hover); +} + +.btn-outline { + background: transparent; + color: var(--color-primary); + border: var(--border-width-thin) solid var(--color-primary); +} + +.btn-outline:hover:not(:disabled) { + background: var(--color-primary); + color: var(--color-text-inverse); +} + +.btn-ghost { + background: var(--color-bg-surface); + color: var(--color-text-primary); + border: var(--border-width-thin) solid var(--color-border-medium); +} + +.btn-ghost:hover:not(:disabled) { + background: var(--color-bg-hover); + border-color: var(--color-border-dark); +} + +.btn-sm { + padding: var(--spacing-xs) var(--spacing-sm); + font-size: var(--font-size-sm); +} + +.btn-lg { + padding: var(--spacing-md) var(--spacing-xl); + font-size: var(--font-size-lg); +} + +.btn-block { + width: 100%; + display: block; +} + +.btn:disabled { + opacity: 0.6; + cursor: not-allowed; +} + +/* ============================================ + FORM COMPONENTS + ============================================ */ + +.form-group { + margin-bottom: var(--spacing-md); +} + +.form-label { + display: block; + margin-bottom: var(--spacing-xs); + font-size: var(--font-size-sm); + font-weight: var(--font-weight-medium); + color: var(--color-text-primary); +} + +.form-input { + width: 100%; + 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); + color: var(--color-text-primary); + background: var(--color-bg-surface); + transition: var(--transition-base); + box-sizing: border-box; +} + +.form-input:focus { + outline: none; + border-color: var(--input-focus-border-color); + box-shadow: var(--input-focus-shadow); +} + +.form-input::placeholder { + color: var(--color-text-muted); +} + +.form-select { + width: 100%; + 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); + color: var(--color-text-primary); + background: var(--color-bg-surface); + cursor: pointer; + transition: var(--transition-base); +} + +.form-select:focus { + outline: none; + border-color: var(--input-focus-border-color); + box-shadow: var(--input-focus-shadow); +} + +/* ============================================ + MODAL COMPONENTS + ============================================ */ + +.modal-overlay { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: var(--modal-backdrop-bg); + display: flex; + align-items: center; + justify-content: center; + z-index: var(--z-modal); + padding: var(--spacing-md); +} + +.modal { + background: var(--modal-bg); + border-radius: var(--modal-border-radius); + padding: var(--modal-padding); + max-width: var(--modal-max-width); + width: 100%; + box-shadow: var(--shadow-xl); + animation: modalSlideIn 0.2s ease-out; +} + +@keyframes modalSlideIn { + from { + opacity: 0; + transform: translateY(-20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.modal-header { + margin-bottom: var(--spacing-lg); +} + +.modal-title { + margin: 0; + font-size: var(--font-size-xl); + font-weight: var(--font-weight-semibold); + color: var(--color-text-primary); + text-align: center; +} + +.modal-content { + margin-bottom: var(--spacing-lg); +} + +.modal-actions { + display: flex; + gap: var(--spacing-md); + margin-top: var(--spacing-lg); +} + +.modal-actions .btn { + flex: 1; +} + +/* ============================================ + LIST COMPONENTS + ============================================ */ + +.list-unstyled { + list-style: none; + padding: 0; + margin: 0; +} + +.list-item { + padding: var(--spacing-md); + border: var(--border-width-thin) solid var(--color-border-light); + border-radius: var(--border-radius-md); + background: var(--color-bg-surface); + margin-bottom: var(--spacing-sm); + transition: var(--transition-base); +} + +.list-item:hover { + background: var(--color-bg-hover); + border-color: var(--color-border-medium); + transform: translateY(-1px); +} + +.list-item:last-child { + margin-bottom: 0; +} + +/* ============================================ + IMAGE COMPONENTS + ============================================ */ + +.image-placeholder { + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + background: var(--color-bg-surface); + border: var(--border-width-medium) dashed var(--color-border-medium); + border-radius: var(--border-radius-md); + color: var(--color-text-muted); + font-size: 2rem; +} + +.image-thumbnail { + width: 50px; + height: 50px; + border-radius: var(--border-radius-md); + object-fit: cover; + border: var(--border-width-thin) solid var(--color-border-light); +} + +/* ============================================ + BADGE COMPONENTS + ============================================ */ + +.badge { + display: inline-block; + padding: var(--spacing-xs) var(--spacing-sm); + border-radius: var(--border-radius-full); + font-size: var(--font-size-xs); + font-weight: var(--font-weight-medium); + line-height: 1; +} + +.badge-primary { + background: var(--color-primary-light); + color: var(--color-primary); +} + +.badge-success { + background: var(--color-success-light); + color: var(--color-success); +} + +.badge-danger { + background: var(--color-danger-light); + color: var(--color-danger); +} + +.badge-warning { + background: var(--color-warning-light); + color: var(--color-warning); +} + +.badge-secondary { + background: var(--color-secondary-light); + color: var(--color-secondary); +} + +/* ============================================ + DIVIDER + ============================================ */ + +.divider { + border: none; + border-top: var(--border-width-thin) solid var(--color-border-light); + margin: var(--spacing-lg) 0; +} + +.divider-thick { + border-top-width: var(--border-width-medium); +} + +/* ============================================ + SPACING HELPERS + ============================================ */ + +.mt-0 { margin-top: 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-0 { margin-bottom: 0 !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; } + +.ml-auto { margin-left: auto !important; } +.mr-auto { margin-right: auto !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; } + +.px-0 { padding-left: 0 !important; padding-right: 0 !important; } +.px-1 { padding-left: var(--spacing-xs) !important; padding-right: var(--spacing-xs) !important; } +.px-2 { padding-left: var(--spacing-sm) !important; padding-right: var(--spacing-sm) !important; } +.px-3 { padding-left: var(--spacing-md) !important; padding-right: var(--spacing-md) !important; } +.px-4 { padding-left: var(--spacing-lg) !important; padding-right: var(--spacing-lg) !important; } + +.py-0 { padding-top: 0 !important; padding-bottom: 0 !important; } +.py-1 { padding-top: var(--spacing-xs) !important; padding-bottom: var(--spacing-xs) !important; } +.py-2 { padding-top: var(--spacing-sm) !important; padding-bottom: var(--spacing-sm) !important; } +.py-3 { padding-top: var(--spacing-md) !important; padding-bottom: var(--spacing-md) !important; } +.py-4 { padding-top: var(--spacing-lg) !important; padding-bottom: var(--spacing-lg) !important; } + +/* ============================================ + TEXT UTILITIES + ============================================ */ + +.text-xs { font-size: var(--font-size-xs) !important; } +.text-sm { font-size: var(--font-size-sm) !important; } +.text-base { font-size: var(--font-size-base) !important; } +.text-lg { font-size: var(--font-size-lg) !important; } +.text-xl { font-size: var(--font-size-xl) !important; } +.text-2xl { font-size: var(--font-size-2xl) !important; } + +.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; } +.text-warning { color: var(--color-warning) !important; } + +.font-normal { font-weight: var(--font-weight-normal) !important; } +.font-medium { font-weight: var(--font-weight-medium) !important; } +.font-semibold { font-weight: var(--font-weight-semibold) !important; } +.font-bold { font-weight: var(--font-weight-bold) !important; } + +.text-uppercase { text-transform: uppercase !important; } +.text-lowercase { text-transform: lowercase !important; } +.text-capitalize { text-transform: capitalize !important; } + +.text-truncate { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +/* ============================================ + DISPLAY & VISIBILITY + ============================================ */ + +.d-none { display: none !important; } +.d-block { display: block !important; } +.d-inline { display: inline !important; } +.d-inline-block { display: inline-block !important; } +.d-flex { display: flex !important; } +.d-grid { display: grid !important; } + +.hidden { visibility: hidden !important; } +.visible { visibility: visible !important; } + +/* ============================================ + BORDER UTILITIES + ============================================ */ + +.border { border: var(--border-width-thin) solid var(--color-border-light) !important; } +.border-0 { border: none !important; } +.border-top { border-top: var(--border-width-thin) solid var(--color-border-light) !important; } +.border-bottom { border-bottom: var(--border-width-thin) solid var(--color-border-light) !important; } + +.rounded { border-radius: var(--border-radius-md) !important; } +.rounded-sm { border-radius: var(--border-radius-sm) !important; } +.rounded-lg { border-radius: var(--border-radius-lg) !important; } +.rounded-full { border-radius: var(--border-radius-full) !important; } + +/* ============================================ + SHADOW UTILITIES + ============================================ */ + +.shadow-none { box-shadow: none !important; } +.shadow-sm { box-shadow: var(--shadow-sm) !important; } +.shadow { box-shadow: var(--shadow-md) !important; } +.shadow-lg { box-shadow: var(--shadow-lg) !important; } +.shadow-xl { box-shadow: var(--shadow-xl) !important; } + +/* ============================================ + INTERACTION + ============================================ */ + +.cursor-pointer { cursor: pointer !important; } +.cursor-not-allowed { cursor: not-allowed !important; } +.cursor-default { cursor: default !important; } + +.pointer-events-none { pointer-events: none !important; } +.user-select-none { user-select: none !important; } + +/* ============================================ + POSITION + ============================================ */ + +.position-relative { position: relative !important; } +.position-absolute { position: absolute !important; } +.position-fixed { position: fixed !important; } +.position-sticky { position: sticky !important; } + +/* ============================================ + OVERFLOW + ============================================ */ + +.overflow-hidden { overflow: hidden !important; } +.overflow-auto { overflow: auto !important; } +.overflow-scroll { overflow: scroll !important; } + +/* ============================================ + WIDTH & HEIGHT + ============================================ */ + +.w-100 { width: 100% !important; } +.w-auto { width: auto !important; } +.h-100 { height: 100% !important; } +.h-auto { height: auto !important; } + +.min-h-screen { min-height: 100vh !important; } + +/* ============================================ + RESPONSIVE UTILITIES + ============================================ */ + +@media (max-width: 480px) { + .mobile-hidden { display: none !important; } + .mobile-block { display: block !important; } + .mobile-text-center { text-align: center !important; } +} + +@media (min-width: 481px) { + .desktop-hidden { display: none !important; } +}