/* ═══════════════════════════════════════════ SenSu Web Panel — Material Design 3 2026 ═══════════════════════════════════════════ */ /* ── MD3 Color Tokens (Dark Theme) ── */ :root { --md-sys-color-primary: #D0BCFF; --md-sys-color-on-primary: #381E72; --md-sys-color-primary-container: #4F378B; --md-sys-color-on-primary-container: #EADDFF; --md-sys-color-secondary: #CCC2DC; --md-sys-color-on-secondary: #332D41; --md-sys-color-secondary-container: #4A4458; --md-sys-color-on-secondary-container: #E8DEF8; --md-sys-color-tertiary: #EFB8C8; --md-sys-color-on-tertiary: #492532; --md-sys-color-tertiary-container: #633B48; --md-sys-color-on-tertiary-container: #FFD8E4; --md-sys-color-error: #F2B8B5; --md-sys-color-on-error: #601410; --md-sys-color-error-container: #8C1D18; --md-sys-color-on-error-container: #F9DEDC; --md-sys-color-surface: #141218; --md-sys-color-on-surface: #E6E1E5; --md-sys-color-surface-variant: #49454F; --md-sys-color-on-surface-variant: #CAC4D0; --md-sys-color-outline: #938F99; --md-sys-color-outline-variant: #49454F; --md-sys-color-surface-container-lowest: #0F0D13; --md-sys-color-surface-container-low: #1D1B20; --md-sys-color-surface-container: #211F26; --md-sys-color-surface-container-high: #2B2930; --md-sys-color-surface-container-highest: #36343B; /* Aliases for quick refactoring */ --bg: var(--md-sys-color-surface); --bg-card: var(--md-sys-color-surface-container); --bg-elevated: var(--md-sys-color-surface-container-high); --bg-hover: var(--md-sys-color-surface-container-highest); --text: var(--md-sys-color-on-surface); --text-dim: var(--md-sys-color-on-surface-variant); --primary: var(--md-sys-color-primary); --on-primary: var(--md-sys-color-on-primary); --primary-container: var(--md-sys-color-primary-container); --outline: var(--md-sys-color-outline-variant); --error: var(--md-sys-color-error); /* MD3 Elevation */ --md-sys-elevation-0: none; --md-sys-elevation-1: 0 1px 2px 0 rgba(0,0,0,.3), 0 1px 3px 1px rgba(0,0,0,.15); --md-sys-elevation-2: 0 1px 2px 0 rgba(0,0,0,.3), 0 2px 6px 2px rgba(0,0,0,.15); --md-sys-elevation-3: 0 4px 8px 3px rgba(0,0,0,.15), 0 1px 3px 0 rgba(0,0,0,.3); --md-sys-elevation-4: 0 6px 10px 4px rgba(0,0,0,.15), 0 2px 3px 0 rgba(0,0,0,.3); --md-sys-elevation-5: 0 8px 12px 6px rgba(0,0,0,.15), 0 4px 4px 0 rgba(0,0,0,.3); /* MD3 Shape */ --shape-xs: 8px; --shape-sm: 12px; --shape-md: 16px; --shape-lg: 24px; --shape-xl: 28px; --shape-full: 9999px; /* Layout */ --sidebar-w: 260px; --sidebar-collapsed: 64px; --topbar-h: 64px; } /* ── Reset ── */ *,*::before,*::after{box-sizing:border-box;margin:0;padding:0} body{ background:var(--bg);color:var(--text); font-family:"Google Sans",system-ui,-apple-system,"Segoe UI",Roboto,sans-serif; font-size:14px;line-height:1.5;height:100vh;overflow:hidden; -webkit-font-smoothing:antialiased; } /* ── Typography Scale ── */ h2{font-size:1.5rem;font-weight:500;letter-spacing:0;color:var(--text)} h3{font-size:1rem;font-weight:500;letter-spacing:.15px} .display{font-size:2.25rem;font-weight:400;line-height:1.1} .headline{font-size:1.75rem;font-weight:400} .title{font-size:1.25rem;font-weight:500} .label{font-size:.75rem;font-weight:500;letter-spacing:.5px;text-transform:uppercase} .mono{font-family:"JetBrains Mono","Fira Code","Cascadia Code",monospace} /* ── MD3 Surface Tint ── */ .surface{background:var(--bg-card);border-radius:var(--shape-md)} .surface-high{background:var(--bg-elevated);border-radius:var(--shape-md)} .surface-highest{background:var(--bg-hover);border-radius:var(--shape-md)} /* ── MD3 Card ── */ .card{ background:var(--bg-card);border-radius:var(--shape-sm); padding:16px;box-shadow:var(--md-sys-elevation-1); transition:box-shadow .2s,background .2s; } .card:hover{box-shadow:var(--md-sys-elevation-2);background:var(--bg-elevated)} .card.outlined{box-shadow:none;border:1px solid var(--outline)} .card.outlined:hover{border-color:var(--primary);box-shadow:none} /* ── MD3 Button Variants ── */ .btn{ display:inline-flex;align-items:center;justify-content:center;gap:8px; padding:10px 24px;border:none;border-radius:var(--shape-full);font-size:14px; font-weight:500;letter-spacing:.1px;cursor:pointer;transition:.2s;text-decoration:none; line-height:1.25;white-space:nowrap;position:relative;overflow:hidden; } .btn-filled{background:var(--primary);color:var(--on-primary)} .btn-filled:hover{box-shadow:var(--md-sys-elevation-1);filter:brightness(1.08)} .btn-tonal{background:var(--primary-container);color:var(--md-sys-color-on-primary-container)} .btn-tonal:hover{filter:brightness(1.1)} .btn-outlined{border:1px solid var(--outline);background:transparent;color:var(--primary)} .btn-outlined:hover{border-color:var(--primary);background:rgba(208,188,255,.08)} .btn-text{background:transparent;color:var(--primary)} .btn-text:hover{background:rgba(208,188,255,.08)} .btn-danger{color:var(--error)} .btn-danger:hover{background:rgba(242,184,181,.08)} .btn-sm{padding:6px 16px;font-size:12px} .btn-lg{padding:14px 32px;font-size:16px} .btn-icon{width:40px;height:40px;padding:0;border-radius:var(--shape-full)} .btn:disabled{opacity:.38;pointer-events:none} /* ── MD3 Input ── */ .input-group{margin-bottom:16px} .input-group .label{display:block;margin-bottom:6px;color:var(--text-dim)} .input{ width:100%;padding:12px 16px;background:var(--md-sys-color-surface-container-lowest); border:1px solid var(--outline);border-radius:var(--shape-xs);color:var(--text); font-size:14px;transition:border-color .2s,box-shadow .2s;outline:none; } .input:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(208,188,255,.2)} .input::placeholder{color:var(--text-dim);opacity:.6} /* ── MD3 FAB ── */ .fab{ width:56px;height:56px;border-radius:var(--shape-md);background:var(--primary-container); color:var(--md-sys-color-on-primary-container);border:none;cursor:pointer; display:flex;align-items:center;justify-content:center;box-shadow:var(--md-sys-elevation-3); position:fixed;bottom:24px;right:24px;font-size:24px;transition:.2s;z-index:100; } .fab:hover{box-shadow:var(--md-sys-elevation-4);filter:brightness(1.1)} /* ── MD3 Chip ── */ .chip{ display:inline-flex;align-items:center;padding:4px 12px;border-radius:var(--shape-xs); border:1px solid var(--outline);font-size:12px;color:var(--text-dim);gap:6px; background:transparent;transition:.2s; } .chip.active{background:var(--primary-container);color:var(--md-sys-color-on-primary-container);border-color:transparent} /* ── Login Page ── */ .login-wrapper{ display:flex;align-items:center;justify-content:center;height:100vh; background:radial-gradient(circle at 50% 0%,var(--md-sys-color-primary-container) 0%,var(--bg) 70%); } .login-card{ background:var(--md-sys-color-surface-container-high);border-radius:var(--shape-xl); padding:40px 32px;width:360px;text-align:center;box-shadow:var(--md-sys-elevation-4); } .login-card h2{color:var(--primary);margin-bottom:24px} .err-msg{color:var(--error);font-size:.8rem;margin-top:12px;min-height:1.2rem} /* ── App Shell ── */ .app-frame{ display:grid;grid-template-columns:var(--sidebar-w) 1fr; grid-template-rows:var(--topbar-h) 1fr;height:100vh;transition:grid-template-columns .3s cubic-bezier(.4,0,.2,1); } .app-frame.collapsed{grid-template-columns:var(--sidebar-collapsed) 1fr} /* ── Top Bar ── */ .top-bar{ grid-column:1/-1;display:flex;align-items:center;justify-content:space-between; padding:0 24px;background:var(--md-sys-color-surface-container);z-index:10; border-bottom:1px solid var(--outline); } .top-bar .title{font-size:1.15rem;font-weight:500;color:var(--primary);display:flex;align-items:center;gap:8px} .top-bar .user-info{display:flex;align-items:center;gap:12px;color:var(--text-dim);font-size:.85rem} .top-bar .logout-btn{background:transparent;border:1px solid var(--outline);color:var(--text-dim);padding:6px 14px;border-radius:var(--shape-full);cursor:pointer;transition:.2s} .top-bar .logout-btn:hover{border-color:var(--error);color:var(--error)} /* ── Navigation Rail / Sidebar ── */ .sidebar{ background:var(--md-sys-color-surface-container-low);display:flex;flex-direction:column; padding:8px 0;overflow:hidden;transition:.3s;gap:2px; } .nav-item{ display:flex;align-items:center;padding:14px 16px;color:var(--text-dim); text-decoration:none;cursor:pointer;transition:.15s;white-space:nowrap; gap:12px;margin:0 8px;border-radius:var(--shape-full);font-weight:500;font-size:14px; position:relative; } .nav-item:hover{background:rgba(208,188,255,.08);color:var(--text)} .nav-item.active{background:var(--primary-container);color:var(--md-sys-color-on-primary-container)} .nav-item .nav-icon{width:24px;height:24px;flex-shrink:0;display:flex;align-items:center;justify-content:center} .nav-item .nav-label{overflow:hidden;text-overflow:ellipsis} .toggle-sidebar{ margin-top:auto;padding:16px;text-align:center;cursor:pointer; color:var(--text-dim);border-top:1px solid var(--outline); transition:.2s;font-size:12px; } .toggle-sidebar:hover{color:var(--primary)} /* ── Main Content ── */ .content-area{overflow:hidden;display:flex;flex-direction:column;background:var(--bg)} .progress-bar{ position:absolute;top:0;left:0;height:3px;background:var(--primary); width:0;transition:width .3s,opacity .3s;opacity:0;z-index:100;border-radius:0 2px 2px 0; } .progress-bar.active{opacity:1} .page-container{flex:1;padding:24px;overflow-y:auto;scrollbar-width:thin;scrollbar-color:var(--outline) transparent} /* ── Dashboard ── */ .dash-layout{display:flex;gap:24px;height:calc(100vh - var(--topbar-h) - 48px);overflow:hidden} .dash-main{flex:1;overflow-y:auto;scrollbar-width:thin;scrollbar-color:var(--outline) transparent} .dash-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:16px} .stat-card{background:var(--bg-card);border-radius:var(--shape-sm);padding:20px;box-shadow:var(--md-sys-elevation-1);display:flex;flex-direction:column;gap:8px;transition:.2s} .stat-card:hover{box-shadow:var(--md-sys-elevation-2)} .stat-card h3{font-size:.8rem;color:var(--text-dim);text-transform:uppercase;letter-spacing:.5px;font-weight:500} .stat-value{font-size:2rem;font-weight:400;color:var(--text)} .stat-sub{font-size:.75rem;color:var(--text-dim)} .mini-chart{width:100%;height:64px;background:rgba(208,188,255,.05);border-radius:var(--shape-xs);margin-top:8px} .dash-sidebar{width:340px;flex-shrink:0;display:flex;flex-direction:column;gap:16px;overflow-y:auto} .side-card{background:var(--bg-card);border-radius:var(--shape-sm);padding:20px;box-shadow:var(--md-sys-elevation-1)} .side-card h3{font-size:.85rem;color:var(--primary);margin-bottom:12px;padding-bottom:8px;border-bottom:1px solid var(--outline)} .info-row{display:flex;justify-content:space-between;font-size:.82rem;padding:6px 0;color:var(--text-dim)} .info-value{color:var(--text);font-family:monospace;font-weight:500;text-align:right;max-width:60%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap} /* ── Terminal / Log ── */ .terminal{background:var(--md-sys-color-surface-container-lowest);border-radius:var(--shape-sm);overflow:hidden;height:75vh;display:flex;flex-direction:column;box-shadow:var(--md-sys-elevation-1)} .term-header{background:var(--bg-card);padding:8px 16px;font-size:.8rem;color:var(--text-dim);display:flex;justify-content:space-between;align-items:center} .term-body{flex:1;padding:12px;overflow-y:auto;font-family:"JetBrains Mono",monospace;font-size:.8rem;color:#ccc;line-height:1.6;scrollbar-width:thin} .term-input-area{display:flex;border-top:1px solid var(--outline)} .term-input{flex:1;background:transparent;border:none;padding:12px 16px;color:var(--text);font-family:monospace;outline:none;font-size:.85rem} /* ── Log entries ── */ .log-entry{padding:3px 0;border-bottom:1px solid rgba(255,255,255,.03);font-size:.8rem} .log-INFO{color:var(--primary)}.log-WARNING{color:#E0AF68}.log-ERROR{color:var(--error)} /* ── Plugin Cards ── */ .plugin-list{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:16px} .plugin-card{background:var(--bg-card);border-radius:var(--shape-sm);padding:20px;box-shadow:var(--md-sys-elevation-1);display:flex;justify-content:space-between;align-items:center;transition:.2s} .plugin-card:hover{box-shadow:var(--md-sys-elevation-2)} .plugin-info h4{color:var(--primary);font-weight:500;margin-bottom:4px} .plugin-info p{font-size:.8rem;color:var(--text-dim)} .badge{padding:4px 12px;border-radius:var(--shape-full);font-size:.7rem;font-weight:600;letter-spacing:.3px} .badge-run{background:rgba(158,206,106,.15);color:#9ece6a} .badge-stop{background:rgba(242,184,181,.15);color:var(--error)} .plugin-act{display:flex;gap:8px} /* ── Project / Proxy page cards (shared) ── */ .mgmt-card{background:var(--bg-card);border-radius:var(--shape-sm);padding:16px;box-shadow:var(--md-sys-elevation-1);margin-bottom:12px;display:flex;align-items:center;gap:16px;transition:.2s} .mgmt-card:hover{box-shadow:var(--md-sys-elevation-2)} .mgmt-card .info{flex:1} .mgmt-card .info b{color:var(--primary);font-weight:500} .mgmt-card .info small{color:var(--text-dim);font-size:.8rem} .mgmt-card .actions{display:flex;gap:8px;flex-shrink:0} .status-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0} .status-running{background:#9ece6a;box-shadow:0 0 8px rgba(158,206,106,.4)} .status-stopped{background:var(--error);box-shadow:0 0 8px rgba(242,184,181,.4)} .status-error{background:#E0AF68;box-shadow:0 0 8px rgba(224,175,104,.4)} .log-box{background:var(--md-sys-color-surface-container-lowest);border-radius:var(--shape-xs);padding:8px 12px;max-height:300px;overflow-y:auto;font-family:monospace;font-size:11px;color:#0f0;margin-top:8px;display:none} /* ── Tabs ── */ .tabs{display:flex;gap:0;margin-bottom:20px;background:var(--bg-card);border-radius:var(--shape-full);padding:4px;width:fit-content} .tab{padding:8px 20px;border-radius:var(--shape-full);cursor:pointer;font-size:13px;font-weight:500;color:var(--text-dim);transition:.2s} .tab.active{background:var(--primary-container);color:var(--md-sys-color-on-primary-container)} .tab:hover:not(.active){color:var(--text)} /* ── Responsive ── */ @media(max-width:1100px){.dash-layout{flex-direction:column;height:auto;overflow:visible}.dash-sidebar{width:100%}} @media(max-width:768px){.app-frame{grid-template-columns:var(--sidebar-collapsed) 1fr}.nav-label{display:none}.toggle-sidebar{display:none}} /* ═══════════════════════════════════════════ MD3 Light Theme ═══════════════════════════════════════════ */ [data-theme="light"] { --md-sys-color-primary: #6750A4; --md-sys-color-on-primary: #FFFFFF; --md-sys-color-primary-container: #EADDFF; --md-sys-color-on-primary-container: #21005D; --md-sys-color-secondary: #625B71; --md-sys-color-on-secondary: #FFFFFF; --md-sys-color-secondary-container: #E8DEF8; --md-sys-color-on-secondary-container: #1D192B; --md-sys-color-tertiary: #7D5260; --md-sys-color-on-tertiary: #FFFFFF; --md-sys-color-tertiary-container: #FFD8E4; --md-sys-color-on-tertiary-container: #31111D; --md-sys-color-error: #B3261E; --md-sys-color-on-error: #FFFFFF; --md-sys-color-error-container: #F9DEDC; --md-sys-color-on-error-container: #410E0B; --md-sys-color-surface: #FFFBFE; --md-sys-color-on-surface: #1C1B1F; --md-sys-color-surface-variant: #E7E0EC; --md-sys-color-on-surface-variant: #49454F; --md-sys-color-outline: #79747E; --md-sys-color-outline-variant: #CAC4D0; --md-sys-color-surface-container-lowest: #FFFFFF; --md-sys-color-surface-container-low: #F7F2FA; --md-sys-color-surface-container: #F3EDF7; --md-sys-color-surface-container-high: #ECE6F0; --md-sys-color-surface-container-highest: #E6E0E9; --md-sys-elevation-1: 0 1px 2px 0 rgba(0,0,0,.05), 0 1px 3px 1px rgba(0,0,0,.08); --md-sys-elevation-2: 0 1px 2px 0 rgba(0,0,0,.08), 0 2px 6px 2px rgba(0,0,0,.06); --md-sys-elevation-3: 0 4px 8px 3px rgba(0,0,0,.06), 0 1px 3px 0 rgba(0,0,0,.08); --md-sys-elevation-4: 0 6px 10px 4px rgba(0,0,0,.05), 0 2px 3px 0 rgba(0,0,0,.08); --md-sys-elevation-5: 0 8px 12px 6px rgba(0,0,0,.04), 0 4px 4px 0 rgba(0,0,0,.08); --bg: var(--md-sys-color-surface); --bg-card: var(--md-sys-color-surface-container); --bg-elevated: var(--md-sys-color-surface-container-high); --bg-hover: var(--md-sys-color-surface-container-highest); --text: var(--md-sys-color-on-surface); --text-dim: var(--md-sys-color-on-surface-variant); --primary: var(--md-sys-color-primary); --on-primary: var(--md-sys-color-on-primary); --primary-container: var(--md-sys-color-primary-container); --outline: var(--md-sys-color-outline-variant); --error: var(--md-sys-color-error); } /* ── Theme Toggle Button ── */ .theme-toggle{ display:flex;align-items:center;justify-content:center; width:40px;height:40px;border-radius:var(--shape-full); background:transparent;border:none;color:var(--text-dim);cursor:pointer; font-size:20px;transition:.2s; } .theme-toggle:hover{background:rgba(208,188,255,.08)}