:root { --bg: #f6f8fb; --panel: #ffffff; --panel2: #f2f5fb; --text: #0f172a; --muted: #64748b; --border: rgba(15, 23, 42, 0.12); --accent: #2563eb; --accent2: #10b981; --danger: #ef4444; --shadow: 0 8px 20px rgba(15, 23, 42, 0.08); --shadow2: 0 14px 36px rgba(15, 23, 42, 0.10); } * { box-sizing: border-box; } html, body { height: 100%; } body { margin: 0; font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, "Apple Color Emoji", "Segoe UI Emoji"; background: var(--bg); color: var(--text); } .shell { display: grid; grid-template-columns: 260px 1fr; min-height: 100vh; } .sidebar { position: sticky; top: 0; height: 100vh; background: linear-gradient(180deg, #0b1220, #0b1220); color: #e8eefc; padding: 16px 14px; border-right: 1px solid rgba(255, 255, 255, 0.08); } .brand { display: grid; grid-template-columns: 40px 1fr; gap: 10px; align-items: center; padding: 10px; border-radius: 12px; background: rgba(255, 255, 255, 0.04); border: 1px solid rgba(255, 255, 255, 0.06); } .brandIcon { width: 40px; height: 40px; border-radius: 12px; display: grid; place-items: center; background: rgba(37, 99, 235, 0.22); border: 1px solid rgba(37, 99, 235, 0.35); font-weight: 800; } .brandTitle { font-weight: 800; font-size: 13px; letter-spacing: 0.2px; } .brandSub { color: rgba(232,238,252,0.75); font-size: 12px; margin-top: 2px; } .navTitle { margin-top: 16px; padding: 0 10px; font-size: 11px; color: rgba(232,238,252,0.65); letter-spacing: 0.12em; } .nav { margin-top: 8px; display: grid; gap: 6px; } .navItem { display: flex; align-items: center; gap: 10px; padding: 10px 10px; border-radius: 12px; color: rgba(232,238,252,0.85); text-decoration: none; border: 1px solid transparent; } .navItem:hover { background: rgba(255,255,255,0.05); } .navItem.active { background: rgba(37, 99, 235, 0.22); border-color: rgba(37, 99, 235, 0.30); color: #ffffff; } .navDot { width: 10px; height: 10px; border-radius: 999px; background: rgba(255,255,255,0.25); } .navItem.active .navDot { background: rgba(37, 99, 235, 1); } .sidebarFooter { position: absolute; left: 14px; right: 14px; bottom: 14px; } .statusBadge { display: flex; align-items: center; gap: 10px; padding: 10px 12px; border-radius: 14px; background: rgba(255, 255, 255, 0.04); border: 1px solid rgba(255, 255, 255, 0.08); } .statusLed { width: 10px; height: 10px; border-radius: 999px; background: rgba(16, 185, 129, 0.85); box-shadow: 0 0 0 4px rgba(16, 185, 129, 0.12); } .statusText { color: rgba(232,238,252,0.85); font-size: 12px; } .body { display: grid; grid-template-rows: 72px 1fr; min-width: 0; } .topbar { background: var(--panel); border-bottom: 1px solid var(--border); padding: 14px 18px; display: flex; align-items: center; justify-content: space-between; gap: 14px; } .kicker { font-size: 12px; color: var(--muted); } .pageTitle { font-size: 16px; font-weight: 800; letter-spacing: 0.2px; margin-top: 2px; } .topbarActions { display: flex; gap: 10px; align-items: center; } .content { padding: 18px; display: grid; grid-template-columns: min(460px, 100%) 1fr; gap: 16px; align-items: start; } .contentLeft { display: flex; flex-direction: column; gap: 16px; min-width: 0; } .modelForm { display: grid; gap: 10px; } .modelParams { display: grid; gap: 10px; } .modelParams[hidden] { display: none; } .modelForm .rowWide { grid-template-columns: 1fr; gap: 6px; align-items: stretch; } .modelForm .rowWide label { line-height: 1.3; } .inputUnit { display: grid; grid-template-columns: 1fr auto; gap: 8px; align-items: center; } .inputUnit input { min-width: 0; } .inputUnit .unit { font-size: 12px; color: var(--muted); white-space: nowrap; } .acc { border: 1px solid var(--border); border-radius: 10px; background: var(--panel2); overflow: hidden; } .acc > summary { padding: 10px 12px; font-size: 13px; font-weight: 700; cursor: pointer; list-style: none; user-select: none; } .acc > summary::-webkit-details-marker { display: none; } .acc > summary::after { content: ""; float: right; width: 8px; height: 8px; margin-top: 4px; border-right: 2px solid var(--muted); border-bottom: 2px solid var(--muted); transform: rotate(45deg); transition: transform 0.15s ease; } .acc[open] > summary::after { transform: rotate(-135deg); margin-top: 7px; } .accBody { padding: 0 12px 12px; display: grid; gap: 10px; } .accNested { margin-top: 4px; } .validation { margin: 0; padding: 8px 10px; border-radius: 8px; font-size: 12px; line-height: 1.35; background: rgba(234, 179, 8, 0.12); border: 1px solid rgba(234, 179, 8, 0.35); color: #92400e; } .validation.error { background: rgba(239, 68, 68, 0.1); border-color: rgba(239, 68, 68, 0.35); color: #b91c1c; } .yamlPreview { margin: 0; padding: 10px 12px; max-height: 220px; overflow: auto; font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; font-size: 11px; line-height: 1.45; background: #0f172a; color: #e2e8f0; border-radius: 10px; border: 1px solid var(--border); white-space: pre-wrap; word-break: break-word; } .btnBlock { width: 100%; justify-content: center; } .mutedNote { margin: 0; font-size: 12px; color: var(--muted); } .mutedNote .mono { font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; font-size: 11px; } .mutedNote a { color: rgba(37, 99, 235, 0.9); } .layoutManagerActions { display: flex; gap: 8px; margin-top: 4px; } .layoutManagerActions .btn { flex: 1; justify-content: center; } #layoutSelect { width: 100%; } .motorWheels { display: grid; gap: 12px; } .wheelMotorBlock { border: 1px solid var(--border); border-radius: 10px; padding: 10px 12px; background: #fff; } .wheelMotorTitle { font-size: 13px; font-weight: 700; margin-bottom: 8px; color: var(--text); } .wheelMotorMeta { font-size: 11px; color: var(--muted); margin-top: 6px; line-height: 1.35; } .wheelMotorBlock .rowWide { margin-bottom: 6px; } .wheelMotorBlock .rowWide:last-child { margin-bottom: 0; } .wheelMotorBlock input[type="checkbox"] { width: auto; margin-right: 6px; } .checkRow { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--muted); } .robotDiffSummary { width: 100%; font-size: 12px; color: rgba(37, 99, 235, 0.95); } .card { background: var(--panel); border: 1px solid var(--border); border-radius: 14px; box-shadow: var(--shadow); overflow: hidden; } .cardHeader { padding: 14px 16px; border-bottom: 1px solid var(--border); background: linear-gradient(180deg, rgba(37, 99, 235, 0.06), transparent 70%); } .cardHeaderToggle { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; cursor: pointer; user-select: none; } .cardHeaderToggle:hover { background: linear-gradient(180deg, rgba(37, 99, 235, 0.10), transparent 70%); } .cardChevron { flex-shrink: 0; width: 28px; height: 28px; border-radius: 8px; border: 1px solid var(--border); background: var(--panel2); position: relative; margin-top: 2px; transition: transform 0.2s ease; } .cardChevron::before { content: ""; position: absolute; left: 50%; top: 50%; width: 8px; height: 8px; border-right: 2px solid var(--muted); border-bottom: 2px solid var(--muted); transform: translate(-50%, -65%) rotate(45deg); } .card.collapsed .cardChevron { transform: rotate(-90deg); } .card.collapsed .cardBody { display: none; } .card.collapsed .cardHeader { border-bottom: none; } .cardTitle { font-size: 14px; font-weight: 800; letter-spacing: 0.2px; } .cardSub { margin-top: 4px; color: var(--muted); font-size: 12px; line-height: 1.35; } .cardBody { padding: 14px 16px; } .form { display: grid; gap: 10px; margin-bottom: 12px; } .formHint { margin: 0; font-size: 12px; line-height: 1.35; color: #b91c1c; } .formHint[hidden] { display: none; } .row { display: grid; grid-template-columns: 90px 1fr; gap: 10px; align-items: center; } label { color: var(--muted); font-size: 12px; } input, select { width: 100%; padding: 10px 10px; background: var(--panel2); border: 1px solid var(--border); color: var(--text); border-radius: 10px; outline: none; } input:focus, select:focus { border-color: rgba(37, 99, 235, 0.55); box-shadow: 0 0 0 4px rgba(37, 99, 235, 0.12); } .actions { display: flex; gap: 10px; } .btn, button { cursor: pointer; border: 1px solid var(--border); background: var(--panel2); color: var(--text); padding: 9px 12px; border-radius: 10px; font-weight: 600; } .btn.primary { background: rgba(37, 99, 235, 0.92); border-color: rgba(37, 99, 235, 0.92); color: #fff; } .btn.primary:hover { background: rgba(37, 99, 235, 1); } .btn.subtle { background: var(--panel2); } .btn.danger { color: var(--danger); border-color: rgba(239, 68, 68, 0.35); } .btn:active, button:active { transform: translateY(1px); } .btn.active, button.active { box-shadow: 0 0 0 4px rgba(37, 99, 235, 0.12); border-color: rgba(37, 99, 235, 0.55); } .list { display: grid; gap: 10px; } .item { border: 1px solid var(--border); background: #ffffff; border-radius: 12px; padding: 10px; } .itemTop { display: flex; justify-content: space-between; gap: 10px; align-items: flex-start; } .itemMain { flex: 1; min-width: 0; } .itemToggle { flex-shrink: 0; width: 26px; height: 26px; margin-top: 2px; margin-right: 8px; padding: 0; border-radius: 8px; border: 1px solid var(--border); background: var(--panel2); cursor: pointer; position: relative; } .itemToggle::before { content: ""; position: absolute; left: 50%; top: 50%; width: 7px; height: 7px; border-right: 2px solid var(--muted); border-bottom: 2px solid var(--muted); transform: translate(-50%, -65%) rotate(45deg); transition: transform 0.2s ease; } .item.collapsed .itemToggle::before { transform: translate(-50%, -35%) rotate(-135deg); } .item.collapsed .itemBody { display: none; } .itemTopRow { display: flex; align-items: flex-start; } .itemName { font-weight: 700; } .itemMeta { color: var(--muted); font-size: 12px; margin-top: 4px; } .itemBtns { display: flex; gap: 8px; } .poseRow { margin-top: 8px; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; } .poseField { display: grid; grid-template-columns: 18px 1fr; gap: 8px; align-items: center; } .poseLabel { color: var(--muted); font-size: 12px; text-align: right; } .poseInput { padding: 8px 9px; border-radius: 10px; background: var(--panel2); } .pill { display: inline-flex; align-items: center; gap: 6px; background: rgba(16, 185, 129, 0.10); border: 1px solid rgba(16, 185, 129, 0.22); color: rgba(16, 185, 129, 1); padding: 2px 8px; border-radius: 999px; font-size: 12px; } .toolbar { display: flex; flex-wrap: wrap; gap: 10px; align-items: end; margin-bottom: 10px; } .tool { display: grid; gap: 6px; } .tool label { font-size: 12px; } .tool input { width: 120px; } .toolGroup { display: flex; gap: 10px; align-items: end; } .toolGroup[hidden] { display: none; } .tool select { width: 170px; } .toolGroup .tool input { width: 110px; } .canvasWrap { background: #ffffff; border: 1px solid var(--border); border-radius: 12px; padding: 10px; height: min(72vh, 680px); min-height: 420px; } canvas { display: block; width: 100%; height: 100%; border-radius: 10px; background: #0b1220; touch-action: none; } .canvasWrap.panning canvas { cursor: grabbing; } .canvasWrap.shift-pan canvas { cursor: grab; } .metaBar { margin-top: 10px; display: flex; flex-wrap: wrap; gap: 10px 14px; color: var(--muted); font-size: 12px; } .fpHint { color: rgba(37, 99, 235, 0.95); margin-top: 8px; font-size: 12px; line-height: 1.4; } .footprintPresetPanel { display: grid; gap: 8px; margin-bottom: 10px; padding: 10px 12px; border-radius: 10px; border: 1px solid var(--border); background: #f8fafc; } .footprintPresetPanel .fpShapeParams { display: grid; gap: 6px; } .footprintPresetPanel.hidden { display: none; } .footprintCustomPanel { display: grid; gap: 8px; margin-bottom: 10px; padding: 10px 12px; border-radius: 10px; border: 1px solid var(--border); background: #f8fafc; } .footprintCustomPanel.hidden { display: none; } .fpVertexRow { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 6px 12px; font-size: 12px; } .fpVertexLabel strong { color: var(--text); } .fpSelectedVertex { font-size: 11px; } .fpVertexActions { display: flex; gap: 8px; } .fpVertexActions .btn { flex: 1; justify-content: center; font-size: 12px; padding: 6px 10px; } .viewHint { color: var(--muted); font-size: 12px; width: 100%; } .canvasWrap canvas.edit-footprint { cursor: crosshair; } @media (max-width: 980px) { .shell { grid-template-columns: 1fr; } .sidebar { position: relative; height: auto; } .body { grid-template-rows: auto 1fr; } .content { grid-template-columns: 1fr; } }