:root{
  --blue:#0052D9; --blue2:#2F7BEF; --green:#79C000; --green-dk:#5A8A00;
  --ink:#1F2733; --sub:#5B6573; --line:#E3E8EF; --soft:#F4F6F8; --soft2:#F9FAFB;
  --el-color-primary:#0052D9;
  --el-color-primary-light-3:#3a78e0; --el-color-primary-light-5:#6a9bea;
  --el-color-primary-light-7:#9dbef2; --el-color-primary-light-9:#eaf1ff;
  --el-color-success:#5A8A00; --el-border-radius-base:8px;
  --el-font-family:"PingFang SC","Microsoft YaHei","Hiragino Sans GB",sans-serif;
}
*{box-sizing:border-box}
html,body,#app{height:100%;margin:0}
body{font-family:var(--el-font-family);color:var(--ink);background:var(--soft)}

/* ---------- login ---------- */
.login-wrap{height:100%;display:flex}
.login-brand{flex:1.1;background:linear-gradient(135deg,#0052D9 0%,#2F7BEF 55%,#5A8A00 130%);
  color:#fff;position:relative;overflow:hidden;display:flex;flex-direction:column;justify-content:center;padding:0 7%}
.login-brand h1{font-size:40px;font-weight:800;margin:0 0 14px;letter-spacing:1px}
.login-brand .slogan{font-size:16.5px;opacity:.92;line-height:1.7;max-width:460px;animation:fadeUp .7s .2s both}
.login-brand .pills{margin-top:26px;display:flex;gap:12px;flex-wrap:wrap;animation:fadeUp .7s .4s both}
.login-brand .pill{background:rgba(255,255,255,.14);border:1px solid rgba(255,255,255,.28);
  padding:9px 16px;border-radius:999px;font-size:13.5px;font-weight:600;backdrop-filter:blur(4px)}
.login-brand .pill.p1{animation:bob 5s 1.2s ease-in-out infinite}
.login-brand .pill.p2{animation:bob 5s 1.8s ease-in-out infinite}
.login-brand .pill.p3{animation:bob 5s 2.4s ease-in-out infinite}
/* 动态科技层 */
.fx-canvas{position:absolute;inset:0;width:100%;height:100%;pointer-events:none}
.fx-orb{position:absolute;border-radius:50%;filter:blur(64px);pointer-events:none}
.fx-orb.o1{width:400px;height:400px;background:#2F7BEF;opacity:.55;top:-110px;right:-90px;animation:orb1 14s ease-in-out infinite alternate}
.fx-orb.o2{width:320px;height:320px;background:#79C000;opacity:.32;bottom:-110px;left:16%;animation:orb2 18s ease-in-out infinite alternate}
.fx-orb.o3{width:230px;height:230px;background:#7C4DFF;opacity:.22;top:32%;left:-70px;animation:orb3 16s ease-in-out infinite alternate}
@keyframes orb1{to{transform:translate(-46px,56px) scale(1.14)}}
@keyframes orb2{to{transform:translate(60px,-40px) scale(1.1)}}
@keyframes orb3{to{transform:translate(40px,46px) scale(1.18)}}
.fx-floor{position:absolute;left:-22%;right:-22%;bottom:-12px;height:40%;pointer-events:none;overflow:hidden;
  transform:perspective(440px) rotateX(62deg);transform-origin:bottom;
  -webkit-mask-image:linear-gradient(to top,rgba(0,0,0,.6),transparent 85%);
  mask-image:linear-gradient(to top,rgba(0,0,0,.6),transparent 85%)}
.fx-floor::before{content:'';position:absolute;left:0;right:0;top:-44px;bottom:0;
  background:repeating-linear-gradient(90deg,rgba(255,255,255,.13) 0 1px,transparent 1px 58px),
             repeating-linear-gradient(0deg,rgba(255,255,255,.13) 0 1px,transparent 1px 44px);
  will-change:transform;animation:floor 8s linear infinite}
@keyframes floor{to{transform:translateY(44px)}}
.fx-scan{position:absolute;inset:0;overflow:hidden;pointer-events:none}
.fx-scan::after{content:'';position:absolute;top:-25%;bottom:-25%;width:200px;left:-30%;
  background:linear-gradient(105deg,transparent,rgba(255,255,255,.13),transparent);transform:skewX(-14deg);
  animation:scan 7s ease-in-out infinite}
@keyframes scan{0%,12%{left:-30%}55%,100%{left:125%}}
.brand-inner{position:relative;z-index:2;max-width:540px}
.fx-chip{display:inline-flex;align-items:center;gap:9px;padding:7px 15px;border-radius:999px;
  background:rgba(255,255,255,.12);border:1px solid rgba(255,255,255,.26);font-size:12.5px;letter-spacing:1.5px;
  margin-bottom:22px;backdrop-filter:blur(4px);animation:fadeUp .7s both}
.fx-dot{width:8px;height:8px;border-radius:50%;background:#A8E63E;animation:pulse 2s infinite}
@keyframes pulse{0%{box-shadow:0 0 0 0 rgba(168,230,62,.65)}70%{box-shadow:0 0 0 9px rgba(168,230,62,0)}100%{box-shadow:0 0 0 0 rgba(168,230,62,0)}}
.fx-title{background:linear-gradient(95deg,#fff 20%,#BFD9FF 42%,#fff 60%,#D9F2A8 82%,#fff 100%);
  background-size:220% 100%;-webkit-background-clip:text;background-clip:text;color:transparent;
  text-shadow:none;animation:shine 6s linear infinite,fadeUp .7s .1s both}
@keyframes shine{to{background-position:220% 0}}
.fx-type{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:16.5px;font-weight:600;
  margin-top:18px;display:flex;align-items:center;gap:9px;min-height:26px;animation:fadeUp .7s .3s both}
.fx-type .pfx{color:#A8E63E;font-weight:800;font-size:19px}
.fx-type .cursor{width:9px;height:19px;background:rgba(255,255,255,.85);animation:blink 1s steps(1) infinite}
@keyframes blink{50%{opacity:0}}
.fx-stats{display:flex;gap:42px;margin-top:34px;animation:fadeUp .7s .55s both}
.fx-stats .n{font-size:27px;font-weight:800;line-height:1.2}
.fx-stats .l{font-size:12.5px;opacity:.8;margin-top:3px;letter-spacing:1px}
@keyframes fadeUp{from{opacity:0;transform:translateY(20px)}to{opacity:1;transform:none}}
@keyframes bob{50%{transform:translateY(-5px)}}
@media (prefers-reduced-motion:reduce){
  .login-brand *,.login-brand *::before,.login-brand *::after,
  .captcha *,.captcha *::before,.captcha *::after{animation:none!important}}
.login-form{flex:.9;display:flex;align-items:center;justify-content:center;background:#fff}
.login-card{width:380px}
.login-card .lg-title{font-size:25px;font-weight:800;color:var(--ink)}
.login-card .lg-sub{color:var(--sub);font-size:13.5px;margin:8px 0 24px}
.login-card .el-input{height:46px}
.login-card .el-button{height:46px;font-size:16px;font-weight:600;letter-spacing:2px}
/* ---------- 滑块拼图验证码 ---------- */
.captcha{user-select:none;width:380px}
.cap-stage{position:relative;border-radius:10px;overflow:hidden;box-shadow:inset 0 0 0 1px rgba(31,39,51,.08)}
.cap-stage canvas{position:absolute;left:0;top:0;display:block}
.cap-stage{height:150px}
.cap-piece{will-change:transform;filter:drop-shadow(0 3px 6px rgba(0,10,40,.45))}
.cap-refresh{position:absolute;top:8px;right:8px;width:28px;height:28px;border-radius:8px;z-index:3;
  background:rgba(255,255,255,.88);display:flex;align-items:center;justify-content:center;cursor:pointer;
  color:#33415C;transition:.2s}
.cap-refresh:hover{background:#fff;transform:rotate(180deg)}
.cap-badge{position:absolute;inset:0;z-index:2;display:flex;align-items:center;justify-content:center;gap:8px;
  background:linear-gradient(120deg,rgba(90,138,0,.85),rgba(121,192,0,.8));color:#fff;font-weight:700;
  font-size:15px;letter-spacing:1px;animation:capIn .3s ease}
@keyframes capIn{from{opacity:0;transform:scale(1.04)}to{opacity:1;transform:none}}
.cap-track{position:relative;height:42px;border-radius:999px;background:var(--soft);border:1px solid var(--line);
  margin-top:12px;overflow:hidden}
.cap-fill{position:absolute;left:0;top:0;bottom:0;border-radius:999px;background:linear-gradient(90deg,#DCE9FF,#BAD4FF)}
.captcha.ok .cap-fill{background:linear-gradient(90deg,#A4D45C,#79C000)}
.captcha.fail .cap-track{animation:shake .4s}
@keyframes shake{20%,60%{transform:translateX(-6px)}40%,80%{transform:translateX(6px)}}
.cap-text{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
  font-size:13px;color:var(--sub);letter-spacing:.5px;pointer-events:none}
.captcha.ok .cap-text{color:#fff;font-weight:700}
.captcha.fail .cap-text{color:#D54941;font-weight:600}
.cap-handle{position:absolute;left:0;top:0;width:40px;height:40px;border-radius:50%;background:#fff;z-index:2;
  box-shadow:0 2px 10px rgba(31,39,51,.28);display:flex;align-items:center;justify-content:center;
  color:var(--blue);font-size:17px;cursor:grab;touch-action:none}
.cap-handle:active{cursor:grabbing}
.captcha.ok .cap-handle{color:#5A8A00}
.captcha.fail .cap-handle{color:#D54941}

/* ---------- shell ---------- */
.topbar{height:60px;background:#fff;border-bottom:1px solid var(--line);display:flex;align-items:center;
  padding:0 22px;box-shadow:0 1px 8px rgba(31,39,51,.05);position:relative;z-index:10}
.logo-tile{width:36px;height:36px;border-radius:9px;background:linear-gradient(135deg,#0052D9,#2F7BEF);
  color:#fff;display:flex;align-items:center;justify-content:center;font-weight:800;font-size:18px;margin-right:12px}
.brand-name{font-size:17px;font-weight:800;color:var(--ink)}
.brand-name small{font-weight:500;color:var(--sub);font-size:12px;margin-left:8px}
.spacer{flex:1}
.org-chip{display:flex;align-items:center;gap:6px;background:var(--soft);border:1px solid var(--line);
  padding:6px 12px;border-radius:999px;font-size:13px;color:var(--sub);margin-right:16px}
.user-box{display:flex;align-items:center;gap:9px;cursor:pointer;padding:5px 8px;border-radius:8px}
.user-box:hover{background:var(--soft)}
.avatar{width:32px;height:32px;border-radius:50%;background:linear-gradient(135deg,#5A8A00,#93D61F);
  color:#fff;display:flex;align-items:center;justify-content:center;font-weight:700;font-size:14px}
.layout{height:calc(100% - 60px);display:flex}
.content{flex:1;overflow:auto;background:var(--soft);position:relative}
/* top nav (一级菜单 + 下拉二级) */
.topnav{display:flex;align-items:center;gap:6px;margin-left:22px}
.topnav-item{display:flex;align-items:center;gap:6px;padding:8px 14px;border-radius:9px;cursor:pointer;
  font-size:14.5px;font-weight:600;color:var(--sub);transition:.15s;user-select:none;outline:none}
.topnav-item:hover{background:var(--soft);color:var(--blue)}
.topnav-item.active{background:#eaf1ff;color:var(--blue)}
.topnav-item .caret{font-size:12px;opacity:.65;margin-left:-1px}
.el-dropdown-menu__item .el-icon{margin-right:7px;vertical-align:middle}
.page{padding:24px 26px}
.page-h{font-size:21px;font-weight:800;color:var(--ink);margin:0 0 4px}
.page-sub{color:var(--sub);font-size:13px;margin-bottom:20px}

/* launcher */
.launch-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:18px}
.app-card{background:#fff;border:1px solid var(--line);border-radius:14px;padding:22px;cursor:pointer;
  transition:.18s;box-shadow:0 8px 24px rgba(31,39,51,.05);position:relative}
.app-card:hover{transform:translateY(-3px);box-shadow:0 14px 34px rgba(0,82,217,.13);border-color:#cfe0ff}
.app-icon{width:52px;height:52px;border-radius:13px;display:flex;align-items:center;justify-content:center;color:#fff;font-size:26px;margin-bottom:14px}
.app-row{display:flex;align-items:center;gap:16px}
.app-main{flex:1;min-width:0}
.app-cover{flex:none;width:44%;max-width:180px;height:150px;display:flex;align-items:center;justify-content:center;
  overflow:hidden;border-radius:11px;background:linear-gradient(135deg,#EEF4FF 0%,#F8FBFF 58%,#F1F8E8 130%)}
.app-cover img{max-width:90%;max-height:128px;object-fit:contain;transition:transform .25s ease}
.app-card:hover .app-cover img{transform:scale(1.06)}
.app-head{display:flex;align-items:center;gap:12px;margin-bottom:2px}
.app-head .app-icon{width:40px;height:40px;border-radius:11px;font-size:21px;margin-bottom:0;flex:none}
.app-card .nm{font-size:18px;font-weight:800;color:var(--ink)}
.app-card .ds{color:var(--sub);font-size:13px;margin:6px 0 16px;line-height:1.6;min-height:42px}
.app-card .tag{position:absolute;top:20px;right:20px;width:30px;height:30px;border-radius:9px;
  display:flex;align-items:center;justify-content:center;font-weight:800;color:#fff;font-size:14px}

/* workbench tabs */
.wb{height:100%;display:flex;flex-direction:column}
.wb .el-tabs{height:100%;display:flex;flex-direction:column}
.wb .el-tabs__content{flex:1;padding:0}
.wb .el-tab-pane{height:100%}
.wb iframe{width:100%;height:100%;border:0;display:block;background:#fff}

/* stat cards */
.stat-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;margin-bottom:22px}
.stat{background:#fff;border:1px solid var(--line);border-radius:13px;padding:18px 20px}
.stat .v{font-size:30px;font-weight:800;color:var(--blue)}
.stat:nth-child(even) .v{color:var(--green-dk)}
.stat .l{color:var(--sub);font-size:13px;margin-top:4px}
.card{background:#fff;border:1px solid var(--line);border-radius:13px;padding:20px;margin-bottom:18px}
.card h3{margin:0 0 14px;font-size:15px;font-weight:800;color:var(--ink)}
.toolbar{display:flex;gap:10px;margin-bottom:14px;align-items:center}
.matrix td,.matrix th{text-align:center}
.dot{width:18px;height:18px;border-radius:50%;display:inline-block}
