Added AMS discovery module
@@ -19,6 +19,8 @@ from backend.app.schemas.printer import (
|
||||
PrinterResponse,
|
||||
PrinterStatus,
|
||||
HMSErrorResponse,
|
||||
AMSUnit,
|
||||
AMSTray,
|
||||
)
|
||||
from backend.app.services.printer_manager import printer_manager
|
||||
from backend.app.services.bambu_ftp import (
|
||||
@@ -145,6 +147,42 @@ async def get_printer_status(printer_id: int, db: AsyncSession = Depends(get_db)
|
||||
for e in (state.hms_errors or [])
|
||||
]
|
||||
|
||||
# Parse AMS data from raw_data
|
||||
ams_units = []
|
||||
vt_tray = None
|
||||
ams_exists = False
|
||||
raw_data = state.raw_data or {}
|
||||
|
||||
if "ams" in raw_data:
|
||||
ams_exists = True
|
||||
for ams_data in raw_data["ams"]:
|
||||
trays = []
|
||||
for tray_data in ams_data.get("tray", []):
|
||||
trays.append(AMSTray(
|
||||
id=tray_data.get("id", 0),
|
||||
tray_color=tray_data.get("tray_color"),
|
||||
tray_type=tray_data.get("tray_type"),
|
||||
remain=tray_data.get("remain", 0),
|
||||
k=tray_data.get("k"),
|
||||
))
|
||||
ams_units.append(AMSUnit(
|
||||
id=ams_data.get("id", 0),
|
||||
humidity=ams_data.get("humidity"),
|
||||
temp=ams_data.get("temp"),
|
||||
tray=trays,
|
||||
))
|
||||
|
||||
# Virtual tray (external spool holder) - comes from vt_tray in raw_data
|
||||
if "vt_tray" in raw_data:
|
||||
vt_data = raw_data["vt_tray"]
|
||||
vt_tray = AMSTray(
|
||||
id=254, # Virtual tray ID
|
||||
tray_color=vt_data.get("tray_color"),
|
||||
tray_type=vt_data.get("tray_type"),
|
||||
remain=vt_data.get("remain", 0),
|
||||
k=vt_data.get("k"),
|
||||
)
|
||||
|
||||
return PrinterStatus(
|
||||
id=printer_id,
|
||||
name=printer.name,
|
||||
@@ -160,6 +198,9 @@ async def get_printer_status(printer_id: int, db: AsyncSession = Depends(get_db)
|
||||
temperatures=state.temperatures,
|
||||
cover_url=cover_url,
|
||||
hms_errors=hms_errors,
|
||||
ams=ams_units,
|
||||
ams_exists=ams_exists,
|
||||
vt_tray=vt_tray,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -43,6 +43,21 @@ class HMSErrorResponse(BaseModel):
|
||||
severity: int # 1=fatal, 2=serious, 3=common, 4=info
|
||||
|
||||
|
||||
class AMSTray(BaseModel):
|
||||
id: int
|
||||
tray_color: str | None = None
|
||||
tray_type: str | None = None
|
||||
remain: int = 0
|
||||
k: float | None = None # Pressure advance value
|
||||
|
||||
|
||||
class AMSUnit(BaseModel):
|
||||
id: int
|
||||
humidity: int | None = None
|
||||
temp: float | None = None
|
||||
tray: list[AMSTray] = []
|
||||
|
||||
|
||||
class PrinterStatus(BaseModel):
|
||||
id: int
|
||||
name: str
|
||||
@@ -58,3 +73,6 @@ class PrinterStatus(BaseModel):
|
||||
temperatures: dict | None = None
|
||||
cover_url: str | None = None
|
||||
hms_errors: list[HMSErrorResponse] = []
|
||||
ams: list[AMSUnit] = []
|
||||
ams_exists: bool = False
|
||||
vt_tray: AMSTray | None = None # Virtual tray / external spool
|
||||
|
||||
@@ -179,6 +179,17 @@ class BambuMQTTClient:
|
||||
f"gcode_file: {print_data.get('gcode_file')}, subtask_name: {print_data.get('subtask_name')}"
|
||||
)
|
||||
|
||||
# Handle AMS data that comes inside print key
|
||||
if "ams" in print_data:
|
||||
try:
|
||||
self._handle_ams_data(print_data["ams"])
|
||||
except Exception as e:
|
||||
logger.error(f"[{self.serial_number}] Error handling AMS data from print: {e}")
|
||||
|
||||
# Handle vt_tray (virtual tray / external spool) data
|
||||
if "vt_tray" in print_data:
|
||||
self.state.raw_data["vt_tray"] = print_data["vt_tray"]
|
||||
|
||||
# Check for K-profile response (extrusion_cali)
|
||||
if "command" in print_data:
|
||||
logger.debug(f"[{self.serial_number}] Received command response: {print_data.get('command')}")
|
||||
@@ -187,7 +198,7 @@ class BambuMQTTClient:
|
||||
|
||||
self._update_state(print_data)
|
||||
|
||||
def _handle_ams_data(self, ams_data: list):
|
||||
def _handle_ams_data(self, ams_data):
|
||||
"""Handle AMS data changes for Spoolman integration.
|
||||
|
||||
This is called when we receive top-level AMS data in MQTT messages.
|
||||
@@ -195,15 +206,22 @@ class BambuMQTTClient:
|
||||
"""
|
||||
import hashlib
|
||||
|
||||
# Store AMS data in raw_data so it's accessible via API
|
||||
if "ams" not in self.state.raw_data:
|
||||
self.state.raw_data["ams"] = ams_data
|
||||
# Handle nested ams structure: {"ams": {"ams": [...]}} or {"ams": [...]}
|
||||
if isinstance(ams_data, dict) and "ams" in ams_data:
|
||||
ams_list = ams_data["ams"]
|
||||
elif isinstance(ams_data, list):
|
||||
ams_list = ams_data
|
||||
else:
|
||||
self.state.raw_data["ams"] = ams_data
|
||||
logger.warning(f"[{self.serial_number}] Unexpected AMS data format: {type(ams_data)}")
|
||||
return
|
||||
|
||||
# Store AMS data in raw_data so it's accessible via API
|
||||
self.state.raw_data["ams"] = ams_list
|
||||
logger.debug(f"[{self.serial_number}] Stored AMS data with {len(ams_list)} units")
|
||||
|
||||
# Create a hash of relevant AMS data to detect changes
|
||||
ams_hash_data = []
|
||||
for ams_unit in ams_data:
|
||||
for ams_unit in ams_list:
|
||||
for tray in ams_unit.get("tray", []):
|
||||
# Include fields that matter for filament tracking
|
||||
ams_hash_data.append(
|
||||
@@ -217,7 +235,7 @@ class BambuMQTTClient:
|
||||
self._previous_ams_hash = ams_hash
|
||||
if self.on_ams_change:
|
||||
logger.info(f"[{self.serial_number}] AMS data changed, triggering sync callback")
|
||||
self.on_ams_change(ams_data)
|
||||
self.on_ams_change(ams_list)
|
||||
|
||||
def _update_state(self, data: dict):
|
||||
"""Update printer state from message data."""
|
||||
@@ -306,11 +324,14 @@ class BambuMQTTClient:
|
||||
severity=severity if severity > 0 else 3,
|
||||
))
|
||||
|
||||
# Preserve AMS data when updating raw_data (AMS comes at top level, not in print)
|
||||
# Preserve AMS and vt_tray data when updating raw_data
|
||||
ams_data = self.state.raw_data.get("ams")
|
||||
vt_tray_data = self.state.raw_data.get("vt_tray")
|
||||
self.state.raw_data = data
|
||||
if ams_data is not None:
|
||||
self.state.raw_data["ams"] = ams_data
|
||||
if vt_tray_data is not None:
|
||||
self.state.raw_data["vt_tray"] = vt_tray_data
|
||||
|
||||
# Log state transitions for debugging
|
||||
if "gcode_state" in data:
|
||||
|
||||
@@ -41,6 +41,21 @@ export interface HMSError {
|
||||
severity: number; // 1=fatal, 2=serious, 3=common, 4=info
|
||||
}
|
||||
|
||||
export interface AMSTray {
|
||||
id: number;
|
||||
tray_color: string | null;
|
||||
tray_type: string | null;
|
||||
remain: number;
|
||||
k: number | null; // Pressure advance value
|
||||
}
|
||||
|
||||
export interface AMSUnit {
|
||||
id: number;
|
||||
humidity: number | null;
|
||||
temp: number | null;
|
||||
tray: AMSTray[];
|
||||
}
|
||||
|
||||
export interface PrinterStatus {
|
||||
id: number;
|
||||
name: string;
|
||||
@@ -62,6 +77,9 @@ export interface PrinterStatus {
|
||||
} | null;
|
||||
cover_url: string | null;
|
||||
hms_errors: HMSError[];
|
||||
ams: AMSUnit[];
|
||||
ams_exists: boolean;
|
||||
vt_tray: AMSTray | null; // Virtual tray / external spool
|
||||
}
|
||||
|
||||
export interface PrinterCreate {
|
||||
|
||||
@@ -1,59 +1,16 @@
|
||||
import { useState } from 'react';
|
||||
import { useMutation } from '@tanstack/react-query';
|
||||
import { api } from '../../api/client';
|
||||
import type { PrinterStatus } from '../../api/client';
|
||||
import { Package, Loader2, ArrowDown, ArrowUp } from 'lucide-react';
|
||||
import type { PrinterStatus, AMSUnit } from '../../api/client';
|
||||
import { Package, Loader2, ArrowDown, ArrowUp, Droplets, Thermometer } from 'lucide-react';
|
||||
|
||||
interface AMSPanelProps {
|
||||
printerId: number;
|
||||
status: PrinterStatus | null | undefined;
|
||||
}
|
||||
|
||||
interface AMSTray {
|
||||
id: number;
|
||||
color: string;
|
||||
type: string;
|
||||
remain: number;
|
||||
active: boolean;
|
||||
}
|
||||
|
||||
interface AMSUnit {
|
||||
id: number;
|
||||
trays: AMSTray[];
|
||||
}
|
||||
|
||||
// Parse AMS data from raw_data in status
|
||||
function parseAMSData(status: PrinterStatus | null | undefined): AMSUnit[] {
|
||||
// AMS data comes from raw MQTT data
|
||||
// This is a simplified parser - actual data structure may vary
|
||||
const rawData = (status as { raw_data?: { ams?: unknown[] } })?.raw_data;
|
||||
if (!rawData?.ams) return [];
|
||||
|
||||
try {
|
||||
return (rawData.ams as Array<{
|
||||
id?: number;
|
||||
tray?: Array<{
|
||||
id?: number;
|
||||
tray_color?: string;
|
||||
tray_type?: string;
|
||||
remain?: number;
|
||||
}>;
|
||||
}>).map((unit) => ({
|
||||
id: unit.id ?? 0,
|
||||
trays: (unit.tray ?? []).map((tray) => ({
|
||||
id: tray.id ?? 0,
|
||||
color: tray.tray_color ?? 'FFFFFF',
|
||||
type: tray.tray_type ?? 'Unknown',
|
||||
remain: tray.remain ?? 0,
|
||||
active: false, // Would need additional MQTT data to determine
|
||||
})),
|
||||
}));
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
function hexToRgb(hex: string): string {
|
||||
function hexToRgb(hex: string | null): string {
|
||||
if (!hex) return 'rgb(128, 128, 128)';
|
||||
// Handle RRGGBBAA format
|
||||
const cleanHex = hex.replace('#', '').substring(0, 6);
|
||||
const r = parseInt(cleanHex.substring(0, 2), 16) || 128;
|
||||
@@ -65,7 +22,7 @@ function hexToRgb(hex: string): string {
|
||||
export function AMSPanel({ printerId, status }: AMSPanelProps) {
|
||||
const isConnected = status?.connected ?? false;
|
||||
const isPrinting = status?.state === 'RUNNING';
|
||||
const amsUnits = parseAMSData(status);
|
||||
const amsUnits: AMSUnit[] = status?.ams ?? [];
|
||||
|
||||
const [selectedTray, setSelectedTray] = useState<number | null>(null);
|
||||
|
||||
@@ -116,14 +73,28 @@ export function AMSPanel({ printerId, status }: AMSPanelProps) {
|
||||
{/* AMS Units */}
|
||||
{amsUnits.map((unit) => (
|
||||
<div key={unit.id} className="mb-4">
|
||||
{amsUnits.length > 1 && (
|
||||
<div className="text-xs text-bambu-gray mb-2">AMS {unit.id + 1}</div>
|
||||
)}
|
||||
<div className="flex items-center justify-between text-xs text-bambu-gray mb-2">
|
||||
<span>AMS {unit.id + 1}</span>
|
||||
<div className="flex items-center gap-3">
|
||||
{unit.humidity !== null && (
|
||||
<span className="flex items-center gap-1">
|
||||
<Droplets className="w-3 h-3" />
|
||||
{unit.humidity}%
|
||||
</span>
|
||||
)}
|
||||
{unit.temp !== null && (
|
||||
<span className="flex items-center gap-1">
|
||||
<Thermometer className="w-3 h-3" />
|
||||
{unit.temp}°C
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid grid-cols-4 gap-2">
|
||||
{unit.trays.map((tray) => {
|
||||
{unit.tray.map((tray) => {
|
||||
const globalTrayId = unit.id * 4 + tray.id;
|
||||
const isSelected = selectedTray === globalTrayId;
|
||||
const isEmpty = tray.type === 'NONE' || !tray.type;
|
||||
const isEmpty = !tray.tray_type || tray.tray_type === '' || tray.tray_type === 'NONE';
|
||||
|
||||
return (
|
||||
<button
|
||||
@@ -140,7 +111,7 @@ export function AMSPanel({ printerId, status }: AMSPanelProps) {
|
||||
<div
|
||||
className="w-8 h-8 mx-auto rounded-full mb-1 border-2 border-bambu-dark-tertiary"
|
||||
style={{
|
||||
backgroundColor: isEmpty ? '#333' : hexToRgb(tray.color),
|
||||
backgroundColor: isEmpty ? '#333' : hexToRgb(tray.tray_color),
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -150,8 +121,8 @@ export function AMSPanel({ printerId, status }: AMSPanelProps) {
|
||||
</div>
|
||||
|
||||
{/* Type */}
|
||||
<div className="text-xs text-center truncate" title={tray.type}>
|
||||
{isEmpty ? '--' : tray.type}
|
||||
<div className="text-xs text-center truncate" title={tray.tray_type ?? ''}>
|
||||
{isEmpty ? '--' : tray.tray_type}
|
||||
</div>
|
||||
|
||||
{/* Remaining */}
|
||||
@@ -168,11 +139,6 @@ export function AMSPanel({ printerId, status }: AMSPanelProps) {
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Active Indicator */}
|
||||
{tray.active && (
|
||||
<div className="absolute top-1 right-1 w-2 h-2 rounded-full bg-bambu-green animate-pulse" />
|
||||
)}
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
|
||||
@@ -0,0 +1,923 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>BambuTrack Control - v10</title>
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
|
||||
:root {
|
||||
--bg-main: #f5f5f5;
|
||||
--bg-white: #ffffff;
|
||||
--bg-light: #fafafa;
|
||||
--bg-panel: #f5f5f5;
|
||||
--bg-hover: #e8e8e8;
|
||||
--text-primary: #333333;
|
||||
--text-secondary: #666666;
|
||||
--text-muted: #999999;
|
||||
--border: #e0e0e0;
|
||||
--border-light: #eeeeee;
|
||||
--accent: #00ae42;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
background: var(--bg-main);
|
||||
color: var(--text-primary);
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.main-layout {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 450px;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
/* Left Panel - Camera */
|
||||
.left-panel {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: var(--bg-main);
|
||||
}
|
||||
|
||||
.camera-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 8px 12px;
|
||||
background: var(--bg-white);
|
||||
border-bottom: 1px solid var(--border);
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.camera-title {
|
||||
font-size: 13px;
|
||||
color: var(--text-primary);
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.icon-btn {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
border: none;
|
||||
background: none;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.icon-btn:hover { background: var(--bg-hover); }
|
||||
.icon-btn img { width: 18px; height: 18px; opacity: 0.6; }
|
||||
|
||||
.camera-feed {
|
||||
flex: 1;
|
||||
background: #1a1a1a;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #555;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* Status bar */
|
||||
.status-bar {
|
||||
background: var(--accent);
|
||||
padding: 4px 12px;
|
||||
}
|
||||
|
||||
/* Print Progress */
|
||||
.print-progress {
|
||||
background: var(--bg-white);
|
||||
padding: 16px 20px;
|
||||
}
|
||||
|
||||
.progress-label { font-size: 12px; color: var(--text-muted); margin-bottom: 12px; }
|
||||
.progress-row { display: flex; gap: 14px; align-items: center; }
|
||||
.progress-thumb {
|
||||
width: 60px; height: 60px;
|
||||
background: var(--bg-light);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
flex-direction: column;
|
||||
font-size: 10px;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
.progress-info { flex: 1; }
|
||||
.progress-name { font-weight: 500; font-size: 14px; margin-bottom: 2px; }
|
||||
.progress-status { color: var(--accent); font-size: 13px; margin-bottom: 8px; }
|
||||
.progress-bar-bg { height: 4px; background: var(--border-light); border-radius: 2px; margin-bottom: 8px; }
|
||||
.progress-bar-fill { height: 100%; background: var(--accent); border-radius: 2px; width: 0%; }
|
||||
.progress-meta { font-size: 12px; color: var(--text-muted); margin-bottom: 4px; }
|
||||
.progress-btns { display: flex; gap: 6px; }
|
||||
.progress-btn {
|
||||
width: 32px; height: 32px;
|
||||
border: 1px solid var(--border);
|
||||
background: var(--bg-white);
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
.progress-btn:hover { background: var(--bg-hover); }
|
||||
|
||||
/* Right Panel - Control */
|
||||
.right-panel {
|
||||
background: var(--bg-white);
|
||||
border-left: 1px solid var(--border);
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.control-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px 16px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.control-title { font-size: 13px; margin-right: auto; color: var(--text-secondary); }
|
||||
.header-btn {
|
||||
padding: 7px 16px;
|
||||
font-size: 12px;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
background: var(--accent);
|
||||
color: white;
|
||||
}
|
||||
.header-btn:hover { background: #009938; }
|
||||
|
||||
.control-body {
|
||||
padding: 16px;
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
/* Top Section: Temp + Movement side by side */
|
||||
.top-section {
|
||||
display: flex;
|
||||
gap: 24px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
/* Temperature Column */
|
||||
.temp-column { flex: 0 0 auto; }
|
||||
|
||||
.temp-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 5px 0;
|
||||
}
|
||||
|
||||
.temp-icon { width: 20px; height: 20px; display: flex; align-items: center; justify-content: center; }
|
||||
.temp-icon img { width: 18px; opacity: 0.5; }
|
||||
|
||||
.temp-badge {
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
color: var(--accent);
|
||||
background: #e8f5e9;
|
||||
padding: 2px 8px;
|
||||
border-radius: 4px;
|
||||
min-width: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.temp-value { font-size: 18px; font-weight: 500; }
|
||||
.temp-target { font-size: 15px; color: var(--text-muted); }
|
||||
|
||||
/* Air Condition */
|
||||
.air-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 12px 0;
|
||||
margin-top: 10px;
|
||||
border-top: 1px solid var(--border-light);
|
||||
}
|
||||
|
||||
.air-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
font-size: 13px;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.air-label img { width: 18px; opacity: 0.5; }
|
||||
|
||||
.air-value {
|
||||
font-size: 13px;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.lamp-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
font-size: 13px;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.lamp-dot { width: 14px; height: 14px; border-radius: 50%; background: var(--accent); }
|
||||
|
||||
/* Movement Column */
|
||||
.movement-column {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.nozzle-toggle {
|
||||
display: flex;
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--border);
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.nozzle-toggle button {
|
||||
padding: 7px 20px;
|
||||
border: none;
|
||||
background: var(--bg-white);
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.nozzle-toggle button:first-child { border-right: 1px solid var(--border); }
|
||||
.nozzle-toggle button.active { background: var(--accent); color: white; }
|
||||
|
||||
.movement-row {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.jog-section { display: flex; flex-direction: column; align-items: center; }
|
||||
|
||||
.jog-pad {
|
||||
position: relative;
|
||||
width: 110px;
|
||||
height: 110px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.jog-ring {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(135deg, #f8f8f8 0%, #ebebeb 100%);
|
||||
border: 1px solid var(--border);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.jog-label {
|
||||
position: absolute;
|
||||
font-size: 11px;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.jog-label.top { top: 8px; left: 50%; transform: translateX(-50%); }
|
||||
.jog-label.bottom { bottom: 8px; left: 50%; transform: translateX(-50%); }
|
||||
.jog-label.left { left: 8px; top: 50%; transform: translateY(-50%); }
|
||||
.jog-label.right { right: 8px; top: 50%; transform: translateY(-50%); }
|
||||
|
||||
.jog-btn {
|
||||
position: absolute;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
background: var(--bg-white);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 10px;
|
||||
color: var(--text-muted);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.jog-btn:hover { background: var(--bg-hover); }
|
||||
.jog-btn.up { top: 18px; left: 50%; transform: translateX(-50%); }
|
||||
.jog-btn.down { bottom: 18px; left: 50%; transform: translateX(-50%); }
|
||||
.jog-btn.left { left: 18px; top: 50%; transform: translateY(-50%); }
|
||||
.jog-btn.right { right: 18px; top: 50%; transform: translateY(-50%); }
|
||||
|
||||
.jog-home {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: 50%;
|
||||
background: var(--accent);
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.jog-home:hover { background: #009938; }
|
||||
.jog-home img { width: 18px; filter: brightness(0) invert(1); }
|
||||
|
||||
/* Bed Controls */
|
||||
.bed-controls {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.bed-btn {
|
||||
padding: 7px 12px;
|
||||
background: var(--bg-white);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.bed-btn:hover { background: var(--bg-hover); }
|
||||
.bed-label { font-size: 12px; color: var(--text-muted); padding: 0 6px; }
|
||||
|
||||
/* Extruder Section */
|
||||
.extruder-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.extruder-btn {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
background: var(--bg-white);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
color: var(--text-muted);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.extruder-btn:hover { background: var(--bg-hover); }
|
||||
|
||||
.extruder-graphic {
|
||||
height: 70px;
|
||||
margin: 6px 0;
|
||||
}
|
||||
|
||||
.extruder-graphic img { height: 100%; }
|
||||
.extruder-label { font-size: 12px; color: var(--text-muted); }
|
||||
|
||||
/* ========== FILAMENT BOXES ========== */
|
||||
.filament-boxes {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
margin-bottom: 14px;
|
||||
padding-bottom: 14px;
|
||||
border-bottom: 1px solid var(--border-light);
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.filament-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
padding: 10px 12px;
|
||||
background: var(--bg-white);
|
||||
border: 2px solid var(--border);
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.filament-box:hover { border-color: #ccc; }
|
||||
.filament-box.active { border-color: var(--accent); }
|
||||
|
||||
.filament-dots { display: flex; gap: 4px; }
|
||||
|
||||
.f-dot {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.f-dot.empty {
|
||||
background: #e8e8e8 !important;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.f-dot-sep {
|
||||
width: 1px;
|
||||
height: 18px;
|
||||
background: #ccc;
|
||||
margin: 0 2px;
|
||||
}
|
||||
|
||||
.filament-count {
|
||||
font-size: 13px;
|
||||
color: var(--text-muted);
|
||||
margin-left: 6px;
|
||||
}
|
||||
|
||||
/* ========== AMS SECTION ========== */
|
||||
.ams-section {
|
||||
display: flex;
|
||||
gap: 14px;
|
||||
}
|
||||
|
||||
.ams-unit {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
background: var(--bg-panel);
|
||||
border-radius: 12px;
|
||||
padding: 14px;
|
||||
}
|
||||
|
||||
/* AMS Header */
|
||||
.ams-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.ams-humidity {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
font-size: 14px;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.ams-humidity img { width: 16px; opacity: 0.5; }
|
||||
.ams-humidity .sun { font-size: 16px; color: #f5a623; }
|
||||
|
||||
/* Slot Labels */
|
||||
.slot-labels {
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.slot-label {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
font-size: 11px;
|
||||
color: var(--text-muted);
|
||||
padding: 3px 0;
|
||||
background: var(--bg-white);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
/* AMS Slots */
|
||||
.ams-slots {
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.ams-slot {
|
||||
flex: 1;
|
||||
height: 80px;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
border: 2px solid var(--border);
|
||||
background: var(--bg-white);
|
||||
}
|
||||
|
||||
.ams-slot:hover { border-color: #bbb; }
|
||||
.ams-slot.active { border-color: #d4a84b; }
|
||||
|
||||
.ams-slot-fill {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
.ams-slot-type {
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: white;
|
||||
text-shadow: 0 1px 2px rgba(0,0,0,0.3);
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.ams-slot-type.dark { color: #333; text-shadow: none; }
|
||||
|
||||
.ams-slot-eye { width: 18px; height: 18px; }
|
||||
.ams-slot-eye img { width: 16px; height: 16px; opacity: 0.8; }
|
||||
.ams-slot-eye.invert img { filter: invert(1); }
|
||||
|
||||
/* Connector Lines */
|
||||
.ams-connectors {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
.connector-group {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.connector-line {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.connector-line .vline {
|
||||
width: 2px;
|
||||
height: 14px;
|
||||
background: #c0c0c0;
|
||||
}
|
||||
|
||||
.connector-hbar {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 12%;
|
||||
right: 12%;
|
||||
height: 2px;
|
||||
background: #c0c0c0;
|
||||
}
|
||||
|
||||
/* AMS Actions */
|
||||
.ams-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
margin-top: 14px;
|
||||
padding-top: 14px;
|
||||
border-top: 1px solid var(--border-light);
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.auto-refill-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 9px 16px;
|
||||
background: var(--bg-white);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
font-size: 13px;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.auto-refill-btn:hover { background: var(--bg-hover); }
|
||||
|
||||
.ams-settings-btn {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
background: var(--bg-white);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.ams-settings-btn:hover { background: var(--bg-hover); }
|
||||
.ams-settings-btn img { width: 20px; opacity: 0.5; }
|
||||
|
||||
/* Hub */
|
||||
.hub-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.hub-line { width: 30px; height: 2px; background: #c0c0c0; }
|
||||
|
||||
.hub-graphic {
|
||||
display: flex;
|
||||
padding: 5px 8px;
|
||||
background: var(--bg-white);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.hub-port {
|
||||
width: 10px;
|
||||
height: 14px;
|
||||
background: var(--accent);
|
||||
border-radius: 2px;
|
||||
margin: 0 2px;
|
||||
}
|
||||
|
||||
.ams-spacer { flex: 1; }
|
||||
|
||||
.ams-action-btn {
|
||||
padding: 9px 24px;
|
||||
border-radius: 8px;
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
background: #e8e8e8;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.ams-action-btn:hover { background: #ddd; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="main-layout">
|
||||
<!-- Left Panel - Camera -->
|
||||
<div class="left-panel">
|
||||
<div class="camera-header">
|
||||
<span class="camera-title">Camera</span>
|
||||
<button class="icon-btn"><img src="icons/video-camera.svg"></button>
|
||||
<button class="icon-btn"><img src="icons/webcam.svg"></button>
|
||||
<button class="icon-btn"><img src="icons/settings.svg"></button>
|
||||
<button class="icon-btn"><img src="icons/reload.svg"></button>
|
||||
</div>
|
||||
<div class="camera-feed">Camera Feed</div>
|
||||
<div class="status-bar"></div>
|
||||
<div class="print-progress">
|
||||
<div class="progress-label">Printing Progress</div>
|
||||
<div class="progress-row">
|
||||
<div class="progress-thumb">
|
||||
Bambu<br>Lab
|
||||
</div>
|
||||
<div class="progress-info">
|
||||
<div class="progress-name">N/A</div>
|
||||
<div class="progress-status">N/A</div>
|
||||
<div class="progress-bar-bg"><div class="progress-bar-fill"></div></div>
|
||||
<div class="progress-meta">Layer: N/A N/A</div>
|
||||
<div class="progress-meta">Estimated finish time: N/A</div>
|
||||
</div>
|
||||
<div class="progress-btns">
|
||||
<button class="progress-btn">⌂</button>
|
||||
<button class="progress-btn">⏸</button>
|
||||
<button class="progress-btn">■</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Right Panel - Control -->
|
||||
<div class="right-panel">
|
||||
<div class="control-header">
|
||||
<span class="control-title">Control</span>
|
||||
<button class="header-btn">Printer Parts</button>
|
||||
<button class="header-btn">Print Options</button>
|
||||
<button class="header-btn">Calibration</button>
|
||||
</div>
|
||||
|
||||
<div class="control-body">
|
||||
<!-- Top Section: Temp + Movement side by side -->
|
||||
<div class="top-section">
|
||||
<!-- Temperature Column -->
|
||||
<div class="temp-column">
|
||||
<div class="temp-row">
|
||||
<div class="temp-icon"><img src="icons/hotend.svg"></div>
|
||||
<span class="temp-badge">L</span>
|
||||
<span class="temp-value">24</span>
|
||||
<span class="temp-target">/0 °C</span>
|
||||
</div>
|
||||
<div class="temp-row">
|
||||
<div class="temp-icon"><img src="icons/hotend.svg"></div>
|
||||
<span class="temp-badge">R</span>
|
||||
<span class="temp-value">23</span>
|
||||
<span class="temp-target">/0 °C</span>
|
||||
</div>
|
||||
<div class="temp-row">
|
||||
<div class="temp-icon"><img src="icons/heatbed.svg"></div>
|
||||
<span class="temp-value">23</span>
|
||||
<span class="temp-target">/0 °C</span>
|
||||
</div>
|
||||
<div class="temp-row">
|
||||
<div class="temp-icon"><img src="icons/chamber.svg"></div>
|
||||
<span class="temp-value">23</span>
|
||||
<span class="temp-target">/0 °C</span>
|
||||
</div>
|
||||
|
||||
<!-- Air Condition -->
|
||||
<div class="air-section">
|
||||
<div class="air-label"><img src="icons/ventilation.svg"> Air Condition</div>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: 16px; margin-top: 8px;">
|
||||
<div class="air-value"><img src="icons/ventilation.svg" style="width:16px; opacity:0.5; vertical-align:middle;"> 100%</div>
|
||||
<div class="lamp-section">Lamp <div class="lamp-dot"></div></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Movement Column -->
|
||||
<div class="movement-column">
|
||||
<div class="nozzle-toggle">
|
||||
<button class="active">Left</button>
|
||||
<button>Right</button>
|
||||
</div>
|
||||
|
||||
<div class="movement-row">
|
||||
<div class="jog-section">
|
||||
<div class="jog-pad">
|
||||
<div class="jog-ring">
|
||||
<span class="jog-label top">Y</span>
|
||||
<span class="jog-label bottom">-Y</span>
|
||||
<span class="jog-label left">-X</span>
|
||||
<span class="jog-label right">X</span>
|
||||
<button class="jog-btn up">▲</button>
|
||||
<button class="jog-btn down">▼</button>
|
||||
<button class="jog-btn left">◀</button>
|
||||
<button class="jog-btn right">▶</button>
|
||||
<button class="jog-home"><img src="icons/home.svg"></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bed-controls">
|
||||
<button class="bed-btn">↑10</button>
|
||||
<button class="bed-btn">↑1</button>
|
||||
<span class="bed-label">Bed</span>
|
||||
<button class="bed-btn">↓1</button>
|
||||
<button class="bed-btn">↓10</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="extruder-section">
|
||||
<button class="extruder-btn">▲</button>
|
||||
<div class="extruder-graphic"><img src="icons/dual-extruder.png"></div>
|
||||
<button class="extruder-btn">▼</button>
|
||||
<span class="extruder-label">Extruder</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Filament Assignment Boxes -->
|
||||
<div class="filament-boxes">
|
||||
<div class="filament-box active">
|
||||
<div class="filament-dots">
|
||||
<div class="f-dot" style="background: #FFD700;"></div>
|
||||
<div class="f-dot" style="background: #333;"></div>
|
||||
<div class="f-dot" style="background: #333;"></div>
|
||||
<div class="f-dot" style="background: #333;"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="filament-box">
|
||||
<div class="filament-dots">
|
||||
<div class="f-dot" style="background: #333;"></div>
|
||||
<div class="f-dot" style="background: #333;"></div>
|
||||
<div class="f-dot-sep"></div>
|
||||
<div class="f-dot" style="background: #FF3366;"></div>
|
||||
</div>
|
||||
<span class="filament-count">0</span>
|
||||
</div>
|
||||
<div class="filament-box">
|
||||
<div class="filament-dots">
|
||||
<div class="f-dot empty"></div>
|
||||
<div class="f-dot empty"></div>
|
||||
<div class="f-dot empty"></div>
|
||||
</div>
|
||||
<span class="filament-count">0</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- AMS Section - Two units side by side -->
|
||||
<div class="ams-section">
|
||||
<!-- AMS Unit 1 -->
|
||||
<div class="ams-unit">
|
||||
<div class="ams-header">
|
||||
<div class="ams-humidity"><img src="icons/water.svg"> 17 %</div>
|
||||
<div class="ams-humidity"><span class="sun">☀</span></div>
|
||||
</div>
|
||||
<div class="slot-labels">
|
||||
<div class="slot-label">A1↓</div>
|
||||
<div class="slot-label">A2↓</div>
|
||||
<div class="slot-label">A3↓</div>
|
||||
<div class="slot-label">A4↓</div>
|
||||
</div>
|
||||
<div class="ams-slots">
|
||||
<div class="ams-slot active">
|
||||
<div class="ams-slot-fill" style="background: #FFD700;">
|
||||
<span class="ams-slot-type dark">PLA</span>
|
||||
<div class="ams-slot-eye"><img src="icons/eye.svg"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ams-slot">
|
||||
<div class="ams-slot-fill" style="background: #333;">
|
||||
<span class="ams-slot-type">PETG</span>
|
||||
<div class="ams-slot-eye invert"><img src="icons/eye.svg"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ams-slot">
|
||||
<div class="ams-slot-fill" style="background: #8B4513;">
|
||||
<span class="ams-slot-type">PETG</span>
|
||||
<div class="ams-slot-eye invert"><img src="icons/eye.svg"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ams-slot">
|
||||
<div class="ams-slot-fill" style="background: #666;">
|
||||
<span class="ams-slot-type">PLA</span>
|
||||
<div class="ams-slot-eye invert"><img src="icons/eye.svg"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ams-connectors">
|
||||
<div class="connector-group">
|
||||
<div class="connector-line"><div class="vline"></div></div>
|
||||
<div class="connector-line"><div class="vline"></div></div>
|
||||
<div class="connector-line"><div class="vline"></div></div>
|
||||
<div class="connector-line"><div class="vline"></div></div>
|
||||
<div class="connector-hbar"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- AMS Unit 2 -->
|
||||
<div class="ams-unit">
|
||||
<div class="ams-header">
|
||||
<div class="ams-humidity"><img src="icons/water.svg"> 14 %</div>
|
||||
<div class="ams-humidity"><span class="sun">☀</span></div>
|
||||
</div>
|
||||
<div class="slot-labels">
|
||||
<div class="slot-label">B1↓</div>
|
||||
<div class="slot-label">B2↓</div>
|
||||
<div class="slot-label">B3↓</div>
|
||||
<div class="slot-label">B4↓</div>
|
||||
</div>
|
||||
<div class="ams-slots">
|
||||
<div class="ams-slot">
|
||||
<div class="ams-slot-fill" style="background: #888;">
|
||||
<span class="ams-slot-type">PLA</span>
|
||||
<div class="ams-slot-eye invert"><img src="icons/eye.svg"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ams-slot">
|
||||
<div class="ams-slot-fill" style="background: #666;">
|
||||
<span class="ams-slot-type">PETG</span>
|
||||
<div class="ams-slot-eye invert"><img src="icons/eye.svg"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ams-slot">
|
||||
<div class="ams-slot-fill" style="background: #888;">
|
||||
<span class="ams-slot-type">PLA</span>
|
||||
<div class="ams-slot-eye invert"><img src="icons/eye.svg"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ams-slot">
|
||||
<div class="ams-slot-fill" style="background: #aaa;">
|
||||
<span class="ams-slot-type dark">Sup.PLA</span>
|
||||
<div class="ams-slot-eye"><img src="icons/eye.svg"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ams-connectors">
|
||||
<div class="connector-group">
|
||||
<div class="connector-line"><div class="vline"></div></div>
|
||||
<div class="connector-line"><div class="vline"></div></div>
|
||||
<div class="connector-line"><div class="vline"></div></div>
|
||||
<div class="connector-line"><div class="vline"></div></div>
|
||||
<div class="connector-hbar"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- AMS Actions -->
|
||||
<div class="ams-actions">
|
||||
<button class="auto-refill-btn">Auto-refill</button>
|
||||
<button class="ams-settings-btn"><img src="icons/ams-settings.svg"></button>
|
||||
<div class="hub-section">
|
||||
<div class="hub-line"></div>
|
||||
<div class="hub-graphic">
|
||||
<div class="hub-port"></div>
|
||||
<div class="hub-port"></div>
|
||||
</div>
|
||||
<div class="hub-line"></div>
|
||||
</div>
|
||||
<div class="ams-spacer"></div>
|
||||
<button class="ams-action-btn">Unload</button>
|
||||
<button class="ams-action-btn">Load</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,936 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>BambuTrack Control - v11</title>
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
|
||||
:root {
|
||||
--bg-main: #f5f5f5;
|
||||
--bg-white: #ffffff;
|
||||
--bg-light: #fafafa;
|
||||
--bg-panel: #f5f5f5;
|
||||
--bg-hover: #e8e8e8;
|
||||
--text-primary: #333333;
|
||||
--text-secondary: #666666;
|
||||
--text-muted: #999999;
|
||||
--border: #e0e0e0;
|
||||
--border-light: #eeeeee;
|
||||
--accent: #00ae42;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
background: var(--bg-main);
|
||||
color: var(--text-primary);
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.main-layout {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 580px;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
/* Left Panel - Camera */
|
||||
.left-panel {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: var(--bg-main);
|
||||
}
|
||||
|
||||
.camera-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 8px 12px;
|
||||
background: var(--bg-white);
|
||||
border-bottom: 1px solid var(--border);
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.camera-title {
|
||||
font-size: 13px;
|
||||
color: var(--text-primary);
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.icon-btn {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
border: none;
|
||||
background: none;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.icon-btn:hover { background: var(--bg-hover); }
|
||||
.icon-btn img { width: 18px; height: 18px; opacity: 0.6; }
|
||||
|
||||
.camera-feed {
|
||||
flex: 1;
|
||||
background: #1a1a1a;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #555;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* Status bar */
|
||||
.status-bar {
|
||||
background: var(--accent);
|
||||
padding: 4px 12px;
|
||||
}
|
||||
|
||||
/* Print Progress */
|
||||
.print-progress {
|
||||
background: var(--bg-white);
|
||||
padding: 16px 20px;
|
||||
}
|
||||
|
||||
.progress-label { font-size: 12px; color: var(--text-muted); margin-bottom: 12px; }
|
||||
.progress-row { display: flex; gap: 14px; align-items: center; }
|
||||
.progress-thumb {
|
||||
width: 60px; height: 60px;
|
||||
background: var(--bg-light);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
flex-direction: column;
|
||||
font-size: 10px;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
.progress-info { flex: 1; }
|
||||
.progress-name { font-weight: 500; font-size: 14px; margin-bottom: 2px; }
|
||||
.progress-status { color: var(--accent); font-size: 13px; margin-bottom: 8px; }
|
||||
.progress-bar-bg { height: 4px; background: var(--border-light); border-radius: 2px; margin-bottom: 8px; }
|
||||
.progress-bar-fill { height: 100%; background: var(--accent); border-radius: 2px; width: 0%; }
|
||||
.progress-meta { font-size: 12px; color: var(--text-muted); margin-bottom: 4px; }
|
||||
.progress-btns { display: flex; gap: 6px; }
|
||||
.progress-btn {
|
||||
width: 32px; height: 32px;
|
||||
border: 1px solid var(--border);
|
||||
background: var(--bg-white);
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
.progress-btn:hover { background: var(--bg-hover); }
|
||||
|
||||
/* Right Panel - Control */
|
||||
.right-panel {
|
||||
background: var(--bg-white);
|
||||
border-left: 1px solid var(--border);
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.control-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px 16px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.control-title { font-size: 13px; margin-right: auto; color: var(--text-secondary); }
|
||||
.header-btn {
|
||||
padding: 7px 16px;
|
||||
font-size: 12px;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
background: var(--accent);
|
||||
color: white;
|
||||
}
|
||||
.header-btn:hover { background: #009938; }
|
||||
|
||||
.control-body {
|
||||
padding: 16px 20px;
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
/* Top Section: Temp + Movement side by side */
|
||||
.top-section {
|
||||
display: flex;
|
||||
gap: 30px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
/* Temperature Column */
|
||||
.temp-column {
|
||||
flex: 0 0 auto;
|
||||
min-width: 140px;
|
||||
}
|
||||
|
||||
.temp-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 5px 0;
|
||||
}
|
||||
|
||||
.temp-icon { width: 20px; height: 20px; display: flex; align-items: center; justify-content: center; }
|
||||
.temp-icon img { width: 18px; opacity: 0.5; }
|
||||
|
||||
.temp-badge {
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
color: var(--accent);
|
||||
background: #e8f5e9;
|
||||
padding: 2px 8px;
|
||||
border-radius: 4px;
|
||||
min-width: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.temp-value { font-size: 18px; font-weight: 500; }
|
||||
.temp-target { font-size: 15px; color: var(--text-muted); }
|
||||
|
||||
/* Air Condition */
|
||||
.air-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 12px 0;
|
||||
margin-top: 10px;
|
||||
border-top: 1px solid var(--border-light);
|
||||
}
|
||||
|
||||
.air-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
font-size: 13px;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.air-label img { width: 18px; opacity: 0.5; }
|
||||
|
||||
.air-values {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.air-value {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
font-size: 13px;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.air-value img { width: 16px; opacity: 0.5; }
|
||||
|
||||
.lamp-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
font-size: 13px;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.lamp-dot { width: 14px; height: 14px; border-radius: 50%; background: var(--accent); }
|
||||
|
||||
/* Movement Column */
|
||||
.movement-column {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.nozzle-toggle {
|
||||
display: flex;
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--border);
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.nozzle-toggle button {
|
||||
padding: 7px 20px;
|
||||
border: none;
|
||||
background: var(--bg-white);
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.nozzle-toggle button:first-child { border-right: 1px solid var(--border); }
|
||||
.nozzle-toggle button.active { background: var(--accent); color: white; }
|
||||
|
||||
.movement-row {
|
||||
display: flex;
|
||||
gap: 24px;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.jog-section { display: flex; flex-direction: column; align-items: center; }
|
||||
|
||||
.jog-pad {
|
||||
position: relative;
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.jog-ring {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(135deg, #f8f8f8 0%, #ebebeb 100%);
|
||||
border: 1px solid var(--border);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.jog-label {
|
||||
position: absolute;
|
||||
font-size: 11px;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.jog-label.top { top: 8px; left: 50%; transform: translateX(-50%); }
|
||||
.jog-label.bottom { bottom: 8px; left: 50%; transform: translateX(-50%); }
|
||||
.jog-label.left { left: 8px; top: 50%; transform: translateY(-50%); }
|
||||
.jog-label.right { right: 8px; top: 50%; transform: translateY(-50%); }
|
||||
|
||||
.jog-btn {
|
||||
position: absolute;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
background: var(--bg-white);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 10px;
|
||||
color: var(--text-muted);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.jog-btn:hover { background: var(--bg-hover); }
|
||||
.jog-btn.up { top: 20px; left: 50%; transform: translateX(-50%); }
|
||||
.jog-btn.down { bottom: 20px; left: 50%; transform: translateX(-50%); }
|
||||
.jog-btn.left { left: 20px; top: 50%; transform: translateY(-50%); }
|
||||
.jog-btn.right { right: 20px; top: 50%; transform: translateY(-50%); }
|
||||
|
||||
.jog-home {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
background: var(--accent);
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.jog-home:hover { background: #009938; }
|
||||
.jog-home img { width: 20px; filter: brightness(0) invert(1); }
|
||||
|
||||
/* Bed Controls */
|
||||
.bed-controls {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.bed-btn {
|
||||
padding: 8px 14px;
|
||||
background: var(--bg-white);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.bed-btn:hover { background: var(--bg-hover); }
|
||||
.bed-label { font-size: 12px; color: var(--text-muted); padding: 0 8px; }
|
||||
|
||||
/* Extruder Section */
|
||||
.extruder-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.extruder-btn {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
background: var(--bg-white);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
color: var(--text-muted);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.extruder-btn:hover { background: var(--bg-hover); }
|
||||
|
||||
.extruder-graphic {
|
||||
height: 80px;
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
.extruder-graphic img { height: 100%; }
|
||||
.extruder-label { font-size: 12px; color: var(--text-muted); }
|
||||
|
||||
/* ========== FILAMENT BOXES ========== */
|
||||
.filament-boxes {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
margin-bottom: 16px;
|
||||
padding-bottom: 16px;
|
||||
border-bottom: 1px solid var(--border-light);
|
||||
}
|
||||
|
||||
.filament-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
padding: 10px 12px;
|
||||
background: var(--bg-white);
|
||||
border: 2px solid var(--border);
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.filament-box:hover { border-color: #ccc; }
|
||||
.filament-box.active { border-color: var(--accent); }
|
||||
|
||||
.filament-dots { display: flex; gap: 4px; }
|
||||
|
||||
.f-dot {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.f-dot.empty {
|
||||
background: #e8e8e8 !important;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.f-dot-sep {
|
||||
width: 1px;
|
||||
height: 18px;
|
||||
background: #ccc;
|
||||
margin: 0 2px;
|
||||
}
|
||||
|
||||
.filament-count {
|
||||
font-size: 13px;
|
||||
color: var(--text-muted);
|
||||
margin-left: 6px;
|
||||
}
|
||||
|
||||
/* ========== AMS SECTION ========== */
|
||||
.ams-section {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.ams-unit {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
background: var(--bg-panel);
|
||||
border-radius: 12px;
|
||||
padding: 14px;
|
||||
}
|
||||
|
||||
/* AMS Header */
|
||||
.ams-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.ams-humidity {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
font-size: 14px;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.ams-humidity img { width: 16px; opacity: 0.5; }
|
||||
.ams-humidity .sun { font-size: 16px; color: #f5a623; }
|
||||
|
||||
/* Slot Labels */
|
||||
.slot-labels {
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.slot-label {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
font-size: 11px;
|
||||
color: var(--text-muted);
|
||||
padding: 4px 0;
|
||||
background: var(--bg-white);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
/* AMS Slots */
|
||||
.ams-slots {
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.ams-slot {
|
||||
flex: 1;
|
||||
height: 80px;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
border: 2px solid var(--border);
|
||||
background: var(--bg-white);
|
||||
}
|
||||
|
||||
.ams-slot:hover { border-color: #bbb; }
|
||||
.ams-slot.active { border-color: #d4a84b; }
|
||||
|
||||
.ams-slot-fill {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
.ams-slot-type {
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: white;
|
||||
text-shadow: 0 1px 2px rgba(0,0,0,0.3);
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.ams-slot-type.dark { color: #333; text-shadow: none; }
|
||||
|
||||
.ams-slot-eye { width: 18px; height: 18px; }
|
||||
.ams-slot-eye img { width: 16px; height: 16px; opacity: 0.8; }
|
||||
.ams-slot-eye.invert img { filter: invert(1); }
|
||||
|
||||
/* Connector Lines */
|
||||
.ams-connectors {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
.connector-group {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.connector-line {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.connector-line .vline {
|
||||
width: 2px;
|
||||
height: 14px;
|
||||
background: #c0c0c0;
|
||||
}
|
||||
|
||||
.connector-hbar {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 12%;
|
||||
right: 12%;
|
||||
height: 2px;
|
||||
background: #c0c0c0;
|
||||
}
|
||||
|
||||
/* AMS Actions */
|
||||
.ams-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
margin-top: 16px;
|
||||
padding-top: 16px;
|
||||
border-top: 1px solid var(--border-light);
|
||||
}
|
||||
|
||||
.auto-refill-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 10px 18px;
|
||||
background: var(--bg-white);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
font-size: 13px;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.auto-refill-btn:hover { background: var(--bg-hover); }
|
||||
|
||||
.ams-settings-btn {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
background: var(--bg-white);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.ams-settings-btn:hover { background: var(--bg-hover); }
|
||||
.ams-settings-btn img { width: 22px; opacity: 0.5; }
|
||||
|
||||
/* Hub */
|
||||
.hub-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.hub-line { width: 40px; height: 2px; background: #c0c0c0; }
|
||||
|
||||
.hub-graphic {
|
||||
display: flex;
|
||||
padding: 6px 10px;
|
||||
background: var(--bg-white);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.hub-port {
|
||||
width: 12px;
|
||||
height: 16px;
|
||||
background: var(--accent);
|
||||
border-radius: 2px;
|
||||
margin: 0 3px;
|
||||
}
|
||||
|
||||
.ams-spacer { flex: 1; }
|
||||
|
||||
.ams-action-btn {
|
||||
padding: 10px 28px;
|
||||
border-radius: 8px;
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
background: #e8e8e8;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.ams-action-btn:hover { background: #ddd; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="main-layout">
|
||||
<!-- Left Panel - Camera -->
|
||||
<div class="left-panel">
|
||||
<div class="camera-header">
|
||||
<span class="camera-title">Camera</span>
|
||||
<button class="icon-btn"><img src="icons/video-camera.svg"></button>
|
||||
<button class="icon-btn"><img src="icons/webcam.svg"></button>
|
||||
<button class="icon-btn"><img src="icons/settings.svg"></button>
|
||||
<button class="icon-btn"><img src="icons/reload.svg"></button>
|
||||
</div>
|
||||
<div class="camera-feed">Camera Feed</div>
|
||||
<div class="status-bar"></div>
|
||||
<div class="print-progress">
|
||||
<div class="progress-label">Printing Progress</div>
|
||||
<div class="progress-row">
|
||||
<div class="progress-thumb">
|
||||
Bambu<br>Lab
|
||||
</div>
|
||||
<div class="progress-info">
|
||||
<div class="progress-name">N/A</div>
|
||||
<div class="progress-status">N/A</div>
|
||||
<div class="progress-bar-bg"><div class="progress-bar-fill"></div></div>
|
||||
<div class="progress-meta">Layer: N/A N/A</div>
|
||||
<div class="progress-meta">Estimated finish time: N/A</div>
|
||||
</div>
|
||||
<div class="progress-btns">
|
||||
<button class="progress-btn">⌂</button>
|
||||
<button class="progress-btn">⏸</button>
|
||||
<button class="progress-btn">■</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Right Panel - Control -->
|
||||
<div class="right-panel">
|
||||
<div class="control-header">
|
||||
<span class="control-title">Control</span>
|
||||
<button class="header-btn">Printer Parts</button>
|
||||
<button class="header-btn">Print Options</button>
|
||||
<button class="header-btn">Calibration</button>
|
||||
</div>
|
||||
|
||||
<div class="control-body">
|
||||
<!-- Top Section: Temp + Movement side by side -->
|
||||
<div class="top-section">
|
||||
<!-- Temperature Column -->
|
||||
<div class="temp-column">
|
||||
<div class="temp-row">
|
||||
<div class="temp-icon"><img src="icons/hotend.svg"></div>
|
||||
<span class="temp-badge">L</span>
|
||||
<span class="temp-value">24</span>
|
||||
<span class="temp-target">/0 °C</span>
|
||||
</div>
|
||||
<div class="temp-row">
|
||||
<div class="temp-icon"><img src="icons/hotend.svg"></div>
|
||||
<span class="temp-badge">R</span>
|
||||
<span class="temp-value">23</span>
|
||||
<span class="temp-target">/0 °C</span>
|
||||
</div>
|
||||
<div class="temp-row">
|
||||
<div class="temp-icon"><img src="icons/heatbed.svg"></div>
|
||||
<span class="temp-value">23</span>
|
||||
<span class="temp-target">/0 °C</span>
|
||||
</div>
|
||||
<div class="temp-row">
|
||||
<div class="temp-icon"><img src="icons/chamber.svg"></div>
|
||||
<span class="temp-value">23</span>
|
||||
<span class="temp-target">/0 °C</span>
|
||||
</div>
|
||||
|
||||
<!-- Air Condition -->
|
||||
<div class="air-section">
|
||||
<div class="air-label"><img src="icons/ventilation.svg"> Air Condition</div>
|
||||
</div>
|
||||
<div class="air-values">
|
||||
<div class="air-value"><img src="icons/ventilation.svg"> 100%</div>
|
||||
<div class="lamp-section">Lamp <div class="lamp-dot"></div></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Movement Column -->
|
||||
<div class="movement-column">
|
||||
<div class="nozzle-toggle">
|
||||
<button class="active">Left</button>
|
||||
<button>Right</button>
|
||||
</div>
|
||||
|
||||
<div class="movement-row">
|
||||
<div class="jog-section">
|
||||
<div class="jog-pad">
|
||||
<div class="jog-ring">
|
||||
<span class="jog-label top">Y</span>
|
||||
<span class="jog-label bottom">-Y</span>
|
||||
<span class="jog-label left">-X</span>
|
||||
<span class="jog-label right">X</span>
|
||||
<button class="jog-btn up">▲</button>
|
||||
<button class="jog-btn down">▼</button>
|
||||
<button class="jog-btn left">◀</button>
|
||||
<button class="jog-btn right">▶</button>
|
||||
<button class="jog-home"><img src="icons/home.svg"></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bed-controls">
|
||||
<button class="bed-btn">↑10</button>
|
||||
<button class="bed-btn">↑1</button>
|
||||
<span class="bed-label">Bed</span>
|
||||
<button class="bed-btn">↓1</button>
|
||||
<button class="bed-btn">↓10</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="extruder-section">
|
||||
<button class="extruder-btn">▲</button>
|
||||
<div class="extruder-graphic"><img src="icons/dual-extruder.png"></div>
|
||||
<button class="extruder-btn">▼</button>
|
||||
<span class="extruder-label">Extruder</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Filament Assignment Boxes -->
|
||||
<div class="filament-boxes">
|
||||
<div class="filament-box active">
|
||||
<div class="filament-dots">
|
||||
<div class="f-dot" style="background: #FFD700;"></div>
|
||||
<div class="f-dot" style="background: #333;"></div>
|
||||
<div class="f-dot" style="background: #333;"></div>
|
||||
<div class="f-dot" style="background: #333;"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="filament-box">
|
||||
<div class="filament-dots">
|
||||
<div class="f-dot" style="background: #333;"></div>
|
||||
<div class="f-dot" style="background: #333;"></div>
|
||||
<div class="f-dot-sep"></div>
|
||||
<div class="f-dot" style="background: #FF3366;"></div>
|
||||
</div>
|
||||
<span class="filament-count">0</span>
|
||||
</div>
|
||||
<div class="filament-box">
|
||||
<div class="filament-dots">
|
||||
<div class="f-dot empty"></div>
|
||||
<div class="f-dot empty"></div>
|
||||
<div class="f-dot empty"></div>
|
||||
</div>
|
||||
<span class="filament-count">0</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- AMS Section - Two units side by side -->
|
||||
<div class="ams-section">
|
||||
<!-- AMS Unit 1 -->
|
||||
<div class="ams-unit">
|
||||
<div class="ams-header">
|
||||
<div class="ams-humidity"><img src="icons/water.svg"> 17 %</div>
|
||||
<div class="ams-humidity"><span class="sun">☀</span></div>
|
||||
</div>
|
||||
<div class="slot-labels">
|
||||
<div class="slot-label">A1↓</div>
|
||||
<div class="slot-label">A2↓</div>
|
||||
<div class="slot-label">A3↓</div>
|
||||
<div class="slot-label">A4↓</div>
|
||||
</div>
|
||||
<div class="ams-slots">
|
||||
<div class="ams-slot active">
|
||||
<div class="ams-slot-fill" style="background: #FFD700;">
|
||||
<span class="ams-slot-type dark">PLA</span>
|
||||
<div class="ams-slot-eye"><img src="icons/eye.svg"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ams-slot">
|
||||
<div class="ams-slot-fill" style="background: #333;">
|
||||
<span class="ams-slot-type">PETG</span>
|
||||
<div class="ams-slot-eye invert"><img src="icons/eye.svg"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ams-slot">
|
||||
<div class="ams-slot-fill" style="background: #8B4513;">
|
||||
<span class="ams-slot-type">PETG</span>
|
||||
<div class="ams-slot-eye invert"><img src="icons/eye.svg"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ams-slot">
|
||||
<div class="ams-slot-fill" style="background: #666;">
|
||||
<span class="ams-slot-type">PLA</span>
|
||||
<div class="ams-slot-eye invert"><img src="icons/eye.svg"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ams-connectors">
|
||||
<div class="connector-group">
|
||||
<div class="connector-line"><div class="vline"></div></div>
|
||||
<div class="connector-line"><div class="vline"></div></div>
|
||||
<div class="connector-line"><div class="vline"></div></div>
|
||||
<div class="connector-line"><div class="vline"></div></div>
|
||||
<div class="connector-hbar"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- AMS Unit 2 -->
|
||||
<div class="ams-unit">
|
||||
<div class="ams-header">
|
||||
<div class="ams-humidity"><img src="icons/water.svg"> 14 %</div>
|
||||
<div class="ams-humidity"><span class="sun">☀</span></div>
|
||||
</div>
|
||||
<div class="slot-labels">
|
||||
<div class="slot-label">B1↓</div>
|
||||
<div class="slot-label">B2↓</div>
|
||||
<div class="slot-label">B3↓</div>
|
||||
<div class="slot-label">B4↓</div>
|
||||
</div>
|
||||
<div class="ams-slots">
|
||||
<div class="ams-slot">
|
||||
<div class="ams-slot-fill" style="background: #888;">
|
||||
<span class="ams-slot-type">PLA</span>
|
||||
<div class="ams-slot-eye invert"><img src="icons/eye.svg"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ams-slot">
|
||||
<div class="ams-slot-fill" style="background: #666;">
|
||||
<span class="ams-slot-type">PETG</span>
|
||||
<div class="ams-slot-eye invert"><img src="icons/eye.svg"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ams-slot">
|
||||
<div class="ams-slot-fill" style="background: #888;">
|
||||
<span class="ams-slot-type">PLA</span>
|
||||
<div class="ams-slot-eye invert"><img src="icons/eye.svg"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ams-slot">
|
||||
<div class="ams-slot-fill" style="background: #aaa;">
|
||||
<span class="ams-slot-type dark">Sup.PLA</span>
|
||||
<div class="ams-slot-eye"><img src="icons/eye.svg"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ams-connectors">
|
||||
<div class="connector-group">
|
||||
<div class="connector-line"><div class="vline"></div></div>
|
||||
<div class="connector-line"><div class="vline"></div></div>
|
||||
<div class="connector-line"><div class="vline"></div></div>
|
||||
<div class="connector-line"><div class="vline"></div></div>
|
||||
<div class="connector-hbar"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- AMS Actions -->
|
||||
<div class="ams-actions">
|
||||
<button class="auto-refill-btn">Auto-refill</button>
|
||||
<button class="ams-settings-btn"><img src="icons/ams-settings.svg"></button>
|
||||
<div class="hub-section">
|
||||
<div class="hub-line"></div>
|
||||
<div class="hub-graphic">
|
||||
<div class="hub-port"></div>
|
||||
<div class="hub-port"></div>
|
||||
</div>
|
||||
<div class="hub-line"></div>
|
||||
</div>
|
||||
<div class="ams-spacer"></div>
|
||||
<button class="ams-action-btn">Unload</button>
|
||||
<button class="ams-action-btn">Load</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,952 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>BambuTrack Control - Exact Match</title>
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
|
||||
:root {
|
||||
--bg-main: #f5f5f5;
|
||||
--bg-white: #ffffff;
|
||||
--bg-light: #fafafa;
|
||||
--bg-hover: #f0f0f0;
|
||||
--text-primary: #333333;
|
||||
--text-secondary: #666666;
|
||||
--text-muted: #999999;
|
||||
--border: #e0e0e0;
|
||||
--border-light: #eeeeee;
|
||||
--accent: #00ae42;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
background: var(--bg-main);
|
||||
color: var(--text-primary);
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.main-layout {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 340px;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
/* Left Panel */
|
||||
.left-panel {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: var(--bg-main);
|
||||
}
|
||||
|
||||
.camera-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 8px 12px;
|
||||
background: var(--bg-white);
|
||||
border-bottom: 1px solid var(--border);
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.camera-title {
|
||||
font-size: 12px;
|
||||
color: var(--text-secondary);
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.icon-btn {
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
border: none;
|
||||
background: none;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.icon-btn:hover { background: var(--bg-hover); }
|
||||
.icon-btn img { width: 16px; height: 16px; opacity: 0.5; }
|
||||
|
||||
.camera-feed {
|
||||
flex: 1;
|
||||
background: #1a1a1a;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #555;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* Print Progress */
|
||||
.print-progress {
|
||||
background: var(--bg-white);
|
||||
border-top: 1px solid var(--border);
|
||||
padding: 12px 16px;
|
||||
}
|
||||
|
||||
.progress-label {
|
||||
font-size: 11px;
|
||||
color: var(--text-muted);
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.progress-row {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.progress-thumb {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
background: var(--bg-light);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 6px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.progress-thumb img { width: 30px; opacity: 0.4; }
|
||||
|
||||
.progress-info { flex: 1; }
|
||||
.progress-name { font-weight: 500; font-size: 13px; }
|
||||
.progress-status { color: var(--accent); font-size: 12px; margin: 2px 0 6px; }
|
||||
|
||||
.progress-bar-bg {
|
||||
height: 3px;
|
||||
background: var(--border-light);
|
||||
border-radius: 2px;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.progress-bar-fill {
|
||||
height: 100%;
|
||||
background: var(--accent);
|
||||
border-radius: 2px;
|
||||
width: 0%;
|
||||
}
|
||||
|
||||
.progress-details {
|
||||
font-size: 11px;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.progress-btns {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.progress-btn {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
border: 1px solid var(--border);
|
||||
background: var(--bg-white);
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.progress-btn:hover { background: var(--bg-hover); }
|
||||
|
||||
/* Right Panel */
|
||||
.right-panel {
|
||||
background: var(--bg-white);
|
||||
border-left: 1px solid var(--border);
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.control-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 8px 12px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.control-title {
|
||||
font-size: 13px;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.header-btn {
|
||||
padding: 5px 12px;
|
||||
font-size: 11px;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
background: var(--accent);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.control-body {
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
/* Temperature */
|
||||
.temp-section {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.temp-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 5px 0;
|
||||
}
|
||||
|
||||
.temp-icon { width: 18px; height: 18px; }
|
||||
.temp-icon img { width: 100%; opacity: 0.6; }
|
||||
|
||||
.temp-badge {
|
||||
font-size: 9px;
|
||||
font-weight: 700;
|
||||
color: var(--accent);
|
||||
background: #e8f5e9;
|
||||
padding: 1px 5px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.temp-value { font-size: 16px; font-weight: 500; }
|
||||
.temp-target { font-size: 14px; color: var(--text-muted); }
|
||||
|
||||
/* Air Condition */
|
||||
.air-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 10px 0;
|
||||
border-top: 1px solid var(--border-light);
|
||||
border-bottom: 1px solid var(--border-light);
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.air-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
font-size: 12px;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.air-label img { width: 14px; opacity: 0.5; }
|
||||
|
||||
.air-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 5px 10px;
|
||||
background: var(--bg-light);
|
||||
border-radius: 6px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.air-item img { width: 14px; opacity: 0.5; }
|
||||
.lamp-dot { width: 10px; height: 10px; border-radius: 50%; background: var(--accent); }
|
||||
|
||||
/* Movement */
|
||||
.movement-section {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.jog-pad {
|
||||
position: relative;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
.jog-ring {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
background: var(--bg-light);
|
||||
border: 1px solid var(--border);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.jog-label {
|
||||
position: absolute;
|
||||
font-size: 9px;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.jog-label.top { top: 6px; left: 50%; transform: translateX(-50%); }
|
||||
.jog-label.bottom { bottom: 6px; left: 50%; transform: translateX(-50%); }
|
||||
.jog-label.left { left: 6px; top: 50%; transform: translateY(-50%); }
|
||||
.jog-label.right { right: 6px; top: 50%; transform: translateY(-50%); }
|
||||
|
||||
.jog-arrow {
|
||||
position: absolute;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
font-size: 10px;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.jog-arrow:hover { color: var(--accent); }
|
||||
.jog-arrow.up { top: 18px; left: 50%; transform: translateX(-50%); }
|
||||
.jog-arrow.down { bottom: 18px; left: 50%; transform: translateX(-50%); }
|
||||
.jog-arrow.left { left: 18px; top: 50%; transform: translateY(-50%); }
|
||||
.jog-arrow.right { right: 18px; top: 50%; transform: translateY(-50%); }
|
||||
|
||||
.jog-home {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 50%;
|
||||
background: var(--accent);
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.jog-home img { width: 16px; filter: brightness(0) invert(1); }
|
||||
|
||||
.step-col {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.step-btn {
|
||||
padding: 4px 8px;
|
||||
background: var(--bg-light);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 9px;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.step-btn.active { background: var(--bg-hover); color: var(--text-primary); }
|
||||
.step-label { text-align: center; color: var(--text-muted); font-size: 9px; padding: 2px 0; }
|
||||
|
||||
.extruder-col {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.nozzle-toggle {
|
||||
display: flex;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.nozzle-toggle button {
|
||||
padding: 3px 12px;
|
||||
border: none;
|
||||
background: var(--bg-white);
|
||||
font-size: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.nozzle-toggle button.active { background: var(--accent); color: white; }
|
||||
|
||||
.extruder-img { height: 70px; }
|
||||
.extruder-img img { height: 100%; }
|
||||
.extruder-label { font-size: 9px; color: var(--text-muted); }
|
||||
|
||||
.ext-btns { display: flex; flex-direction: column; gap: 2px; }
|
||||
.ext-btn {
|
||||
width: 22px;
|
||||
height: 18px;
|
||||
background: var(--bg-light);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
font-size: 8px;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
/* AMS Section */
|
||||
.ams-section {
|
||||
border-top: 1px solid var(--border-light);
|
||||
padding-top: 12px;
|
||||
}
|
||||
|
||||
/* Nozzle Color Boxes */
|
||||
.nozzle-boxes {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.nozzle-box {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
padding: 8px 12px;
|
||||
background: var(--bg-white);
|
||||
border: 2px solid var(--border);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.nozzle-box.active { border-color: var(--accent); }
|
||||
|
||||
.nozzle-dots {
|
||||
display: flex;
|
||||
gap: 3px;
|
||||
}
|
||||
|
||||
.n-dot {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.n-dot.empty {
|
||||
background: var(--bg-light) !important;
|
||||
border: 1px dashed var(--border);
|
||||
}
|
||||
|
||||
.nozzle-box-spacer { flex: 1; }
|
||||
|
||||
.nozzle-box-label {
|
||||
font-size: 11px;
|
||||
color: var(--text-muted);
|
||||
padding: 4px 8px;
|
||||
background: var(--bg-light);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
/* AMS Middle Row - Tabs */
|
||||
.ams-tabs-row {
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.ams-tab {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 3px;
|
||||
padding: 4px 8px;
|
||||
background: var(--bg-light);
|
||||
border: 2px solid transparent;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.ams-tab:hover { background: var(--bg-hover); }
|
||||
.ams-tab.active { border-color: var(--accent); }
|
||||
|
||||
.ams-tab-dot {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 3px;
|
||||
border: 1px solid rgba(0,0,0,0.08);
|
||||
}
|
||||
|
||||
/* AMS Content Area */
|
||||
.ams-content {
|
||||
background: var(--bg-light);
|
||||
border-radius: 10px;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.ams-info-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-bottom: 8px;
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
||||
.ams-humidity {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
font-size: 12px;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.ams-humidity img { width: 14px; opacity: 0.5; }
|
||||
|
||||
/* Slot Labels */
|
||||
.slot-labels {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
margin-bottom: 6px;
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
||||
.slot-label {
|
||||
width: 60px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 2px;
|
||||
font-size: 10px;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.slot-label img { width: 12px; opacity: 0.4; }
|
||||
|
||||
/* AMS Main Grid */
|
||||
.ams-grid {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
/* AMS Slots */
|
||||
.ams-slots {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.ams-slot {
|
||||
width: 60px;
|
||||
height: 90px;
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
border: 2px solid var(--border);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: var(--bg-white);
|
||||
}
|
||||
|
||||
.ams-slot:hover { border-color: var(--text-muted); }
|
||||
.ams-slot.active { border-color: var(--accent); }
|
||||
|
||||
.ams-slot-color {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: center;
|
||||
padding-bottom: 6px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.ams-slot-color img {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.ams-slot-bottom {
|
||||
padding: 6px 4px;
|
||||
text-align: center;
|
||||
background: var(--bg-light);
|
||||
border-top: 1px solid var(--border-light);
|
||||
}
|
||||
|
||||
.ams-slot-type {
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
/* Connector Lines */
|
||||
.ams-connectors {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 8px 0;
|
||||
margin-left: 30px;
|
||||
}
|
||||
|
||||
.connector-group {
|
||||
display: flex;
|
||||
gap: 32px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.connector-line {
|
||||
width: 2px;
|
||||
height: 20px;
|
||||
background: #ccc;
|
||||
}
|
||||
|
||||
.connector-bar {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 2px;
|
||||
background: #ccc;
|
||||
}
|
||||
|
||||
/* External Section */
|
||||
.ext-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.ext-title {
|
||||
font-size: 12px;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.ext-slot-box {
|
||||
width: 60px;
|
||||
height: 70px;
|
||||
background: var(--bg-white);
|
||||
border: 2px solid var(--border);
|
||||
border-radius: 12px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
font-size: 20px;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.ext-slot-box:hover { border-color: var(--text-muted); }
|
||||
.ext-slot-symbol { font-size: 14px; }
|
||||
|
||||
.spool-holder-img {
|
||||
height: 70px;
|
||||
}
|
||||
|
||||
.spool-holder-img img { height: 100%; }
|
||||
|
||||
/* Hub Row */
|
||||
.hub-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 10px 0;
|
||||
margin-left: 30px;
|
||||
}
|
||||
|
||||
.hub-line { width: 40px; height: 2px; background: #ccc; }
|
||||
|
||||
.hub-graphic {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
padding: 4px 8px;
|
||||
background: var(--bg-white);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.hub-dot {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
background: var(--accent);
|
||||
}
|
||||
|
||||
/* AMS Actions */
|
||||
.ams-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.auto-refill-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 8px 14px;
|
||||
background: var(--bg-white);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.auto-refill-btn:hover { background: var(--bg-hover); }
|
||||
.auto-refill-btn img { width: 16px; opacity: 0.5; }
|
||||
|
||||
.ams-spacer { flex: 1; }
|
||||
|
||||
.ams-btn {
|
||||
padding: 10px 20px;
|
||||
border-radius: 8px;
|
||||
font-size: 12px;
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.ams-btn.unload {
|
||||
background: #e0e0e0;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.ams-btn.unload:hover { background: #d5d5d5; }
|
||||
|
||||
.ams-btn.load {
|
||||
background: #e0e0e0;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.ams-btn.load:hover { background: #d5d5d5; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="main-layout">
|
||||
<!-- Left Panel -->
|
||||
<div class="left-panel">
|
||||
<div class="camera-header">
|
||||
<span class="camera-title">Camera</span>
|
||||
<button class="icon-btn"><img src="icons/video-camera.svg"></button>
|
||||
<button class="icon-btn"><img src="icons/webcam.svg"></button>
|
||||
<button class="icon-btn"><img src="icons/settings.svg"></button>
|
||||
<button class="icon-btn"><img src="icons/reload.svg"></button>
|
||||
</div>
|
||||
<div class="camera-feed">Camera Feed</div>
|
||||
<div class="print-progress">
|
||||
<div class="progress-label">Printing Progress</div>
|
||||
<div class="progress-row">
|
||||
<div class="progress-thumb"><img src="icons/micro-sd.svg"></div>
|
||||
<div class="progress-info">
|
||||
<div class="progress-name">N/A</div>
|
||||
<div class="progress-status">N/A</div>
|
||||
<div class="progress-bar-bg"><div class="progress-bar-fill"></div></div>
|
||||
<div class="progress-details">Layer: N/A N/A</div>
|
||||
<div class="progress-details">Estimated finish time: N/A</div>
|
||||
</div>
|
||||
<div class="progress-btns">
|
||||
<button class="progress-btn">⌂</button>
|
||||
<button class="progress-btn">⏸</button>
|
||||
<button class="progress-btn">⏹</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Right Panel -->
|
||||
<div class="right-panel">
|
||||
<div class="control-header">
|
||||
<span class="control-title">Control</span>
|
||||
<button class="header-btn">Printer Parts</button>
|
||||
<button class="header-btn">Print Options</button>
|
||||
<button class="header-btn">Calibration</button>
|
||||
</div>
|
||||
|
||||
<div class="control-body">
|
||||
<!-- Temperature -->
|
||||
<div class="temp-section">
|
||||
<div class="temp-row">
|
||||
<div class="temp-icon"><img src="icons/hotend.svg"></div>
|
||||
<span class="temp-badge">L</span>
|
||||
<span class="temp-value">22</span>
|
||||
<span class="temp-target">/0 °C</span>
|
||||
</div>
|
||||
<div class="temp-row">
|
||||
<div class="temp-icon"><img src="icons/hotend.svg"></div>
|
||||
<span class="temp-badge">R</span>
|
||||
<span class="temp-value">21</span>
|
||||
<span class="temp-target">/0 °C</span>
|
||||
</div>
|
||||
<div class="temp-row">
|
||||
<div class="temp-icon"><img src="icons/heatbed.svg"></div>
|
||||
<span class="temp-value">21</span>
|
||||
<span class="temp-target">/0 °C</span>
|
||||
</div>
|
||||
<div class="temp-row">
|
||||
<div class="temp-icon"><img src="icons/chamber.svg"></div>
|
||||
<span class="temp-value">21</span>
|
||||
<span class="temp-target">/0 °C</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Air Condition -->
|
||||
<div class="air-row">
|
||||
<div class="air-label"><img src="icons/ventilation.svg"> Air Condition</div>
|
||||
<div class="air-item"><img src="icons/ventilation.svg"> 100%</div>
|
||||
<div class="air-item">Lamp <div class="lamp-dot"></div></div>
|
||||
</div>
|
||||
|
||||
<!-- Movement -->
|
||||
<div class="movement-section">
|
||||
<div class="jog-pad">
|
||||
<div class="jog-ring">
|
||||
<span class="jog-label top">Y</span>
|
||||
<span class="jog-label bottom">-Y</span>
|
||||
<span class="jog-label left">-X</span>
|
||||
<span class="jog-label right">X</span>
|
||||
<button class="jog-arrow up">▲</button>
|
||||
<button class="jog-arrow down">▼</button>
|
||||
<button class="jog-arrow left">◀</button>
|
||||
<button class="jog-arrow right">▶</button>
|
||||
<button class="jog-home"><img src="icons/home.svg"></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="step-col">
|
||||
<button class="step-btn">↑ 10</button>
|
||||
<button class="step-btn active">↑ 1</button>
|
||||
<span class="step-label">Bed</span>
|
||||
<button class="step-btn">↓ 1</button>
|
||||
<button class="step-btn">↓ 10</button>
|
||||
</div>
|
||||
|
||||
<div class="extruder-col">
|
||||
<div class="nozzle-toggle">
|
||||
<button class="active">Left</button>
|
||||
<button>Right</button>
|
||||
</div>
|
||||
<div class="extruder-img"><img src="icons/dual-extruder.png"></div>
|
||||
<span class="extruder-label">Extruder</span>
|
||||
<div class="ext-btns">
|
||||
<button class="ext-btn">▲</button>
|
||||
<button class="ext-btn">▼</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- AMS Section -->
|
||||
<div class="ams-section">
|
||||
<!-- Nozzle Color Boxes -->
|
||||
<div class="nozzle-boxes">
|
||||
<div class="nozzle-box active">
|
||||
<div class="nozzle-dots">
|
||||
<div class="n-dot" style="background: #FFD700;"></div>
|
||||
<div class="n-dot" style="background: #8B4513;"></div>
|
||||
<div class="n-dot" style="background: #1a1a1a;"></div>
|
||||
<div class="n-dot" style="background: #222;"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="nozzle-box">
|
||||
<div class="nozzle-dots">
|
||||
<div class="n-dot" style="background: #0066FF;"></div>
|
||||
<div class="n-dot" style="background: #FF0000;"></div>
|
||||
</div>
|
||||
<div class="nozzle-box-spacer"></div>
|
||||
<div class="nozzle-box-label">0</div>
|
||||
</div>
|
||||
<div class="nozzle-box">
|
||||
<div class="nozzle-dots">
|
||||
<div class="n-dot empty"></div>
|
||||
<div class="n-dot empty"></div>
|
||||
<div class="n-dot empty"></div>
|
||||
</div>
|
||||
<div class="nozzle-box-spacer"></div>
|
||||
<div class="nozzle-box-label" style="background: var(--accent); color: white;">0</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- AMS Content -->
|
||||
<div class="ams-content">
|
||||
<!-- Info Row -->
|
||||
<div class="ams-info-row">
|
||||
<div class="ams-humidity"><img src="icons/water.svg"> 18 %</div>
|
||||
<div class="ams-humidity">☀</div>
|
||||
</div>
|
||||
|
||||
<!-- Slot Labels -->
|
||||
<div class="slot-labels">
|
||||
<div class="slot-label">A1↓</div>
|
||||
<div class="slot-label">A2↓</div>
|
||||
<div class="slot-label">A3↓</div>
|
||||
<div class="slot-label">A4↓</div>
|
||||
<div style="flex: 1;"></div>
|
||||
<div class="slot-label">Ext</div>
|
||||
</div>
|
||||
|
||||
<!-- AMS Grid -->
|
||||
<div class="ams-grid">
|
||||
<!-- Slots -->
|
||||
<div class="ams-slots">
|
||||
<div class="ams-slot active">
|
||||
<div class="ams-slot-color" style="background: #FFD700;">
|
||||
<img src="icons/eye.svg">
|
||||
</div>
|
||||
<div class="ams-slot-bottom">
|
||||
<div class="ams-slot-type">PLA</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ams-slot">
|
||||
<div class="ams-slot-color" style="background: #1a1a1a;">
|
||||
<img src="icons/eye.svg" style="filter: invert(1);">
|
||||
</div>
|
||||
<div class="ams-slot-bottom">
|
||||
<div class="ams-slot-type">PETG</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ams-slot">
|
||||
<div class="ams-slot-color" style="background: #8B4513;">
|
||||
<img src="icons/eye.svg" style="filter: invert(1);">
|
||||
</div>
|
||||
<div class="ams-slot-bottom">
|
||||
<div class="ams-slot-type">PETG</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ams-slot">
|
||||
<div class="ams-slot-color" style="background: #222;">
|
||||
<img src="icons/eye.svg" style="filter: invert(1);">
|
||||
</div>
|
||||
<div class="ams-slot-bottom">
|
||||
<div class="ams-slot-type">PLA</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- External -->
|
||||
<div class="ext-section">
|
||||
<div class="ext-slot-box">
|
||||
?
|
||||
<span class="ext-slot-symbol">∠</span>
|
||||
</div>
|
||||
<div class="spool-holder-img">
|
||||
<img src="icons/single-extruder1.png">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Connectors -->
|
||||
<div class="ams-connectors">
|
||||
<div class="connector-group">
|
||||
<div class="connector-line"></div>
|
||||
<div class="connector-line"></div>
|
||||
<div class="connector-line"></div>
|
||||
<div class="connector-line"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Hub -->
|
||||
<div class="hub-row">
|
||||
<div class="hub-line"></div>
|
||||
<div class="hub-graphic">
|
||||
<div class="hub-dot"></div>
|
||||
<div class="hub-dot"></div>
|
||||
</div>
|
||||
<div class="hub-line"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Actions -->
|
||||
<div class="ams-actions">
|
||||
<button class="auto-refill-btn">
|
||||
Auto-refill
|
||||
<img src="icons/ams-settings.svg">
|
||||
</button>
|
||||
<div class="ams-spacer"></div>
|
||||
<button class="ams-btn unload">Unload</button>
|
||||
<button class="ams-btn load">Load</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,690 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>BambuTrack Control - v6 Multi-AMS</title>
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
|
||||
:root {
|
||||
--bg-main: #f5f5f5;
|
||||
--bg-white: #ffffff;
|
||||
--bg-light: #fafafa;
|
||||
--bg-panel: #f0f0f0;
|
||||
--bg-hover: #e8e8e8;
|
||||
--text-primary: #333333;
|
||||
--text-secondary: #666666;
|
||||
--text-muted: #999999;
|
||||
--border: #e0e0e0;
|
||||
--border-light: #eeeeee;
|
||||
--accent: #00ae42;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
background: var(--bg-main);
|
||||
color: var(--text-primary);
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.main-layout {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 400px;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
/* Left Panel */
|
||||
.left-panel {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: var(--bg-main);
|
||||
}
|
||||
|
||||
.camera-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 8px 12px;
|
||||
background: var(--bg-white);
|
||||
border-bottom: 1px solid var(--border);
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.camera-title {
|
||||
font-size: 13px;
|
||||
color: var(--text-primary);
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.icon-btn {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
border: none;
|
||||
background: none;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.icon-btn:hover { background: var(--bg-hover); }
|
||||
.icon-btn img { width: 18px; height: 18px; opacity: 0.6; }
|
||||
|
||||
.camera-feed {
|
||||
flex: 1;
|
||||
background: #1a1a1a;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
/* Print Progress */
|
||||
.print-progress {
|
||||
background: var(--bg-white);
|
||||
border-top: 1px solid var(--border);
|
||||
padding: 16px 20px;
|
||||
}
|
||||
|
||||
.progress-label { font-size: 12px; color: var(--text-muted); margin-bottom: 10px; }
|
||||
.progress-row { display: flex; gap: 14px; align-items: center; }
|
||||
.progress-thumb {
|
||||
width: 54px; height: 54px;
|
||||
background: var(--bg-light);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 6px;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
}
|
||||
.progress-thumb img { width: 32px; opacity: 0.4; }
|
||||
.progress-info { flex: 1; }
|
||||
.progress-name { font-weight: 500; font-size: 13px; margin-bottom: 2px; }
|
||||
.progress-status { color: var(--accent); font-size: 12px; margin-bottom: 8px; }
|
||||
.progress-bar-bg { height: 4px; background: var(--border-light); border-radius: 2px; margin-bottom: 8px; }
|
||||
.progress-bar-fill { height: 100%; background: var(--accent); border-radius: 2px; width: 0%; }
|
||||
.progress-meta { display: flex; gap: 20px; font-size: 11px; color: var(--text-muted); }
|
||||
.progress-btns { display: flex; gap: 6px; }
|
||||
.progress-btn {
|
||||
width: 32px; height: 32px;
|
||||
border: 1px solid var(--border);
|
||||
background: var(--bg-white);
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
.progress-btn:hover { background: var(--bg-hover); }
|
||||
|
||||
/* Right Panel */
|
||||
.right-panel {
|
||||
background: var(--bg-white);
|
||||
border-left: 1px solid var(--border);
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.control-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px 14px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.control-title { font-size: 13px; margin-right: auto; }
|
||||
.header-btn {
|
||||
padding: 6px 14px;
|
||||
font-size: 12px;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
background: var(--accent);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.control-body { padding: 14px; }
|
||||
|
||||
/* Temperature */
|
||||
.temp-section { margin-bottom: 14px; }
|
||||
.temp-row { display: flex; align-items: center; gap: 8px; padding: 4px 0; }
|
||||
.temp-icon { width: 20px; height: 20px; display: flex; align-items: center; justify-content: center; }
|
||||
.temp-icon img { width: 18px; opacity: 0.6; }
|
||||
.temp-badge {
|
||||
font-size: 10px; font-weight: 700; color: var(--accent);
|
||||
background: #e8f5e9; padding: 2px 6px; border-radius: 4px;
|
||||
}
|
||||
.temp-value { font-size: 15px; font-weight: 500; }
|
||||
.temp-target { font-size: 14px; color: var(--text-muted); }
|
||||
|
||||
/* Air Condition */
|
||||
.air-section {
|
||||
display: flex; align-items: center; gap: 12px;
|
||||
padding: 10px 0;
|
||||
border-top: 1px solid var(--border-light);
|
||||
border-bottom: 1px solid var(--border-light);
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
.air-label { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text-secondary); }
|
||||
.air-label img { width: 16px; opacity: 0.5; }
|
||||
.air-item { display: flex; align-items: center; gap: 6px; padding: 6px 12px; background: var(--bg-light); border-radius: 6px; font-size: 12px; }
|
||||
.air-item img { width: 16px; opacity: 0.5; }
|
||||
.lamp-dot { width: 12px; height: 12px; border-radius: 50%; background: var(--accent); }
|
||||
|
||||
/* Movement */
|
||||
.movement-section { display: flex; gap: 16px; margin-bottom: 16px; }
|
||||
.jog-pad { position: relative; width: 100px; height: 100px; }
|
||||
.jog-ring {
|
||||
width: 100%; height: 100%; border-radius: 50%;
|
||||
background: linear-gradient(135deg, #f8f8f8 0%, #e8e8e8 100%);
|
||||
border: 1px solid var(--border); position: relative;
|
||||
}
|
||||
.jog-label { position: absolute; font-size: 10px; color: var(--text-muted); }
|
||||
.jog-label.top { top: 6px; left: 50%; transform: translateX(-50%); }
|
||||
.jog-label.bottom { bottom: 6px; left: 50%; transform: translateX(-50%); }
|
||||
.jog-label.left { left: 6px; top: 50%; transform: translateY(-50%); }
|
||||
.jog-label.right { right: 6px; top: 50%; transform: translateY(-50%); }
|
||||
.jog-btn {
|
||||
position: absolute; width: 22px; height: 22px;
|
||||
background: var(--bg-light); border: 1px solid var(--border);
|
||||
border-radius: 4px; cursor: pointer; font-size: 9px; color: var(--text-muted);
|
||||
}
|
||||
.jog-btn:hover { background: var(--bg-hover); }
|
||||
.jog-btn.up { top: 18px; left: 50%; transform: translateX(-50%); }
|
||||
.jog-btn.down { bottom: 18px; left: 50%; transform: translateX(-50%); }
|
||||
.jog-btn.left { left: 18px; top: 50%; transform: translateY(-50%); }
|
||||
.jog-btn.right { right: 18px; top: 50%; transform: translateY(-50%); }
|
||||
.jog-home {
|
||||
position: absolute; top: 50%; left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 32px; height: 32px; border-radius: 50%;
|
||||
background: var(--accent); border: none; cursor: pointer;
|
||||
}
|
||||
.jog-home img { width: 16px; filter: brightness(0) invert(1); }
|
||||
|
||||
.step-section { display: flex; flex-direction: column; gap: 4px; }
|
||||
.step-row { display: flex; gap: 6px; }
|
||||
.step-btn {
|
||||
padding: 5px 8px; background: var(--bg-light);
|
||||
border: 1px solid var(--border); border-radius: 6px;
|
||||
cursor: pointer; font-size: 10px; color: var(--text-secondary);
|
||||
}
|
||||
.step-btn.active { background: var(--bg-hover); border-color: var(--text-muted); }
|
||||
.step-label { font-size: 10px; color: var(--text-muted); text-align: center; padding: 3px 0; }
|
||||
|
||||
.extruder-section { display: flex; flex-direction: column; align-items: center; gap: 4px; }
|
||||
.nozzle-toggle { display: flex; border-radius: 6px; overflow: hidden; border: 1px solid var(--border); }
|
||||
.nozzle-toggle button {
|
||||
padding: 5px 14px; border: none; background: var(--bg-white);
|
||||
font-size: 10px; cursor: pointer; color: var(--text-secondary);
|
||||
}
|
||||
.nozzle-toggle button:first-child { border-right: 1px solid var(--border); }
|
||||
.nozzle-toggle button.active { background: var(--accent); color: white; }
|
||||
.extruder-graphic { height: 70px; }
|
||||
.extruder-graphic img { height: 100%; }
|
||||
.extruder-label { font-size: 10px; color: var(--text-muted); }
|
||||
.ext-controls { display: flex; flex-direction: column; gap: 3px; }
|
||||
.ext-btn {
|
||||
width: 26px; height: 26px; background: var(--bg-light);
|
||||
border: 1px solid var(--border); border-radius: 6px;
|
||||
cursor: pointer; font-size: 11px; color: var(--text-muted);
|
||||
}
|
||||
|
||||
/* ========== AMS SECTION ========== */
|
||||
.ams-section { border-top: 1px solid var(--border-light); padding-top: 14px; }
|
||||
|
||||
/* Nozzle Filament Boxes */
|
||||
.nozzle-filament-row { display: flex; gap: 8px; margin-bottom: 10px; }
|
||||
.nozzle-filament-box {
|
||||
display: flex; align-items: center; gap: 6px;
|
||||
padding: 8px 10px; background: var(--bg-white);
|
||||
border: 2px solid var(--border); border-radius: 8px; cursor: pointer;
|
||||
}
|
||||
.nozzle-filament-box:hover { border-color: #ccc; }
|
||||
.nozzle-filament-box.active { border-color: var(--accent); }
|
||||
.filament-dots { display: flex; gap: 3px; }
|
||||
.f-dot { width: 16px; height: 16px; border-radius: 3px; border: 1px solid rgba(0,0,0,0.1); }
|
||||
.f-dot.empty { background: #eee !important; border: 1px dashed #ccc; }
|
||||
.f-dot-separator { width: 1px; height: 16px; background: #ccc; margin: 0 2px; }
|
||||
.filament-count { font-size: 11px; color: var(--text-muted); padding: 2px 6px; background: var(--bg-light); border-radius: 4px; margin-left: auto; }
|
||||
.filament-count.active { background: var(--accent); color: white; }
|
||||
|
||||
/* AMS Tabs */
|
||||
.ams-tabs { display: flex; gap: 6px; margin-bottom: 8px; flex-wrap: wrap; }
|
||||
.ams-tab {
|
||||
display: flex; align-items: center; gap: 4px;
|
||||
padding: 5px 8px; background: var(--bg-light);
|
||||
border: 2px solid transparent; border-radius: 6px;
|
||||
cursor: pointer; font-size: 10px; color: var(--text-secondary);
|
||||
}
|
||||
.ams-tab:hover { background: var(--bg-hover); }
|
||||
.ams-tab.active { border-color: var(--accent); }
|
||||
.ams-tab-dots { display: flex; gap: 2px; }
|
||||
.ams-tab-dot { width: 10px; height: 10px; border-radius: 2px; border: 1px solid rgba(0,0,0,0.08); }
|
||||
.ams-tab-label { font-size: 9px; color: var(--text-muted); margin-left: 2px; }
|
||||
|
||||
/* AMS-HT Tab (single slot indicator) */
|
||||
.ams-tab.ams-ht .ams-tab-dots { gap: 0; }
|
||||
.ams-tab.ams-ht .ams-tab-dot { width: 14px; height: 14px; border-radius: 3px; }
|
||||
|
||||
/* AMS Content Panel */
|
||||
.ams-content { background: var(--bg-panel); border-radius: 12px; padding: 12px; }
|
||||
|
||||
/* AMS Info Row */
|
||||
.ams-info-row { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
|
||||
.ams-humidity { display: flex; align-items: center; gap: 4px; font-size: 12px; color: var(--text-secondary); }
|
||||
.ams-humidity img { width: 14px; opacity: 0.5; }
|
||||
.ams-humidity .sun { font-size: 14px; color: #f5a623; }
|
||||
|
||||
/* AMS Main Area */
|
||||
.ams-main { display: flex; gap: 16px; }
|
||||
|
||||
/* AMS Slots Container */
|
||||
.ams-slots-container { flex: 1; }
|
||||
|
||||
/* Slot Labels Row */
|
||||
.slot-labels-row { display: flex; gap: 6px; margin-bottom: 4px; padding-left: 2px; }
|
||||
.slot-label-item { width: 50px; display: flex; align-items: center; justify-content: center; }
|
||||
.slot-label-badge {
|
||||
display: flex; align-items: center; gap: 2px;
|
||||
padding: 2px 5px; background: var(--bg-white);
|
||||
border: 1px solid var(--border); border-radius: 10px;
|
||||
font-size: 9px; color: var(--text-muted);
|
||||
}
|
||||
.slot-label-badge .arrow { font-size: 7px; }
|
||||
|
||||
/* AMS Slots */
|
||||
.ams-slots { display: flex; gap: 6px; }
|
||||
.ams-slot {
|
||||
width: 50px; height: 72px;
|
||||
border-radius: 8px; overflow: hidden;
|
||||
cursor: pointer; border: 2px solid var(--border);
|
||||
}
|
||||
.ams-slot:hover { border-color: #bbb; }
|
||||
.ams-slot.active { border-color: #d4a84b; }
|
||||
.ams-slot.selected { border-color: var(--accent); }
|
||||
.ams-slot-fill {
|
||||
width: 100%; height: 100%;
|
||||
display: flex; flex-direction: column;
|
||||
align-items: center; justify-content: flex-end;
|
||||
padding-bottom: 6px;
|
||||
}
|
||||
.ams-slot-type { font-size: 11px; font-weight: 600; color: white; text-shadow: 0 1px 2px rgba(0,0,0,0.3); margin-bottom: 2px; }
|
||||
.ams-slot-type.dark { color: #333; text-shadow: none; }
|
||||
.ams-slot-eye { width: 18px; height: 18px; }
|
||||
.ams-slot-eye img { width: 14px; height: 14px; opacity: 0.8; }
|
||||
.ams-slot-eye.invert img { filter: invert(1); }
|
||||
.ams-slot-empty {
|
||||
width: 100%; height: 100%;
|
||||
background: var(--bg-white);
|
||||
display: flex; flex-direction: column;
|
||||
align-items: center; justify-content: center;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
.ams-slot-empty .question { font-size: 16px; }
|
||||
.ams-slot-empty .angle { font-size: 12px; margin-top: 2px; }
|
||||
|
||||
/* Connector Lines */
|
||||
.ams-connectors { display: flex; padding-left: 2px; margin-top: 4px; }
|
||||
.connector-lines { display: flex; gap: 6px; position: relative; }
|
||||
.connector-line { width: 50px; display: flex; justify-content: center; }
|
||||
.connector-line .vline { width: 2px; height: 12px; background: #c0c0c0; }
|
||||
.connector-hbar { position: absolute; bottom: 0; left: 25px; right: 25px; height: 2px; background: #c0c0c0; }
|
||||
|
||||
/* Hub Row */
|
||||
.hub-row { display: flex; align-items: center; padding-left: 2px; margin-top: -1px; }
|
||||
.hub-line-left { width: calc(100px + 3px); height: 2px; background: #c0c0c0; }
|
||||
.hub-graphic { display: flex; padding: 3px 5px; background: var(--bg-white); border: 1px solid var(--border); border-radius: 3px; }
|
||||
.hub-port { width: 8px; height: 12px; background: var(--accent); border-radius: 2px; margin: 0 1px; }
|
||||
.hub-line-right { width: 30px; height: 2px; background: #c0c0c0; }
|
||||
|
||||
/* External Spool Section */
|
||||
.ext-spool-section { display: flex; flex-direction: column; align-items: center; min-width: 90px; }
|
||||
.ext-label { font-size: 12px; color: var(--text-secondary); margin-bottom: 4px; }
|
||||
.ext-content { display: flex; gap: 6px; align-items: flex-start; }
|
||||
.ext-slot {
|
||||
width: 50px; height: 72px;
|
||||
background: var(--bg-white); border: 2px solid var(--border);
|
||||
border-radius: 8px; display: flex; flex-direction: column;
|
||||
align-items: center; justify-content: center;
|
||||
cursor: pointer; color: var(--text-muted);
|
||||
}
|
||||
.ext-slot:hover { border-color: #bbb; }
|
||||
.ext-slot .question { font-size: 18px; }
|
||||
.ext-slot .angle { font-size: 12px; margin-top: 2px; }
|
||||
.ext-connector { width: 2px; height: 16px; background: #c0c0c0; margin-top: 4px; }
|
||||
.spool-holder-graphic { width: 70px; height: 90px; }
|
||||
.spool-holder-graphic img { width: 100%; height: 100%; object-fit: contain; }
|
||||
|
||||
/* AMS Actions */
|
||||
.ams-actions { display: flex; align-items: center; gap: 8px; margin-top: 10px; }
|
||||
.auto-refill-btn {
|
||||
display: flex; align-items: center; gap: 5px;
|
||||
padding: 8px 12px; background: var(--bg-white);
|
||||
border: 1px solid var(--border); border-radius: 6px;
|
||||
cursor: pointer; font-size: 12px; color: var(--text-secondary);
|
||||
}
|
||||
.auto-refill-btn:hover { background: var(--bg-hover); }
|
||||
.ams-settings-btn {
|
||||
width: 32px; height: 32px;
|
||||
background: var(--bg-white); border: 1px solid var(--border);
|
||||
border-radius: 6px; cursor: pointer;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
}
|
||||
.ams-settings-btn:hover { background: var(--bg-hover); }
|
||||
.ams-settings-btn img { width: 18px; opacity: 0.5; }
|
||||
.ams-spacer { flex: 1; }
|
||||
.ams-action-btn {
|
||||
padding: 8px 20px; border-radius: 6px;
|
||||
font-size: 12px; cursor: pointer; border: none;
|
||||
background: #e0e0e0; color: var(--text-secondary);
|
||||
}
|
||||
.ams-action-btn:hover { background: #d5d5d5; }
|
||||
|
||||
/* AMS-HT Specific Styles */
|
||||
.ams-ht-content { padding: 10px; }
|
||||
.ams-ht-slot {
|
||||
width: 60px; height: 80px;
|
||||
border-radius: 10px; overflow: hidden;
|
||||
cursor: pointer; border: 2px solid var(--border);
|
||||
margin: 0 auto;
|
||||
}
|
||||
.ams-ht-label { font-size: 10px; color: var(--text-muted); text-align: center; margin-top: 4px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="main-layout">
|
||||
<!-- Left Panel -->
|
||||
<div class="left-panel">
|
||||
<div class="camera-header">
|
||||
<span class="camera-title">Camera</span>
|
||||
<button class="icon-btn"><img src="icons/video-camera.svg"></button>
|
||||
<button class="icon-btn"><img src="icons/webcam.svg"></button>
|
||||
<button class="icon-btn"><img src="icons/settings.svg"></button>
|
||||
<button class="icon-btn"><img src="icons/reload.svg"></button>
|
||||
</div>
|
||||
<div class="camera-feed">Camera Feed</div>
|
||||
<div class="print-progress">
|
||||
<div class="progress-label">Printing Progress</div>
|
||||
<div class="progress-row">
|
||||
<div class="progress-thumb"><img src="icons/micro-sd.svg"></div>
|
||||
<div class="progress-info">
|
||||
<div class="progress-name">N/A</div>
|
||||
<div class="progress-status">N/A</div>
|
||||
<div class="progress-bar-bg"><div class="progress-bar-fill"></div></div>
|
||||
<div class="progress-meta"><span>Layer: N/A</span><span>N/A</span></div>
|
||||
<div class="progress-meta">Estimated finish time: N/A</div>
|
||||
</div>
|
||||
<div class="progress-btns">
|
||||
<button class="progress-btn">⌂</button>
|
||||
<button class="progress-btn">⏸</button>
|
||||
<button class="progress-btn">■</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Right Panel -->
|
||||
<div class="right-panel">
|
||||
<div class="control-header">
|
||||
<span class="control-title">Control</span>
|
||||
<button class="header-btn">Printer Parts</button>
|
||||
<button class="header-btn">Print Options</button>
|
||||
<button class="header-btn">Calibration</button>
|
||||
</div>
|
||||
|
||||
<div class="control-body">
|
||||
<!-- Temperature -->
|
||||
<div class="temp-section">
|
||||
<div class="temp-row">
|
||||
<div class="temp-icon"><img src="icons/hotend.svg"></div>
|
||||
<span class="temp-badge">L</span>
|
||||
<span class="temp-value">22</span>
|
||||
<span class="temp-target">/0 °C</span>
|
||||
</div>
|
||||
<div class="temp-row">
|
||||
<div class="temp-icon"><img src="icons/hotend.svg"></div>
|
||||
<span class="temp-badge">R</span>
|
||||
<span class="temp-value">21</span>
|
||||
<span class="temp-target">/0 °C</span>
|
||||
</div>
|
||||
<div class="temp-row">
|
||||
<div class="temp-icon"><img src="icons/heatbed.svg"></div>
|
||||
<span class="temp-value">21</span>
|
||||
<span class="temp-target">/0 °C</span>
|
||||
</div>
|
||||
<div class="temp-row">
|
||||
<div class="temp-icon"><img src="icons/chamber.svg"></div>
|
||||
<span class="temp-value">21</span>
|
||||
<span class="temp-target">/0 °C</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Air Condition -->
|
||||
<div class="air-section">
|
||||
<div class="air-label"><img src="icons/ventilation.svg"> Air Condition</div>
|
||||
<div class="air-item"><img src="icons/ventilation.svg"> 100%</div>
|
||||
<div class="air-item">Lamp <div class="lamp-dot"></div></div>
|
||||
</div>
|
||||
|
||||
<!-- Movement -->
|
||||
<div class="movement-section">
|
||||
<div class="jog-pad">
|
||||
<div class="jog-ring">
|
||||
<span class="jog-label top">Y</span>
|
||||
<span class="jog-label bottom">-Y</span>
|
||||
<span class="jog-label left">-X</span>
|
||||
<span class="jog-label right">X</span>
|
||||
<button class="jog-btn up">▲</button>
|
||||
<button class="jog-btn down">▼</button>
|
||||
<button class="jog-btn left">◀</button>
|
||||
<button class="jog-btn right">▶</button>
|
||||
<button class="jog-home"><img src="icons/home.svg"></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="step-section">
|
||||
<div class="step-row">
|
||||
<button class="step-btn">↑ 10</button>
|
||||
<button class="step-btn active">↑ 1</button>
|
||||
</div>
|
||||
<div class="step-label">Bed</div>
|
||||
<div class="step-row">
|
||||
<button class="step-btn">↓ 1</button>
|
||||
<button class="step-btn">↓ 10</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="extruder-section">
|
||||
<div class="nozzle-toggle">
|
||||
<button class="active">Left</button>
|
||||
<button>Right</button>
|
||||
</div>
|
||||
<div class="extruder-graphic"><img src="icons/dual-extruder.png"></div>
|
||||
<span class="extruder-label">Extruder</span>
|
||||
<div class="ext-controls">
|
||||
<button class="ext-btn">▲</button>
|
||||
<button class="ext-btn">▼</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- AMS Section -->
|
||||
<div class="ams-section">
|
||||
<!-- Nozzle Filament Assignment Boxes -->
|
||||
<div class="nozzle-filament-row">
|
||||
<div class="nozzle-filament-box active">
|
||||
<div class="filament-dots">
|
||||
<div class="f-dot" style="background: #FFD700;"></div>
|
||||
<div class="f-dot" style="background: #8B4513;"></div>
|
||||
<div class="f-dot" style="background: #1a1a1a;"></div>
|
||||
<div class="f-dot" style="background: #222;"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="nozzle-filament-box">
|
||||
<div class="filament-dots">
|
||||
<div class="f-dot" style="background: #FF6600;"></div>
|
||||
<div class="f-dot" style="background: #00AA00;"></div>
|
||||
<div class="f-dot" style="background: #0066FF;"></div>
|
||||
<div class="f-dot" style="background: #FF0000;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- AMS Tabs - Shows all connected AMS/AMS-HT units -->
|
||||
<div class="ams-tabs">
|
||||
<!-- AMS 1 (Regular AMS - 4 slots) -->
|
||||
<div class="ams-tab active">
|
||||
<div class="ams-tab-dots">
|
||||
<div class="ams-tab-dot" style="background: #FFD700;"></div>
|
||||
<div class="ams-tab-dot" style="background: #1a1a1a;"></div>
|
||||
<div class="ams-tab-dot" style="background: #8B4513;"></div>
|
||||
<div class="ams-tab-dot" style="background: #222;"></div>
|
||||
</div>
|
||||
<span class="ams-tab-label">AMS 1</span>
|
||||
</div>
|
||||
<!-- AMS 2 (Regular AMS - 4 slots) -->
|
||||
<div class="ams-tab">
|
||||
<div class="ams-tab-dots">
|
||||
<div class="ams-tab-dot" style="background: #FF6600;"></div>
|
||||
<div class="ams-tab-dot" style="background: #00AA00;"></div>
|
||||
<div class="ams-tab-dot" style="background: #0066FF;"></div>
|
||||
<div class="ams-tab-dot" style="background: #FF0000;"></div>
|
||||
</div>
|
||||
<span class="ams-tab-label">AMS 2</span>
|
||||
</div>
|
||||
<!-- AMS 3 (Regular AMS - 4 slots) -->
|
||||
<div class="ams-tab">
|
||||
<div class="ams-tab-dots">
|
||||
<div class="ams-tab-dot" style="background: #FFFFFF; border-color: #ccc;"></div>
|
||||
<div class="ams-tab-dot" style="background: #333;"></div>
|
||||
<div class="ams-tab-dot" style="background: #666;"></div>
|
||||
<div class="ams-tab-dot" style="background: #999;"></div>
|
||||
</div>
|
||||
<span class="ams-tab-label">AMS 3</span>
|
||||
</div>
|
||||
<!-- AMS-HT 1 (High Temp - single slot) -->
|
||||
<div class="ams-tab ams-ht">
|
||||
<div class="ams-tab-dots">
|
||||
<div class="ams-tab-dot" style="background: #8844AA;"></div>
|
||||
</div>
|
||||
<span class="ams-tab-label">HT 1</span>
|
||||
</div>
|
||||
<!-- AMS-HT 2 (High Temp - single slot) -->
|
||||
<div class="ams-tab ams-ht">
|
||||
<div class="ams-tab-dots">
|
||||
<div class="ams-tab-dot" style="background: #44AA88;"></div>
|
||||
</div>
|
||||
<span class="ams-tab-label">HT 2</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- AMS Content Panel -->
|
||||
<div class="ams-content">
|
||||
<!-- Info Row -->
|
||||
<div class="ams-info-row">
|
||||
<div class="ams-humidity"><img src="icons/water.svg"> 18 %</div>
|
||||
<div class="ams-humidity"><span class="sun">☼</span></div>
|
||||
</div>
|
||||
|
||||
<!-- Main AMS Area -->
|
||||
<div class="ams-main">
|
||||
<!-- AMS Slots Container -->
|
||||
<div class="ams-slots-container">
|
||||
<!-- Slot Labels -->
|
||||
<div class="slot-labels-row">
|
||||
<div class="slot-label-item">
|
||||
<div class="slot-label-badge">A1 <span class="arrow">↓</span></div>
|
||||
</div>
|
||||
<div class="slot-label-item">
|
||||
<div class="slot-label-badge">A2 <span class="arrow">↓</span></div>
|
||||
</div>
|
||||
<div class="slot-label-item">
|
||||
<div class="slot-label-badge">A3 <span class="arrow">↓</span></div>
|
||||
</div>
|
||||
<div class="slot-label-item">
|
||||
<div class="slot-label-badge">A4 <span class="arrow">↓</span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Slots -->
|
||||
<div class="ams-slots">
|
||||
<div class="ams-slot active">
|
||||
<div class="ams-slot-fill" style="background: #FFD700;">
|
||||
<span class="ams-slot-type dark">PLA</span>
|
||||
<div class="ams-slot-eye"><img src="icons/eye.svg"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ams-slot">
|
||||
<div class="ams-slot-fill" style="background: #1a1a1a;">
|
||||
<span class="ams-slot-type">PETG</span>
|
||||
<div class="ams-slot-eye invert"><img src="icons/eye.svg"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ams-slot">
|
||||
<div class="ams-slot-fill" style="background: #8B4513;">
|
||||
<span class="ams-slot-type">PETG</span>
|
||||
<div class="ams-slot-eye invert"><img src="icons/eye.svg"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ams-slot">
|
||||
<div class="ams-slot-fill" style="background: #222;">
|
||||
<span class="ams-slot-type">PLA</span>
|
||||
<div class="ams-slot-eye invert"><img src="icons/eye.svg"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Connectors -->
|
||||
<div class="ams-connectors">
|
||||
<div class="connector-lines">
|
||||
<div class="connector-line"><div class="vline"></div></div>
|
||||
<div class="connector-line"><div class="vline"></div></div>
|
||||
<div class="connector-line"><div class="vline"></div></div>
|
||||
<div class="connector-line"><div class="vline"></div></div>
|
||||
<div class="connector-hbar"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Hub -->
|
||||
<div class="hub-row">
|
||||
<div class="hub-line-left"></div>
|
||||
<div class="hub-graphic">
|
||||
<div class="hub-port"></div>
|
||||
<div class="hub-port"></div>
|
||||
</div>
|
||||
<div class="hub-line-right"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- External Spool Section -->
|
||||
<div class="ext-spool-section">
|
||||
<div class="ext-label">Ext</div>
|
||||
<div class="ext-content">
|
||||
<div style="display: flex; flex-direction: column; align-items: center;">
|
||||
<div class="ext-slot">
|
||||
<span class="question">?</span>
|
||||
<span class="angle">∠</span>
|
||||
</div>
|
||||
<div class="ext-connector"></div>
|
||||
</div>
|
||||
<div class="spool-holder-graphic">
|
||||
<img src="icons/single-extruder1.png">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- AMS Actions -->
|
||||
<div class="ams-actions">
|
||||
<button class="auto-refill-btn">Auto-refill</button>
|
||||
<button class="ams-settings-btn"><img src="icons/ams-settings.svg"></button>
|
||||
<div class="ams-spacer"></div>
|
||||
<button class="ams-action-btn">Unload</button>
|
||||
<button class="ams-action-btn">Load</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,654 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>BambuTrack Control - v7</title>
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
|
||||
:root {
|
||||
--bg-main: #f5f5f5;
|
||||
--bg-white: #ffffff;
|
||||
--bg-light: #fafafa;
|
||||
--bg-panel: #f0f0f0;
|
||||
--bg-hover: #e8e8e8;
|
||||
--text-primary: #333333;
|
||||
--text-secondary: #666666;
|
||||
--text-muted: #999999;
|
||||
--border: #e0e0e0;
|
||||
--border-light: #eeeeee;
|
||||
--accent: #00ae42;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
background: var(--bg-main);
|
||||
color: var(--text-primary);
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.main-layout {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 300px;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
/* Left Panel */
|
||||
.left-panel {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: var(--bg-main);
|
||||
}
|
||||
|
||||
.camera-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 6px 10px;
|
||||
background: var(--bg-white);
|
||||
border-bottom: 1px solid var(--border);
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.camera-title {
|
||||
font-size: 12px;
|
||||
color: var(--text-primary);
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.icon-btn {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border: none;
|
||||
background: none;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.icon-btn:hover { background: var(--bg-hover); }
|
||||
.icon-btn img { width: 16px; height: 16px; opacity: 0.6; }
|
||||
|
||||
.camera-feed {
|
||||
flex: 1;
|
||||
background: #1a1a1a;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
/* Print Progress */
|
||||
.print-progress {
|
||||
background: var(--bg-white);
|
||||
border-top: 1px solid var(--border);
|
||||
padding: 12px 16px;
|
||||
}
|
||||
|
||||
.progress-label { font-size: 11px; color: var(--text-muted); margin-bottom: 8px; }
|
||||
.progress-row { display: flex; gap: 12px; align-items: center; }
|
||||
.progress-thumb {
|
||||
width: 48px; height: 48px;
|
||||
background: var(--bg-light);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 6px;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
}
|
||||
.progress-thumb img { width: 28px; opacity: 0.4; }
|
||||
.progress-info { flex: 1; }
|
||||
.progress-name { font-weight: 500; font-size: 13px; }
|
||||
.progress-status { color: var(--accent); font-size: 12px; margin: 2px 0 6px; }
|
||||
.progress-bar-bg { height: 3px; background: var(--border-light); border-radius: 2px; margin-bottom: 6px; }
|
||||
.progress-bar-fill { height: 100%; background: var(--accent); border-radius: 2px; width: 0%; }
|
||||
.progress-meta { font-size: 11px; color: var(--text-muted); }
|
||||
.progress-btns { display: flex; gap: 4px; }
|
||||
.progress-btn {
|
||||
width: 28px; height: 28px;
|
||||
border: 1px solid var(--border);
|
||||
background: var(--bg-white);
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
.progress-btn:hover { background: var(--bg-hover); }
|
||||
|
||||
/* Right Panel */
|
||||
.right-panel {
|
||||
background: var(--bg-white);
|
||||
border-left: 1px solid var(--border);
|
||||
overflow-y: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.control-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 8px 10px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.control-title { font-size: 12px; margin-right: auto; }
|
||||
.header-btn {
|
||||
padding: 5px 10px;
|
||||
font-size: 11px;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
background: var(--accent);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.control-body { padding: 10px; flex: 1; overflow-y: auto; }
|
||||
|
||||
/* Temperature - Compact */
|
||||
.temp-section { margin-bottom: 10px; }
|
||||
.temp-row { display: flex; align-items: center; gap: 6px; padding: 2px 0; }
|
||||
.temp-icon { width: 16px; height: 16px; display: flex; align-items: center; justify-content: center; }
|
||||
.temp-icon img { width: 14px; opacity: 0.6; }
|
||||
.temp-badge {
|
||||
font-size: 9px; font-weight: 700; color: var(--accent);
|
||||
background: #e8f5e9; padding: 1px 4px; border-radius: 3px;
|
||||
}
|
||||
.temp-value { font-size: 14px; font-weight: 500; }
|
||||
.temp-target { font-size: 12px; color: var(--text-muted); }
|
||||
|
||||
/* Air Condition - Compact */
|
||||
.air-section {
|
||||
display: flex; align-items: center; gap: 8px;
|
||||
padding: 8px 0;
|
||||
border-top: 1px solid var(--border-light);
|
||||
border-bottom: 1px solid var(--border-light);
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.air-label { display: flex; align-items: center; gap: 4px; font-size: 11px; color: var(--text-secondary); }
|
||||
.air-label img { width: 14px; opacity: 0.5; }
|
||||
.air-item { display: flex; align-items: center; gap: 4px; padding: 4px 8px; background: var(--bg-light); border-radius: 4px; font-size: 11px; }
|
||||
.air-item img { width: 14px; opacity: 0.5; }
|
||||
.lamp-dot { width: 10px; height: 10px; border-radius: 50%; background: var(--accent); }
|
||||
|
||||
/* Movement - Compact */
|
||||
.movement-section { display: flex; gap: 10px; margin-bottom: 12px; align-items: flex-start; }
|
||||
|
||||
.jog-pad { position: relative; width: 90px; height: 90px; }
|
||||
.jog-ring {
|
||||
width: 100%; height: 100%; border-radius: 50%;
|
||||
background: linear-gradient(135deg, #f8f8f8 0%, #e8e8e8 100%);
|
||||
border: 1px solid var(--border); position: relative;
|
||||
}
|
||||
.jog-label { position: absolute; font-size: 9px; color: var(--text-muted); }
|
||||
.jog-label.top { top: 5px; left: 50%; transform: translateX(-50%); }
|
||||
.jog-label.bottom { bottom: 5px; left: 50%; transform: translateX(-50%); }
|
||||
.jog-label.left { left: 5px; top: 50%; transform: translateY(-50%); }
|
||||
.jog-label.right { right: 5px; top: 50%; transform: translateY(-50%); }
|
||||
.jog-btn {
|
||||
position: absolute; width: 18px; height: 18px;
|
||||
background: var(--bg-light); border: 1px solid var(--border);
|
||||
border-radius: 3px; cursor: pointer; font-size: 8px; color: var(--text-muted);
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
}
|
||||
.jog-btn:hover { background: var(--bg-hover); }
|
||||
.jog-btn.up { top: 16px; left: 50%; transform: translateX(-50%); }
|
||||
.jog-btn.down { bottom: 16px; left: 50%; transform: translateX(-50%); }
|
||||
.jog-btn.left { left: 16px; top: 50%; transform: translateY(-50%); }
|
||||
.jog-btn.right { right: 16px; top: 50%; transform: translateY(-50%); }
|
||||
.jog-home {
|
||||
position: absolute; top: 50%; left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 28px; height: 28px; border-radius: 50%;
|
||||
background: var(--accent); border: none; cursor: pointer;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
}
|
||||
.jog-home img { width: 14px; filter: brightness(0) invert(1); }
|
||||
|
||||
.step-section { display: flex; flex-direction: column; gap: 2px; }
|
||||
.step-row { display: flex; gap: 4px; }
|
||||
.step-btn {
|
||||
padding: 4px 6px; background: var(--bg-light);
|
||||
border: 1px solid var(--border); border-radius: 4px;
|
||||
cursor: pointer; font-size: 9px; color: var(--text-secondary);
|
||||
}
|
||||
.step-btn.active { background: var(--bg-hover); border-color: var(--text-muted); }
|
||||
.step-label { font-size: 9px; color: var(--text-muted); text-align: center; padding: 2px 0; }
|
||||
|
||||
.extruder-section { display: flex; flex-direction: column; align-items: center; gap: 3px; }
|
||||
.nozzle-toggle { display: flex; border-radius: 4px; overflow: hidden; border: 1px solid var(--border); }
|
||||
.nozzle-toggle button {
|
||||
padding: 4px 10px; border: none; background: var(--bg-white);
|
||||
font-size: 9px; cursor: pointer; color: var(--text-secondary);
|
||||
}
|
||||
.nozzle-toggle button:first-child { border-right: 1px solid var(--border); }
|
||||
.nozzle-toggle button.active { background: var(--accent); color: white; }
|
||||
.extruder-graphic { height: 60px; }
|
||||
.extruder-graphic img { height: 100%; }
|
||||
.extruder-label { font-size: 9px; color: var(--text-muted); }
|
||||
.ext-controls { display: flex; flex-direction: column; gap: 2px; }
|
||||
.ext-btn {
|
||||
width: 22px; height: 22px; background: var(--bg-light);
|
||||
border: 1px solid var(--border); border-radius: 4px;
|
||||
cursor: pointer; font-size: 10px; color: var(--text-muted);
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
}
|
||||
|
||||
/* ========== AMS SECTION ========== */
|
||||
.ams-section { border-top: 1px solid var(--border-light); padding-top: 10px; }
|
||||
|
||||
/* Nozzle Filament Boxes */
|
||||
.nozzle-filament-row { display: flex; gap: 6px; margin-bottom: 8px; }
|
||||
.nozzle-filament-box {
|
||||
display: flex; align-items: center; gap: 4px;
|
||||
padding: 6px 8px; background: var(--bg-white);
|
||||
border: 2px solid var(--border); border-radius: 6px; cursor: pointer;
|
||||
}
|
||||
.nozzle-filament-box:hover { border-color: #ccc; }
|
||||
.nozzle-filament-box.active { border-color: var(--accent); }
|
||||
.filament-dots { display: flex; gap: 2px; }
|
||||
.f-dot { width: 14px; height: 14px; border-radius: 3px; border: 1px solid rgba(0,0,0,0.1); }
|
||||
.f-dot.empty { background: #eee !important; border: 1px dashed #ccc; }
|
||||
|
||||
/* AMS Tabs */
|
||||
.ams-tabs { display: flex; gap: 4px; margin-bottom: 6px; flex-wrap: wrap; }
|
||||
.ams-tab {
|
||||
display: flex; align-items: center; gap: 3px;
|
||||
padding: 4px 6px; background: var(--bg-light);
|
||||
border: 2px solid transparent; border-radius: 5px;
|
||||
cursor: pointer; font-size: 9px; color: var(--text-secondary);
|
||||
}
|
||||
.ams-tab:hover { background: var(--bg-hover); }
|
||||
.ams-tab.active { border-color: var(--accent); }
|
||||
.ams-tab-dots { display: flex; gap: 1px; }
|
||||
.ams-tab-dot { width: 8px; height: 8px; border-radius: 2px; border: 1px solid rgba(0,0,0,0.08); }
|
||||
.ams-tab-label { font-size: 8px; color: var(--text-muted); }
|
||||
|
||||
/* AMS Content Panel */
|
||||
.ams-content { background: var(--bg-panel); border-radius: 10px; padding: 10px; }
|
||||
|
||||
/* AMS Info Row */
|
||||
.ams-info-row { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
|
||||
.ams-humidity { display: flex; align-items: center; gap: 3px; font-size: 11px; color: var(--text-secondary); }
|
||||
.ams-humidity img { width: 12px; opacity: 0.5; }
|
||||
.ams-humidity .sun { font-size: 12px; color: #f5a623; }
|
||||
|
||||
/* AMS Main Area */
|
||||
.ams-main { display: flex; gap: 8px; }
|
||||
|
||||
/* AMS Slots Container */
|
||||
.ams-slots-container { flex: 1; }
|
||||
|
||||
/* Slot Labels Row */
|
||||
.slot-labels-row { display: flex; gap: 4px; margin-bottom: 3px; }
|
||||
.slot-label-item { width: 44px; display: flex; align-items: center; justify-content: center; }
|
||||
.slot-label-badge {
|
||||
display: flex; align-items: center; gap: 1px;
|
||||
padding: 2px 4px; background: var(--bg-white);
|
||||
border: 1px solid var(--border); border-radius: 8px;
|
||||
font-size: 8px; color: var(--text-muted);
|
||||
}
|
||||
|
||||
/* AMS Slots */
|
||||
.ams-slots { display: flex; gap: 4px; }
|
||||
.ams-slot {
|
||||
width: 44px; height: 64px;
|
||||
border-radius: 6px; overflow: hidden;
|
||||
cursor: pointer; border: 2px solid var(--border);
|
||||
}
|
||||
.ams-slot:hover { border-color: #bbb; }
|
||||
.ams-slot.active { border-color: #d4a84b; }
|
||||
.ams-slot-fill {
|
||||
width: 100%; height: 100%;
|
||||
display: flex; flex-direction: column;
|
||||
align-items: center; justify-content: flex-end;
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
.ams-slot-type { font-size: 10px; font-weight: 600; color: white; text-shadow: 0 1px 2px rgba(0,0,0,0.3); margin-bottom: 2px; }
|
||||
.ams-slot-type.dark { color: #333; text-shadow: none; }
|
||||
.ams-slot-eye { width: 14px; height: 14px; }
|
||||
.ams-slot-eye img { width: 12px; height: 12px; opacity: 0.8; }
|
||||
.ams-slot-eye.invert img { filter: invert(1); }
|
||||
.ams-slot-empty {
|
||||
width: 100%; height: 100%;
|
||||
background: var(--bg-white);
|
||||
display: flex; flex-direction: column;
|
||||
align-items: center; justify-content: center;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
.ams-slot-empty .question { font-size: 14px; }
|
||||
.ams-slot-empty .angle { font-size: 10px; }
|
||||
|
||||
/* Connector Lines */
|
||||
.ams-connectors { display: flex; margin-top: 3px; }
|
||||
.connector-lines { display: flex; gap: 4px; position: relative; }
|
||||
.connector-line { width: 44px; display: flex; justify-content: center; }
|
||||
.connector-line .vline { width: 2px; height: 10px; background: #c0c0c0; }
|
||||
.connector-hbar { position: absolute; bottom: 0; left: 22px; right: 22px; height: 2px; background: #c0c0c0; }
|
||||
|
||||
/* Hub Row */
|
||||
.hub-row { display: flex; align-items: center; margin-top: -1px; }
|
||||
.hub-line-left { width: 88px; height: 2px; background: #c0c0c0; }
|
||||
.hub-graphic { display: flex; padding: 2px 4px; background: var(--bg-white); border: 1px solid var(--border); border-radius: 3px; }
|
||||
.hub-port { width: 6px; height: 10px; background: var(--accent); border-radius: 1px; margin: 0 1px; }
|
||||
.hub-line-right { width: 20px; height: 2px; background: #c0c0c0; }
|
||||
|
||||
/* External Spool Section */
|
||||
.ext-spool-section { display: flex; flex-direction: column; align-items: center; }
|
||||
.ext-label { font-size: 10px; color: var(--text-secondary); margin-bottom: 3px; }
|
||||
.ext-content { display: flex; gap: 4px; align-items: flex-start; }
|
||||
.ext-slot {
|
||||
width: 44px; height: 64px;
|
||||
background: var(--bg-white); border: 2px solid var(--border);
|
||||
border-radius: 6px; display: flex; flex-direction: column;
|
||||
align-items: center; justify-content: center;
|
||||
cursor: pointer; color: var(--text-muted);
|
||||
}
|
||||
.ext-slot:hover { border-color: #bbb; }
|
||||
.ext-slot .question { font-size: 14px; }
|
||||
.ext-slot .angle { font-size: 10px; }
|
||||
.ext-connector { width: 2px; height: 12px; background: #c0c0c0; margin-top: 3px; }
|
||||
.spool-holder-graphic { width: 50px; height: 70px; }
|
||||
.spool-holder-graphic img { width: 100%; height: 100%; object-fit: contain; }
|
||||
|
||||
/* AMS Actions */
|
||||
.ams-actions { display: flex; align-items: center; gap: 6px; margin-top: 8px; }
|
||||
.auto-refill-btn {
|
||||
display: flex; align-items: center; gap: 4px;
|
||||
padding: 6px 10px; background: var(--bg-white);
|
||||
border: 1px solid var(--border); border-radius: 5px;
|
||||
cursor: pointer; font-size: 11px; color: var(--text-secondary);
|
||||
}
|
||||
.auto-refill-btn:hover { background: var(--bg-hover); }
|
||||
.ams-settings-btn {
|
||||
width: 28px; height: 28px;
|
||||
background: var(--bg-white); border: 1px solid var(--border);
|
||||
border-radius: 5px; cursor: pointer;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
}
|
||||
.ams-settings-btn:hover { background: var(--bg-hover); }
|
||||
.ams-settings-btn img { width: 16px; opacity: 0.5; }
|
||||
.ams-spacer { flex: 1; }
|
||||
.ams-action-btn {
|
||||
padding: 6px 16px; border-radius: 5px;
|
||||
font-size: 11px; cursor: pointer; border: none;
|
||||
background: #e0e0e0; color: var(--text-secondary);
|
||||
}
|
||||
.ams-action-btn:hover { background: #d5d5d5; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="main-layout">
|
||||
<!-- Left Panel -->
|
||||
<div class="left-panel">
|
||||
<div class="camera-header">
|
||||
<span class="camera-title">Camera</span>
|
||||
<button class="icon-btn"><img src="icons/video-camera.svg"></button>
|
||||
<button class="icon-btn"><img src="icons/webcam.svg"></button>
|
||||
<button class="icon-btn"><img src="icons/settings.svg"></button>
|
||||
<button class="icon-btn"><img src="icons/reload.svg"></button>
|
||||
</div>
|
||||
<div class="camera-feed">Camera Feed</div>
|
||||
<div class="print-progress">
|
||||
<div class="progress-label">Printing Progress</div>
|
||||
<div class="progress-row">
|
||||
<div class="progress-thumb"><img src="icons/micro-sd.svg"></div>
|
||||
<div class="progress-info">
|
||||
<div class="progress-name">N/A</div>
|
||||
<div class="progress-status">N/A</div>
|
||||
<div class="progress-bar-bg"><div class="progress-bar-fill"></div></div>
|
||||
<div class="progress-meta">Layer: N/A Estimated finish time: N/A</div>
|
||||
</div>
|
||||
<div class="progress-btns">
|
||||
<button class="progress-btn">⌂</button>
|
||||
<button class="progress-btn">⏸</button>
|
||||
<button class="progress-btn">■</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Right Panel -->
|
||||
<div class="right-panel">
|
||||
<div class="control-header">
|
||||
<span class="control-title">Control</span>
|
||||
<button class="header-btn">Printer Parts</button>
|
||||
<button class="header-btn">Print Options</button>
|
||||
<button class="header-btn">Calibration</button>
|
||||
</div>
|
||||
|
||||
<div class="control-body">
|
||||
<!-- Temperature -->
|
||||
<div class="temp-section">
|
||||
<div class="temp-row">
|
||||
<div class="temp-icon"><img src="icons/hotend.svg"></div>
|
||||
<span class="temp-badge">L</span>
|
||||
<span class="temp-value">22</span>
|
||||
<span class="temp-target">/0 °C</span>
|
||||
</div>
|
||||
<div class="temp-row">
|
||||
<div class="temp-icon"><img src="icons/hotend.svg"></div>
|
||||
<span class="temp-badge">R</span>
|
||||
<span class="temp-value">21</span>
|
||||
<span class="temp-target">/0 °C</span>
|
||||
</div>
|
||||
<div class="temp-row">
|
||||
<div class="temp-icon"><img src="icons/heatbed.svg"></div>
|
||||
<span class="temp-value">21</span>
|
||||
<span class="temp-target">/0 °C</span>
|
||||
</div>
|
||||
<div class="temp-row">
|
||||
<div class="temp-icon"><img src="icons/chamber.svg"></div>
|
||||
<span class="temp-value">21</span>
|
||||
<span class="temp-target">/0 °C</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Air Condition -->
|
||||
<div class="air-section">
|
||||
<div class="air-label"><img src="icons/ventilation.svg"> Air Condition</div>
|
||||
<div class="air-item"><img src="icons/ventilation.svg"> 100%</div>
|
||||
<div class="air-item">Lamp <div class="lamp-dot"></div></div>
|
||||
</div>
|
||||
|
||||
<!-- Movement -->
|
||||
<div class="movement-section">
|
||||
<div class="jog-pad">
|
||||
<div class="jog-ring">
|
||||
<span class="jog-label top">Y</span>
|
||||
<span class="jog-label bottom">-Y</span>
|
||||
<span class="jog-label left">-X</span>
|
||||
<span class="jog-label right">X</span>
|
||||
<button class="jog-btn up">▲</button>
|
||||
<button class="jog-btn down">▼</button>
|
||||
<button class="jog-btn left">◀</button>
|
||||
<button class="jog-btn right">▶</button>
|
||||
<button class="jog-home"><img src="icons/home.svg"></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="step-section">
|
||||
<div class="step-row">
|
||||
<button class="step-btn">↑10</button>
|
||||
<button class="step-btn active">↑1</button>
|
||||
</div>
|
||||
<div class="step-label">Bed</div>
|
||||
<div class="step-row">
|
||||
<button class="step-btn">↓1</button>
|
||||
<button class="step-btn">↓10</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="extruder-section">
|
||||
<div class="nozzle-toggle">
|
||||
<button class="active">Left</button>
|
||||
<button>Right</button>
|
||||
</div>
|
||||
<div class="extruder-graphic"><img src="icons/dual-extruder.png"></div>
|
||||
<span class="extruder-label">Extruder</span>
|
||||
<div class="ext-controls">
|
||||
<button class="ext-btn">▲</button>
|
||||
<button class="ext-btn">▼</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- AMS Section -->
|
||||
<div class="ams-section">
|
||||
<!-- Nozzle Filament Assignment Boxes -->
|
||||
<div class="nozzle-filament-row">
|
||||
<div class="nozzle-filament-box active">
|
||||
<div class="filament-dots">
|
||||
<div class="f-dot" style="background: #FFD700;"></div>
|
||||
<div class="f-dot" style="background: #8B4513;"></div>
|
||||
<div class="f-dot" style="background: #1a1a1a;"></div>
|
||||
<div class="f-dot" style="background: #222;"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="nozzle-filament-box">
|
||||
<div class="filament-dots">
|
||||
<div class="f-dot" style="background: #FF6600;"></div>
|
||||
<div class="f-dot" style="background: #00AA00;"></div>
|
||||
<div class="f-dot" style="background: #0066FF;"></div>
|
||||
<div class="f-dot" style="background: #FF0000;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- AMS Tabs -->
|
||||
<div class="ams-tabs">
|
||||
<div class="ams-tab active">
|
||||
<div class="ams-tab-dots">
|
||||
<div class="ams-tab-dot" style="background: #FFD700;"></div>
|
||||
<div class="ams-tab-dot" style="background: #8B4513;"></div>
|
||||
<div class="ams-tab-dot" style="background: #1a1a1a;"></div>
|
||||
<div class="ams-tab-dot" style="background: #222;"></div>
|
||||
</div>
|
||||
<span class="ams-tab-label">AMS 1</span>
|
||||
</div>
|
||||
<div class="ams-tab">
|
||||
<div class="ams-tab-dots">
|
||||
<div class="ams-tab-dot" style="background: #FF6600;"></div>
|
||||
<div class="ams-tab-dot" style="background: #00AA00;"></div>
|
||||
<div class="ams-tab-dot" style="background: #0066FF;"></div>
|
||||
<div class="ams-tab-dot" style="background: #FF0000;"></div>
|
||||
</div>
|
||||
<span class="ams-tab-label">AMS 2</span>
|
||||
</div>
|
||||
<div class="ams-tab">
|
||||
<div class="ams-tab-dots">
|
||||
<div class="ams-tab-dot" style="background: #fff; border-color: #ccc;"></div>
|
||||
<div class="ams-tab-dot" style="background: #333;"></div>
|
||||
<div class="ams-tab-dot" style="background: #666;"></div>
|
||||
<div class="ams-tab-dot" style="background: #999;"></div>
|
||||
</div>
|
||||
<span class="ams-tab-label">AMS 3</span>
|
||||
</div>
|
||||
<div class="ams-tab">
|
||||
<div class="ams-tab-dots">
|
||||
<div class="ams-tab-dot" style="background: #8844AA;"></div>
|
||||
</div>
|
||||
<span class="ams-tab-label">HT 1</span>
|
||||
</div>
|
||||
<div class="ams-tab">
|
||||
<div class="ams-tab-dots">
|
||||
<div class="ams-tab-dot" style="background: #44AA88;"></div>
|
||||
</div>
|
||||
<span class="ams-tab-label">HT 2</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- AMS Content Panel -->
|
||||
<div class="ams-content">
|
||||
<div class="ams-info-row">
|
||||
<div class="ams-humidity"><img src="icons/water.svg"> 18 %</div>
|
||||
<div class="ams-humidity"><span class="sun">☼</span></div>
|
||||
</div>
|
||||
|
||||
<div class="ams-main">
|
||||
<div class="ams-slots-container">
|
||||
<div class="slot-labels-row">
|
||||
<div class="slot-label-item"><div class="slot-label-badge">A1↓</div></div>
|
||||
<div class="slot-label-item"><div class="slot-label-badge">A2↓</div></div>
|
||||
<div class="slot-label-item"><div class="slot-label-badge">A3↓</div></div>
|
||||
<div class="slot-label-item"><div class="slot-label-badge">A4↓</div></div>
|
||||
</div>
|
||||
|
||||
<div class="ams-slots">
|
||||
<div class="ams-slot active">
|
||||
<div class="ams-slot-fill" style="background: #FFD700;">
|
||||
<span class="ams-slot-type dark">PLA</span>
|
||||
<div class="ams-slot-eye"><img src="icons/eye.svg"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ams-slot">
|
||||
<div class="ams-slot-fill" style="background: #1a1a1a;">
|
||||
<span class="ams-slot-type">PETG</span>
|
||||
<div class="ams-slot-eye invert"><img src="icons/eye.svg"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ams-slot">
|
||||
<div class="ams-slot-fill" style="background: #8B4513;">
|
||||
<span class="ams-slot-type">PETG</span>
|
||||
<div class="ams-slot-eye invert"><img src="icons/eye.svg"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ams-slot">
|
||||
<div class="ams-slot-fill" style="background: #222;">
|
||||
<span class="ams-slot-type">PLA</span>
|
||||
<div class="ams-slot-eye invert"><img src="icons/eye.svg"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ams-connectors">
|
||||
<div class="connector-lines">
|
||||
<div class="connector-line"><div class="vline"></div></div>
|
||||
<div class="connector-line"><div class="vline"></div></div>
|
||||
<div class="connector-line"><div class="vline"></div></div>
|
||||
<div class="connector-line"><div class="vline"></div></div>
|
||||
<div class="connector-hbar"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hub-row">
|
||||
<div class="hub-line-left"></div>
|
||||
<div class="hub-graphic">
|
||||
<div class="hub-port"></div>
|
||||
<div class="hub-port"></div>
|
||||
</div>
|
||||
<div class="hub-line-right"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ext-spool-section">
|
||||
<div class="ext-label">Ext</div>
|
||||
<div class="ext-content">
|
||||
<div style="display: flex; flex-direction: column; align-items: center;">
|
||||
<div class="ext-slot">
|
||||
<span class="question">?</span>
|
||||
<span class="angle">∠</span>
|
||||
</div>
|
||||
<div class="ext-connector"></div>
|
||||
</div>
|
||||
<div class="spool-holder-graphic">
|
||||
<img src="icons/single-extruder1.png">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ams-actions">
|
||||
<button class="auto-refill-btn">Auto-refill</button>
|
||||
<button class="ams-settings-btn"><img src="icons/ams-settings.svg"></button>
|
||||
<div class="ams-spacer"></div>
|
||||
<button class="ams-action-btn">Unload</button>
|
||||
<button class="ams-action-btn">Load</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,652 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>BambuTrack Control - v8</title>
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
|
||||
:root {
|
||||
--bg-main: #f5f5f5;
|
||||
--bg-white: #ffffff;
|
||||
--bg-light: #fafafa;
|
||||
--bg-panel: #f0f0f0;
|
||||
--bg-hover: #e8e8e8;
|
||||
--text-primary: #333333;
|
||||
--text-secondary: #666666;
|
||||
--text-muted: #999999;
|
||||
--border: #e0e0e0;
|
||||
--border-light: #eeeeee;
|
||||
--accent: #00ae42;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
background: var(--bg-main);
|
||||
color: var(--text-primary);
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.main-layout {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 280px;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
/* Left Panel */
|
||||
.left-panel {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: var(--bg-main);
|
||||
}
|
||||
|
||||
.camera-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 6px 10px;
|
||||
background: var(--bg-white);
|
||||
border-bottom: 1px solid var(--border);
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.camera-title {
|
||||
font-size: 12px;
|
||||
color: var(--text-primary);
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.icon-btn {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border: none;
|
||||
background: none;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.icon-btn:hover { background: var(--bg-hover); }
|
||||
.icon-btn img { width: 16px; height: 16px; opacity: 0.6; }
|
||||
|
||||
.camera-feed {
|
||||
flex: 1;
|
||||
background: #1a1a1a;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
/* Print Progress */
|
||||
.print-progress {
|
||||
background: var(--bg-white);
|
||||
border-top: 1px solid var(--border);
|
||||
padding: 10px 14px;
|
||||
}
|
||||
|
||||
.progress-label { font-size: 11px; color: var(--text-muted); margin-bottom: 6px; }
|
||||
.progress-row { display: flex; gap: 10px; align-items: center; }
|
||||
.progress-thumb {
|
||||
width: 44px; height: 44px;
|
||||
background: var(--bg-light);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 6px;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
}
|
||||
.progress-thumb img { width: 26px; opacity: 0.4; }
|
||||
.progress-info { flex: 1; }
|
||||
.progress-name { font-weight: 500; font-size: 12px; }
|
||||
.progress-status { color: var(--accent); font-size: 11px; margin: 2px 0 4px; }
|
||||
.progress-bar-bg { height: 3px; background: var(--border-light); border-radius: 2px; margin-bottom: 4px; }
|
||||
.progress-bar-fill { height: 100%; background: var(--accent); border-radius: 2px; width: 0%; }
|
||||
.progress-meta { font-size: 10px; color: var(--text-muted); }
|
||||
.progress-btns { display: flex; gap: 4px; }
|
||||
.progress-btn {
|
||||
width: 26px; height: 26px;
|
||||
border: 1px solid var(--border);
|
||||
background: var(--bg-white);
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 11px;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
.progress-btn:hover { background: var(--bg-hover); }
|
||||
|
||||
/* Right Panel */
|
||||
.right-panel {
|
||||
background: var(--bg-white);
|
||||
border-left: 1px solid var(--border);
|
||||
overflow-y: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.control-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 6px 8px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.control-title { font-size: 11px; margin-right: auto; }
|
||||
.header-btn {
|
||||
padding: 4px 8px;
|
||||
font-size: 10px;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
background: var(--accent);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.control-body { padding: 8px; flex: 1; overflow-y: auto; }
|
||||
|
||||
/* Temperature - Compact */
|
||||
.temp-section { margin-bottom: 8px; }
|
||||
.temp-row { display: flex; align-items: center; gap: 4px; padding: 1px 0; }
|
||||
.temp-icon { width: 14px; height: 14px; display: flex; align-items: center; justify-content: center; }
|
||||
.temp-icon img { width: 12px; opacity: 0.6; }
|
||||
.temp-badge {
|
||||
font-size: 8px; font-weight: 700; color: var(--accent);
|
||||
background: #e8f5e9; padding: 1px 3px; border-radius: 2px;
|
||||
}
|
||||
.temp-value { font-size: 13px; font-weight: 500; }
|
||||
.temp-target { font-size: 11px; color: var(--text-muted); }
|
||||
|
||||
/* Air Condition - Compact */
|
||||
.air-section {
|
||||
display: flex; align-items: center; gap: 6px;
|
||||
padding: 6px 0;
|
||||
border-top: 1px solid var(--border-light);
|
||||
border-bottom: 1px solid var(--border-light);
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.air-label { display: flex; align-items: center; gap: 3px; font-size: 10px; color: var(--text-secondary); }
|
||||
.air-label img { width: 12px; opacity: 0.5; }
|
||||
.air-item { display: flex; align-items: center; gap: 3px; padding: 3px 6px; background: var(--bg-light); border-radius: 4px; font-size: 10px; }
|
||||
.air-item img { width: 12px; opacity: 0.5; }
|
||||
.lamp-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--accent); }
|
||||
|
||||
/* Movement - Compact */
|
||||
.movement-section { display: flex; gap: 8px; margin-bottom: 10px; align-items: flex-start; }
|
||||
|
||||
.jog-pad { position: relative; width: 80px; height: 80px; }
|
||||
.jog-ring {
|
||||
width: 100%; height: 100%; border-radius: 50%;
|
||||
background: linear-gradient(135deg, #f8f8f8 0%, #e8e8e8 100%);
|
||||
border: 1px solid var(--border); position: relative;
|
||||
}
|
||||
.jog-label { position: absolute; font-size: 8px; color: var(--text-muted); }
|
||||
.jog-label.top { top: 4px; left: 50%; transform: translateX(-50%); }
|
||||
.jog-label.bottom { bottom: 4px; left: 50%; transform: translateX(-50%); }
|
||||
.jog-label.left { left: 4px; top: 50%; transform: translateY(-50%); }
|
||||
.jog-label.right { right: 4px; top: 50%; transform: translateY(-50%); }
|
||||
.jog-btn {
|
||||
position: absolute; width: 16px; height: 16px;
|
||||
background: var(--bg-light); border: 1px solid var(--border);
|
||||
border-radius: 3px; cursor: pointer; font-size: 7px; color: var(--text-muted);
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
}
|
||||
.jog-btn:hover { background: var(--bg-hover); }
|
||||
.jog-btn.up { top: 14px; left: 50%; transform: translateX(-50%); }
|
||||
.jog-btn.down { bottom: 14px; left: 50%; transform: translateX(-50%); }
|
||||
.jog-btn.left { left: 14px; top: 50%; transform: translateY(-50%); }
|
||||
.jog-btn.right { right: 14px; top: 50%; transform: translateY(-50%); }
|
||||
.jog-home {
|
||||
position: absolute; top: 50%; left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 24px; height: 24px; border-radius: 50%;
|
||||
background: var(--accent); border: none; cursor: pointer;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
}
|
||||
.jog-home img { width: 12px; filter: brightness(0) invert(1); }
|
||||
|
||||
.step-section { display: flex; flex-direction: column; gap: 2px; }
|
||||
.step-row { display: flex; gap: 3px; }
|
||||
.step-btn {
|
||||
padding: 3px 5px; background: var(--bg-light);
|
||||
border: 1px solid var(--border); border-radius: 3px;
|
||||
cursor: pointer; font-size: 8px; color: var(--text-secondary);
|
||||
}
|
||||
.step-btn.active { background: var(--bg-hover); border-color: var(--text-muted); }
|
||||
.step-label { font-size: 8px; color: var(--text-muted); text-align: center; padding: 1px 0; }
|
||||
|
||||
.extruder-section { display: flex; flex-direction: column; align-items: center; gap: 2px; }
|
||||
.nozzle-toggle { display: flex; border-radius: 3px; overflow: hidden; border: 1px solid var(--border); }
|
||||
.nozzle-toggle button {
|
||||
padding: 3px 8px; border: none; background: var(--bg-white);
|
||||
font-size: 8px; cursor: pointer; color: var(--text-secondary);
|
||||
}
|
||||
.nozzle-toggle button:first-child { border-right: 1px solid var(--border); }
|
||||
.nozzle-toggle button.active { background: var(--accent); color: white; }
|
||||
.extruder-graphic { height: 50px; }
|
||||
.extruder-graphic img { height: 100%; }
|
||||
.extruder-label { font-size: 8px; color: var(--text-muted); }
|
||||
.ext-controls { display: flex; flex-direction: column; gap: 2px; }
|
||||
.ext-btn {
|
||||
width: 20px; height: 20px; background: var(--bg-light);
|
||||
border: 1px solid var(--border); border-radius: 3px;
|
||||
cursor: pointer; font-size: 9px; color: var(--text-muted);
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
}
|
||||
|
||||
/* ========== AMS SECTION ========== */
|
||||
.ams-section { border-top: 1px solid var(--border-light); padding-top: 8px; }
|
||||
|
||||
/* Nozzle Filament Boxes */
|
||||
.nozzle-filament-row { display: flex; gap: 4px; margin-bottom: 6px; }
|
||||
.nozzle-filament-box {
|
||||
display: flex; align-items: center; gap: 3px;
|
||||
padding: 5px 6px; background: var(--bg-white);
|
||||
border: 2px solid var(--border); border-radius: 5px; cursor: pointer;
|
||||
}
|
||||
.nozzle-filament-box:hover { border-color: #ccc; }
|
||||
.nozzle-filament-box.active { border-color: var(--accent); }
|
||||
.filament-dots { display: flex; gap: 2px; }
|
||||
.f-dot { width: 12px; height: 12px; border-radius: 2px; border: 1px solid rgba(0,0,0,0.1); }
|
||||
|
||||
/* AMS Tabs */
|
||||
.ams-tabs { display: flex; gap: 3px; margin-bottom: 5px; flex-wrap: wrap; }
|
||||
.ams-tab {
|
||||
display: flex; align-items: center; gap: 2px;
|
||||
padding: 3px 5px; background: var(--bg-light);
|
||||
border: 2px solid transparent; border-radius: 4px;
|
||||
cursor: pointer; font-size: 8px; color: var(--text-secondary);
|
||||
}
|
||||
.ams-tab:hover { background: var(--bg-hover); }
|
||||
.ams-tab.active { border-color: var(--accent); }
|
||||
.ams-tab-dots { display: flex; gap: 1px; }
|
||||
.ams-tab-dot { width: 7px; height: 7px; border-radius: 1px; border: 1px solid rgba(0,0,0,0.08); }
|
||||
.ams-tab-label { font-size: 7px; color: var(--text-muted); }
|
||||
|
||||
/* AMS Content Panel */
|
||||
.ams-content { background: var(--bg-panel); border-radius: 8px; padding: 8px; }
|
||||
|
||||
/* AMS Info Row */
|
||||
.ams-info-row { display: flex; align-items: center; gap: 6px; margin-bottom: 5px; }
|
||||
.ams-humidity { display: flex; align-items: center; gap: 2px; font-size: 10px; color: var(--text-secondary); }
|
||||
.ams-humidity img { width: 11px; opacity: 0.5; }
|
||||
.ams-humidity .sun { font-size: 11px; color: #f5a623; }
|
||||
|
||||
/* AMS Main Area */
|
||||
.ams-main { display: flex; gap: 6px; }
|
||||
|
||||
/* AMS Slots Container */
|
||||
.ams-slots-container { flex: 1; }
|
||||
|
||||
/* Slot Labels Row */
|
||||
.slot-labels-row { display: flex; gap: 3px; margin-bottom: 2px; }
|
||||
.slot-label-item { width: 40px; display: flex; align-items: center; justify-content: center; }
|
||||
.slot-label-badge {
|
||||
display: flex; align-items: center;
|
||||
padding: 1px 3px;
|
||||
font-size: 7px; color: var(--text-muted);
|
||||
}
|
||||
|
||||
/* AMS Slots */
|
||||
.ams-slots { display: flex; gap: 3px; }
|
||||
.ams-slot {
|
||||
width: 40px; height: 56px;
|
||||
border-radius: 5px; overflow: hidden;
|
||||
cursor: pointer; border: 2px solid var(--border);
|
||||
}
|
||||
.ams-slot:hover { border-color: #bbb; }
|
||||
.ams-slot.active { border-color: #d4a84b; }
|
||||
.ams-slot-fill {
|
||||
width: 100%; height: 100%;
|
||||
display: flex; flex-direction: column;
|
||||
align-items: center; justify-content: flex-end;
|
||||
padding-bottom: 3px;
|
||||
}
|
||||
.ams-slot-type { font-size: 9px; font-weight: 600; color: white; text-shadow: 0 1px 2px rgba(0,0,0,0.3); margin-bottom: 1px; }
|
||||
.ams-slot-type.dark { color: #333; text-shadow: none; }
|
||||
.ams-slot-eye { width: 12px; height: 12px; }
|
||||
.ams-slot-eye img { width: 10px; height: 10px; opacity: 0.8; }
|
||||
.ams-slot-eye.invert img { filter: invert(1); }
|
||||
.ams-slot-empty {
|
||||
width: 100%; height: 100%;
|
||||
background: var(--bg-white);
|
||||
display: flex; flex-direction: column;
|
||||
align-items: center; justify-content: center;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
.ams-slot-empty .question { font-size: 12px; }
|
||||
.ams-slot-empty .angle { font-size: 9px; }
|
||||
|
||||
/* Connector Lines */
|
||||
.ams-connectors { display: flex; margin-top: 2px; }
|
||||
.connector-lines { display: flex; gap: 3px; position: relative; }
|
||||
.connector-line { width: 40px; display: flex; justify-content: center; }
|
||||
.connector-line .vline { width: 2px; height: 8px; background: #c0c0c0; }
|
||||
.connector-hbar { position: absolute; bottom: 0; left: 20px; right: 20px; height: 2px; background: #c0c0c0; }
|
||||
|
||||
/* Hub Row */
|
||||
.hub-row { display: flex; align-items: center; margin-top: -1px; }
|
||||
.hub-line-left { width: 78px; height: 2px; background: #c0c0c0; }
|
||||
.hub-graphic { display: flex; padding: 2px 3px; background: var(--bg-white); border: 1px solid var(--border); border-radius: 2px; }
|
||||
.hub-port { width: 5px; height: 8px; background: var(--accent); border-radius: 1px; margin: 0 1px; }
|
||||
.hub-line-right { width: 14px; height: 2px; background: #c0c0c0; }
|
||||
|
||||
/* External Spool Section */
|
||||
.ext-spool-section { display: flex; flex-direction: column; align-items: center; width: 80px; }
|
||||
.ext-label { font-size: 9px; color: var(--text-secondary); margin-bottom: 2px; }
|
||||
.ext-row { display: flex; align-items: flex-start; gap: 4px; }
|
||||
.ext-slot {
|
||||
width: 40px; height: 56px;
|
||||
background: var(--bg-white); border: 2px solid var(--border);
|
||||
border-radius: 5px; display: flex; flex-direction: column;
|
||||
align-items: center; justify-content: center;
|
||||
cursor: pointer; color: var(--text-muted);
|
||||
}
|
||||
.ext-slot:hover { border-color: #bbb; }
|
||||
.ext-slot .question { font-size: 12px; }
|
||||
.ext-slot .angle { font-size: 9px; }
|
||||
.ext-connector { width: 2px; height: 10px; background: #c0c0c0; margin: 2px auto 0; }
|
||||
.spool-holder { width: 36px; height: 56px; display: flex; align-items: center; justify-content: center; }
|
||||
.spool-holder img { width: 100%; height: 100%; object-fit: contain; }
|
||||
|
||||
/* AMS Actions */
|
||||
.ams-actions { display: flex; align-items: center; gap: 4px; margin-top: 6px; }
|
||||
.auto-refill-btn {
|
||||
display: flex; align-items: center; gap: 3px;
|
||||
padding: 5px 8px; background: var(--bg-white);
|
||||
border: 1px solid var(--border); border-radius: 4px;
|
||||
cursor: pointer; font-size: 10px; color: var(--text-secondary);
|
||||
}
|
||||
.auto-refill-btn:hover { background: var(--bg-hover); }
|
||||
.ams-settings-btn {
|
||||
width: 24px; height: 24px;
|
||||
background: var(--bg-white); border: 1px solid var(--border);
|
||||
border-radius: 4px; cursor: pointer;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
}
|
||||
.ams-settings-btn:hover { background: var(--bg-hover); }
|
||||
.ams-settings-btn img { width: 14px; opacity: 0.5; }
|
||||
.ams-spacer { flex: 1; }
|
||||
.ams-action-btn {
|
||||
padding: 5px 12px; border-radius: 4px;
|
||||
font-size: 10px; cursor: pointer; border: none;
|
||||
background: #e0e0e0; color: var(--text-secondary);
|
||||
}
|
||||
.ams-action-btn:hover { background: #d5d5d5; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="main-layout">
|
||||
<!-- Left Panel -->
|
||||
<div class="left-panel">
|
||||
<div class="camera-header">
|
||||
<span class="camera-title">Camera</span>
|
||||
<button class="icon-btn"><img src="icons/video-camera.svg"></button>
|
||||
<button class="icon-btn"><img src="icons/webcam.svg"></button>
|
||||
<button class="icon-btn"><img src="icons/settings.svg"></button>
|
||||
<button class="icon-btn"><img src="icons/reload.svg"></button>
|
||||
</div>
|
||||
<div class="camera-feed">Camera Feed</div>
|
||||
<div class="print-progress">
|
||||
<div class="progress-label">Printing Progress</div>
|
||||
<div class="progress-row">
|
||||
<div class="progress-thumb"><img src="icons/micro-sd.svg"></div>
|
||||
<div class="progress-info">
|
||||
<div class="progress-name">N/A</div>
|
||||
<div class="progress-status">N/A</div>
|
||||
<div class="progress-bar-bg"><div class="progress-bar-fill"></div></div>
|
||||
<div class="progress-meta">Layer: N/A Estimated finish time: N/A</div>
|
||||
</div>
|
||||
<div class="progress-btns">
|
||||
<button class="progress-btn">⌂</button>
|
||||
<button class="progress-btn">⏸</button>
|
||||
<button class="progress-btn">■</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Right Panel -->
|
||||
<div class="right-panel">
|
||||
<div class="control-header">
|
||||
<span class="control-title">Control</span>
|
||||
<button class="header-btn">Printer Parts</button>
|
||||
<button class="header-btn">Print Options</button>
|
||||
<button class="header-btn">Calibration</button>
|
||||
</div>
|
||||
|
||||
<div class="control-body">
|
||||
<!-- Temperature -->
|
||||
<div class="temp-section">
|
||||
<div class="temp-row">
|
||||
<div class="temp-icon"><img src="icons/hotend.svg"></div>
|
||||
<span class="temp-badge">L</span>
|
||||
<span class="temp-value">22</span>
|
||||
<span class="temp-target">/0 °C</span>
|
||||
</div>
|
||||
<div class="temp-row">
|
||||
<div class="temp-icon"><img src="icons/hotend.svg"></div>
|
||||
<span class="temp-badge">R</span>
|
||||
<span class="temp-value">21</span>
|
||||
<span class="temp-target">/0 °C</span>
|
||||
</div>
|
||||
<div class="temp-row">
|
||||
<div class="temp-icon"><img src="icons/heatbed.svg"></div>
|
||||
<span class="temp-value">21</span>
|
||||
<span class="temp-target">/0 °C</span>
|
||||
</div>
|
||||
<div class="temp-row">
|
||||
<div class="temp-icon"><img src="icons/chamber.svg"></div>
|
||||
<span class="temp-value">21</span>
|
||||
<span class="temp-target">/0 °C</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Air Condition -->
|
||||
<div class="air-section">
|
||||
<div class="air-label"><img src="icons/ventilation.svg"> Air Condition</div>
|
||||
<div class="air-item"><img src="icons/ventilation.svg"> 100%</div>
|
||||
<div class="air-item">Lamp <div class="lamp-dot"></div></div>
|
||||
</div>
|
||||
|
||||
<!-- Movement -->
|
||||
<div class="movement-section">
|
||||
<div class="jog-pad">
|
||||
<div class="jog-ring">
|
||||
<span class="jog-label top">Y</span>
|
||||
<span class="jog-label bottom">-Y</span>
|
||||
<span class="jog-label left">-X</span>
|
||||
<span class="jog-label right">X</span>
|
||||
<button class="jog-btn up">▲</button>
|
||||
<button class="jog-btn down">▼</button>
|
||||
<button class="jog-btn left">◀</button>
|
||||
<button class="jog-btn right">▶</button>
|
||||
<button class="jog-home"><img src="icons/home.svg"></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="step-section">
|
||||
<div class="step-row">
|
||||
<button class="step-btn">↑10</button>
|
||||
<button class="step-btn active">↑1</button>
|
||||
</div>
|
||||
<div class="step-label">Bed</div>
|
||||
<div class="step-row">
|
||||
<button class="step-btn">↓1</button>
|
||||
<button class="step-btn">↓10</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="extruder-section">
|
||||
<div class="nozzle-toggle">
|
||||
<button class="active">Left</button>
|
||||
<button>Right</button>
|
||||
</div>
|
||||
<div class="extruder-graphic"><img src="icons/dual-extruder.png"></div>
|
||||
<span class="extruder-label">Extruder</span>
|
||||
<div class="ext-controls">
|
||||
<button class="ext-btn">▲</button>
|
||||
<button class="ext-btn">▼</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- AMS Section -->
|
||||
<div class="ams-section">
|
||||
<!-- Nozzle Filament Boxes -->
|
||||
<div class="nozzle-filament-row">
|
||||
<div class="nozzle-filament-box active">
|
||||
<div class="filament-dots">
|
||||
<div class="f-dot" style="background: #FFD700;"></div>
|
||||
<div class="f-dot" style="background: #8B4513;"></div>
|
||||
<div class="f-dot" style="background: #1a1a1a;"></div>
|
||||
<div class="f-dot" style="background: #222;"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="nozzle-filament-box">
|
||||
<div class="filament-dots">
|
||||
<div class="f-dot" style="background: #FF6600;"></div>
|
||||
<div class="f-dot" style="background: #00AA00;"></div>
|
||||
<div class="f-dot" style="background: #0066FF;"></div>
|
||||
<div class="f-dot" style="background: #FF0000;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- AMS Tabs -->
|
||||
<div class="ams-tabs">
|
||||
<div class="ams-tab active">
|
||||
<div class="ams-tab-dots">
|
||||
<div class="ams-tab-dot" style="background: #FFD700;"></div>
|
||||
<div class="ams-tab-dot" style="background: #8B4513;"></div>
|
||||
<div class="ams-tab-dot" style="background: #1a1a1a;"></div>
|
||||
<div class="ams-tab-dot" style="background: #222;"></div>
|
||||
</div>
|
||||
<span class="ams-tab-label">AMS 1</span>
|
||||
</div>
|
||||
<div class="ams-tab">
|
||||
<div class="ams-tab-dots">
|
||||
<div class="ams-tab-dot" style="background: #FF6600;"></div>
|
||||
<div class="ams-tab-dot" style="background: #00AA00;"></div>
|
||||
<div class="ams-tab-dot" style="background: #0066FF;"></div>
|
||||
<div class="ams-tab-dot" style="background: #FF0000;"></div>
|
||||
</div>
|
||||
<span class="ams-tab-label">AMS 2</span>
|
||||
</div>
|
||||
<div class="ams-tab">
|
||||
<div class="ams-tab-dots">
|
||||
<div class="ams-tab-dot" style="background: #fff; border-color: #ccc;"></div>
|
||||
<div class="ams-tab-dot" style="background: #333;"></div>
|
||||
<div class="ams-tab-dot" style="background: #666;"></div>
|
||||
<div class="ams-tab-dot" style="background: #999;"></div>
|
||||
</div>
|
||||
<span class="ams-tab-label">AMS 3</span>
|
||||
</div>
|
||||
<div class="ams-tab">
|
||||
<div class="ams-tab-dots">
|
||||
<div class="ams-tab-dot" style="background: #8844AA;"></div>
|
||||
</div>
|
||||
<span class="ams-tab-label">HT 1</span>
|
||||
</div>
|
||||
<div class="ams-tab">
|
||||
<div class="ams-tab-dots">
|
||||
<div class="ams-tab-dot" style="background: #44AA88;"></div>
|
||||
</div>
|
||||
<span class="ams-tab-label">HT 2</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- AMS Content Panel -->
|
||||
<div class="ams-content">
|
||||
<div class="ams-info-row">
|
||||
<div class="ams-humidity"><img src="icons/water.svg"> 18 %</div>
|
||||
<div class="ams-humidity"><span class="sun">☼</span></div>
|
||||
</div>
|
||||
|
||||
<div class="ams-main">
|
||||
<div class="ams-slots-container">
|
||||
<div class="slot-labels-row">
|
||||
<div class="slot-label-item"><div class="slot-label-badge">A1↓</div></div>
|
||||
<div class="slot-label-item"><div class="slot-label-badge">A2↓</div></div>
|
||||
<div class="slot-label-item"><div class="slot-label-badge">A3↓</div></div>
|
||||
<div class="slot-label-item"><div class="slot-label-badge">A4↓</div></div>
|
||||
</div>
|
||||
|
||||
<div class="ams-slots">
|
||||
<div class="ams-slot active">
|
||||
<div class="ams-slot-fill" style="background: #FFD700;">
|
||||
<span class="ams-slot-type dark">PLA</span>
|
||||
<div class="ams-slot-eye"><img src="icons/eye.svg"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ams-slot">
|
||||
<div class="ams-slot-fill" style="background: #1a1a1a;">
|
||||
<span class="ams-slot-type">PETG</span>
|
||||
<div class="ams-slot-eye invert"><img src="icons/eye.svg"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ams-slot">
|
||||
<div class="ams-slot-fill" style="background: #8B4513;">
|
||||
<span class="ams-slot-type">PETG</span>
|
||||
<div class="ams-slot-eye invert"><img src="icons/eye.svg"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ams-slot">
|
||||
<div class="ams-slot-fill" style="background: #222;">
|
||||
<span class="ams-slot-type">PLA</span>
|
||||
<div class="ams-slot-eye invert"><img src="icons/eye.svg"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ams-connectors">
|
||||
<div class="connector-lines">
|
||||
<div class="connector-line"><div class="vline"></div></div>
|
||||
<div class="connector-line"><div class="vline"></div></div>
|
||||
<div class="connector-line"><div class="vline"></div></div>
|
||||
<div class="connector-line"><div class="vline"></div></div>
|
||||
<div class="connector-hbar"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hub-row">
|
||||
<div class="hub-line-left"></div>
|
||||
<div class="hub-graphic">
|
||||
<div class="hub-port"></div>
|
||||
<div class="hub-port"></div>
|
||||
</div>
|
||||
<div class="hub-line-right"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ext-spool-section">
|
||||
<div class="ext-label">Ext</div>
|
||||
<div class="ext-row">
|
||||
<div>
|
||||
<div class="ext-slot">
|
||||
<span class="question">?</span>
|
||||
<span class="angle">∠</span>
|
||||
</div>
|
||||
<div class="ext-connector"></div>
|
||||
</div>
|
||||
<div class="spool-holder">
|
||||
<img src="icons/single-extruder1.png">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ams-actions">
|
||||
<button class="auto-refill-btn">Auto-refill</button>
|
||||
<button class="ams-settings-btn"><img src="icons/ams-settings.svg"></button>
|
||||
<div class="ams-spacer"></div>
|
||||
<button class="ams-action-btn">Unload</button>
|
||||
<button class="ams-action-btn">Load</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,924 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>BambuTrack Control - v9</title>
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
|
||||
:root {
|
||||
--bg-main: #f5f5f5;
|
||||
--bg-white: #ffffff;
|
||||
--bg-light: #fafafa;
|
||||
--bg-panel: #f5f5f5;
|
||||
--bg-hover: #e8e8e8;
|
||||
--text-primary: #333333;
|
||||
--text-secondary: #666666;
|
||||
--text-muted: #999999;
|
||||
--border: #e0e0e0;
|
||||
--border-light: #eeeeee;
|
||||
--accent: #00ae42;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
background: var(--bg-main);
|
||||
color: var(--text-primary);
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.main-layout {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 380px;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
/* Left Panel - Camera */
|
||||
.left-panel {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: var(--bg-main);
|
||||
}
|
||||
|
||||
.camera-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 8px 12px;
|
||||
background: var(--bg-white);
|
||||
border-bottom: 1px solid var(--border);
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.camera-title {
|
||||
font-size: 13px;
|
||||
color: var(--text-primary);
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.icon-btn {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
border: none;
|
||||
background: none;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.icon-btn:hover { background: var(--bg-hover); }
|
||||
.icon-btn img { width: 18px; height: 18px; opacity: 0.6; }
|
||||
|
||||
.camera-feed {
|
||||
flex: 1;
|
||||
background: #1a1a1a;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #555;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* Status bar */
|
||||
.status-bar {
|
||||
background: var(--accent);
|
||||
padding: 4px 12px;
|
||||
}
|
||||
|
||||
/* Print Progress */
|
||||
.print-progress {
|
||||
background: var(--bg-white);
|
||||
padding: 16px 20px;
|
||||
}
|
||||
|
||||
.progress-label { font-size: 12px; color: var(--text-muted); margin-bottom: 12px; }
|
||||
.progress-row { display: flex; gap: 14px; align-items: center; }
|
||||
.progress-thumb {
|
||||
width: 60px; height: 60px;
|
||||
background: var(--bg-light);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
flex-direction: column;
|
||||
font-size: 10px;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
.progress-thumb-icon { font-size: 20px; margin-bottom: 2px; }
|
||||
.progress-info { flex: 1; }
|
||||
.progress-name { font-weight: 500; font-size: 14px; margin-bottom: 2px; }
|
||||
.progress-status { color: var(--accent); font-size: 13px; margin-bottom: 8px; }
|
||||
.progress-bar-bg { height: 4px; background: var(--border-light); border-radius: 2px; margin-bottom: 8px; }
|
||||
.progress-bar-fill { height: 100%; background: var(--accent); border-radius: 2px; width: 0%; }
|
||||
.progress-meta { font-size: 12px; color: var(--text-muted); margin-bottom: 4px; }
|
||||
.progress-btns { display: flex; gap: 6px; }
|
||||
.progress-btn {
|
||||
width: 32px; height: 32px;
|
||||
border: 1px solid var(--border);
|
||||
background: var(--bg-white);
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
.progress-btn:hover { background: var(--bg-hover); }
|
||||
|
||||
/* Right Panel - Control */
|
||||
.right-panel {
|
||||
background: var(--bg-white);
|
||||
border-left: 1px solid var(--border);
|
||||
overflow-y: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.control-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px 14px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.control-title { font-size: 13px; margin-right: auto; color: var(--text-secondary); }
|
||||
.header-btn {
|
||||
padding: 6px 14px;
|
||||
font-size: 12px;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
background: var(--accent);
|
||||
color: white;
|
||||
}
|
||||
.header-btn:hover { background: #009938; }
|
||||
|
||||
.control-body { padding: 14px; flex: 1; overflow-y: auto; }
|
||||
|
||||
/* Top Section: Temp + Movement side by side */
|
||||
.top-section {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
/* Temperature Column */
|
||||
.temp-column { flex: 0 0 auto; }
|
||||
|
||||
.temp-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
.temp-icon { width: 18px; height: 18px; display: flex; align-items: center; justify-content: center; }
|
||||
.temp-icon img { width: 16px; opacity: 0.5; }
|
||||
|
||||
.temp-badge {
|
||||
font-size: 10px;
|
||||
font-weight: 600;
|
||||
color: var(--accent);
|
||||
background: #e8f5e9;
|
||||
padding: 2px 6px;
|
||||
border-radius: 4px;
|
||||
min-width: 16px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.temp-value { font-size: 16px; font-weight: 500; }
|
||||
.temp-target { font-size: 14px; color: var(--text-muted); }
|
||||
|
||||
/* Air Condition */
|
||||
.air-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 10px 0;
|
||||
margin-top: 8px;
|
||||
border-top: 1px solid var(--border-light);
|
||||
}
|
||||
|
||||
.air-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
font-size: 12px;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.air-label img { width: 16px; opacity: 0.5; }
|
||||
|
||||
.air-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
font-size: 12px;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.air-item img { width: 16px; opacity: 0.5; }
|
||||
.lamp-label { display: flex; align-items: center; gap: 5px; }
|
||||
.lamp-dot { width: 12px; height: 12px; border-radius: 50%; background: var(--accent); }
|
||||
|
||||
/* Movement Column */
|
||||
.movement-column {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.nozzle-toggle {
|
||||
display: flex;
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--border);
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.nozzle-toggle button {
|
||||
padding: 6px 18px;
|
||||
border: none;
|
||||
background: var(--bg-white);
|
||||
font-size: 12px;
|
||||
cursor: pointer;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.nozzle-toggle button:first-child { border-right: 1px solid var(--border); }
|
||||
.nozzle-toggle button.active { background: var(--accent); color: white; }
|
||||
|
||||
.movement-row {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.jog-section { display: flex; flex-direction: column; align-items: center; }
|
||||
|
||||
.jog-pad {
|
||||
position: relative;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.jog-ring {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(135deg, #f8f8f8 0%, #ebebeb 100%);
|
||||
border: 1px solid var(--border);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.jog-label {
|
||||
position: absolute;
|
||||
font-size: 10px;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.jog-label.top { top: 6px; left: 50%; transform: translateX(-50%); }
|
||||
.jog-label.bottom { bottom: 6px; left: 50%; transform: translateX(-50%); }
|
||||
.jog-label.left { left: 6px; top: 50%; transform: translateY(-50%); }
|
||||
.jog-label.right { right: 6px; top: 50%; transform: translateY(-50%); }
|
||||
|
||||
.jog-btn {
|
||||
position: absolute;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background: var(--bg-white);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 9px;
|
||||
color: var(--text-muted);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.jog-btn:hover { background: var(--bg-hover); }
|
||||
.jog-btn.up { top: 16px; left: 50%; transform: translateX(-50%); }
|
||||
.jog-btn.down { bottom: 16px; left: 50%; transform: translateX(-50%); }
|
||||
.jog-btn.left { left: 16px; top: 50%; transform: translateY(-50%); }
|
||||
.jog-btn.right { right: 16px; top: 50%; transform: translateY(-50%); }
|
||||
|
||||
.jog-home {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 50%;
|
||||
background: var(--accent);
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.jog-home:hover { background: #009938; }
|
||||
.jog-home img { width: 16px; filter: brightness(0) invert(1); }
|
||||
|
||||
/* Bed Controls */
|
||||
.bed-controls {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.bed-btn {
|
||||
padding: 6px 10px;
|
||||
background: var(--bg-white);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
font-size: 11px;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.bed-btn:hover { background: var(--bg-hover); }
|
||||
.bed-label { font-size: 11px; color: var(--text-muted); padding: 0 4px; }
|
||||
|
||||
/* Extruder Section */
|
||||
.extruder-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.extruder-btn {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
background: var(--bg-white);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
color: var(--text-muted);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.extruder-btn:hover { background: var(--bg-hover); }
|
||||
|
||||
.extruder-graphic {
|
||||
height: 60px;
|
||||
margin: 4px 0;
|
||||
}
|
||||
|
||||
.extruder-graphic img { height: 100%; }
|
||||
.extruder-label { font-size: 11px; color: var(--text-muted); }
|
||||
|
||||
/* ========== FILAMENT BOXES ========== */
|
||||
.filament-boxes {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
margin-bottom: 12px;
|
||||
padding-bottom: 12px;
|
||||
border-bottom: 1px solid var(--border-light);
|
||||
}
|
||||
|
||||
.filament-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
padding: 8px 10px;
|
||||
background: var(--bg-white);
|
||||
border: 2px solid var(--border);
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.filament-box:hover { border-color: #ccc; }
|
||||
.filament-box.active { border-color: var(--accent); }
|
||||
|
||||
.filament-dots { display: flex; gap: 3px; }
|
||||
|
||||
.f-dot {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.f-dot.empty {
|
||||
background: #e8e8e8 !important;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.f-dot-sep {
|
||||
width: 1px;
|
||||
height: 16px;
|
||||
background: #ccc;
|
||||
margin: 0 2px;
|
||||
}
|
||||
|
||||
.filament-count {
|
||||
font-size: 12px;
|
||||
color: var(--text-muted);
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
/* ========== AMS SECTION ========== */
|
||||
.ams-section {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.ams-unit {
|
||||
flex: 1;
|
||||
background: var(--bg-panel);
|
||||
border-radius: 12px;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
/* AMS Header */
|
||||
.ams-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.ams-humidity {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
font-size: 13px;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.ams-humidity img { width: 14px; opacity: 0.5; }
|
||||
.ams-humidity .sun { font-size: 14px; color: #f5a623; }
|
||||
|
||||
/* Slot Labels */
|
||||
.slot-labels {
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.slot-label {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
font-size: 11px;
|
||||
color: var(--text-muted);
|
||||
padding: 2px 0;
|
||||
background: var(--bg-white);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
/* AMS Slots */
|
||||
.ams-slots {
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.ams-slot {
|
||||
flex: 1;
|
||||
height: 70px;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
border: 2px solid var(--border);
|
||||
background: var(--bg-white);
|
||||
}
|
||||
|
||||
.ams-slot:hover { border-color: #bbb; }
|
||||
.ams-slot.active { border-color: #d4a84b; }
|
||||
|
||||
.ams-slot-fill {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
padding-bottom: 6px;
|
||||
}
|
||||
|
||||
.ams-slot-type {
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
color: white;
|
||||
text-shadow: 0 1px 2px rgba(0,0,0,0.3);
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.ams-slot-type.dark { color: #333; text-shadow: none; }
|
||||
|
||||
.ams-slot-eye { width: 16px; height: 16px; }
|
||||
.ams-slot-eye img { width: 14px; height: 14px; opacity: 0.8; }
|
||||
.ams-slot-eye.invert img { filter: invert(1); }
|
||||
|
||||
.ams-slot-empty {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: var(--text-muted);
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
/* Connector Lines */
|
||||
.ams-connectors {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.connector-group {
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
position: relative;
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
.connector-line {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.connector-line .vline {
|
||||
width: 2px;
|
||||
height: 12px;
|
||||
background: #c0c0c0;
|
||||
}
|
||||
|
||||
.connector-hbar {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 20px;
|
||||
right: 20px;
|
||||
height: 2px;
|
||||
background: #c0c0c0;
|
||||
}
|
||||
|
||||
/* AMS Actions */
|
||||
.ams-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-top: 12px;
|
||||
padding-top: 12px;
|
||||
border-top: 1px solid var(--border-light);
|
||||
}
|
||||
|
||||
.auto-refill-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 8px 14px;
|
||||
background: var(--bg-white);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.auto-refill-btn:hover { background: var(--bg-hover); }
|
||||
|
||||
.ams-settings-btn {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
background: var(--bg-white);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.ams-settings-btn:hover { background: var(--bg-hover); }
|
||||
.ams-settings-btn img { width: 18px; opacity: 0.5; }
|
||||
|
||||
/* Hub */
|
||||
.hub-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.hub-line { width: 30px; height: 2px; background: #c0c0c0; }
|
||||
|
||||
.hub-graphic {
|
||||
display: flex;
|
||||
padding: 4px 6px;
|
||||
background: var(--bg-white);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.hub-port {
|
||||
width: 8px;
|
||||
height: 12px;
|
||||
background: var(--accent);
|
||||
border-radius: 2px;
|
||||
margin: 0 2px;
|
||||
}
|
||||
|
||||
.ams-spacer { flex: 1; }
|
||||
|
||||
.ams-action-btn {
|
||||
padding: 8px 20px;
|
||||
border-radius: 8px;
|
||||
font-size: 12px;
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
background: #e8e8e8;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.ams-action-btn:hover { background: #ddd; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="main-layout">
|
||||
<!-- Left Panel - Camera -->
|
||||
<div class="left-panel">
|
||||
<div class="camera-header">
|
||||
<span class="camera-title">Camera</span>
|
||||
<button class="icon-btn"><img src="icons/video-camera.svg"></button>
|
||||
<button class="icon-btn"><img src="icons/webcam.svg"></button>
|
||||
<button class="icon-btn"><img src="icons/settings.svg"></button>
|
||||
<button class="icon-btn"><img src="icons/reload.svg"></button>
|
||||
</div>
|
||||
<div class="camera-feed">Camera Feed</div>
|
||||
<div class="status-bar"></div>
|
||||
<div class="print-progress">
|
||||
<div class="progress-label">Printing Progress</div>
|
||||
<div class="progress-row">
|
||||
<div class="progress-thumb">
|
||||
<span class="progress-thumb-icon">🗺</span>
|
||||
Bambu<br>Lab
|
||||
</div>
|
||||
<div class="progress-info">
|
||||
<div class="progress-name">N/A</div>
|
||||
<div class="progress-status">N/A</div>
|
||||
<div class="progress-bar-bg"><div class="progress-bar-fill"></div></div>
|
||||
<div class="progress-meta">Layer: N/A N/A</div>
|
||||
<div class="progress-meta">Estimated finish time: N/A</div>
|
||||
</div>
|
||||
<div class="progress-btns">
|
||||
<button class="progress-btn">⌂</button>
|
||||
<button class="progress-btn">⏸</button>
|
||||
<button class="progress-btn">■</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Right Panel - Control -->
|
||||
<div class="right-panel">
|
||||
<div class="control-header">
|
||||
<span class="control-title">Control</span>
|
||||
<button class="header-btn">Printer Parts</button>
|
||||
<button class="header-btn">Print Options</button>
|
||||
<button class="header-btn">Calibration</button>
|
||||
</div>
|
||||
|
||||
<div class="control-body">
|
||||
<!-- Top Section: Temp + Movement side by side -->
|
||||
<div class="top-section">
|
||||
<!-- Temperature Column -->
|
||||
<div class="temp-column">
|
||||
<div class="temp-row">
|
||||
<div class="temp-icon"><img src="icons/hotend.svg"></div>
|
||||
<span class="temp-badge">L</span>
|
||||
<span class="temp-value">24</span>
|
||||
<span class="temp-target">/0 °C</span>
|
||||
</div>
|
||||
<div class="temp-row">
|
||||
<div class="temp-icon"><img src="icons/hotend.svg"></div>
|
||||
<span class="temp-badge">R</span>
|
||||
<span class="temp-value">23</span>
|
||||
<span class="temp-target">/0 °C</span>
|
||||
</div>
|
||||
<div class="temp-row">
|
||||
<div class="temp-icon"><img src="icons/heatbed.svg"></div>
|
||||
<span class="temp-value">23</span>
|
||||
<span class="temp-target">/0 °C</span>
|
||||
</div>
|
||||
<div class="temp-row">
|
||||
<div class="temp-icon"><img src="icons/chamber.svg"></div>
|
||||
<span class="temp-value">23</span>
|
||||
<span class="temp-target">/0 °C</span>
|
||||
</div>
|
||||
|
||||
<!-- Air Condition -->
|
||||
<div class="air-section">
|
||||
<div class="air-label"><img src="icons/ventilation.svg"> Air Condition</div>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: 12px; margin-top: 6px;">
|
||||
<div class="air-item"><img src="icons/ventilation.svg"> 100%</div>
|
||||
<div class="lamp-label">Lamp <div class="lamp-dot"></div></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Movement Column -->
|
||||
<div class="movement-column">
|
||||
<div class="nozzle-toggle">
|
||||
<button class="active">Left</button>
|
||||
<button>Right</button>
|
||||
</div>
|
||||
|
||||
<div class="movement-row">
|
||||
<div class="jog-section">
|
||||
<div class="jog-pad">
|
||||
<div class="jog-ring">
|
||||
<span class="jog-label top">Y</span>
|
||||
<span class="jog-label bottom">-Y</span>
|
||||
<span class="jog-label left">-X</span>
|
||||
<span class="jog-label right">X</span>
|
||||
<button class="jog-btn up">▲</button>
|
||||
<button class="jog-btn down">▼</button>
|
||||
<button class="jog-btn left">◀</button>
|
||||
<button class="jog-btn right">▶</button>
|
||||
<button class="jog-home"><img src="icons/home.svg"></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bed-controls">
|
||||
<button class="bed-btn">↑10</button>
|
||||
<button class="bed-btn">↑1</button>
|
||||
<span class="bed-label">Bed</span>
|
||||
<button class="bed-btn">↓1</button>
|
||||
<button class="bed-btn">↓10</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="extruder-section">
|
||||
<button class="extruder-btn">▲</button>
|
||||
<div class="extruder-graphic"><img src="icons/dual-extruder.png"></div>
|
||||
<button class="extruder-btn">▼</button>
|
||||
<span class="extruder-label">Extruder</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Filament Assignment Boxes -->
|
||||
<div class="filament-boxes">
|
||||
<div class="filament-box active">
|
||||
<div class="filament-dots">
|
||||
<div class="f-dot" style="background: #FFD700;"></div>
|
||||
<div class="f-dot" style="background: #333;"></div>
|
||||
<div class="f-dot" style="background: #333;"></div>
|
||||
<div class="f-dot" style="background: #333;"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="filament-box">
|
||||
<div class="filament-dots">
|
||||
<div class="f-dot" style="background: #333;"></div>
|
||||
<div class="f-dot" style="background: #333;"></div>
|
||||
<div class="f-dot-sep"></div>
|
||||
<div class="f-dot" style="background: #FF3366;"></div>
|
||||
</div>
|
||||
<span class="filament-count">0</span>
|
||||
</div>
|
||||
<div class="filament-box">
|
||||
<div class="filament-dots">
|
||||
<div class="f-dot empty"></div>
|
||||
<div class="f-dot empty"></div>
|
||||
<div class="f-dot empty"></div>
|
||||
</div>
|
||||
<span class="filament-count">0</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- AMS Section - Two units side by side -->
|
||||
<div class="ams-section">
|
||||
<!-- AMS Unit 1 -->
|
||||
<div class="ams-unit">
|
||||
<div class="ams-header">
|
||||
<div class="ams-humidity"><img src="icons/water.svg"> 17 %</div>
|
||||
<div class="ams-humidity"><span class="sun">☀</span></div>
|
||||
</div>
|
||||
<div class="slot-labels">
|
||||
<div class="slot-label">A1↓</div>
|
||||
<div class="slot-label">A2↓</div>
|
||||
<div class="slot-label">A3↓</div>
|
||||
<div class="slot-label">A4↓</div>
|
||||
</div>
|
||||
<div class="ams-slots">
|
||||
<div class="ams-slot active">
|
||||
<div class="ams-slot-fill" style="background: #FFD700;">
|
||||
<span class="ams-slot-type dark">PLA</span>
|
||||
<div class="ams-slot-eye"><img src="icons/eye.svg"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ams-slot">
|
||||
<div class="ams-slot-fill" style="background: #333;">
|
||||
<span class="ams-slot-type">PETG</span>
|
||||
<div class="ams-slot-eye invert"><img src="icons/eye.svg"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ams-slot">
|
||||
<div class="ams-slot-fill" style="background: #8B4513;">
|
||||
<span class="ams-slot-type">PETG</span>
|
||||
<div class="ams-slot-eye invert"><img src="icons/eye.svg"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ams-slot">
|
||||
<div class="ams-slot-fill" style="background: #666;">
|
||||
<span class="ams-slot-type">PLA</span>
|
||||
<div class="ams-slot-eye invert"><img src="icons/eye.svg"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ams-connectors">
|
||||
<div class="connector-group">
|
||||
<div class="connector-line"><div class="vline"></div></div>
|
||||
<div class="connector-line"><div class="vline"></div></div>
|
||||
<div class="connector-line"><div class="vline"></div></div>
|
||||
<div class="connector-line"><div class="vline"></div></div>
|
||||
<div class="connector-hbar"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- AMS Unit 2 -->
|
||||
<div class="ams-unit">
|
||||
<div class="ams-header">
|
||||
<div class="ams-humidity"><img src="icons/water.svg"> 14 %</div>
|
||||
<div class="ams-humidity"><span class="sun">☀</span></div>
|
||||
</div>
|
||||
<div class="slot-labels">
|
||||
<div class="slot-label">B1↓</div>
|
||||
<div class="slot-label">B2↓</div>
|
||||
<div class="slot-label">B3↓</div>
|
||||
<div class="slot-label">B4↓</div>
|
||||
</div>
|
||||
<div class="ams-slots">
|
||||
<div class="ams-slot">
|
||||
<div class="ams-slot-fill" style="background: #888;">
|
||||
<span class="ams-slot-type">PLA</span>
|
||||
<div class="ams-slot-eye invert"><img src="icons/eye.svg"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ams-slot">
|
||||
<div class="ams-slot-fill" style="background: #666;">
|
||||
<span class="ams-slot-type">PETG</span>
|
||||
<div class="ams-slot-eye invert"><img src="icons/eye.svg"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ams-slot">
|
||||
<div class="ams-slot-fill" style="background: #888;">
|
||||
<span class="ams-slot-type">PLA</span>
|
||||
<div class="ams-slot-eye invert"><img src="icons/eye.svg"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ams-slot">
|
||||
<div class="ams-slot-fill" style="background: #aaa;">
|
||||
<span class="ams-slot-type dark">Sup.PLA</span>
|
||||
<div class="ams-slot-eye"><img src="icons/eye.svg"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ams-connectors">
|
||||
<div class="connector-group">
|
||||
<div class="connector-line"><div class="vline"></div></div>
|
||||
<div class="connector-line"><div class="vline"></div></div>
|
||||
<div class="connector-line"><div class="vline"></div></div>
|
||||
<div class="connector-line"><div class="vline"></div></div>
|
||||
<div class="connector-hbar"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- AMS Actions -->
|
||||
<div class="ams-actions">
|
||||
<button class="auto-refill-btn">Auto-refill</button>
|
||||
<button class="ams-settings-btn"><img src="icons/ams-settings.svg"></button>
|
||||
<div class="hub-section">
|
||||
<div class="hub-line"></div>
|
||||
<div class="hub-graphic">
|
||||
<div class="hub-port"></div>
|
||||
<div class="hub-port"></div>
|
||||
</div>
|
||||
<div class="hub-line"></div>
|
||||
</div>
|
||||
<div class="ams-spacer"></div>
|
||||
<button class="ams-action-btn">Unload</button>
|
||||
<button class="ams-action-btn">Load</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 4.2 KiB |
@@ -0,0 +1 @@
|
||||
<svg fill="none" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><g clip-rule="evenodd" fill="#000" fill-rule="evenodd"><path d="m2.25 6c0-.41421.33579-.75.75-.75h3.5c.41421 0 .75.33579.75.75s-.33579.75-.75.75h-3.5c-.41421 0-.75-.33579-.75-.75zm8.5 0c0-.41421.3358-.75.75-.75h9.5c.4142 0 .75.33579.75.75s-.3358.75-.75.75h-9.5c-.4142 0-.75-.33579-.75-.75z"/><path d="m9 4.25c-.9665 0-1.75.7835-1.75 1.75s.7835 1.75 1.75 1.75 1.75-.7835 1.75-1.75-.7835-1.75-1.75-1.75zm-3.25 1.75c0-1.79493 1.45507-3.25 3.25-3.25 1.7949 0 3.25 1.45507 3.25 3.25s-1.4551 3.25-3.25 3.25c-1.79493 0-3.25-1.45507-3.25-3.25z"/><path d="m21.75 12c0-.4142-.3358-.75-.75-.75h-2c-.4142 0-.75.3358-.75.75s.3358.75.75.75h2c.4142 0 .75-.3358.75-.75zm-7 0c0-.4142-.3358-.75-.75-.75h-5c-.41421 0-.75.3358-.75.75s.33579.75.75.75h5c.4142 0 .75-.3358.75-.75zm-9 0c0-.4142-.33579-.75-.75-.75h-2c-.41421 0-.75.3358-.75.75s.33579.75.75.75h2c.41421 0 .75-.3358.75-.75z"/><path d="m16.5 10.25c.9665 0 1.75.7835 1.75 1.75s-.7835 1.75-1.75 1.75-1.75-.7835-1.75-1.75.7835-1.75 1.75-1.75zm3.25 1.75c0-1.7949-1.4551-3.25-3.25-3.25s-3.25 1.4551-3.25 3.25 1.4551 3.25 3.25 3.25 3.25-1.4551 3.25-3.25z"/><path d="m2.25 18c0-.4142.33579-.75.75-.75h5c.41421 0 .75.3358.75.75s-.33579.75-.75.75h-5c-.41421 0-.75-.3358-.75-.75zm10 0c0-.4142.3358-.75.75-.75h8c.4142 0 .75.3358.75.75s-.3358.75-.75.75h-8c-.4142 0-.75-.3358-.75-.75z"/><path d="m10.5 16.25c-.9665 0-1.75.7835-1.75 1.75s.7835 1.75 1.75 1.75 1.75-.7835 1.75-1.75-.7835-1.75-1.75-1.75zm-3.25 1.75c0-1.7949 1.45507-3.25 3.25-3.25 1.7949 0 3.25 1.4551 3.25 3.25s-1.4551 3.25-3.25 3.25c-1.79493 0-3.25-1.4551-3.25-3.25z"/></g></svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 6.3 KiB |
@@ -0,0 +1 @@
|
||||
<svg id="Capa_1" enable-background="new 0 0 512 512" height="512" viewBox="0 0 512 512" width="512" xmlns="http://www.w3.org/2000/svg"><g><g><path d="m422.995 217.87c4.143 0 7.5-3.357 7.5-7.5v-192.87c0-9.649-7.851-17.5-17.5-17.5h-313.99c-9.649 0-17.5 7.851-17.5 17.5v477c0 9.649 7.851 17.5 17.5 17.5h313.99c9.649 0 17.5-7.851 17.5-17.5v-248.203c0-4.143-3.357-7.5-7.5-7.5s-7.5 3.357-7.5 7.5v52.811h-16.639v-117.615h16.639v28.877c0 4.143 3.358 7.5 7.5 7.5zm-294.851-144.77h33.028c4.143 0 7.5-3.357 7.5-7.5s-3.357-7.5-7.5-7.5h-33.028v-43.1h255.713v43.1h-186.759c-4.143 0-7.5 3.357-7.5 7.5s3.357 7.5 7.5 7.5h186.759v22.158h-255.713zm-29.139-58.1h14.139v151.493h-16.639v-148.993c0-1.379 1.121-2.5 2.5-2.5zm-2.5 447v-15.278h16.639v15.278zm0-280.507h16.639v117.614h-16.639zm316.49 315.507h-313.99c-1.379 0-2.5-1.121-2.5-2.5v-17.5h318.99v17.5c0 1.379-1.121 2.5-2.5 2.5zm2.5-35h-16.639v-15.278h16.639zm0-147.893v117.614h-16.639v-117.614zm-31.639-15h-3.586c-4.143 0-7.5 3.357-7.5 7.5s3.357 7.5 7.5 7.5h3.586v117.614h-3.586c-4.143 0-7.5 3.357-7.5 7.5s3.357 7.5 7.5 7.5h3.586v15.279h-255.712v-15.278h3.586c4.143 0 7.5-3.357 7.5-7.5s-3.357-7.5-7.5-7.5h-3.586v-53.092c0-4.143-3.357-7.5-7.5-7.5s-7.5 3.357-7.5 7.5v53.092h-16.639v-117.615h16.639v28.596c0 4.143 3.357 7.5 7.5 7.5s7.5-3.357 7.5-7.5v-28.596h3.586c4.143 0 7.5-3.357 7.5-7.5s-3.357-7.5-7.5-7.5h-3.586v-117.614h3.586c4.143 0 7.5-3.357 7.5-7.5s-3.357-7.5-7.5-7.5h-3.586v-56.235h255.713v56.235h-3.586c-4.143 0-7.5 3.357-7.5 7.5s3.357 7.5 7.5 7.5h3.586v117.614zm15-132.614v-151.493h14.139c1.379 0 2.5 1.121 2.5 2.5v148.993z"/><path d="m256 129.22c-17.53 0-31.793 14.263-31.793 31.794 0 17.53 14.263 31.793 31.793 31.793s31.793-14.263 31.793-31.793c0-17.532-14.263-31.794-31.793-31.794zm0 48.587c-9.26 0-16.793-7.533-16.793-16.793s7.533-16.794 16.793-16.794 16.793 7.534 16.793 16.794-7.533 16.793-16.793 16.793z"/><path d="m201.313 419.229c-1.407-1.406-3.314-2.196-5.304-2.196s-3.897.79-5.304 2.197l-10.465 10.466c-2.929 2.929-2.929 7.678.001 10.606 1.464 1.464 3.384 2.196 5.303 2.196s3.839-.732 5.304-2.197l5.161-5.162 5.162 5.163c2.93 2.928 7.678 2.928 10.607 0 2.929-2.93 2.929-7.678 0-10.607z"/><path d="m261.304 419.23c-1.406-1.407-3.314-2.197-5.304-2.197s-3.897.79-5.304 2.197l-10.465 10.466c-2.929 2.929-2.929 7.678.001 10.606 2.928 2.928 7.677 2.929 10.606-.001l5.161-5.161 5.161 5.161c1.465 1.465 3.384 2.197 5.304 2.197 1.919 0 3.839-.732 5.303-2.196 2.93-2.929 2.93-7.678.001-10.606z"/><path d="m321.295 419.23c-1.406-1.407-3.314-2.197-5.304-2.197s-3.896.79-5.304 2.196l-10.466 10.466c-2.929 2.93-2.929 7.678 0 10.607 2.93 2.928 7.678 2.928 10.607 0l5.162-5.163 5.161 5.162c1.465 1.465 3.384 2.197 5.304 2.197 1.919 0 3.839-.732 5.303-2.196 2.93-2.929 2.93-7.678.001-10.606z"/><path d="m213.252 44.05h85.496c4.143 0 7.5-3.357 7.5-7.5s-3.357-7.5-7.5-7.5h-85.496c-4.143 0-7.5 3.357-7.5 7.5s3.357 7.5 7.5 7.5z"/></g></g></svg>
|
||||
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 6.1 KiB |
@@ -0,0 +1,51 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 511.999 511.999" style="enable-background:new 0 0 511.999 511.999;" xml:space="preserve">
|
||||
<g>
|
||||
<g>
|
||||
<path d="M508.745,246.041c-4.574-6.257-113.557-153.206-252.748-153.206S7.818,239.784,3.249,246.035
|
||||
c-4.332,5.936-4.332,13.987,0,19.923c4.569,6.257,113.557,153.206,252.748,153.206s248.174-146.95,252.748-153.201
|
||||
C513.083,260.028,513.083,251.971,508.745,246.041z M255.997,385.406c-102.529,0-191.33-97.533-217.617-129.418
|
||||
c26.253-31.913,114.868-129.395,217.617-129.395c102.524,0,191.319,97.516,217.617,129.418
|
||||
C447.361,287.923,358.746,385.406,255.997,385.406z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path d="M255.997,154.725c-55.842,0-101.275,45.433-101.275,101.275s45.433,101.275,101.275,101.275
|
||||
s101.275-45.433,101.275-101.275S311.839,154.725,255.997,154.725z M255.997,323.516c-37.23,0-67.516-30.287-67.516-67.516
|
||||
s30.287-67.516,67.516-67.516s67.516,30.287,67.516,67.516S293.227,323.516,255.997,323.516z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
@@ -0,0 +1 @@
|
||||
<svg id="Layer_1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" data-name="Layer 1"><g fill="rgb(0,0,0)"><path d="m6.3 3.9c.54-.4 1.2-.9 1.2-1.9 0-.28-.22-.5-.5-.5s-.5.22-.5.5c0 .48-.29.71-.8 1.1-.53.4-1.2.9-1.2 1.9s.67 1.5 1.2 1.9c.51.38.8.62.8 1.1s-.29.72-.8 1.1c-.54.4-1.2.9-1.2 1.9 0 .28.22.5.5.5s.5-.22.5-.5c0-.48.29-.72.8-1.1.54-.4 1.2-.9 1.2-1.9s-.67-1.5-1.2-1.9c-.51-.38-.8-.62-.8-1.1s.29-.72.8-1.1z"/><path d="m12.3 3.9c.54-.4 1.2-.9 1.2-1.9 0-.28-.22-.5-.5-.5s-.5.22-.5.5c0 .48-.29.71-.8 1.1-.53.4-1.2.9-1.2 1.9s.67 1.5 1.2 1.9c.51.38.8.62.8 1.1s-.29.72-.8 1.1c-.54.4-1.2.9-1.2 1.9 0 .28.22.5.5.5s.5-.22.5-.5c0-.48.29-.72.8-1.1.54-.4 1.2-.9 1.2-1.9s-.67-1.5-1.2-1.9c-.51-.38-.8-.62-.8-1.1s.29-.72.8-1.1z"/><path d="m18.3 3.9c.54-.4 1.2-.9 1.2-1.9 0-.28-.22-.5-.5-.5s-.5.22-.5.5c0 .48-.29.71-.8 1.1-.53.4-1.2.9-1.2 1.9s.67 1.5 1.2 1.9c.51.38.8.62.8 1.1s-.29.72-.8 1.1c-.54.4-1.2.9-1.2 1.9 0 .28.22.5.5.5s.5-.22.5-.5c0-.48.29-.72.8-1.1.54-.4 1.2-.9 1.2-1.9s-.67-1.5-1.2-1.9c-.51-.38-.8-.62-.8-1.1s.29-.72.8-1.1z"/><path d="m22 13.5c-1.07 0-1.61.65-2.05 1.18-.44.52-.71.82-1.29.82s-.85-.3-1.29-.82c-.44-.53-.98-1.18-2.05-1.18s-1.61.65-2.05 1.18c-.44.52-.71.82-1.28.82s-.85-.3-1.28-.82c-.44-.53-.98-1.18-2.05-1.18s-1.61.65-2.05 1.18c-.44.52-.71.82-1.28.82s-.84-.3-1.28-.82c-.44-.53-.98-1.18-2.05-1.18-.28 0-.5.22-.5.5s.22.5.5.5c.57 0 .84.3 1.28.82.44.53.98 1.18 2.05 1.18s1.61-.65 2.05-1.18c.44-.52.71-.82 1.28-.82s.85.3 1.28.82c.44.53.98 1.18 2.05 1.18s1.61-.65 2.05-1.18c.44-.52.71-.82 1.28-.82s.85.3 1.29.82c.44.53.98 1.18 2.05 1.18s1.61-.65 2.05-1.18c.44-.52.71-.82 1.29-.82.28 0 .5-.22.5-.5s-.22-.5-.5-.5z"/><path d="m21 18.5h-18c-.83 0-1.5.67-1.5 1.5v1c0 .83.67 1.5 1.5 1.5h18c.83 0 1.5-.67 1.5-1.5v-1c0-.83-.67-1.5-1.5-1.5zm.5 2.5c0 .28-.22.5-.5.5h-18c-.28 0-.5-.22-.5-.5v-1c0-.28.22-.5.5-.5h18c.28 0 .5.22.5.5z"/></g></svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
@@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 476.912 476.912" style="enable-background:new 0 0 476.912 476.912;" xml:space="preserve">
|
||||
<g>
|
||||
<g>
|
||||
<path d="M461.776,209.408L249.568,4.52c-6.182-6.026-16.042-6.026-22.224,0L15.144,209.4c-3.124,3.015-4.888,7.17-4.888,11.512
|
||||
c0,8.837,7.164,16,16,16h28.2v224c0,8.837,7.163,16,16,16h112c8.837,0,16-7.163,16-16v-128h80v128c0,8.837,7.163,16,16,16h112
|
||||
c8.837,0,16-7.163,16-16v-224h28.2c4.338,0,8.489-1.761,11.504-4.88C468.301,225.678,468.129,215.549,461.776,209.408z
|
||||
M422.456,220.912c-8.837,0-16,7.163-16,16v224h-112v-128c0-8.837-7.163-16-16-16h-80c-8.837,0-16,7.163-16,16v128h-112v-224
|
||||
c0-8.837-7.163-16-16-16h-28.2l212.2-204.88l212.28,204.88H422.456z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg"><g id="Front_Heater" data-name="Front Heater"><path d="m33.14 29h2.86l-4-7-4 7h3l1.5 3.7a8.38 8.38 0 0 1 -.92 8l-.67.82a10.43 10.43 0 0 0 -.29 11.74 1 1 0 0 0 .82.42 1 1 0 0 0 .58-.19 1 1 0 0 0 .23-1.39 8.4 8.4 0 0 1 .21-9.32l.67-.82a10.32 10.32 0 0 0 1.22-10z"/><path d="m23.22 29h2.78l-4-7-4 7h3.06l1.5 3.7a8.35 8.35 0 0 1 -.92 8l-.67.82a10.43 10.43 0 0 0 -.29 11.74 1 1 0 0 0 .82.42 1 1 0 0 0 .58-.19 1 1 0 0 0 .24-1.39 8.4 8.4 0 0 1 .2-9.32l.67-.82a10.32 10.32 0 0 0 1.22-10z"/><path d="m57.88 20.09a3 3 0 0 0 -1.49-1.84l-7.73-4.1a35.48 35.48 0 0 0 -33.32 0l-7.72 4.1a3 3 0 0 0 -1.22 4.2l9.72 17a3 3 0 0 0 2.6 1.55 3 3 0 0 0 1.39-.34 1 1 0 0 0 .42-1.35 1 1 0 0 0 -1.34-.42 1 1 0 0 1 -1.33-.39l-9.72-17a1 1 0 0 1 -.1-.81 1 1 0 0 1 .52-.69l7.72-4.1a33.46 33.46 0 0 1 31.44 0l7.73 4.1a1 1 0 0 1 .51.63 1 1 0 0 1 -.1.81l-9.72 17a1 1 0 0 1 -1.33.39l-.2-.11a10.82 10.82 0 0 0 -.36-6.72l-1.19-3h2.94l-4-7-4 7h2.9l1.5 3.7a8.38 8.38 0 0 1 -.93 8l-.66.82a10.43 10.43 0 0 0 -.29 11.74 1 1 0 0 0 .82.42 1 1 0 0 0 .58-.19 1 1 0 0 0 .23-1.39 8.4 8.4 0 0 1 .21-9.32l.64-.78a8.27 8.27 0 0 0 .84-1.3 3 3 0 0 0 4-1.17l9.72-17a3 3 0 0 0 .32-2.44z"/></g></svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -0,0 +1 @@
|
||||
<svg id="Ecommerce" enable-background="new 0 0 48 48" height="512" viewBox="0 0 48 48" width="512" xmlns="http://www.w3.org/2000/svg"><g><path d="m25 7.03c0-.552-.447-1-1-1-5.514 0-10 4.486-10 10 0 .552.447 1 1 1s1-.448 1-1c0-4.411 3.589-8 8-8 .553 0 1-.448 1-1z"/><path d="m22.246 45.79h1.754 1.754c1.652 0 2.999-1.345 3-3v-1.099c1.032-.475 1.755-1.512 1.755-2.721v-3.72c.176-.382.281-.802.281-1.25 0-1.016.226-2 .671-2.927.441-.919 1.086-1.752 1.864-2.409 3.746-3.165 5.709-7.989 5.25-12.909-.7-7.375-6.813-13.189-14.265-13.525l-.31-.01-.354.011c-7.408.335-13.521 6.149-14.222 13.526-.458 4.917 1.505 9.742 5.251 12.906.778.658 1.423 1.491 1.864 2.41.445.927.671 1.911.671 2.927 0 .447.105.868.281 1.25v3.721c0 1.209.722 2.247 1.755 2.721v1.1c.001 1.653 1.348 2.998 3 2.998zm4.508-3c0 .552-.449 1-1 1h-1.754-1.754c-.551 0-1-.449-1-1v-.82h2.754 2.754zm1.755-3.819c0 .551-.448 1-1 1h-3.509-3.509c-.552 0-1-.449-1-1v-2.068c.232.058.47.097.719.097h3.79 3.79c.249 0 .487-.039.719-.097zm-9.299-4.971c0-1.318-.292-2.595-.868-3.793-.563-1.171-1.385-2.233-2.376-3.071-3.247-2.742-4.948-6.926-4.551-11.191.607-6.389 5.903-11.426 12.275-11.715l.31-.01.265.009c6.417.29 11.713 5.327 12.319 11.714.398 4.267-1.303 8.451-4.55 11.193-.991.838-1.813 1.9-2.376 3.071-.576 1.198-.868 2.475-.868 3.793 0 .551-.448 1-1 1h-3.79-3.79c-.552 0-1-.449-1-1z"/></g></svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1 @@
|
||||
<svg id="Layer_1" height="512" viewBox="0 0 100 100" width="512" xmlns="http://www.w3.org/2000/svg"><path d="m44.94 55.32h4.08c.71 0 1.29.68 1.29 1.52 0 .83.67 1.5 1.5 1.5s1.5-.67 1.5-1.5c0-2.49-1.93-4.52-4.29-4.52h-4.08c-2.37 0-4.29 2.03-4.29 4.52v2.07c0 2.38 1.76 4.32 3.98 4.49.1.02.2.03.31.03h4.08c.71 0 1.29.68 1.29 1.52v2.08c0 .84-.58 1.52-1.29 1.52h-4.08c-.71 0-1.29-.68-1.29-1.52 0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5c0 2.49 1.93 4.52 4.29 4.52h4.08c2.37 0 4.29-2.03 4.29-4.52v-2.08c0-2.38-1.76-4.31-3.98-4.49-.1-.02-.2-.03-.31-.03h-4.08c-.71 0-1.29-.68-1.29-1.52v-2.07c0-.84.58-1.52 1.29-1.52z"/><path d="m64.22 52.32h-4.64c-.83 0-1.5.67-1.5 1.5v16.22c0 .83.67 1.5 1.5 1.5h4.64c3.59 0 6.52-2.92 6.52-6.52v-6.19c-.01-3.59-2.93-6.51-6.52-6.51zm3.51 12.7c0 1.94-1.58 3.52-3.52 3.52h-3.14v-13.22h3.14c1.94 0 3.52 1.58 3.52 3.52z"/><path d="m11.22 72.57c-.28.28-.44.66-.44 1.06v16.99c0 3.44 2.8 6.25 6.25 6.25h65.95c3.44 0 6.25-2.8 6.25-6.25v-81.23c0-3.44-2.8-6.25-6.25-6.25h-55.9c-3.37 0-6.11 2.74-6.11 6.12v24.13l-9.75 9.75c-.28.28-.44.66-.44 1.06v9.87c0 .83.67 1.5 1.5 1.5h8.69v7.26zm11.25-20.01h-8.69v-7.75l9.75-9.75c.28-.28.44-.66.44-1.06v-24.74c0-1.72 1.4-3.12 3.11-3.12h55.9c1.79 0 3.25 1.46 3.25 3.25v81.23c0 1.79-1.46 3.25-3.25 3.25h-65.96c-1.79 0-3.25-1.46-3.25-3.25v-16.37l9.75-9.75c.28-.28.44-.66.44-1.06v-9.38c.01-.83-.67-1.5-1.49-1.5z"/><path d="m31.84 32.33h4.73c1.39 0 2.51-1.13 2.51-2.51v-16.9c0-1.39-1.13-2.51-2.51-2.51h-4.73c-1.39 0-2.51 1.13-2.51 2.51v16.9c0 1.38 1.13 2.51 2.51 2.51zm.49-18.93h3.76v15.93h-3.76z"/><path d="m45.82 32.33h4.73c1.39 0 2.51-1.13 2.51-2.51v-16.9c0-1.39-1.13-2.51-2.51-2.51h-4.73c-1.39 0-2.51 1.13-2.51 2.51v16.9c-.01 1.38 1.12 2.51 2.51 2.51zm.48-18.93h3.76v15.93h-3.76z"/><path d="m59.79 32.33h4.73c1.39 0 2.51-1.13 2.51-2.51v-16.9c0-1.39-1.13-2.51-2.51-2.51h-4.73c-1.39 0-2.51 1.13-2.51 2.51v16.9c-.01 1.38 1.12 2.51 2.51 2.51zm.48-18.93h3.76v15.93h-3.76z"/><path d="m73.76 32.33h4.73c1.39 0 2.51-1.13 2.51-2.51v-16.9c0-1.39-1.13-2.51-2.51-2.51h-4.73c-1.39 0-2.51 1.13-2.51 2.51v16.9c0 1.38 1.12 2.51 2.51 2.51zm.49-18.93h3.76v15.93h-3.76z"/><path d="m30.83 83.8h48.67c.83 0 1.5-.67 1.5-1.5v-38.79c0-.83-.67-1.5-1.5-1.5h-48.67c-.83 0-1.5.67-1.5 1.5v38.79c0 .82.67 1.5 1.5 1.5zm1.5-38.79h45.67v35.79h-45.67z"/></svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="m22 11a1 1 0 0 0 -1 1 9 9 0 1 1 -9-9 8.9 8.9 0 0 1 4.42 1.166l-1.127 1.127a1 1 0 0 0 .707 1.707h4a1 1 0 0 0 1-1v-4a1 1 0 0 0 -1.707-.707l-1.411 1.407a10.9 10.9 0 0 0 -5.882-1.7 11 11 0 1 0 11 11 1 1 0 0 0 -1-1z"/></svg>
|
||||
|
After Width: | Height: | Size: 288 B |
@@ -0,0 +1 @@
|
||||
<svg id="Layer_1" enable-background="new 0 0 512 512" height="512" viewBox="0 0 512 512" width="512" xmlns="http://www.w3.org/2000/svg"><path d="m272.066 512h-32.133c-25.989 0-47.134-21.144-47.134-47.133v-10.871c-11.049-3.53-21.784-7.986-32.097-13.323l-7.704 7.704c-18.659 18.682-48.548 18.134-66.665-.007l-22.711-22.71c-18.149-18.129-18.671-48.008.006-66.665l7.698-7.698c-5.337-10.313-9.792-21.046-13.323-32.097h-10.87c-25.988 0-47.133-21.144-47.133-47.133v-32.134c0-25.989 21.145-47.133 47.134-47.133h10.87c3.531-11.05 7.986-21.784 13.323-32.097l-7.704-7.703c-18.666-18.646-18.151-48.528.006-66.665l22.713-22.712c18.159-18.184 48.041-18.638 66.664.006l7.697 7.697c10.313-5.336 21.048-9.792 32.097-13.323v-10.87c0-25.989 21.144-47.133 47.134-47.133h32.133c25.989 0 47.133 21.144 47.133 47.133v10.871c11.049 3.53 21.784 7.986 32.097 13.323l7.704-7.704c18.659-18.682 48.548-18.134 66.665.007l22.711 22.71c18.149 18.129 18.671 48.008-.006 66.665l-7.698 7.698c5.337 10.313 9.792 21.046 13.323 32.097h10.87c25.989 0 47.134 21.144 47.134 47.133v32.134c0 25.989-21.145 47.133-47.134 47.133h-10.87c-3.531 11.05-7.986 21.784-13.323 32.097l7.704 7.704c18.666 18.646 18.151 48.528-.006 66.665l-22.713 22.712c-18.159 18.184-48.041 18.638-66.664-.006l-7.697-7.697c-10.313 5.336-21.048 9.792-32.097 13.323v10.871c0 25.987-21.144 47.131-47.134 47.131zm-106.349-102.83c14.327 8.473 29.747 14.874 45.831 19.025 6.624 1.709 11.252 7.683 11.252 14.524v22.148c0 9.447 7.687 17.133 17.134 17.133h32.133c9.447 0 17.134-7.686 17.134-17.133v-22.148c0-6.841 4.628-12.815 11.252-14.524 16.084-4.151 31.504-10.552 45.831-19.025 5.895-3.486 13.4-2.538 18.243 2.305l15.688 15.689c6.764 6.772 17.626 6.615 24.224.007l22.727-22.726c6.582-6.574 6.802-17.438.006-24.225l-15.695-15.695c-4.842-4.842-5.79-12.348-2.305-18.242 8.473-14.326 14.873-29.746 19.024-45.831 1.71-6.624 7.684-11.251 14.524-11.251h22.147c9.447 0 17.134-7.686 17.134-17.133v-32.134c0-9.447-7.687-17.133-17.134-17.133h-22.147c-6.841 0-12.814-4.628-14.524-11.251-4.151-16.085-10.552-31.505-19.024-45.831-3.485-5.894-2.537-13.4 2.305-18.242l15.689-15.689c6.782-6.774 6.605-17.634.006-24.225l-22.725-22.725c-6.587-6.596-17.451-6.789-24.225-.006l-15.694 15.695c-4.842 4.843-12.35 5.791-18.243 2.305-14.327-8.473-29.747-14.874-45.831-19.025-6.624-1.709-11.252-7.683-11.252-14.524v-22.15c0-9.447-7.687-17.133-17.134-17.133h-32.133c-9.447 0-17.134 7.686-17.134 17.133v22.148c0 6.841-4.628 12.815-11.252 14.524-16.084 4.151-31.504 10.552-45.831 19.025-5.896 3.485-13.401 2.537-18.243-2.305l-15.688-15.689c-6.764-6.772-17.627-6.615-24.224-.007l-22.727 22.726c-6.582 6.574-6.802 17.437-.006 24.225l15.695 15.695c4.842 4.842 5.79 12.348 2.305 18.242-8.473 14.326-14.873 29.746-19.024 45.831-1.71 6.624-7.684 11.251-14.524 11.251h-22.148c-9.447.001-17.134 7.687-17.134 17.134v32.134c0 9.447 7.687 17.133 17.134 17.133h22.147c6.841 0 12.814 4.628 14.524 11.251 4.151 16.085 10.552 31.505 19.024 45.831 3.485 5.894 2.537 13.4-2.305 18.242l-15.689 15.689c-6.782 6.774-6.605 17.634-.006 24.225l22.725 22.725c6.587 6.596 17.451 6.789 24.225.006l15.694-15.695c3.568-3.567 10.991-6.594 18.244-2.304z"/><path d="m256 367.4c-61.427 0-111.4-49.974-111.4-111.4s49.973-111.4 111.4-111.4 111.4 49.974 111.4 111.4-49.973 111.4-111.4 111.4zm0-192.8c-44.885 0-81.4 36.516-81.4 81.4s36.516 81.4 81.4 81.4 81.4-36.516 81.4-81.4-36.515-81.4-81.4-81.4z"/></svg>
|
||||
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 5.0 KiB |
|
After Width: | Height: | Size: 14 KiB |
@@ -0,0 +1,53 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 412.8 412.8" style="enable-background:new 0 0 412.8 412.8;" xml:space="preserve">
|
||||
<g>
|
||||
<g>
|
||||
<path d="M378.4,225.6L304,251.2L274,234v-27.6v-27.2l30-17.2l74.4,25.6c5.2,2,11.2-1.2,12.8-6.4c2-5.2-1.2-11.2-6.4-12.8
|
||||
l-57.6-19.6l54-31.2c4.8-2.8,6.4-9.2,3.6-14c-2.8-4.8-9.2-6.4-14-3.6l-54,31.2l11.6-59.6c1.2-5.6-2.4-10.8-8-12
|
||||
c-5.6-1.2-10.8,2.4-12,8l-15.2,77.2l-30,17.2l-22.8-13.2l-0.4-0.4l-23.2-13.6v-34.4L276,48.8c4.4-3.6,4.8-10,0.8-14.4
|
||||
c-3.6-4.4-10-4.8-14.4-0.8l-45.6,40V10.4c0-5.6-4.4-10.4-10.4-10.4C200.8,0,196,4.4,196,10.4v62.4l-45.6-39.6
|
||||
C146,29.6,139.6,30,136,34c-3.6,4.4-3.2,10.8,0.8,14.4L196,100v34.4L172.8,148l-23.2,13.6l-30-17.2l-15.2-77.2
|
||||
c-1.2-5.6-6.4-9.2-12-8c-5.6,1.2-9.2,6.4-8,12L96,130.8L42,99.6c-4.8-2.8-11.2-1.2-14,3.6s-1.2,11.2,3.6,14l54,31.2L28,168
|
||||
c-5.2,2-8.4,7.6-6.4,12.8s7.6,8.4,12.8,6.4l74.4-25.6l30,17.2v27.6v27.2h0.4l-30,17.2l-74.4-25.6c-5.2-2-11.2,1.2-12.8,6.4
|
||||
c-2,5.2,1.2,11.2,6.4,12.8L86,264l-54,31.2c-4.8,2.8-6.4,9.2-3.6,14c2.8,4.8,9.2,6.4,14,3.6l54-31.2l-11.6,59.6
|
||||
c-1.2,5.6,2.4,10.8,8,12c5.6,1.2,10.8-2.4,12-8L120,268l30-17.2l23.6,13.6l23.2,13.6v34.4L137.6,364c-4.4,3.6-4.8,10-0.8,14.4
|
||||
c3.6,4.4,10,4.8,14.4,0.8l45.6-40v63.2c0,5.6,4.4,10.4,10.4,10.4c5.6,0,10.4-4.4,10.4-10.4V340l45.6,40c4.4,3.6,10.8,3.2,14.4-0.8
|
||||
c3.6-4.4,3.2-10.8-0.8-14.4l-60-52v-34.4l23.2-13.6l23.2-13.6l30,17.2l15.2,77.2c1.2,5.6,6.4,9.2,12,8c5.6-1.2,9.2-6.4,8-12
|
||||
L316.8,282l54,31.2c4.8,2.8,11.2,1.2,14-3.6c2.8-4.8,1.2-11.2-3.6-14l-54-31.2l57.6-19.6c5.2-2,8.4-7.6,6.4-12.8
|
||||
C389.2,226.8,383.6,223.6,378.4,225.6z M252.4,206.4v27.2l-23.2,13.6l-22.8,13.2l-23.6-13.6l-23.2-13.6v-26.8v-27.2l23.2-13.6
|
||||
L206,152l23.2,13.6l0.4,0.4l22.8,13.2V206.4z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.1 KiB |
@@ -0,0 +1 @@
|
||||
<svg id="Teamwork" enable-background="new 0 0 64 64" height="512" viewBox="0 0 64 64" width="512" xmlns="http://www.w3.org/2000/svg"><path d="m29.351 39h-15.351c-.553 0-1-.448-1-1s.447-1 1-1h15.351c.553 0 1 .448 1 1s-.448 1-1 1z"/><path d="m29.351 27h-15.351c-.553 0-1-.448-1-1s.447-1 1-1h15.351c.553 0 1 .448 1 1s-.448 1-1 1z"/><path d="m28 33h-20c-.553 0-1-.448-1-1s.447-1 1-1h20c.553 0 1 .448 1 1s-.447 1-1 1z"/><path d="m38 35.902c-1.987 0-4-1.34-4-3.902s2.013-3.902 4-3.902 4 1.34 4 3.902-2.013 3.902-4 3.902zm0-5.804c-.923 0-2 .498-2 1.902s1.077 1.902 2 1.902 2-.498 2-1.902-1.077-1.902-2-1.902z"/><path d="m40.121 30.879c-.256 0-.512-.098-.707-.293-.391-.391-.391-1.023 0-1.414l5.657-5.657c.391-.391 1.023-.391 1.414 0s.391 1.023 0 1.414l-5.657 5.657c-.195.195-.451.293-.707.293z"/><path d="m34.465 36.536c-.256 0-.512-.098-.707-.293-.391-.39-.391-1.023 0-1.414l1.414-1.415c.391-.391 1.023-.391 1.414 0 .391.39.391 1.023 0 1.414l-1.414 1.415c-.195.195-.451.293-.707.293z"/><path d="m38 51c-.553 0-1-.448-1-1v-3c0-.552.447-1 1-1s1 .448 1 1v3c0 .552-.447 1-1 1z"/><path d="m50.728 45.728c-.256 0-.512-.098-.707-.293l-2.121-2.122c-.391-.391-.391-1.024 0-1.414.391-.391 1.023-.391 1.414 0l2.121 2.122c.391.391.391 1.024 0 1.414-.196.195-.452.293-.707.293z"/><path d="m48.606 22.394c-.256 0-.512-.098-.707-.293-.391-.39-.391-1.023 0-1.414l2.121-2.122c.391-.391 1.023-.391 1.414 0 .391.39.391 1.023 0 1.414l-2.121 2.122c-.195.195-.451.293-.707.293z"/><path d="m38 18c-.553 0-1-.448-1-1v-3c0-.552.447-1 1-1s1 .448 1 1v3c0 .552-.447 1-1 1z"/><path d="m56 33h-3c-.553 0-1-.448-1-1s.447-1 1-1h3c.553 0 1 .448 1 1s-.447 1-1 1z"/><path d="m30.789 21h-10.789c-.553 0-1-.448-1-1s.447-1 1-1h10.789c.553 0 1 .448 1 1s-.447 1-1 1z"/><path d="m30.789 45h-10.789c-.553 0-1-.448-1-1s.447-1 1-1h10.789c.553 0 1 .448 1 1s-.447 1-1 1z"/><path d="m37.938 50.981c-2.931 0-5.892-.675-8.642-2.092-.491-.253-.684-.856-.431-1.347s.857-.684 1.347-.431c7.844 4.042 17.615 1.334 22.245-6.165 4.643-7.521 2.7-17.48-4.423-22.673-5.159-3.76-12.155-4.304-17.822-1.385-.49.253-1.094.061-1.347-.431-.253-.491-.061-1.094.431-1.347 6.333-3.264 14.149-2.657 19.916 1.546 7.962 5.804 10.135 16.935 4.946 25.34-3.551 5.754-9.81 8.985-16.22 8.985z"/></svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
@@ -0,0 +1 @@
|
||||
<svg id="layer_1" enable-background="new 0 0 200 200" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg"><g fill="rgb(0,0,0)"><path d="m61.3366 198.7365c-3.8893 0-7.7945-1.0847-11.3086-3.2781-32.6418-20.3714-44.9485-46.703-49.5247-65.2053-6.1066-30.8373 44.9333-36.4535 67.8505-35.056 1.761-6.9634 6.1301-13.08 12.1249-17.0214-9.0714-12.1387-21.2458-19.7867-36.2543-22.7586-19.3391-3.2847-23.4263-31.1087-5.8545-39.8477 33.3392-19.0024 97.1952-22.5083 96.3704 10.811-.6835 19.2868-6.9715 37.8308-18.7038 55.1859 5.1612 4.9953 8.292 11.7803 8.6884 19.0147 15.0429-1.7888 27.7494-8.5077 37.8247-20.0165 6.0052-6.8593 15.3868-9.1156 23.9022-5.7478 8.5361 3.3773 13.8491 11.4631 13.535 20.6005-1.3216 38.4536-17.9721 62.2774-31.708 75.4917-23.6412 20.7064-54.0319-20.679-64.2755-41.2153-6.816 1.9769-14.557 1.2532-20.8202-1.9875-5.969 13.9198-6.5027 28.2804-1.574 42.7574 5.0949 13.3396-6.2694 28.6219-20.2725 28.273zm-1.6188-94.5681c-14.1176.1632-54.2272 5.0317-50.2069 23.856 4.1646 16.8367 15.4261 40.8368 45.43 59.562 5.3197 3.3207 10.6838 1.7539 13.9293-.8201 3.2305-2.5623 5.9658-7.4048 3.9546-13.3126-6.3202-18.5652-4.873-36.9425 4.3011-54.6216.6379-1.2292 1.7915-2.1091 3.1458-2.3995 1.3551-.2882 2.7674.0404 3.8526.8993 3.4512 2.733 7.6019 4.1775 12.0037 4.1775 4.9261.8516 11.3607-5.6527 14.5071.4457 6.0281 15.2396 35.1102 56.5264 51.2108 42.2675 12.4987-12.025 27.6526-33.7782 28.8673-69.1245.0159-11.6249-13.2308-16.8886-21.1812-8.4221-12.9177 14.7553-29.5546 22.6907-49.4492 23.5865-1.3715.0602-2.7195-.4957-3.6482-1.5215-1.8205-1.8024-.9363-4.3611-.9455-6.5928-.0001-6.3459-3.1223-12.2987-8.3528-15.9233-1.0257-.7109-1.7221-1.8051-1.931-3.0357-.2093-1.2306.0861-2.4938.8196-3.5037 10.2153-12.9246 31.3669-58.5212 11.0023-65.4878-16.6655-4.8123-43.08-7.0587-74.2968 9.5628-10.0753 5.7972-8.0115 19.9044 3.2961 22.5543 19.2372 3.809 34.4279 14.2491 45.1507 31.0306 1.5812 2.3482.4574 5.827-2.1953 6.8094-6.7913 2.7009-11.5582 9.1434-12.144 16.4131-.1006 1.2455-.6991 2.3982-1.6611 3.1966-4.5407 2.4665-10.5485-.3007-15.459.4039z"/><path d="m96.1279 112.2302c-7.607 1.0321-15.4151-13.051-5.4426-14.7224 2.5623.0007 4.6397 2.0781 4.6397 4.6403 0 .4354.3675.8028.8029.8028 6.0654.0249 6.0675 9.2545 0 9.2793z"/><path d="m9.2329 99.228c-12.7712-.764 4.8333-40.6245 9.5289-46.5697 3.292-5.0803 11.0691-.1194 7.8098 5.0118-7.1818 11.1897-11.5808 24.0937-12.7217 37.3166-.2085 2.4172-2.2352 4.2413-4.617 4.2413z"/><path d="m39.2577 89.6348c-11.0543-1.6919 1.3997-18.9153 4.3572-24.1282 3.4934-4.9529 11.064.3241 7.6063 5.3167-3.325 4.7567-5.8564 9.9749-7.5229 15.5084-.6044 2.0077-2.4471 3.3031-4.4406 3.3031z"/><path d="m96.2071 193.9939c-3.6525.2417-8.8695-.1084-8.6734-4.9527.12-2.5591 2.2921-4.5182 4.8525-4.4162 13.2881.6302 26.6579-2.0181 38.6783-7.6414 5.4914-2.5456 9.4266 5.808 3.9316 8.4049-12.0948 5.6586-25.4224 8.6054-38.789 8.6054z"/><path d="m96.194 166.1857c-3.9048.076-10.1254.1951-9.7645-5.2634.2215-2.5524 2.4715-4.439 5.0229-4.2215 5.7823.502 11.5673.0847 17.1924-1.2392 2.4947-.584 4.9917.9597 5.5789 3.4539.8588 8.4162-12.5193 6.4771-18.0297 7.2702z"/><path d="m173.5515 66.6619c-1.6806 0-3.3021-.9157-4.1263-2.512-6.0995-11.8142-15.0751-22.0758-25.9565-29.6754-4.9499-3.4817.3164-11.067 5.3132-7.6072 6.2137 3.1209 41.191 37.1803 24.7696 39.7946z"/><path d="m149.9162 81.597c-1.7462 0-3.4186-.99-4.2065-2.6759-2.4571-5.2576-5.7103-10.0585-9.6698-14.27-4.1842-4.3187 2.6992-10.8071 6.7603-6.3556 3.7145 4.588 19.1197 21.1144 7.116 23.3015z"/></g></svg>
|
||||
|
After Width: | Height: | Size: 3.4 KiB |
@@ -0,0 +1 @@
|
||||
<svg height="472pt" viewBox="0 -87 472 472" width="472pt" xmlns="http://www.w3.org/2000/svg"><path d="m467.101562 26.527344c-3.039062-1.800782-6.796874-1.871094-9.898437-.179688l-108.296875 59.132813v-35.480469c-.03125-27.601562-22.398438-49.96875-50-50h-248.90625c-27.601562.03125-49.96875 22.398438-50 50v197.421875c.03125 27.601563 22.398438 49.96875 50 50h248.90625c27.601562-.03125 49.96875-22.398437 50-50v-34.835937l108.300781 59.132812c3.097657 1.691406 6.859375 1.625 9.894531-.175781 3.039063-1.804688 4.898438-5.074219 4.898438-8.601563v-227.816406c0-3.53125-1.863281-6.796875-4.898438-8.597656zm-138.203124 220.898437c-.015626 16.5625-13.4375 29.980469-30 30h-248.898438c-16.5625-.019531-29.980469-13.4375-30-30v-197.425781c.019531-16.558594 13.4375-29.980469 30-30h248.90625c16.558594.019531 29.980469 13.441406 30 30zm123.101562-1.335937-103.09375-56.289063v-81.535156l103.09375-56.285156zm0 0"/></svg>
|
||||
|
After Width: | Height: | Size: 916 B |
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="512" height="512"><g id="Water"><path d="M24,46A16.0183,16.0183,0,0,1,8,30C8,16.0942,22.708,2.8125,23.3345,2.2539a.9983.9983,0,0,1,1.331,0C25.292,2.8125,40,16.0942,40,30A16.0183,16.0183,0,0,1,24,46ZM24,4.3721C21.1333,7.1372,10,18.6118,10,30a14,14,0,0,0,28,0C38,18.6118,26.8667,7.1372,24,4.3721Z"/><path d="M18.4976,40.5273a.9946.9946,0,0,1-.5-.1342A12.0449,12.0449,0,0,1,12,30a1,1,0,0,1,2,0,10.0373,10.0373,0,0,0,5,8.6616,1,1,0,0,1-.5019,1.8657Z"/></g></svg>
|
||||
|
After Width: | Height: | Size: 548 B |
@@ -0,0 +1,73 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
|
||||
<g>
|
||||
<g>
|
||||
<path d="M256,40c-5.52,0-10,4.48-10,10s4.48,10,10,10s10-4.48,10-10S261.52,40,256,40z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path d="M466,210C466,94.206,371.794,0,256,0S46,94.206,46,210c0,96.488,66.579,180.855,159.516,203.859
|
||||
c-1.591,14.119-6.958,31.441-13.568,38.051l-0.131,0.131c-18.899,0.353-32.638,3.149-42.999,8.73
|
||||
C133.677,468.949,126,482.82,126,502c0,5.522,4.478,10,10,10h240c5.522,0,10-4.478,10-10c0-19.187-7.68-33.058-22.824-41.229
|
||||
c-10.344-5.58-24.082-8.378-42.992-8.731l-0.132-0.132c-6.61-6.609-11.977-23.931-13.568-38.05
|
||||
C399.423,390.853,466,306.486,466,210z M316,472c33.23,0,45.303,7.689,48.794,20H147.226c2.172-7.762,6.862-11.345,11.087-13.626
|
||||
C166.274,474.085,178.603,472,196,472H316z M215.517,452c5.068-10.601,8.238-23.466,9.638-34.27
|
||||
C235.326,419.232,245.658,420,256,420c10.342,0,20.674-0.768,30.845-2.27c1.401,10.804,4.57,23.67,9.638,34.27H215.517z
|
||||
M294.015,396.179c-0.019,0.004-0.037,0.007-0.056,0.011c-24.788,5.056-51.127,5.057-75.922-0.001
|
||||
c-0.017-0.004-0.035-0.007-0.052-0.01C129.918,378.227,66,299.929,66,210c0-104.767,85.233-190,190-190s190,85.233,190,190
|
||||
C446,299.929,382.082,378.227,294.015,396.179z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path d="M389.606,104.994c-23.072-29.303-55.544-50.505-91.434-59.701c-5.355-1.374-10.799,1.855-12.17,7.205
|
||||
c-1.37,5.35,1.855,10.798,7.205,12.169c31.66,8.112,60.314,26.828,80.686,52.7c3.426,4.352,9.716,5.077,14.043,1.67
|
||||
C392.275,115.621,393.023,109.333,389.606,104.994z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path d="M256,100c-60.654,0-110,49.346-110,110s49.346,110,110,110s110-49.346,110-110S316.654,100,256,100z M256,300
|
||||
c-49.626,0-90-40.374-90-90c0-49.626,40.374-90,90-90c49.626,0,90,40.374,90,90C346,259.626,305.626,300,256,300z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path d="M256,140c-38.598,0-70,31.402-70,70c0,38.598,31.402,70,70,70c38.598,0,70-31.402,70-70C326,171.402,294.598,140,256,140z
|
||||
M256,260c-27.57,0-50-22.43-50-50s22.43-50,50-50s50,22.43,50,50S283.57,260,256,260z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.5 KiB |
@@ -7,8 +7,8 @@
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/img/favicon-32x32.png" />
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/img/favicon-16x16.png" />
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/img/apple-touch-icon.png" />
|
||||
<script type="module" crossorigin src="/assets/index-CLsUm3wk.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-Dqi_M3E3.css">
|
||||
<script type="module" crossorigin src="/assets/index-BarB10XI.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-DiPSi5MU.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
||||