<template>
	<el-container class="dashboard">
		<!-- Header -->
		<el-header class="dash-header">
			<div class="dash-header-side dash-header-left">
				<span class="header-tag">PHOTON · {{ mgroupName }}</span>
				<span class="header-status"><i class="led-dot"></i>实时数据</span>
			</div>
			<div class="dash-header-center">
				<div class="dash-title">{{ mgroupName }}工段生产数据看板</div>
				<div class="dash-title-deco"><span></span><i></i><span></span></div>
			</div>
			<div class="dash-header-side dash-header-right">
				<div class="dash-day">{{ currentDay }}</div>
				<div class="dash-time">{{ currentTime }}</div>
			</div>
		</el-header>

		<el-main class="dash-main">
			<!-- KPI Cards -->
			<div class="kpi-row">
				<div class="kpi-card kpi-c2">
					<div class="kpi-meta">
						<div class="kpi-label">昨日流转量</div>
						<div class="kpi-sub">PROCESSED</div>
					</div>
					<div class="kpi-value">{{ sctj.rjgs }}</div>
					<div class="kpi-bar"></div>
				</div>
				<div class="kpi-card kpi-c3">
					<div class="kpi-meta">
						<div class="kpi-label">昨日加工前不良</div>
						<div class="kpi-sub">PRE-DEFECT</div>
					</div>
					<div class="kpi-value">{{ sctj.rjgqbls }}</div>
					<div class="kpi-bar"></div>
				</div>
				<div class="kpi-card kpi-c4">
					<div class="kpi-meta">
						<div class="kpi-label">昨日合格数</div>
						<div class="kpi-sub">QUALIFIED</div>
					</div>
					<div class="kpi-value">{{ sctj.rhgs }}</div>
					<div class="kpi-bar"></div>
				</div>
				<div class="kpi-card kpi-c5">
					<div class="kpi-meta">
						<div class="kpi-label">昨日不合格数</div>
						<div class="kpi-sub">REJECTED</div>
					</div>
					<div class="kpi-value">{{ sctj.rbhgs }}</div>
					<div class="kpi-bar"></div>
				</div>
				<div class="kpi-card kpi-c1">
					<div class="kpi-meta">
						<div class="kpi-label">昨日合格率</div>
						<div class="kpi-sub">DAILY QUALITY RATE</div>
					</div>
					<div class="kpi-value">{{ sctj.rhgl }}</div>
					<div class="kpi-bar"></div>
				</div>
				<div class="kpi-card kpi-c1">
					<div class="kpi-meta">
						<div class="kpi-label">昨日生产直通率</div>
						<div class="kpi-sub">DAILY QUALITY RATE</div>
					</div>
					<div class="kpi-value">{{ sctj.rztls }}</div>
					<div class="kpi-bar"></div>
				</div>
			</div>

			<!-- Top row: 2 panels -->
			<el-row :gutter="12" type="flex" class="row-top">
				<el-col :span="12" class="col-full">
					<div class="panel">
						<div class="panel-head">
							<span class="panel-title">设备状态</span>
							<div class="panel-states">
								<span class="state-chip s-run"><i></i>运行<em>{{ hh.yx }}</em></span>
								<span class="state-chip s-idle"><i></i>未运行<em>{{ hh.wyx }}</em></span>
								<span class="state-chip s-err"><i></i>故障<em>{{ hh.gz }}</em></span>
							</div>
						</div>
						<div class="panel-body" id="scrollContainer">
							<dv-scroll-board :config="configDataEq" class="board" />
						</div>
						<i class="corner tl"></i><i class="corner tr"></i>
						<i class="corner bl"></i><i class="corner br"></i>
					</div>
				</el-col>
				<el-col :span="4" class="col-full">
					<div class="panel">
						<div class="panel-head">
							<span class="panel-title">工序余料</span>
						</div>
						<div class="panel-body" ref="processBox">
							<dv-scroll-board :config="configDataProcess" class="board" />
						</div>
						<i class="corner tl"></i><i class="corner tr"></i>
						<i class="corner bl"></i><i class="corner br"></i>
					</div>
				</el-col>
				<el-col :span="8" class="col-full">
					<div class="panel">
						<div class="panel-head">
							<span class="panel-title">昨日损耗分析</span>
						</div>
						<div class="panel-body chart-body" id="chart2"></div>
						<i class="corner tl"></i><i class="corner tr"></i>
						<i class="corner bl"></i><i class="corner br"></i>
					</div>
				</el-col>
			</el-row>

			<!-- Bottom row: 2 panels -->
			<el-row :gutter="12" type="flex" class="row-bottom">
				<el-col :span="12" class="col-full">
					<div class="panel">
						<div class="panel-head">
							<span class="panel-title">生产统计</span>
						</div>
						<div class="panel-body">
							<dv-scroll-board :config="configDatas" class="board" />
						</div>
						<i class="corner tl"></i><i class="corner tr"></i>
						<i class="corner bl"></i><i class="corner br"></i>
					</div>
				</el-col>
				<el-col :span="12" class="col-full">
					<div class="panel">
						<div class="panel-head">
							<span class="panel-title">车间库存</span>
						</div>
						<div class="panel-body">
							<dv-scroll-board :config="configDataInm" class="board" />
						</div>
						<i class="corner tl"></i><i class="corner tr"></i>
						<i class="corner bl"></i><i class="corner br"></i>
					</div>
				</el-col>
			</el-row>
		</el-main>
	</el-container>
</template>

<script>
import * as echarts from "echarts";
import scScrollTavle from "@/components/scScrollTable.vue";
function deepCopy(obj) {
	return JSON.parse(JSON.stringify(obj));
}
export default {
	components: { scScrollTavle },
	data() {
		return {
			pieOption: {
				backgroundColor: "",
				tooltip: { trigger: 'item' },
				legend: {
					icon: "stack",
					right: 10,
					orient: 'vertical',
					itemWidth: 10,
					itemHeight: 10,
					textStyle: { color: '#c8f2ff', fontSize: 11 },
				},
				series: {
					name: '不合格占比',
					type: 'pie',
					radius: ['35%', '65%'],
					center: ['38%', '52%'],
					itemStyle: {
						borderColor: 'rgba(3, 22, 26, 0.8)',
						borderWidth: 2,
					},
					label: { show: false },
					labelLine: { show: false },
					data: []
				}
			},
			tableHeight: 100,
			speed: 2000,
			time: null,
			hh: {
				yx: 0,
				wyx: 0,
				gz: 0,
			},
			sctj: {
				rjgs: 0,
				rjgqbls: 0,
				rhgs: 0,
				rbhgs: 0,
				rhgl: 0,
				rztls: 0,
				rlzls: 0,
			},
			dayInterval: null,
			chartInterval2: null,
			//库存
			configDataInm: {
				header: ['物料名称', '批次号', '数量', '生产中'],
				headerBGC: 'rgba(0, 229, 255, 0.16)',
				oddRowBGC: 'rgba(0, 229, 255, 0.04)',
				evenRowBGC: 'rgba(0, 229, 255, 0.10)',
				headerHeight: 38,
				rowNum: 8,
				align: 'center',
				data: [],
				waitTime: 1500,
			},
			configDataProcess: {
			    headerBGC: 'rgba(0, 229, 255, 0.16)',
				oddRowBGC: 'rgba(0, 229, 255, 0.04)',
				evenRowBGC: 'rgba(0, 229, 255, 0.10)',
				header: ['物料名', '数量(个)'],
				headerHeight: 38,
				rowNum: 8,
				align: 'center',
				columnWidth: [],
				data: []
			},
			//设备
			configDataEq: {
				headerBGC: 'rgba(0, 229, 255, 0.16)',
				oddRowBGC: 'rgba(0, 229, 255, 0.04)',
				evenRowBGC: 'rgba(0, 229, 255, 0.10)',
				header: ['设备名称', '设备编号', '设备状态', '日加工量', '累计加工量'],
				headerHeight: 38,
				rowNum: 8,
				align: 'center',
				data: []
			},
			//生产统计
			configDatas: {
				headerBGC: 'rgba(0, 229, 255, 0.16)',
				oddRowBGC: 'rgba(0, 229, 255, 0.04)',
				evenRowBGC: 'rgba(0, 229, 255, 0.10)',
				header: ['日期', '物料名', '接收数', '合格数', '不合格数', '交送数'],
				headerHeight: 38,
				rowNum: 7,
				align: 'center',
				data: []
			},
			page: 1,
			currentTime: "",
			currentDay: "",
			mgroupName: "",
			mgroupId: "",
			today: "",
			end_time: '',
			start_time: '',
			daysList: [],
		};
	},
	mounted() {
		let that = this;
		let arr = this.$route.path.split("/");
		that.mgroup_code = arr[2];
		that.page = 1;
		that.getMgroups(this.mgroup_code);
		that.configDataInm.data = [];
		//表格table的高度
		this.tableHeight = document.getElementById("scrollContainer").clientHeight;
		this.$nextTick(() => {
			const box = this.$refs.processBox;
			if (box) {
				const w = box.clientWidth - 16;
				this.configDataProcess.columnWidth = [Math.max(50, w - 100), 100];
			}
		});
		this.showTime();
		this.dayInterval = setInterval(() => {
			this.showTime();
		}, 1000);
		//近七天的日期数组
		let daysArr = this.getMondayOfCurrentWeek();
		this.daysArr = daysArr;
		let xAxisData = [];
		daysArr.forEach((item) => {
			let dates = item.split('-');
			let obj = dates[1] + '-' + dates[2];
			xAxisData.push(obj);
			let dayitem = Number(dates[2]);
			that.daysList.push(dayitem);
		})
		that.today = new Date().toISOString().split('T')[0];
		that.yesterday =that.$TOOL.dateFormat2(new Date().getTime() - 24 * 60 * 60 * 1000);;
		this.xAxisData = xAxisData;
		let startDate = new Date(daysArr[0]).getTime() - (1000 * 60 * 60 * 24);
		let endDate = new Date(daysArr[6]).getTime() + (1000 * 60 * 60 * 24);
		let start_time = this.$TOOL.dateFormat(new Date(startDate), "yyyy-MM-dd");
		let end_time = this.$TOOL.dateFormat(new Date(endDate), "yyyy-MM-dd");
		this.start_time = start_time;
		this.end_time = end_time;
	},
	beforeDestroy() {
		if (this.dayInterval) clearInterval(this.dayInterval);
		if (this.chartInterval2) clearInterval(this.chartInterval2);
	},
	methods: {
		getMgroups(code){
			let that = this;
			that.$API.mtm.mgroup.list.req({page:0,code}).then((res) => {
				that.mgroupName = res[0].name;
				that.mgroupId = res[0].id;
				this.$nextTick(() => {
					that.getEqState(that.mgroupId);
					this.getMaterials(that.page);
					this.getProductLine();
					this.getCountnotok();
					this.getProcessLeft();
				})
			});
		},
		getMondayOfCurrentWeek() {
			let today = new Date();
			let days = [];
			for (let i = 6; i >= 0; i--) {
				let date = new Date(today);
				date.setDate(today.getDate() - i);
				days.push(date.toISOString().split('T')[0]);
			}
			return days;
		},
		//时间
		showTime() {
			this.currentTime = this.$TOOL.dateFormat(new Date(), "hh:mm:ss");
			this.currentDay = this.$TOOL.dateFormat(
				new Date(),
				"yyyy年MM月dd日"
			);
		},
		setChart(name, option = null) {
			let dom = document.getElementById(name);
			if (!dom) return null;
			var myChart = echarts.getInstanceByDom(dom);
			if (myChart == undefined) {
				myChart = echarts.init(dom, "dark", {
					renderer: "svg",
				});
			}
			if (option == null) {
				option = Object.assign({}, this.barOption);
			}
			setTimeout(() => {
				try {
					myChart.setOption(option);
				} catch (error) { }
			}, 500);
			return myChart;
		},
		getProcessLeft() {
			let that = this;
			let obj = {
				query: { mgroup_name: that.mgroupName },
			};
			that.$API.bi.dataset.exec.req("mgroup_yuliao", obj).then((res) => {
				let list = res.data2.ds0;
				if (list.length > 0) {
					list.forEach((item) => {
						if(item.状态=='合格'&&(item.物料名.indexOf('QS')>-1||item.物料名.indexOf('32.2')>-1||item.物料名.indexOf('3D')>-1||item.物料名.indexOf('2.5D')>-1)){
							let arr = [];
							arr[0] = item.物料名+'('+item.状态+')';
							arr[1] = item.数量;
							that.configDataProcess.data.push(arr);
						}
					})
				}
		    })
		},
		//生产统计
		getProductLine() {
			let that = this;
			let obj = {
				query: { start_date: that.start_time, end_date: that.end_time, mgroup_name: that.mgroupName },
			};
			that.$API.bi.dataset.exec.req("lineDay", obj).then((res) => {
				let list = res.data2.ds0;
				if (list.length > 0) {
					list.forEach((item) => {
						let dateYes = that.yesterday.split('-')[2];
						if (item.日 == dateYes) {
							that.sctj.rjgs += item.生产数;
							that.sctj.rjgqbls += item.加工前不良;
							that.sctj.rhgs += item.合格数;
							that.sctj.rbhgs += item.不合格数;
						}
						let arr = [];
						arr[0] = item.年 + '-' + item.月 + '-' + item.日;
						arr[1] = item.物料名;
						arr[2] = item.接收数;
						arr[3] = item.生产数;
						arr[4] = item.合格数;
						arr[5] = item.交送数;
						that.configDatas.data.push(arr);
					});
					that.sctj.rhgl = Number((that.sctj.rhgs / that.sctj.rjgs * 100).toFixed(2));
					let total = that.sctj.rjgs+that.sctj.rjgqbls;
					that.sctj.rztls = Number((that.sctj.rhgs / total * 100).toFixed(2));
				}
			});
		},
		//不合格分布
		getCountnotok() {
			let that = this;
			let obj = { 
				query: { start_date: that.yesterday, end_date: that.yesterday,mgroup_name:that.mgroupName } 
			};
			that.$API.bi.dataset.exec.req('notok_dis', obj).then((res) => {
				let seriesData = [];
				if (res.data2.ds0) {
					res.data2.ds0.forEach((item) => {
						let obj = {};
						obj.name = item.不合格项;
						obj.value = item.数量;
						seriesData.push(obj);
					})
				}
				that.pieOption.series.data = seriesData;
				let index2 = 0;
				let chart2 = this.setChart("chart2", that.pieOption);
				if (!chart2) return;
				this.chartInterval2 = setInterval(function () {
					if (index2 < seriesData.length) {
						chart2.dispatchAction({ type: "downplay", seriesIndex: 0 });
						chart2.dispatchAction({ type: "highlight", seriesIndex: 0, dataIndex: index2 });
						chart2.dispatchAction({ type: "showTip", seriesIndex: 0, dataIndex: index2 });
						index2++;
					} else {
						index2 = 0;
					}
				}, 3000);
			})
		},
		//设备状态
		getEqState() {
			let that = this;
			let obj = {
				query: { query_date: that.today, mgroup_name: that.mgroupName },
			};
			that.$API.wpm.ana.equipLastMlog.req({ mgroup: that.mgroupId }).then((res) => {
				that.hh.yx = res.运行;
				that.hh.wyx = res.未运行;
				that.hh.gz = res.故障;
			});
			that.$API.bi.dataset.exec.req("equit_static", obj).then((res) => {
				let list = res.data2.ds0;
				if (list.length > 0) {
				    list.forEach((item) => {
						let arr = [];
						arr[0] = item.设备名称;
						arr[1] = item.设备编号;
						if (item.运行状态 == '运行') {
							arr[2] = '<span style="color:#00e5ff">● 运行</span>';
						} else if (item.运行状态 == '待机') {
							arr[2] = '<span style="color:#45b076">● 待机</span>';
						} else if (item.运行状态 == '停机') {
							arr[2] = '<span style="color:#de3c36">● 停机</span>';
						}else if (item.运行状态 == '故障') {
							arr[2] = '<span style="color:#de3c36">● 故障</span>';
						}else if (item.运行状态 == '离线') {
							arr[2] = '<span style="color:#de3c36">● 离线</span>';
						}
						arr[3] = item.当日加工量 ? item.当日加工量 : 0;
						arr[4] = item.累计总加工量 ? item.累计总加工量 : 0;
						that.configDataEq.data.push(arr);
					});
				}
			})
		},
		//库存统计列表
		getMaterials(page) {
			let that = this;
			let query = '{ material_name, batch, count, count_working }';
			that.$API.wpm.wmaterial.list.req({ page: page, page_size: 100, mgroup: that.mgroupId, query: query }).then((res) => {
				if (res.results.length > 0) {
					res.results.forEach((item) => {
						let arr = [];
						arr[0] = item.material_name;
						arr[1] = item.batch;
						arr[2] = item.count;
						arr[3] = item.count_working;
						that.configDataInm.data.push(arr);
					})
					if(that.configDataInm.data.length<res.count){
						that.getMaterials(page+1);
					}
				}
			})
		},
	},
};
</script>

<style scoped>
@font-face {
	font-family: "myfont";
	src: url("../../../utils/youShe.ttf");
}

.dashboard,
.dashboard * {
	box-sizing: border-box;
}

.dashboard {
	position: fixed;
	top: 0;
	left: 0;
	width: 100vw;
	height: 100vh;
	overflow: hidden;
	background: #00181c url("/public/img/photon_bg.png") center / cover no-repeat;
	color: #fff;
	font-family: "Microsoft Yahei" !important;
}

.dashboard::before {
	content: "";
	position: absolute;
	inset: 0;
	background:
		radial-gradient(ellipse at 20% 0%, rgba(0, 229, 255, 0.10), transparent 55%),
		radial-gradient(ellipse at 80% 100%, rgba(0, 122, 153, 0.18), transparent 55%);
	pointer-events: none;
	z-index: 0;
}

/* ============= Header ============= */
.dash-header {
	position: relative;
	z-index: 1;
	flex: 0 0 72px !important;
	height: 72px !important;
	padding: 0 24px !important;
	display: flex;
	align-items: center;
	justify-content: space-between;
	background: url("/public/img/photon_header.png") center / 100% 100% no-repeat;
}

.dash-header-side {
	flex: 0 0 280px;
	display: flex;
	align-items: center;
	gap: 14px;
}

.dash-header-right {
	justify-content: flex-end;
}

.dash-header-center {
	flex: 1;
	text-align: center;
}

.dash-title {
	font-family: "myfont", "Microsoft Yahei";
	font-size: 30px;
	font-weight: bold;
	letter-spacing: 8px;
	background: linear-gradient(180deg, #ffffff 0%, #b9fbff 55%, #00d4ff 100%);
	-webkit-background-clip: text;
	-webkit-text-fill-color: transparent;
	text-shadow: 0 0 22px rgba(0, 212, 255, 0.45);
	line-height: 1;
}

.dash-title-deco {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 10px;
	margin-top: 6px;
}

.dash-title-deco span {
	display: inline-block;
	width: 90px;
	height: 1px;
	background: linear-gradient(90deg, transparent, rgba(0, 229, 255, 0.7), transparent);
}

.dash-title-deco i {
	display: inline-block;
	width: 6px;
	height: 6px;
	background: #00e5ff;
	transform: rotate(45deg);
	box-shadow: 0 0 8px #00e5ff;
}

.header-tag {
	font-size: 12px;
	letter-spacing: 2px;
	padding: 4px 10px;
	border: 1px solid rgba(0, 229, 255, 0.45);
	color: #95ffff;
	background: rgba(0, 229, 255, 0.06);
	font-weight: bold;
}

.header-status {
	font-size: 13px;
	color: #95ffff;
	display: flex;
	align-items: center;
	gap: 6px;
}

.led-dot {
	width: 8px;
	height: 8px;
	border-radius: 50%;
	background: #18f1a4;
	box-shadow: 0 0 8px #18f1a4;
	animation: led-pulse 1.4s ease-in-out infinite;
}

@keyframes led-pulse {

	0%,
	100% {
		opacity: 1;
	}

	50% {
		opacity: 0.35;
	}
}

.dash-day {
	font-size: 14px;
	color: #c8f2ff;
	letter-spacing: 1px;
}

.dash-time {
	font-family: "myfont", "Microsoft Yahei";
	font-size: 22px;
	color: #fff;
	letter-spacing: 3px;
	text-shadow: 0 0 12px rgba(0, 229, 255, 0.55);
}

/* ============= Main ============= */
.dash-main {
	position: relative;
	z-index: 1;
	flex: 1 1 0 !important;
	min-height: 0;
	padding: 10px !important;
	display: flex;
	flex-direction: column;
	gap: 10px;
	overflow: hidden;
}

/* ============= KPI Strip ============= */
.kpi-row {
	display: grid;
	grid-template-columns: repeat(6, 1fr);
	gap: 10px;
	flex: 0 0 92px;
	min-height: 0;
}

.kpi-card {
	position: relative;
	padding: 10px 16px;
	background: linear-gradient(135deg, rgba(0, 60, 80, 0.55) 0%, rgba(3, 22, 26, 0.7) 100%);
	border: 1px solid rgba(0, 229, 255, 0.22);
	display: flex;
	align-items: center;
	justify-content: space-between;
	overflow: hidden;
}

.kpi-card::before {
	content: "";
	position: absolute;
	inset: 0;
	background: radial-gradient(circle at 100% 0%, rgba(0, 229, 255, 0.16), transparent 60%);
	pointer-events: none;
}

.kpi-card::after {
	content: "";
	position: absolute;
	top: 0;
	left: 0;
	width: 3px;
	height: 100%;
	background: #00e5ff;
	box-shadow: 0 0 10px #00e5ff;
}

.kpi-meta {
	z-index: 1;
}

.kpi-label {
	font-size: 15px;
	letter-spacing: 2px;
	color: #d8f6ff;
	font-weight: 500;
}

.kpi-sub {
	font-size: 10px;
	letter-spacing: 2px;
	color: rgba(149, 255, 255, 0.45);
	margin-top: 4px;
}

.kpi-value {
	font-family: "myfont", "Microsoft Yahei";
	font-size: 34px;
	font-weight: bold;
	letter-spacing: 1px;
	z-index: 1;
	line-height: 1;
}

.kpi-bar {
	position: absolute;
	left: 0;
	bottom: 0;
	height: 2px;
	width: 100%;
}

.kpi-c1 .kpi-value {
	color: #95ffff;
	text-shadow: 0 0 14px rgba(0, 229, 255, 0.55);
}

.kpi-c1::after {
	background: #00e5ff;
	box-shadow: 0 0 10px #00e5ff;
}

.kpi-c1 .kpi-bar {
	background: linear-gradient(90deg, #00e5ff, transparent);
}

.kpi-c2 .kpi-value {
	color: #c5ff7a;
	text-shadow: 0 0 14px rgba(170, 255, 102, 0.55);
}

.kpi-c2::after {
	background: #aaff66;
	box-shadow: 0 0 10px #aaff66;
}

.kpi-c2 .kpi-bar {
	background: linear-gradient(90deg, #aaff66, transparent);
}

.kpi-c3 .kpi-value {
	color: #ffd87a;
	text-shadow: 0 0 14px rgba(255, 200, 80, 0.55);
}

.kpi-c3::after {
	background: #ffb74d;
	box-shadow: 0 0 10px #ffb74d;
}

.kpi-c3 .kpi-bar {
	background: linear-gradient(90deg, #ffb74d, transparent);
}

.kpi-c4 .kpi-value {
	color: #7af0a8;
	text-shadow: 0 0 14px rgba(45, 210, 140, 0.55);
}

.kpi-c4::after {
	background: #2dd28c;
	box-shadow: 0 0 10px #2dd28c;
}

.kpi-c4 .kpi-bar {
	background: linear-gradient(90deg, #2dd28c, transparent);
}

.kpi-c5 .kpi-value {
	color: #ff8a8a;
	text-shadow: 0 0 14px rgba(255, 107, 107, 0.55);
}

.kpi-c5::after {
	background: #ff6b6b;
	box-shadow: 0 0 10px #ff6b6b;
}

.kpi-c5 .kpi-bar {
	background: linear-gradient(90deg, #ff6b6b, transparent);
}

/* ============= Content Rows ============= */
.row-top,
.row-bottom {
	display: flex;
	min-height: 0;
	margin: 0 !important;
}

.row-top {
	flex: 1.15 1 0;
}

.row-bottom {
	flex: 1 1 0;
}

.col-full {
	height: 100%;
	display: flex;
	flex-direction: column;
}

/* ============= Panel ============= */
.panel {
	position: relative;
	height: 100%;
	background: linear-gradient(180deg, rgba(10, 63, 68, 0.45) 0%, rgba(3, 22, 26, 0.65) 100%);
	border: 1px solid rgba(0, 229, 255, 0.18);
	display: flex;
	flex-direction: column;
	overflow: hidden;
}

.panel-head {
	position: relative;
	height: 36px;
	flex: 0 0 36px;
	padding: 0 12px;
	display: flex;
	align-items: center;
	gap: 12px;
	background: linear-gradient(90deg, rgba(0, 229, 255, 0.16) 0%, rgba(0, 229, 255, 0.02) 60%, rgba(0, 229, 255, 0.08) 100%);
	border-bottom: 1px solid rgba(0, 229, 255, 0.18);
}

.panel-head::before {
	content: "";
	width: 4px;
	height: 16px;
	background: linear-gradient(180deg, #00e5ff, #007a99);
	box-shadow: 0 0 6px rgba(0, 229, 255, 0.6);
}

.panel-title {
	font-size: 16px;
	font-weight: 600;
	color: #fff;
	letter-spacing: 2px;
}

.panel-sub {
	font-size: 11px;
	letter-spacing: 2px;
	color: rgba(149, 255, 255, 0.5);
	font-weight: 300;
}

.panel-states {
	margin-left: auto;
	display: flex;
	gap: 6px;
}

.state-chip {
	font-size: 12px;
	padding: 2px 8px;
	display: flex;
	align-items: center;
	gap: 5px;
	background: rgba(255, 255, 255, 0.04);
	border: 1px solid rgba(255, 255, 255, 0.08);
	color: #d8f6ff;
}

.state-chip i {
	width: 7px;
	height: 7px;
	border-radius: 50%;
	display: inline-block;
}

.state-chip em {
	font-style: normal;
	font-weight: bold;
	color: #fff;
	margin-left: 3px;
}

.s-run i {
	background: #00a3f5;
	box-shadow: 0 0 6px #00a3f5;
}

.s-idle i {
	background: #45b076;
	box-shadow: 0 0 6px #45b076;
}

.s-err i {
	background: #de3c36;
	box-shadow: 0 0 6px #de3c36;
}

.panel-body {
	flex: 1 1 0;
	min-height: 0;
	padding: 8px;
	position: relative;
	overflow: hidden;
}

.chart-body {
	padding: 4px;
}

.board {
	width: 100%;
	height: 100%;
}

/* ============= Corner brackets ============= */
.corner {
	position: absolute;
	width: 12px;
	height: 12px;
	border-color: #00e5ff;
	border-style: solid;
	pointer-events: none;
	z-index: 2;
}

.corner.tl {
	top: -1px;
	left: -1px;
	border-width: 2px 0 0 2px;
}

.corner.tr {
	top: -1px;
	right: -1px;
	border-width: 2px 2px 0 0;
}

.corner.bl {
	bottom: -1px;
	left: -1px;
	border-width: 0 0 2px 2px;
}

.corner.br {
	bottom: -1px;
	right: -1px;
	border-width: 0 2px 2px 0;
}
</style>
