/* ============================================ CSS Custom Properties (Themes) ============================================ */ :root { /* Accent Colors - Can be overridden by data-accent */ --accent-primary: #6366f1; --accent-secondary: #8b5cf6; --accent-glow: rgba(99, 102, 241, 0.4); /* Status Colors */ --status-online: #22c55e; --status-offline: #ef4444; --status-checking: #f59e0b; /* Sizing */ --card-radius: 20px; --border-radius: 12px; /* Transitions */ --transition-fast: 150ms ease; --transition-normal: 300ms ease; --transition-slow: 500ms ease; } /* Dark Theme (Default) */ [data-theme="dark"] { --bg-primary: #0a0a0f; --bg-secondary: #12121a; --bg-card: rgba(20, 20, 30, 0.6); --bg-card-hover: rgba(30, 30, 45, 0.8); --text-primary: #ffffff; --text-secondary: #a0a0b0; --text-muted: #6a6a7a; --border-color: rgba(255, 255, 255, 0.08); --border-hover: rgba(255, 255, 255, 0.15); --shadow-card: 0 8px 32px rgba(0, 0, 0, 0.4); --shadow-hover: 0 16px 48px rgba(0, 0, 0, 0.5); --orb-opacity: 0.5; } /* Light Theme */ [data-theme="light"] { --bg-primary: #f5f5f7; --bg-secondary: #ffffff; --bg-card: rgba(255, 255, 255, 0.8); --bg-card-hover: rgba(255, 255, 255, 0.95); --text-primary: #1a1a2e; --text-secondary: #4a4a5a; --text-muted: #8a8a9a; --border-color: rgba(0, 0, 0, 0.08); --border-hover: rgba(0, 0, 0, 0.15); --shadow-card: 0 8px 32px rgba(0, 0, 0, 0.1); --shadow-hover: 0 16px 48px rgba(0, 0, 0, 0.15); --orb-opacity: 0.3; } /* Nord Theme */ [data-theme="nord"] { --bg-primary: #2e3440; --bg-secondary: #3b4252; --bg-card: rgba(59, 66, 82, 0.8); --bg-card-hover: rgba(67, 76, 94, 0.9); --text-primary: #eceff4; --text-secondary: #d8dee9; --text-muted: #a0a8b7; --border-color: rgba(216, 222, 233, 0.1); --border-hover: rgba(216, 222, 233, 0.2); --accent-primary: #88c0d0; --accent-secondary: #81a1c1; --accent-glow: rgba(136, 192, 208, 0.3); --shadow-card: 0 8px 32px rgba(0, 0, 0, 0.3); --shadow-hover: 0 16px 48px rgba(0, 0, 0, 0.4); --orb-opacity: 0.3; } /* Dracula Theme */ [data-theme="dracula"] { --bg-primary: #282a36; --bg-secondary: #1e1f29; --bg-card: rgba(40, 42, 54, 0.8); --bg-card-hover: rgba(68, 71, 90, 0.9); --text-primary: #f8f8f2; --text-secondary: #bd93f9; --text-muted: #6272a4; --border-color: rgba(189, 147, 249, 0.15); --border-hover: rgba(189, 147, 249, 0.3); --accent-primary: #ff79c6; --accent-secondary: #bd93f9; --accent-glow: rgba(255, 121, 198, 0.3); --shadow-card: 0 8px 32px rgba(0, 0, 0, 0.4); --shadow-hover: 0 16px 48px rgba(0, 0, 0, 0.5); --orb-opacity: 0.4; } /* Accent Color Overrides */ [data-accent="indigo"] { --accent-primary: #6366f1; --accent-secondary: #8b5cf6; --accent-glow: rgba(99, 102, 241, 0.4); } [data-accent="purple"] { --accent-primary: #8b5cf6; --accent-secondary: #a78bfa; --accent-glow: rgba(139, 92, 246, 0.4); } [data-accent="pink"] { --accent-primary: #ec4899; --accent-secondary: #f472b6; --accent-glow: rgba(236, 72, 153, 0.4); } [data-accent="red"] { --accent-primary: #ef4444; --accent-secondary: #f87171; --accent-glow: rgba(239, 68, 68, 0.4); } [data-accent="orange"] { --accent-primary: #f97316; --accent-secondary: #fb923c; --accent-glow: rgba(249, 115, 22, 0.4); } [data-accent="yellow"] { --accent-primary: #eab308; --accent-secondary: #facc15; --accent-glow: rgba(234, 179, 8, 0.4); } [data-accent="green"] { --accent-primary: #22c55e; --accent-secondary: #4ade80; --accent-glow: rgba(34, 197, 94, 0.4); } [data-accent="teal"] { --accent-primary: #14b8a6; --accent-secondary: #2dd4bf; --accent-glow: rgba(20, 184, 166, 0.4); } [data-accent="cyan"] { --accent-primary: #06b6d4; --accent-secondary: #22d3ee; --accent-glow: rgba(6, 182, 212, 0.4); } [data-accent="blue"] { --accent-primary: #3b82f6; --accent-secondary: #60a5fa; --accent-glow: rgba(59, 130, 246, 0.4); } /* Card Size Variants */ [data-card-size="compact"] .service-card { padding: 1rem; } [data-card-size="compact"] .card-icon { width: 40px; height: 40px; } [data-card-size="compact"] .card-icon svg { width: 20px; height: 20px; } [data-card-size="compact"] .service-name { font-size: 1rem; } [data-card-size="compact"] .service-description { font-size: 0.85rem; display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; overflow: hidden; } [data-card-size="large"] .service-card { padding: 2rem; } [data-card-size="large"] .card-icon { width: 72px; height: 72px; } [data-card-size="large"] .card-icon svg { width: 36px; height: 36px; } [data-card-size="large"] .service-name { font-size: 1.5rem; } [data-card-size="large"] .service-description { font-size: 1.05rem; } /* ============================================ Reset & Base Styles ============================================ */ *, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; } html { font-size: 16px; scroll-behavior: smooth; } body { font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: var(--bg-primary); color: var(--text-primary); min-height: 100vh; line-height: 1.6; overflow-x: hidden; transition: background var(--transition-normal), color var(--transition-normal); } /* ============================================ Particles Canvas ============================================ */ #particles-canvas { position: fixed; inset: 0; z-index: -2; pointer-events: none; } /* ============================================ Background Effects ============================================ */ .background-effects { position: fixed; inset: 0; z-index: -1; overflow: hidden; pointer-events: none; } .gradient-orb { position: absolute; border-radius: 50%; filter: blur(80px); opacity: var(--orb-opacity, 0.5); animation: float 20s ease-in-out infinite; transition: opacity var(--transition-slow); } .orb-1 { width: 600px; height: 600px; background: linear-gradient(135deg, var(--accent-primary), var(--accent-secondary)); top: -200px; left: -100px; animation-delay: 0s; } .orb-2 { width: 500px; height: 500px; background: linear-gradient(135deg, #ec4899, #8b5cf6); bottom: -150px; right: -100px; animation-delay: -7s; } .orb-3 { width: 400px; height: 400px; background: linear-gradient(135deg, #06b6d4, #3b82f6); top: 50%; left: 50%; transform: translate(-50%, -50%); animation-delay: -14s; } .grid-overlay { position: absolute; inset: 0; background-image: linear-gradient(rgba(255, 255, 255, 0.02) 1px, transparent 1px), linear-gradient(90deg, rgba(255, 255, 255, 0.02) 1px, transparent 1px); background-size: 50px 50px; mask-image: radial-gradient(ellipse at center, black 0%, transparent 70%); } .custom-bg { position: absolute; inset: 0; background-size: cover; background-position: center; opacity: 0.3; } @keyframes float { 0%, 100% { transform: translate(0, 0) scale(1); } 33% { transform: translate(30px, -30px) scale(1.05); } 66% { transform: translate(-20px, 20px) scale(0.95); } } /* Background style variants */ [data-bg="minimal"] .gradient-orb, [data-bg="minimal"] .grid-overlay { display: none; } [data-bg="gradient"] .grid-overlay { display: none; } [data-bg="particles"] .gradient-orb { opacity: 0.3; } /* ============================================ Container ============================================ */ .container { max-width: 1400px; margin: 0 auto; padding: 2rem; min-height: 100vh; display: flex; flex-direction: column; gap: 1.5rem; } /* ============================================ Top Bar ============================================ */ .top-bar { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 1.5rem; padding-bottom: 1.5rem; border-bottom: 1px solid var(--border-color); } .greeting-section { flex: 1; min-width: 250px; } .greeting { font-size: clamp(1.75rem, 4vw, 2.5rem); font-weight: 700; background: linear-gradient(135deg, var(--text-primary), var(--accent-primary)); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; letter-spacing: -0.02em; animation: fadeIn 0.6s ease; } .date-display { color: var(--text-secondary); font-size: 1rem; font-weight: 400; margin-top: 0.25rem; } .clock-weather { display: flex; align-items: center; gap: 1.5rem; } .clock { font-family: 'JetBrains Mono', monospace; display: flex; align-items: baseline; } .clock-time { font-size: 2.5rem; font-weight: 600; color: var(--text-primary); letter-spacing: -0.02em; } .clock-seconds { font-size: 1.25rem; font-weight: 400; color: var(--text-muted); animation: pulse 1s ease-in-out infinite; } @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.4; } } .weather-widget { display: flex; align-items: center; gap: 0.75rem; padding: 0.75rem 1rem; background: var(--bg-card); border: 1px solid var(--border-color); border-radius: var(--border-radius); backdrop-filter: blur(20px); } .weather-icon { font-size: 1.75rem; line-height: 1; } .weather-info { display: flex; flex-direction: column; } .weather-temp { font-size: 1.25rem; font-weight: 600; color: var(--text-primary); line-height: 1.2; } .weather-desc { font-size: 0.75rem; color: var(--text-muted); text-transform: capitalize; } .theme-toggle { width: 44px; height: 44px; display: flex; align-items: center; justify-content: center; background: var(--bg-card); border: 1px solid var(--border-color); border-radius: var(--border-radius); color: var(--text-secondary); cursor: pointer; backdrop-filter: blur(20px); transition: var(--transition-normal); } .theme-toggle svg { width: 20px; height: 20px; transition: var(--transition-normal); } .theme-toggle:hover { background: var(--bg-card-hover); border-color: var(--border-hover); color: var(--text-primary); } .icon-sun { display: none; } .icon-moon { display: block; } [data-theme="light"] .icon-sun { display: block; } [data-theme="light"] .icon-moon { display: none; } /* ============================================ Stats Panel ============================================ */ .stats-panel { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 1rem; } .stat-card { display: flex; align-items: center; gap: 1rem; padding: 1.25rem; background: var(--bg-card); border: 1px solid var(--border-color); border-radius: var(--border-radius); backdrop-filter: blur(20px); transition: var(--transition-normal); } .stat-card:hover { border-color: var(--border-hover); transform: translateY(-2px); } .stat-icon { width: 48px; height: 48px; display: flex; align-items: center; justify-content: center; border-radius: 12px; position: relative; } .stat-icon::before { content: ''; position: absolute; inset: 0; border-radius: inherit; opacity: 0.15; background: currentColor; } .stat-icon svg { width: 24px; height: 24px; position: relative; z-index: 1; } .stat-icon.online { color: var(--status-online); } .stat-icon.offline { color: var(--status-offline); } .stat-icon.total { color: var(--accent-primary); } .stat-icon.uptime { color: #06b6d4; } .stat-content { display: flex; flex-direction: column; } .stat-value { font-size: 1.5rem; font-weight: 700; color: var(--text-primary); line-height: 1.2; } .stat-label { font-size: 0.875rem; color: var(--text-muted); } /* ============================================ Actions Bar ============================================ */ .actions-bar { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; } .search-container { position: relative; display: flex; align-items: center; flex: 1; min-width: 280px; max-width: 500px; } .search-icon { position: absolute; left: 1rem; width: 20px; height: 20px; color: var(--text-muted); pointer-events: none; } .search-input { width: 100%; background: var(--bg-card); border: 1px solid var(--border-color); border-radius: var(--border-radius); padding: 0.875rem 1rem 0.875rem 2.75rem; font-size: 0.95rem; color: var(--text-primary); backdrop-filter: blur(20px); transition: var(--transition-normal); } .search-input::placeholder { color: var(--text-muted); } .search-input:focus { outline: none; border-color: var(--accent-primary); box-shadow: 0 0 0 3px var(--accent-glow); } .search-shortcut { position: absolute; right: 1rem; display: flex; gap: 0.25rem; pointer-events: none; } .search-shortcut kbd { padding: 0.25rem 0.5rem; font-size: 0.7rem; font-family: inherit; background: var(--bg-secondary); border: 1px solid var(--border-color); border-radius: 6px; color: var(--text-muted); } .action-buttons { display: flex; gap: 0.5rem; } .action-btn { display: flex; align-items: center; justify-content: center; width: 48px; height: 48px; background: var(--bg-card); border: 1px solid var(--border-color); border-radius: var(--border-radius); color: var(--text-secondary); cursor: pointer; backdrop-filter: blur(20px); transition: var(--transition-normal); } .action-btn svg { width: 22px; height: 22px; } .action-btn:hover { background: var(--bg-card-hover); border-color: var(--border-hover); color: var(--text-primary); } .action-btn.spinning svg { animation: spin 1s linear infinite; } @keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } /* ============================================ Quick Links ============================================ */ .quick-links { display: flex; gap: 0.75rem; flex-wrap: wrap; } .quick-link { display: flex; align-items: center; gap: 0.5rem; padding: 0.5rem 1rem; background: linear-gradient(135deg, var(--accent-primary), var(--accent-secondary)); border: none; border-radius: 20px; color: white; font-size: 0.875rem; font-weight: 500; text-decoration: none; cursor: pointer; transition: var(--transition-normal); box-shadow: 0 4px 15px var(--accent-glow); } .quick-link:hover { transform: translateY(-2px); box-shadow: 0 6px 20px var(--accent-glow); } .quick-link svg { width: 16px; height: 16px; } /* ============================================ Category Tabs ============================================ */ .category-tabs { display: flex; gap: 0.5rem; flex-wrap: wrap; padding-bottom: 0.5rem; border-bottom: 1px solid var(--border-color); } .category-tab { display: flex; align-items: center; gap: 0.5rem; padding: 0.625rem 1.25rem; background: transparent; border: 1px solid transparent; border-radius: 10px; color: var(--text-secondary); font-size: 0.9rem; font-weight: 500; cursor: pointer; transition: var(--transition-normal); } .category-tab:hover { background: var(--bg-card); color: var(--text-primary); } .category-tab.active { background: var(--bg-card); border-color: var(--border-hover); color: var(--text-primary); } .tab-icon { font-size: 1rem; } .tab-count { padding: 0.125rem 0.5rem; background: var(--bg-secondary); border-radius: 10px; font-size: 0.75rem; color: var(--text-muted); } /* ============================================ Favorites Section ============================================ */ .favorites-section { display: none; } .favorites-section.has-favorites { display: block; } .section-header { display: flex; align-items: center; gap: 0.75rem; margin-bottom: 1rem; } .section-title { font-size: 1.1rem; font-weight: 600; color: var(--text-secondary); } .favorites-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 1rem; } /* ============================================ Services Grid ============================================ */ .services-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 1.5rem; flex: 1; } /* ============================================ Service Card ============================================ */ .service-card { position: relative; background: var(--bg-card); border: 1px solid var(--border-color); border-radius: var(--card-radius); padding: 1.75rem; backdrop-filter: blur(20px); box-shadow: var(--shadow-card); cursor: pointer; transition: all var(--transition-normal); overflow: hidden; text-decoration: none; color: inherit; display: block; } .service-card::before { content: ''; position: absolute; inset: 0; background: linear-gradient(135deg, transparent 0%, rgba(255, 255, 255, 0.03) 100%); opacity: 0; transition: var(--transition-normal); } .service-card::after { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3px; background: linear-gradient(90deg, var(--card-accent, var(--accent-primary)), var(--accent-secondary)); opacity: 0; transition: var(--transition-normal); } .service-card:hover { transform: translateY(-8px) scale(1.02); border-color: var(--border-hover); box-shadow: var(--shadow-hover); } .service-card:hover::before { opacity: 1; } .service-card:hover::after { opacity: 1; } .service-card.hidden { display: none; } /* Favorite indicator */ .service-card.is-favorite::before { content: '⭐'; position: absolute; top: 0.5rem; right: 0.5rem; font-size: 1rem; opacity: 1; background: none; } .card-header { display: flex; align-items: flex-start; justify-content: space-between; margin-bottom: 1rem; } .card-icon { width: 56px; height: 56px; border-radius: 14px; display: flex; align-items: center; justify-content: center; font-size: 1.75rem; position: relative; overflow: hidden; transition: var(--transition-normal); } .service-card:hover .card-icon { transform: scale(1.1); } .card-icon::before { content: ''; position: absolute; inset: 0; opacity: 0.15; background: currentColor; } .card-icon svg { width: 28px; height: 28px; position: relative; z-index: 1; } .card-icon img { width: 32px; height: 32px; object-fit: contain; position: relative; z-index: 1; } /* Status Indicator */ .status-indicator { display: flex; align-items: center; gap: 0.5rem; padding: 0.35rem 0.75rem; border-radius: 20px; font-size: 0.75rem; font-weight: 500; text-transform: uppercase; letter-spacing: 0.05em; transition: var(--transition-normal); } .status-indicator.online { background: rgba(34, 197, 94, 0.15); color: var(--status-online); } .status-indicator.offline { background: rgba(239, 68, 68, 0.15); color: var(--status-offline); } .status-indicator.checking { background: rgba(245, 158, 11, 0.15); color: var(--status-checking); } .status-dot { width: 8px; height: 8px; border-radius: 50%; background: currentColor; } .status-indicator.online .status-dot { animation: pulse-online 2s ease-in-out infinite; } .status-indicator.checking .status-dot { animation: pulse-checking 1s ease-in-out infinite; } @keyframes pulse-online { 0%, 100% { opacity: 1; box-shadow: 0 0 0 0 currentColor; } 50% { opacity: 0.8; box-shadow: 0 0 0 4px transparent; } } @keyframes pulse-checking { 0%, 100% { opacity: 1; } 50% { opacity: 0.3; } } .ping-time { font-size: 0.7rem; color: var(--text-muted); margin-left: 0.25rem; } .card-body { position: relative; z-index: 1; } .service-name { font-size: 1.25rem; font-weight: 600; color: var(--text-primary); margin-bottom: 0.5rem; } .service-description { font-size: 0.95rem; color: var(--text-secondary); line-height: 1.5; margin-bottom: 1rem; } .service-url { display: flex; align-items: center; gap: 0.5rem; font-size: 0.85rem; color: var(--text-muted); word-break: break-all; } .service-url svg { width: 14px; height: 14px; flex-shrink: 0; } /* Card Actions */ .card-actions { position: absolute; top: 0.75rem; right: 0.75rem; display: flex; gap: 0.25rem; opacity: 0; transition: var(--transition-normal); z-index: 20; } .service-card:hover .card-actions { opacity: 1; } .card-action-btn { width: 28px; height: 28px; display: flex; align-items: center; justify-content: center; background: var(--bg-secondary); border: 1px solid var(--border-color); border-radius: 6px; color: var(--text-muted); cursor: pointer; transition: var(--transition-fast); } .card-action-btn:hover { background: var(--bg-card-hover); color: var(--text-primary); } .card-action-btn svg { width: 14px; height: 14px; } /* Card accent colors */ .service-card[data-color="orange"] { --card-accent: #f97316; } .service-card[data-color="orange"] .card-icon { color: #f97316; } .service-card[data-color="blue"] { --card-accent: #3b82f6; } .service-card[data-color="blue"] .card-icon { color: #3b82f6; } .service-card[data-color="green"] { --card-accent: #22c55e; } .service-card[data-color="green"] .card-icon { color: #22c55e; } .service-card[data-color="purple"] { --card-accent: #8b5cf6; } .service-card[data-color="purple"] .card-icon { color: #8b5cf6; } .service-card[data-color="red"] { --card-accent: #ef4444; } .service-card[data-color="red"] .card-icon { color: #ef4444; } .service-card[data-color="cyan"] { --card-accent: #06b6d4; } .service-card[data-color="cyan"] .card-icon { color: #06b6d4; } .service-card[data-color="pink"] { --card-accent: #ec4899; } .service-card[data-color="pink"] .card-icon { color: #ec4899; } .service-card[data-color="yellow"] { --card-accent: #eab308; } .service-card[data-color="yellow"] .card-icon { color: #eab308; } .service-card[data-color="teal"] { --card-accent: #14b8a6; } .service-card[data-color="teal"] .card-icon { color: #14b8a6; } .service-card[data-color="indigo"] { --card-accent: #6366f1; } .service-card[data-color="indigo"] .card-icon { color: #6366f1; } /* ============================================ Footer ============================================ */ .footer { display: flex; justify-content: space-between; align-items: center; padding-top: 1.5rem; border-top: 1px solid var(--border-color); margin-top: auto; } .footer-brand { font-weight: 600; color: var(--text-secondary); } .footer-center p { color: var(--text-muted); font-size: 0.875rem; } .footer-right { display: flex; gap: 0.5rem; } .footer-btn { display: flex; align-items: center; justify-content: center; width: 36px; height: 36px; background: transparent; border: none; color: var(--text-muted); border-radius: 8px; cursor: pointer; transition: var(--transition-normal); } .footer-btn:hover { background: var(--bg-card); color: var(--text-primary); } .footer-btn svg { width: 20px; height: 20px; } /* ============================================ Modal ============================================ */ .modal-overlay { position: fixed; inset: 0; background: rgba(0, 0, 0, 0.7); backdrop-filter: blur(8px); display: flex; align-items: center; justify-content: center; opacity: 0; visibility: hidden; transition: var(--transition-normal); z-index: 1000; padding: 1rem; } .modal-overlay.active { opacity: 1; visibility: visible; } .modal { background: var(--bg-secondary); border: 1px solid var(--border-color); border-radius: var(--card-radius); width: 100%; max-width: 480px; max-height: 90vh; overflow: hidden; transform: scale(0.9) translateY(20px); transition: var(--transition-normal); display: flex; flex-direction: column; } .modal-large { max-width: 560px; } .modal-overlay.active .modal { transform: scale(1) translateY(0); } .modal-header { display: flex; justify-content: space-between; align-items: center; padding: 1.5rem; border-bottom: 1px solid var(--border-color); } .modal-header h2 { font-size: 1.25rem; font-weight: 600; } .modal-close { width: 36px; height: 36px; display: flex; align-items: center; justify-content: center; background: transparent; border: none; border-radius: 8px; color: var(--text-muted); cursor: pointer; transition: var(--transition-normal); } .modal-close:hover { background: var(--bg-card); color: var(--text-primary); } .modal-close svg { width: 20px; height: 20px; } .modal-tabs { display: flex; padding: 0 1.5rem; border-bottom: 1px solid var(--border-color); } .modal-tab { padding: 1rem 1.25rem; background: transparent; border: none; border-bottom: 2px solid transparent; color: var(--text-muted); font-size: 0.9rem; font-weight: 500; cursor: pointer; transition: var(--transition-normal); } .modal-tab:hover { color: var(--text-primary); } .modal-tab.active { color: var(--accent-primary); border-bottom-color: var(--accent-primary); } .modal-body { padding: 1.5rem; display: flex; flex-direction: column; gap: 1.25rem; overflow-y: auto; flex: 1; } .tab-content { display: none; flex-direction: column; gap: 1.25rem; } .tab-content.active { display: flex; } .setting-group { display: flex; flex-direction: column; gap: 0.5rem; } .setting-label { font-size: 0.875rem; font-weight: 500; color: var(--text-secondary); display: flex; align-items: center; gap: 0.5rem; } .setting-hint { font-size: 0.8rem; color: var(--text-muted); } .setting-input, .setting-select, .setting-textarea { padding: 0.75rem 1rem; background: var(--bg-card); border: 1px solid var(--border-color); border-radius: var(--border-radius); font-size: 0.95rem; color: var(--text-primary); font-family: inherit; transition: var(--transition-normal); } .setting-textarea { resize: vertical; min-height: 80px; } .import-textarea { min-height: 150px; font-family: 'JetBrains Mono', monospace; font-size: 0.85rem; } .setting-input:focus, .setting-select:focus, .setting-textarea:focus { outline: none; border-color: var(--accent-primary); } .setting-toggle-group { display: flex; gap: 0.5rem; } .setting-toggle { flex: 1; padding: 0.75rem; background: var(--bg-card); border: 1px solid var(--border-color); border-radius: var(--border-radius); font-size: 0.95rem; font-weight: 500; color: var(--text-muted); cursor: pointer; transition: var(--transition-normal); } .setting-toggle:hover { border-color: var(--border-hover); color: var(--text-primary); } .setting-toggle.active { background: var(--accent-primary); border-color: var(--accent-primary); color: white; } /* Theme Grid */ .theme-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0.75rem; } .theme-option { display: flex; flex-direction: column; align-items: center; gap: 0.5rem; padding: 0.75rem; background: var(--bg-card); border: 2px solid var(--border-color); border-radius: var(--border-radius); cursor: pointer; transition: var(--transition-normal); } .theme-option:hover { border-color: var(--border-hover); } .theme-option.active { border-color: var(--accent-primary); } .theme-option span { font-size: 0.8rem; color: var(--text-secondary); } .theme-preview { width: 100%; height: 40px; border-radius: 6px; } .dark-preview { background: linear-gradient(135deg, #0a0a0f, #12121a); } .light-preview { background: linear-gradient(135deg, #f5f5f7, #ffffff); border: 1px solid rgba(0, 0, 0, 0.1); } .nord-preview { background: linear-gradient(135deg, #2e3440, #4c566a); } .dracula-preview { background: linear-gradient(135deg, #282a36, #44475a); } /* Color Picker */ .color-picker { display: flex; gap: 0.5rem; flex-wrap: wrap; } .color-option { width: 36px; height: 36px; border-radius: 50%; background: var(--preview-color); border: 3px solid transparent; cursor: pointer; transition: var(--transition-normal); position: relative; } .color-option:hover { transform: scale(1.1); } .color-option.active { border-color: var(--text-primary); } .color-option.active::after { content: '✓'; position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; color: white; font-size: 0.9rem; font-weight: bold; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5); } /* Background Options */ .bg-options { display: flex; gap: 0.5rem; flex-wrap: wrap; } .bg-option { padding: 0.5rem 1rem; background: var(--bg-card); border: 1px solid var(--border-color); border-radius: 20px; font-size: 0.85rem; color: var(--text-secondary); cursor: pointer; transition: var(--transition-normal); } .bg-option:hover { border-color: var(--border-hover); color: var(--text-primary); } .bg-option.active { background: var(--accent-primary); border-color: var(--accent-primary); color: white; } .custom-bg-upload { margin-top: 0.75rem; } .upload-label { display: inline-flex; align-items: center; gap: 0.5rem; padding: 0.75rem 1rem; background: var(--bg-card); border: 1px dashed var(--border-color); border-radius: var(--border-radius); color: var(--text-secondary); cursor: pointer; transition: var(--transition-normal); } .upload-label:hover { border-color: var(--accent-primary); color: var(--accent-primary); } .modal-footer { display: flex; justify-content: flex-end; gap: 0.75rem; padding: 1.5rem; border-top: 1px solid var(--border-color); } .btn-primary, .btn-secondary, .btn-danger { padding: 0.75rem 1.5rem; border-radius: var(--border-radius); font-size: 0.95rem; font-weight: 500; cursor: pointer; transition: var(--transition-normal); border: none; } .btn-primary { background: var(--accent-primary); color: white; } .btn-primary:hover { background: var(--accent-secondary); } .btn-secondary { background: var(--bg-card); border: 1px solid var(--border-color); color: var(--text-secondary); } .btn-secondary:hover { background: var(--bg-card-hover); color: var(--text-primary); } .btn-danger { background: var(--status-offline); color: white; } .btn-danger:hover { background: #dc2626; } /* Service Detail Modal */ .service-detail-status { display: flex; align-items: center; gap: 1rem; padding: 1rem; background: var(--bg-card); border-radius: var(--border-radius); } .detail-status-indicator { width: 12px; height: 12px; border-radius: 50%; } .detail-status-indicator.online { background: var(--status-online); } .detail-status-indicator.offline { background: var(--status-offline); } .detail-ping { font-family: 'JetBrains Mono', monospace; font-size: 1.25rem; font-weight: 600; color: var(--text-primary); } /* Uptime History Bar */ .uptime-history { margin-top: 0.5rem; } .uptime-bar { display: flex; gap: 2px; height: 24px; margin-top: 0.5rem; } .uptime-segment { flex: 1; border-radius: 2px; background: var(--bg-card); transition: var(--transition-fast); } .uptime-segment.online { background: var(--status-online); } .uptime-segment.offline { background: var(--status-offline); } .uptime-segment:hover { transform: scaleY(1.2); } /* ============================================ Toast Notifications ============================================ */ .toast-container { position: fixed; bottom: 2rem; right: 2rem; display: flex; flex-direction: column; gap: 0.75rem; z-index: 1001; } .toast { display: flex; align-items: center; gap: 0.75rem; padding: 1rem 1.25rem; background: var(--bg-secondary); border: 1px solid var(--border-color); border-radius: var(--border-radius); box-shadow: var(--shadow-card); animation: slideIn 0.3s ease; } .toast.success { border-left: 4px solid var(--status-online); } .toast.error { border-left: 4px solid var(--status-offline); } .toast.info { border-left: 4px solid var(--accent-primary); } .toast-icon { width: 20px; height: 20px; } .toast.success .toast-icon { color: var(--status-online); } .toast.error .toast-icon { color: var(--status-offline); } .toast.info .toast-icon { color: var(--accent-primary); } .toast-message { font-size: 0.9rem; color: var(--text-primary); } @keyframes slideIn { from { opacity: 0; transform: translateX(100%); } to { opacity: 1; transform: translateX(0); } } @keyframes slideOut { from { opacity: 1; transform: translateX(0); } to { opacity: 0; transform: translateX(100%); } } /* ============================================ Empty State ============================================ */ .empty-state { grid-column: 1 / -1; display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 4rem 2rem; text-align: center; } .empty-state svg { width: 80px; height: 80px; color: var(--text-muted); margin-bottom: 1.5rem; opacity: 0.5; } .empty-state h3 { font-size: 1.5rem; font-weight: 600; color: var(--text-secondary); margin-bottom: 0.5rem; } .empty-state p { color: var(--text-muted); max-width: 400px; } /* ============================================ Responsive Design ============================================ */ @media (max-width: 768px) { .container { padding: 1.5rem; } .top-bar { flex-direction: column; align-items: flex-start; } .clock-weather { width: 100%; justify-content: space-between; } .stats-panel { grid-template-columns: repeat(2, 1fr); } .actions-bar { flex-direction: column; } .search-container { max-width: none; width: 100%; } .action-buttons { align-self: flex-end; } .services-grid { grid-template-columns: 1fr; } .favorites-grid { grid-template-columns: 1fr; } .footer { flex-direction: column; gap: 1rem; text-align: center; } .theme-grid { grid-template-columns: repeat(2, 1fr); } } @media (max-width: 480px) { .container { padding: 1rem; } .greeting { font-size: 1.5rem; } .clock-time { font-size: 1.75rem; } .stats-panel { grid-template-columns: 1fr; } .category-tabs { overflow-x: auto; flex-wrap: nowrap; padding-bottom: 0.75rem; -webkit-overflow-scrolling: touch; } .category-tab { flex-shrink: 0; } .service-card { padding: 1.25rem; } .card-icon { width: 48px; height: 48px; } .card-icon svg, .card-icon img { width: 24px; height: 24px; } .search-shortcut { display: none; } } /* ============================================ Animations ============================================ */ @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } @keyframes fadeInUp { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } } .service-card { animation: fadeInUp 0.5s ease forwards; opacity: 0; } .service-card:nth-child(1) { animation-delay: 0.05s; } .service-card:nth-child(2) { animation-delay: 0.1s; } .service-card:nth-child(3) { animation-delay: 0.15s; } .service-card:nth-child(4) { animation-delay: 0.2s; } .service-card:nth-child(5) { animation-delay: 0.25s; } .service-card:nth-child(6) { animation-delay: 0.3s; } .service-card:nth-child(7) { animation-delay: 0.35s; } .service-card:nth-child(8) { animation-delay: 0.4s; } .stat-card { animation: fadeInUp 0.4s ease forwards; opacity: 0; } .stat-card:nth-child(1) { animation-delay: 0s; } .stat-card:nth-child(2) { animation-delay: 0.05s; } .stat-card:nth-child(3) { animation-delay: 0.1s; } .stat-card:nth-child(4) { animation-delay: 0.15s; } /* ============================================ Scrollbar ============================================ */ ::-webkit-scrollbar { width: 8px; height: 8px; } ::-webkit-scrollbar-track { background: transparent; } ::-webkit-scrollbar-thumb { background: var(--border-color); border-radius: 4px; } ::-webkit-scrollbar-thumb:hover { background: var(--border-hover); } /* Checkbox styling */ input[type="checkbox"] { width: 18px; height: 18px; accent-color: var(--accent-primary); cursor: pointer; } /* ============================================ Maintenance Mode Styles ============================================ */ .status-indicator.maintenance { background: rgba(245, 158, 11, 0.15); color: #f59e0b; } .status-indicator.maintenance .status-dot { background: #f59e0b; animation: none; } .service-card.in-maintenance { border-color: rgba(245, 158, 11, 0.3); } .service-card.in-maintenance::before { content: '🔧'; position: absolute; top: 0.5rem; left: 0.5rem; font-size: 1rem; z-index: 10; } .maintenance-group .setting-hint { margin-bottom: 0.75rem; } .maintenance-options { display: none; flex-direction: column; gap: 0.75rem; padding: 1rem; background: var(--bg-secondary); border-radius: var(--border-radius); margin-top: 0.75rem; } .maintenance-options.visible { display: flex; } .maintenance-until, .maintenance-reason { display: flex; flex-direction: column; gap: 0.5rem; } .maintenance-until label, .maintenance-reason label { font-size: 0.85rem; color: var(--text-secondary); } .maintenance-badge { display: inline-flex; align-items: center; gap: 0.25rem; padding: 0.25rem 0.5rem; background: rgba(245, 158, 11, 0.2); color: #f59e0b; border-radius: 6px; font-size: 0.7rem; font-weight: 600; text-transform: uppercase; } .detail-status-indicator.maintenance { background: rgba(245, 158, 11, 0.15); border-color: rgba(245, 158, 11, 0.3); } /* ============================================ Recently Accessed Section ============================================ */ .recently-accessed-section { display: none; } .recently-accessed-section.has-recent { display: block; } .recently-accessed-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 1rem; margin-top: 1rem; } .recent-card { display: flex; align-items: center; gap: 0.75rem; padding: 0.875rem 1rem; background: var(--bg-card); border: 1px solid var(--border-color); border-radius: var(--border-radius); text-decoration: none; color: var(--text-primary); backdrop-filter: blur(20px); transition: var(--transition-normal); } .recent-card:hover { background: var(--bg-card-hover); border-color: var(--accent-primary); transform: translateY(-2px); box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2); } .recent-card .recent-icon { width: 36px; height: 36px; display: flex; align-items: center; justify-content: center; background: linear-gradient(135deg, var(--accent-primary), var(--accent-secondary)); border-radius: 10px; flex-shrink: 0; } .recent-card .recent-icon svg { width: 18px; height: 18px; color: white; } .recent-card .recent-info { display: flex; flex-direction: column; overflow: hidden; } .recent-card .recent-name { font-weight: 500; font-size: 0.9rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .recent-card .recent-time { font-size: 0.75rem; color: var(--text-muted); } /* ============================================ RSS Widget Styles ============================================ */ .rss-widget { background: var(--bg-card); border: 1px solid var(--border-color); border-radius: var(--card-radius); padding: 1.5rem; backdrop-filter: blur(20px); } .rss-widget .section-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem; } .rss-refresh-btn { width: 36px; height: 36px; display: flex; align-items: center; justify-content: center; background: transparent; border: 1px solid var(--border-color); border-radius: 8px; color: var(--text-secondary); cursor: pointer; transition: var(--transition-normal); } .rss-refresh-btn svg { width: 18px; height: 18px; } .rss-refresh-btn:hover { background: var(--bg-secondary); border-color: var(--border-hover); color: var(--text-primary); } .rss-refresh-btn.spinning svg { animation: spin 1s linear infinite; } .rss-feed-container { display: flex; flex-direction: column; gap: 0.75rem; max-height: 400px; overflow-y: auto; } .rss-loading { text-align: center; padding: 2rem; color: var(--text-muted); } .rss-item { display: flex; gap: 1rem; padding: 0.875rem; background: var(--bg-secondary); border-radius: var(--border-radius); text-decoration: none; color: var(--text-primary); transition: var(--transition-normal); } .rss-item:hover { background: var(--bg-card-hover); transform: translateX(4px); } .rss-item-icon { width: 40px; height: 40px; display: flex; align-items: center; justify-content: center; background: linear-gradient(135deg, var(--accent-primary), var(--accent-secondary)); border-radius: 10px; flex-shrink: 0; font-size: 1.25rem; } .rss-item-content { display: flex; flex-direction: column; gap: 0.25rem; overflow: hidden; } .rss-item-title { font-weight: 500; font-size: 0.9rem; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; } .rss-item-meta { display: flex; gap: 0.75rem; font-size: 0.75rem; color: var(--text-muted); } .rss-item-source { color: var(--accent-primary); font-weight: 500; } .rss-empty { text-align: center; padding: 2rem; color: var(--text-muted); } .rss-empty svg { width: 48px; height: 48px; margin-bottom: 0.75rem; opacity: 0.5; } /* RSS Settings Tab Styles */ .rss-feeds-list { display: flex; flex-direction: column; gap: 0.5rem; margin-bottom: 1rem; max-height: 200px; overflow-y: auto; } .rss-feed-item { display: flex; align-items: center; justify-content: space-between; padding: 0.75rem; background: var(--bg-secondary); border-radius: var(--border-radius); } .rss-feed-item-info { display: flex; flex-direction: column; gap: 0.25rem; } .rss-feed-item-name { font-weight: 500; font-size: 0.9rem; } .rss-feed-item-url { font-size: 0.75rem; color: var(--text-muted); max-width: 250px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .rss-feed-remove { width: 28px; height: 28px; display: flex; align-items: center; justify-content: center; background: transparent; border: none; border-radius: 6px; color: var(--text-muted); cursor: pointer; transition: var(--transition-fast); } .rss-feed-remove:hover { background: rgba(239, 68, 68, 0.2); color: #ef4444; } .rss-feed-remove svg { width: 16px; height: 16px; } .add-feed-form { display: grid; grid-template-columns: 1fr 2fr auto; gap: 0.5rem; align-items: center; } .default-feeds { display: flex; gap: 0.5rem; flex-wrap: wrap; } .default-feeds button { font-size: 0.85rem; padding: 0.5rem 1rem; }