/* Crane — 样式表。风格参考 Cloudflare 控制台：浅灰底、白色圆角卡片、细边框、蓝色主按钮、橙色品牌色。 */
:root{
  --bg:#f6f6f7;--card:#fff;--fg:#1f2328;--mute:#6b7280;--line:#e4e5e7;--soft:#fafafa;
  --pri:#0051c3;--pri-h:#003f9a;--pri-soft:#eaf1fc;--orange:#f6821f;
  --ok:#168a49;--bad:#c4302b;--run:#0051c3;--radius:10px;
  --shadow:0 1px 2px rgba(16,24,40,.04);
  --ring:0 0 0 3px rgba(0,81,195,.28);--ctl:#d0d4da;--ctl-h:#b4bac3;--sh-ctl:0 1px 2px rgba(16,24,40,.07);
}
*{box-sizing:border-box}
html,body{margin:0}
body{background:var(--bg);color:var(--fg);font:14px/1.55 Inter,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;-webkit-font-smoothing:antialiased}
a{color:var(--pri);text-decoration:none}a:hover{text-decoration:underline}
code{background:#f0f1f3;border-radius:4px;padding:1px 5px;font:12px ui-monospace,Menlo,Consolas,monospace}
button,input,select,textarea{font-family:inherit}
:focus-visible{outline:0}
.mute{color:var(--mute)}.small{font-size:12px}

/* 顶栏 */
#hdr{height:60px;background:#fff;border-bottom:1px solid var(--line);display:flex;align-items:center;padding:0 24px;position:sticky;top:0;z-index:20}
.logo{display:flex;align-items:center;gap:10px;font-size:20px;font-weight:700;letter-spacing:-.02em;color:var(--fg)!important;text-decoration:none!important}
.logo img{display:block}
.hr{display:flex;align-items:center;gap:4px;margin-left:auto}
.hr a,.hr button.link{color:var(--fg);background:none;border:0;cursor:pointer;font:inherit;padding:6px 12px;border-radius:6px}
.hr a:hover,.hr button.link:hover{background:#f0f1f3;text-decoration:none}

/* 页面容器 */
.crumbs{max-width:1120px;margin:0 auto;padding:22px 24px 0;color:var(--mute);font-size:13px}
.crumbs a{color:var(--mute)}.crumbs a:hover{color:var(--fg);text-decoration:none}
.crumbs span:last-child{color:var(--fg)}.crumbs .sep{margin:0 8px;color:#b8bcc2}
.crumbs.none{padding-top:8px;height:0;overflow:hidden}
.layout{max-width:1120px;margin:0 auto;padding:14px 24px 56px;display:flex;gap:24px;align-items:flex-start}
.side{width:236px;flex:none;position:sticky;top:84px}
.main{flex:1;min-width:0}
h1{font-size:24px;font-weight:650;letter-spacing:-.015em;margin:0 0 18px;display:flex;align-items:center;gap:10px}
h2{font-size:15px;font-weight:650;margin:28px 0 12px}
.pagehead{display:flex;align-items:center;justify-content:space-between;margin-bottom:18px}.pagehead h1{margin:0}

/* 项目页侧栏 */
.nav{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);padding:6px;box-shadow:var(--shadow)}
.task{display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:7px;color:var(--fg);cursor:pointer;border:0;background:none;width:100%;font:inherit;text-align:left;transition:background .1s,color .1s}
.task:hover{background:#f3f4f6;text-decoration:none}.task.on{background:var(--pri-soft);color:var(--pri);font-weight:600}
.task svg{width:18px;height:18px;flex:none;color:#7a828e}.task.on svg{color:var(--pri)}
.task.danger,.task.danger svg{color:var(--bad)}.task.danger:hover{background:#fdf1f0}
.panel{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);margin-top:16px;overflow:hidden;box-shadow:var(--shadow)}
.panel h3{margin:0;padding:11px 14px;font-size:12px;font-weight:650;letter-spacing:.04em;text-transform:uppercase;color:var(--mute);border-bottom:1px solid var(--line)}
.panel .pb{padding:6px 8px}
.panel .it{display:flex;align-items:center;gap:8px;padding:6px;border-radius:6px}.panel .it:hover{background:#f6f7f8}

/* 项目列表 */
table.jobs{width:100%;border-collapse:separate;border-spacing:0;background:var(--card);border:1px solid var(--line);border-radius:12px;overflow:hidden;box-shadow:var(--shadow)}
table.jobs th{text-align:left;font-size:11px;font-weight:650;letter-spacing:.05em;text-transform:uppercase;color:var(--mute);padding:11px 14px;background:var(--soft);border-bottom:1px solid var(--line);white-space:nowrap}
table.jobs td{padding:12px 14px;border-bottom:1px solid var(--line);vertical-align:middle}
table.jobs tr:last-child td{border-bottom:0}
table.jobs tbody tr:hover td{background:#fafbfc}
.empty{background:var(--card);border:1px dashed #cfd3d8;border-radius:var(--radius);padding:48px 24px;text-align:center;color:var(--mute)}
.empty b{display:block;color:var(--fg);font-size:16px;margin-bottom:6px}
.ball{width:20px;height:20px;display:inline-block;vertical-align:middle;flex:none}
.ball.running{animation:spin 1s linear infinite}
@keyframes spin{to{transform:rotate(360deg)}}

/* 按钮：实色 + 细描边 + 顶部高光 + 柔和阴影；悬停加深，按下下沉 */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:6px;height:36px;padding:0 16px;border-radius:7px;font-size:14px;font-weight:550;letter-spacing:.005em;cursor:pointer;
  background:linear-gradient(180deg,#0a5fd8 0%,#0051c3 100%);border:1px solid #003f9a;color:#fff;
  box-shadow:0 1px 2px rgba(0,40,110,.28),inset 0 1px 0 rgba(255,255,255,.18);transition:background .12s,box-shadow .12s,border-color .12s,transform .06s}
.btn:hover{background:linear-gradient(180deg,#0b66e6 0%,#0047ad 100%);border-color:#003a8a;text-decoration:none;box-shadow:0 2px 5px rgba(0,40,110,.32),inset 0 1px 0 rgba(255,255,255,.2)}
.btn:active{transform:translateY(1px);background:#0047ad;box-shadow:inset 0 2px 3px rgba(0,30,90,.35)}
.btn:focus-visible{box-shadow:var(--ring),0 1px 2px rgba(0,40,110,.28)}
.btn:disabled{opacity:.45;box-shadow:none;transform:none;cursor:not-allowed}
.btn.sec{background:linear-gradient(180deg,#fff 0%,#f7f8f9 100%);color:#2b3138;border:1px solid var(--ctl);box-shadow:var(--sh-ctl),inset 0 1px 0 #fff}
.btn.sec:hover{background:linear-gradient(180deg,#fff 0%,#f0f2f4 100%);border-color:var(--ctl-h);box-shadow:0 1px 3px rgba(16,24,40,.12),inset 0 1px 0 #fff}
.btn.sec:active{background:#eceef1;box-shadow:inset 0 1px 3px rgba(16,24,40,.15)}
.btn.sec:focus-visible{border-color:var(--pri);box-shadow:var(--ring)}
.btn.bad{background:linear-gradient(180deg,#fff 0%,#fff9f8 100%);color:#b42318;border:1px solid #f0c4c0;box-shadow:var(--sh-ctl),inset 0 1px 0 #fff}
.btn.bad:hover{background:#fdeceb;border-color:#e6a39e}
.btn.bad:active{background:#fadcda;box-shadow:inset 0 1px 3px rgba(180,35,24,.2)}
.btn.bad:focus-visible{box-shadow:0 0 0 3px rgba(196,48,43,.25)}
.btn.sm{height:30px;padding:0 12px;font-size:13px;border-radius:6px}
.icobtn{background:none;border:0;cursor:pointer;color:#8a919c;padding:5px;border-radius:7px;display:inline-flex;transition:background .12s,color .12s}
.icobtn:hover{background:var(--pri-soft);color:var(--pri)}.icobtn:focus-visible{box-shadow:var(--ring)}
.icobtn svg{width:20px;height:20px}

/* 输入框 / 文本域 / 下拉：同一套边框、内阴影、悬停与聚焦环 */
input[type=text],input[type=password],textarea,select{width:100%;height:38px;padding:0 12px;border:1px solid var(--ctl);border-radius:7px;background:#fff;color:var(--fg);font-size:14px;
  box-shadow:inset 0 1px 2px rgba(16,24,40,.05);transition:border-color .12s,box-shadow .12s,background .12s}
textarea{height:auto;padding:9px 12px;line-height:1.5;resize:vertical;min-height:80px}
textarea.code{font:13px/1.55 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;min-height:140px;background:#fbfbfc}
input::placeholder,textarea::placeholder{color:#9aa1ab}
input:hover,textarea:hover,select:hover{border-color:var(--ctl-h)}
input:focus,textarea:focus,select:focus{border-color:var(--pri);box-shadow:inset 0 1px 2px rgba(16,24,40,.04),var(--ring)}
input:disabled,select:disabled,textarea:disabled{background:#f3f4f6;color:#8a919c;cursor:not-allowed;box-shadow:none}
select{appearance:none;-webkit-appearance:none;padding-right:34px;cursor:pointer;
  background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3E%3Cpath d='M4 6l4 4 4-4' fill='none' stroke='%236b7280' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat right 11px center}
select:disabled{background:#f3f4f6 url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3E%3Cpath d='M4 6l4 4 4-4' fill='none' stroke='%23b4bac3' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat right 11px center}
.field{margin:0 0 16px}.field>label{display:block;font-size:13px;font-weight:600;color:#2b3138;margin-bottom:6px}
.err{color:var(--bad);white-space:pre-wrap}

/* 复选框：自绘，选中为蓝底白勾 */
input[type=checkbox]{appearance:none;-webkit-appearance:none;width:17px;height:17px;margin:0;flex:none;border:1.5px solid #b4bac3;border-radius:5px;background:#fff;
  box-shadow:inset 0 1px 1px rgba(16,24,40,.06);cursor:pointer;transition:background .12s,border-color .12s,box-shadow .12s}
input[type=checkbox]:hover{border-color:#8f97a3}
input[type=checkbox]:checked{background:var(--pri) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3.6 8.4l3 3 5.8-6.4' fill='none' stroke='white' stroke-width='2.1' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center/13px no-repeat;border-color:var(--pri-h);box-shadow:0 1px 2px rgba(0,40,110,.3)}
input[type=checkbox]:focus-visible{box-shadow:var(--ring)}
.chk{display:flex;align-items:center;gap:10px;margin:8px 0}.chk label{cursor:pointer;font-weight:550;user-select:none}

/* 卡片、提示、标签 */
.card{background:var(--card);border:1px solid var(--line);border-radius:12px;padding:20px;box-shadow:var(--shadow)}
.banner{border-radius:8px;padding:11px 14px;margin-bottom:16px}
.banner.bad{background:#fdf1f0;border:1px solid #efc1be}
.pill{display:inline-flex;align-items:center;height:22px;padding:0 9px;border-radius:11px;font-size:12px;font-weight:600;background:#eef0f2;color:#5f6773;border:1px solid #e0e3e7}
.pill.ok{background:#e7f6ee;color:#11713a;border-color:#bfe5cf}

/* 控制台 */
.con{margin-top:14px;border:1px solid var(--line);border-radius:var(--radius);overflow:hidden;background:#0f1114;box-shadow:var(--shadow)}
.conbar{display:flex;align-items:center;gap:12px;padding:10px 14px;background:#fff;border-bottom:1px solid var(--line)}
pre.console{margin:0;background:#0f1114;color:#d6d9de;padding:12px 0;overflow:auto;min-height:180px;font:12.5px/1.7 ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,monospace;tab-size:4}
.console .l{padding:0 18px;border-left:2px solid transparent;white-space:pre-wrap;word-break:break-all;min-height:1.7em}
.console .l:hover{background:rgba(255,255,255,.04)}
.console .cmd{color:#7f8896}
.console .err{color:#ff8f87;background:rgba(229,83,75,.1);border-left-color:#e5534b}
.console .ok{color:#5fd38d;font-weight:600}
.console .warn{color:#e3b341;font-weight:600}
.console::-webkit-scrollbar{width:10px;height:10px}.console::-webkit-scrollbar-thumb{background:#2c313a;border-radius:5px}
.tool{display:flex;gap:10px;align-items:center;margin-left:auto;font-size:13px}

/* 配置页：一张卡片 */
.cfg{max-width:900px}
.cfg section{background:var(--card);border:1px solid var(--line);border-radius:12px;padding:22px 24px;margin-bottom:18px;box-shadow:var(--shadow)}
.indent{margin:8px 0 12px 8px;padding-left:18px;border-left:2px solid var(--line)}
.block{border:1px solid var(--line);border-radius:10px;padding:14px 16px;margin:0 0 12px;background:#fafafb;box-shadow:inset 0 1px 0 #fff}
.block .bh{display:flex;align-items:center;gap:8px;font-weight:650;margin-bottom:12px}
.divider{height:1px;background:var(--line);margin:24px -24px 20px}
.savebar{position:sticky;bottom:0;background:rgba(246,246,247,.92);backdrop-filter:blur(6px);border-top:1px solid var(--line);padding:14px 0;display:flex;gap:10px;align-items:center;margin-top:8px}
.drop{position:relative;display:inline-block}
.drop .menu{position:absolute;left:0;top:42px;background:#fff;border:1px solid var(--line);border-radius:10px;box-shadow:0 12px 32px rgba(16,24,40,.16),0 2px 6px rgba(16,24,40,.06);min-width:210px;z-index:15;display:none;padding:5px}
.drop.open .menu{display:block}
.drop .menu a{display:block;padding:8px 12px;border-radius:7px;color:var(--fg);cursor:pointer}.drop .menu a:hover{background:#f3f4f6;text-decoration:none}

/* 登录 */
.login{max-width:380px;margin:7vh auto}.login .card{padding:28px}
.login h1{justify-content:center;font-size:22px;margin-bottom:22px}
.brand{text-align:center;margin-bottom:18px}

#toast{position:fixed;left:50%;bottom:28px;transform:translateX(-50%);background:#1f2328;color:#fff;padding:10px 18px;border-radius:8px;z-index:50;display:none;box-shadow:0 8px 24px rgba(16,24,40,.25)}
#toast.bad{background:var(--bad)}
#netbar{display:none;position:fixed;top:0;left:0;right:0;background:var(--bad);color:#fff;text-align:center;padding:7px;z-index:60}
@media(max-width:860px){.layout{flex-direction:column}.side{width:100%;position:static}}
.btn.danger{background:linear-gradient(180deg,#e5483b 0%,#c62d21 100%);border-color:#a8231a}
.btn.danger:hover{background:linear-gradient(180deg,#d63e31 0%,#b02419 100%);border-color:#8f1d15}
.modal-bg{position:fixed;inset:0;background:rgba(16,24,40,.45);display:flex;align-items:center;justify-content:center;z-index:50;padding:16px}
.modal{background:#fff;border-radius:10px;padding:22px;max-width:420px;width:100%;box-shadow:0 12px 40px rgba(16,24,40,.28)}
.modal p{margin:0 0 18px;line-height:1.5;word-break:break-word}
.modal-row{display:flex;justify-content:flex-end;gap:8px}
.sshrow{display:grid;grid-template-columns:1.2fr 1.4fr 1fr 1fr;gap:12px}
@media(max-width:760px){.sshrow{grid-template-columns:1fr 1fr}}
.ok-t{color:#0a7a3b}
.chk{display:flex;align-items:center;flex-wrap:wrap}

/* ===== 点击手感：马上有反馈 ===== */
button,.btn,.icobtn,.task,a{-webkit-tap-highlight-color:transparent;touch-action:manipulation}
button,.btn,.icobtn{user-select:none;-webkit-user-select:none}
.icobtn{transition:background .12s,color .12s,transform .06s}
.icobtn:active{transform:scale(.88);background:#e8ebef}
.task:active{background:#e8ebef}
.hr a:active,.hr button.link:active{background:#e8ebef}
.drop .menu a:active{background:#e8ebef}
/* 请求进行中：按钮转圈、不可重复点击 */
.busy{pointer-events:none;position:relative;color:transparent!important;--spin:#6b7480}
.busy>*{opacity:0}
.btn.busy{--spin:#fff}
.busy::after{content:'';position:absolute;left:50%;top:50%;width:16px;height:16px;margin:-8px 0 0 -8px;border-radius:50%;
  border:2px solid var(--spin);border-right-color:transparent;animation:spin .6s linear infinite}
/* 顶部进度条 */
#prog{position:fixed;left:0;top:0;height:2px;width:0;background:#0051c3;z-index:100;opacity:0;pointer-events:none}
#prog.on{opacity:1;width:85%;transition:width 10s cubic-bezier(.1,.7,.2,1)}
#prog.done{opacity:0;width:100%;transition:width .12s,opacity .25s .1s}
/* 页面切换等待时，旧内容变淡，告诉用户已经收到点击 */
#app{transition:opacity .15s}
#app.loading{opacity:.55;pointer-events:none}
@media (prefers-reduced-motion:reduce){.busy::after{animation-duration:1.6s}#prog.on{transition:none}}
