/** * 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-primary); color: var(--color-text-inverse); } .btn-secondary:hover:not(:disabled) { background: var(--color-primary-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; } }