diff --git a/src/admin/AdminApp.tsx b/src/admin/AdminApp.tsx index 6633640..b1a4fe5 100644 --- a/src/admin/AdminApp.tsx +++ b/src/admin/AdminApp.tsx @@ -7,7 +7,18 @@ import AdminLayout from "./components/AdminLayout"; import AlertContainer from "./components/AlertContainer"; import Login from "./pages/Login"; import Dashboard from "./pages/Dashboard"; -import "./admin.css"; +import "./variables.css"; +import "./base.css"; +import "./forms.css"; +import "./buttons.css"; +import "./layout.css"; +import "./components.css"; +import "./tables.css"; +import "./skeleton.css"; +import "./datepicker.css"; +import "./filemanager.css"; +import "./pagination.css"; +import "./responsive.css"; import "./login.css"; import "./dashboard.css"; import "./attendance.css"; diff --git a/src/admin/admin.css b/src/admin/admin.css deleted file mode 100644 index 2822fee..0000000 --- a/src/admin/admin.css +++ /dev/null @@ -1,3228 +0,0 @@ -/* ============================================================================ - Admin Panel Styles - ============================================================================ */ - -/* ============================================================================ - Reset & Base - ============================================================================ */ - -* { - margin: 0; - padding: 0; - box-sizing: border-box; -} - -html { - scroll-behavior: smooth; - overflow-x: hidden; -} - -html, -body, -#root { - min-height: 100%; - min-height: 100dvh; - max-width: 100vw; -} - -body { - font-family: var(--font-body); - font-size: 16px; - line-height: 1.6; - color: var(--text-primary); - background: var(--bg-primary); - overflow-x: hidden; - overscroll-behavior-x: none; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - transition: - background-color 0.3s ease, - color 0.3s ease; -} - -.admin-sidebar, -.admin-header, -.admin-card, -.admin-modal { - transition: - background-color 0.3s ease, - color 0.3s ease, - border-color 0.3s ease; -} - -#root { - overflow-x: hidden; - touch-action: pan-y pinch-zoom; -} - -h1, -h2, -h3, -h4, -h5, -h6 { - font-family: var(--font-heading); - font-weight: 700; - line-height: 1.2; - color: var(--text-primary); -} - -h1 { - font-size: clamp(2.5rem, 5vw, 4rem); -} -h2 { - font-size: clamp(2rem, 4vw, 3rem); -} -h3 { - font-size: clamp(1.25rem, 2vw, 1.5rem); -} - -p { - color: var(--text-secondary); - line-height: 1.6; -} - -a { - color: inherit; - text-decoration: none; - transition: var(--transition); -} - -img { - max-width: 100%; - height: auto; -} - -::-webkit-scrollbar { - width: 8px; -} - -::-webkit-scrollbar-track { - background: var(--bg-secondary); -} - -::-webkit-scrollbar-thumb { - background: var(--border-color); - border-radius: 4px; -} - -::-webkit-scrollbar-thumb:hover { - background: var(--text-muted); -} - -::selection { - background: var(--accent-color); - color: #fff; -} - -/* ============================================================================ - CSS Variables - ============================================================================ */ - -:root { - /* Spacing scale */ - --space-1: 0.25rem; - --space-2: 0.5rem; - --space-3: 0.75rem; - --space-4: 1rem; - --space-5: 1.25rem; - --space-6: 1.5rem; - --space-8: 2rem; - --space-10: 2.5rem; - --space-12: 3rem; - - /* Shared colors */ - --accent-color: #d63031; - --accent-hover: #b52626; - --success: #22c55e; - --warning: #f59e0b; - --danger: #ef4444; - --info: #3b82f6; - --error: var(--danger); - --muted: #9ca3af; - --gradient: #d63031; - --gradient-subtle: rgba(214, 48, 49, 0.9); - - /* Shared layout */ - --border-radius: 10px; - --border-radius-sm: 8px; - --border-radius-lg: 16px; - --transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); - --transition-slow: all 0.5s cubic-bezier(0.4, 0, 0.2, 1); - --font-heading: "Urbanist", sans-serif; - --font-body: "Plus Jakarta Sans", sans-serif; - --font-mono: "DM Mono", "Menlo", monospace; - --safe-top: env(safe-area-inset-top, 0px); - --safe-bottom: env(safe-area-inset-bottom, 0px); - --safe-left: env(safe-area-inset-left, 0px); - --safe-right: env(safe-area-inset-right, 0px); - --navbar-height: calc(76px + var(--safe-top)); -} - -/* ---- Dark theme ---- */ -[data-theme="dark"] { - --bg-primary: #0f0f0f; - --bg-secondary: #171717; - --bg-tertiary: #1e1e1e; - --text-primary: #ffffff; - --text-secondary: #a0a0a0; - --text-muted: #666666; - --text-tertiary: #555555; - --border-color: rgba(255, 255, 255, 0.08); - --border-color-hover: rgba(255, 255, 255, 0.15); - --glass-bg: #171717; - --glass-bg-solid: #171717; - --glass-border: rgba(255, 255, 255, 0.08); - --glass-shadow: 0 1px 3px rgba(0, 0, 0, 0.2), 0 4px 16px rgba(0, 0, 0, 0.15); - --card-bg: #1a1a1a; - --card-bg-hover: #1e1e1e; - --input-bg: #1a1a1a; - --glow-color: rgba(214, 48, 49, 0.15); - --accent-light: rgba(214, 48, 49, 0.1); - --accent-soft: #2a1a1a; - --accent-glow: rgba(214, 48, 49, 0.3); - --success-light: rgba(34, 197, 94, 0.1); - --success-soft: #1a2a1e; - --warning-light: rgba(245, 158, 11, 0.1); - --warning-soft: #2a2518; - --danger-light: rgba(239, 68, 68, 0.1); - --danger-soft: #2a1a1a; - --info-light: rgba(59, 130, 246, 0.1); - --info-soft: #1a1e2a; - --muted-light: rgba(107, 114, 128, 0.15); - --orb-color-1: rgba(214, 48, 49, 0.2); - --orb-color-2: rgba(120, 119, 198, 0.15); - --calendar-icon-filter: invert(1); - --select-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23a0a0a0' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E"); - --table-row-hover: rgba(255, 255, 255, 0.02); - --row-current: color-mix(in srgb, var(--success) 5%, transparent); - --row-current-hover: color-mix(in srgb, var(--success) 8%, transparent); - --row-draft: color-mix(in srgb, var(--warning) 6%, transparent); - --row-expired: color-mix(in srgb, var(--danger) 5%, transparent); -} - -/* ---- Light theme ---- */ -[data-theme="light"] { - --success: #15803d; - --warning: #b45309; - --danger: #b91c1c; - --info: #1d4ed8; - --accent-color: #c73030; - --accent-hover: #b52828; - --muted: #6b7280; - --bg-primary: #f5f4f2; - --bg-secondary: #ffffff; - --bg-tertiary: #eeecea; - --text-primary: #1a1a1a; - --text-secondary: #555555; - --text-muted: #717180; - --text-tertiary: #8a8a96; - --border-color: rgba(0, 0, 0, 0.1); - --border-color-hover: rgba(0, 0, 0, 0.18); - --glass-bg: #ffffff; - --glass-bg-solid: #ffffff; - --glass-border: rgba(0, 0, 0, 0.08); - --glass-shadow: 0 1px 3px rgba(0, 0, 0, 0.06), 0 4px 16px rgba(0, 0, 0, 0.04); - --card-bg: #ffffff; - --card-bg-hover: #ffffff; - --input-bg: #ffffff; - --glow-color: rgba(222, 58, 58, 0.08); - --accent-light: rgba(222, 58, 58, 0.08); - --accent-soft: #fff0f0; - --accent-glow: rgba(222, 58, 58, 0.15); - --success-light: rgba(34, 197, 94, 0.1); - --success-soft: #e8fbf7; - --warning-light: rgba(245, 158, 11, 0.1); - --warning-soft: #fef9ec; - --danger-light: rgba(239, 68, 68, 0.1); - --danger-soft: #fef2f2; - --info-light: rgba(59, 130, 246, 0.1); - --info-soft: #ebf3fd; - --muted-light: rgba(107, 114, 128, 0.12); - --calendar-icon-filter: none; - --select-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23555555' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E"); - --table-row-hover: rgba(0, 0, 0, 0.03); - --row-current: var(--success-soft); - --row-current-hover: color-mix(in srgb, var(--success) 12%, transparent); - --row-draft: var(--warning-soft); - --row-expired: var(--danger-soft); - --orb-color-1: rgba(214, 48, 49, 0.12); - --orb-color-2: rgba(120, 119, 198, 0.1); -} - -/* Light mode - jemnejsi stiny */ -[data-theme="light"] .admin-toast { - box-shadow: - 0 2px 8px rgba(0, 0, 0, 0.08), - 0 1px 3px rgba(0, 0, 0, 0.06); -} - -[data-theme="light"] .react-datepicker { - box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1) !important; -} - -[data-theme="light"] .rich-editor .ql-snow .ql-picker-options, -[data-theme="light"] .rich-editor .ql-snow .ql-tooltip { - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); -} - -[data-theme="light"] .offers-customer-dropdown, -[data-theme="light"] .offers-template-menu { - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); -} - -[data-theme="light"] .dash-quick-btn:hover { - filter: brightness(0.9); -} - -/* ============================================================================ - Base / Utilities - ============================================================================ */ - -.text-warning { - color: var(--warning) !important; -} - -.text-danger { - color: var(--danger) !important; -} - -.text-success { - color: var(--success) !important; -} - -.text-muted { - color: var(--text-muted) !important; -} - -.text-secondary { - color: var(--text-secondary) !important; -} - -.text-tertiary { - color: var(--text-tertiary) !important; -} - -.text-accent { - color: var(--accent-color) !important; -} - -.fw-600 { - font-weight: 600 !important; -} - -.link-accent { - color: var(--accent-color); - font-weight: 500; - text-decoration: none; -} - -.link-accent:hover { - text-decoration: underline; -} - -/* Layout utilities */ -.flex-1 { - flex: 1; -} -.flex-row { - display: flex; - align-items: center; -} -.flex-row-gap { - display: flex; - align-items: center; - gap: var(--space-3); -} -.flex-between { - display: flex; - align-items: center; - justify-content: space-between; -} - -/* Spacing utilities */ -.mb-2 { - margin-bottom: var(--space-2); -} -.mb-4 { - margin-bottom: var(--space-4); -} -.mb-6 { - margin-bottom: var(--space-6); -} -.mt-2 { - margin-top: var(--space-2); -} -.mt-6 { - margin-top: var(--space-6); -} -.gap-2 { - gap: var(--space-2); -} -.gap-4 { - gap: var(--space-4); -} -.gap-5 { - gap: var(--space-5); -} - -/* Typography utilities */ -.fw-500 { - font-weight: 500; -} -.text-right { - text-align: right; -} -.text-center { - text-align: center; -} - -/* Spinner variant */ -.admin-spinner-sm { - width: 16px; - height: 16px; - border-width: 2px; -} - -/* ============================================================================ - Forms - ============================================================================ */ - -.admin-form { - display: flex; - flex-direction: column; - gap: 16px; -} - -.admin-form-group { - display: flex; - flex-direction: column; - gap: 0.5rem; -} - -.admin-form-label { - font-size: 12px; - font-weight: 600; - color: var(--text-secondary); -} - -.admin-form-input { - width: 100%; - padding: 9px 12px; - background: var(--input-bg); - border: 1px solid var(--border-color); - border-radius: var(--border-radius-sm); - color: var(--text-primary); - font-size: 13px; - font-family: inherit; - outline: none; - transition: - border-color 0.3s cubic-bezier(0.4, 0, 0.2, 1), - box-shadow 0.3s cubic-bezier(0.4, 0, 0.2, 1); - box-sizing: border-box; - min-height: 36px; -} - -.admin-form-input:focus { - border-color: var(--accent-color); - box-shadow: 0 0 0 3px var(--accent-light); -} - -.admin-form-input::placeholder { - color: var(--text-muted); -} - -.admin-form-input[type="date"], -.admin-form-input[type="time"], -.admin-form-input[type="month"], -.admin-form-input[type="number"] { - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; - text-align: left; - height: 36px; - max-width: 100%; -} - -.admin-form-input[type="number"]::-webkit-inner-spin-button, -.admin-form-input[type="number"]::-webkit-outer-spin-button { - -webkit-appearance: none; - margin: 0; -} - -.admin-form-input[type="date"]::-webkit-date-and-time-value, -.admin-form-input[type="time"]::-webkit-date-and-time-value, -.admin-form-input[type="month"]::-webkit-date-and-time-value { - text-align: left; - margin: 0; -} - -.admin-form-input[type="date"]::-webkit-datetime-edit, -.admin-form-input[type="time"]::-webkit-datetime-edit, -.admin-form-input[type="month"]::-webkit-datetime-edit { - padding: 0; -} - -.admin-form-input[type="date"]::-webkit-calendar-picker-indicator, -.admin-form-input[type="time"]::-webkit-calendar-picker-indicator, -.admin-form-input[type="month"]::-webkit-calendar-picker-indicator { - filter: var(--calendar-icon-filter, none); - cursor: pointer; -} - -/* Select */ -.admin-form-select { - width: 100%; - padding: 9px 12px; - background: var(--input-bg); - border: 1px solid var(--border-color); - border-radius: var(--border-radius-sm); - color: var(--text-primary); - font-size: 13px; - font-family: inherit; - outline: none; - transition: - border-color 0.3s cubic-bezier(0.4, 0, 0.2, 1), - box-shadow 0.3s cubic-bezier(0.4, 0, 0.2, 1); - min-height: 36px; - box-sizing: border-box; - cursor: pointer; - appearance: none; - background-image: var(--select-arrow); - background-repeat: no-repeat; - background-position: right 0.75rem center; - padding-right: 32px; -} - -.admin-form-select:focus { - border-color: var(--accent-color); - box-shadow: 0 0 0 3px var(--accent-light); -} - -.admin-form-select option { - background: var(--bg-secondary); - color: var(--text-primary); -} - -/* Textarea */ -.admin-form-textarea { - width: 100%; - padding: 9px 12px; - background: var(--input-bg); - border: 1px solid var(--border-color); - border-radius: var(--border-radius-sm); - color: var(--text-primary); - font-size: 13px; - font-family: inherit; - outline: none; - transition: - border-color 0.3s cubic-bezier(0.4, 0, 0.2, 1), - box-shadow 0.3s cubic-bezier(0.4, 0, 0.2, 1); - resize: vertical; - box-sizing: border-box; - min-height: 80px; -} - -.admin-form-textarea:focus { - border-color: var(--accent-color); - box-shadow: 0 0 0 3px var(--accent-light); -} - -/* Checkbox */ -.admin-form-checkbox { - display: inline-flex; - align-items: flex-start; - gap: 0; - cursor: pointer; - user-select: none; -} - -.admin-form-checkbox input { - position: absolute; - opacity: 0; - width: 0; - height: 0; - pointer-events: none; -} - -.admin-form-checkbox input + span::before { - content: ""; - display: inline-flex; - align-items: center; - justify-content: center; - width: 16px; - height: 16px; - margin-right: 8px; - background: var(--input-bg); - border: 1px solid var(--border-color); - border-radius: 4px; - vertical-align: middle; - transition: - border-color var(--transition), - box-shadow var(--transition), - background var(--transition); - flex-shrink: 0; -} - -.admin-form-checkbox input:checked + span::before { - background: var(--accent-color); - border-color: var(--accent-color); - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E"); - background-size: 12px; - background-position: center; - background-repeat: no-repeat; -} - -.admin-form-checkbox input:focus + span::before { - border-color: var(--accent-color); - box-shadow: 0 0 0 3px var(--accent-light); -} - -.admin-form-checkbox:hover - input:not(:checked):not(:disabled):not(:indeterminate) - + span::before { - border-color: var(--border-color-hover); - background: var(--bg-secondary); -} - -.admin-form-checkbox input:indeterminate + span::before { - background: var(--accent-color); - border-color: var(--accent-color); - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3' stroke-linecap='round'%3E%3Cline x1='6' y1='12' x2='18' y2='12'%3E%3C/line%3E%3C/svg%3E"); - background-size: 12px; - background-position: center; - background-repeat: no-repeat; -} - -.admin-form-checkbox input:disabled + span::before { - opacity: 0.5; - cursor: not-allowed; -} - -.admin-form-checkbox:has(input:disabled) { - cursor: not-allowed; - opacity: 0.7; -} - -.admin-form-checkbox span { - display: flex; - align-items: center; - font-size: 13px; - color: var(--text-secondary); - line-height: 1.4; -} - -/* Reorderable List */ -.admin-reorder-list { - display: flex; - flex-direction: column; - gap: 2px; -} - -.admin-reorder-item { - display: flex; - align-items: center; - gap: 8px; - padding: 5px 8px; - background: var(--bg-tertiary); - border-radius: var(--border-radius-sm); -} - -.admin-reorder-arrows { - display: flex; - gap: 2px; -} - -.admin-reorder-label { - font-size: 13px; - color: var(--text-primary); -} - -.admin-reorder-label.accent { - color: var(--accent-color); -} - -.admin-reorder-arrows .admin-btn-icon { - width: 22px; - height: 22px; - color: var(--text-muted); -} - -.admin-reorder-arrows .admin-btn-icon:hover:not(:disabled) { - background: var(--bg-primary); - color: var(--text-primary); -} - -.admin-reorder-arrows .admin-btn-icon:disabled { - opacity: 0.25; -} - -/* Form Rows (Grid Layouts) */ -.admin-form-row { - display: grid; - gap: 1rem; - grid-template-columns: repeat(2, 1fr); -} - -.admin-form-row-3 { - grid-template-columns: repeat(3, 1fr); -} - -.admin-form-row-4 { - grid-template-columns: repeat(4, 1fr); -} - -.admin-form-row-5 { - grid-template-columns: 1.2fr 1fr 1fr 1fr 1fr; -} - -@media (max-width: 768px) { - .admin-form-row-4 { - grid-template-columns: repeat(2, 1fr); - } - .admin-form-row-5 { - grid-template-columns: repeat(3, 1fr); - } -} - -@media (max-width: 640px) { - .admin-form-row, - .admin-form-row-3 { - grid-template-columns: 1fr; - } - .admin-form-row-5 { - grid-template-columns: repeat(2, 1fr); - } -} - -@media (max-width: 480px) { - .admin-form-row-4, - .admin-form-row-5 { - grid-template-columns: 1fr; - } -} - -/* Form Utilities */ -.admin-form-hint { - font-size: 0.75rem; - color: var(--text-muted); - margin-top: 0.25rem; -} - -/* Required field indicator */ -.admin-form-label.required::after { - content: " *"; - color: var(--danger); - font-weight: 600; -} - -/* Inline field errors */ -.admin-form-group.has-error .admin-form-input, -.admin-form-group.has-error .admin-form-select, -.admin-form-group.has-error .admin-form-textarea { - border-color: var(--danger); - box-shadow: 0 0 0 3px var(--danger-light); -} - -.admin-form-group.has-error .admin-form-label { - color: var(--danger); -} - -.admin-form-error { - font-size: 0.75rem; - color: var(--danger); - margin-top: 0.25rem; - display: flex; - align-items: center; - gap: 0.25rem; -} - -/* Monospace for data values (times, dates, numbers, IDs) */ -.admin-mono { - font-family: var(--font-mono); - font-size: 0.875em; - letter-spacing: -0.01em; -} - -.admin-form-actions { - display: flex; - gap: 0.75rem; - justify-content: flex-end; - margin-top: 1.5rem; - padding-top: 1.5rem; - border-top: 1px solid var(--border-color); -} - -/* ============================================================================ - Buttons - ============================================================================ */ - -.admin-btn { - display: inline-flex; - align-items: center; - justify-content: center; - gap: 0.5rem; - padding: 8px 14px; - border: none; - border-radius: var(--border-radius-sm); - font-size: 13px; - font-weight: 550; - font-family: inherit; - cursor: pointer; - transition: var(--transition); - white-space: nowrap; -} - -.admin-btn:disabled { - opacity: 0.7; - cursor: not-allowed; -} - -/* Prevent buttons from growing when text changes to spinner + loading text */ -.admin-modal-footer .admin-btn { - min-width: 100px; -} -.admin-modal-footer .admin-btn .admin-spinner { - margin: -2px 0; -} - -.admin-btn-sm { - padding: 6px 11px; - font-size: 12px; -} - -.admin-btn-primary { - background: var(--accent-color); - color: #fff; -} - -.admin-btn-primary:hover:not(:disabled) { - background: var(--accent-hover); - transform: translateY(-1px); - box-shadow: 0 4px 12px rgba(214, 48, 49, 0.3); -} - -.admin-btn .admin-spinner { - width: 16px; - height: 16px; - border-width: 2px; -} - -.admin-btn-primary .admin-spinner { - border-color: rgba(255, 255, 255, 0.3); - border-top-color: #fff; -} - -.admin-btn-secondary .admin-spinner { - border-color: rgba(var(--text-secondary-rgb, 107, 114, 128), 0.3); - border-top-color: var(--text-secondary); -} - -.admin-btn-secondary { - background: var(--bg-tertiary); - border: 1px solid var(--border-color); - color: var(--text-secondary); -} - -.admin-btn-secondary:hover:not(:disabled) { - background: var(--bg-secondary); - border-color: var(--border-color-hover); - color: var(--text-primary); -} - -.admin-btn-icon { - display: inline-flex; - align-items: center; - justify-content: center; - padding: 0; - width: 32px; - height: 32px; - background: transparent; - border: none; - color: var(--text-secondary); - border-radius: var(--border-radius-sm); - cursor: pointer; - transition: var(--transition); -} - -.admin-btn-icon:hover { - background: var(--bg-tertiary); - color: var(--text-primary); -} - -.admin-btn-icon.accent { - color: var(--info); -} - -.admin-btn-icon.accent:hover { - background: color-mix(in srgb, var(--info) 15%, transparent); - color: var(--info); -} - -.admin-btn-icon.danger { - color: var(--danger); -} - -.admin-btn-icon.danger:hover { - background: var(--danger-light); -} - -/* ============================================================================ - Layout - ============================================================================ */ - -.admin-layout { - display: flex; - min-height: 100vh; - min-height: 100dvh; - background: var(--bg-primary); -} - -@media (min-width: 1024px) { - .admin-layout { - align-items: flex-start; - } -} - -/* ============================================================================ - Sidebar - ============================================================================ */ - -/* -- Theme variables for sidebar -- */ -[data-theme="dark"] .admin-sidebar { - --sb-bg: #141414; - --sb-border: #2a2a2a; - --sb-text: #a0a0a0; - --sb-text-hover: #ddd; - --sb-hover-bg: #1f1f1f; - --sb-active-bg: #ffffff; - --sb-active-text: #141414; - --sb-label: #444; - --sb-muted: #555; - --sb-scrollbar: #333; -} - -[data-theme="light"] .admin-sidebar { - --sb-bg: #ffffff; - --sb-border: #e8e6e1; - --sb-text: #7c7c84; - --sb-text-hover: #1a1a1a; - --sb-hover-bg: #f5f4f2; - --sb-active-bg: #141414; - --sb-active-text: #ffffff; - --sb-label: #a0a0a0; - --sb-muted: #a0a0a0; - --sb-scrollbar: #ddd; -} - -.admin-sidebar { - position: fixed; - top: 0; - left: 0; - right: 0; - bottom: 0; - width: 100%; - height: 100vh; - height: 100dvh; - z-index: 50; - background: var(--sb-bg); - border-right: 1px solid var(--sb-border); - display: flex; - flex-direction: column; - padding-top: env(safe-area-inset-top, 0px); - padding-bottom: env(safe-area-inset-bottom, 0px); - padding-left: env(safe-area-inset-left, 0px); - padding-right: env(safe-area-inset-right, 0px); - transform: translateX(-100%); - visibility: hidden; - transition: - transform 0.3s ease, - visibility 0.3s ease; - overflow: hidden; - overscroll-behavior: none; -} - -.admin-sidebar.open { - transform: translateX(0); - visibility: visible; - touch-action: none; -} - -@media (min-width: 1024px) { - .admin-sidebar { - right: auto; - width: 220px; - height: 100%; - transform: none; - visibility: visible; - padding: 0; - } -} - -[data-theme="light"] .admin-sidebar { - box-shadow: - 1px 0 0 0 var(--sb-border), - 4px 0 16px rgba(0, 0, 0, 0.04); -} - -/* Sidebar Overlay (mobile) */ -.admin-sidebar-overlay { - display: none; - position: fixed; - inset: 0; - background: rgba(0, 0, 0, 0.5); - z-index: 49; - backdrop-filter: blur(2px); -} - -.admin-sidebar-overlay.open { - display: block; -} - -@media (min-width: 1024px) { - .admin-sidebar-overlay { - display: none !important; - } -} - -/* Sidebar Header */ -.admin-sidebar-header { - padding: 0 18px; - height: 73px; - border-bottom: 1px solid var(--sb-border); - display: flex; - align-items: center; - justify-content: space-between; - flex-shrink: 0; -} - -.admin-sidebar-logo { - height: 28px; - width: auto; -} - -.admin-sidebar-close { - display: block; - padding: 0.5rem; - background: transparent; - border: none; - color: var(--sb-text); - cursor: pointer; - border-radius: 6px; -} - -.admin-sidebar-close:hover { - background: var(--sb-hover-bg); - color: var(--sb-text-hover); -} - -@media (min-width: 1024px) { - .admin-sidebar-close { - display: none; - } -} - -/* Sidebar Navigation */ -.admin-sidebar-nav { - flex: 1; - min-height: 0; - overflow-y: auto; - -webkit-overflow-scrolling: touch; - overscroll-behavior: contain; - padding: 4px 0; -} - -.admin-sidebar-nav::-webkit-scrollbar { - width: 5px; -} - -.admin-sidebar-nav::-webkit-scrollbar-track { - background: transparent; -} - -.admin-sidebar-nav::-webkit-scrollbar-thumb { - background: var(--sb-scrollbar); - border-radius: 99px; -} - -/* Nav Section */ -.admin-nav-section { - padding: 14px 10px 6px; -} - -.admin-nav-label { - font-size: 10px; - font-weight: 600; - letter-spacing: 1px; - text-transform: uppercase; - color: var(--sb-label); - padding: 0 8px; - margin-bottom: 4px; -} - -/* Nav Item */ -.admin-nav-item { - display: flex; - align-items: center; - gap: 9px; - padding: 7px 10px; - border-radius: 7px; - color: var(--sb-text); - cursor: pointer; - transition: all 0.15s ease; - font-size: 13px; - font-weight: 450; - margin-bottom: 1px; - text-decoration: none; - user-select: none; -} - -.admin-nav-item:hover { - background: var(--sb-hover-bg); - color: var(--sb-text-hover); -} - -.admin-nav-item.active { - background: var(--sb-active-bg); - color: var(--sb-active-text); - font-weight: 600; -} - -.admin-nav-item.active svg { - color: var(--accent-color); -} - -.admin-nav-item svg { - width: 16px; - height: 16px; - flex-shrink: 0; -} - -@media (max-width: 1023px) { - .admin-nav-item { - padding: 10px 12px; - font-size: 15px; - gap: 10px; - } - - .admin-nav-item svg { - width: 18px; - height: 18px; - } -} - -/* Sidebar Footer */ -.admin-sidebar-footer { - margin-top: auto; - border-top: 1px solid var(--sb-border); - padding: 14px 10px; - flex-shrink: 0; -} - -.admin-user-chip { - display: flex; - align-items: center; - gap: 10px; - padding: 8px; - border-radius: 8px; - margin-bottom: 4px; -} - -.admin-user-avatar { - width: 32px; - height: 32px; - border-radius: 50%; - background: var(--accent-color); - color: #fff; - display: flex; - align-items: center; - justify-content: center; - font-weight: 700; - font-size: 12px; - flex-shrink: 0; -} - -.admin-user-details { - flex: 1; - min-width: 0; -} - -.admin-user-name { - color: var(--sb-text-hover); - font-size: 13px; - font-weight: 500; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.admin-user-role { - color: var(--sb-muted); - font-size: 11px; -} - -.admin-logout-btn { - display: flex; - align-items: center; - justify-content: center; - gap: 8px; - width: 100%; - padding: 7px 10px; - background: transparent; - border: none; - color: var(--sb-text); - cursor: pointer; - border-radius: 7px; - font-size: 12px; - font-family: inherit; - transition: all 0.15s ease; -} - -.admin-logout-btn:hover { - background: var(--sb-hover-bg); - color: var(--sb-text-hover); -} - -.admin-logout-btn svg { - width: 16px; - height: 16px; - flex-shrink: 0; -} - -@media (max-width: 480px) { - .admin-sidebar-footer { - padding: 10px 8px; - } - - .admin-user-chip { - padding: 6px; - } - - .admin-logout-btn { - padding: 8px; - font-size: 13px; - } -} - -/* ============================================================================ - Main Content Area - ============================================================================ */ - -.admin-main { - flex: 1; - min-width: 0; - min-height: 100vh; - min-height: 100dvh; - display: flex; - flex-direction: column; -} - -@media (min-width: 1024px) { - .admin-main { - margin-left: 220px; - } -} - -/* Header */ -.admin-header { - position: fixed; - top: 0; - left: 0; - right: 0; - z-index: 30; - height: calc(73px + env(safe-area-inset-top, 0px)); - background: var(--bg-secondary); - border-bottom: 1px solid var(--border-color); - display: flex; - align-items: center; - justify-content: space-between; - padding: 0 1rem; - padding-top: env(safe-area-inset-top, 0px); -} - -@media (min-width: 1024px) { - .admin-header { - left: 220px; - padding: 0 1.5rem; - } -} - -.admin-menu-btn { - display: block; - padding: 0.5rem; - background: transparent; - border: none; - color: var(--text-secondary); - cursor: pointer; - border-radius: var(--border-radius-sm); -} - -.admin-menu-btn:hover { - background: var(--bg-tertiary); -} - -@media (min-width: 1024px) { - .admin-menu-btn { - display: none; - } -} - -.admin-header-theme-btn { - display: flex; - align-items: center; - justify-content: center; - width: 40px; - height: 40px; - padding: 0; - background: var(--bg-tertiary); - border: 1px solid var(--border-color); - color: var(--text-secondary); - cursor: pointer; - border-radius: 50%; - transition: var(--transition); - position: relative; - overflow: hidden; -} - -.admin-header-theme-btn:hover { - background: var(--bg-tertiary); - border-color: var(--border-color-hover); - transform: scale(1.05); -} - -.admin-theme-icon { - position: absolute; - display: flex; - align-items: center; - justify-content: center; - color: var(--text-primary); - transition: all 0.3s ease; - opacity: 0; - transform: rotate(180deg) scale(0.5); -} - -.admin-theme-icon.visible { - opacity: 1; - transform: rotate(0) scale(1); -} - -/* Content */ -.admin-content { - flex: 1; - padding: 1rem; - padding-top: calc(73px + 1rem + env(safe-area-inset-top, 0px)); -} - -@media (min-width: 1024px) { - .admin-content { - padding: 28px 32px; - padding-top: calc(73px + 28px); - } -} - -/* ============================================================================ - Page Headers - ============================================================================ */ - -.admin-page-header { - display: flex; - flex-direction: column; - gap: 0.5rem; - margin-bottom: 1rem; -} - -@media (min-width: 640px) { - .admin-page-header { - flex-direction: row; - align-items: center; - justify-content: space-between; - } -} - -.admin-page-title { - font-size: 22px; - font-weight: 700; - color: var(--text-primary); - font-family: var(--font-heading); - margin-bottom: 0.25rem; -} - -.admin-page-subtitle { - color: var(--text-secondary); - font-size: 13px; -} - -.admin-page-actions { - display: flex; - gap: 0.75rem; - flex-wrap: wrap; -} - -@media (max-width: 640px) { - .admin-page-actions { - width: 100%; - } - - .admin-page-actions .admin-btn { - flex: 1; - } -} - -/* ============================================================================ - Cards - ============================================================================ */ - -.admin-card { - background: var(--card-bg); - border: 1px solid var(--glass-border); - box-shadow: var(--glass-shadow); - border-radius: var(--border-radius); - overflow: hidden; - margin-bottom: 1rem; -} - -.admin-card:last-child { - margin-bottom: 0; -} - -.admin-card-header { - padding: 14px 18px; - border-bottom: 1px solid var(--border-color); -} - -.admin-card-title { - font-size: 14px; - font-weight: 650; - color: var(--text-primary); - margin: 0 0 12px 0; -} - -.admin-card-body { - padding: 18px; -} - -/* ============================================================================ - Grid System - ============================================================================ */ - -.admin-grid { - display: grid; - gap: 1rem; -} - -.admin-grid > .admin-card { - margin-bottom: 0; -} - -.admin-grid-3 { - grid-template-columns: 1fr; -} - -@media (min-width: 640px) { - .admin-grid-3 { - grid-template-columns: repeat(2, 1fr); - } -} - -@media (min-width: 1024px) { - .admin-grid-3 { - grid-template-columns: repeat(3, 1fr); - } -} - -.admin-grid-4 { - grid-template-columns: repeat(2, 1fr); -} - -@media (min-width: 768px) { - .admin-grid-4 { - grid-template-columns: repeat(4, 1fr); - } -} - -/* ============================================================================ - Tables - ============================================================================ */ - -.admin-table-wrapper, -.admin-table-responsive { - overflow-x: auto; - -webkit-overflow-scrolling: touch; -} - -.admin-table { - width: 100%; - min-width: 650px; - border-collapse: collapse; -} - -.admin-table th { - text-align: left; - padding: 10px 16px; - font-size: 11px; - font-weight: 600; - color: var(--text-muted); - text-transform: uppercase; - letter-spacing: 0.05em; - border-bottom: 1px solid var(--border-color); - white-space: nowrap; -} - -.admin-table td { - padding: 11px 16px; - border-bottom: 1px solid var(--border-color); - color: var(--text-secondary); - font-size: 13px; - line-height: 1.5; - white-space: nowrap; -} - -.admin-table tr:last-child td { - border-bottom: none; -} - -@media (max-width: 768px) { - .admin-table th, - .admin-table td { - padding: 8px 10px; - font-size: 12px; - } - - .admin-table th { - font-size: 10px; - } - - .admin-table-avatar { - width: 32px; - height: 32px; - font-size: 11px; - } - - .admin-table-name { - font-size: 12px; - } - - .admin-table-username { - font-size: 11px; - } -} - -.admin-table-user { - display: flex; - align-items: center; - gap: 0.75rem; - white-space: nowrap; -} - -.admin-table-avatar { - width: 34px; - height: 34px; - border-radius: 50%; - background: var(--accent-light); - color: var(--accent-color); - display: flex; - align-items: center; - justify-content: center; - font-weight: 600; - font-size: 12px; -} - -.admin-table-name { - font-weight: 500; - color: var(--text-primary); - white-space: nowrap; -} - -.admin-table-username { - font-size: 13px; - color: var(--text-muted); - white-space: nowrap; -} - -.admin-table-actions { - display: flex; - align-items: center; - gap: 0.5rem; -} - -/* ============================================================================ - Badges - ============================================================================ */ - -.admin-badge { - display: inline-flex; - align-items: center; - gap: 0.375rem; - padding: 3px 9px; - border-radius: 9999px; - font-size: 11.5px; - font-weight: 600; - border: none; - font-family: inherit; - white-space: nowrap; - max-width: 100%; -} - -.admin-badge-wrap { - white-space: normal; - word-break: break-word; - border-radius: var(--border-radius-sm); - text-align: left; -} - -.admin-badge-admin { - background: var(--accent-soft); - color: var(--accent-color); -} - -.admin-badge-viewer { - background: var(--bg-tertiary); - color: var(--text-secondary); -} - -.admin-badge-active { - background: var(--success-soft); - color: var(--success); - cursor: pointer; - transition: var(--transition); -} - -.admin-badge-active:hover { - background: color-mix(in srgb, var(--success) 20%, transparent); -} - -.admin-badge-inactive { - background: var(--danger-soft); - color: var(--danger); - cursor: pointer; - transition: var(--transition); -} - -.admin-badge-inactive:hover { - background: color-mix(in srgb, var(--danger) 20%, transparent); -} - -.admin-badge-success { - background: var(--success-soft); - color: var(--success); -} - -.admin-badge-warning { - background: var(--warning-soft); - color: var(--warning); -} - -.admin-badge-secondary { - background: var(--bg-tertiary); - color: var(--text-muted); -} - -.admin-badge-info { - background: var(--info-soft); - color: var(--info); -} - -.admin-badge-danger { - background: var(--danger-soft); - color: var(--danger); -} - -/* Status Badges - Leave Requests */ -.badge-pending { - background: color-mix(in srgb, var(--warning) 15%, transparent); - color: var(--warning); -} -.badge-approved { - background: color-mix(in srgb, var(--success) 15%, transparent); - color: var(--success); -} -.badge-rejected { - background: color-mix(in srgb, var(--danger) 15%, transparent); - color: var(--danger); -} -.badge-cancelled { - background: var(--muted-light); - color: var(--muted); -} - -/* Status Badges - Orders */ -.admin-badge-order-prijata { - background: color-mix(in srgb, var(--info) 15%, transparent); - color: var(--info); -} -.admin-badge-order-realizace { - background: color-mix(in srgb, var(--warning) 15%, transparent); - color: var(--warning); -} -.admin-badge-order-dokoncena { - background: color-mix(in srgb, var(--success) 15%, transparent); - color: var(--success); -} -.admin-badge-order-stornovana { - background: color-mix(in srgb, var(--danger) 15%, transparent); - color: var(--danger); -} - -/* Status Badges - Projects */ -.admin-badge-project-aktivni { - background: color-mix(in srgb, var(--success) 15%, transparent); - color: var(--success); -} -.admin-badge-project-dokonceny { - background: color-mix(in srgb, var(--info) 15%, transparent); - color: var(--info); -} -.admin-badge-project-zruseny { - background: color-mix(in srgb, var(--danger) 15%, transparent); - color: var(--danger); -} - -/* ============================================================================ - Modals - ============================================================================ */ - -.admin-modal-overlay { - position: fixed; - inset: 0; - z-index: 50; - display: flex; - align-items: center; - justify-content: center; - padding: 1rem; - overflow: hidden; - overscroll-behavior: none; - touch-action: none; -} - -.admin-modal-backdrop { - position: absolute; - inset: 0; - background: rgba(0, 0, 0, 0.6); - touch-action: none; -} - -.admin-modal { - position: relative; - width: 100%; - max-width: 480px; - background: var(--bg-secondary); - border: 1px solid var(--border-color); - border-radius: var(--border-radius); - max-height: calc(100vh - 2rem); - max-height: calc(100dvh - 2rem); - overflow: hidden; - display: flex; - flex-direction: column; - touch-action: auto; -} - -.admin-modal-lg { - max-width: 900px; -} - -.admin-modal-header { - padding: 18px; - border-bottom: 1px solid var(--border-color); - flex-shrink: 0; -} - -.admin-modal-title { - font-size: 16px; - font-weight: 700; - color: var(--text-primary); -} - -.admin-modal-body { - padding: 18px; - overflow-y: auto; - flex: 1; - -webkit-overflow-scrolling: touch; - overscroll-behavior: contain; - background: var(--bg-primary); -} - -.admin-modal-footer { - padding: 14px 18px; - border-top: 1px solid var(--border-color); - display: flex; - gap: 0.75rem; - justify-content: flex-end; - flex-shrink: 0; -} - -@media (max-width: 768px) { - .admin-modal-overlay { - padding: 0; - } - - .admin-modal, - .admin-modal.admin-modal-lg { - max-width: 100%; - width: 100%; - height: 100%; - height: 100dvh; - max-height: 100%; - max-height: 100dvh; - border-radius: 0; - border: none; - } - - .admin-modal-header { - padding: 1rem; - padding-top: calc(1rem + env(safe-area-inset-top, 0px)); - } - - .admin-modal-body { - padding: 1rem; - flex: 1; - overflow-y: auto; - overflow-x: hidden; - -webkit-overflow-scrolling: touch; - } - - .admin-modal-footer { - padding: 1rem; - padding-bottom: calc(1rem + env(safe-area-inset-bottom, 0px)); - } - - .admin-modal .admin-form-input, - .admin-modal .admin-form-select, - .admin-modal .admin-form-textarea { - max-width: 100%; - } -} - -/* Confirm Modal */ -.admin-confirm-modal { - max-width: 400px; -} - -.admin-confirm-content { - text-align: center; - padding: 2rem 1.5rem; -} - -.admin-confirm-icon { - width: 56px; - height: 56px; - border-radius: 50%; - display: flex; - align-items: center; - justify-content: center; - margin: 0 auto 1.25rem; -} - -.admin-confirm-icon-danger { - background: var(--danger-light); - color: var(--danger); -} - -.admin-confirm-icon-warning { - background: var(--warning-light); - color: var(--warning); -} - -.admin-confirm-icon-info { - background: var(--info-light); - color: var(--info); -} - -.admin-confirm-icon-default { - background: var(--bg-tertiary); - color: var(--text-secondary); -} - -.admin-confirm-title { - font-size: 1.25rem; - font-weight: 700; - color: var(--text-primary); - margin-bottom: 0.5rem; -} - -.admin-confirm-message { - color: var(--text-secondary); - font-size: 0.95rem; - line-height: 1.5; -} - -@media (max-width: 768px) { - .admin-confirm-modal { - max-width: 100%; - height: auto; - max-height: calc(100% - 2rem); - max-height: calc(100dvh - 2rem); - margin: 1rem; - border-radius: var(--border-radius); - border: 1px solid var(--border-color); - } - - .admin-confirm-modal .admin-modal-footer { - padding-bottom: calc(1rem + env(safe-area-inset-bottom, 0px)); - } -} - -/* ============================================================================ - Toast Alerts - ============================================================================ */ - -.admin-alert-container { - position: fixed; - bottom: calc(1rem + env(safe-area-inset-bottom, 0px)); - right: 1rem; - z-index: 100; - display: flex; - flex-direction: column-reverse; - gap: 0.5rem; - max-width: 400px; - width: calc(100% - 2rem); - pointer-events: none; - transform: translateZ(0); -} - -@media (min-width: 640px) { - .admin-alert-container { - bottom: calc(1.5rem + env(safe-area-inset-bottom, 0px)); - right: 1.5rem; - } -} - -.admin-toast { - display: flex; - align-items: center; - gap: 0.75rem; - padding: 0.875rem 1rem; - border-radius: var(--border-radius-sm); - background: var(--bg-secondary); - border: 1px solid var(--border-color); - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); - pointer-events: auto; -} - -.admin-toast-icon { - flex-shrink: 0; - display: flex; - align-items: center; - justify-content: center; -} - -.admin-toast-message { - flex: 1; - font-size: 0.875rem; - color: var(--text-primary); -} - -.admin-toast-close { - flex-shrink: 0; - padding: 0.25rem; - background: transparent; - border: none; - color: var(--text-muted); - cursor: pointer; - border-radius: var(--border-radius-sm); - transition: var(--transition); -} - -.admin-toast-close:hover { - background: var(--bg-tertiary); - color: var(--text-primary); -} - -.admin-toast-success .admin-toast-icon { - color: var(--success); -} -.admin-toast-error .admin-toast-icon { - color: var(--danger); -} -.admin-toast-warning .admin-toast-icon { - color: var(--warning); -} -.admin-toast-info .admin-toast-icon { - color: var(--info); -} - -/* ============================================================================ - Loading & Animations - ============================================================================ */ - -.admin-spinner { - width: 32px; - height: 32px; - border: 2px solid var(--accent-color); - border-top-color: transparent; - border-radius: 50%; - animation: spin 0.8s linear infinite; -} - -.admin-loading { - display: flex; - align-items: center; - justify-content: center; - min-height: 256px; -} - -@keyframes spin { - to { - transform: rotate(360deg); - } -} - -@keyframes float { - 0%, - 100% { - transform: translate(0, 0); - } - 50% { - transform: translate(30px, -30px); - } -} - -@keyframes pulse { - 0%, - 100% { - opacity: 1; - } - 50% { - opacity: 0.5; - } -} - -@keyframes shimmer { - 0% { - background-position: -200% 0; - } - 100% { - background-position: 200% 0; - } -} - -/* ============================================================================ - Skeleton Loading - ============================================================================ */ - -.admin-skeleton { - display: flex; - flex-direction: column; - gap: 1rem; - padding: 1.5rem; - opacity: 0; - animation: skeleton-fade-in 0.15s ease 0.08s forwards; -} - -@keyframes skeleton-fade-in { - to { - opacity: 1; - } -} - -.admin-skeleton-row { - display: flex; - gap: 1rem; - align-items: center; -} - -.admin-skeleton-line { - height: 14px; - border-radius: 6px; - background: linear-gradient( - 90deg, - var(--bg-tertiary) 25%, - var(--border-color) 50%, - var(--bg-tertiary) 75% - ); - background-size: 200% 100%; - animation: shimmer 1.2s ease-in-out infinite; -} - -.admin-skeleton-line.w-full { - width: 100%; -} -.admin-skeleton-line.w-3\/4 { - width: 75%; -} -.admin-skeleton-line.w-1\/2 { - width: 50%; -} -.admin-skeleton-line.w-1\/3 { - width: 33%; -} -.admin-skeleton-line.w-1\/4 { - width: 25%; -} -.admin-skeleton-line.h-8 { - height: 32px; -} -.admin-skeleton-line.h-10 { - height: 40px; -} -.admin-skeleton-line.circle { - width: 40px; - height: 40px; - border-radius: 50%; - flex-shrink: 0; -} - -/* ============================================================================ - Tabs (Global) - ============================================================================ */ - -.admin-tabs { - display: inline-flex; - gap: 4px; - padding: 4px; - background: var(--bg-tertiary); - border: 1px solid var(--border-color); - border-radius: 0.625rem; -} - -.admin-tab { - position: relative; - display: inline-flex; - align-items: center; - gap: 0.5rem; - padding: 0.5rem 1.25rem; - background: transparent; - border: none; - border-radius: 0.5rem; - color: var(--text-muted); - font-size: 0.8125rem; - font-weight: 500; - font-family: inherit; - cursor: pointer; - transition: - color 0.2s ease, - background 0.2s ease, - box-shadow 0.2s ease; - letter-spacing: 0.01em; - white-space: nowrap; -} - -.admin-tab:hover { - color: var(--text-primary); -} - -.admin-tab.active { - color: var(--text-primary); - font-weight: 600; - background: var(--bg-secondary); - box-shadow: - 0 1px 3px rgba(0, 0, 0, 0.12), - 0 0 0 1px var(--border-color); -} - -/* ============================================================================ - Empty State - ============================================================================ */ - -.admin-empty-state { - display: flex; - flex-direction: column; - align-items: center; - text-align: center; - padding: 3rem 1.5rem; - color: var(--text-secondary); -} - -.admin-empty-icon { - width: 64px; - height: 64px; - border-radius: 50%; - background: var(--bg-tertiary); - color: var(--text-muted); - display: flex; - align-items: center; - justify-content: center; - margin-bottom: 1.25rem; -} - -.admin-empty-state p { - margin-bottom: 1rem; - font-size: 0.95rem; - max-width: 320px; -} - -.admin-role-locked-notice { - display: flex; - align-items: center; - gap: 0.5rem; - padding: 0.75rem 1rem; - background: var(--warning-light); - border: 1px solid color-mix(in srgb, var(--warning) 25%, transparent); - border-radius: 0.5rem; - color: var(--warning); - font-size: 0.875rem; - margin-bottom: 0.5rem; -} - -/* ============================================================================ - React DatePicker Overrides - ============================================================================ */ - -.react-datepicker-wrapper { - width: 100%; -} - -.react-datepicker-popper { - z-index: 100 !important; -} - -.react-datepicker { - font-family: inherit !important; - background-color: var(--bg-secondary) !important; - border: 1px solid var(--border-color) !important; - border-radius: var(--border-radius-sm) !important; - box-shadow: 0 8px 32px rgba(0, 0, 0, 0.25) !important; - color: var(--text-primary) !important; - font-size: 0.875rem !important; -} - -.react-datepicker__triangle { - display: none !important; -} - -/* Header */ -.react-datepicker__header { - background-color: var(--bg-tertiary) !important; - border-bottom: 1px solid var(--border-color) !important; - padding-top: 0.75rem !important; -} - -.react-datepicker__current-month, -.react-datepicker-time__header { - color: var(--text-primary) !important; - font-weight: 600 !important; -} - -.react-datepicker__day-name { - color: var(--text-secondary) !important; -} - -/* Days */ -.react-datepicker__day { - color: var(--text-primary) !important; - border-radius: 6px !important; - transition: - background 0.15s, - color 0.15s !important; -} - -.react-datepicker__day:hover { - background-color: var(--accent-light) !important; - color: var(--text-primary) !important; -} - -.react-datepicker__day--selected, -.react-datepicker__day--keyboard-selected { - background-color: var(--accent-color) !important; - color: #fff !important; -} - -.react-datepicker__day--today { - font-weight: 700 !important; -} - -.react-datepicker__day--outside-month { - color: var(--text-muted) !important; - opacity: 0.5; -} - -.react-datepicker__day--disabled { - color: var(--text-muted) !important; - opacity: 0.3 !important; -} - -/* Navigation arrows */ -.react-datepicker__navigation { - top: 0.75rem !important; -} - -.react-datepicker__navigation-icon::before { - border-color: var(--text-secondary) !important; -} - -.react-datepicker__navigation:hover *::before { - border-color: var(--accent-color) !important; -} - -/* Year dropdown */ -.react-datepicker__year-dropdown, -.react-datepicker__month-dropdown, -.react-datepicker__year-read-view, -.react-datepicker__month-read-view { - color: var(--text-primary) !important; -} - -/* Time picker */ -.react-datepicker__time-container { - border-left: 1px solid var(--border-color) !important; -} - -.react-datepicker__time-container .react-datepicker__time { - background-color: var(--bg-secondary) !important; -} - -.react-datepicker__time-container - .react-datepicker__time - .react-datepicker__time-box { - width: 100% !important; -} - -.react-datepicker__time-container - .react-datepicker__time - .react-datepicker__time-box - ul.react-datepicker__time-list - li.react-datepicker__time-list-item { - color: var(--text-primary) !important; - transition: background 0.15s !important; -} - -.react-datepicker__time-container - .react-datepicker__time - .react-datepicker__time-box - ul.react-datepicker__time-list - li.react-datepicker__time-list-item:hover { - background-color: var(--accent-light) !important; - color: var(--text-primary) !important; -} - -.react-datepicker__time-container - .react-datepicker__time - .react-datepicker__time-box - ul.react-datepicker__time-list - li.react-datepicker__time-list-item--selected { - background-color: var(--accent-color) !important; - color: #fff !important; - font-weight: 600 !important; -} - -/* Month picker */ -.react-datepicker__monthPicker { - background-color: var(--bg-secondary) !important; -} - -.react-datepicker-year-header { - background-color: var(--bg-tertiary) !important; - color: var(--text-primary) !important; - border-bottom: 1px solid var(--border-color) !important; -} - -.react-datepicker__month-wrapper { - background-color: var(--bg-secondary) !important; -} - -.react-datepicker__month-text { - color: var(--text-primary) !important; - padding: 0.5rem !important; - border-radius: 6px !important; - transition: background 0.15s !important; - background-color: transparent !important; -} - -.react-datepicker__month-text:hover { - background-color: var(--accent-light) !important; - color: var(--text-primary) !important; -} - -.react-datepicker__month-text--keyboard-selected, -.react-datepicker__month-text--selected { - background-color: var(--accent-color) !important; - color: #fff !important; -} - -.react-datepicker__month-text--today { - font-weight: 700 !important; -} - -/* Input */ -.react-datepicker__input-container input { - cursor: pointer; -} - -.react-datepicker__close-icon::after { - background-color: var(--accent-color) !important; -} - -/* Forbidden (403) */ - -.forbidden-page { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - min-height: 60vh; - text-align: center; - padding: 2rem; -} - -.forbidden-icon { - color: var(--accent-color); - margin-bottom: 1.5rem; - opacity: 0.8; -} - -.forbidden-title { - font-family: var(--font-heading); - font-size: 2rem; - font-weight: 700; - color: var(--text-primary); - margin: 0 0 0.75rem; -} - -.forbidden-text { - color: var(--text-secondary); - font-size: 1rem; - max-width: 400px; - line-height: 1.6; - margin: 0 0 2rem; -} - -.forbidden-link { - display: inline-flex; - align-items: center; - gap: 0.5rem; - padding: 0.75rem 1.5rem; - background: var(--accent-color); - color: #fff; - border-radius: var(--border-radius-sm); - text-decoration: none; - font-weight: 600; - transition: var(--transition); -} - -.forbidden-link:hover { - background: var(--accent-hover); - transform: translateY(-1px); -} - -/* ============================================================================ - Mobile Responsive Enhancements - ============================================================================ */ - -/* Touch targets - min 44px na mobilech */ -@media (max-width: 768px) { - .admin-btn { - min-height: 44px; - padding: 10px 16px; - } - - .admin-btn-sm { - min-height: 36px; - } - - .admin-btn-icon { - min-width: 44px; - min-height: 44px; - } - - .admin-form-input, - .admin-form-select, - .admin-form-textarea { - min-height: 44px; - font-size: 16px; /* prevent auto-zoom on iOS */ - } - - .admin-form-checkbox { - min-height: 44px; - padding: 8px 0; - } - - .admin-form-checkbox input + span::before { - width: 20px; - height: 20px; - } - - .admin-form-label { - font-size: 13px; - } -} - -/* Tabulky - kompaktnejsi na mobilech, lepsi scroll indikace */ -@media (max-width: 640px) { - .admin-table-wrapper, - .admin-table-responsive { - margin: 0 -1rem; - padding: 0 1rem; - position: relative; - } - - .admin-table { - min-width: 500px; - } - - .admin-table th, - .admin-table td { - padding: 8px; - font-size: 11px; - } - - .admin-table th { - font-size: 9px; - } - - .admin-table-actions { - gap: 0.25rem; - } -} - -/* Page header na mobilech */ -@media (max-width: 480px) { - .admin-page-title { - font-size: 18px; - } - - .admin-page-subtitle { - font-size: 12px; - } - - .admin-content { - padding: 12px !important; - padding-top: calc(73px + 12px + env(safe-area-inset-top, 0px)) !important; - } - - .admin-card-body { - padding: 12px; - } - - .admin-card-header { - padding: 12px; - } -} - -/* Grid - single column na malych mobilech */ -@media (max-width: 480px) { - .admin-grid-4 { - grid-template-columns: 1fr; - } -} - -/* Confirm modal - ne fullscreen na mobilech */ -@media (max-width: 480px) { - .admin-confirm-content { - padding: 1.5rem 1rem; - } - - .admin-confirm-title { - font-size: 1.1rem; - } - - .admin-confirm-message { - font-size: 0.875rem; - } -} - -/* Skeleton loading na mobilech */ -@media (max-width: 640px) { - .admin-skeleton { - border-radius: 4px; - } -} - -/* Badge na mobilech - vetsi pro touch */ -@media (max-width: 768px) { - .admin-badge { - padding: 4px 10px; - font-size: 12px; - } - - button.admin-badge { - min-height: 32px; - } -} - -/* Prefers reduced motion */ -@media (prefers-reduced-motion: reduce) { - *, - *::before, - *::after { - animation-duration: 0.01ms !important; - animation-iteration-count: 1 !important; - transition-duration: 0.01ms !important; - scroll-behavior: auto !important; - } -} - -/* Drag handle */ -.admin-drag-handle { - display: flex; - align-items: center; - justify-content: center; - width: 24px; - height: 24px; - border: none; - background: none; - color: var(--text-muted); - cursor: grab; - border-radius: 4px; - padding: 0; - transition: - color 0.15s, - background 0.15s; - touch-action: none; -} - -.admin-drag-handle:hover { - color: var(--text-primary); - background: var(--bg-secondary); -} - -.admin-drag-handle:active { - cursor: grabbing; -} - -/* ============================================================================ - Pagination - ============================================================================ */ - -.admin-pagination { - display: flex; - align-items: center; - justify-content: center; - gap: 0.75rem; - padding: 0.75rem 1rem; - margin-top: 0.5rem; - border-top: 1px solid var(--border-color); - font-size: 13px; -} - -.admin-pagination-info { - color: var(--text-muted); - font-family: var(--font-mono); - font-size: 12px; - white-space: nowrap; -} - -.admin-pagination-controls { - display: flex; - align-items: center; - gap: 2px; -} - -.admin-pagination-page { - display: inline-flex; - align-items: center; - justify-content: center; - min-width: 32px; - height: 32px; - padding: 0 6px; - border: 1px solid transparent; - border-radius: var(--border-radius-sm); - background: none; - color: var(--text-secondary); - font-size: 13px; - font-family: var(--font-mono); - cursor: pointer; - transition: - background 0.15s, - color 0.15s, - border-color 0.15s; -} - -.admin-pagination-page:hover { - background: var(--bg-secondary); - color: var(--text-primary); -} - -.admin-pagination-page.active { - background: var(--accent-color); - color: #fff; - border-color: var(--accent-color); - font-weight: 600; -} - -.admin-pagination-ellipsis { - display: inline-flex; - align-items: center; - justify-content: center; - width: 28px; - color: var(--text-muted); - font-size: 14px; -} - -.admin-pagination-select { - padding: 4px 8px; - border: 1px solid var(--border-color); - border-radius: var(--border-radius-sm); - background: var(--bg-primary); - color: var(--text-secondary); - font-size: 12px; - cursor: pointer; -} - -@media (max-width: 640px) { - .admin-pagination { - flex-wrap: wrap; - gap: 0.5rem; - } - - .admin-pagination-info { - order: 2; - width: 100%; - text-align: center; - } -} - -/* Error stack (DEV only) */ -.admin-error-stack { - max-width: 600px; - max-height: 200px; - overflow: auto; - padding: 0.75rem 1rem; - margin: 0; - border-radius: var(--border-radius-sm); - background: var(--bg-tertiary); - border: 1px solid var(--border-color); - color: var(--danger-color); - font-family: var(--font-mono); - font-size: 11px; - line-height: 1.5; - text-align: left; - white-space: pre-wrap; - word-break: break-word; -} - -/* Keyboard shortcut badge */ -.admin-kbd { - display: inline-block; - padding: 2px 7px; - font-family: var(--font-mono); - font-size: 12px; - line-height: 1.4; - border-radius: 4px; - background: var(--bg-secondary); - border: 1px solid var(--border-color); - white-space: nowrap; -} - -/* ============================================================================ - File Manager - ============================================================================ */ - -.fm-toolbar { - display: flex; - align-items: center; - justify-content: space-between; - gap: 0.75rem; - margin-bottom: 0.75rem; - flex-wrap: wrap; -} - -.fm-full-path { - font-family: var(--font-mono); - font-size: 11px; - color: var(--text-tertiary); - user-select: all; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - max-width: 100%; -} - -.fm-toolbar-actions { - display: flex; - gap: 0.5rem; - align-items: center; -} - -.fm-breadcrumb { - display: flex; - align-items: center; - flex-wrap: wrap; - gap: 0; - font-size: 12px; - min-height: 28px; -} - -.fm-breadcrumb-segment { - display: inline-flex; - align-items: center; -} - -.fm-breadcrumb-sep { - color: var(--text-tertiary); - margin: 0 4px; - user-select: none; -} - -.fm-breadcrumb-btn { - background: none; - border: none; - padding: 2px 6px; - border-radius: 4px; - color: var(--text-secondary); - cursor: pointer; - font-family: var(--font-mono); - font-size: 12px; - transition: all 0.15s ease; -} - -.fm-breadcrumb-btn:hover { - background: var(--bg-tertiary); - color: var(--text-primary); -} - -.fm-breadcrumb-btn.active { - color: var(--text-primary); - font-weight: 600; -} - -.fm-new-folder { - display: flex; - gap: 0.5rem; - align-items: center; - margin-bottom: 0.75rem; -} - -.fm-new-folder .admin-form-input { - max-width: 250px; -} - -.fm-content { - position: relative; - border-radius: var(--border-radius-sm); - transition: border-color 0.2s ease; -} - -.fm-content.fm-drag-over { - border: 2px dashed var(--accent-color); - background: var(--accent-light); -} - -.fm-dropzone-overlay { - position: absolute; - inset: 0; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - gap: 0.5rem; - background: color-mix(in srgb, var(--bg-primary) 90%, transparent); - border-radius: var(--border-radius-sm); - z-index: 5; - color: var(--accent-color); - font-size: 13px; - font-weight: 500; - pointer-events: none; -} - -.fm-empty { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - gap: 0.5rem; - padding: 2.5rem 1rem; - color: var(--text-tertiary); - font-size: 13px; -} - -.fm-folder-link { - background: none; - border: none; - padding: 0; - color: var(--accent-color); - font-weight: 500; - font-size: inherit; - font-family: inherit; - cursor: pointer; -} - -.fm-folder-link:hover { - text-decoration: underline; -} - -.fm-item-count { - font-size: 10px; - color: var(--text-tertiary); - font-weight: 400; -} - -.fm-file-name { - color: var(--text-primary); -} - -.fm-meta { - color: var(--text-secondary); - font-family: var(--font-mono); - font-size: 11px; -} - -.fm-actions { - display: inline-flex; - gap: 2px; - justify-content: flex-end; -} - -.fm-name-cell { - display: inline-flex; - align-items: center; - gap: 6px; -} - -.fm-symlink-badge { - display: inline-flex; - align-items: center; - color: var(--text-tertiary); - cursor: help; -} - -/* ============================================= - React DatePicker Overrides - ============================================= */ - -.react-datepicker-wrapper { - width: 100%; -} - -.react-datepicker-popper { - z-index: 100 !important; -} - -/* Prevent flash at top-left before popper calculates position */ -#datepicker-portal .react-datepicker-popper { - opacity: 0; - animation: dp-fade-in 0.01s forwards 0.02s; -} - -@keyframes dp-fade-in { - to { - opacity: 1; - } -} - -.react-datepicker { - font-family: inherit !important; - background-color: var(--bg-secondary) !important; - border: 1px solid var(--border-color) !important; - border-radius: var(--border-radius-sm) !important; - box-shadow: 0 8px 32px rgba(0, 0, 0, 0.25) !important; - color: var(--text-primary) !important; - font-size: 0.875rem !important; -} - -.react-datepicker__triangle { - display: none !important; -} - -.react-datepicker__header { - background-color: var(--bg-tertiary) !important; - border-bottom: 1px solid var(--border-color) !important; - padding-top: 0.75rem !important; -} - -.react-datepicker__current-month, -.react-datepicker-time__header { - color: var(--text-primary) !important; - font-weight: 600 !important; -} - -.react-datepicker__day-name { - color: var(--text-secondary) !important; -} - -.react-datepicker__day { - color: var(--text-primary) !important; - border-radius: 6px !important; - transition: - background 0.15s, - color 0.15s !important; -} - -.react-datepicker__day:hover { - background-color: var(--accent-light) !important; - color: var(--text-primary) !important; -} - -.react-datepicker__day--selected, -.react-datepicker__day--keyboard-selected { - background-color: var(--accent-color) !important; - color: #fff !important; -} - -.react-datepicker__day--today { - font-weight: 700 !important; -} - -.react-datepicker__day--outside-month { - color: var(--text-muted) !important; - opacity: 0.5; -} - -.react-datepicker__day--disabled { - color: var(--text-muted) !important; - opacity: 0.3 !important; -} - -.react-datepicker__navigation { - top: 0.75rem !important; -} - -.react-datepicker__navigation-icon::before { - border-color: var(--text-secondary) !important; -} - -.react-datepicker__navigation:hover *::before { - border-color: var(--accent-color) !important; -} - -.react-datepicker__year-dropdown, -.react-datepicker__month-dropdown, -.react-datepicker__year-read-view, -.react-datepicker__month-read-view { - color: var(--text-primary) !important; -} - -.react-datepicker__time-container { - border-left: 1px solid var(--border-color) !important; -} - -.react-datepicker__time-container .react-datepicker__time { - background-color: var(--bg-secondary) !important; -} - -.react-datepicker__time-container - .react-datepicker__time - .react-datepicker__time-box { - width: 100% !important; -} - -.react-datepicker__time-container - .react-datepicker__time - .react-datepicker__time-box - ul.react-datepicker__time-list - li.react-datepicker__time-list-item { - color: var(--text-primary) !important; - transition: background 0.15s !important; -} - -.react-datepicker__time-container - .react-datepicker__time - .react-datepicker__time-box - ul.react-datepicker__time-list - li.react-datepicker__time-list-item:hover { - background-color: var(--accent-light) !important; - color: var(--text-primary) !important; -} - -.react-datepicker__time-container - .react-datepicker__time - .react-datepicker__time-box - ul.react-datepicker__time-list - li.react-datepicker__time-list-item--selected { - background-color: var(--accent-color) !important; - color: #fff !important; - font-weight: 600 !important; -} - -.react-datepicker__monthPicker { - background-color: var(--bg-secondary) !important; -} - -.react-datepicker-year-header { - background-color: var(--bg-tertiary) !important; - color: var(--text-primary) !important; - border-bottom: 1px solid var(--border-color) !important; -} - -.react-datepicker__month-wrapper { - background-color: var(--bg-secondary) !important; -} - -.react-datepicker__month-text { - color: var(--text-primary) !important; - padding: 0.5rem !important; - border-radius: 6px !important; - transition: background 0.15s !important; - background-color: transparent !important; -} - -.react-datepicker__month-text:hover { - background-color: var(--accent-light) !important; - color: var(--text-primary) !important; -} - -.react-datepicker__month-text--keyboard-selected, -.react-datepicker__month-text--selected { - background-color: var(--accent-color) !important; - color: #fff !important; -} - -.react-datepicker__month-text--today { - font-weight: 700 !important; -} - -.react-datepicker__input-container input { - cursor: pointer; -} - -.react-datepicker__close-icon::after { - background-color: var(--accent-color) !important; -} - -/* ── File Manager ── */ - -.fm-toolbar { - display: flex; - align-items: center; - justify-content: space-between; - gap: 0.75rem; - margin-bottom: 0.75rem; - flex-wrap: wrap; -} - -.fm-full-path { - font-family: var(--font-mono); - font-size: 11px; - color: var(--text-tertiary); - user-select: all; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - max-width: 100%; -} - -.fm-toolbar-actions { - display: flex; - gap: 0.5rem; - align-items: center; -} - -.fm-breadcrumb { - display: flex; - align-items: center; - flex-wrap: wrap; - gap: 0; - font-size: 12px; - min-height: 28px; -} - -.fm-breadcrumb-segment { - display: inline-flex; - align-items: center; -} - -.fm-breadcrumb-sep { - color: var(--text-tertiary); - margin: 0 4px; - user-select: none; -} - -.fm-breadcrumb-btn { - background: none; - border: none; - padding: 2px 6px; - border-radius: 4px; - color: var(--text-secondary); - cursor: pointer; - font-family: var(--font-mono); - font-size: 12px; - transition: all 0.15s ease; -} - -.fm-breadcrumb-btn:hover { - background: var(--bg-tertiary); - color: var(--text-primary); -} - -.fm-breadcrumb-btn.active { - color: var(--text-primary); - font-weight: 600; -} - -.fm-new-folder { - display: flex; - gap: 0.5rem; - align-items: center; - margin-bottom: 0.75rem; -} - -.fm-new-folder .admin-form-input { - max-width: 250px; -} - -.fm-content { - position: relative; - border-radius: var(--border-radius-sm); - transition: border-color 0.2s ease; -} - -.fm-content.fm-drag-over { - border: 2px dashed var(--accent-color); - background: var(--accent-light); -} - -.fm-dropzone-overlay { - position: absolute; - inset: 0; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - gap: 0.5rem; - background: color-mix(in srgb, var(--bg-primary) 90%, transparent); - border-radius: var(--border-radius-sm); - z-index: 5; - color: var(--accent-color); - font-size: 13px; - font-weight: 500; - pointer-events: none; -} - -.fm-empty { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - gap: 0.5rem; - padding: 2.5rem 1rem; - color: var(--text-tertiary); - font-size: 13px; -} - -.fm-folder-link { - background: none; - border: none; - padding: 0; - color: var(--accent-color); - font-weight: 500; - font-size: inherit; - font-family: inherit; - cursor: pointer; -} - -.fm-folder-link:hover { - text-decoration: underline; -} - -.fm-item-count { - font-size: 10px; - color: var(--text-tertiary); - font-weight: 400; -} - -.fm-file-name { - color: var(--text-primary); -} - -.fm-meta { - color: var(--text-secondary); - font-family: var(--font-mono); - font-size: 11px; -} - -.fm-actions { - display: inline-flex; - gap: 2px; - justify-content: flex-end; -} - -.fm-name-cell { - display: inline-flex; - align-items: center; - gap: 6px; -} - -.fm-symlink-badge { - display: inline-flex; - align-items: center; - color: var(--text-tertiary); - cursor: help; -} diff --git a/src/admin/base.css b/src/admin/base.css new file mode 100644 index 0000000..17081f6 --- /dev/null +++ b/src/admin/base.css @@ -0,0 +1,415 @@ +/* ============================================================================ + Reset & Base + ============================================================================ */ + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +html { + scroll-behavior: smooth; + overflow-x: hidden; +} + +html, +body, +#root { + min-height: 100%; + min-height: 100dvh; + max-width: 100vw; +} + +body { + font-family: var(--font-body); + font-size: 16px; + line-height: 1.6; + color: var(--text-primary); + background: var(--bg-primary); + overflow-x: hidden; + overscroll-behavior-x: none; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + transition: + background-color 0.3s ease, + color 0.3s ease; +} + +.admin-sidebar, +.admin-header, +.admin-card, +.admin-modal { + transition: + background-color 0.3s ease, + color 0.3s ease, + border-color 0.3s ease; +} + +#root { + overflow-x: hidden; + touch-action: pan-y pinch-zoom; +} + +h1, +h2, +h3, +h4, +h5, +h6 { + font-family: var(--font-heading); + font-weight: 700; + line-height: 1.2; + color: var(--text-primary); +} + +h1 { + font-size: clamp(2.5rem, 5vw, 4rem); +} +h2 { + font-size: clamp(2rem, 4vw, 3rem); +} +h3 { + font-size: clamp(1.25rem, 2vw, 1.5rem); +} + +p { + color: var(--text-secondary); + line-height: 1.6; +} + +a { + color: inherit; + text-decoration: none; + transition: var(--transition); +} + +img { + max-width: 100%; + height: auto; +} + +::-webkit-scrollbar { + width: 8px; +} + +::-webkit-scrollbar-track { + background: var(--bg-secondary); +} + +::-webkit-scrollbar-thumb { + background: var(--border-color); + border-radius: 4px; +} + +::-webkit-scrollbar-thumb:hover { + background: var(--text-muted); +} + +::selection { + background: var(--accent-color); + color: #fff; +} + +/* ============================================================================ + Base / Utilities + ============================================================================ */ + +.text-warning { + color: var(--warning) !important; +} + +.text-danger { + color: var(--danger) !important; +} + +.text-success { + color: var(--success) !important; +} + +.text-muted { + color: var(--text-muted) !important; +} + +.text-secondary { + color: var(--text-secondary) !important; +} + +.text-tertiary { + color: var(--text-tertiary) !important; +} + +.text-accent { + color: var(--accent-color) !important; +} + +.fw-600 { + font-weight: 600 !important; +} + +.link-accent { + color: var(--accent-color); + font-weight: 500; + text-decoration: none; +} + +.link-accent:hover { + text-decoration: underline; +} + +/* Layout utilities */ +.flex-1 { + flex: 1; +} +.flex-row { + display: flex; + align-items: center; +} +.flex-row-gap { + display: flex; + align-items: center; + gap: var(--space-3); +} +.flex-between { + display: flex; + align-items: center; + justify-content: space-between; +} + +/* Spacing utilities */ +.mb-2 { + margin-bottom: var(--space-2); +} +.mb-4 { + margin-bottom: var(--space-4); +} +.mb-6 { + margin-bottom: var(--space-6); +} +.mt-2 { + margin-top: var(--space-2); +} +.mt-6 { + margin-top: var(--space-6); +} +.gap-2 { + gap: var(--space-2); +} +.gap-4 { + gap: var(--space-4); +} +.gap-5 { + gap: var(--space-5); +} + +/* Typography utilities */ +.fw-500 { + font-weight: 500; +} +.text-right { + text-align: right; +} +.text-center { + text-align: center; +} + +/* Spinner variant */ +.admin-spinner-sm { + width: 16px; + height: 16px; + border-width: 2px; +} + +/* Monospace for data values (times, dates, numbers, IDs) */ +.admin-mono { + font-family: var(--font-mono); + font-size: 0.875em; + letter-spacing: -0.01em; +} + +/* Drag handle */ +.admin-drag-handle { + display: flex; + align-items: center; + justify-content: center; + width: 24px; + height: 24px; + border: none; + background: none; + color: var(--text-muted); + cursor: grab; + border-radius: 4px; + padding: 0; + transition: + color 0.15s, + background 0.15s; + touch-action: none; +} + +.admin-drag-handle:hover { + color: var(--text-primary); + background: var(--bg-secondary); +} + +.admin-drag-handle:active { + cursor: grabbing; +} + +/* Error stack (DEV only) */ +.admin-error-stack { + max-width: 600px; + max-height: 200px; + overflow: auto; + padding: 0.75rem 1rem; + margin: 0; + border-radius: var(--border-radius-sm); + background: var(--bg-tertiary); + border: 1px solid var(--border-color); + color: var(--danger-color); + font-family: var(--font-mono); + font-size: 11px; + line-height: 1.5; + text-align: left; + white-space: pre-wrap; + word-break: break-word; +} + +/* Keyboard shortcut badge */ +.admin-kbd { + display: inline-block; + padding: 2px 7px; + font-family: var(--font-mono); + font-size: 12px; + line-height: 1.4; + border-radius: 4px; + background: var(--bg-secondary); + border: 1px solid var(--border-color); + white-space: nowrap; +} + +/* Loading & Animations */ +.admin-spinner { + width: 32px; + height: 32px; + border: 2px solid var(--accent-color); + border-top-color: transparent; + border-radius: 50%; + animation: spin 0.8s linear infinite; +} + +.admin-loading { + display: flex; + align-items: center; + justify-content: center; + min-height: 256px; +} + +@keyframes spin { + to { + transform: rotate(360deg); + } +} + +@keyframes float { + 0%, + 100% { + transform: translate(0, 0); + } + 50% { + transform: translate(30px, -30px); + } +} + +@keyframes pulse { + 0%, + 100% { + opacity: 1; + } + 50% { + opacity: 0.5; + } +} + +@keyframes shimmer { + 0% { + background-position: -200% 0; + } + 100% { + background-position: 200% 0; + } +} + +/* ── Additional Utilities ─────────────────────────────────────────── */ + +/* Font sizes */ +.text-xs { + font-size: 0.75rem; +} +.text-sm { + font-size: 0.8125rem; +} +.text-md { + font-size: 0.875rem; +} +.text-base { + font-size: 1rem; +} + +/* Width utilities */ +.w-full { + width: 100%; +} +.max-w-xs { + max-width: 120px; +} +.max-w-sm { + max-width: 200px; +} + +/* Whitespace */ +.whitespace-nowrap { + white-space: nowrap; +} + +/* Additional gaps */ +.gap-1 { + gap: 0.25rem; +} +.gap-3 { + gap: 0.75rem; +} +.gap-6 { + gap: 1.5rem; +} + +/* Additional margins */ +.mb-1 { + margin-bottom: 0.25rem; +} +.mb-3 { + margin-bottom: 0.75rem; +} +.mt-1 { + margin-top: 0.25rem; +} +.mt-3 { + margin-top: 0.75rem; +} + +/* Display */ +.inline-flex { + display: inline-flex; + align-items: center; +} + +/* Prefers reduced motion */ +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + scroll-behavior: auto !important; + } +} diff --git a/src/admin/buttons.css b/src/admin/buttons.css new file mode 100644 index 0000000..70ab891 --- /dev/null +++ b/src/admin/buttons.css @@ -0,0 +1,130 @@ +/* ============================================================================ + Buttons + ============================================================================ */ + +.admin-btn { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 0.5rem; + padding: 8px 14px; + border: none; + border-radius: var(--border-radius-sm); + font-size: 13px; + font-weight: 550; + font-family: inherit; + cursor: pointer; + transition: var(--transition); + white-space: nowrap; +} + +.admin-btn:disabled { + opacity: 0.7; + cursor: not-allowed; +} + +/* Prevent buttons from growing when text changes to spinner + loading text */ +.admin-modal-footer .admin-btn { + min-width: 100px; +} +.admin-modal-footer .admin-btn .admin-spinner { + margin: -2px 0; +} + +.admin-btn-sm { + padding: 6px 11px; + font-size: 12px; +} + +.admin-btn-primary { + background: var(--accent-color); + color: #fff; +} + +.admin-btn-primary:hover:not(:disabled) { + background: var(--accent-hover); + transform: translateY(-1px); + box-shadow: 0 4px 12px rgba(214, 48, 49, 0.3); +} + +.admin-btn .admin-spinner { + width: 16px; + height: 16px; + border-width: 2px; +} + +.admin-btn-primary .admin-spinner { + border-color: rgba(255, 255, 255, 0.3); + border-top-color: #fff; +} + +.admin-btn-secondary .admin-spinner { + border-color: rgba(var(--text-secondary-rgb, 107, 114, 128), 0.3); + border-top-color: var(--text-secondary); +} + +.admin-btn-secondary { + background: var(--bg-tertiary); + border: 1px solid var(--border-color); + color: var(--text-secondary); +} + +.admin-btn-secondary:hover:not(:disabled) { + background: var(--bg-secondary); + border-color: var(--border-color-hover); + color: var(--text-primary); +} + +.admin-btn-icon { + display: inline-flex; + align-items: center; + justify-content: center; + padding: 0; + width: 32px; + height: 32px; + background: transparent; + border: none; + color: var(--text-secondary); + border-radius: var(--border-radius-sm); + cursor: pointer; + transition: var(--transition); +} + +.admin-btn-icon:hover { + background: var(--bg-tertiary); + color: var(--text-primary); +} + +.admin-btn-icon.accent { + color: var(--info); +} + +.admin-btn-icon.accent:hover { + background: color-mix(in srgb, var(--info) 15%, transparent); + color: var(--info); +} + +.admin-btn-icon.danger { + color: var(--danger); +} + +.admin-btn-icon.danger:hover { + background: var(--danger-light); +} + +/* Touch targets - min 44px on mobile */ +@media (max-width: 768px) { + .admin-btn { + min-height: 44px; + padding: 10px 16px; + } + + .admin-btn-sm { + min-height: 36px; + } + + .admin-btn-icon { + min-width: 44px; + min-height: 44px; + } +} diff --git a/src/admin/components.css b/src/admin/components.css new file mode 100644 index 0000000..a192bfb --- /dev/null +++ b/src/admin/components.css @@ -0,0 +1,925 @@ +/* ============================================================================ + Cards + ============================================================================ */ + +.admin-card { + background: var(--card-bg); + border: 1px solid var(--glass-border); + box-shadow: var(--glass-shadow); + border-radius: var(--border-radius); + overflow: hidden; + margin-bottom: 1rem; +} + +.admin-card:last-child { + margin-bottom: 0; +} + +.admin-card-header { + padding: 14px 18px; + border-bottom: 1px solid var(--border-color); +} + +.admin-card-title { + font-size: 14px; + font-weight: 650; + color: var(--text-primary); + margin: 0 0 12px 0; +} + +.admin-card-body { + padding: 18px; +} + +@media (max-width: 480px) { + .admin-card-body { + padding: 12px; + } + + .admin-card-header { + padding: 12px; + } +} + +/* ============================================================================ + Badges + ============================================================================ */ + +.admin-badge { + display: inline-flex; + align-items: center; + gap: 0.375rem; + padding: 3px 9px; + border-radius: 9999px; + font-size: 11.5px; + font-weight: 600; + border: none; + font-family: inherit; + white-space: nowrap; + max-width: 100%; +} + +.admin-badge-wrap { + white-space: normal; + word-break: break-word; + border-radius: var(--border-radius-sm); + text-align: left; +} + +.admin-badge-admin { + background: var(--accent-soft); + color: var(--accent-color); +} + +.admin-badge-viewer { + background: var(--bg-tertiary); + color: var(--text-secondary); +} + +.admin-badge-active { + background: var(--success-soft); + color: var(--success); + cursor: pointer; + transition: var(--transition); +} + +.admin-badge-active:hover { + background: color-mix(in srgb, var(--success) 20%, transparent); +} + +.admin-badge-inactive { + background: var(--danger-soft); + color: var(--danger); + cursor: pointer; + transition: var(--transition); +} + +.admin-badge-inactive:hover { + background: color-mix(in srgb, var(--danger) 20%, transparent); +} + +.admin-badge-success { + background: var(--success-soft); + color: var(--success); +} + +.admin-badge-warning { + background: var(--warning-soft); + color: var(--warning); +} + +.admin-badge-secondary { + background: var(--bg-tertiary); + color: var(--text-muted); +} + +.admin-badge-info { + background: var(--info-soft); + color: var(--info); +} + +.admin-badge-danger { + background: var(--danger-soft); + color: var(--danger); +} + +/* Status Badges - Leave Requests */ +.badge-pending { + background: color-mix(in srgb, var(--warning) 15%, transparent); + color: var(--warning); +} +.badge-approved { + background: color-mix(in srgb, var(--success) 15%, transparent); + color: var(--success); +} +.badge-rejected { + background: color-mix(in srgb, var(--danger) 15%, transparent); + color: var(--danger); +} +.badge-cancelled { + background: var(--muted-light); + color: var(--muted); +} + +/* Status Badges - Orders */ +.admin-badge-order-prijata { + background: color-mix(in srgb, var(--info) 15%, transparent); + color: var(--info); +} +.admin-badge-order-realizace { + background: color-mix(in srgb, var(--warning) 15%, transparent); + color: var(--warning); +} +.admin-badge-order-dokoncena { + background: color-mix(in srgb, var(--success) 15%, transparent); + color: var(--success); +} +.admin-badge-order-stornovana { + background: color-mix(in srgb, var(--danger) 15%, transparent); + color: var(--danger); +} + +/* Status Badges - Projects */ +.admin-badge-project-aktivni { + background: color-mix(in srgb, var(--success) 15%, transparent); + color: var(--success); +} +.admin-badge-project-dokonceny { + background: color-mix(in srgb, var(--info) 15%, transparent); + color: var(--info); +} +.admin-badge-project-zruseny { + background: color-mix(in srgb, var(--danger) 15%, transparent); + color: var(--danger); +} + +/* Badge on mobile - larger for touch */ +@media (max-width: 768px) { + .admin-badge { + padding: 4px 10px; + font-size: 12px; + } + + button.admin-badge { + min-height: 32px; + } +} + +/* ============================================================================ + Modals + ============================================================================ */ + +.admin-modal-overlay { + position: fixed; + inset: 0; + z-index: 50; + display: flex; + align-items: center; + justify-content: center; + padding: 1rem; + overflow: hidden; + overscroll-behavior: none; + touch-action: none; +} + +.admin-modal-backdrop { + position: absolute; + inset: 0; + background: rgba(0, 0, 0, 0.6); + touch-action: none; +} + +.admin-modal { + position: relative; + width: 100%; + max-width: 480px; + background: var(--bg-secondary); + border: 1px solid var(--border-color); + border-radius: var(--border-radius); + max-height: calc(100vh - 2rem); + max-height: calc(100dvh - 2rem); + overflow: hidden; + display: flex; + flex-direction: column; + touch-action: auto; +} + +.admin-modal-lg { + max-width: 900px; +} + +.admin-modal-header { + padding: 18px; + border-bottom: 1px solid var(--border-color); + flex-shrink: 0; +} + +.admin-modal-title { + font-size: 16px; + font-weight: 700; + color: var(--text-primary); +} + +.admin-modal-body { + padding: 18px; + overflow-y: auto; + flex: 1; + -webkit-overflow-scrolling: touch; + overscroll-behavior: contain; + background: var(--bg-primary); +} + +.admin-modal-footer { + padding: 14px 18px; + border-top: 1px solid var(--border-color); + display: flex; + gap: 0.75rem; + justify-content: flex-end; + flex-shrink: 0; +} + +@media (max-width: 768px) { + .admin-modal-overlay { + padding: 0; + } + + .admin-modal, + .admin-modal.admin-modal-lg { + max-width: 100%; + width: 100%; + height: 100%; + height: 100dvh; + max-height: 100%; + max-height: 100dvh; + border-radius: 0; + border: none; + } + + .admin-modal-header { + padding: 1rem; + padding-top: calc(1rem + env(safe-area-inset-top, 0px)); + } + + .admin-modal-body { + padding: 1rem; + flex: 1; + overflow-y: auto; + overflow-x: hidden; + -webkit-overflow-scrolling: touch; + } + + .admin-modal-footer { + padding: 1rem; + padding-bottom: calc(1rem + env(safe-area-inset-bottom, 0px)); + } + + .admin-modal .admin-form-input, + .admin-modal .admin-form-select, + .admin-modal .admin-form-textarea { + max-width: 100%; + } +} + +/* Confirm Modal */ +.admin-confirm-modal { + max-width: 400px; +} + +.admin-confirm-content { + text-align: center; + padding: 2rem 1.5rem; +} + +.admin-confirm-icon { + width: 56px; + height: 56px; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + margin: 0 auto 1.25rem; +} + +.admin-confirm-icon-danger { + background: var(--danger-light); + color: var(--danger); +} + +.admin-confirm-icon-warning { + background: var(--warning-light); + color: var(--warning); +} + +.admin-confirm-icon-info { + background: var(--info-light); + color: var(--info); +} + +.admin-confirm-icon-default { + background: var(--bg-tertiary); + color: var(--text-secondary); +} + +.admin-confirm-title { + font-size: 1.25rem; + font-weight: 700; + color: var(--text-primary); + margin-bottom: 0.5rem; +} + +.admin-confirm-message { + color: var(--text-secondary); + font-size: 0.95rem; + line-height: 1.5; +} + +@media (max-width: 768px) { + .admin-confirm-modal { + max-width: 100%; + height: auto; + max-height: calc(100% - 2rem); + max-height: calc(100dvh - 2rem); + margin: 1rem; + border-radius: var(--border-radius); + border: 1px solid var(--border-color); + } + + .admin-confirm-modal .admin-modal-footer { + padding-bottom: calc(1rem + env(safe-area-inset-bottom, 0px)); + } +} + +/* Confirm modal on small mobile */ +@media (max-width: 480px) { + .admin-confirm-content { + padding: 1.5rem 1rem; + } + + .admin-confirm-title { + font-size: 1.1rem; + } + + .admin-confirm-message { + font-size: 0.875rem; + } +} + +/* ============================================================================ + Toast Alerts + ============================================================================ */ + +.admin-alert-container { + position: fixed; + bottom: calc(1rem + env(safe-area-inset-bottom, 0px)); + right: 1rem; + z-index: 100; + display: flex; + flex-direction: column-reverse; + gap: 0.5rem; + max-width: 400px; + width: calc(100% - 2rem); + pointer-events: none; + transform: translateZ(0); +} + +@media (min-width: 640px) { + .admin-alert-container { + bottom: calc(1.5rem + env(safe-area-inset-bottom, 0px)); + right: 1.5rem; + } +} + +.admin-toast { + display: flex; + align-items: center; + gap: 0.75rem; + padding: 0.875rem 1rem; + border-radius: var(--border-radius-sm); + background: var(--bg-secondary); + border: 1px solid var(--border-color); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); + pointer-events: auto; +} + +.admin-toast-icon { + flex-shrink: 0; + display: flex; + align-items: center; + justify-content: center; +} + +.admin-toast-message { + flex: 1; + font-size: 0.875rem; + color: var(--text-primary); +} + +.admin-toast-close { + flex-shrink: 0; + padding: 0.25rem; + background: transparent; + border: none; + color: var(--text-muted); + cursor: pointer; + border-radius: var(--border-radius-sm); + transition: var(--transition); +} + +.admin-toast-close:hover { + background: var(--bg-tertiary); + color: var(--text-primary); +} + +.admin-toast-success .admin-toast-icon { + color: var(--success); +} +.admin-toast-error .admin-toast-icon { + color: var(--danger); +} +.admin-toast-warning .admin-toast-icon { + color: var(--warning); +} +.admin-toast-info .admin-toast-icon { + color: var(--info); +} + +/* ============================================================================ + Tabs (Global) + ============================================================================ */ + +.admin-tabs { + display: inline-flex; + gap: 4px; + padding: 4px; + background: var(--bg-tertiary); + border: 1px solid var(--border-color); + border-radius: 0.625rem; +} + +.admin-tab { + position: relative; + display: inline-flex; + align-items: center; + gap: 0.5rem; + padding: 0.5rem 1.25rem; + background: transparent; + border: none; + border-radius: 0.5rem; + color: var(--text-muted); + font-size: 0.8125rem; + font-weight: 500; + font-family: inherit; + cursor: pointer; + transition: + color 0.2s ease, + background 0.2s ease, + box-shadow 0.2s ease; + letter-spacing: 0.01em; + white-space: nowrap; +} + +.admin-tab:hover { + color: var(--text-primary); +} + +.admin-tab.active { + color: var(--text-primary); + font-weight: 600; + background: var(--bg-secondary); + box-shadow: + 0 1px 3px rgba(0, 0, 0, 0.12), + 0 0 0 1px var(--border-color); +} + +/* ============================================================================ + Empty State + ============================================================================ */ + +.admin-empty-state { + display: flex; + flex-direction: column; + align-items: center; + text-align: center; + padding: 3rem 1.5rem; + color: var(--text-secondary); +} + +.admin-empty-icon { + width: 64px; + height: 64px; + border-radius: 50%; + background: var(--bg-tertiary); + color: var(--text-muted); + display: flex; + align-items: center; + justify-content: center; + margin-bottom: 1.25rem; +} + +.admin-empty-state p { + margin-bottom: 1rem; + font-size: 0.95rem; + max-width: 320px; +} + +.admin-role-locked-notice { + display: flex; + align-items: center; + gap: 0.5rem; + padding: 0.75rem 1rem; + background: var(--warning-light); + border: 1px solid color-mix(in srgb, var(--warning) 25%, transparent); + border-radius: 0.5rem; + color: var(--warning); + font-size: 0.875rem; + margin-bottom: 0.5rem; +} + +/* ============================================================================ + Forbidden (403) + ============================================================================ */ + +.forbidden-page { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + min-height: 60vh; + text-align: center; + padding: 2rem; +} + +.forbidden-icon { + color: var(--accent-color); + margin-bottom: 1.5rem; + opacity: 0.8; +} + +.forbidden-title { + font-family: var(--font-heading); + font-size: 2rem; + font-weight: 700; + color: var(--text-primary); + margin: 0 0 0.75rem; +} + +.forbidden-text { + color: var(--text-secondary); + font-size: 1rem; + max-width: 400px; + line-height: 1.6; + margin: 0 0 2rem; +} + +.forbidden-link { + display: inline-flex; + align-items: center; + gap: 0.5rem; + padding: 0.75rem 1.5rem; + background: var(--accent-color); + color: #fff; + border-radius: var(--border-radius-sm); + text-decoration: none; + font-weight: 600; + transition: var(--transition); +} + +.forbidden-link:hover { + background: var(--accent-hover); + transform: translateY(-1px); +} + +/* ============================================================================ + Stat Cards + ============================================================================ */ + +.admin-stat-card { + position: relative; + background: var(--glass-bg); + backdrop-filter: blur(12px); + -webkit-backdrop-filter: blur(12px); + border: 1px solid var(--glass-border); + box-shadow: var(--glass-shadow); + border-radius: var(--border-radius); + padding: 1.25rem; + display: flex; + flex-direction: column; + gap: 0.5rem; + overflow: hidden; +} + +.admin-stat-card::before { + content: ""; + position: absolute; + top: 0; + left: 0; + right: 0; + height: 3px; + background: var(--accent-color); + border-radius: var(--border-radius) var(--border-radius) 0 0; +} + +.admin-stat-card.success::before { + background: var(--success); +} +.admin-stat-card.warning::before { + background: var(--warning); +} +.admin-stat-card.danger::before { + background: var(--danger); +} +.admin-stat-card.info::before { + background: var(--info); +} + +.admin-stat-icon { + width: 40px; + height: 40px; + border-radius: var(--border-radius-sm); + background: var(--accent-soft); + color: var(--accent-color); + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; +} + +.admin-stat-content { + display: flex; + flex-direction: column; + gap: 0.125rem; +} + +.admin-stat-value { + font-size: 28px; + font-weight: 700; + color: var(--text-primary); + font-family: var(--font-mono); + letter-spacing: -0.02em; + line-height: 1.2; +} + +.admin-stat-label { + font-size: 0.6875rem; + font-weight: 600; + color: var(--text-muted); + text-transform: uppercase; + letter-spacing: 0.04em; +} + +.admin-stat-footer { + font-size: 0.75rem; + color: var(--text-secondary); +} + +.admin-stat-icon.danger { + background: var(--danger-soft); + color: var(--danger); +} +.admin-stat-icon.info { + background: var(--info-soft); + color: var(--info); +} +.admin-stat-icon.success { + background: var(--success-soft); + color: var(--success); +} +.admin-stat-icon.warning { + background: var(--warning-soft); + color: var(--warning); +} + +/* ============================================================================ + KPI Grid + ============================================================================ */ + +.admin-kpi-grid { + display: grid; + gap: 0.875rem; +} + +.admin-kpi-4 { + grid-template-columns: repeat(4, 1fr); +} +.admin-kpi-3 { + grid-template-columns: repeat(3, 1fr); +} +.admin-kpi-2 { + grid-template-columns: repeat(2, 1fr); +} +.admin-kpi-1 { + grid-template-columns: 1fr; + max-width: 320px; +} + +@media (max-width: 1024px) { + .admin-kpi-4 { + grid-template-columns: repeat(2, 1fr); + } +} + +@media (max-width: 768px) { + .admin-kpi-grid { + grid-template-columns: repeat(2, 1fr); + } +} + +@media (max-width: 480px) { + .admin-kpi-grid { + grid-template-columns: 1fr; + } +} + +/* ============================================================================ + Editor Section Cards + ============================================================================ */ + +.admin-editor-section { + background: var(--glass-bg); + backdrop-filter: blur(12px); + -webkit-backdrop-filter: blur(12px); + border: 1px solid var(--glass-border); + box-shadow: var(--glass-shadow); + border-radius: 0.75rem; + padding: 1.5rem; + margin-bottom: 1.5rem; +} + +@media (max-width: 640px) { + .admin-editor-section { + padding: 1rem; + } +} + +/* ============================================================================ + Totals Summary + ============================================================================ */ + +.admin-totals-summary { + display: flex; + flex-direction: column; + align-items: flex-end; + gap: 0.25rem; + padding-top: 0.75rem; + border-top: 1px solid var(--border-color); +} + +.admin-totals-row { + display: flex; + gap: 2rem; + justify-content: flex-end; + min-width: 250px; + padding: 0.25rem 0; + font-size: 0.875rem; + color: var(--text-secondary); +} + +.admin-totals-row span:last-child { + min-width: 100px; + text-align: right; + font-weight: 500; + color: var(--text-primary); +} + +.admin-totals-total { + border-top: 2px solid var(--text-primary); + margin-top: 0.25rem; + padding-top: 0.5rem; + font-size: 1rem; + font-weight: 600; +} + +.admin-totals-total span:last-child { + font-weight: 700; +} + +@media (max-width: 640px) { + .admin-totals-summary { + align-items: stretch; + } + + .admin-totals-row { + min-width: unset; + } +} + +/* ============================================================================ + Scope Sections + ============================================================================ */ + +.admin-scope-list { + margin-top: 1.25rem; + display: flex; + flex-direction: column; + gap: 1rem; +} + +.admin-scope-section { + border: 1px solid var(--border-color); + border-radius: 0.5rem; + overflow: visible; + transition: border-color var(--transition); + background: var(--bg-primary); +} + +.admin-scope-content { + overflow: hidden; +} + +.admin-scope-section:hover { + border-color: color-mix( + in srgb, + var(--border-color) 70%, + var(--accent-color) + ); +} + +.admin-scope-section-header { + display: flex; + align-items: center; + padding: 0.625rem 1rem; + background: var(--bg-tertiary); + border-bottom: 1px solid var(--border-color); + border-radius: 0.5rem 0.5rem 0 0; + gap: 0.5rem; +} + +.admin-scope-section-header .admin-scope-number { + font-size: 0.75rem; + font-weight: 600; + color: var(--text-tertiary); + flex-shrink: 0; + min-width: 1.25rem; +} + +.admin-scope-section-header .admin-scope-title { + font-weight: 600; + font-size: 0.875rem; + color: var(--text-primary); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + flex: 1; +} + +.admin-scope-section-header .admin-scope-actions { + display: flex; + gap: 0.25rem; + margin-left: auto; + flex-shrink: 0; +} + +.admin-scope-section .admin-form { + padding: 1rem; +} + +/* ============================================================================ + Logo Section + ============================================================================ */ + +.admin-logo-section { + display: flex; + flex-direction: column; + align-items: center; + gap: 1rem; + padding: 1rem; +} + +.admin-logo-preview { + max-width: 200px; + max-height: 100px; + border: 1px solid var(--border-color); + border-radius: 0.5rem; + overflow: hidden; + display: flex; + align-items: center; + justify-content: center; + padding: 0.5rem; + background: #fff; +} + +.admin-logo-preview img { + max-width: 100%; + max-height: 80px; + object-fit: contain; +} diff --git a/src/admin/components/RichEditor.tsx b/src/admin/components/RichEditor.tsx index 3df962a..de09580 100644 --- a/src/admin/components/RichEditor.tsx +++ b/src/admin/components/RichEditor.tsx @@ -161,7 +161,7 @@ export default function RichEditor({ return (
= { - 4: "dash-kpi-4", - 3: "dash-kpi-3", - 2: "dash-kpi-2", - 1: "dash-kpi-1", + 4: "admin-kpi-4", + 3: "admin-kpi-3", + 2: "admin-kpi-2", + 1: "admin-kpi-1", }; export default function DashKpiCards({ dashData }: DashKpiCardsProps) { @@ -121,11 +121,11 @@ export default function DashKpiCards({ dashData }: DashKpiCardsProps) { return null; } - const kpiClass = KPI_CLASS_MAP[Math.min(kpiCards.length, 4)] || "dash-kpi-4"; + const kpiClass = KPI_CLASS_MAP[Math.min(kpiCards.length, 4)] || "admin-kpi-4"; return ( )} {!sessionsLoading && sessions.length > 0 && ( -
+
{sessions.map((session) => (
-
+
{getDeviceIcon(session.device_info?.icon)}
-
-
+
+
{session.device_info?.browser} na{" "} {session.device_info?.os} {session.is_current && ( @@ -240,13 +240,13 @@ export default function DashSessions() { )}
-
+
{session.ip_address} - | + | {formatSessionDate(session.created_at)}
-
+
{!session.is_current && (