Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>HuggingClaw · ENV Builder</title> | |
| <link rel="preconnect" href="https://fonts.googleapis.com"> | |
| <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> | |
| <link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&family=Syne:wght@400;500;600;700;800&display=swap" rel="stylesheet"> | |
| <style> | |
| /* ── Reset & Tokens ── */ | |
| *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } | |
| :root { | |
| --bg: #0b0c0f; | |
| --bg2: #111318; | |
| --bg3: #181c23; | |
| --bg4: #1e2330; | |
| --border: #252b38; | |
| --border2: #2e3648; | |
| --amber: #f5a623; | |
| --amber2: #ffbe55; | |
| --amber-dim: rgba(245,166,35,.12); | |
| --amber-glow:rgba(245,166,35,.22); | |
| --green: #3dd68c; | |
| --red: #f05f5f; | |
| --blue: #5b8af5; | |
| --text: #e4e8f0; | |
| --text2: #8d97ad; | |
| --text3: #535f76; | |
| --mono: 'JetBrains Mono', monospace; | |
| --sans: 'Syne', sans-serif; | |
| --r: 8px; | |
| --r2: 12px; | |
| --sidebar-w: 220px; | |
| --panel-w: 340px; | |
| } | |
| html { scroll-behavior: smooth; height: 100%; } | |
| body { | |
| font-family: var(--sans); | |
| background: var(--bg); | |
| color: var(--text); | |
| height: 100vh; | |
| overflow: hidden; | |
| display: flex; | |
| flex-direction: column; | |
| } | |
| /* ── Topbar ── */ | |
| .topbar { | |
| position: sticky; | |
| top: 0; | |
| z-index: 100; | |
| height: 52px; | |
| background: rgba(11,12,15,.9); | |
| backdrop-filter: blur(14px); | |
| border-bottom: 1px solid var(--border); | |
| display: flex; | |
| align-items: center; | |
| padding: 0 20px; | |
| gap: 16px; | |
| flex-shrink: 0; | |
| } | |
| .topbar-logo { | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| flex-shrink: 0; | |
| } | |
| .topbar-logo svg { width: 26px; height: 26px; } | |
| .topbar-wordmark { | |
| font-weight: 800; | |
| font-size: 14px; | |
| letter-spacing: -.2px; | |
| color: var(--text); | |
| white-space: nowrap; | |
| } | |
| .topbar-wordmark em { | |
| color: var(--amber); | |
| font-style: normal; | |
| } | |
| .topbar-divider { | |
| width: 1px; | |
| height: 22px; | |
| background: var(--border2); | |
| } | |
| .topbar-title { | |
| font-size: 12px; | |
| font-weight: 600; | |
| color: var(--text2); | |
| letter-spacing: .5px; | |
| text-transform: uppercase; | |
| } | |
| .topbar-spacer { flex: 1; } | |
| .topbar-pill { | |
| font-family: var(--mono); | |
| font-size: 10px; | |
| color: var(--amber); | |
| background: var(--amber-dim); | |
| border: 1px solid var(--amber-glow); | |
| border-radius: 20px; | |
| padding: 3px 10px; | |
| letter-spacing: .5px; | |
| } | |
| /* ── Layout ── */ | |
| .layout { | |
| display: flex; | |
| flex: 1; | |
| min-height: 0; | |
| height: calc(100vh - 52px); | |
| } | |
| /* ── Sidebar ── */ | |
| .sidebar-wrap { | |
| width: var(--sidebar-w); | |
| flex-shrink: 0; | |
| border-right: 1px solid var(--border); | |
| background: var(--bg2); | |
| display: flex; | |
| flex-direction: column; | |
| overflow: hidden; | |
| } | |
| .sidebar-scroll { | |
| flex: 1; | |
| overflow-y: auto; | |
| padding: 14px 10px; | |
| } | |
| .sidebar-scroll::-webkit-scrollbar { width: 4px; } | |
| .sidebar-scroll::-webkit-scrollbar-track { background: transparent; } | |
| .sidebar-scroll::-webkit-scrollbar-thumb { background: var(--border2); border-radius: 4px; } | |
| /* sb-label rendered by JS */ | |
| .sb-label { | |
| font-size: 9px; | |
| font-weight: 700; | |
| text-transform: uppercase; | |
| letter-spacing: 1.2px; | |
| color: var(--text3); | |
| padding: 0 8px 10px; | |
| } | |
| .nav-btn { | |
| width: 100%; | |
| display: flex; | |
| align-items: center; | |
| gap: 8px; | |
| padding: 8px 10px; | |
| border: none; | |
| background: transparent; | |
| cursor: pointer; | |
| border-radius: var(--r); | |
| text-align: left; | |
| color: var(--text2); | |
| font-family: var(--sans); | |
| font-size: 12.5px; | |
| font-weight: 500; | |
| transition: background .15s, color .15s; | |
| margin-bottom: 2px; | |
| } | |
| .nav-btn:hover { background: var(--bg3); color: var(--text); } | |
| .nav-btn.active { | |
| background: var(--amber-dim); | |
| color: var(--amber); | |
| border: 1px solid var(--amber-glow); | |
| } | |
| .nav-icon { font-size: 13px; flex-shrink: 0; } | |
| .nav-label { flex: 1; } | |
| .nav-count { | |
| font-family: var(--mono); | |
| font-size: 10px; | |
| font-weight: 600; | |
| color: var(--text3); | |
| background: var(--bg3); | |
| border-radius: 10px; | |
| padding: 1px 6px; | |
| min-width: 20px; | |
| text-align: center; | |
| transition: background .2s, color .2s; | |
| } | |
| .nav-btn.active .nav-count { | |
| background: var(--amber-glow); | |
| color: var(--amber2); | |
| } | |
| /* ── Main ── */ | |
| .main { | |
| flex: 1; | |
| display: flex; | |
| flex-direction: column; | |
| min-width: 0; | |
| overflow: hidden; | |
| } | |
| /* ── Toolbar ── */ | |
| .toolbar { | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| padding: 12px 20px; | |
| border-bottom: 1px solid var(--border); | |
| background: var(--bg2); | |
| flex-shrink: 0; | |
| flex-wrap: wrap; | |
| } | |
| .search-wrap { | |
| position: relative; | |
| flex: 1; | |
| min-width: 160px; | |
| max-width: 340px; | |
| } | |
| .search-icon { | |
| position: absolute; | |
| left: 10px; | |
| top: 50%; | |
| transform: translateY(-50%); | |
| color: var(--text3); | |
| pointer-events: none; | |
| font-size: 12px; | |
| } | |
| #search { | |
| width: 100%; | |
| background: var(--bg3); | |
| border: 1px solid var(--border2); | |
| border-radius: var(--r); | |
| padding: 7px 10px 7px 30px; | |
| font-family: var(--mono); | |
| font-size: 12px; | |
| color: var(--text); | |
| outline: none; | |
| transition: border-color .15s; | |
| } | |
| #search:focus { border-color: var(--amber); } | |
| #search::placeholder { color: var(--text3); } | |
| .tb-sep { | |
| width: 1px; | |
| height: 24px; | |
| background: var(--border2); | |
| } | |
| .btn { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 5px; | |
| padding: 6px 13px; | |
| border-radius: var(--r); | |
| border: 1px solid var(--border2); | |
| background: var(--bg3); | |
| color: var(--text2); | |
| font-family: var(--sans); | |
| font-size: 11.5px; | |
| font-weight: 600; | |
| cursor: pointer; | |
| transition: all .15s; | |
| white-space: nowrap; | |
| } | |
| .btn:hover { background: var(--bg4); color: var(--text); border-color: var(--border2); } | |
| .btn-amber { | |
| background: var(--amber); | |
| color: #0b0c0f; | |
| border-color: var(--amber); | |
| } | |
| .btn-amber:hover { background: var(--amber2); border-color: var(--amber2); } | |
| .btn-ghost { | |
| background: transparent; | |
| border-color: transparent; | |
| color: var(--text3); | |
| } | |
| .btn-ghost:hover { background: var(--bg3); color: var(--text2); border-color: var(--border2); } | |
| /* ── Content area ── */ | |
| .content-wrap { | |
| flex: 1; | |
| display: flex; | |
| min-height: 0; | |
| overflow: hidden; | |
| } | |
| /* ── Sections scroll ── */ | |
| .sections-scroll { | |
| flex: 1; | |
| overflow-y: auto; | |
| padding: 16px 20px 80px; | |
| min-width: 0; | |
| } | |
| .sections-scroll::-webkit-scrollbar { width: 5px; } | |
| .sections-scroll::-webkit-scrollbar-track { background: transparent; } | |
| .sections-scroll::-webkit-scrollbar-thumb { background: var(--border2); border-radius: 4px; } | |
| /* ── Section ── */ | |
| .sec { margin-bottom: 28px; } | |
| .sec.sec-hidden { display: none ; } | |
| .sec-header { | |
| display: flex; | |
| align-items: center; | |
| gap: 8px; | |
| margin-bottom: 12px; | |
| } | |
| .sec-icon { font-size: 14px; } | |
| .sec-title { | |
| font-size: 11px; | |
| font-weight: 700; | |
| text-transform: uppercase; | |
| letter-spacing: 1.2px; | |
| color: var(--text3); | |
| } | |
| .sec-count { | |
| font-family: var(--mono); | |
| font-size: 10px; | |
| color: var(--text3); | |
| background: var(--bg3); | |
| border: 1px solid var(--border); | |
| border-radius: 10px; | |
| padding: 1px 7px; | |
| } | |
| .sec-line { | |
| flex: 1; | |
| height: 1px; | |
| background: var(--border); | |
| } | |
| .cards { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); | |
| gap: 9px; | |
| } | |
| /* ── ENV Card ── */ | |
| .env-card { | |
| background: var(--bg2); | |
| border: 1px solid var(--border); | |
| border-radius: var(--r2); | |
| padding: 12px; | |
| transition: border-color .2s, background .2s; | |
| } | |
| .env-card:hover { border-color: var(--border2); } | |
| .env-card.hidden { display: none; } | |
| .env-card.selected { | |
| border-color: var(--amber-glow); | |
| background: linear-gradient(135deg, var(--bg2) 80%, rgba(245,166,35,.04)); | |
| } | |
| /* Critical cards get a red left-border accent */ | |
| .env-card:has(.badge-critical) { | |
| border-left: 3px solid rgba(240,80,80,.4); | |
| } | |
| .env-card:has(.badge-critical):hover { | |
| border-left-color: rgba(240,80,80,.7); | |
| } | |
| .env-card:has(.badge-critical).selected { | |
| border-left-color: #f05f5f; | |
| } | |
| /* Credential cards get an amber left-border accent */ | |
| .env-card:has(.badge-credential) { | |
| border-left: 3px solid rgba(220,140,60,.3); | |
| } | |
| .card-top { | |
| display: flex; | |
| align-items: flex-start; | |
| gap: 9px; | |
| margin-bottom: 9px; | |
| } | |
| .card-check { | |
| width: 15px; | |
| height: 15px; | |
| accent-color: var(--amber); | |
| flex-shrink: 0; | |
| margin-top: 2px; | |
| cursor: pointer; | |
| } | |
| .card-info { flex: 1; min-width: 0; } | |
| .card-key { | |
| font-family: var(--mono); | |
| font-size: 11.5px; | |
| font-weight: 600; | |
| color: var(--text); | |
| letter-spacing: .3px; | |
| white-space: nowrap; | |
| overflow: hidden; | |
| text-overflow: ellipsis; | |
| } | |
| .card-lbl { | |
| font-size: 11px; | |
| color: var(--text3); | |
| margin-top: 2px; | |
| line-height: 1.35; | |
| } | |
| .badge { | |
| flex-shrink: 0; | |
| font-family: var(--mono); | |
| font-size: 9px; | |
| font-weight: 700; | |
| text-transform: uppercase; | |
| letter-spacing: .6px; | |
| padding: 2px 7px; | |
| border-radius: 20px; | |
| } | |
| /* critical — space breaks without this */ | |
| .badge-critical { | |
| background: rgba(240,80,80,.14); | |
| color: #f05f5f; | |
| border: 1px solid rgba(240,80,80,.3); | |
| } | |
| /* credential — sensitive key / token */ | |
| .badge-credential { | |
| background: rgba(220,140,60,.13); | |
| color: #e09040; | |
| border: 1px solid rgba(220,140,60,.28); | |
| } | |
| /* feature — enables an optional feature */ | |
| .badge-feature { | |
| background: rgba(70,140,250,.12); | |
| color: #5a9eff; | |
| border: 1px solid rgba(70,140,250,.25); | |
| } | |
| /* optional — safe to change freely */ | |
| .badge-optional { | |
| background: rgba(61,214,140,.10); | |
| color: #3dd68c; | |
| border: 1px solid rgba(61,214,140,.22); | |
| } | |
| /* advanced — power-user, risky if wrong */ | |
| .badge-advanced { | |
| background: rgba(160,100,230,.12); | |
| color: #b07ae0; | |
| border: 1px solid rgba(160,100,230,.25); | |
| } | |
| /* build-time — needs HF Space rebuild */ | |
| .badge-build { | |
| background: rgba(240,185,60,.12); | |
| color: #e0b030; | |
| border: 1px solid rgba(240,185,60,.28); | |
| } | |
| /* ── Card inputs ── */ | |
| .card-input { position: relative; } | |
| .card-input input[type="text"], | |
| .card-input input[type="password"], | |
| .card-input input[type="number"], | |
| .card-input textarea, | |
| .card-input select { | |
| width: 100%; | |
| background: var(--bg3); | |
| border: 1px solid var(--border); | |
| border-radius: var(--r); | |
| padding: 7px 10px; | |
| font-family: var(--mono); | |
| font-size: 11.5px; | |
| color: var(--text); | |
| outline: none; | |
| transition: border-color .15s; | |
| resize: vertical; | |
| } | |
| .card-input input[type="text"]:focus, | |
| .card-input input[type="password"]:focus, | |
| .card-input input[type="number"]:focus, | |
| .card-input textarea:focus, | |
| .card-input select:focus { | |
| border-color: var(--amber); | |
| } | |
| .card-input textarea { min-height: 64px; } | |
| .card-input select { | |
| cursor: pointer; | |
| appearance: none; | |
| background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%238d97ad' d='M6 8L1 3h10z'/%3E%3C/svg%3E"); | |
| background-repeat: no-repeat; | |
| background-position: right 10px center; | |
| padding-right: 28px; | |
| } | |
| .card-input optgroup { color: var(--text2); font-weight: 600; } | |
| .card-input option { color: var(--text); background: var(--bg3); } | |
| /* ── Toggle ── */ | |
| .toggle-shell { display: flex; align-items: center; gap: 8px; } | |
| .tog { | |
| padding: 5px 14px; | |
| border-radius: 20px; | |
| border: 1px solid var(--border2); | |
| background: var(--bg3); | |
| color: var(--text3); | |
| font-family: var(--mono); | |
| font-size: 11px; | |
| font-weight: 700; | |
| cursor: pointer; | |
| transition: all .18s; | |
| letter-spacing: .5px; | |
| } | |
| .tog.on { | |
| background: rgba(61,214,140,.15); | |
| border-color: rgba(61,214,140,.4); | |
| color: var(--green); | |
| } | |
| /* ── Picker shell ── */ | |
| .picker-shell { display: flex; flex-direction: column; gap: 6px; } | |
| .picker-row { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; } | |
| .picker-select { | |
| flex: 1; | |
| min-width: 0; | |
| padding: 6px 28px 6px 8px ; | |
| font-size: 11px ; | |
| } | |
| .mini-btn { | |
| padding: 5px 9px; | |
| border-radius: var(--r); | |
| border: 1px solid var(--border2); | |
| background: var(--bg3); | |
| color: var(--text2); | |
| font-family: var(--mono); | |
| font-size: 10px; | |
| font-weight: 600; | |
| cursor: pointer; | |
| transition: all .15s; | |
| white-space: nowrap; | |
| } | |
| .mini-btn:hover { background: var(--bg4); color: var(--text); } | |
| /* ── Right panel ── */ | |
| .right-panel { | |
| width: var(--panel-w); | |
| flex-shrink: 0; | |
| border-left: 1px solid var(--border); | |
| background: var(--bg2); | |
| display: flex; | |
| flex-direction: column; | |
| overflow: hidden; | |
| } | |
| .panel-scroll { | |
| flex: 1; | |
| overflow-y: auto; | |
| padding: 16px; | |
| display: flex; | |
| flex-direction: column; | |
| gap: 16px; | |
| } | |
| .panel-scroll::-webkit-scrollbar { width: 4px; } | |
| .panel-scroll::-webkit-scrollbar-track { background: transparent; } | |
| .panel-scroll::-webkit-scrollbar-thumb { background: var(--border2); border-radius: 4px; } | |
| /* ── Panel block ── */ | |
| .pblock { | |
| background: var(--bg3); | |
| border: 1px solid var(--border); | |
| border-radius: var(--r2); | |
| overflow: hidden; | |
| } | |
| .pblock-head { | |
| display: flex; | |
| align-items: center; | |
| justify-content: space-between; | |
| padding: 10px 14px; | |
| border-bottom: 1px solid var(--border); | |
| } | |
| .pblock-title { | |
| font-size: 10.5px; | |
| font-weight: 700; | |
| text-transform: uppercase; | |
| letter-spacing: 1px; | |
| color: var(--text3); | |
| display: flex; | |
| align-items: center; | |
| gap: 6px; | |
| } | |
| .pblock-body { padding: 12px 14px; display: flex; flex-direction: column; gap: 8px; } | |
| .pblock-body textarea, | |
| .pblock-body input[type="text"] { | |
| width: 100%; | |
| background: var(--bg); | |
| border: 1px solid var(--border); | |
| border-radius: var(--r); | |
| padding: 8px 10px; | |
| font-family: var(--mono); | |
| font-size: 10.5px; | |
| color: var(--text2); | |
| outline: none; | |
| resize: vertical; | |
| transition: border-color .15s; | |
| } | |
| .pblock-body textarea:focus, | |
| .pblock-body input[type="text"]:focus { | |
| border-color: var(--amber); | |
| color: var(--text); | |
| } | |
| #importText { min-height: 80px; } | |
| #bundleOut { min-height: 60px; color: var(--amber2); } | |
| #envLineOut { font-size: 10px; } | |
| .row-btns { display: flex; gap: 6px; flex-wrap: wrap; } | |
| /* ── Summary ── */ | |
| #summary { | |
| font-size: 11.5px; | |
| color: var(--text2); | |
| line-height: 1.6; | |
| } | |
| #summary strong { | |
| font-size: 15px; | |
| color: var(--amber); | |
| font-family: var(--mono); | |
| } | |
| .sum-keys { | |
| margin-top: 8px; | |
| display: flex; | |
| flex-wrap: wrap; | |
| gap: 4px; | |
| } | |
| .sum-key { | |
| font-family: var(--mono); | |
| font-size: 9.5px; | |
| color: var(--text2); | |
| background: var(--bg4); | |
| border: 1px solid var(--border2); | |
| border-radius: 4px; | |
| padding: 2px 6px; | |
| } | |
| /* ── Custom Env section ── */ | |
| #customSec { | |
| margin-top: 8px; | |
| } | |
| .custom-row { | |
| display: flex; | |
| gap: 8px; | |
| align-items: center; | |
| margin-bottom: 8px; | |
| } | |
| .custom-row input { | |
| flex: 1; | |
| background: var(--bg3); | |
| border: 1px solid var(--border); | |
| border-radius: var(--r); | |
| padding: 7px 10px; | |
| font-family: var(--mono); | |
| font-size: 11px; | |
| color: var(--text); | |
| outline: none; | |
| transition: border-color .15s; | |
| min-width: 0; | |
| } | |
| .custom-row input:focus { border-color: var(--amber); } | |
| .custom-row input:first-child { flex: 0 0 40%; } | |
| /* ── Toast ── */ | |
| #toast { | |
| position: fixed; | |
| bottom: 24px; | |
| left: 50%; | |
| transform: translateX(-50%) translateY(20px); | |
| background: var(--bg4); | |
| border: 1px solid var(--border2); | |
| color: var(--amber); | |
| font-family: var(--mono); | |
| font-size: 12px; | |
| font-weight: 600; | |
| padding: 9px 20px; | |
| border-radius: 30px; | |
| z-index: 9999; | |
| opacity: 0; | |
| transition: opacity .2s, transform .2s; | |
| pointer-events: none; | |
| box-shadow: 0 8px 32px rgba(0,0,0,.5); | |
| } | |
| #toast.show { | |
| opacity: 1; | |
| transform: translateX(-50%) translateY(0); | |
| } | |
| /* ── Scrollbar global ── */ | |
| ::-webkit-scrollbar { width: 6px; height: 6px; } | |
| ::-webkit-scrollbar-track { background: transparent; } | |
| ::-webkit-scrollbar-thumb { background: var(--border2); border-radius: 4px; } | |
| /* ── Responsive ── */ | |
| @media (max-width: 900px) { | |
| :root { --panel-w: 280px; --sidebar-w: 180px; } | |
| } | |
| @media (max-width: 700px) { | |
| .right-panel { display: none; } | |
| :root { --sidebar-w: 160px; } | |
| } | |
| @media (max-width: 520px) { | |
| .sidebar-wrap { display: none; } | |
| .topbar-divider, .topbar-title { display: none; } | |
| } | |
| /* ── Tag Legend (collapsible) ── */ | |
| .tag-legend { | |
| margin-bottom: 14px; | |
| background: var(--bg2); | |
| border: 1px solid var(--border); | |
| border-radius: var(--r); | |
| overflow: hidden; | |
| } | |
| .legend-summary { | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| padding: 7px 12px; | |
| cursor: pointer; | |
| list-style: none; | |
| user-select: none; | |
| outline: none; | |
| } | |
| .legend-summary::-webkit-details-marker { display: none; } | |
| .legend-chips { display: flex; gap: 5px; flex-wrap: wrap; flex: 1; } | |
| .legend-hint { | |
| font-size: 10px; | |
| color: var(--text3); | |
| white-space: nowrap; | |
| flex-shrink: 0; | |
| } | |
| .tag-legend[open] .legend-hint { opacity: 0; } | |
| .legend-body { | |
| padding: 8px 12px 10px; | |
| border-top: 1px solid var(--border); | |
| display: flex; | |
| flex-direction: column; | |
| gap: 6px; | |
| } | |
| .legend-row { | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| font-size: 11px; | |
| color: var(--text2); | |
| } | |
| .legend-row .badge { flex-shrink: 0; width: 74px; text-align: center; } | |
| .legend-tip { | |
| font-size: 9.5px; | |
| color: var(--text3); | |
| margin-top: 4px; | |
| padding-top: 6px; | |
| border-top: 1px solid var(--border); | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <!-- ── Topbar ── --> | |
| <header class="topbar"> | |
| <div class="topbar-logo"> | |
| <svg viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg"> | |
| <rect width="64" height="64" rx="14" fill="#1a1f2e"/> | |
| <text x="10" y="46" font-size="40" font-family="monospace">🤗</text> | |
| <circle cx="46" cy="20" r="10" fill="#f5a623"/> | |
| <text x="40" y="25" font-size="14" font-family="monospace" fill="#0b0c0f">⚡</text> | |
| </svg> | |
| <span class="topbar-wordmark">Hugging<em>Claw</em></span> | |
| </div> | |
| <div class="topbar-divider"></div> | |
| <span class="topbar-title">ENV Builder</span> | |
| <div class="topbar-spacer"></div> | |
| <span class="topbar-pill">v2025</span> | |
| </header> | |
| <!-- ── Layout ── --> | |
| <div class="layout"> | |
| <!-- ── Sidebar ── --> | |
| <aside class="sidebar-wrap"> | |
| <div class="sidebar-scroll"> | |
| <div id="sidebar"></div> | |
| </div> | |
| </aside> | |
| <!-- ── Main ── --> | |
| <main class="main"> | |
| <!-- toolbar --> | |
| <div class="toolbar"> | |
| <div class="search-wrap"> | |
| <span class="search-icon">⌕</span> | |
| <input id="search" type="text" placeholder="Search variables…" autocomplete="off" spellcheck="false"> | |
| </div> | |
| <div class="tb-sep"></div> | |
| <button id="selectCommon" class="btn">★ Common</button> | |
| <button id="selectVisible" class="btn">☑ Visible</button> | |
| <button id="clearAll" class="btn btn-ghost">✕ Clear</button> | |
| </div> | |
| <!-- content row --> | |
| <div class="content-wrap"> | |
| <!-- sections --> | |
| <div class="sections-scroll"> | |
| <!-- Tag Legend (compact collapsible) --> | |
| <details class="tag-legend" id="tagLegend"> | |
| <summary class="legend-summary"> | |
| <span class="legend-chips"> | |
| <span class="badge badge-critical">critical</span> | |
| <span class="badge badge-credential">credential</span> | |
| <span class="badge badge-feature">feature</span> | |
| <span class="badge badge-optional">optional</span> | |
| <span class="badge badge-advanced">advanced</span> | |
| <span class="badge badge-build">build-time</span> | |
| </span> | |
| <span class="legend-hint">what do these mean?</span> | |
| </summary> | |
| <div class="legend-body"> | |
| <div class="legend-row"><span class="badge badge-critical">critical</span><span>Space won't work without this</span></div> | |
| <div class="legend-row"><span class="badge badge-credential">credential</span><span>Sensitive key or token — never share</span></div> | |
| <div class="legend-row"><span class="badge badge-feature">feature</span><span>Enables a specific optional feature</span></div> | |
| <div class="legend-row"><span class="badge badge-optional">optional</span><span>Safe to change — nothing breaks</span></div> | |
| <div class="legend-row"><span class="badge badge-advanced">advanced</span><span>Power-user setting — wrong value causes issues</span></div> | |
| <div class="legend-row"><span class="badge badge-build">build-time</span><span>Needs HF Space rebuild to fully take effect</span></div> | |
| <div class="legend-tip">💡 Type a tag name in search to filter by it</div> | |
| </div> | |
| </details> | |
| <div id="sections"></div> | |
| <!-- Custom Env section --> | |
| <div id="customSec" class="sec" data-section="Custom Env"> | |
| <div class="sec-header"> | |
| <span class="sec-icon">🔧</span> | |
| <span class="sec-title">Custom Env</span> | |
| <div class="sec-line"></div> | |
| </div> | |
| <div id="customRows"></div> | |
| <button id="addCustom" class="btn" style="margin-top:6px;">+ Add variable</button> | |
| </div> | |
| </div> | |
| <!-- right panel --> | |
| <aside class="right-panel"> | |
| <div class="panel-scroll"> | |
| <!-- Summary --> | |
| <div class="pblock"> | |
| <div class="pblock-head"> | |
| <span class="pblock-title">📊 Summary</span> | |
| </div> | |
| <div class="pblock-body"> | |
| <div id="summary">No variables selected yet.</div> | |
| </div> | |
| </div> | |
| <!-- Output --> | |
| <div class="pblock"> | |
| <div class="pblock-head"> | |
| <span class="pblock-title">📦 Bundle Output</span> | |
| </div> | |
| <div class="pblock-body"> | |
| <button id="generateBundle" class="btn btn-amber" style="width:100%;font-size:12.5px;"># Generate Bundle</button> | |
| <textarea id="bundleOut" placeholder="Click # Generate to build your bundle…" readonly spellcheck="false"></textarea> | |
| <input type="text" id="envLineOut" placeholder="HUGGINGCLAW_ENV_BUNDLE=…" readonly spellcheck="false"> | |
| <div class="row-btns"> | |
| <button id="copyBundle" class="btn btn-amber">⎘ Bundle</button> | |
| <button id="copyEnvLine" class="btn">⎘ Env Line</button> | |
| <button id="copyJson" class="btn">⎘ JSON</button> | |
| <button id="applyBundle" class="btn btn-ghost">↺ Apply</button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Import --> | |
| <div class="pblock"> | |
| <div class="pblock-head"> | |
| <span class="pblock-title">📥 Import</span> | |
| </div> | |
| <div class="pblock-body"> | |
| <textarea id="importText" placeholder="Paste .env, JSON, or HUGGINGCLAW_ENV_BUNDLE=… here" spellcheck="false"></textarea> | |
| <button id="applyImport" class="btn btn-amber" style="width:100%;">↓ Import & Apply</button> | |
| </div> | |
| </div> | |
| </div> | |
| </aside> | |
| </div><!-- /content-wrap --> | |
| </main> | |
| </div><!-- /layout --> | |
| <!-- Toast --> | |
| <div id="toast">Copied ✓</div> | |
| <!-- env-builder.js provides MODEL_CATALOGS, FIELDS, ICONS and all logic --> | |
| <script src="env-builder.js"></script> | |
| </body> | |
| </html> | |