:root{font-family:Inter,"Microsoft YaHei",system-ui,sans-serif;color:#dce8f1;background:#07131d;--bg:#07131d;--panel:#0d1d29;--panel2:#102432;--line:#263d4d;--cyan:#45d9ce;--muted:#88a0b0}*{box-sizing:border-box}body{margin:0;min-width:900px;overflow:hidden;background:var(--bg)}button,input,select,textarea{font:inherit}.app-shell{height:100vh;display:flex;flex-direction:column}header{height:58px;flex:none;display:flex;align-items:center;justify-content:space-between;padding:0 18px;border-bottom:1px solid var(--line);background:#0a1924}.brand{display:flex;align-items:center;gap:12px}.brand b{color:var(--cyan);font-size:13px;border:1px solid #2d6e70;padding:6px 8px;border-radius:6px}.brand span{font-weight:700}.status{font-size:13px;color:var(--muted);display:flex;align-items:center;gap:7px}.status i{width:8px;height:8px;border-radius:50%;background:#9d3434}.status.online i{background:var(--cyan);box-shadow:0 0 10px var(--cyan)}.workspace{height:calc(100vh - 58px);display:flex;min-height:0}.sidebar{width:250px;flex:none;overflow:auto;border-right:1px solid var(--line);background:#0a1822;padding:10px}.sidebar section{padding:9px 4px 12px;border-bottom:1px solid #1d3342}.sidebar h3{font-size:13px;margin:0 0 8px;color:#bcd0dc}.sidebar label:not(.check){display:grid;grid-template-columns:64px 1fr;align-items:center;gap:6px;font-size:12px;color:var(--muted);margin:6px 0}.sidebar select,.sidebar input,.cmd input{min-width:0;background:#07141e;color:#e5eef4;border:1px solid var(--line);border-radius:5px;padding:6px}.wide{width:100%;margin-top:6px}.primary,.ghost,.mini,.sendbtn,.ymodem,.linkbtn,.cmd button,#closeCmd{cursor:pointer}.primary{border:0;background:var(--cyan);color:#05211f;padding:8px;border-radius:6px;font-weight:700}.ghost{border:1px solid var(--line);background:#102532;color:#c7d9e3;padding:7px;border-radius:6px}.check{display:flex;align-items:center;gap:7px;font-size:12px;margin:8px 0;color:#c5d5df}.check input{accent-color:var(--cyan)}.sub{opacity:.8}.sub input{width:58px}.pair{display:flex;justify-content:space-between;margin-top:8px}.linkbtn{border:0;background:transparent;color:#55bfea;padding:4px}.ymodem{width:100%;margin-top:12px;border:1px solid #347c7c;background:#102d32;color:#72e5db;padding:10px;border-radius:7px;font-weight:700}.mainpanel{flex:1;min-width:0;display:flex;flex-direction:column;padding:10px;gap:7px}.rx-head,.send-head,.bottom{height:28px;display:flex;align-items:center;justify-content:space-between;font-size:12px;color:var(--muted)}.rx-head b,.send-head b{color:#dce8f1}.rx-head div{display:flex;align-items:center;gap:12px}.mini{border:1px solid var(--line);background:#102532;color:#cbdbe4;border-radius:5px;padding:4px 9px}.receive{flex:1;min-height:160px;margin:0;overflow:auto;background:#050d13;border:1px solid var(--line);border-radius:5px;padding:10px;white-space:pre-wrap;overflow-wrap:anywhere;color:#dce8f1;font:13px/1.55 Consolas,monospace}.sendrow{height:126px;display:flex;gap:7px}.sendrow textarea{flex:1;resize:none;background:#07141e;color:#e7f0f5;border:1px solid var(--line);border-radius:5px;padding:10px;font:13px/1.5 Consolas,monospace;outline:none}.sendbtn{width:82px;border:1px solid #347c7c;background:#10343a;color:#7aeee4;border-radius:6px;font-size:28px}.sendbtn small{display:block;font-size:12px;margin-top:4px}.sendbtn:disabled{opacity:.35}.bottom{border-top:1px solid #182d3b;padding-top:4px}.bottom #msg{flex:1;text-align:center}.commands{width:410px;flex:none;border-left:1px solid var(--line);background:#0a1822;padding:10px;overflow:auto;transition:.2s}.commands.hidden{width:0;padding-left:0;padding-right:0;border:0;overflow:hidden}.cmdtitle{display:flex;justify-content:space-between;align-items:center;margin-bottom:9px}.cmdtitle b{font-size:13px}.cmdtitle button{background:transparent;border:0;color:#b9cbd6;font-size:20px}.cmd{display:grid;grid-template-columns:48px 1fr 54px 34px;gap:5px;align-items:center;margin:7px 0}.cmd label{font-size:11px;color:var(--muted);display:flex;align-items:center;gap:3px}.cmd button{height:31px;border:1px solid #347c7c;background:#10343a;color:#70e8de;border-radius:5px}@media(max-height:700px){header{height:48px}.workspace{height:calc(100vh - 48px)}.sidebar section{padding-top:5px;padding-bottom:7px}.sidebar label:not(.check){margin:4px 0}.check{margin:5px 0}.sendrow{height:96px}}

/* V2.1 compact sidebar: keep all daily controls visible without vertical scrolling */
.sidebar{width:232px;padding:6px;overflow:hidden;font-size:11px}
.sidebar section{padding:5px 3px 6px}
.sidebar h3{font-size:11px;margin:0 0 4px}
.sidebar label:not(.check){grid-template-columns:52px 1fr;gap:4px;font-size:11px;margin:3px 0}
.sidebar select,.sidebar input{height:25px;padding:2px 5px;font-size:11px;border-radius:4px}
.primary,.ghost{padding:5px 6px;font-size:11px;border-radius:4px}
.wide{margin-top:4px}
.check{gap:5px;font-size:11px;margin:4px 0;line-height:1.2}
.check input{width:13px;height:13px;margin:0}
.sub{font-size:10px!important}
.sub input{width:52px!important;height:23px!important}
.pair{margin-top:3px}
.linkbtn{font-size:11px;padding:2px 3px}
.ymodem{margin-top:6px;padding:6px;font-size:11px;border-radius:5px}
@media(max-height:760px){
  header{height:44px}.workspace{height:calc(100vh - 44px)}
  .sidebar{padding:4px}.sidebar section{padding:3px 2px 4px}
  .sidebar h3{margin-bottom:2px}.sidebar label:not(.check){margin:2px 0}
  .sidebar select,.sidebar input{height:23px}.primary,.ghost{padding:4px 5px}
  .check{margin:3px 0}.ymodem{margin-top:4px;padding:5px}
  .sendrow{height:90px}
}

/* V2.2 responsive desktop layout */
:root{
  --header-h:clamp(40px,6.2vh,58px);
  --side-w:clamp(188px,19vw,242px);
  --ui-font:clamp(10px,1.45vh,13px);
  --ui-h:clamp(21px,3.35vh,30px);
  --ui-gap:clamp(2px,.55vh,7px);
  --side-pad:clamp(4px,.7vh,9px);
}
body{min-width:680px;min-height:420px;overflow:hidden}
header{height:var(--header-h);padding:0 clamp(8px,1.4vw,18px)}
.brand{gap:clamp(6px,1vw,12px)}
.brand b{font-size:clamp(10px,1.5vh,13px);padding:clamp(3px,.7vh,6px) clamp(5px,.7vw,8px)}
.brand span,.status{font-size:clamp(10px,1.55vh,13px)}
.workspace{height:calc(100vh - var(--header-h));min-height:0}
.sidebar{width:var(--side-w);padding:var(--side-pad);font-size:var(--ui-font);overflow:hidden}
.sidebar section{padding:clamp(2px,.6vh,7px) 3px clamp(3px,.7vh,8px)}
.sidebar h3{font-size:var(--ui-font);margin:0 0 clamp(2px,.45vh,5px)}
.sidebar label:not(.check){grid-template-columns:clamp(45px,5.2vw,62px) minmax(0,1fr);gap:clamp(3px,.45vw,6px);font-size:var(--ui-font);margin:var(--ui-gap) 0}
.sidebar select,.sidebar input{height:var(--ui-h);padding:1px clamp(3px,.45vw,6px);font-size:var(--ui-font)}
.primary,.ghost{min-height:var(--ui-h);padding:clamp(2px,.5vh,6px);font-size:var(--ui-font)}
.wide{margin-top:var(--ui-gap)}
.check{gap:clamp(3px,.4vw,6px);font-size:var(--ui-font);margin:var(--ui-gap) 0;line-height:1.1}
.check input{width:clamp(11px,1.6vh,14px);height:clamp(11px,1.6vh,14px)}
.sub{font-size:clamp(9px,1.25vh,11px)!important}
.sub input{width:clamp(42px,4.8vw,58px)!important;height:var(--ui-h)!important}
.pair{margin-top:var(--ui-gap)}
.linkbtn{font-size:var(--ui-font);padding:clamp(1px,.3vh,4px)}
.ymodem{margin-top:clamp(3px,.7vh,8px);padding:clamp(4px,.75vh,9px);font-size:var(--ui-font)}
.mainpanel{padding:clamp(4px,.8vh,10px);gap:clamp(3px,.65vh,7px)}
.rx-head,.send-head,.bottom{height:clamp(21px,3.4vh,30px);font-size:clamp(10px,1.45vh,12px)}
.receive{min-height:70px;padding:clamp(5px,.8vh,10px);font-size:clamp(10px,1.65vh,13px);line-height:1.45}
.sendrow{height:clamp(72px,17vh,132px);min-height:58px;gap:clamp(4px,.6vw,7px)}
.sendrow textarea{padding:clamp(5px,.8vh,10px);font-size:clamp(10px,1.65vh,13px)}
.sendbtn{width:clamp(58px,7vw,82px);font-size:clamp(20px,3.2vh,28px)}
.sendbtn small{font-size:clamp(9px,1.4vh,12px);margin-top:clamp(1px,.4vh,4px)}
.commands{width:clamp(300px,32vw,410px);padding:clamp(5px,.8vh,10px)}
.commands.hidden{width:0;padding-left:0;padding-right:0}
.cmd{grid-template-columns:clamp(40px,4vw,48px) minmax(90px,1fr) clamp(46px,4.8vw,54px) clamp(30px,3vw,34px);gap:clamp(3px,.4vw,5px);margin:clamp(4px,.7vh,7px) 0}
.cmd input,.cmd button{min-height:var(--ui-h);font-size:var(--ui-font)}
.cmd label{font-size:clamp(9px,1.3vh,11px)}

/* Short windows: keep all primary controls visible, then sacrifice terminal area first. */
@media(max-height:620px){
  :root{--header-h:38px;--ui-font:10px;--ui-h:20px;--ui-gap:1px;--side-pad:3px}
  .brand b{padding:2px 5px}.sidebar section{padding:2px 2px 3px}.sidebar h3{margin-bottom:1px}
  .check{line-height:1}.ymodem{margin-top:2px;padding:3px}.sendrow{height:62px}.receive{min-height:48px}
}
@media(max-height:500px){
  .sidebar{overflow-y:auto;scrollbar-width:thin}.sendrow{height:54px}.rx-head,.send-head,.bottom{height:19px}
}

/* Narrow desktop windows: shrink side panels first. */
@media(max-width:1000px){
  :root{--side-w:clamp(180px,22vw,215px)}
  .commands{width:clamp(270px,34vw,350px)}
}
@media(max-width:780px){
  :root{--side-w:178px}
  .brand span{display:none}.commands{position:absolute;right:0;top:0;bottom:0;z-index:10;width:min(330px,48vw);box-shadow:-8px 0 20px #0008}
  .commands.hidden{width:0}.sendbtn{width:54px}.rx-head div{gap:5px}
}

/* V2.3 single open/close serial button */
#portToggle.disconnecting{background:#4b2528;border-color:#7b3a40;color:#ffd9dc}
#portToggle.disconnecting:hover{background:#5a2b2f}
#portToggle:disabled{opacity:.55;cursor:not-allowed}

/* V2.9: 扩展命令最多 100 条，面板内部滚动查看 */
.commands{overflow-y:auto;overflow-x:hidden;scrollbar-gutter:stable;}
.cmdtitle{position:sticky;top:0;z-index:2;background:#0a1822;padding:2px 0 7px;}


/* V2.10: conditional timing options and aligned ms fields */
.option-row{
  display:grid!important;
  grid-template-columns:minmax(0,1fr) 58px 18px!important;
  align-items:center!important;
  gap:5px!important;
  margin:3px 0 5px 18px!important;
  padding:0!important;
}
.option-row input{
  width:58px!important;
  min-width:0!important;
  text-align:right;
}
.option-row span:last-child{
  text-align:left;
  white-space:nowrap;
}
.hidden-option{display:none!important;}
@media(max-width:1000px){
  .option-row{grid-template-columns:minmax(0,1fr) 52px 18px!important;margin-left:16px!important;}
  .option-row input{width:52px!important;}
}

/* V2.11: true interactive terminal mode */
.terminal-hidden{display:none!important;}
.receive.terminal-active{
  flex:1;
  min-height:0;
  outline:none;
  cursor:text;
  white-space:pre-wrap;
  background:#050d13;
  caret-color:transparent;
  position:relative;
  padding-bottom:28px;
}
.receive.terminal-active:focus{
  border-color:#347c7c;
  box-shadow:inset 0 0 0 1px #173d43;
}
.receive.terminal-active::after{
  content:"";
  display:inline-block;
  width:.62em;
  height:1.05em;
  margin-left:1px;
  vertical-align:-.16em;
  background:#8d9aa1;
  animation:terminal-cursor-blink 1s steps(1,end) infinite;
}
@keyframes terminal-cursor-blink{0%,48%{opacity:1}49%,100%{opacity:0}}

/* V2.12 YMODEM modal */
.modal{position:fixed;inset:0;z-index:100;background:#0007;display:flex;align-items:center;justify-content:center;padding:18px}
.hidden-modal{display:none!important}
.modal-card{width:min(650px,94vw);background:#f7f9fb;color:#34404a;border-radius:8px;box-shadow:0 18px 55px #0009;overflow:hidden}
.modal-head{height:52px;display:flex;align-items:center;justify-content:space-between;padding:0 18px;border-bottom:1px solid #dce3e8;font-size:20px}.modal-head button{border:0;background:transparent;font-size:25px;color:#7b858d;cursor:pointer}
.ym-warn{margin:14px 18px;padding:12px 16px;background:#fff4df;color:#e58b16;border-radius:6px}.ym-section{padding:12px 18px}.ym-label{margin-bottom:9px;font-size:15px}.ym-file-row{display:grid;grid-template-columns:minmax(0,1fr) auto auto auto;gap:10px;align-items:center}.ym-file-row input{min-width:0;height:32px}.ym-badge{padding:6px 9px;border:1px solid #bcd5ee;background:#eef7ff;border-radius:5px;white-space:nowrap}.ym-grid{display:grid;grid-template-columns:1fr 1fr;gap:34px}.ym-grid small{display:block;margin-bottom:7px;color:#7b858d}.seg{display:flex}.seg button{padding:7px 15px;border:1px solid #cbd5df;background:#fff}.seg button:first-child{border-radius:5px 0 0 5px}.seg button:last-child{border-radius:0 5px 5px 0}.seg .active{background:#3395f5;color:#fff;border-color:#3395f5}.seg button:disabled{color:#aab2b9;background:#f2f4f6}.progress{height:10px;background:#e3e9ee;border-radius:6px;overflow:hidden}.progress i{display:block;width:0;height:100%;background:#3395f5;transition:width .15s}.ym-progress-line{display:flex;justify-content:space-between;margin-top:8px;font-size:13px}.ym-actions{display:flex;justify-content:flex-end;gap:12px;padding:16px 18px;border-top:1px solid #dce3e8}.ym-actions button{min-width:84px;padding:8px 16px}.ym-actions .primary:disabled{opacity:.45}
@media(max-width:650px){.ym-file-row{grid-template-columns:1fr auto auto}.ym-badge{grid-column:1/-1;width:max-content}.ym-grid{gap:12px}.modal-card{max-height:94vh;overflow:auto}}

/* V2.13 - YMODEM follows the existing serial-tool theme */
.modal{background:#0009}
.modal-card{width:min(650px,94vw);background:var(--panel);color:#dce8f1;border:1px solid var(--line);border-radius:7px;box-shadow:0 18px 55px #000b}
.modal-head{height:48px;padding:0 14px;border-bottom:1px solid var(--line);font-size:16px;background:#0a1924}
.modal-head button{color:var(--muted)}
.ym-warn{margin:12px 14px;padding:9px 11px;background:#2b2517;color:#e8c36b;border:1px solid #514629;border-radius:5px;font-size:12px}
.ym-section{padding:11px 14px}.ym-label{margin-bottom:8px;font-size:13px;color:#c8d8e2}
.ym-file-row{gap:7px}.ym-file-row input{height:31px;background:#07141e;color:#e5eef4;border:1px solid var(--line);border-radius:5px;padding:6px}
.ym-file-row button:not(.primary),.ym-actions button:not(.primary){border:1px solid var(--line);background:#102532;color:#c7d9e3;border-radius:5px;cursor:pointer}
.ym-badge{padding:6px 8px;border:1px solid var(--line);background:#102532;color:#c7d9e3;border-radius:5px}
.ym-grid{gap:24px}.ym-grid small{color:var(--muted)}
.seg button{padding:6px 13px;border:1px solid var(--line);background:#102532;color:#c7d9e3}.seg .active{background:#10343a;color:#7aeee4;border-color:#347c7c}.seg button:disabled{color:#657986;background:#0b1923;border-color:#203541}
.progress{height:8px;background:#07141e;border:1px solid #203541}.progress i{background:var(--cyan)}
.ym-progress-line{color:var(--muted)}.ym-actions{padding:12px 14px;border-top:1px solid var(--line);background:#0a1924}
.ym-actions button{min-width:82px;padding:7px 14px}.ym-actions .primary:disabled{opacity:.35}


/* V2.19 - stable responsive sidebar, no forced row heights */
.sidebar{
  display:flex;
  flex-direction:column;
  justify-content:flex-start;
  gap:clamp(5px,1vh,11px);
  overflow:hidden;
}
.sidebar section{
  flex:0 0 auto;
  padding:clamp(5px,.85vh,9px) 3px clamp(6px,.95vh,10px);
}
.sidebar h3{
  font-size:clamp(11px,1.55vh,13px);
  margin:0 0 clamp(3px,.55vh,6px);
}
.sidebar label:not(.check){
  margin:clamp(3px,.55vh,6px) 0;
}
.check{
  margin:clamp(3px,.55vh,6px) 0;
  line-height:1.15;
}
.sidebar select,.sidebar input{min-height:25px;}
.sidebar .primary,.sidebar .ghost,.sidebar .ymodem,.sidebar .about-btn{min-height:29px;}
.ymodem{margin-top:0;}
.about-btn{
  width:100%;
  border:1px solid var(--line);
  background:#102532;
  color:#c7d9e3;
  padding:6px 8px;
  border-radius:6px;
  cursor:pointer;
  font-weight:600;
  font-size:var(--ui-font);
  flex:0 0 auto;
}
@media(min-height:760px){
  .sidebar{gap:clamp(9px,1.35vh,14px);padding-top:clamp(8px,1.2vh,12px);padding-bottom:clamp(8px,1.2vh,12px);}
  .sidebar section{padding-top:clamp(7px,1vh,11px);padding-bottom:clamp(8px,1.1vh,12px);}
  .sidebar h3{margin-bottom:clamp(5px,.7vh,8px);}
  .check{margin:clamp(5px,.7vh,8px) 0;}
}
@media(max-height:620px){
  .sidebar{gap:2px;overflow-y:auto;scrollbar-width:thin;padding-top:3px;padding-bottom:3px;}
  .sidebar section{padding:2px 2px 3px;}
  .sidebar h3{margin-bottom:2px;}
  .check{margin:2px 0;line-height:1;}
  .sidebar .primary,.sidebar .ghost,.sidebar .ymodem,.sidebar .about-btn{min-height:23px;padding-top:3px;padding-bottom:3px;}
}

/* V2.19 - YMODEM typography and spacing match the main UI */
.modal-card{font-size:13px;}
.modal-head{height:46px;padding:0 14px;font-size:15px;font-weight:600;}
.ym-warn{margin:11px 14px;padding:8px 10px;font-size:13px;}
.ym-section{padding:10px 14px;}
.ym-label{margin-bottom:7px;font-size:13px;font-weight:600;color:#cbdbe4;}
.ym-file-row{gap:7px;}
.ym-file-row input{height:30px;font-size:13px;}
.ym-file-row button,.ym-badge{font-size:13px;min-height:30px;}
.ym-grid{gap:22px;}
.ym-grid small{font-size:13px;margin-bottom:6px;color:#9bb0bd;}
.seg button{font-size:13px;line-height:1.15;padding:6px 12px;min-height:30px;}
.ym-progress-line{font-size:13px;margin-top:7px;}
.ym-actions{padding:11px 14px;}
.ym-actions button{font-size:13px;min-width:80px;min-height:31px;padding:6px 13px;}

/* About */
.about-card{width:min(430px,92vw);}
.about-content{padding:18px 20px;text-align:center;}
.about-meta{padding-bottom:13px;border-bottom:1px solid var(--line);}
.about-meta>div{display:flex;justify-content:center;align-items:center;gap:9px;font-size:16px;}
.about-meta p{margin:8px 0 0;color:#b8cad5;font-size:13px;}
.version-badge{display:inline-block;padding:3px 8px;border:1px solid #347c7c;border-radius:999px;color:#72e5db;background:#10343a;font-size:12px;}
.about-support{margin:15px auto 13px;max-width:350px;line-height:1.7;color:#dce8f1;font-size:13px;}
.about-qr{display:inline-block;background:#fff;border-radius:7px;padding:9px 9px 7px;box-shadow:0 6px 22px #0005;}
.about-qr img{display:block;width:220px;max-width:58vw;height:auto;object-fit:contain;}
.about-qr div{color:#222;font-size:15px;margin-top:6px;}
.about-thanks{margin-top:12px;color:#9fb4c1;font-size:13px;}


/* V2.22 - official entry, CAN presets and seamless command header */
.official-site{display:inline-flex;align-items:center;color:#8fb0bd;text-decoration:none;font-size:clamp(10px,1.45vh,12px);padding:4px 7px;border:1px solid #274454;border-radius:5px;background:#0c202c;transition:.15s}
.official-site:hover{color:#72e5db;border-color:#347c7c;background:#10343a}
.support-heart,.thanks-heart{display:inline-block;color:#ff6b7a;margin-right:7px;font-size:17px;line-height:1;vertical-align:-1px;text-shadow:0 0 10px #ff6b7a55}
.thanks-heart{margin:0 0 0 4px;font-size:14px}
.commands{display:flex;flex-direction:column;overflow:hidden!important;padding:0!important}
.commands.hidden{width:0;padding:0!important;border:0;overflow:hidden!important}
.cmdtitle{position:relative!important;top:auto!important;z-index:3;flex:0 0 auto;margin:0!important;padding:10px!important;background:#0a1822!important;border-bottom:1px solid #1d3342;box-shadow:none!important}
.cmdlist{flex:1;min-height:0;overflow-y:auto;overflow-x:hidden;scrollbar-gutter:stable;padding:3px 10px 10px}
.cmd{margin:7px 0}
.cmd:first-child{margin-top:4px}
@media(max-width:780px){.official-site{padding:3px 5px}}

/* V2.23 - stronger error feedback */
.bottom #msg.msg-error{color:#ffb4b4;font-weight:700;}
.bottom #msg.msg-port-busy{color:#ff5f67;background:#3a1519;border:1px solid #8d3038;border-radius:5px;padding:3px 10px;box-shadow:0 0 12px #ff4b5533;}

/* V2.24: fixed command column header; only command rows scroll. */
.cmdhead{display:grid;grid-template-columns:clamp(40px,4vw,48px) minmax(90px,1fr) clamp(46px,4.8vw,54px) clamp(30px,3vw,34px);gap:clamp(3px,.4vw,5px);align-items:center;flex:0 0 auto;padding:6px 10px;border-bottom:1px solid #1d3342;background:#0a1822;color:var(--muted);font-size:11px}
.cmdhead span:nth-child(3),.cmdhead span:nth-child(4){text-align:center}


/* V2.25: align command header with rows; hide HEX header text. */
.cmdhead,.cmd{grid-template-columns:48px minmax(0,1fr) 54px 34px!important;gap:5px!important}
.cmdhead{padding:6px 18px 6px 10px!important}
.cmdlist{scrollbar-width:thin;scrollbar-gutter:auto!important}
.cmdlist::-webkit-scrollbar{width:8px}
.cmdhead span:nth-child(2){text-align:left}
.cmdhead span:nth-child(3),.cmdhead span:nth-child(4){text-align:center}


/* V2.27: command notes + persistent settings */
.cmdhead,.cmd{grid-template-columns:48px minmax(150px,1.35fr) minmax(110px,.9fr) 54px 34px!important;gap:5px!important}
.cmdNote{min-width:0;color:#a9bdc9;background:#0d202b;border:1px solid #294252;border-radius:5px;padding:6px 8px}
.cmdNote::placeholder{color:#617783}
.cmdhead span:nth-child(2),.cmdhead span:nth-child(3){text-align:left}
.cmdhead span:nth-child(4),.cmdhead span:nth-child(5){text-align:center}


/* V2.28: inline command notes. Notes live inside the command field so the send column keeps its width. */
.cmdhead,.cmd{grid-template-columns:48px minmax(0,1fr) 54px 34px!important;gap:5px!important}
.cmdhead span:nth-child(2){text-align:left!important}
.cmdhead span:nth-child(3),.cmdhead span:nth-child(4){text-align:center!important}
.cmdInputWrap{position:relative;min-width:0}
.cmdInputWrap>.cmdText{width:100%;padding-right:25px;padding-bottom:12px}
.cmdNoteText{position:absolute;right:7px;bottom:2px;left:8px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:right;color:#657b88;font-size:9px;line-height:10px;pointer-events:none}
.cmdNoteAdd{position:absolute;right:3px;top:3px!important;width:22px!important;height:22px!important;min-height:22px!important;padding:0!important;border:0!important;background:transparent!important;color:#78909d!important;font-size:16px!important;line-height:20px;opacity:0;transition:opacity .12s}
.cmdInputWrap:focus-within>.cmdNoteAdd,.cmdInputWrap:hover>.cmdNoteAdd{opacity:1}
.cmdNoteAdd:hover{color:#72e5db!important;background:#10343a!important}
.cmdNotePopup{display:none;position:absolute;z-index:30;right:0;top:calc(100% + 4px);width:min(250px,100%);padding:7px;background:#102432;border:1px solid #355263;border-radius:6px;box-shadow:0 7px 18px #0009}
.cmdNotePopup.open{display:block}
.cmdNotePopup>.cmdNote{display:block;width:100%;color:#d7e3ea;background:#07141e;border:1px solid #355263;border-radius:5px;padding:6px 7px}
.cmdNotePopup small{display:block;margin-top:4px;text-align:right;color:#657b88;font-size:9px}


/* V2.29: match the inline-note reference UI. */
.cmdInputWrap>.cmdText{padding:7px 34px 14px 12px!important}
.cmdNoteText{right:12px!important;bottom:3px!important;left:42px!important;color:#778087!important;font-size:11px!important;line-height:12px!important;font-weight:400!important}
.cmdNoteAdd{right:8px!important;top:auto!important;bottom:5px!important;width:18px!important;height:16px!important;min-height:16px!important;opacity:0!important;border:0!important;background:transparent!important;padding:0!important}
.cmdInputWrap:focus-within>.cmdNoteAdd{opacity:.72!important}
.cmdInputWrap:hover>.cmdNoteAdd{opacity:.72!important}
.cmdInputWrap:has(.cmdNoteText:not(:empty))>.cmdNoteAdd{opacity:0!important}
.cmdInputWrap:has(.cmdNoteText:not(:empty)):hover>.cmdNoteAdd{opacity:.55!important}
.cmdNoteAdd::before{content:"";position:absolute;left:2px;top:2px;width:11px;height:8px;border:1px solid currentColor;border-radius:1px;box-sizing:border-box}
.cmdNoteAdd::after{content:"+";position:absolute;right:0;bottom:-1px;font-size:10px;line-height:10px;font-weight:700;background:var(--panel,#0d202b);padding-left:1px}
.cmdNoteAdd:hover{color:inherit!important;background:transparent!important;opacity:1!important}

/* V2.30: HEX is a column header; rows contain only the checkbox. */
.cmdhead span:first-child{text-align:center!important}
.cmdHexCell{justify-content:center!important}


/* V2.32: softly flash the bottom status when sending without an open serial port. */
@keyframes portWarningPulse{0%,100%{color:var(--muted);opacity:.72}35%,65%{color:#ff8f8f;opacity:1;text-shadow:0 0 7px #ff6b6b55}}
.bottom #msg.msg-port-warning{font-weight:600;animation:portWarningPulse .7s ease-in-out 3;}

/* V2.33 - theme bridge from lekaiwu ToolFrame. Kept inside the tool so it also works standalone. */
html[data-theme="light"]{
  color-scheme:light;
  color:#30343b;
  background:#f7f8fa;
  --bg:#f7f8fa;
  --panel:#ffffff;
  --panel2:#f2f4f7;
  --line:#d9dee5;
  --cyan:#168f86;
  --muted:#68717d;
}
html[data-theme="light"] body{background:var(--bg);color:#30343b}
html[data-theme="light"] header{background:#fff;border-bottom-color:var(--line)}
html[data-theme="light"] .brand span,html[data-theme="light"] .rx-head b,html[data-theme="light"] .send-head b{color:#242932}
html[data-theme="light"] .brand b{color:#087f76;border-color:#9acfc9;background:#edf9f7}
html[data-theme="light"] .sidebar,html[data-theme="light"] .commands{background:#f3f5f7}
html[data-theme="light"] .sidebar section,html[data-theme="light"] .cmdtitle,html[data-theme="light"] .cmdhead{border-color:#d9dee5}
html[data-theme="light"] .sidebar h3{color:#3d4651}
html[data-theme="light"] .sidebar select,html[data-theme="light"] .sidebar input,html[data-theme="light"] .cmd input,html[data-theme="light"] .sendrow textarea,html[data-theme="light"] .ym-file-row input,html[data-theme="light"] .cmdNotePopup>.cmdNote{background:#fff;color:#2d333b;border-color:#cfd6de}
html[data-theme="light"] .ghost,html[data-theme="light"] .mini,html[data-theme="light"] .ym-file-row button:not(.primary),html[data-theme="light"] .ym-actions button:not(.primary),html[data-theme="light"] .ym-badge,html[data-theme="light"] .seg button{background:#fff;color:#3d4651;border-color:#cfd6de}
html[data-theme="light"] .receive{background:#fff;color:#242932;border-color:#cfd6de}
html[data-theme="light"] .sendbtn,html[data-theme="light"] .ymodem,html[data-theme="light"] .cmd button{background:#e8f6f4;color:#087f76;border-color:#86c6bf}
html[data-theme="light"] .bottom{border-top-color:#d9dee5}
html[data-theme="light"] .cmdtitle,html[data-theme="light"] .cmdhead{background:#f3f5f7!important}
html[data-theme="light"] .cmdNote{color:#56616d;background:#fff;border-color:#cfd6de}
html[data-theme="light"] .cmdNote::placeholder,html[data-theme="light"] .cmdNoteText{color:#8a949e}
html[data-theme="light"] .cmdNotePopup{background:#fff;border-color:#cfd6de;box-shadow:0 7px 18px #0002}
html[data-theme="light"] .modal{background:#0005}
html[data-theme="light"] .modal-card{background:#fff;color:#30343b;border-color:#d9dee5;box-shadow:0 18px 55px #0003}
html[data-theme="light"] .modal-head,html[data-theme="light"] .ym-actions{background:#f7f8fa;border-color:#d9dee5}
html[data-theme="light"] .ym-label,html[data-theme="light"] .about-support{color:#3d4651}
html[data-theme="light"] .ym-warn{background:#fff7e8;color:#9a6712;border-color:#ead8ad}
html[data-theme="light"] .seg button:disabled{color:#9aa2aa;background:#f2f4f6;border-color:#d9dee5}
html[data-theme="light"] .progress{background:#edf0f3;border-color:#d9dee5}
html[data-theme="light"] .official-site{color:#52616b;background:#fff;border-color:#cfd6de}
html[data-theme="light"] .official-site:hover{color:#087f76;border-color:#86c6bf;background:#edf9f7}
html[data-theme="light"] .version-badge{color:#087f76;background:#edf9f7;border-color:#86c6bf}
html[data-theme="light"] .about-thanks{color:#68717d}
html[data-theme="light"] .primary{color:#fff;background:#168f86}
\n\n/* V2.34 - embedded ToolFrame integration: outer site owns title/status chrome. */
.app-shell{height:100vh}
.workspace{height:100vh!important}
/* The left settings column must stay scrollbar-free in the embedded tool. */
.sidebar{overflow:hidden!important;scrollbar-width:none!important}
.sidebar::-webkit-scrollbar{display:none!important}
@media(max-height:700px){
  .sidebar{gap:2px!important;padding:3px!important}
  .sidebar section{padding:2px 2px 3px!important}
  .sidebar h3{margin-bottom:2px!important}
  .sidebar label:not(.check){margin:2px 0!important}
  .sidebar select,.sidebar input{height:22px!important;min-height:22px!important;padding-top:1px!important;padding-bottom:1px!important}
  .check{margin:2px 0!important;line-height:1!important}
  .primary,.ghost,.ymodem,.about-btn{min-height:23px!important;padding-top:3px!important;padding-bottom:3px!important}
  .ymodem{margin-top:2px!important}
}
@media(max-height:560px){
  .sidebar{font-size:10px!important}
  .sidebar h3,.sidebar label:not(.check),.check,.primary,.ghost,.ymodem,.about-btn{font-size:10px!important}
  .sidebar section{padding:1px 2px 2px!important}
  .sidebar select,.sidebar input{height:20px!important;min-height:20px!important}
  .primary,.ghost,.ymodem,.about-btn{min-height:21px!important;padding:2px 4px!important}
}

/* V2.30 - dialogs fit inside the embedded tool viewport */
.modal{
  overflow-y:auto;
  overflow-x:hidden;
  align-items:center;
  padding:10px 14px;
  overscroll-behavior:contain;
}
.modal-card{
  max-height:calc(100vh - 20px);
  display:flex;
  flex-direction:column;
  overflow:hidden;
}
.modal-head{flex:0 0 auto;}
.ym-actions{flex:0 0 auto;}

/* About: compact enough to fit without clipping in the iframe */
.about-card{width:min(390px,92vw);}
.about-content{
  flex:1 1 auto;
  min-height:0;
  overflow-y:auto;
  padding:12px 18px 10px;
}
.about-meta{padding-bottom:9px;}
.about-meta p{margin-top:5px;}
.about-support{margin:10px auto 9px;line-height:1.55;max-width:330px;}
.about-qr{padding:7px 7px 5px;}
.about-qr img{width:160px;max-width:44vw;max-height:160px;}
.about-qr div{font-size:13px;margin-top:4px;}
.about-thanks{margin-top:8px;}

/* YMODEM: the middle content scrolls only when the iframe is unusually short. */
#ymodemModal .modal-card{width:min(650px,94vw);}
#ymodemModal .ym-warn{flex:0 0 auto;}
#ymodemModal .ym-section{flex:0 0 auto;}

@media(max-height:700px){
  .modal{align-items:flex-start;padding:7px 12px;}
  .modal-card{max-height:calc(100vh - 14px);margin:auto 0;}
  .modal-head{height:38px;min-height:38px;font-size:13px;}
  .ym-warn{margin:6px 10px;padding:5px 8px;font-size:11px;}
  .ym-section{padding:6px 10px;}
  .ym-label{margin-bottom:4px;font-size:11px;}
  .ym-file-row input{height:26px;font-size:11px;}
  .ym-file-row button,.ym-badge,.seg button{min-height:26px;font-size:11px;padding-top:4px;padding-bottom:4px;}
  .ym-grid{gap:12px;}
  .ym-grid small{font-size:11px;margin-bottom:3px;}
  .ym-progress-line{font-size:11px;margin-top:4px;}
  .ym-actions{padding:6px 10px;}
  .ym-actions button{min-height:27px;font-size:11px;padding:4px 10px;}
  .about-content{padding:8px 14px 7px;}
  .about-meta{padding-bottom:6px;}
  .about-meta>div{font-size:14px;}
  .about-meta p{margin-top:3px;font-size:11px;}
  .about-support{margin:6px auto;line-height:1.4;font-size:11px;}
  .about-qr{padding:5px 5px 4px;}
  .about-qr img{width:125px;max-height:125px;}
  .about-qr div{font-size:11px;margin-top:3px;}
  .about-thanks{margin-top:5px;font-size:11px;}
}

/* V2.35 - phone presentation. Web Serial may be unavailable on some mobile browsers,
   but the tool must still render as a normal responsive page instead of a clipped desktop canvas. */
@media(max-width:620px){
  html,body{width:100%;min-width:0!important;min-height:100%;overflow:auto!important}
  .app-shell{width:100%;height:auto!important;min-height:100vh;overflow:visible}
  .workspace{position:relative;width:100%;height:auto!important;min-height:100vh;display:flex;flex-direction:column;overflow:visible}
  .sidebar{order:1;width:100%!important;flex:none;border-right:0;border-bottom:1px solid var(--line);padding:8px!important;overflow:visible!important;font-size:12px!important}
  .sidebar section{padding:7px 4px 9px!important}
  .sidebar h3{font-size:13px!important;margin-bottom:6px!important}
  .sidebar label:not(.check){grid-template-columns:72px minmax(0,1fr)!important;gap:7px!important;font-size:12px!important;margin:6px 0!important}
  .sidebar select,.sidebar input{height:34px!important;min-height:34px!important;font-size:13px!important;padding:5px 8px!important}
  .check{font-size:12px!important;margin:8px 0!important;line-height:1.25!important}
  .check input{width:16px!important;height:16px!important}
  .primary,.ghost,.ymodem,.about-btn{min-height:36px!important;padding:7px 9px!important;font-size:12px!important}
  .pair{margin-top:7px!important}
  .linkbtn{font-size:12px!important}
  .mainpanel{order:2;width:100%;min-height:560px;padding:8px;gap:6px}
  .rx-head,.send-head,.bottom{height:28px;font-size:11px}
  .receive{min-height:300px;font-size:12px;padding:8px}
  .sendrow{height:112px;min-height:112px;gap:6px}
  .sendrow textarea{font-size:12px;padding:8px}
  .sendbtn{width:58px;flex:0 0 58px;font-size:22px}
  .sendbtn small{font-size:10px}
  .commands{position:fixed!important;left:8px!important;right:8px!important;top:72px!important;bottom:8px!important;width:auto!important;z-index:50;border:1px solid var(--line)!important;border-radius:10px;box-shadow:0 14px 40px #000b;overflow:auto!important}
  .commands.hidden{display:none!important;width:auto!important;padding:0!important}
  .cmd{grid-template-columns:42px minmax(0,1fr) 50px 32px}
  .modal{padding:8px}
  .modal-card,#ymodemModal .modal-card,.about-card{width:calc(100vw - 16px);max-width:100%;max-height:calc(100vh - 16px)}
}

/* V2.36 - keep serial settings visible at every viewport width.
   Do not force the iframe to a 900px desktop canvas: that could push/crop the
   left settings panel when the outer tool window becomes narrower. */
html,body{min-width:0!important;width:100%}
.workspace{min-width:0;width:100%}
.sidebar{flex:0 0 var(--side-w);min-width:0}
.mainpanel{min-width:0}
@media (min-width:621px) and (max-width:900px){
  :root{--side-w:clamp(170px,27vw,210px)}
  .sidebar{display:flex!important;visibility:visible!important;opacity:1!important}
  .mainpanel{flex:1 1 0;min-width:0}
  .sendbtn{width:54px;flex:0 0 54px}
}

/* V2.37 - fluid resize + overflow fallback.
   Normal window sizes adapt without scrollbars. If the viewport becomes too small
   to preserve usable controls, native scrolling is allowed instead of clipping. */
@media (min-width:621px){
  html,body{min-width:0!important;width:100%;height:100%;overflow:auto!important}
  .app-shell{width:100%;height:100vh;min-width:0;min-height:0;overflow:hidden}
  .workspace{width:100%;min-width:0;min-height:0;overflow:auto;display:flex;flex-wrap:nowrap}
  .sidebar{display:block!important;visibility:visible!important;opacity:1!important;width:clamp(188px,18vw,250px)!important;flex:0 1 clamp(188px,18vw,250px)!important;min-width:188px;overflow-y:auto!important;overflow-x:hidden!important}
  .mainpanel{flex:1 1 420px;min-width:360px}
  .commands:not(.hidden){flex:0 1 410px;min-width:280px;width:clamp(280px,29vw,410px)}
  .sendbtn{flex:0 1 82px;min-width:52px;width:clamp(52px,6vw,82px)}
}

/* V2.38 - two-axis overflow ownership.
   The workspace may scroll horizontally only as a last-resort fallback.
   Vertical overflow belongs to each column, so resizing never scrolls the
   entire workspace down and hide the top of the settings sidebar. */
@media (min-width:621px){
  html,body{height:100%;overflow:hidden!important}
  .app-shell{height:100vh;overflow:hidden}
  .workspace{height:100%;min-height:0;overflow-x:auto!important;overflow-y:hidden!important;align-items:stretch}
  .sidebar{height:100%;min-height:0;overflow-x:hidden!important;overflow-y:auto!important;overscroll-behavior:contain;scrollbar-gutter:auto}
  .mainpanel{height:100%;min-height:0;overflow:hidden}
  .commands:not(.hidden){height:100%;min-height:0;overflow-y:auto!important;overflow-x:hidden!important}
}

/* V2.39 - visible sidebar scrollbar + reliable access to the first setting.
   Keep it subtle, and only show it when the sidebar actually overflows. */
@media (min-width:621px){
  .sidebar{
    overflow-y:auto!important;
    overflow-x:hidden!important;
    scrollbar-width:thin!important;
    scrollbar-color:rgba(136,160,176,.42) transparent!important;
    scrollbar-gutter:auto!important;
  }
  .sidebar::-webkit-scrollbar{display:block!important;width:7px!important}
  .sidebar::-webkit-scrollbar-track{background:transparent!important}
  .sidebar::-webkit-scrollbar-thumb{
    background:rgba(136,160,176,.36)!important;
    border-radius:999px!important;
    border:2px solid transparent!important;
    background-clip:padding-box!important;
  }
  .sidebar::-webkit-scrollbar-thumb:hover{background:rgba(136,160,176,.62)!important;background-clip:padding-box!important}
}

/* V2.40 - More / advanced settings */
.more-card{max-width:560px}.more-content{padding:18px 20px}.more-setting,.more-reset{display:flex;align-items:center;justify-content:space-between;gap:18px}.more-setting>span,.more-reset>span{display:flex;flex-direction:column;gap:5px;min-width:0}.more-setting small,.more-reset small,.confirm-content small{color:var(--muted);line-height:1.45}.more-setting input{width:18px;height:18px;flex:0 0 auto}.more-divider{height:1px;background:var(--line);margin:18px 0}.danger-outline,.danger-btn{border:1px solid #b54a4a;color:#ff9c9c;background:transparent;border-radius:6px;padding:8px 12px;white-space:nowrap}.danger-btn{background:#7b2929;color:#fff}.confirm-card{max-width:460px}.confirm-content{padding:22px 20px;display:flex;flex-direction:column;gap:8px;line-height:1.5}
@media(max-width:620px){.more-setting,.more-reset{align-items:flex-start;flex-direction:column}.danger-outline{width:100%}}


/* V2.5.4 - mobile modal viewport fix.
   The tool iframe grows to its document height on phones, so position dialogs
   inside the part of the iframe that is actually visible in the parent page. */
.more-content{flex:1 1 auto;min-height:0;overflow-y:auto;-webkit-overflow-scrolling:touch}
@media(max-width:620px){
  .modal.mobile-visible-modal{
    position:absolute!important;
    left:0!important;
    right:0!important;
    bottom:auto!important;
    align-items:flex-start!important;
    justify-content:center!important;
    overflow-y:auto!important;
    -webkit-overflow-scrolling:touch;
    overscroll-behavior:contain;
  }
  .modal.mobile-visible-modal .modal-card{
    margin:0 auto!important;
    max-height:100%!important;
    min-height:0!important;
  }
  .more-content{overflow-y:auto!important;-webkit-overflow-scrolling:touch}
}

/* V2.5.8 communication capture */
.log-capture-actions{display:flex;align-items:center;gap:10px;flex:0 0 auto}.log-switch{display:flex;align-items:center;gap:6px;white-space:nowrap}.log-switch input{width:18px;height:18px}.log-capture-actions button:disabled{opacity:.4;cursor:not-allowed}
@media(max-width:620px){.log-capture-actions{width:100%;justify-content:space-between}.log-capture-actions #downloadLog{flex:1;max-width:180px}}
/* V2.5.9 communication log clear action */
@media(max-width:620px){.log-capture-actions{flex-wrap:wrap}.log-capture-actions #downloadLog,.log-capture-actions #clearCaptureLog{flex:1 1 120px;max-width:none}}

/* V2.5.18 - phone serial workspace sizing.
   Keep the desktop flex-fill terminal behavior, but on phones do not let RX
   consume all of the iframe/viewport height. The page itself may scroll. */
@media (max-width:620px){
  .mainpanel{
    min-height:0!important;
    height:auto!important;
    flex:none!important;
    overflow:visible!important;
  }
  .receive{
    flex:0 0 clamp(190px,32dvh,260px)!important;
    height:clamp(190px,32dvh,260px)!important;
    min-height:190px!important;
    max-height:260px!important;
  }
  .sendrow{
    flex:0 0 112px!important;
    height:112px!important;
    min-height:112px!important;
  }
}
@media (max-width:620px) and (max-height:700px){
  .receive{
    flex-basis:clamp(170px,29dvh,220px)!important;
    height:clamp(170px,29dvh,220px)!important;
    min-height:170px!important;
    max-height:220px!important;
  }
}


/* V2.5.20 - when the parent promotes this iframe to the phone viewport,
   dialogs can use normal fixed positioning again. */
@media(max-width:620px){
  .modal{position:fixed!important;inset:0!important;height:auto!important;display:flex;align-items:center!important;justify-content:center!important;padding:8px!important;overflow:auto!important}
  .modal.hidden-modal{display:none!important}
  .modal .modal-card{width:calc(100vw - 16px);max-width:650px;max-height:calc(100dvh - 16px)!important;margin:auto!important;min-height:0!important}
  .more-content{overflow-y:auto!important;-webkit-overflow-scrolling:touch}
}
