Added AMS discovery module

This commit is contained in:
Martin Ziegler
2025-12-02 12:13:48 +01:00
parent 37caef239f
commit f6836e0fdb
63 changed files with 27497 additions and 467 deletions
+41
View File
@@ -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,
)
+18
View File
@@ -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
+29 -8
View File
@@ -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:
+18
View File
@@ -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 {
+27 -61
View File
@@ -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>
);
})}
File diff suppressed because it is too large Load Diff
+923
View File
@@ -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 &nbsp;&nbsp; N/A</div>
<div class="progress-meta">Estimated finish time: N/A</div>
</div>
<div class="progress-btns">
<button class="progress-btn">&#8962;</button>
<button class="progress-btn">&#9208;</button>
<button class="progress-btn">&#9632;</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">&#9650;</button>
<button class="jog-btn down">&#9660;</button>
<button class="jog-btn left">&#9664;</button>
<button class="jog-btn right">&#9654;</button>
<button class="jog-home"><img src="icons/home.svg"></button>
</div>
</div>
<div class="bed-controls">
<button class="bed-btn">&#8593;10</button>
<button class="bed-btn">&#8593;1</button>
<span class="bed-label">Bed</span>
<button class="bed-btn">&#8595;1</button>
<button class="bed-btn">&#8595;10</button>
</div>
</div>
<div class="extruder-section">
<button class="extruder-btn">&#9650;</button>
<div class="extruder-graphic"><img src="icons/dual-extruder.png"></div>
<button class="extruder-btn">&#9660;</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">&#9728;</span></div>
</div>
<div class="slot-labels">
<div class="slot-label">A1&#8595;</div>
<div class="slot-label">A2&#8595;</div>
<div class="slot-label">A3&#8595;</div>
<div class="slot-label">A4&#8595;</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">&#9728;</span></div>
</div>
<div class="slot-labels">
<div class="slot-label">B1&#8595;</div>
<div class="slot-label">B2&#8595;</div>
<div class="slot-label">B3&#8595;</div>
<div class="slot-label">B4&#8595;</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>
+936
View File
@@ -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 &nbsp;&nbsp; N/A</div>
<div class="progress-meta">Estimated finish time: N/A</div>
</div>
<div class="progress-btns">
<button class="progress-btn">&#8962;</button>
<button class="progress-btn">&#9208;</button>
<button class="progress-btn">&#9632;</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">&#9650;</button>
<button class="jog-btn down">&#9660;</button>
<button class="jog-btn left">&#9664;</button>
<button class="jog-btn right">&#9654;</button>
<button class="jog-home"><img src="icons/home.svg"></button>
</div>
</div>
<div class="bed-controls">
<button class="bed-btn">&#8593;10</button>
<button class="bed-btn">&#8593;1</button>
<span class="bed-label">Bed</span>
<button class="bed-btn">&#8595;1</button>
<button class="bed-btn">&#8595;10</button>
</div>
</div>
<div class="extruder-section">
<button class="extruder-btn">&#9650;</button>
<div class="extruder-graphic"><img src="icons/dual-extruder.png"></div>
<button class="extruder-btn">&#9660;</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">&#9728;</span></div>
</div>
<div class="slot-labels">
<div class="slot-label">A1&#8595;</div>
<div class="slot-label">A2&#8595;</div>
<div class="slot-label">A3&#8595;</div>
<div class="slot-label">A4&#8595;</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">&#9728;</span></div>
</div>
<div class="slot-labels">
<div class="slot-label">B1&#8595;</div>
<div class="slot-label">B2&#8595;</div>
<div class="slot-label">B3&#8595;</div>
<div class="slot-label">B4&#8595;</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>
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+952
View File
@@ -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 &nbsp; 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>
+690
View File
@@ -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">&#8962;</button>
<button class="progress-btn">&#9208;</button>
<button class="progress-btn">&#9632;</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">&#9650;</button>
<button class="jog-btn down">&#9660;</button>
<button class="jog-btn left">&#9664;</button>
<button class="jog-btn right">&#9654;</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">&#8593; 10</button>
<button class="step-btn active">&#8593; 1</button>
</div>
<div class="step-label">Bed</div>
<div class="step-row">
<button class="step-btn">&#8595; 1</button>
<button class="step-btn">&#8595; 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">&#9650;</button>
<button class="ext-btn">&#9660;</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">&#9788;</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">&#8595;</span></div>
</div>
<div class="slot-label-item">
<div class="slot-label-badge">A2 <span class="arrow">&#8595;</span></div>
</div>
<div class="slot-label-item">
<div class="slot-label-badge">A3 <span class="arrow">&#8595;</span></div>
</div>
<div class="slot-label-item">
<div class="slot-label-badge">A4 <span class="arrow">&#8595;</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">&#8736;</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>
File diff suppressed because it is too large Load Diff
+654
View File
@@ -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 &nbsp;&nbsp; Estimated finish time: N/A</div>
</div>
<div class="progress-btns">
<button class="progress-btn">&#8962;</button>
<button class="progress-btn">&#9208;</button>
<button class="progress-btn">&#9632;</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">&#9650;</button>
<button class="jog-btn down">&#9660;</button>
<button class="jog-btn left">&#9664;</button>
<button class="jog-btn right">&#9654;</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">&#8593;10</button>
<button class="step-btn active">&#8593;1</button>
</div>
<div class="step-label">Bed</div>
<div class="step-row">
<button class="step-btn">&#8595;1</button>
<button class="step-btn">&#8595;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">&#9650;</button>
<button class="ext-btn">&#9660;</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">&#9788;</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&#8595;</div></div>
<div class="slot-label-item"><div class="slot-label-badge">A2&#8595;</div></div>
<div class="slot-label-item"><div class="slot-label-badge">A3&#8595;</div></div>
<div class="slot-label-item"><div class="slot-label-badge">A4&#8595;</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">&#8736;</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>
+652
View File
@@ -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 &nbsp; Estimated finish time: N/A</div>
</div>
<div class="progress-btns">
<button class="progress-btn">&#8962;</button>
<button class="progress-btn">&#9208;</button>
<button class="progress-btn">&#9632;</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">&#9650;</button>
<button class="jog-btn down">&#9660;</button>
<button class="jog-btn left">&#9664;</button>
<button class="jog-btn right">&#9654;</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">&#8593;10</button>
<button class="step-btn active">&#8593;1</button>
</div>
<div class="step-label">Bed</div>
<div class="step-row">
<button class="step-btn">&#8595;1</button>
<button class="step-btn">&#8595;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">&#9650;</button>
<button class="ext-btn">&#9660;</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">&#9788;</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&#8595;</div></div>
<div class="slot-label-item"><div class="slot-label-badge">A2&#8595;</div></div>
<div class="slot-label-item"><div class="slot-label-badge">A3&#8595;</div></div>
<div class="slot-label-item"><div class="slot-label-badge">A4&#8595;</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">&#8736;</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>
+924
View File
@@ -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">&#128506;</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 &nbsp;&nbsp; N/A</div>
<div class="progress-meta">Estimated finish time: N/A</div>
</div>
<div class="progress-btns">
<button class="progress-btn">&#8962;</button>
<button class="progress-btn">&#9208;</button>
<button class="progress-btn">&#9632;</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">&#9650;</button>
<button class="jog-btn down">&#9660;</button>
<button class="jog-btn left">&#9664;</button>
<button class="jog-btn right">&#9654;</button>
<button class="jog-home"><img src="icons/home.svg"></button>
</div>
</div>
<div class="bed-controls">
<button class="bed-btn">&#8593;10</button>
<button class="bed-btn">&#8593;1</button>
<span class="bed-label">Bed</span>
<button class="bed-btn">&#8595;1</button>
<button class="bed-btn">&#8595;10</button>
</div>
</div>
<div class="extruder-section">
<button class="extruder-btn">&#9650;</button>
<div class="extruder-graphic"><img src="icons/dual-extruder.png"></div>
<button class="extruder-btn">&#9660;</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">&#9728;</span></div>
</div>
<div class="slot-labels">
<div class="slot-label">A1&#8595;</div>
<div class="slot-label">A2&#8595;</div>
<div class="slot-label">A3&#8595;</div>
<div class="slot-label">A4&#8595;</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">&#9728;</span></div>
</div>
<div class="slot-labels">
<div class="slot-label">B1&#8595;</div>
<div class="slot-label">B2&#8595;</div>
<div class="slot-label">B3&#8595;</div>
<div class="slot-label">B4&#8595;</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>
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.
+1
View File
@@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.
+1
View File
@@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.
+51
View File
@@ -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

+1
View File
@@ -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

+44
View File
@@ -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

+1
View File
@@ -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

+1
View File
@@ -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

+1
View File
@@ -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

+1
View File
@@ -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

+1
View File
@@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.
+53
View File
@@ -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

+1
View File
@@ -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

+1
View File
@@ -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

+1
View File
@@ -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

+2
View File
@@ -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

+73
View File
@@ -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

File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -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>