|
|
@@ -22,16 +22,21 @@ body{background:linear-gradient(180deg,#fbfcfe 0%,var(--bg) 100%);color:var(--te |
|
|
button,input,select{font:inherit}button{user-select:none} |
|
|
button,input,select{font:inherit}button{user-select:none} |
|
|
.app{max-width:1560px;margin:0 auto;padding:24px} |
|
|
.app{max-width:1560px;margin:0 auto;padding:24px} |
|
|
/* Header */ |
|
|
/* Header */ |
|
|
.header{display:flex;align-items:flex-start;justify-content:space-between;gap:18px;padding:4px 0 20px;border-bottom:1px solid var(--border);margin-bottom:20px} |
|
|
|
|
|
.header-main{display:flex;flex-direction:column;gap:8px} |
|
|
|
|
|
.header h1{font-size:28px;font-weight:800;letter-spacing:-.03em} |
|
|
|
|
|
|
|
|
.header{display:flex;align-items:center;justify-content:space-between;gap:18px;padding:2px 0 18px;border-bottom:1px solid var(--border);margin-bottom:20px} |
|
|
|
|
|
.header-main{display:flex;align-items:center;min-height:64px} |
|
|
|
|
|
.brand-lockup{display:flex;align-items:center;gap:0} |
|
|
|
|
|
.brand-logo{height:62px;width:auto;display:block;object-fit:contain} |
|
|
|
|
|
.brand-title{font-size:28px;font-weight:800;letter-spacing:-.03em} |
|
|
.header-note{font-size:13px;color:var(--text-muted)} |
|
|
.header-note{font-size:13px;color:var(--text-muted)} |
|
|
.header-sub{display:flex;flex-wrap:wrap;gap:8px} |
|
|
.header-sub{display:flex;flex-wrap:wrap;gap:8px} |
|
|
.badge{display:inline-flex;align-items:center;gap:8px;min-height:28px;padding:0 10px;border:1px solid var(--border);border-radius:999px;background:var(--surface2);color:var(--text-dim);font-size:11px;text-transform:uppercase;letter-spacing:.08em} |
|
|
.badge{display:inline-flex;align-items:center;gap:8px;min-height:28px;padding:0 10px;border:1px solid var(--border);border-radius:999px;background:var(--surface2);color:var(--text-dim);font-size:11px;text-transform:uppercase;letter-spacing:.08em} |
|
|
.badge strong{white-space:nowrap} |
|
|
.badge strong{white-space:nowrap} |
|
|
.badge .tag{margin-left:2px} |
|
|
.badge .tag{margin-left:2px} |
|
|
.badge strong{color:var(--text);font-weight:700} |
|
|
.badge strong{color:var(--text);font-weight:700} |
|
|
.header-status{display:flex;align-items:center;gap:10px;padding-top:6px} |
|
|
|
|
|
|
|
|
.header-status{display:flex;align-items:center;gap:8px;padding-top:0;padding-right:2px} |
|
|
|
|
|
.header-status .danger-btn{min-height:36px;padding:0 14px;border-radius:10px;background:rgba(176,48,48,.06);border-color:rgba(176,48,48,.22);font-size:11px;letter-spacing:.08em} |
|
|
|
|
|
.header-status .danger-btn:hover:not(:disabled){background:rgba(176,48,48,.1)} |
|
|
|
|
|
.header-status .led{margin-left:4px} |
|
|
/* LED */ |
|
|
/* LED */ |
|
|
.led{width:10px;height:10px;border-radius:50%;background:#333;transition:all .25s;flex-shrink:0} |
|
|
.led{width:10px;height:10px;border-radius:50%;background:#333;transition:all .25s;flex-shrink:0} |
|
|
.led.on-green{background:var(--green);box-shadow:0 0 0 3px rgba(13,148,74,.16)} |
|
|
.led.on-green{background:var(--green);box-shadow:0 0 0 3px rgba(13,148,74,.16)} |
|
|
@@ -285,19 +290,15 @@ input.input-error{border-color:var(--red);box-shadow:0 0 0 3px rgba(176,48,48,.1 |
|
|
.toast.warn{background:var(--amber);color:#141414}.toast.info{background:var(--text-dim);color:#fff} |
|
|
.toast.warn{background:var(--amber);color:#141414}.toast.info{background:var(--text-dim);color:#fff} |
|
|
/* Responsive */ |
|
|
/* Responsive */ |
|
|
@media(max-width:980px){.app{max-width:100%;padding:14px}.tab-columns.two{grid-template-columns:1fr}.tx-bar{grid-template-columns:1fr}.tx-state-wrap{align-items:flex-start}.status-hint{text-align:left}.quick-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.signal-grid{grid-template-columns:1fr}.flow-master{grid-template-columns:1fr}.flow-topbar,.flow-bottom{grid-template-columns:repeat(2,minmax(0,1fr))}.flow-chain{grid-template-columns:repeat(4,minmax(140px,1fr))}} |
|
|
@media(max-width:980px){.app{max-width:100%;padding:14px}.tab-columns.two{grid-template-columns:1fr}.tx-bar{grid-template-columns:1fr}.tx-state-wrap{align-items:flex-start}.status-hint{text-align:left}.quick-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.signal-grid{grid-template-columns:1fr}.flow-master{grid-template-columns:1fr}.flow-topbar,.flow-bottom{grid-template-columns:repeat(2,minmax(0,1fr))}.flow-chain{grid-template-columns:repeat(4,minmax(140px,1fr))}} |
|
|
@media(max-width:640px){.app{padding:12px}.header{flex-direction:column;gap:10px}.header h1{font-size:22px}.badge{width:100%;justify-content:space-between}.badge strong{max-width:52%;overflow:hidden;text-overflow:ellipsis}.quick-grid{grid-template-columns:1fr 1fr;gap:8px}.ctrl-row{flex-direction:column;align-items:stretch}.ctrl-label-wrap{min-width:auto}.ctrl-input{flex-wrap:wrap}.ingest-grid{grid-template-columns:1fr}input[type="number"]{width:100%;text-align:left}.actions-row,.tx-actions{flex-direction:column}.tx-btn,.ghost-btn,.apply-btn,.preset-btn,.danger-btn{width:100%}.freq-display{font-size:31px}.flow-master,.flow-topbar,.flow-bottom,.flow-chain{grid-template-columns:1fr}} |
|
|
|
|
|
|
|
|
@media(max-width:640px){.app{padding:12px}.header{flex-direction:column;align-items:flex-start;gap:10px}.brand-logo{height:54px}.badge{width:100%;justify-content:space-between}.badge strong{max-width:52%;overflow:hidden;text-overflow:ellipsis}.quick-grid{grid-template-columns:1fr 1fr;gap:8px}.ctrl-row{flex-direction:column;align-items:stretch}.ctrl-label-wrap{min-width:auto}.ctrl-input{flex-wrap:wrap}.ingest-grid{grid-template-columns:1fr}input[type="number"]{width:100%;text-align:left}.actions-row,.tx-actions{flex-direction:column}.tx-btn,.ghost-btn,.apply-btn,.preset-btn,.danger-btn{width:100%}.freq-display{font-size:31px}.flow-master,.flow-topbar,.flow-bottom,.flow-chain{grid-template-columns:1fr}} |
|
|
</style> |
|
|
</style> |
|
|
</head> |
|
|
</head> |
|
|
<body> |
|
|
<body> |
|
|
<div class="app"> |
|
|
<div class="app"> |
|
|
<div class="header"> |
|
|
<div class="header"> |
|
|
<div class="header-main"> |
|
|
<div class="header-main"> |
|
|
<h1>ferrite.fm Control Plane</h1> |
|
|
|
|
|
<div class="header-note">Operate confidently: tune fast, inspect state instantly, diagnose only when needed.</div> |
|
|
|
|
|
<div class="header-sub"> |
|
|
|
|
|
<div class="badge"><span>Backend</span><strong id="badge-backend">--</strong></div> |
|
|
|
|
|
<div class="badge"><span>Mode</span><strong id="badge-mode">Control Plane</strong></div> |
|
|
|
|
|
<div class="badge"><span>Live Config</span><strong id="badge-live">--</strong></div> |
|
|
|
|
|
|
|
|
<div class="brand-lockup"> |
|
|
|
|
|
<img class="brand-logo" src="/logo" alt="ferrite.fm logo"> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
<div class="header-status"> |
|
|
<div class="header-status"> |
|
|
|