/* แล็บ IoT — เวทีเครือข่ายซ้าย / ตัวสร้างกฎขวา */
:root{
  --sans:'IBM Plex Sans Thai','Noto Sans Thai',system-ui,-apple-system,'Segoe UI',sans-serif;
  --ink:#191a24; --muted:#6b6c7e; --line:#e6e3dc; --surface:#fff; --bg:#f5f4ef;
  --brand:#2e7d88; --brand-ink:#1f5f68; --brand-soft:#dcecee;
  --ok:#129a72; --warn:#d68a17; --danger:#e2564a; --net:#2f8fe0;
}
*{box-sizing:border-box}
html,body{margin:0;height:100%;overflow:hidden}
body{font-family:var(--sans);color:var(--ink);background:var(--bg);display:flex;flex-direction:column;
  -webkit-font-smoothing:antialiased;user-select:none;-webkit-user-select:none}

#stage{position:relative;flex:1;min-height:0;background:#0f1524;display:flex;flex-direction:column;overflow:hidden}

/* ---------- กระดานลากวาง ---------- */
#board{position:relative;flex:1;min-height:0;overflow:hidden;touch-action:none;
  background:radial-gradient(circle at 50% 36%, rgba(47,143,224,.16), transparent 62%);}
#board::before{content:'';position:absolute;inset:0;pointer-events:none;
  background-image:linear-gradient(rgba(120,150,220,.05) 1px,transparent 1px),
                   linear-gradient(90deg,rgba(120,150,220,.05) 1px,transparent 1px);
  background-size:30px 30px;}
#wires{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;z-index:1}
#nodes{position:absolute;inset:0;z-index:2}
.board-hint{position:absolute;left:50%;bottom:12px;transform:translateX(-50%);z-index:1;
  color:#5f6b90;font-size:.76rem;pointer-events:none;text-align:center;white-space:nowrap}
.board-hint.gone{display:none}

.cloud-node{position:absolute;left:50%;top:34%;transform:translate(-50%,-50%);z-index:3;
  display:flex;flex-direction:column;align-items:center;gap:1px;pointer-events:none;
  padding:11px 20px;border-radius:18px;background:rgba(47,143,224,.15);border:1.5px solid #2f8fe0;
  box-shadow:0 0 32px rgba(47,143,224,.45);color:#cfe6ff}
.cloud-ic{font-size:1.7rem;line-height:1}
.cloud-tx{font-size:.68rem;font-weight:700}

.dev-node{position:absolute;transform:translate(-50%,-50%);z-index:4;
  display:flex;flex-direction:column;align-items:center;gap:2px;width:76px;
  padding:8px 6px;border-radius:12px;background:#1a2438;border:1.5px solid #34406a;
  color:#dfe6f5;cursor:grab;touch-action:none;box-shadow:0 4px 12px rgba(0,0,0,.35);transition:box-shadow .15s,border-color .15s}
.dev-node.dragging{cursor:grabbing;z-index:9;box-shadow:0 12px 26px rgba(0,0,0,.55)}
.dev-node.sensor{border-color:#2f7d5e}
.dev-node.actuator{border-color:#5a49a0}
.dev-node .di{font-size:1.5rem;line-height:1;pointer-events:none}
.dev-node .dn{font-size:.6rem;text-align:center;line-height:1.1;pointer-events:none}
.dev-node .drm{position:absolute;top:-8px;right:-8px;width:19px;height:19px;border-radius:50%;
  background:#e2564a;color:#fff;border:none;font-size:.72rem;cursor:pointer;display:none;
  align-items:center;justify-content:center;line-height:1}
.dev-node:hover .drm,.dev-node.dragging .drm{display:flex}
.dev-node.linked.sensor{border-color:#3ddc9a}
.dev-node.linked.actuator{border-color:#9a7bff}
.dev-node.on{box-shadow:0 0 24px rgba(57,217,138,.7);border-color:#39d98a}
.dev-node.on.alarmish{box-shadow:0 0 24px rgba(255,107,125,.75);border-color:#ff6b7d}

/* ---------- คลังอุปกรณ์ ---------- */
#palette{flex:none;background:#141a2c;border-top:1px solid #2b3350;padding:8px 10px;
  display:flex;gap:16px;overflow-x:auto;overflow-y:hidden}
.pal-group{display:flex;flex-direction:column;gap:4px}
.pal-head{font-size:.6rem;font-weight:700;color:#7f8bb0;text-transform:uppercase;letter-spacing:.05em}
.pal-row{display:flex;gap:6px}
.pal-chip{display:flex;flex-direction:column;align-items:center;gap:1px;width:56px;flex:none;padding:6px 4px;
  border-radius:10px;background:#1a2438;border:1px solid #34406a;color:#cfd6ea;cursor:grab;touch-action:none}
.pal-chip.sensor{border-color:#2b6b52}
.pal-chip.actuator{border-color:#4b3f8a}
.pal-chip.placed{opacity:.32;cursor:default}
.pal-chip .pi{font-size:1.25rem;line-height:1;pointer-events:none}
.pal-chip .pn{font-size:.55rem;text-align:center;line-height:1.05;pointer-events:none}

.drag-ghost{position:fixed;z-index:100;pointer-events:none;transform:translate(-50%,-50%);
  width:60px;padding:7px 4px;border-radius:11px;background:#1a2438;border:1.5px solid #2e7d88;color:#fff;
  display:flex;flex-direction:column;align-items:center;gap:1px;box-shadow:0 10px 24px rgba(0,0,0,.55);opacity:.95}
.drag-ghost .pi{font-size:1.3rem}.drag-ghost .pn{font-size:.55rem;text-align:center}

.wire{stroke:#2f8fe0;stroke-width:2;fill:none;opacity:.4}
.wire.rule{stroke:#3ddc9a;stroke-width:2.5;opacity:.75}
.packet{fill:#7fe0ff}

.status{
  position:absolute;left:12px;top:12px;right:96px;
  background:rgba(255,255,255,.95);border:1px solid var(--line);border-radius:12px;
  padding:8px 13px;font-size:.82rem;box-shadow:0 4px 14px rgba(0,0,0,.25);
  pointer-events:none;max-width:min(560px,calc(100% - 120px));line-height:1.5;
}
.status.ok{border-color:#bfe9da;color:#0a6b50;background:#f0fbf7}
.status.bad{border-color:#f6cdc9;color:#8f2018;background:#fdf3f2}
.status.warn{border-color:#f7e2bd;color:#7d5209;background:#fffaf0}

/* ---------- แดชบอร์ด ---------- */
.dash{
  position:absolute;right:12px;top:58px;max-width:min(300px,calc(100% - 24px));z-index:6;
  background:rgba(255,255,255,.96);border:1px solid var(--line);border-radius:14px;
  padding:10px 12px;box-shadow:0 6px 20px rgba(0,0,0,.3);max-height:52%;overflow-y:auto;
}
.dash-head{font-size:.72rem;font-weight:700;color:var(--muted);margin-bottom:6px;letter-spacing:.02em}
.dash-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(96px,1fr));gap:6px}
.dcard{display:flex;flex-direction:column;gap:1px;padding:6px 8px;border-radius:9px;background:var(--bg);border:1px solid var(--line)}
.dcard .dl{font-size:.66rem;color:var(--muted);display:flex;align-items:center;gap:3px}
.dcard .dv{font-size:.95rem;font-weight:700;font-variant-numeric:tabular-nums}
.dcard.act{background:#0f1524;border-color:#2b3350}
.dcard.act .dl{color:#9aa4c4}
.dcard.act .dv{color:#59627e}
.dcard.act.on{background:#123a2a;border-color:#1c6b47}
.dcard.act.on .dv{color:#39d98a}
.dcard.on-alarm.on{background:#3a1620;border-color:#7a2233}
.dcard.on-alarm.on .dv{color:#ff6b7d}

/* ---------- แผงสร้างกฎ ---------- */
#panel{
  flex:none;background:var(--surface);border-top:1px solid var(--line);
  padding:12px 14px 14px;display:flex;flex-direction:column;gap:9px;max-height:52vh;overflow-y:auto;
}
.panel-head{display:flex;align-items:baseline;gap:10px}
.panel-title{font-weight:700;font-size:.92rem}
.goal{font-size:.78rem;color:var(--muted);margin-left:auto;text-align:right}
.hint{margin:0;font-size:.74rem;color:var(--muted);line-height:1.5}
.btn-add{align-self:flex-start;background:var(--brand-soft);color:var(--brand-ink);border:1px solid var(--brand-soft)}

.rule-list{display:flex;flex-direction:column;gap:7px;min-height:40px}
.rule-empty{margin:6px auto;color:#a0a1b0;font-size:.8rem}
.rule{
  display:flex;flex-wrap:wrap;align-items:center;gap:5px;padding:8px 9px;
  border:1px solid var(--line);border-left:3px solid var(--brand);border-radius:10px;background:var(--bg);
}
.rule .kw{font-size:.74rem;color:var(--muted);font-weight:600}
.rule select,.rule input{
  font-family:inherit;font-size:.78rem;border:1px solid var(--line);border-radius:7px;
  padding:4px 6px;background:#fff;color:var(--ink);
}
.rule input[type=number]{width:56px}
.rule .rm{margin-left:auto;border:none;background:none;color:#b9bac6;cursor:pointer;font-size:.9rem}
.rule .rm:hover{color:var(--danger)}

.tasks{display:flex;flex-direction:column;gap:5px}
.tk-head{font-size:.78rem;font-weight:600;color:var(--muted)}
.tk-head span:last-child{background:var(--brand-soft);color:var(--brand-ink);padding:1px 8px;border-radius:999px;font-size:.72rem}
.task-list{display:flex;flex-direction:column;gap:4px}
.task-item{display:flex;align-items:center;gap:7px;font-size:.78rem;padding:6px 9px;border-radius:8px;background:var(--bg)}
.task-item.is-done{background:#e9f8f2;color:#0a6b50}
.task-check{width:16px;height:16px;border-radius:50%;border:2px solid var(--line);flex:none}
.task-item.is-done .task-check{background:var(--ok);border-color:var(--ok)}

.actions{display:flex;gap:8px}
.btn{padding:10px 14px;border-radius:999px;border:1px solid transparent;font-family:inherit;
  font-size:.84rem;font-weight:600;cursor:pointer;box-shadow:0 2px 6px rgba(25,26,36,.12)}
.btn:active{transform:translateY(1px)}
.btn[disabled]{opacity:.45;pointer-events:none}
.btn-ghost{background:var(--surface);border-color:var(--line);color:var(--ink);flex:1}
.btn-run{background:var(--brand);color:#fff;flex:2}
.btn-submit{background:var(--ok);color:#fff;flex:1}

/* ---------- กล่องโค้ด ---------- */
.modal{position:fixed;inset:0;z-index:50;display:flex;align-items:center;justify-content:center;background:rgba(6,10,20,.6);padding:18px}
.modal[hidden]{display:none}
.modal-box{background:#fff;border-radius:16px;max-width:min(660px,100%);width:100%;max-height:86vh;display:flex;flex-direction:column;box-shadow:0 18px 50px rgba(0,0,0,.4);overflow:hidden}
.modal-head{display:flex;align-items:center;justify-content:space-between;padding:14px 16px;border-bottom:1px solid var(--line);font-weight:700}
.modal-x{border:none;background:none;font-size:1.1rem;cursor:pointer;color:var(--muted)}
.code{margin:0;padding:16px;overflow:auto;background:#0f1117;color:#e6e6ee;font-size:.8rem;line-height:1.5;
  font-family:'SF Mono',ui-monospace,Menlo,Consolas,monospace;white-space:pre;flex:1}
.modal-foot{padding:12px 16px;border-top:1px solid var(--line);display:flex;justify-content:flex-end}
.modal-foot .btn{flex:none}

@media (min-width:900px){
  body{flex-direction:row}
  #panel{width:352px;max-height:none;height:100%;border-top:none;border-left:1px solid var(--line);padding:16px}
}
@media (max-width:560px){
  .status{left:8px;top:8px;right:8px;max-width:none}
  .dash{top:auto;bottom:8px;right:8px;left:8px;max-width:none;max-height:38%}
  #stage{min-height:52vh}
  #board{min-height:220px}
}

/* ---------- สลับมุมมอง + ห้องจำลอง 3D ---------- */
.view-tabs{position:absolute;left:50%;top:10px;transform:translateX(-50%);z-index:8;
  display:flex;gap:3px;background:rgba(20,26,44,.82);border:1px solid #2b3350;border-radius:999px;padding:3px;
  box-shadow:0 4px 14px rgba(0,0,0,.3)}
.vtab{font-family:inherit;font-size:.76rem;font-weight:700;color:#9aa3bd;background:none;border:none;
  cursor:pointer;padding:6px 15px;border-radius:999px;line-height:1.2;display:inline-flex;align-items:center;gap:5px}
.vtab:hover{color:#cdd4e6}
.vtab.is-on{background:#2e7d88;color:#fff}
#room3d{position:absolute;inset:0;z-index:7;background:#0e1730}
#room3d canvas{display:block;width:100%;height:100%;touch-action:none}
.room-hint{position:absolute;left:50%;bottom:14px;transform:translateX(-50%);z-index:2;
  background:rgba(20,26,44,.85);color:#cdd4e6;font-size:.8rem;font-weight:600;padding:8px 15px;
  border-radius:999px;pointer-events:none;max-width:90%;text-align:center}

/* ---------- โหมดทดสอบค่าเซนเซอร์ ---------- */
.test-panel{left:12px;right:auto;top:58px;max-width:min(300px,calc(100% - 24px))}
.test-knobs{display:flex;flex-direction:column;gap:10px}
.test-knobs .pgknob-label{color:#3a3f4c}
.test-bool{display:flex;align-items:center;gap:8px}
.tb-name{flex:1;min-width:0;font-size:.78rem;color:#3a3f4c;display:inline-flex;align-items:center;gap:5px}
.tb-toggle{font-family:inherit;font-size:.74rem;font-weight:700;border-radius:999px;
  border:1.5px solid var(--line,#e6e3dc);background:#fff;color:#6b6c7e;padding:5px 13px;cursor:pointer}
.tb-toggle.on{background:#39d98a;border-color:#39d98a;color:#fff}
