diff --git a/.github/workflows/deploy-beta.yml b/.github/workflows/deploy-beta.yml index 9048598..fa7402b 100644 --- a/.github/workflows/deploy-beta.yml +++ b/.github/workflows/deploy-beta.yml @@ -13,8 +13,9 @@ jobs: with: host: ${{ secrets.SSH_HOST }} username: ${{ secrets.SSH_USER }} - password: ${{ secrets.SSH_PASSWORD }} + key: ${{ secrets.SSH_PRIVATE_KEY }} port: ${{ secrets.SSH_PORT || 22 }} + host_key_checking: false script: | cd ${{ secrets.BETA_PATH }} cp .env /tmp/beta.env 2>/dev/null; cp port.txt /tmp/beta.port.txt 2>/dev/null diff --git a/.github/workflows/deploy-main.yml b/.github/workflows/deploy-main.yml index 6eeb022..4b4461d 100644 --- a/.github/workflows/deploy-main.yml +++ b/.github/workflows/deploy-main.yml @@ -13,8 +13,9 @@ jobs: with: host: ${{ secrets.SSH_HOST }} username: ${{ secrets.SSH_USER }} - password: ${{ secrets.SSH_PASSWORD }} + key: ${{ secrets.SSH_PRIVATE_KEY }} port: ${{ secrets.SSH_PORT || 22 }} + host_key_checking: false script: | cd ${{ secrets.MAIN_PATH }} cp .env /tmp/main.env 2>/dev/null; cp port.txt /tmp/main.port.txt 2>/dev/null diff --git a/config/pyrodactyl.js b/config/pyrodactyl.js index cbe1cba..f03a6ed 100644 --- a/config/pyrodactyl.js +++ b/config/pyrodactyl.js @@ -1,6 +1,7 @@ export const PTERO_URL = process.env.PTERO_URL || 'https://panel.zero-host.org'; export const PTERO_API_KEY = process.env.PTERO_API_KEY || ''; -export const PANEL_DB_NAME = (process.env.PANEL_DB_NAME || 'panel').replace(/[^a-zA-Z0-9_]/g, ''); +const _rawPanelDb = (process.env.PANEL_DB_NAME || 'panel').replace(/[^a-zA-Z0-9_]/g, ''); +export const PANEL_DB_NAME = '`' + _rawPanelDb + '`'; export const SERVER_LIMITS = { memory: 512, diff --git a/middleware/auth.js b/middleware/auth.js index 3f7faa9..309c511 100644 --- a/middleware/auth.js +++ b/middleware/auth.js @@ -75,9 +75,17 @@ export function requireNotRestricted(req, res, next) { next(); } +const ALLOWED_TABLES = new Set(['server_meta']); +const ALLOWED_COLUMNS = new Set(['ptero_server_id', 'user_id', 'id']); + export function requireOwnership(table, column, paramName, idSource = 'params') { return async (req, res, next) => { try { + if (!ALLOWED_TABLES.has(table) || !ALLOWED_COLUMNS.has(column)) { + console.error(`Blocked ownership check on unauthorized table/column: ${table}.${column}`); + return res.status(500).json({ error: 'Ownership verification failed' }); + } + const id = parseInt(idSource === 'params' ? req.params[paramName] : req.body[paramName], 10); if (isNaN(id)) { return res.status(400).json({ error: 'Invalid ID' }); diff --git a/public/css/style.css b/public/css/style.css index 6532807..483ada3 100644 --- a/public/css/style.css +++ b/public/css/style.css @@ -424,6 +424,34 @@ cap-widget { display: block; } +.auth-error.show:has(.auth-resend-btn) { + display: flex; + flex-direction: column; + gap: 10px; +} + +.auth-resend-btn { + background: rgba(239, 68, 68, 0.15); + border: 1px solid rgba(239, 68, 68, 0.4); + color: var(--accent-red); + padding: 6px 14px; + border-radius: var(--radius-sm); + font-size: 0.8rem; + font-weight: 600; + cursor: pointer; + transition: background var(--transition), opacity var(--transition); + align-self: flex-start; +} + +.auth-resend-btn:hover:not(:disabled) { + background: rgba(239, 68, 68, 0.25); +} + +.auth-resend-btn:disabled { + opacity: 0.5; + cursor: not-allowed; +} + /* ===== DASHBOARD LAYOUT ===== */ .dashboard-layout { display: flex; @@ -528,6 +556,24 @@ cap-widget { gap: 0; } +.sidebar.collapsed .nav-parent { + font-size: 0; + justify-content: center; + padding: 10px 0; + gap: 0; +} + +.sidebar.collapsed .nav-parent-label, +.sidebar.collapsed .nav-parent-chevron { + display: none; +} + +.sidebar.collapsed .nav-parent svg { + font-size: 1rem; + width: 20px; + height: 20px; +} + .sidebar.collapsed .nav-indicator { left: 8px; width: calc(100% - 16px); @@ -635,6 +681,9 @@ cap-widget { position: relative; } +.nav-items { +} + .nav-indicator { position: absolute; left: 12px; @@ -678,7 +727,8 @@ cap-widget { background: rgba(238, 129, 50, 0.08); } -.nav-item.active { +.nav-item.active, +.nav-parent.active { color: var(--accent-1); } @@ -688,6 +738,120 @@ cap-widget { flex-shrink: 0; } +.nav-parent { + display: flex; + align-items: center; + gap: 12px; + padding: 10px 12px; + border-radius: var(--radius-sm); + color: var(--text-secondary); + font-size: 0.9rem; + font-weight: 500; + cursor: pointer; + transition: color var(--transition); + text-decoration: none; + margin-bottom: 2px; + position: relative; + z-index: 2; + user-select: none; +} + +.nav-parent:hover { + color: var(--text-primary); + background: rgba(238, 129, 50, 0.08); +} + +.nav-parent svg { + width: 18px; + height: 18px; + flex-shrink: 0; +} + +.nav-parent-label { + flex: 1; + min-width: 0; +} + +.nav-parent-chevron { + width: 16px; + height: 16px; + flex-shrink: 0; + transition: transform 0.2s ease; +} + +.nav-parent.open .nav-parent-chevron { + transform: rotate(90deg); +} + +.nav-sub-list { + max-height: 0; + overflow: hidden; + transition: max-height 0.25s ease; + margin-bottom: 2px; +} + +.nav-sub-list.open { + max-height: 400px; +} + +.sidebar.collapsed .nav-sub-list { + display: none; +} + +.nav-sub-item { + display: flex; + align-items: center; + gap: 10px; + padding: 7px 12px 7px 42px; + border-radius: var(--radius-sm); + color: var(--text-secondary); + font-size: 0.82rem; + font-weight: 500; + cursor: pointer; + transition: color var(--transition); + text-decoration: none; + margin-bottom: 1px; + position: relative; + z-index: 2; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.nav-sub-item:hover { + color: var(--text-primary); + background: rgba(238, 129, 50, 0.08); +} + +.nav-sub-item.active { + color: var(--accent-1); +} + +.nav-sub-item .nav-sub-dot { + width: 6px; + height: 6px; + border-radius: 50%; + flex-shrink: 0; +} + +.nav-sub-dot.dot-active { + background: #22c55e; +} + +.nav-sub-dot.dot-installing { + background: #f59e0b; +} + +.nav-sub-dot.dot-suspended { + background: var(--accent-red); +} + +.nav-sub-empty { + padding: 8px 12px 8px 42px; + font-size: 0.8rem; + color: var(--text-muted); +} + .sidebar-footer { padding: 12px 12px 4px; border-top: 1px solid var(--border); @@ -1343,12 +1507,22 @@ tbody tr:hover { flex-shrink: 0; } +.notif-header-actions { + display: flex; + align-items: center; + gap: 8px; +} + .notif-panel-header h3 { font-size: 1.1rem; font-weight: 700; color: var(--text-primary); } +.notif-close-mobile { + display: none; +} + .notif-mark-all { background: none; border: none; @@ -1581,9 +1755,49 @@ tbody tr:hover { padding: 8px; } +/* ─── Tablet & below (≤ 1024px) ─── */ +@media (max-width: 1024px) { + .main-content { + padding: 24px; + } + + .admin-content { + padding: 24px; + } + + .page-title { + font-size: 1.5rem; + } + + .stat-value { + font-size: 1.7rem; + } + + .modal { + max-width: 480px; + } + + .wizard-progress { + max-width: 100%; + } + + .wizard-step-label { + font-size: 0.75rem; + } + + .wizard-step-indicator { + padding: 6px 8px; + gap: 6px; + } +} + +/* ─── Mobile (≤ 768px) ─── */ @media (max-width: 768px) { + /* Sidebar: off-canvas */ .sidebar { transform: translateX(-100%); + width: 260px; + z-index: 200; } .sidebar.open { @@ -1594,106 +1808,1247 @@ tbody tr:hover { display: none; } + .sidebar.collapsed { + width: 260px; + } + + .sidebar.collapsed .sidebar-resizer { + display: none; + } + + .sidebar.collapsed ~ .main-content { + margin-left: 0; + } + + /* Sidebar backdrop for mobile */ + .sidebar-backdrop { + display: none; + } + + .sidebar.open ~ .sidebar-backdrop { + display: block; + position: fixed; + inset: 0; + background: rgba(0, 0, 0, 0.5); + z-index: 99; + -webkit-backdrop-filter: blur(2px); + backdrop-filter: blur(2px); + } + + /* Main content: full width */ .main-content { margin-left: 0; - padding: 20px; + padding: 16px; + padding-top: 60px; } + /* Hamburger button */ .hamburger-toggle { display: flex; align-items: center; justify-content: center; position: fixed; - top: 16px; - left: 16px; + top: 12px; + left: 12px; z-index: 101; background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 10px; + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3); + } + + /* Page header */ + .page-header { + margin-bottom: 24px; + } + + .page-title { + font-size: 1.35rem; + word-break: break-word; + } + + .page-subtitle { + font-size: 0.85rem; } + /* Stat grid: 2 columns on tablet, 1 on mobile */ .stat-grid { - grid-template-columns: 1fr; + grid-template-columns: repeat(2, 1fr); + gap: 12px; + } + + .stat-card { + padding: 16px; + } + + .stat-value { + font-size: 1.5rem; + } + + .stat-label { + font-size: 0.75rem; } + /* Server grid: single column */ .server-grid { grid-template-columns: 1fr; + gap: 12px; } - .form-row { - flex-direction: column; - gap: 0; + .server-card { + padding: 16px; } - .auth-card { - padding: 32px 24px; + .server-card-name { + font-size: 0.92rem; } - .table-container { - overflow-x: auto; + /* Cards */ + .card { + padding: 16px; + border-radius: var(--radius-md); } -} -/* ===== PYRODACTYL PAGE ===== */ -.ptero-grid { - max-width: 640px; -} + .card-header { + flex-wrap: wrap; + gap: 8px; + } -.ptero-card-icon { - width: 56px; - height: 56px; - border-radius: var(--radius-md); - display: flex; - align-items: center; - justify-content: center; - margin-bottom: 20px; - color: var(--accent-cyan); - background: rgba(34, 211, 238, 0.1); -} + /* Tables: card layout on mobile */ + .table-container { + background: transparent; + border: none; + border-radius: 0; + overflow: visible; + } -.ptero-card-title { - font-size: 1.4rem; - font-weight: 700; - margin-bottom: 12px; -} + .table-container table { + width: 100%; + } -.ptero-card-desc { - color: var(--text-secondary); - line-height: 1.7; - margin-bottom: 24px; -} + .table-container thead { + display: none; + } -.ptero-info { - display: flex; - flex-direction: column; - gap: 14px; -} + .table-container tbody { + display: flex; + flex-direction: column; + gap: 10px; + } -.ptero-info-item { - display: flex; - align-items: flex-start; - gap: 12px; - font-size: 0.9rem; - color: var(--text-secondary); - line-height: 1.5; -} + .table-container tbody tr { + display: flex; + flex-direction: column; + background: var(--bg-card); + border: 1px solid var(--border); + border-radius: var(--radius-md); + padding: 14px 16px; + gap: 6px; + } -.ptero-info-item svg { - flex-shrink: 0; - margin-top: 2px; - color: var(--accent-cyan); -} + .table-container tbody tr:hover { + background: var(--bg-card); + } -.ptero-info-item span { - flex: 1; -} + .table-container tbody td { + padding: 0; + border-bottom: none; + font-size: 0.85rem; + display: flex; + align-items: center; + justify-content: space-between; + gap: 8px; + } -.ptero-info-item strong { - color: var(--text-primary); -} + .table-container tbody td::before { + content: attr(data-label); + font-size: 0.72rem; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.06em; + color: var(--text-muted); + white-space: nowrap; + flex-shrink: 0; + } -/* ===== ACCOUNT PAGE ===== */ + .table-container tbody td:last-child { + border-top: 1px solid rgba(255, 255, 255, 0.04); + padding-top: 8px; + margin-top: 2px; + justify-content: flex-end; + } + + .table-container tbody td:first-child::before { + display: none; + } + + .table-container tbody td:first-child { + font-weight: 700; + font-size: 0.92rem; + } + + /* Form rows */ + .form-row { + flex-direction: column; + gap: 0; + } + + /* Auth card */ + .auth-card { + padding: 28px 20px; + border-radius: var(--radius-lg); + } + + .auth-title { + font-size: 1.35rem; + } + + .auth-logo-text { + font-size: 1.2rem; + } + + /* Tabs: scrollable */ + .tabs { + overflow-x: auto; + -webkit-overflow-scrolling: touch; + scrollbar-width: none; + gap: 0; + padding-bottom: 0; + } + + .tabs::-webkit-scrollbar { + display: none; + } + + .tab { + padding: 10px 14px; + font-size: 0.82rem; + white-space: nowrap; + flex-shrink: 0; + } + + /* Server detail */ + .server-detail-grid { + grid-template-columns: 1fr; + gap: 16px; + } + + .detail-item { + flex-direction: column; + align-items: flex-start; + gap: 4px; + } + + .detail-label { + font-size: 0.72rem; + } + + .detail-value { + font-size: 0.85rem; + word-break: break-all; + } + + /* Resource gauges */ + .resource-gauges { + grid-template-columns: 1fr; + gap: 12px; + } + + .resource-gauge { + padding: 16px 12px; + } + + .resource-gauge-value { + font-size: 1.4rem; + } + + /* Servers toolbar */ + .servers-toolbar { + flex-direction: column; + align-items: stretch; + gap: 10px; + } + + .search-wrapper { + min-width: 0; + } + + .filter-group { + justify-content: center; + flex-wrap: wrap; + } + + .filter-btn { + padding: 6px 12px; + font-size: 0.75rem; + } + + /* Modal */ + .modal-overlay { + padding: 16px; + align-items: flex-end; + } + + .modal { + max-width: 100%; + border-radius: var(--radius-xl) var(--radius-xl) 0 0; + padding: 24px 20px; + max-height: 85vh; + } + + .modal-title { + font-size: 1.15rem; + margin-bottom: 20px; + } + + .modal-actions { + flex-direction: column; + gap: 8px; + margin-top: 20px; + } + + .modal-actions .btn { + width: 100%; + } + + /* Toast */ + .toast-container { + bottom: 16px; + right: 16px; + left: 16px; + z-index: 500; + } + + .toast { + padding: 12px 16px; + font-size: 0.82rem; + } + + /* Notification panel: adapts on tablet */ + .notif-panel { + left: 0; + width: 100%; + top: 0; + bottom: 0; + height: 100%; + border-right: none; + border-radius: 0; + z-index: 150; + } + + .sidebar.collapsed ~ .notif-panel { + left: 0; + } + + .notif-panel-header { + padding: 16px 16px 14px; + border-bottom: 1px solid var(--border); + } + + .notif-panel-header h3 { + font-size: 1rem; + } + + .notif-mark-all { + display: none; + } + + .notif-close-mobile { + display: flex; + align-items: center; + justify-content: center; + background: none; + border: none; + color: var(--text-secondary); + cursor: pointer; + padding: 4px; + border-radius: var(--radius-sm); + transition: all var(--transition); + } + + .notif-close-mobile:hover { + color: var(--text-primary); + background: var(--bg-3); + } + + .notif-item { + padding: 12px 16px; + gap: 10px; + } + + .notif-item-icon { + width: 32px; + height: 32px; + } + + .notif-icon { + width: 16px; + height: 16px; + } + + .notif-item-title { + font-size: 0.85rem; + } + + .notif-item-msg { + font-size: 0.78rem; + line-height: 1.4; + } + + .notif-item-time { + font-size: 0.7rem; + } + + .notif-empty { + padding: 40px 16px; + font-size: 0.85rem; + } + + .notif-backdrop { + z-index: 149; + } + + /* Cookie banner */ + .cookie-banner { + flex-direction: column; + padding: 16px; + gap: 12px; + align-items: stretch; + } + + .cookie-banner-text { + min-width: 0; + } + + .cookie-banner-text p { + font-size: 0.82rem; + } + + .cookie-banner-actions { + justify-content: stretch; + flex-wrap: nowrap; + } + + .cookie-banner-actions .btn { + flex: 1; + } + + /* Empty state */ + .empty-state { + padding: 40px 16px; + } + + .empty-state-icon { + width: 48px; + height: 48px; + } + + .empty-state-title { + font-size: 1rem; + } + + .empty-state-desc { + font-size: 0.82rem; + } + + /* Wizard */ + .wizard-progress { + display: none; + } + + .wizard-progress::-webkit-scrollbar { + display: none; + } + + .wizard-step-indicator { + padding: 6px 8px; + gap: 5px; + } + + .wizard-step-circle { + width: 26px; + height: 26px; + } + + .wizard-step-circle svg { + width: 13px !important; + height: 13px !important; + } + + .wizard-step-label { + font-size: 0.7rem; + } + + .wizard-step-title { + font-size: 1.1rem; + } + + .wizard-step-desc { + font-size: 0.82rem; + margin-bottom: 16px; + } + + .wizard-actions { + flex-direction: column-reverse; + gap: 8px; + } + + .wizard-actions .btn { + width: 100%; + } + + #wizard-next-btn { + margin-left: 0; + } + + /* Create page header fix */ + #page-create .page-header { + display: none !important; + } + + /* Nest grid */ + .nest-grid { + grid-template-columns: repeat(2, 1fr); + gap: 10px; + } + + .nest-card { + padding: 16px 12px; + border-radius: var(--radius-md); + } + + .nest-card-logo { + width: 48px; + height: 48px; + } + + .nest-card-logo img, + .nest-card-logo i { + width: 32px !important; + height: 32px !important; + } + + .nest-card-name { + font-size: 0.85rem; + line-height: 1.2; + } + + .nest-card-desc { + font-size: 0.72rem; + line-height: 1.3; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; + } + + /* Egg grid */ + .egg-grid { + grid-template-columns: 1fr; + gap: 8px; + } + + .egg-card { + padding: 12px; + gap: 10px; + border-radius: var(--radius-md); + } + + .egg-card-logo { + width: 36px; + height: 36px; + } + + .egg-card-logo img, + .egg-card-logo i { + width: 28px !important; + height: 28px !important; + } + + .egg-card-logo { + width: 32px; + height: 32px; + } + + .egg-card-name { + font-size: 0.85rem; + } + + .egg-card-desc { + font-size: 0.75rem; + } + + /* Summary card */ + .summary-card { + padding: 16px; + max-width: 100%; + } + + .summary-row { + flex-direction: column; + align-items: flex-start; + gap: 2px; + } + + .summary-value { + text-align: left; + max-width: 100%; + } + + /* Account page */ + .account-grid { + max-width: 100%; + } + + .account-menu-icon { + width: 36px; + height: 36px; + } + + /* Pyrodactyl page */ + .ptero-grid { + max-width: 100%; + } + + .ptero-card-icon { + width: 44px; + height: 44px; + margin-bottom: 14px; + } + + .ptero-card-title { + font-size: 1.15rem; + } + + /* Activity timeline */ + .activity-item { + gap: 10px; + padding: 10px 0; + } + + .activity-icon { + width: 28px; + height: 28px; + font-size: 0.7rem; + } + + .activity-action { + font-size: 0.82rem; + } + + .activity-details { + font-size: 0.72rem; + } + + .activity-time { + font-size: 0.68rem; + } + + /* Log pagination */ + .log-pagination { + flex-wrap: wrap; + gap: 8px; + } + + .log-pagination-info { + font-size: 0.75rem; + width: 100%; + text-align: center; + } + + /* API key input group */ + .api-key-input-group { + flex-direction: column; + gap: 8px; + } + + /* Buttons: ensure touch targets */ + .btn { + min-height: 40px; + } + + .btn-sm { + min-height: 34px; + padding: 6px 12px; + font-size: 0.78rem; + } + + /* SVG picker */ + .svg-picker-grid { + grid-template-columns: repeat(auto-fill, minmax(40px, 1fr)); + } + + /* Admin navbar */ + .admin-navbar { + padding: 0 12px; + gap: 8px; + height: 52px; + } + + .admin-navbar-brand { + font-size: 0.82rem; + } + + .admin-navbar-logo { + width: 24px; + height: 24px; + } + + .admin-badge { + font-size: 0.55rem; + padding: 1px 5px; + } + + .admin-navbar-center { + gap: 2px; + overflow-x: auto; + -webkit-overflow-scrolling: touch; + scrollbar-width: none; + padding: 0 4px; + } + + .admin-navbar-center::-webkit-scrollbar { + display: none; + } + + .admin-nav-link { + padding: 6px 10px; + font-size: 0.78rem; + white-space: nowrap; + flex-shrink: 0; + } + + .admin-nav-link svg { + width: 14px; + height: 14px; + } + + .admin-navbar-user { + display: none; + } + + .admin-content { + padding: 16px; + } + + .admin-notice { + font-size: 0.78rem; + padding: 10px 12px; + } + + /* Toggle switch */ + .toggle-switch { + position: relative; + display: inline-block; + width: 44px; + height: 24px; + } + + /* Cap modal */ + .cap-modal { + padding: 16px; + margin: 16px; + } + + .cap-modal cap-widget { + width: 100% !important; + } + + /* Notif view modal */ + .notif-view-modal-content { + width: 95%; + max-height: 75vh; + } + + .notif-view-modal-header { + padding: 16px 16px 0; + } + + .notif-view-modal-body { + padding: 12px 16px 16px; + font-size: 0.85rem; + } + + /* Server detail page header */ + .server-detail-grid .card-title { + font-size: 0.92rem; + } + + /* Action cards */ + .action-card { + padding: 16px; + border-radius: var(--radius-md); + margin-bottom: 12px; + } + + .action-card-header { + gap: 10px; + margin-bottom: 12px; + } + + .action-card-header svg { + width: 20px; + height: 20px; + } + + .action-card-title { + font-size: 0.92rem; + } + + .action-card-desc { + font-size: 0.8rem; + } + + /* Server card actions */ + .server-card-actions { + flex-wrap: wrap; + } + + .server-card-actions .btn { + flex: 1; + min-width: 0; + } + + /* Power controls grid */ + [style*="display:flex"][style*="gap:8px"][style*="flex-wrap:wrap"] { + gap: 6px !important; + } +} + +/* ─── Small mobile (≤ 480px) ─── */ +@media (max-width: 480px) { + .main-content { + padding: 12px; + padding-top: 56px; + } + + .hamburger-toggle { + top: 10px; + left: 10px; + padding: 8px; + } + + .stat-grid { + grid-template-columns: 1fr; + gap: 10px; + } + + .stat-card { + padding: 14px; + display: flex; + align-items: center; + gap: 14px; + } + + .stat-icon { + margin-bottom: 0; + } + + .stat-card::before { + height: 100%; + } + + .page-title { + font-size: 1.2rem; + } + + .auth-card { + padding: 24px 16px; + } + + .auth-title { + font-size: 1.2rem; + } + + .auth-subtitle { + font-size: 0.82rem; + margin-bottom: 24px; + } + + .form-group input, + .form-group select, + .form-group textarea { + padding: 10px 12px; + font-size: 0.88rem; + } + + .btn { + min-height: 44px; + font-size: 0.85rem; + } + + .btn-sm { + min-height: 36px; + font-size: 0.75rem; + } + + .server-card-name { + font-size: 0.88rem; + } + + .server-card-status { + font-size: 0.65rem; + padding: 2px 8px; + } + + .server-detail-tag { + font-size: 0.68rem; + padding: 3px 7px; + } + + .nest-grid { + grid-template-columns: 1fr 1fr; + gap: 8px; + } + + .nest-card { + padding: 12px 8px; + } + + .nest-card-logo { + width: 40px; + height: 40px; + } + + .nest-card-name { + font-size: 0.78rem; + } + + .wizard-step-indicator { + padding: 4px 6px; + gap: 2px; + } + + .wizard-step-circle { + width: 22px; + height: 22px; + } + + .wizard-step-circle svg { + width: 11px !important; + height: 11px !important; + } + + .wizard-step-label { + font-size: 0.62rem; + } + + .wizard-step-title { + font-size: 1rem; + } + + .wizard-step-desc { + font-size: 0.78rem; + } + + .nest-grid { + grid-template-columns: 1fr 1fr; + gap: 8px; + } + + .nest-card { + padding: 12px 8px; + } + + .nest-card-logo { + width: 40px; + height: 40px; + } + + .nest-card-logo img, + .nest-card-logo i { + width: 28px !important; + height: 28px !important; + } + + .nest-card-name { + font-size: 0.78rem; + } + + .egg-card { + padding: 10px; + gap: 8px; + } + + .egg-card-logo { + width: 30px; + height: 30px; + } + + .egg-card-logo img, + .egg-card-logo i { + width: 24px !important; + height: 24px !important; + } + + .egg-card-name { + font-size: 0.82rem; + } + + .egg-card-desc { + font-size: 0.72rem; + } + + .detail-item { + padding-bottom: 6px; + } + + .resource-gauge-value { + font-size: 1.2rem; + } + + .resource-gauge-label { + font-size: 0.68rem; + } + + .resource-gauge-sub { + font-size: 0.6rem; + } + + .modal { + padding: 20px 16px; + } + + .modal-title { + font-size: 1.05rem; + } + + .admin-navbar { + height: 48px; + padding: 0 8px; + gap: 6px; + } + + .admin-navbar-brand { + font-size: 0.75rem; + gap: 4px; + } + + .admin-nav-link { + padding: 5px 8px; + font-size: 0.72rem; + } + + .admin-content { + padding: 12px; + } + + .page-header .btn-ghost[style*="margin-bottom:16px"] { + margin-bottom: 12px !important; + } + + /* Summary card on very small screens */ + .summary-row { + gap: 4px; + padding: 8px 0; + } + + .summary-label { + font-size: 0.78rem; + } + + .summary-value { + font-size: 0.85rem; + } + + .toast-container { + bottom: 12px; + right: 12px; + left: 12px; + } + + .toast { + padding: 10px 14px; + font-size: 0.78rem; + } + + .cookie-banner { + padding: 12px; + } + + .cookie-banner-actions .btn { + padding: 8px 12px; + font-size: 0.78rem; + } + + /* Notif panel */ + .notif-panel-header { + padding: 12px 12px 10px; + } + + .notif-panel-header h3 { + font-size: 0.92rem; + } + + .notif-mark-all { + font-size: 0.72rem; + padding: 4px 8px; + } + + .notif-item { + padding: 10px 12px; + gap: 8px; + } + + .notif-item-icon { + width: 28px; + height: 28px; + } + + .notif-icon { + width: 14px; + height: 14px; + } + + .notif-item-title { + font-size: 0.8rem; + } + + .notif-item-msg { + font-size: 0.72rem; + } + + .notif-item-time { + font-size: 0.65rem; + } + + .notif-dot { + width: 6px; + height: 6px; + margin-top: 4px; + } + + /* Create page 480px */ + .wizard-step-indicator { + padding: 3px 5px; + gap: 2px; + } + + .wizard-step-circle { + width: 20px; + height: 20px; + } + + .wizard-step-circle svg { + width: 10px !important; + height: 10px !important; + } + + .wizard-step-label { + font-size: 0.58rem; + } + + /* Notif panel */ + .notif-panel-header { + padding: 14px 14px 12px; + } + + .notif-panel-header h3 { + font-size: 0.95rem; + } + + .notif-item { + padding: 10px 14px; + } + + .notif-item-title { + font-size: 0.82rem; + } + + .notif-item-msg { + font-size: 0.75rem; + } + + /* Activity */ + .activity-item { + gap: 8px; + padding: 8px 0; + } + + .activity-icon { + width: 24px; + height: 24px; + font-size: 0.6rem; + } + + .activity-action { + font-size: 0.78rem; + } + + .activity-time { + font-size: 0.65rem; + } + + /* Admin table card layout adjustments */ + .admin-content .table-container tbody td:first-child { + font-size: 0.88rem; + } + + .admin-content .table-container tbody td { + font-size: 0.8rem; + } +} + +/* ===== PYRODACTYL PAGE ===== */ +.ptero-grid { + max-width: 640px; +} + +.ptero-card-icon { + width: 56px; + height: 56px; + border-radius: var(--radius-md); + display: flex; + align-items: center; + justify-content: center; + margin-bottom: 20px; + color: var(--accent-cyan); + background: rgba(34, 211, 238, 0.1); +} + +.ptero-card-title { + font-size: 1.4rem; + font-weight: 700; + margin-bottom: 12px; +} + +.ptero-card-desc { + color: var(--text-secondary); + line-height: 1.7; + margin-bottom: 24px; +} + +.ptero-info { + display: flex; + flex-direction: column; + gap: 14px; +} + +.ptero-info-item { + display: flex; + align-items: flex-start; + gap: 12px; + font-size: 0.9rem; + color: var(--text-secondary); + line-height: 1.5; +} + +.ptero-info-item svg { + flex-shrink: 0; + margin-top: 2px; + color: var(--accent-cyan); +} + +.ptero-info-item span { + flex: 1; +} + +.ptero-info-item strong { + color: var(--text-primary); +} + +/* ===== ACCOUNT PAGE ===== */ .account-grid { display: flex; flex-direction: column; @@ -1811,11 +3166,7 @@ tbody tr:hover { font-weight: 500; } -@media (max-width: 768px) { - .server-detail-grid { - grid-template-columns: 1fr; - } -} +/* server-detail-grid mobile: handled in RESPONSIVE section */ /* ===== RGPD / COOKIE CONSENT ===== */ .cookie-banner { @@ -2237,18 +3588,7 @@ tbody tr:hover { flex: 1; } -@media (max-width: 768px) { - .servers-toolbar { - flex-direction: column; - align-items: stretch; - } - .filter-group { - justify-content: center; - } - .resource-gauges { - grid-template-columns: 1fr; - } -} +/* servers-toolbar + resource-gauges mobile: handled in RESPONSIVE section */ /* ===== ADMIN PANEL ===== */ .admin-layout { @@ -2402,21 +3742,7 @@ tbody tr:hover { z-index: 1; } -@media (max-width: 768px) { - .admin-navbar { - padding: 0 12px; - gap: 8px; - } - .admin-navbar-brand { - font-size: 0.85rem; - } - .admin-navbar-user { - display: none; - } - .admin-content { - padding: 20px; - } -} +/* admin mobile: handled in RESPONSIVE section */ /* ─── Create Wizard ─── */ .wizard-progress { @@ -2538,6 +3864,16 @@ tbody tr:hover { padding-top: 20px; } +.wizard-progress::-webkit-scrollbar { + display: none; +} + +@media (max-width: 768px) { + .wizard-progress { + display: none; + } +} + /* Nest Cards Grid */ .nest-grid { display: grid; diff --git a/public/index.html b/public/index.html index f208569..f02948a 100644 --- a/public/index.html +++ b/public/index.html @@ -17,7 +17,7 @@
- - + +