synfull 0.1.4 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ @import"https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;600;700&family=Space+Grotesk:wght@500;600;700&display=swap";@tailwind base;@tailwind components;@tailwind utilities;:root[data-theme]{color:var(--text-main)}:root[data-theme=synfull]{color:#e7ebf3}body{color:var(--text-main);background:radial-gradient(ellipse at 72% -10%,color-mix(in srgb,var(--accent) 10%,transparent),transparent 38%),var(--page-bg)}.sidebar{background:var(--sidebar-bg)}.panel,.metric-card,.skeleton-card{background:var(--panel-bg);border-color:var(--surface-border)}.form-input,.webhook-input-row input{background:var(--field-bg);color:var(--text-main)}:root[data-theme=hacker] body{font-family:ui-monospace,SFMono-Regular,Consolas,monospace}:root[data-theme=hacker] .brand-icon,:root[data-theme=hacker] .metric-icon{background:#062712;color:#40ff8a;box-shadow:0 0 15px #17d45c28}:root[data-theme=hacker] .nav-item.active,:root[data-theme=hacker] .nav-item:hover{background:#0b2615;color:#c8ffd8}:root[data-theme=hacker] .metric-card,:root[data-theme=hacker] .panel{box-shadow:0 0 20px #10a64712,inset 0 1px #7aff9e0c}:root[data-theme=light] .nav-item,:root[data-theme=light] td,:root[data-theme=light] .detail-row,:root[data-theme=light] .metric-title,:root[data-theme=light] .topbar{color:#40506a}:root[data-theme=light] th{color:#586880}:root[data-theme=light] .host-pill,:root[data-theme=light] .console-button,:root[data-theme=light] .throttle-field select{background:#edf1f7;color:#27364e;border-color:#cbd4e1}:root[data-theme=light] .status{background:#d8f4e6;color:#176742}:root[data-theme=light] .metric-icon.blue{background:#e4eaff;color:#315fe8}:root[data-theme=light] .metric-icon.violet{background:#eee6ff;color:#7044b5}:root[data-theme=light] .metric-icon.green{background:#d8f4e6;color:#176742}:root[data-theme=light] .metric-icon.amber{background:#fff0d5;color:#98620a}:root{font-family:DM Sans,sans-serif;color:#e7ebf3;background:#0b111b;font-synthesis:none;text-rendering:optimizeLegibility;--surface:rgba(17,26,39,.82);--surface-border:rgba(134,157,194,.14);--accent:#8290ff;--page-bg:#0b111b;--sidebar-bg:rgba(12,19,30,.88);--panel-bg:linear-gradient(145deg,rgba(20,30,45,.91),rgba(14,22,34,.82));--text-main:#e7ebf3;--text-muted:#8490a2;--field-bg:rgba(7,12,20,.7);--border-color:rgba(134,157,194,.14)}:root[data-theme=monochrome]{--accent:#d1d5db;--page-bg:#111315;--sidebar-bg:rgba(15,17,19,.94);--panel-bg:linear-gradient(145deg,rgba(31,33,35,.96),rgba(22,24,26,.94));--surface-border:rgba(220,224,228,.12);--text-main:#f0f1f2;--text-muted:#9da1a6;--field-bg:rgba(10,11,12,.8)}:root[data-theme=hacker]{--accent:#40ff8a;--page-bg:#020805;--sidebar-bg:rgba(1,10,5,.97);--panel-bg:linear-gradient(145deg,rgba(5,21,12,.98),rgba(3,13,8,.98));--surface-border:rgba(53,255,121,.2);--text-main:#d8ffe5;--text-muted:#80ad8c;--field-bg:#020805}:root[data-theme=light]{--accent:#315fe8;--page-bg:#f1f4f8;--sidebar-bg:rgba(255,255,255,.96);--panel-bg:linear-gradient(145deg,#fff,#f7f9fc);--surface-border:rgba(49,65,89,.14);--text-main:#172033;--text-muted:#627087;--field-bg:#f8fafc;color:var(--text-main)}:root[data-theme=oled]{--accent:#97a6ff;--page-bg:#000;--sidebar-bg:rgba(0,0,0,.98);--panel-bg:linear-gradient(145deg,#08090b,#030405);--surface-border:rgba(154,169,199,.15);--text-main:#eff2f7;--text-muted:#919aaa;--field-bg:#000}*{box-sizing:border-box}body{margin:0;min-width:350px;min-height:100vh;background:radial-gradient(ellipse at 72% -10%,rgba(76,95,192,.17),transparent 38%),radial-gradient(ellipse at 18% 47%,rgba(32,115,119,.09),transparent 32%),#0b111b;background-attachment:fixed}.app-shell{min-height:100vh}.app-shell:before{content:"";position:fixed;top:0;right:0;bottom:0;left:0;pointer-events:none;z-index:-1;opacity:.13;background-image:radial-gradient(rgba(185,202,228,.4) .6px,transparent .6px);background-size:25px 25px;-webkit-mask-image:linear-gradient(to bottom,black,transparent 70%);mask-image:linear-gradient(to bottom,black,transparent 70%)}.sidebar{width:232px;position:fixed;inset:0 auto 0 0;background:#0c131ee0;-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px);border-right:1px solid rgba(134,157,194,.13);padding:25px 16px;display:flex;flex-direction:column;z-index:2;box-shadow:12px 0 50px #0000001f}.brand{display:flex;align-items:center;gap:10px;font-family:Space Grotesk,sans-serif;font-size:21px;font-weight:700;letter-spacing:-.8px;padding:0 10px 42px}.brand-icon{height:31px;width:31px;border-radius:9px;background:linear-gradient(145deg,#8190ff,#5869dc);color:#fff;display:grid;place-items:center;box-shadow:0 5px 20px #6474e540,inset 0 1px #ffffff42}.nav-label,.eyebrow{font-size:10px;letter-spacing:1.2px;color:#728096;font-weight:700}.nav-label{padding:0 11px 10px}.integration-label{padding-top:25px}.nav-item{display:flex;align-items:center;gap:11px;padding:10px 11px;border-radius:7px;color:#8995a8;text-decoration:none;font-size:13px;margin:2px 0;transition:background .15s,color .15s}.nav-item.active,.nav-item:hover{background:linear-gradient(100deg,#6c7edd2e,#6c7edd12);color:#edf0fa}.nav-item.active{box-shadow:inset 2px 0 #91a0ff}.nav-item.active svg{color:#9ba6ff}.nav-badge{margin-left:auto;min-width:19px;height:19px;padding:0 5px;border-radius:12px;display:grid;place-items:center;background:#49342b;color:#f0b57c;font-size:10px;font-weight:700}.nav-badge.online{background:#173a31;color:#65d5a3}.sidebar-bottom{margin-top:auto;border-top:1px solid #202a38;padding:18px 8px 0;color:#a9b3c4;font-size:12px}.sidebar-bottom small{display:block;color:#78869a;margin:6px 0 0 17px}.live-dot{display:inline-block;width:7px;height:7px;background:#49ce9a;border-radius:50%;margin-right:8px;box-shadow:0 0 9px #49ce9a70}.main{margin-left:232px;min-height:100vh;padding:0 36px 22px;max-width:1700px;position:relative}.topbar{height:62px;border-bottom:1px solid rgba(134,157,194,.13);display:flex;align-items:center;justify-content:space-between;font-size:12px;color:#c9d0dd}.eyebrow{margin-right:7px}.connection{color:#a7b2c2;font-size:11px}.page-heading{display:flex;align-items:center;justify-content:space-between;margin:32px 0 23px}.page-heading h1{font-family:Space Grotesk,sans-serif;font-size:24px;letter-spacing:-.8px;margin:0 0 6px}.page-heading p,.panel-head p{margin:0;color:#8490a2;font-size:12px}.host-pill{background:#131d2a;border:1px solid #273344;padding:8px 11px;border-radius:7px;font-size:11px;color:#bcc5d3}.metric-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:14px}.metric-card,.panel{background:linear-gradient(145deg,#141e2de8,#0e1622d1);border:1px solid var(--surface-border);border-radius:12px;box-shadow:0 12px 34px #00000024,inset 0 1px #ffffff06;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);transition:border-color .2s,transform .2s,box-shadow .2s}.metric-card:hover,.panel:hover{border-color:#90a2ff3d;box-shadow:0 16px 42px #0003,inset 0 1px #ffffff09}.metric-card{padding:17px;min-height:143px;position:relative;overflow:hidden}.metric-card:after{content:"";position:absolute;right:-26px;top:-48px;width:100px;height:100px;border-radius:50%;background:#7d8cff0b;filter:blur(2px);pointer-events:none}.metric-icon{width:30px;height:30px;border-radius:7px;display:grid;place-items:center;margin-bottom:12px}.metric-icon svg{width:16px}.blue{color:#8e9cff;background:#222b47}.violet{color:#c097ff;background:#302442}.green{color:#55d7a1;background:#18372f}.amber{color:#f4bd66;background:#393021}.metric-title{font-size:11px;color:#9ba7b9}.metric-value{font-family:Space Grotesk,sans-serif;font-size:24px;letter-spacing:-.8px;margin-top:3px}.metric-note{font-size:10px;color:#738196;margin-top:4px}.content-grid{display:grid;grid-template-columns:minmax(0,1.65fr) minmax(265px,1fr);gap:14px;margin-top:14px}.panel{padding:17px 18px}.panel-head{display:flex;align-items:center;justify-content:space-between}.panel-head h2{font-size:13px;margin:0 0 4px}.panel-head p{font-size:10px}.live-tag{font-size:9px;color:#53d8a3;letter-spacing:.8px}.chart{height:203px;margin:16px -8px -2px -10px}.details-panel .panel-head{margin-bottom:14px}.detail-row{display:flex;justify-content:space-between;gap:10px;border-top:1px solid #222d3a;padding:10px 0;font-size:10px;color:#8e9aab}.detail-row strong{font-weight:500;color:#d2d9e4;text-align:right;overflow-wrap:anywhere}.table-panel{margin-top:14px;padding-bottom:5px}.table-panel>.panel-head{margin-bottom:11px}.text-link{color:#9ba7ff;text-decoration:none;font-size:11px}.table-scroll{width:100%;overflow-x:auto}table{border-collapse:collapse;width:100%;text-align:left;font-size:10px;white-space:nowrap}th{font-size:9px;letter-spacing:.65px;color:#748197;font-weight:600;padding:9px 10px;border-bottom:1px solid #25303e}td{padding:10px;border-bottom:1px solid #202a38;color:#c6cfdd}tbody tr:last-child td{border-bottom:0}.process-name{font-weight:600;color:#e0e6f0}.process-name small{display:block;color:#758297;font-size:9px;font-weight:400;margin-top:3px;max-width:330px;overflow:hidden;text-overflow:ellipsis}.status{background:#173528;color:#67d9a4;padding:3px 7px;border-radius:8px;font-size:9px}.status-stopped{background:#3a3025;color:#e6b56f}.empty{text-align:center;padding:22px;color:#8290a4;font-size:12px}footer{color:#7d899b;font-size:10px;padding:22px 2px}footer span{margin-left:9px;color:#626f82}.alert{margin-top:15px;padding:10px 13px;background:#382827;border:1px solid #66403d;color:#ffc0b9;border-radius:7px;font-size:12px}.route-page{padding-bottom:8px}.process-full{width:100%;margin-top:0}.update-actions{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-top:12px}.update-result{margin:12px 0 0;color:#aab6c8;font-size:11px}.update-command{display:flex;align-items:center;gap:12px;flex-wrap:wrap;border-top:1px solid var(--surface-border);padding-top:12px;margin-top:12px;color:var(--text-muted);font-size:10px}.update-command code{color:var(--text-main);background:var(--field-bg);border:1px solid var(--surface-border);border-radius:6px;padding:8px 10px;font:11px ui-monospace,SFMono-Regular,Consolas,monospace;overflow-wrap:anywhere}.info-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px}.info-card{min-width:0}.info-card>.panel-head{margin-bottom:13px}.info-card>.panel-head>svg{color:#9aa7ff}.info-card .detail-row{font-size:11px}.volume-card,.network-card{border-top:1px solid #222d3a;padding:12px 0}.volume-title{display:flex;justify-content:space-between;gap:10px;font-size:11px}.volume-title span,.volume-caption{font-size:9px;color:#8190a3}.volume-bar{height:6px;background:#222d3a;border-radius:4px;margin:10px 0 6px;overflow:hidden}.volume-bar span{display:block;height:100%;background:linear-gradient(90deg,#6879ee,#9c8aff);border-radius:4px}.network-card>strong{display:block;color:#d6ddea;font-size:11px;margin-bottom:5px}.unsupported{padding:14px 0;color:#909bae;font-size:11px;line-height:1.6}.integration-state{border-radius:20px;padding:7px 10px;font-size:10px;border:1px solid #273344;white-space:nowrap}.state-online{color:#67d9a4;background:#153128}.state-offline{color:#e7b270;background:#342b22}.integration-message{min-height:205px;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;margin-top:12px;padding:35px}.integration-message .metric-icon{margin-bottom:15px}.integration-message h2{font-size:15px;margin:0 0 7px}.integration-message p{max-width:490px;color:#8c99ab;font-size:11px;line-height:1.7;margin:0}.integration-metrics{grid-template-columns:repeat(2,minmax(0,1fr));margin-bottom:14px}.integration-table{margin-top:0}.integration-table>.panel-head{margin-bottom:11px}.container-link{padding:0;border:0;background:none;color:#a7b2ff;font:inherit;font-weight:600;cursor:pointer}.container-link:hover{text-decoration:underline}.container-actions{display:flex;gap:5px}.console-button{border:1px solid #334158;border-radius:5px;padding:5px 8px;background:#1a2636;color:#d7dfed;font:inherit;font-size:9px;cursor:pointer;white-space:nowrap}.console-button:hover:not(:disabled){background:#26364b;border-color:#54698a}.console-button:disabled{opacity:.42;cursor:not-allowed}.secondary-button{padding:7px 10px;font-size:10px}.docker-console{border-top:1px solid #25303e;margin-top:17px;padding-top:15px}.console-header{display:flex;align-items:center;justify-content:space-between;gap:12px}.console-header h3{font-size:12px;margin:0 0 4px}.console-header p{font-size:10px;color:#8794a7;margin:0}.log-output{height:330px;overflow:auto;background:#05090fd4;border:1px solid #202b39;border-radius:7px;padding:13px;color:#c4d2df;font:11px/1.55 ui-monospace,SFMono-Regular,Consolas,monospace;white-space:pre-wrap;overflow-wrap:anywhere;margin:12px 0 0}.console-placeholder{min-height:100px;display:grid;place-items:center;color:#77869a;font-size:11px}.console-alert{margin-top:10px}.discord-alert-panel{margin-top:14px;padding:18px;background:linear-gradient(145deg,#181e30e0,#0e1622d6);border:1px solid rgba(161,139,255,.17);border-radius:12px;box-shadow:0 12px 34px #00000024,inset 0 1px #ffffff06}.discord-alert-heading{display:flex;align-items:center;gap:12px}.discord-alert-heading .metric-icon{flex:none;margin:0;color:#c2a6ff;background:#302744}.discord-alert-heading h3{font-size:13px;margin:0 0 4px}.discord-alert-heading p{color:#8e9bad;font-size:10px;margin:0}.toggle-control{display:flex;align-items:center;gap:8px;margin-left:auto;cursor:pointer}.toggle-control input{position:absolute;opacity:0;width:1px;height:1px}.toggle-track{width:31px;height:18px;border-radius:20px;background:#303b4c;position:relative;transition:background .18s}.toggle-track:after{content:"";position:absolute;width:12px;height:12px;top:3px;left:3px;border-radius:50%;background:#a2afc1;transition:transform .18s,background .18s}.toggle-control input:checked+.toggle-track{background:#365c50}.toggle-control input:checked+.toggle-track:after{transform:translate(13px);background:#75e0ad}.toggle-control input:focus-visible+.toggle-track{outline:2px solid #a6a5ff;outline-offset:2px}.toggle-label{color:#a9b4c4;font-size:10px;min-width:44px}.webhook-field{margin-top:18px}.webhook-field>label,.alert-options-title{display:block;color:#cbd4e1;font-size:10px;font-weight:600;margin-bottom:7px}.webhook-input-row{display:flex;gap:8px}.webhook-input-row input{width:100%;min-width:0;background:#070c14b3;border:1px solid #2c394b;border-radius:6px;padding:9px 11px;color:#dbe3ef;font:11px DM Sans,sans-serif;outline:none}.webhook-input-row input:focus{border-color:#8c83df;box-shadow:0 0 0 3px #8c83df1f}.webhook-input-row input::placeholder{color:#6f7d91}.webhook-field small{display:block;color:#77869a;font-size:9px;margin-top:6px}.alert-options{display:flex;flex-wrap:wrap;gap:8px 18px;margin-top:17px}.alert-option{display:flex;align-items:center;gap:7px;color:#aeb9c9;font-size:10px;cursor:pointer}.alert-option input{position:absolute;opacity:0;width:1px;height:1px}.check-ui{width:14px;height:14px;border:1px solid #445269;border-radius:4px;background:#121b28;position:relative}.alert-option input:checked+.check-ui{background:#756dcc;border-color:#9289ed}.alert-option input:checked+.check-ui:after{content:"";position:absolute;left:4px;top:1px;width:4px;height:7px;border:solid white;border-width:0 1.5px 1.5px 0;transform:rotate(45deg)}.alert-option input:focus-visible+.check-ui{outline:2px solid #a6a5ff;outline-offset:2px}.alert-form-footer{display:flex;align-items:center;justify-content:space-between;gap:12px;border-top:1px solid rgba(134,157,194,.1);padding-top:14px;margin-top:17px}.throttle-field{display:flex;align-items:center;gap:9px;color:#8e9bad;font-size:10px}.throttle-field select{background:#111a27;color:#d4deeb;border:1px solid #2c394b;border-radius:5px;padding:6px 8px;font-size:10px}.save-alert-button{background:linear-gradient(120deg,#5c65bf,#7064bd);border-color:#8479d4;padding:7px 11px}.save-alert-button:hover:not(:disabled){background:linear-gradient(120deg,#6b75d3,#8275d4)}.alert-success{margin-top:11px;color:#76ddb0;background:#235f452e;border:1px solid rgba(80,180,130,.17);border-radius:6px;padding:8px 10px;font-size:10px}.dashboard-skeleton{display:flex;flex-direction:column;gap:14px}.skeleton-metric-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:14px}.skeleton-metric-grid.two-columns{grid-template-columns:repeat(2,minmax(0,1fr));margin-bottom:14px}.skeleton-content-grid{display:grid;grid-template-columns:minmax(0,1.65fr) minmax(265px,1fr);gap:14px}.skeleton-card{background:linear-gradient(145deg,#141e2dc7,#0e1622b3);border:1px solid var(--surface-border);border-radius:12px;padding:17px 18px;overflow:hidden}.metric-skeleton{min-height:143px}.skeleton{position:relative;overflow:hidden;background:#8999b41c;border-radius:6px}.skeleton:after{content:"";position:absolute;top:0;right:0;bottom:0;left:0;transform:translate(-100%);background:linear-gradient(90deg,transparent,rgba(200,214,241,.1),transparent);animation:skeleton-shimmer 1.7s ease-in-out infinite}.skeleton-icon{width:30px;height:30px;border-radius:8px;margin-bottom:13px}.skeleton-line{height:9px;margin:12px 0}.skeleton-line.short{width:38%}.skeleton-line.medium{width:62%}.skeleton-line.full{width:100%;height:26px;margin:0;border-radius:0;background:transparent;border-bottom:1px solid rgba(134,157,194,.08)}.skeleton-line.full:after{top:8px;right:0;bottom:8px;left:0;background:linear-gradient(90deg,transparent,rgba(200,214,241,.08),transparent)}.skeleton-line.value-line{height:25px;width:54%;margin:8px 0}.chart-skeleton{min-height:255px}.skeleton-chart{height:185px;margin-top:20px;background:linear-gradient(180deg,#8290ff14,#8290ff04);border-bottom:1px solid rgba(134,157,194,.11);border-radius:4px}.detail-skeleton{min-height:255px}.table-skeleton{min-height:160px}.skeleton-row{height:29px;margin-top:12px;border-radius:4px;background:linear-gradient(90deg,rgba(137,153,180,.05) 0 28%,transparent 28% 37%,rgba(137,153,180,.05) 37% 56%,transparent 56% 65%,rgba(137,153,180,.05) 65% 82%,transparent 82%)}.process-skeleton{padding:9px 16px}.process-skeleton .skeleton-row{display:flex;align-items:center;justify-content:space-between;height:46px;margin:0;border-radius:0;border-bottom:1px solid rgba(134,157,194,.08);background:none}.process-skeleton .skeleton-line{height:8px;margin:0}.process-skeleton .skeleton-line:first-child{width:36%}.process-skeleton .skeleton-line:nth-child(2){width:12%}.process-skeleton .skeleton-line:nth-child(3){width:20%}.info-skeleton{min-height:220px}.info-skeleton .skeleton-line.full{height:30px}@keyframes skeleton-shimmer{to{transform:translate(100%)}}@media(prefers-reduced-motion:reduce){*,*:before,*:after{scroll-behavior:auto!important;animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}}@media(max-width:1000px){.skeleton-metric-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.skeleton-content-grid{grid-template-columns:1fr}.sidebar{width:190px}.main{margin-left:190px;padding-left:22px;padding-right:22px}.metric-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.content-grid{grid-template-columns:1fr}}@media(max-width:650px){.sidebar{width:58px;padding:19px 8px;overflow-y:auto}.brand{padding:0 5px 34px}.brand>span,.nav-label,.nav-item span:not(.nav-badge){font-size:0}.nav-item{justify-content:center;padding:11px 0;gap:0}.nav-item svg{width:18px;height:18px}.nav-badge{position:absolute;margin-left:32px;margin-top:-17px;min-width:15px;height:15px;font-size:8px;padding:0 3px}.sidebar-bottom{font-size:0;padding:15px 5px}.sidebar-bottom small{display:none}.main{margin-left:58px;padding:0 14px 20px}.topbar{font-size:10px}.page-heading{align-items:flex-start;gap:10px}.page-heading h1{font-size:20px}.host-pill,.integration-state{font-size:9px}.metric-grid{gap:9px}.metric-card{padding:13px;min-height:134px}.metric-value{font-size:20px}.content-grid{gap:9px}.panel{padding:14px}.chart{height:180px}.process-name small{max-width:150px}.info-grid,.skeleton-content-grid{grid-template-columns:1fr}.skeleton-metric-grid{gap:9px}.skeleton-card{padding:14px}.volume-title{flex-wrap:wrap}.discord-alert-panel{padding:14px}.discord-alert-heading{flex-wrap:wrap}.toggle-control{width:100%;margin-left:42px}.alert-form-footer{align-items:flex-start;flex-direction:column}.save-alert-button{align-self:stretch}.webhook-input-row{flex-direction:column}.webhook-input-row button{align-self:flex-start}.integration-metrics{grid-template-columns:repeat(2,minmax(0,1fr))}}.auth-screen{min-height:100vh;display:grid;place-items:center;padding:24px;background:radial-gradient(ellipse at 50% 25%,rgba(93,107,193,.2),transparent 45%)}.auth-card{width:min(100%,430px);padding:30px}.auth-card h1{font:600 23px Space Grotesk,sans-serif;margin:18px 0 8px}.auth-card>p,.muted{color:#8e9bad;font-size:11px;line-height:1.6;margin:0 0 18px}.auth-card small{display:block;color:#78869a;font-size:10px;margin:6px 0 12px}.form-label{display:block;color:#cbd4e1;font-size:11px;font-weight:600;margin:13px 0 7px}.form-input{width:100%;min-width:0;background:#070c14b3;border:1px solid #2c394b;border-radius:6px;padding:9px 11px;color:#dbe3ef;font:11px DM Sans,sans-serif;outline:none}.form-input:focus{border-color:#8c83df;box-shadow:0 0 0 3px #8c83df1f}.auth-submit{display:flex;align-items:center;justify-content:center;gap:8px;width:100%;margin-top:18px;padding:10px;background:linear-gradient(120deg,#5c65bf,#7064bd);border-color:#8479d4;font-size:12px}.topbar-actions{display:flex;align-items:center;gap:12px}.user-chip{color:#b9c3d2;font-size:10px}.nav-label.integration-label{margin-top:14px;padding-top:13px;border-top:1px solid rgba(134,157,194,.08)}.config-panel{margin-top:14px}.config-panel h2,.history-chart h2{font-size:13px;margin:0 0 6px}.form-row{display:flex;align-items:center;gap:8px;margin:12px 0;flex-wrap:wrap}.form-row .form-input{flex:1 1 180px}.small-input{max-width:110px!important}.save-button{margin-right:8px}.security-summary{display:flex;align-items:center;gap:12px;padding:4px 0 18px;margin-bottom:18px;border-bottom:1px solid #25303e}.security-summary>svg{color:#9ba7ff;flex:none}.security-summary strong{font-size:12px}.security-summary p{margin:4px 0 0}.config-panel h2:not(:first-child){margin-top:20px}.chip-list{display:flex;flex-wrap:wrap;gap:6px;margin:10px 0}.target-chip{border:1px solid #354258;border-radius:16px;background:#172234;color:#cbd4e1;padding:5px 9px;font-size:10px;cursor:pointer}.history-chart{margin-top:14px}.history-chart .chart{height:300px;margin-top:14px}.threshold-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:14px}.threshold-input{display:flex;align-items:center;gap:8px}.threshold-input span{font-size:11px;color:#8e9bad}.log-search{max-width:560px}.auth-card .alert{margin-top:10px}@media(max-width:650px){.auth-card{padding:22px}.topbar-actions{gap:5px}.user-chip{display:none}.form-row{align-items:stretch}.form-row .form-input{flex-basis:100%}.threshold-grid{grid-template-columns:1fr}.history-chart .chart{height:230px}.nav-label.integration-label{font-size:0;padding:7px 0;margin-top:6px}.nav-label.integration-label:after{content:"·";font-size:16px;display:block;text-align:center}}:root[data-theme] body{color:var(--text-main);background:radial-gradient(ellipse at 72% -10%,color-mix(in srgb,var(--accent) 10%,transparent),transparent 38%),var(--page-bg)}:root[data-theme] .sidebar{background:var(--sidebar-bg)}:root[data-theme] .panel,:root[data-theme] .metric-card,:root[data-theme] .skeleton-card{background:var(--panel-bg);border-color:var(--surface-border)}:root[data-theme] .form-input,:root[data-theme] .webhook-input-row input{background:var(--field-bg);color:var(--text-main)}:root[data-theme] .theme-choice{background:var(--panel-bg);color:var(--text-main);border:1px solid var(--surface-border);border-radius:8px;padding:13px;text-align:left;cursor:pointer;transition:border-color .15s,transform .15s}:root[data-theme] .theme-choice:hover,:root[data-theme] .theme-choice.selected{border-color:var(--accent);transform:translateY(-1px)}:root[data-theme] .theme-choice strong,:root[data-theme] .theme-choice span{display:block}:root[data-theme] .theme-choice span{color:var(--text-muted);font-size:10px;line-height:1.5;margin-top:5px}.theme-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:9px;margin-top:12px}.permission-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:9px;margin-top:12px}.user-list{display:grid;gap:10px}.user-card{padding:13px;border:1px solid var(--surface-border);border-radius:8px}.user-card-heading{display:flex;justify-content:space-between;gap:8px;color:var(--text-main);font-size:11px}.user-card-heading span{color:var(--text-muted)}:root[data-theme=monochrome] .nav-item.active,:root[data-theme=monochrome] .nav-item:hover{background:#ffffff10;color:#fff}:root[data-theme=monochrome] .nav-item.active,:root[data-theme=monochrome] .nav-item.active svg{color:#fff}:root[data-theme=monochrome] .metric-icon.blue,:root[data-theme=monochrome] .metric-icon.violet,:root[data-theme=monochrome] .metric-icon.green,:root[data-theme=monochrome] .metric-icon.amber{background:#303234;color:#e5e7eb}@media(max-width:650px){.theme-grid,.permission-grid{grid-template-columns:1fr}}
@@ -5,8 +5,8 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <meta name="theme-color" content="#0b1220" />
7
7
  <title>Synfull</title>
8
- <script type="module" crossorigin src="/assets/index-hx4yW_Xg.js"></script>
9
- <link rel="stylesheet" crossorigin href="/assets/index-B40UafPr.css">
8
+ <script type="module" crossorigin src="/assets/index-BdVFYwZZ.js"></script>
9
+ <link rel="stylesheet" crossorigin href="/assets/index-pBaLmQTy.css">
10
10
  </head>
11
11
  <body>
12
12
  <div id="root"></div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "synfull",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "Local-first cross-platform host monitoring dashboard",
5
5
  "license": "MIT",
6
6
  "type": "commonjs",
@@ -224,6 +224,92 @@ function stopServer() {
224
224
  fs.rmSync(PID_FILE, { force: true })
225
225
  console.log('Synfull stopped.')
226
226
  }
227
+ function processExists(pid) {
228
+ try { process.kill(pid, 0); return true } catch (error) { return error.code === 'EPERM' }
229
+ }
230
+ function sleep(milliseconds) {
231
+ return new Promise(resolve => setTimeout(resolve, milliseconds))
232
+ }
233
+ async function waitForProcessExit(pid, timeoutMs = 15000) {
234
+ const deadline = Date.now() + timeoutMs
235
+ while (processExists(pid) && Date.now() < deadline) await sleep(250)
236
+ if (processExists(pid)) throw new Error(`Synfull process ${pid} did not stop; the runtime was not updated.`)
237
+ }
238
+ function windowsTaskStatus() {
239
+ const result = spawnSync('schtasks.exe', ['/Query', '/TN', 'Synfull', '/FO', 'LIST'], { encoding: 'utf8', windowsHide: true })
240
+ if (result.status !== 0) return null
241
+ const status = (result.stdout || '').match(/^Status:\s*(.+)$/im)
242
+ return status?.[1]?.trim() || 'Ready'
243
+ }
244
+ async function waitForWindowsTaskStopped(timeoutMs = 15000) {
245
+ const deadline = Date.now() + timeoutMs
246
+ while (/running/i.test(windowsTaskStatus() || '') && Date.now() < deadline) await sleep(500)
247
+ if (/running/i.test(windowsTaskStatus() || '')) throw new Error('Synfull scheduled task did not stop; the runtime was not updated.')
248
+ }
249
+ async function reloadServer(options = {}) {
250
+ const windows = options.windows ?? WINDOWS
251
+ const spawnCommand = options.spawnSync || spawnSync
252
+ const runCommand = options.run || run
253
+ const ensure = options.ensureRuntime || ensureRuntime
254
+ const processAlive = options.processExists || processExists
255
+ const stop = options.stopServer || stopServer
256
+ const start = options.startServer || (() => startServer(false))
257
+ const startScheduledTask = options.startScheduledTask || (() => runCommand('schtasks.exe', ['/Run', '/TN', 'Synfull']))
258
+ const pidFile = options.pidFile || PID_FILE
259
+
260
+ if (windows) {
261
+ const query = spawnCommand('schtasks.exe', ['/Query', '/TN', 'Synfull', '/FO', 'LIST'], { encoding: 'utf8', windowsHide: true })
262
+ const status = query.status === 0 ? ((query.stdout || '').match(/^Status:\s*(.+)$/im)?.[1]?.trim() || 'Ready') : null
263
+ if (status !== null) {
264
+ if (/running/i.test(status)) {
265
+ runCommand('schtasks.exe', ['/End', '/TN', 'Synfull'])
266
+ const waitForTask = options.waitForWindowsTaskStopped || waitForWindowsTaskStopped
267
+ await waitForTask()
268
+ }
269
+ ensure()
270
+ startScheduledTask()
271
+ console.log('Synfull runtime refreshed and scheduled task started.')
272
+ return
273
+ }
274
+ } else {
275
+ const service = spawnCommand('systemctl', ['cat', 'synfull-npm.service'], { stdio: 'ignore', windowsHide: true })
276
+ if (service.status === 0) {
277
+ const active = spawnCommand('systemctl', ['is-active', '--quiet', 'synfull-npm.service'], { stdio: 'ignore', windowsHide: true }).status === 0
278
+ if (active) runCommand('sudo', ['systemctl', 'stop', 'synfull-npm.service'])
279
+ try {
280
+ ensure()
281
+ } catch (error) {
282
+ if (active) {
283
+ try { runCommand('sudo', ['systemctl', 'start', 'synfull-npm.service']) }
284
+ catch (restartError) { error.message += ` The previous service could not be restored: ${restartError.message}` }
285
+ }
286
+ throw error
287
+ }
288
+ if (!active) {
289
+ console.log('Synfull runtime refreshed; the systemd service was already stopped and remains stopped.')
290
+ return
291
+ }
292
+ runCommand('sudo', ['systemctl', 'start', 'synfull-npm.service'])
293
+ const restarted = spawnCommand('systemctl', ['is-active', '--quiet', 'synfull-npm.service'], { stdio: 'ignore', windowsHide: true }).status === 0
294
+ if (!restarted) throw new Error('Synfull runtime was refreshed, but the systemd service did not become active. Check `systemctl status synfull-npm.service`.')
295
+ console.log('Synfull runtime refreshed and systemd service started.')
296
+ return
297
+ }
298
+ }
299
+
300
+ if (fs.existsSync(pidFile)) {
301
+ const pid = Number(fs.readFileSync(pidFile, 'utf8'))
302
+ if (Number.isInteger(pid) && processAlive(pid)) {
303
+ stop()
304
+ const waitForExit = options.waitForProcessExit || waitForProcessExit
305
+ await waitForExit(pid)
306
+ } else {
307
+ fs.rmSync(pidFile, { force: true })
308
+ }
309
+ }
310
+ ensure()
311
+ start()
312
+ }
227
313
  function status() {
228
314
  let running = false
229
315
  let pid = ''
@@ -276,7 +362,7 @@ function uninstallStartup() {
276
362
  console.log('Synfull startup registration removed; application data was retained.')
277
363
  }
278
364
  function help() {
279
- console.log(`Synfull ${VERSION}\n\nUsage: synfull <command>\n\nCommands:\n setup Prepare local runtime and install Python dependencies\n start Start Synfull in the background\n run Run Synfull in the foreground (for service managers)\n stop Stop a background Synfull process\n status Show status and local URLs\n open Open the local dashboard\n install-service Register start-at-login (Windows) or start-at-boot (Linux)\n uninstall-service Remove startup registration without deleting data\n\nSetup asks whether to allow LAN connections; localhost-only is the default. Use a trusted LAN, open the port in your firewall only as needed, and change the initial admin password locally before remote sign-in.`)
365
+ console.log(`Synfull ${VERSION}\n\nUsage: synfull <command>\n\nCommands:\n setup Prepare local runtime and install Python dependencies\n start Start Synfull in the background\n reload Refresh installed files from this package and restart Synfull\n run Run Synfull in the foreground (for service managers)\n stop Stop a background Synfull process\n status Show status and local URLs\n open Open the local dashboard\n install-service Register start-at-login (Windows) or start-at-boot (Linux)\n uninstall-service Remove startup registration without deleting data\n\nSetup asks whether to allow LAN connections; localhost-only is the default. Use a trusted LAN, open the port in your firewall only as needed, and change the initial admin password locally before remote sign-in.`)
280
366
  }
281
367
  async function main() {
282
368
  const command = process.argv[2]
@@ -290,6 +376,7 @@ async function main() {
290
376
  console.log(`Runtime ready. Data directory: ${STATE_DIR}`)
291
377
  }
292
378
  else if (command === 'start') startServer(false)
379
+ else if (command === 'reload') await reloadServer()
293
380
  else if (command === 'run') startServer(true)
294
381
  else if (command === 'stop') stopServer()
295
382
  else if (command === 'status') status()
@@ -304,4 +391,4 @@ async function main() {
304
391
  else help()
305
392
  }
306
393
  if (require.main === module) main().catch(error => { console.error(`Synfull: ${error.message}`); process.exitCode = 1 })
307
- module.exports = { ensureRuntime, serverEnvironment, configuredBindHost, selectedBindHost, saveBindHost, configureDockerAccess, restartSynfullService, APP_DIR, STATE_DIR, ROOT }
394
+ module.exports = { ensureRuntime, serverEnvironment, configuredBindHost, selectedBindHost, saveBindHost, configureDockerAccess, restartSynfullService, reloadServer, APP_DIR, STATE_DIR, ROOT }
@@ -1 +0,0 @@
1
- @import"https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;600;700&family=Space+Grotesk:wght@500;600;700&display=swap";@tailwind base;@tailwind components;@tailwind utilities;:root[data-theme]{color:var(--text-main)}:root[data-theme=synfull]{color:#e7ebf3}body{color:var(--text-main);background:radial-gradient(ellipse at 72% -10%,color-mix(in srgb,var(--accent) 10%,transparent),transparent 38%),var(--page-bg)}.sidebar{background:var(--sidebar-bg)}.panel,.metric-card,.skeleton-card{background:var(--panel-bg);border-color:var(--surface-border)}.form-input,.webhook-input-row input{background:var(--field-bg);color:var(--text-main)}:root[data-theme=hacker] body{font-family:ui-monospace,SFMono-Regular,Consolas,monospace}:root[data-theme=hacker] .brand-icon,:root[data-theme=hacker] .metric-icon{background:#062712;color:#40ff8a;box-shadow:0 0 15px #17d45c28}:root[data-theme=hacker] .nav-item.active,:root[data-theme=hacker] .nav-item:hover{background:#0b2615;color:#c8ffd8}:root[data-theme=hacker] .metric-card,:root[data-theme=hacker] .panel{box-shadow:0 0 20px #10a64712,inset 0 1px #7aff9e0c}:root[data-theme=light] .nav-item,:root[data-theme=light] td,:root[data-theme=light] .detail-row,:root[data-theme=light] .metric-title,:root[data-theme=light] .topbar{color:#40506a}:root[data-theme=light] th{color:#586880}:root[data-theme=light] .host-pill,:root[data-theme=light] .console-button,:root[data-theme=light] .throttle-field select{background:#edf1f7;color:#27364e;border-color:#cbd4e1}:root[data-theme=light] .status{background:#d8f4e6;color:#176742}:root[data-theme=light] .metric-icon.blue{background:#e4eaff;color:#315fe8}:root[data-theme=light] .metric-icon.violet{background:#eee6ff;color:#7044b5}:root[data-theme=light] .metric-icon.green{background:#d8f4e6;color:#176742}:root[data-theme=light] .metric-icon.amber{background:#fff0d5;color:#98620a}:root{font-family:DM Sans,sans-serif;color:#e7ebf3;background:#0b111b;font-synthesis:none;text-rendering:optimizeLegibility;--surface:rgba(17,26,39,.82);--surface-border:rgba(134,157,194,.14);--accent:#8290ff;--page-bg:#0b111b;--sidebar-bg:rgba(12,19,30,.88);--panel-bg:linear-gradient(145deg,rgba(20,30,45,.91),rgba(14,22,34,.82));--text-main:#e7ebf3;--text-muted:#8490a2;--field-bg:rgba(7,12,20,.7);--border-color:rgba(134,157,194,.14)}:root[data-theme=monochrome]{--accent:#d1d5db;--page-bg:#111315;--sidebar-bg:rgba(15,17,19,.94);--panel-bg:linear-gradient(145deg,rgba(31,33,35,.96),rgba(22,24,26,.94));--surface-border:rgba(220,224,228,.12);--text-main:#f0f1f2;--text-muted:#9da1a6;--field-bg:rgba(10,11,12,.8)}:root[data-theme=hacker]{--accent:#40ff8a;--page-bg:#020805;--sidebar-bg:rgba(1,10,5,.97);--panel-bg:linear-gradient(145deg,rgba(5,21,12,.98),rgba(3,13,8,.98));--surface-border:rgba(53,255,121,.2);--text-main:#d8ffe5;--text-muted:#80ad8c;--field-bg:#020805}:root[data-theme=light]{--accent:#315fe8;--page-bg:#f1f4f8;--sidebar-bg:rgba(255,255,255,.96);--panel-bg:linear-gradient(145deg,#fff,#f7f9fc);--surface-border:rgba(49,65,89,.14);--text-main:#172033;--text-muted:#627087;--field-bg:#f8fafc;color:var(--text-main)}:root[data-theme=oled]{--accent:#97a6ff;--page-bg:#000;--sidebar-bg:rgba(0,0,0,.98);--panel-bg:linear-gradient(145deg,#08090b,#030405);--surface-border:rgba(154,169,199,.15);--text-main:#eff2f7;--text-muted:#919aaa;--field-bg:#000}*{box-sizing:border-box}body{margin:0;min-width:350px;min-height:100vh;background:radial-gradient(ellipse at 72% -10%,rgba(76,95,192,.17),transparent 38%),radial-gradient(ellipse at 18% 47%,rgba(32,115,119,.09),transparent 32%),#0b111b;background-attachment:fixed}.app-shell{min-height:100vh}.app-shell:before{content:"";position:fixed;top:0;right:0;bottom:0;left:0;pointer-events:none;z-index:-1;opacity:.13;background-image:radial-gradient(rgba(185,202,228,.4) .6px,transparent .6px);background-size:25px 25px;-webkit-mask-image:linear-gradient(to bottom,black,transparent 70%);mask-image:linear-gradient(to bottom,black,transparent 70%)}.sidebar{width:232px;position:fixed;inset:0 auto 0 0;background:#0c131ee0;-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px);border-right:1px solid rgba(134,157,194,.13);padding:25px 16px;display:flex;flex-direction:column;z-index:2;box-shadow:12px 0 50px #0000001f}.brand{display:flex;align-items:center;gap:10px;font-family:Space Grotesk,sans-serif;font-size:21px;font-weight:700;letter-spacing:-.8px;padding:0 10px 42px}.brand-icon{height:31px;width:31px;border-radius:9px;background:linear-gradient(145deg,#8190ff,#5869dc);color:#fff;display:grid;place-items:center;box-shadow:0 5px 20px #6474e540,inset 0 1px #ffffff42}.nav-label,.eyebrow{font-size:10px;letter-spacing:1.2px;color:#728096;font-weight:700}.nav-label{padding:0 11px 10px}.integration-label{padding-top:25px}.nav-item{display:flex;align-items:center;gap:11px;padding:10px 11px;border-radius:7px;color:#8995a8;text-decoration:none;font-size:13px;margin:2px 0;transition:background .15s,color .15s}.nav-item.active,.nav-item:hover{background:linear-gradient(100deg,#6c7edd2e,#6c7edd12);color:#edf0fa}.nav-item.active{box-shadow:inset 2px 0 #91a0ff}.nav-item.active svg{color:#9ba6ff}.nav-badge{margin-left:auto;min-width:19px;height:19px;padding:0 5px;border-radius:12px;display:grid;place-items:center;background:#49342b;color:#f0b57c;font-size:10px;font-weight:700}.nav-badge.online{background:#173a31;color:#65d5a3}.sidebar-bottom{margin-top:auto;border-top:1px solid #202a38;padding:18px 8px 0;color:#a9b3c4;font-size:12px}.sidebar-bottom small{display:block;color:#78869a;margin:6px 0 0 17px}.live-dot{display:inline-block;width:7px;height:7px;background:#49ce9a;border-radius:50%;margin-right:8px;box-shadow:0 0 9px #49ce9a70}.main{margin-left:232px;min-height:100vh;padding:0 36px 22px;max-width:1700px;position:relative}.topbar{height:62px;border-bottom:1px solid rgba(134,157,194,.13);display:flex;align-items:center;justify-content:space-between;font-size:12px;color:#c9d0dd}.eyebrow{margin-right:7px}.connection{color:#a7b2c2;font-size:11px}.page-heading{display:flex;align-items:center;justify-content:space-between;margin:32px 0 23px}.page-heading h1{font-family:Space Grotesk,sans-serif;font-size:24px;letter-spacing:-.8px;margin:0 0 6px}.page-heading p,.panel-head p{margin:0;color:#8490a2;font-size:12px}.host-pill{background:#131d2a;border:1px solid #273344;padding:8px 11px;border-radius:7px;font-size:11px;color:#bcc5d3}.metric-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:14px}.metric-card,.panel{background:linear-gradient(145deg,#141e2de8,#0e1622d1);border:1px solid var(--surface-border);border-radius:12px;box-shadow:0 12px 34px #00000024,inset 0 1px #ffffff06;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);transition:border-color .2s,transform .2s,box-shadow .2s}.metric-card:hover,.panel:hover{border-color:#90a2ff3d;box-shadow:0 16px 42px #0003,inset 0 1px #ffffff09}.metric-card{padding:17px;min-height:143px;position:relative;overflow:hidden}.metric-card:after{content:"";position:absolute;right:-26px;top:-48px;width:100px;height:100px;border-radius:50%;background:#7d8cff0b;filter:blur(2px);pointer-events:none}.metric-icon{width:30px;height:30px;border-radius:7px;display:grid;place-items:center;margin-bottom:12px}.metric-icon svg{width:16px}.blue{color:#8e9cff;background:#222b47}.violet{color:#c097ff;background:#302442}.green{color:#55d7a1;background:#18372f}.amber{color:#f4bd66;background:#393021}.metric-title{font-size:11px;color:#9ba7b9}.metric-value{font-family:Space Grotesk,sans-serif;font-size:24px;letter-spacing:-.8px;margin-top:3px}.metric-note{font-size:10px;color:#738196;margin-top:4px}.content-grid{display:grid;grid-template-columns:minmax(0,1.65fr) minmax(265px,1fr);gap:14px;margin-top:14px}.panel{padding:17px 18px}.panel-head{display:flex;align-items:center;justify-content:space-between}.panel-head h2{font-size:13px;margin:0 0 4px}.panel-head p{font-size:10px}.live-tag{font-size:9px;color:#53d8a3;letter-spacing:.8px}.chart{height:203px;margin:16px -8px -2px -10px}.details-panel .panel-head{margin-bottom:14px}.detail-row{display:flex;justify-content:space-between;gap:10px;border-top:1px solid #222d3a;padding:10px 0;font-size:10px;color:#8e9aab}.detail-row strong{font-weight:500;color:#d2d9e4;text-align:right;overflow-wrap:anywhere}.table-panel{margin-top:14px;padding-bottom:5px}.table-panel>.panel-head{margin-bottom:11px}.text-link{color:#9ba7ff;text-decoration:none;font-size:11px}.table-scroll{width:100%;overflow-x:auto}table{border-collapse:collapse;width:100%;text-align:left;font-size:10px;white-space:nowrap}th{font-size:9px;letter-spacing:.65px;color:#748197;font-weight:600;padding:9px 10px;border-bottom:1px solid #25303e}td{padding:10px;border-bottom:1px solid #202a38;color:#c6cfdd}tbody tr:last-child td{border-bottom:0}.process-name{font-weight:600;color:#e0e6f0}.process-name small{display:block;color:#758297;font-size:9px;font-weight:400;margin-top:3px;max-width:330px;overflow:hidden;text-overflow:ellipsis}.status{background:#173528;color:#67d9a4;padding:3px 7px;border-radius:8px;font-size:9px}.status-stopped{background:#3a3025;color:#e6b56f}.empty{text-align:center;padding:22px;color:#8290a4;font-size:12px}footer{color:#7d899b;font-size:10px;padding:22px 2px}footer span{margin-left:9px;color:#626f82}.alert{margin-top:15px;padding:10px 13px;background:#382827;border:1px solid #66403d;color:#ffc0b9;border-radius:7px;font-size:12px}.route-page{padding-bottom:8px}.process-full{width:100%;margin-top:0}.process-full table{background:#111a27;border:1px solid #202c3c;border-radius:8px}.process-full th,.process-full td{padding:12px}.process-full table th:first-child,.process-full table td:first-child{padding-left:16px}.info-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px}.info-card{min-width:0}.info-card>.panel-head{margin-bottom:13px}.info-card>.panel-head>svg{color:#9aa7ff}.info-card .detail-row{font-size:11px}.volume-card,.network-card{border-top:1px solid #222d3a;padding:12px 0}.volume-title{display:flex;justify-content:space-between;gap:10px;font-size:11px}.volume-title span,.volume-caption{font-size:9px;color:#8190a3}.volume-bar{height:6px;background:#222d3a;border-radius:4px;margin:10px 0 6px;overflow:hidden}.volume-bar span{display:block;height:100%;background:linear-gradient(90deg,#6879ee,#9c8aff);border-radius:4px}.network-card>strong{display:block;color:#d6ddea;font-size:11px;margin-bottom:5px}.unsupported{padding:14px 0;color:#909bae;font-size:11px;line-height:1.6}.integration-state{border-radius:20px;padding:7px 10px;font-size:10px;border:1px solid #273344;white-space:nowrap}.state-online{color:#67d9a4;background:#153128}.state-offline{color:#e7b270;background:#342b22}.integration-message{min-height:205px;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;margin-top:12px;padding:35px}.integration-message .metric-icon{margin-bottom:15px}.integration-message h2{font-size:15px;margin:0 0 7px}.integration-message p{max-width:490px;color:#8c99ab;font-size:11px;line-height:1.7;margin:0}.integration-metrics{grid-template-columns:repeat(2,minmax(0,1fr));margin-bottom:14px}.integration-table{margin-top:0}.integration-table>.panel-head{margin-bottom:11px}.container-link{padding:0;border:0;background:none;color:#a7b2ff;font:inherit;font-weight:600;cursor:pointer}.container-link:hover{text-decoration:underline}.container-actions{display:flex;gap:5px}.console-button{border:1px solid #334158;border-radius:5px;padding:5px 8px;background:#1a2636;color:#d7dfed;font:inherit;font-size:9px;cursor:pointer;white-space:nowrap}.console-button:hover:not(:disabled){background:#26364b;border-color:#54698a}.console-button:disabled{opacity:.42;cursor:not-allowed}.secondary-button{padding:7px 10px;font-size:10px}.docker-console{border-top:1px solid #25303e;margin-top:17px;padding-top:15px}.console-header{display:flex;align-items:center;justify-content:space-between;gap:12px}.console-header h3{font-size:12px;margin:0 0 4px}.console-header p{font-size:10px;color:#8794a7;margin:0}.log-output{height:330px;overflow:auto;background:#05090fd4;border:1px solid #202b39;border-radius:7px;padding:13px;color:#c4d2df;font:11px/1.55 ui-monospace,SFMono-Regular,Consolas,monospace;white-space:pre-wrap;overflow-wrap:anywhere;margin:12px 0 0}.console-placeholder{min-height:100px;display:grid;place-items:center;color:#77869a;font-size:11px}.console-alert{margin-top:10px}.discord-alert-panel{margin-top:14px;padding:18px;background:linear-gradient(145deg,#181e30e0,#0e1622d6);border:1px solid rgba(161,139,255,.17);border-radius:12px;box-shadow:0 12px 34px #00000024,inset 0 1px #ffffff06}.discord-alert-heading{display:flex;align-items:center;gap:12px}.discord-alert-heading .metric-icon{flex:none;margin:0;color:#c2a6ff;background:#302744}.discord-alert-heading h3{font-size:13px;margin:0 0 4px}.discord-alert-heading p{color:#8e9bad;font-size:10px;margin:0}.toggle-control{display:flex;align-items:center;gap:8px;margin-left:auto;cursor:pointer}.toggle-control input{position:absolute;opacity:0;width:1px;height:1px}.toggle-track{width:31px;height:18px;border-radius:20px;background:#303b4c;position:relative;transition:background .18s}.toggle-track:after{content:"";position:absolute;width:12px;height:12px;top:3px;left:3px;border-radius:50%;background:#a2afc1;transition:transform .18s,background .18s}.toggle-control input:checked+.toggle-track{background:#365c50}.toggle-control input:checked+.toggle-track:after{transform:translate(13px);background:#75e0ad}.toggle-control input:focus-visible+.toggle-track{outline:2px solid #a6a5ff;outline-offset:2px}.toggle-label{color:#a9b4c4;font-size:10px;min-width:44px}.webhook-field{margin-top:18px}.webhook-field>label,.alert-options-title{display:block;color:#cbd4e1;font-size:10px;font-weight:600;margin-bottom:7px}.webhook-input-row{display:flex;gap:8px}.webhook-input-row input{width:100%;min-width:0;background:#070c14b3;border:1px solid #2c394b;border-radius:6px;padding:9px 11px;color:#dbe3ef;font:11px DM Sans,sans-serif;outline:none}.webhook-input-row input:focus{border-color:#8c83df;box-shadow:0 0 0 3px #8c83df1f}.webhook-input-row input::placeholder{color:#6f7d91}.webhook-field small{display:block;color:#77869a;font-size:9px;margin-top:6px}.alert-options{display:flex;flex-wrap:wrap;gap:8px 18px;margin-top:17px}.alert-option{display:flex;align-items:center;gap:7px;color:#aeb9c9;font-size:10px;cursor:pointer}.alert-option input{position:absolute;opacity:0;width:1px;height:1px}.check-ui{width:14px;height:14px;border:1px solid #445269;border-radius:4px;background:#121b28;position:relative}.alert-option input:checked+.check-ui{background:#756dcc;border-color:#9289ed}.alert-option input:checked+.check-ui:after{content:"";position:absolute;left:4px;top:1px;width:4px;height:7px;border:solid white;border-width:0 1.5px 1.5px 0;transform:rotate(45deg)}.alert-option input:focus-visible+.check-ui{outline:2px solid #a6a5ff;outline-offset:2px}.alert-form-footer{display:flex;align-items:center;justify-content:space-between;gap:12px;border-top:1px solid rgba(134,157,194,.1);padding-top:14px;margin-top:17px}.throttle-field{display:flex;align-items:center;gap:9px;color:#8e9bad;font-size:10px}.throttle-field select{background:#111a27;color:#d4deeb;border:1px solid #2c394b;border-radius:5px;padding:6px 8px;font-size:10px}.save-alert-button{background:linear-gradient(120deg,#5c65bf,#7064bd);border-color:#8479d4;padding:7px 11px}.save-alert-button:hover:not(:disabled){background:linear-gradient(120deg,#6b75d3,#8275d4)}.alert-success{margin-top:11px;color:#76ddb0;background:#235f452e;border:1px solid rgba(80,180,130,.17);border-radius:6px;padding:8px 10px;font-size:10px}.dashboard-skeleton{display:flex;flex-direction:column;gap:14px}.skeleton-metric-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:14px}.skeleton-metric-grid.two-columns{grid-template-columns:repeat(2,minmax(0,1fr));margin-bottom:14px}.skeleton-content-grid{display:grid;grid-template-columns:minmax(0,1.65fr) minmax(265px,1fr);gap:14px}.skeleton-card{background:linear-gradient(145deg,#141e2dc7,#0e1622b3);border:1px solid var(--surface-border);border-radius:12px;padding:17px 18px;overflow:hidden}.metric-skeleton{min-height:143px}.skeleton{position:relative;overflow:hidden;background:#8999b41c;border-radius:6px}.skeleton:after{content:"";position:absolute;top:0;right:0;bottom:0;left:0;transform:translate(-100%);background:linear-gradient(90deg,transparent,rgba(200,214,241,.1),transparent);animation:skeleton-shimmer 1.7s ease-in-out infinite}.skeleton-icon{width:30px;height:30px;border-radius:8px;margin-bottom:13px}.skeleton-line{height:9px;margin:12px 0}.skeleton-line.short{width:38%}.skeleton-line.medium{width:62%}.skeleton-line.full{width:100%;height:26px;margin:0;border-radius:0;background:transparent;border-bottom:1px solid rgba(134,157,194,.08)}.skeleton-line.full:after{top:8px;right:0;bottom:8px;left:0;background:linear-gradient(90deg,transparent,rgba(200,214,241,.08),transparent)}.skeleton-line.value-line{height:25px;width:54%;margin:8px 0}.chart-skeleton{min-height:255px}.skeleton-chart{height:185px;margin-top:20px;background:linear-gradient(180deg,#8290ff14,#8290ff04);border-bottom:1px solid rgba(134,157,194,.11);border-radius:4px}.detail-skeleton{min-height:255px}.table-skeleton{min-height:160px}.skeleton-row{height:29px;margin-top:12px;border-radius:4px;background:linear-gradient(90deg,rgba(137,153,180,.05) 0 28%,transparent 28% 37%,rgba(137,153,180,.05) 37% 56%,transparent 56% 65%,rgba(137,153,180,.05) 65% 82%,transparent 82%)}.process-skeleton{padding:9px 16px}.process-skeleton .skeleton-row{display:flex;align-items:center;justify-content:space-between;height:46px;margin:0;border-radius:0;border-bottom:1px solid rgba(134,157,194,.08);background:none}.process-skeleton .skeleton-line{height:8px;margin:0}.process-skeleton .skeleton-line:first-child{width:36%}.process-skeleton .skeleton-line:nth-child(2){width:12%}.process-skeleton .skeleton-line:nth-child(3){width:20%}.info-skeleton{min-height:220px}.info-skeleton .skeleton-line.full{height:30px}@keyframes skeleton-shimmer{to{transform:translate(100%)}}@media(prefers-reduced-motion:reduce){*,*:before,*:after{scroll-behavior:auto!important;animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}}@media(max-width:1000px){.skeleton-metric-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.skeleton-content-grid{grid-template-columns:1fr}.sidebar{width:190px}.main{margin-left:190px;padding-left:22px;padding-right:22px}.metric-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.content-grid{grid-template-columns:1fr}}@media(max-width:650px){.sidebar{width:58px;padding:19px 8px;overflow-y:auto}.brand{padding:0 5px 34px}.brand>span,.nav-label,.nav-item span:not(.nav-badge){font-size:0}.nav-item{justify-content:center;padding:11px 0;gap:0}.nav-item svg{width:18px;height:18px}.nav-badge{position:absolute;margin-left:32px;margin-top:-17px;min-width:15px;height:15px;font-size:8px;padding:0 3px}.sidebar-bottom{font-size:0;padding:15px 5px}.sidebar-bottom small{display:none}.main{margin-left:58px;padding:0 14px 20px}.topbar{font-size:10px}.page-heading{align-items:flex-start;gap:10px}.page-heading h1{font-size:20px}.host-pill,.integration-state{font-size:9px}.metric-grid{gap:9px}.metric-card{padding:13px;min-height:134px}.metric-value{font-size:20px}.content-grid{gap:9px}.panel{padding:14px}.chart{height:180px}.process-name small{max-width:150px}.info-grid,.skeleton-content-grid{grid-template-columns:1fr}.skeleton-metric-grid{gap:9px}.skeleton-card{padding:14px}.volume-title{flex-wrap:wrap}.discord-alert-panel{padding:14px}.discord-alert-heading{flex-wrap:wrap}.toggle-control{width:100%;margin-left:42px}.alert-form-footer{align-items:flex-start;flex-direction:column}.save-alert-button{align-self:stretch}.webhook-input-row{flex-direction:column}.webhook-input-row button{align-self:flex-start}.integration-metrics{grid-template-columns:repeat(2,minmax(0,1fr))}}.auth-screen{min-height:100vh;display:grid;place-items:center;padding:24px;background:radial-gradient(ellipse at 50% 25%,rgba(93,107,193,.2),transparent 45%)}.auth-card{width:min(100%,430px);padding:30px}.auth-card h1{font:600 23px Space Grotesk,sans-serif;margin:18px 0 8px}.auth-card>p,.muted{color:#8e9bad;font-size:11px;line-height:1.6;margin:0 0 18px}.auth-card small{display:block;color:#78869a;font-size:10px;margin:6px 0 12px}.form-label{display:block;color:#cbd4e1;font-size:11px;font-weight:600;margin:13px 0 7px}.form-input{width:100%;min-width:0;background:#070c14b3;border:1px solid #2c394b;border-radius:6px;padding:9px 11px;color:#dbe3ef;font:11px DM Sans,sans-serif;outline:none}.form-input:focus{border-color:#8c83df;box-shadow:0 0 0 3px #8c83df1f}.auth-submit{display:flex;align-items:center;justify-content:center;gap:8px;width:100%;margin-top:18px;padding:10px;background:linear-gradient(120deg,#5c65bf,#7064bd);border-color:#8479d4;font-size:12px}.topbar-actions{display:flex;align-items:center;gap:12px}.user-chip{color:#b9c3d2;font-size:10px}.nav-label.integration-label{margin-top:14px;padding-top:13px;border-top:1px solid rgba(134,157,194,.08)}.config-panel{margin-top:14px}.config-panel h2,.history-chart h2{font-size:13px;margin:0 0 6px}.form-row{display:flex;align-items:center;gap:8px;margin:12px 0;flex-wrap:wrap}.form-row .form-input{flex:1 1 180px}.small-input{max-width:110px!important}.save-button{margin-right:8px}.security-summary{display:flex;align-items:center;gap:12px;padding:4px 0 18px;margin-bottom:18px;border-bottom:1px solid #25303e}.security-summary>svg{color:#9ba7ff;flex:none}.security-summary strong{font-size:12px}.security-summary p{margin:4px 0 0}.config-panel h2:not(:first-child){margin-top:20px}.chip-list{display:flex;flex-wrap:wrap;gap:6px;margin:10px 0}.target-chip{border:1px solid #354258;border-radius:16px;background:#172234;color:#cbd4e1;padding:5px 9px;font-size:10px;cursor:pointer}.history-chart{margin-top:14px}.history-chart .chart{height:300px;margin-top:14px}.threshold-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:14px}.threshold-input{display:flex;align-items:center;gap:8px}.threshold-input span{font-size:11px;color:#8e9bad}.log-search{max-width:560px}.auth-card .alert{margin-top:10px}@media(max-width:650px){.auth-card{padding:22px}.topbar-actions{gap:5px}.user-chip{display:none}.form-row{align-items:stretch}.form-row .form-input{flex-basis:100%}.threshold-grid{grid-template-columns:1fr}.history-chart .chart{height:230px}.nav-label.integration-label{font-size:0;padding:7px 0;margin-top:6px}.nav-label.integration-label:after{content:"·";font-size:16px;display:block;text-align:center}}:root[data-theme] body{color:var(--text-main);background:radial-gradient(ellipse at 72% -10%,color-mix(in srgb,var(--accent) 10%,transparent),transparent 38%),var(--page-bg)}:root[data-theme] .sidebar{background:var(--sidebar-bg)}:root[data-theme] .panel,:root[data-theme] .metric-card,:root[data-theme] .skeleton-card{background:var(--panel-bg);border-color:var(--surface-border)}:root[data-theme] .form-input,:root[data-theme] .webhook-input-row input{background:var(--field-bg);color:var(--text-main)}:root[data-theme] .theme-choice{background:var(--panel-bg);color:var(--text-main);border:1px solid var(--surface-border);border-radius:8px;padding:13px;text-align:left;cursor:pointer;transition:border-color .15s,transform .15s}:root[data-theme] .theme-choice:hover,:root[data-theme] .theme-choice.selected{border-color:var(--accent);transform:translateY(-1px)}:root[data-theme] .theme-choice strong,:root[data-theme] .theme-choice span{display:block}:root[data-theme] .theme-choice span{color:var(--text-muted);font-size:10px;line-height:1.5;margin-top:5px}.theme-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:9px;margin-top:12px}.permission-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:9px;margin-top:12px}.user-list{display:grid;gap:10px}.user-card{padding:13px;border:1px solid var(--surface-border);border-radius:8px}.user-card-heading{display:flex;justify-content:space-between;gap:8px;color:var(--text-main);font-size:11px}.user-card-heading span{color:var(--text-muted)}:root[data-theme=monochrome] .nav-item.active,:root[data-theme=monochrome] .nav-item:hover{background:#ffffff10;color:#fff}:root[data-theme=monochrome] .nav-item.active,:root[data-theme=monochrome] .nav-item.active svg{color:#fff}:root[data-theme=monochrome] .metric-icon.blue,:root[data-theme=monochrome] .metric-icon.violet,:root[data-theme=monochrome] .metric-icon.green,:root[data-theme=monochrome] .metric-icon.amber{background:#303234;color:#e5e7eb}@media(max-width:650px){.theme-grid,.permission-grid{grid-template-columns:1fr}}