Files
exbyte-depot-viewer-perforce/src/App.css
Bonchellon 30e77664d5 Re-authenticate in place when the Perforce ticket expires
Perforce ends the ticket on its own schedule, so a long day outlives a login.
Every command then failed and the only way back was Exit + restart, which threw
away the scope, selection and open panels.

- p4.ts routes all ~110 commands through one invoke wrapper that recognises an
  auth failure (isAuthError) and raises onAuthLost, so no call site can miss it.
  p4_login / p4_restore / p4_clients are exempt: they report bad credentials
  inline and would otherwise loop the prompt.
- The server poll no longer treats an expired ticket as an outage. The server
  answered, it just refused us — the offline banner it used to raise never
  cleared, since polling stayed refused forever.
- ReauthModal asks for the password over the running app, keeping all state,
  and offers Sign out as the way back to the Connect screen.

The failed command is NOT retried automatically — re-auth then refresh only.
Replaying a half-finished submit or revert unattended is worse than asking.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 17:25:14 +03:00

1156 lines
89 KiB
CSS

:root{
--bg:#08080c;--panel:#12121b;--panel-2:#161621;--panel-3:#1c1c28;
--border:#242433;--border-soft:#1d1d29;
--txt:#ecedf4;--muted:#8a8a9c;--faint:#5a5a6a;
--accent:#7c6ef6;--accent-2:#9a8bf9;--accent-deep:#5b49e6;
--add:#3ecf8e;--edit:#e8b04b;--del:#f2637e;
--win-a:#10101a;--win-b:#0c0c13;--elevated:#14141e;--input-bg:#0c0c13;
--stage-bg:#0b0b12;--grid:rgba(255,255,255,.025);
--bar:rgba(255,255,255,.015);--shadow:0 40px 90px -30px rgba(0,0,0,.7);
--sunk:rgba(0,0,0,.15);--chip:rgba(0,0,0,.4);--hover:rgba(255,255,255,.05);
--diff-add-c:#a8ecca;--diff-del-c:#f3a9b8;
--logo-bg:#0c0e1a;--logo-ring:rgba(124,110,246,.28);
--font:"Segoe UI Variable Text","Segoe UI",-apple-system,BlinkMacSystemFont,system-ui,"Helvetica Neue",Arial,sans-serif;
--mono:"Cascadia Code","JetBrains Mono",ui-monospace,"SF Mono",Consolas,monospace;
}
body.light{
--bg:#eef0f5;--panel:#ffffff;--panel-2:#f4f5f9;--panel-3:#e9eaf1;
--border:#e0e1ea;--border-soft:#ececf1;
--txt:#1b1b26;--muted:#63636f;--faint:#9a9aa8;
--accent:#6d5cf0;--accent-2:#7c6ef6;--accent-deep:#5b49e6;
--add:#1fa971;--edit:#c98a1e;--del:#e0426a;
--win-a:#ffffff;--win-b:#f6f7fb;--elevated:#ffffff;--input-bg:#f4f5f9;
--stage-bg:#e7e8ee;--grid:rgba(0,0,0,.045);
--bar:rgba(0,0,0,.015);--shadow:0 40px 90px -30px rgba(60,60,90,.35);
--sunk:transparent;--chip:rgba(255,255,255,.72);--hover:rgba(0,0,0,.045);
--diff-add-c:#137a4e;--diff-del-c:#c02b52;
--logo-bg:#e9f4ff;--logo-ring:rgba(124,110,246,.22);
}
*{box-sizing:border-box;margin:0;padding:0}
html,body,#root{height:100%}
body{
font-family:var(--font);color:var(--txt);background:var(--bg);
-webkit-font-smoothing:antialiased;letter-spacing:.1px;overflow:hidden;
/* native-app feel: UI chrome text isn't selectable (this is not a web page) */
-webkit-user-select:none;user-select:none;cursor:default;
}
button{font-family:var(--font)}
/* …but keep selection where copying/editing text is genuinely useful */
input,textarea,[contenteditable="true"],
.code,.code-body,.code-edit,.termout,.termbody,.blame-body,.diff-body,.diff,.logbody,.explain-body{
-webkit-user-select:text;user-select:text;cursor:auto;
}
/* height divided by the zoom factor: CSS `zoom` shrinks the box but `vh` still
measures the unzoomed viewport, so without this a gap grows below at zoom<1 */
.win{height:calc(100vh / var(--zoom,1));width:100%;display:flex;flex-direction:column;
background:linear-gradient(180deg,var(--win-a),var(--win-b));overflow:hidden}
/* titlebar + inline menu */
.titlebar{height:48px;flex:0 0 48px;display:flex;align-items:stretch;gap:6px;padding:0 0 0 14px;
background:var(--bar);border-bottom:1px solid var(--border-soft);position:relative;z-index:40}
/* frameless window controls (Windows style) */
.wctrls{display:flex;align-self:stretch;margin-left:10px}
.wbtn{width:46px;border:none;background:none;color:var(--muted);cursor:pointer;display:grid;place-items:center;transition:background .12s,color .12s}
.wbtn:hover{background:var(--hover);color:var(--txt)}
.wbtn.close:hover{background:#e81123;color:#fff}
.wbtn svg{width:11px;height:11px}
.brand{display:flex;align-items:center;gap:10px;padding-right:10px;margin-right:4px;border-right:1px solid var(--border-soft)}
/* theme-aware brand tile: dark tile in dark theme, light tile in light theme */
.logo{width:24px;height:24px;border-radius:8px;background:var(--logo-bg);
box-shadow:inset 0 0 0 1px var(--logo-ring),0 2px 8px rgba(0,0,0,.28);display:grid;place-items:center;flex:0 0 auto}
.logo .exlogo{width:18px;height:18px}
.app-name{font-size:13px;font-weight:600;white-space:nowrap}.app-name span{color:var(--faint);font-weight:500}
.conn-pill{align-self:center;margin-left:auto;display:flex;align-items:center;gap:8px;font-size:11.5px;color:var(--muted);
background:rgba(62,207,142,.08);border:1px solid rgba(62,207,142,.2);padding:4px 10px;border-radius:20px;white-space:nowrap}
.dot{width:7px;height:7px;border-radius:50%;background:var(--add);box-shadow:0 0 8px var(--add)}
.theme-btn{align-self:center;margin-left:12px;width:30px;height:30px;border-radius:9px;border:1px solid var(--border);
background:var(--panel);color:var(--muted);display:grid;place-items:center;cursor:pointer;transition:.15s}
.theme-btn:hover{color:var(--accent-2);border-color:var(--accent)}.theme-btn svg{width:16px;height:16px}
.menubar{display:flex;align-items:center;gap:2px;padding:7px 0}
.menu{position:relative;display:flex;align-items:center;padding:7px 11px;font-size:12.5px;color:var(--muted);
cursor:pointer;user-select:none;border-radius:9px;transition:background .15s,color .15s}
.menu:hover,.menu.open{background:rgba(124,110,246,.12);color:var(--txt)}
.dropdown{position:absolute;top:100%;left:0;min-width:210px;background:var(--elevated);border:1px solid var(--border);
border-radius:10px;padding:6px;box-shadow:0 24px 60px -12px rgba(0,0,0,.45);display:none;flex-direction:column;gap:1px}
.menu.open .dropdown{display:flex}
.di{display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:8px;font-size:12.5px;color:var(--txt);cursor:pointer}
.di:hover{background:rgba(124,110,246,.14)}
.di-ic{flex:0 0 auto;display:grid;place-items:center;width:16px;height:16px;color:var(--muted)}
.di-ic svg{width:15px;height:15px}
.di:hover .di-ic{color:var(--accent-2)}
.di .kb{margin-left:auto;font-size:10.5px;color:var(--faint);font-family:var(--mono)}
.di.ext{color:var(--accent-2)}
.sep{height:1px;background:var(--border-soft);margin:4px 6px}
/* toolbar — first divider tracks --left-w so it lines up with the left/right panel split */
.toolbar{display:grid;grid-template-columns:var(--left-w,380px) 1fr;height:60px;flex:0 0 60px;
border-bottom:1px solid var(--border);background:var(--bar)}
.tzone{display:flex;align-items:center;gap:12px;padding:0 18px;cursor:pointer;position:relative;
border-right:1px solid var(--border-soft);transition:background .15s}
.toolbar > .tzone{border-right:1px solid var(--border)} /* the --left-w divider — matches .left */
.tgroup{display:flex;min-width:0;position:relative}
.tgroup .tzone{flex:1;min-width:0}
.tgroup .tzone:last-child{flex:0 0 var(--right-zone-w,220px);min-width:160px;border-right:none}
.tzone:last-child{border-right:none}
.tzone:hover{background:var(--hover)}
/* keep the labels/icon high-contrast on hover in every theme (fixes greyed-out text) */
.tzone:hover .val{color:var(--txt)}.tzone:hover .lbl,.tzone:hover .sub{color:var(--muted)}
.sync:hover .ic{color:var(--accent-2)}.sync:hover .val{color:var(--txt)}.sync:hover .sub{color:var(--muted)}
/* draggable panel dividers */
.vhandle{position:absolute;top:0;bottom:0;width:9px;cursor:col-resize;z-index:8}
.main{position:relative}
.main > .vhandle.mainh{left:var(--left-w,380px);transform:translateX(-4px)}
.tgroup > .vhandle.grouph{right:var(--right-zone-w,220px);transform:translateX(4px)}
body.resizing{cursor:col-resize!important;user-select:none}
.tzone .ic{color:var(--muted);flex:0 0 auto;display:grid;place-items:center}.tzone .ic svg{width:18px;height:18px}
.tzmeta{display:flex;flex-direction:column;gap:2px;min-width:0}
.tzone .lbl{font-size:10.5px;color:var(--faint);text-transform:uppercase;letter-spacing:.7px}
.tzone .val{font-size:13.5px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tzone .chev{margin-left:auto;color:var(--faint);flex:0 0 auto}.tzone .chev svg{width:14px;height:14px}
.sync .val{color:var(--txt)}.sync .sub{font-size:11px;color:var(--muted)}.sync .ic{color:var(--accent-2)}
.tzone.busy .ic{animation:spin 1s linear infinite}
@keyframes spin{to{transform:rotate(360deg)}}
/* main */
.main{flex:1;display:grid;grid-template-columns:var(--left-w,380px) 1fr;min-height:0;overflow:hidden}
.left{border-right:1px solid var(--border);display:flex;flex-direction:column;min-height:0;overflow:hidden}
.right{display:flex;flex-direction:column;min-height:0}
.tabs{display:flex;height:46px;flex:0 0 46px;border-bottom:1px solid var(--border);position:relative}
.tab{flex:1;display:flex;align-items:center;justify-content:center;gap:8px;font-size:13px;font-weight:600;
color:var(--muted);cursor:pointer;position:relative;transition:color .2s;background:none;border:none}
.tab:hover{color:var(--txt)}.tab.on{color:var(--txt)}
.tab:focus{outline:none}
.tab:focus-visible{outline:none;box-shadow:inset 0 0 0 2px rgba(124,110,246,.35)}
.tab:active{transform:scale(.97)}
/* sliding underline that glides between the two tabs */
.tab-slider{position:absolute;bottom:0;height:2px;width:calc(50% - 32px);border-radius:2px;pointer-events:none;
background:linear-gradient(90deg,var(--accent),var(--accent-2));box-shadow:0 0 10px rgba(124,110,246,.6);
transition:left .34s cubic-bezier(.5,.02,.15,1)}
/* content fades + rises slightly when the tab changes */
.tabpane{flex:1;min-height:0;display:flex;flex-direction:column;animation:tabin .3s cubic-bezier(.4,0,.2,1)}
@keyframes tabin{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}
@media (prefers-reduced-motion:reduce){.tab-slider{transition:none}.tabpane{animation:none}}
.badge{font-size:11px;font-weight:600;color:var(--muted);background:var(--panel-3);padding:1px 8px;border-radius:10px;font-variant-numeric:tabular-nums}
.tab.on .badge{color:var(--accent-2);background:rgba(124,110,246,.16)}
.filter{display:flex;align-items:center;gap:9px;padding:10px 14px;border-bottom:1px solid var(--border-soft)}
.filter .box{flex:1;display:flex;align-items:center;gap:8px;background:var(--panel);border:1px solid var(--border);border-radius:10px;padding:8px 11px}
.filter .box svg{width:14px;height:14px;flex:0 0 auto;color:var(--faint)}
.filter .box input{border:none;background:none;outline:none;color:var(--txt);font-family:var(--font);font-size:12.5px;width:100%}
.filter .box input::placeholder{color:var(--faint)}
.pushbar{display:flex;align-items:center;gap:9px;margin:8px 10px 2px;padding:9px 12px;border-radius:11px;cursor:pointer;font-size:12px;
color:var(--add);background:rgba(62,207,142,.1);border:1px solid rgba(62,207,142,.28);transition:filter .15s}
.pushbar:hover{filter:brightness(1.06)}
.pushbar b{color:var(--add)}
.pushdot{width:8px;height:8px;border-radius:50%;background:var(--add);box-shadow:0 0 8px var(--add);flex:0 0 auto}
.pusharr{margin-left:auto;font-weight:700;font-size:14px}
/* pending changelists (committed, not yet submitted) */
.pending{margin:8px 8px 2px;display:flex;flex-direction:column;gap:6px;max-height:42%;overflow-y:auto;flex:0 0 auto}
.pending-h{display:flex;align-items:center;gap:8px;padding:1px 4px 3px}
.pending-t{display:flex;align-items:center;gap:8px;font-size:10.5px;text-transform:uppercase;letter-spacing:.6px;color:var(--add);font-weight:700}
.pushall{margin-left:auto;font-size:11.5px;font-weight:600;color:var(--add);background:rgba(62,207,142,.1);border:1px solid rgba(62,207,142,.32);border-radius:8px;padding:4px 11px;cursor:pointer}
.pushall:hover{filter:brightness(1.08)}
.clcard{border:1px solid rgba(62,207,142,.28);background:rgba(62,207,142,.06);border-radius:11px;overflow:hidden;flex:0 0 auto}
.clcard-h{display:flex;align-items:center;gap:9px;padding:9px 11px;cursor:pointer}
.clcard-h:hover{background:rgba(62,207,142,.06)}
.cl-chev{width:15px;height:15px;flex:0 0 auto;color:var(--faint);display:grid;place-items:center;transition:transform .18s;transform:rotate(-90deg)}
.cl-chev.open{transform:rotate(0deg)}
.cl-chev svg{width:15px;height:15px}
.cl-num{font-family:var(--mono);font-size:12px;color:var(--accent-2);flex:0 0 auto;font-variant-numeric:tabular-nums}
.cl-desc{flex:1;min-width:0;font-size:12.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cl-count{flex:0 0 auto;font-size:11px;color:var(--faint)}
.cl-actions{flex:0 0 auto;display:flex;align-items:center;gap:5px}
.cl-submit{width:27px;height:27px;border:none;border-radius:8px;cursor:pointer;color:#fff;font-size:14px;font-weight:700;
background:linear-gradient(135deg,var(--add),#1f9f6e);box-shadow:0 4px 12px -5px rgba(62,207,142,.7)}
.cl-submit:hover{filter:brightness(1.1)}
.cl-more{width:27px;height:27px;border:1px solid var(--border);background:var(--panel);color:var(--muted);border-radius:8px;cursor:pointer;font-size:15px;line-height:1;display:grid;place-items:center}
.cl-more:hover{color:var(--txt);border-color:var(--accent)}
.cl-files{border-top:1px solid rgba(62,207,142,.2);padding:4px}
.cl-empty{padding:8px 10px;font-size:11.5px;color:var(--faint)}
.cl-file{display:flex;align-items:center;gap:10px;padding:6px 8px;border-radius:8px;cursor:pointer}
.cl-file:hover{background:var(--hover)}
.cl-file.sel{background:rgba(124,110,246,.14);box-shadow:inset 0 0 0 1px rgba(124,110,246,.25)}
.cl-fname{display:flex;flex-direction:column;gap:1px;min-width:0;flex:1}
.cl-fname .n{font-size:12.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cl-fname .p{font-size:10.5px;color:var(--faint);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* text prompt (edit description) */
.modal-card.prompt{width:460px;max-width:calc(100vw - 40px);text-align:left;align-items:stretch}
.modal-card.prompt h3{text-align:left}
.prompt-label{font-size:11.5px;color:var(--faint);margin:2px 0 9px}
.prompt-input{width:100%;min-height:96px;resize:vertical;background:var(--input-bg);border:1px solid var(--border);border-radius:10px;padding:10px 12px;font-size:13px;color:var(--txt);font-family:var(--font);outline:none;line-height:1.5}
.prompt-input:focus{border-color:var(--accent);box-shadow:0 0 0 3px rgba(124,110,246,.15)}
.chhead{display:flex;align-items:center;gap:10px;padding:9px 16px;font-size:12px;color:var(--muted);border-bottom:1px solid var(--border-soft)}
.chk{width:16px;height:16px;border-radius:6px;border:1.5px solid var(--accent);
background:linear-gradient(145deg,var(--accent-2),var(--accent-deep));display:grid;place-items:center;flex:0 0 auto;box-shadow:0 0 8px rgba(124,110,246,.4)}
.chk svg{width:10px;height:10px;color:#fff}
.chk{cursor:pointer}
.chk.off{background:transparent;border-color:var(--border);box-shadow:none}
.crumb{display:flex;align-items:center;gap:4px;font-family:var(--mono);font-size:12px;flex-wrap:wrap}
.crumb .seg{color:var(--accent-2);cursor:pointer}.crumb .seg:hover{text-decoration:underline}
.crumb .sep{color:var(--faint)}
.scope-choose{margin:0 12px 12px;padding:11px;border:none;border-radius:11px;font-size:13.5px;font-weight:600;color:#fff;cursor:pointer;
background:linear-gradient(135deg,var(--accent-2),var(--accent-deep));box-shadow:0 8px 22px -8px rgba(124,110,246,.7);width:calc(100% - 24px)}
.scope-choose:hover{filter:brightness(1.08)}
.up{color:var(--muted)!important}
/* virtualized list */
.files{flex:1;overflow-y:auto;min-height:0;position:relative}
.vspace{position:relative;width:100%}
.file{position:absolute;left:7px;right:7px;height:50px;display:flex;align-items:center;gap:11px;padding:0 12px;cursor:pointer;
border-radius:11px;transition:background .13s;user-select:none}
.file:hover{background:var(--hover)}
.file.sel{background:rgba(124,110,246,.13);box-shadow:inset 0 0 0 1px rgba(124,110,246,.28)}
.file.primary::before{content:"";position:absolute;left:4px;top:11px;bottom:11px;width:3px;border-radius:3px;
background:linear-gradient(180deg,var(--accent-2),var(--accent-deep));box-shadow:0 0 8px rgba(124,110,246,.6)}
.fchk{width:15px;height:15px;border-radius:6px;border:1.5px solid var(--border);display:grid;place-items:center;flex:0 0 auto;background:var(--panel)}
.fchk.ck{background:linear-gradient(145deg,var(--accent-2),var(--accent-deep));border-color:var(--accent)}
.fchk svg{width:9px;height:9px;color:#fff}.fchk.off svg{display:none}
.fthumb{width:30px;height:30px;border-radius:7px;flex:0 0 auto;object-fit:cover;background:var(--panel-3);border:1px solid var(--border)}
.fthumb.ico{display:grid;place-items:center;font-size:13px;color:var(--faint)}
.fthumb.ico.k-model{color:var(--accent-2)}
.fname{display:flex;flex-direction:column;gap:1px;min-width:0;flex:1}
.fname .n{font-size:13px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.fname .p{font-size:11px;color:var(--faint);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.stat{width:18px;height:18px;border-radius:6px;display:grid;place-items:center;font-size:11px;font-weight:700;flex:0 0 auto}
.st-e{color:var(--edit);background:rgba(232,176,75,.12)}
.st-a{color:var(--add);background:rgba(62,207,142,.12)}
.st-d{color:var(--del);background:rgba(242,99,126,.12)}
.empty{flex:1;min-height:0;overflow:auto;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;color:var(--faint);font-size:13px;padding:30px;gap:10px;white-space:pre-line;line-height:1.5}
.empty svg{width:34px;height:34px;opacity:.5}
.commit{border-top:1px solid var(--border);padding:14px;display:flex;flex-direction:column;gap:9px;background:var(--sunk)}
.addbtn{border:1px dashed var(--accent);border-radius:11px;padding:12px;font-size:13.5px;font-weight:600;color:var(--accent-2);cursor:pointer;
background:rgba(124,110,246,.07);display:flex;align-items:center;justify-content:center;gap:8px;transition:background .15s}
.addbtn:hover{background:rgba(124,110,246,.14)}.addbtn:disabled{opacity:.5;cursor:not-allowed}
.addbtn svg{width:16px;height:16px}
.addhint{font-size:11px;color:var(--faint);text-align:center;line-height:1.5}
.addhint b{color:var(--accent-2)}
/* scan (reconcile) button */
.scanbtn{display:flex;align-items:center;gap:6px;font-size:11.5px;font-weight:500;color:var(--muted);cursor:pointer;
background:var(--panel);border:1px solid var(--border);border-radius:8px;padding:5px 10px;transition:.15s}
.scanbtn:hover:not(:disabled){color:var(--txt);border-color:var(--accent)}
.scanbtn:disabled{opacity:.5;cursor:not-allowed}
.scanbtn svg{width:13px;height:13px}
.scanbtn.spinning svg{animation:spin 1s linear infinite}
@keyframes spin{to{transform:rotate(360deg)}}
/* auto-scan (background reconcile) banner */
.scanbar{display:flex;align-items:center;gap:9px;margin:8px 10px 2px;padding:9px 12px;border-radius:11px;font-size:11.5px;line-height:1.4;
color:var(--accent-2);background:rgba(124,110,246,.08);border:1px solid rgba(124,110,246,.22)}
.scanbar .ldr{flex:0 0 auto}
.scanbar > span{flex:1 1 auto;min-width:0}
.scancount{font-weight:600;color:var(--txt);font-variant-numeric:tabular-nums}
.scan-cancel{flex:0 0 auto;font-size:11px;font-weight:500;color:var(--muted);cursor:pointer;
background:var(--panel);border:1px solid var(--border);border-radius:7px;padding:3px 11px;transition:.15s}
.scan-cancel:hover{color:#fff;background:var(--danger,#e5484d);border-color:var(--danger,#e5484d)}
.empty .scancount{color:var(--accent-2)}
/* submit progress modal */
.push-modal{width:380px;background:var(--elevated);border:1px solid var(--border);border-radius:16px;padding:24px 26px;box-shadow:var(--shadow);text-align:center}
.push-title{display:flex;align-items:center;justify-content:center;gap:10px;font-size:15px;font-weight:600;margin-bottom:6px}
.push-count{font-size:12.5px;color:var(--muted);font-variant-numeric:tabular-nums;margin-bottom:14px}
.push-track{height:8px;border-radius:6px;background:var(--panel-3);overflow:hidden}
.push-fill{height:100%;border-radius:6px;background:linear-gradient(90deg,var(--accent-2),var(--accent-deep));transition:width .3s ease;box-shadow:0 0 12px rgba(124,110,246,.6)}
.push-hint{margin-top:14px;font-size:11px;color:var(--faint)}
/* right-click context menu */
.ctxmenu{position:fixed;z-index:300;min-width:210px;padding:5px;border-radius:12px;
background:var(--elevated);border:1px solid var(--border);box-shadow:0 18px 44px -12px rgba(0,0,0,.6),0 0 0 1px rgba(255,255,255,.03) inset}
.ctxitem{display:flex;align-items:center;gap:10px;padding:8px 12px;border-radius:8px;font-size:12.5px;color:var(--txt);cursor:pointer;white-space:nowrap;transition:background .1s}
.ctx-ic{width:16px;height:16px;flex:0 0 auto;display:grid;place-items:center}
.ctx-ic svg{width:16px;height:16px}
.ctxitem:hover{background:var(--hover)}
.ctxitem.danger{color:var(--del)}
.ctxitem.danger:hover{background:rgba(242,99,126,.12)}
/* non-intrusive update banner (bottom-right) */
.upd{position:fixed;right:18px;bottom:18px;z-index:400;width:320px;padding:15px 16px;border-radius:14px;
background:var(--elevated);border:1px solid var(--border);box-shadow:0 22px 50px -14px rgba(0,0,0,.55);
animation:updin .35s cubic-bezier(.2,.9,.3,1)}
@keyframes updin{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
.upd-head{display:flex;align-items:center;gap:11px}
.upd-ic{width:34px;height:34px;flex:0 0 auto;border-radius:10px;display:grid;place-items:center;color:#fff;
background:linear-gradient(145deg,var(--accent-2),var(--accent-deep));box-shadow:0 0 18px rgba(124,110,246,.5)}
.upd-ic svg{width:18px;height:18px}
.upd.sm{width:auto;max-width:340px;padding:11px 14px}
.upd.sm .upd-ic{width:28px;height:28px}
.upd.sm.ok{cursor:pointer}
.upd-ic.ok{background:linear-gradient(145deg,var(--add),#1f9f6e);box-shadow:0 0 16px rgba(62,207,142,.45)}
.upd-ttl{display:flex;flex-direction:column;gap:1px;min-width:0}
.upd-ttl b{font-size:13.5px}
.upd-ttl span{font-size:11.5px;color:var(--faint);font-variant-numeric:tabular-nums}
.upd-x{margin-left:auto;width:24px;height:24px;flex:0 0 auto;border:none;background:none;color:var(--faint);
border-radius:7px;cursor:pointer;display:grid;place-items:center}
.upd-x:hover{background:var(--hover);color:var(--txt)}
.upd-notes{margin-top:10px;font-size:11.5px;line-height:1.5;color:var(--muted);max-height:70px;overflow:auto;white-space:pre-line}
.upd-notes.err{color:var(--del)}
.upd-prog{margin-top:12px;display:flex;flex-direction:column;gap:7px}
.upd-prog span{font-size:11px;color:var(--muted);font-variant-numeric:tabular-nums}
.upd-track{height:7px;border-radius:5px;background:var(--panel-3);overflow:hidden}
.upd-fill{height:100%;border-radius:5px;background:linear-gradient(90deg,var(--accent-2),var(--accent-deep));transition:width .2s;box-shadow:0 0 10px rgba(124,110,246,.6)}
.upd-actions{margin-top:13px;display:flex;gap:9px}
.upd-later{flex:0 0 auto;padding:8px 14px;border-radius:9px;border:1px solid var(--border);background:var(--panel);
color:var(--muted);font-size:12.5px;cursor:pointer;font-family:var(--font)}
.upd-later:hover{color:var(--txt);border-color:var(--accent)}
.upd-go{flex:1;padding:8px 14px;border:none;border-radius:9px;font-size:12.5px;font-weight:600;color:#fff;cursor:pointer;
background:linear-gradient(135deg,var(--accent-2),var(--accent-deep));box-shadow:0 8px 20px -8px rgba(124,110,246,.7)}
.upd-go:hover{filter:brightness(1.08)}
/* language selector (Settings) */
.langsel{display:flex;flex-wrap:wrap;gap:6px;justify-content:flex-end;flex:1}
.langbtn{display:flex;align-items:center;gap:6px;padding:5px 10px;border-radius:9px;border:1px solid var(--border);
background:var(--panel);color:var(--muted);font-size:12px;cursor:pointer;font-family:var(--font);transition:.14s}
.langbtn:hover{color:var(--txt);border-color:var(--accent)}
.langbtn.on{color:#fff;border-color:transparent;background:linear-gradient(135deg,var(--accent-2),var(--accent-deep));box-shadow:0 6px 16px -6px rgba(124,110,246,.7)}
.langbtn .lflag{font-size:14px;line-height:1}
.langbtn .lname{font-weight:500}
/* zoom selector (Settings) */
.zoomsel{display:flex;align-items:center;gap:5px}
.zbtn{width:28px;height:28px;border:1px solid var(--border);background:var(--panel);color:var(--muted);border-radius:8px;
cursor:pointer;font-size:16px;line-height:1;display:grid;place-items:center;font-family:var(--font)}
.zbtn:hover:not(:disabled){color:var(--txt);border-color:var(--accent)}
.zbtn:disabled{opacity:.4;cursor:not-allowed}
.zval{min-width:58px;height:28px;border:1px solid var(--border);background:var(--panel);color:var(--txt);border-radius:8px;
cursor:pointer;font-size:12px;font-variant-numeric:tabular-nums}
.zval:hover{border-color:var(--accent)}
/* custom dropdown (replaces native <select>) */
.xsel{position:relative}
.xsel-trig{display:flex;align-items:center;gap:9px;width:100%;background:var(--input-bg);border:1px solid var(--border);
border-radius:10px;padding:10px 12px;cursor:pointer;color:var(--txt);font-family:var(--font);font-size:13px;text-align:left}
.xsel-trig:hover,.xsel.open .xsel-trig{border-color:var(--accent)}
.xsel.open .xsel-trig{box-shadow:0 0 0 3px rgba(124,110,246,.15)}
.xsel-trig > svg{width:15px;height:15px;color:var(--faint);flex:0 0 auto}
.xsel-val{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.xsel-ph{color:var(--faint)}
.xsel-chev{flex:0 0 auto;color:var(--faint);display:grid;place-items:center;transition:transform .18s}
.xsel-chev svg{width:15px;height:15px}
.xsel.open .xsel-chev{transform:rotate(180deg)}
.xsel-list{position:absolute;top:calc(100% + 6px);left:0;right:0;z-index:200;max-height:264px;overflow-y:auto;padding:5px;
background:var(--elevated);border:1px solid var(--border);border-radius:12px;box-shadow:0 20px 48px -14px rgba(0,0,0,.5);animation:updin .16s ease}
.xsel-empty{padding:12px;text-align:center;color:var(--faint);font-size:12.5px}
.xsel-item{display:flex;align-items:center;gap:9px;padding:9px 10px;border-radius:9px;cursor:pointer}
.xsel-item:hover{background:var(--hover)}
.xsel-item.on{background:rgba(124,110,246,.12)}
.xsel-ic{width:15px;flex:0 0 auto;display:grid;place-items:center;color:var(--accent-2)}
.xsel-ic svg{width:13px;height:13px}
.xsel-body{display:flex;flex-direction:column;gap:1px;min-width:0}
.xsel-name{font-size:13px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.xsel-sub{font-size:11px;color:var(--faint);font-family:var(--mono);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* Launch-Unreal button (white icon on black / black on white per theme) */
.ue-btn{display:flex;align-items:center;gap:9px;flex:0 0 auto;align-self:center;height:40px;margin:0 8px;padding:0 15px;
border:none;border-radius:11px;cursor:pointer;background:var(--txt);color:var(--win-a);transition:filter .15s,transform .06s}
.ue-btn:hover{filter:brightness(1.12)}
.ue-btn:active{transform:scale(.97)}
.ue-ic{width:24px;height:24px;flex:0 0 auto;display:grid;place-items:center}
.ue-ic svg{width:24px;height:24px}
.ue-lbl{display:flex;flex-direction:column;line-height:1.12;text-align:left}
.ue-a{font-size:9.5px;text-transform:uppercase;letter-spacing:.6px;opacity:.72}
.ue-b{font-size:13px;font-weight:700}
/* bottom status bar (always visible) + hover log peek */
.statusbar{flex:0 0 26px;display:flex;align-items:center;gap:10px;padding:0 12px;border-top:1px solid var(--border);
background:var(--bar);font-size:11.5px;color:var(--muted);position:relative;user-select:none;z-index:60}
.stfront{display:flex;align-items:center;gap:10px;flex:0 1 auto;min-width:0;max-width:70%;height:100%;cursor:default}
.stspace{flex:1}
.stdot{width:16px;height:16px;display:grid;place-items:center;flex:0 0 auto;color:var(--add)}
.stdot svg{width:12px;height:12px}
.stdot.busy{color:var(--accent-2)}
.ldr.sm{width:12px;height:12px;border-width:2px}
.stlast{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-family:var(--mono);font-size:11px}
.stlog{display:flex;align-items:center;gap:6px;flex:0 0 auto;border:1px solid var(--border);background:var(--panel);
color:var(--muted);border-radius:7px;padding:3px 10px;cursor:pointer;font-size:11.5px}
.stlog:hover{color:var(--txt);border-color:var(--accent)}
.stlog svg{width:13px;height:13px}
.stlog.icon{padding:3px 7px}
.stupd{position:relative}
.stupd.has{color:var(--accent);border-color:var(--accent)}
.stupd.busy{color:var(--accent-2)}
.stupd[disabled]{cursor:default;opacity:.85}
.stupd-dot{position:absolute;top:2px;right:2px;width:6px;height:6px;border-radius:50%;background:var(--accent);box-shadow:0 0 0 2px var(--panel)}
.logpeek{position:absolute;left:8px;bottom:26px;width:520px;max-width:calc(100vw - 20px);max-height:min(340px,60vh);overflow-y:auto;z-index:250;
background:var(--elevated);border:1px solid var(--border);border-radius:11px 11px 0 0;padding:5px;box-shadow:0 -14px 40px -12px rgba(0,0,0,.55)}
.logpeek-h{position:sticky;top:0;padding:5px 9px 7px;font-size:10.5px;text-transform:uppercase;letter-spacing:.5px;color:var(--faint);
background:var(--elevated);font-family:var(--font)}
/* log panel (Window → Log) — sits under the main area, above the status bar */
.logpanel{flex:0 0 190px;display:flex;flex-direction:column;min-height:0;border-top:1px solid var(--border);background:var(--sunk)}
.loghead{flex:0 0 auto;display:flex;align-items:center;gap:10px;padding:7px 12px;border-bottom:1px solid var(--border-soft)}
.logtitle{display:flex;align-items:center;gap:7px;font-size:12px;color:var(--muted)}
.logtitle svg{width:14px;height:14px}.logtitle b{color:var(--txt);font-weight:600}
.logn{font-size:10.5px;color:var(--faint);background:var(--panel-3);border-radius:9px;padding:0 7px;font-variant-numeric:tabular-nums}
.loghbtn{margin-left:auto;border:1px solid var(--border);background:var(--panel);color:var(--muted);border-radius:7px;
padding:3px 10px;cursor:pointer;font-size:11px;display:grid;place-items:center}
.loghbtn:hover{color:var(--txt);border-color:var(--accent)}
.loghbtn.x{margin-left:0;padding:3px 8px}
.logbody{flex:1;overflow-y:auto;min-height:0;padding:4px 0;font-family:var(--mono)}
.logempty{padding:20px;text-align:center;color:var(--faint);font-size:12px;font-family:var(--font)}
.logrow{display:flex;align-items:center;gap:9px;padding:3px 12px;font-size:11.5px;line-height:1.55}
.logrow:hover{background:var(--hover)}
.logst{width:12px;flex:0 0 auto;text-align:center;color:var(--add);font-weight:700}
.logrow.err .logst{color:var(--del)}
.logcmd{color:var(--txt);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.logcount{margin-left:auto;flex:0 0 auto;color:var(--faint);white-space:nowrap}
.logrow.err .logcount{color:var(--del)}
/* bottom dock — tabbed Log / Terminal / Unreal */
.dockpanel{position:relative;flex:0 0 240px;display:flex;flex-direction:column;min-height:0;border-top:1px solid var(--border);background:var(--sunk)}
.dockhandle{position:absolute;top:-3px;left:0;right:0;height:7px;cursor:row-resize;z-index:9}
body.resizing-v{cursor:row-resize!important;user-select:none}
.dockhead{flex:0 0 auto;display:flex;align-items:center;gap:6px;padding:4px 10px 0;border-bottom:1px solid var(--border-soft)}
.docktabs{display:flex;gap:2px}
.docktab{display:flex;align-items:center;gap:6px;border:none;background:none;color:var(--muted);font-family:var(--font);font-size:12px;cursor:pointer;padding:7px 12px;border-radius:8px 8px 0 0;border-bottom:2px solid transparent;transition:.12s}
.docktab svg{width:14px;height:14px}
.docktab:hover{color:var(--txt);background:var(--hover)}
.docktab.on{color:var(--txt);border-bottom-color:var(--accent)}
.docktab.on svg{color:var(--accent-2)}
.docktab:active{transform:scale(.96)}
/* dock content fades in when switching Log / Terminal / Unreal */
.dockpane{flex:1;min-height:0;display:flex;flex-direction:column;animation:tabin .26s cubic-bezier(.4,0,.2,1)}
@media (prefers-reduced-motion:reduce){.vpane,.dockpane{animation:none}}
.dockspace{flex:1}
.dockpanel .loghbtn{margin-left:0}
/* terminal */
.term{flex:1;display:flex;flex-direction:column;min-height:0}
.termbody{flex:1;overflow-y:auto;min-height:0;padding:8px 12px;font-family:var(--mono);font-size:12px;line-height:1.5}
.termhint{color:var(--faint);font-family:var(--font);font-size:12px;padding:8px 2px;line-height:1.55}
.termhint.err{color:var(--del)}
.termblock{margin-bottom:9px}
.termcmd{color:var(--txt);white-space:pre-wrap;word-break:break-all}
.termprompt{color:var(--accent);font-weight:700;user-select:none;margin-right:3px}
.termout{margin:2px 0 0;white-space:pre-wrap;word-break:break-word;color:var(--muted)}
.termout.err{color:var(--del)}
.termout.run{color:var(--faint);display:flex;align-items:center;gap:8px}
.terminput-wrap{position:relative;flex:0 0 auto;display:flex;align-items:center;gap:6px;padding:9px 12px;border-top:1px solid var(--border-soft);background:var(--panel)}
.terminput{flex:1;background:none;border:none;outline:none;color:var(--txt);font-family:var(--mono);font-size:12.5px}
.termsug{position:absolute;left:32px;bottom:calc(100% - 1px);min-width:210px;max-height:220px;overflow-y:auto;background:var(--elevated);border:1px solid var(--border);border-radius:10px;box-shadow:0 -14px 34px -14px rgba(0,0,0,.65);z-index:20;padding:4px}
.termsug-i{padding:6px 10px;font-family:var(--mono);font-size:12px;color:var(--muted);border-radius:7px;cursor:pointer;white-space:nowrap}
.termsug-i b{color:var(--accent-2)}
.termsug-i.on,.termsug-i:hover{background:rgba(124,110,246,.14);color:var(--txt)}
/* animated startup splash */
.splash{display:flex;flex-direction:column;align-items:center;gap:16px;padding:20px;animation:updin .5s ease}
.splash-logo{width:64px;height:64px;border-radius:18px;display:grid;place-items:center;color:#fff;
background:linear-gradient(145deg,var(--accent-2),var(--accent-deep));animation:splpulse 1.8s ease-in-out infinite}
.splash-logo svg{width:34px;height:34px}
@keyframes splpulse{0%,100%{transform:scale(1);box-shadow:0 0 40px rgba(124,110,246,.5)}50%{transform:scale(1.06);box-shadow:0 0 62px rgba(124,110,246,.85)}}
.flow{display:flex;align-items:center;margin-top:2px}
.flow .node{width:44px;height:44px;border-radius:12px;display:grid;place-items:center;color:var(--muted);background:var(--panel);border:1px solid var(--border);flex:0 0 auto}
.flow .node svg{width:22px;height:22px}
.wire{position:relative;width:150px;height:2px;background:linear-gradient(90deg,var(--border),var(--accent),var(--border))}
.packet{position:absolute;top:50%;width:7px;height:7px;border-radius:50%;background:var(--accent-2);
box-shadow:0 0 10px var(--accent);transform:translateY(-50%);animation:travel 1.7s linear infinite;opacity:0}
@keyframes travel{0%{left:0;opacity:0}12%{opacity:1}88%{opacity:1}100%{left:100%;opacity:0}}
.splash-title{font-size:20px;font-weight:700;letter-spacing:.3px;margin-top:6px}
.splash-step{font-size:12.5px;color:var(--muted);min-height:16px}
.splash-bar{width:220px;height:4px;border-radius:3px;background:var(--panel-3);overflow:hidden;position:relative}
.splash-bar span{position:absolute;top:0;left:-40%;width:40%;height:100%;border-radius:3px;
background:linear-gradient(90deg,transparent,var(--accent),transparent);animation:shim 1.3s ease-in-out infinite}
@keyframes shim{0%{left:-40%}100%{left:100%}}
/* server transfer progress dialog (P4V-style) */
.xfer-back{backdrop-filter:blur(2px)}
.xfer{width:390px;max-width:calc(100vw - 40px);background:var(--elevated);border:1px solid var(--border);border-radius:16px;padding:20px 22px;box-shadow:var(--shadow);animation:updin .3s ease}
.xfer-head{display:flex;align-items:center;gap:13px}
.xfer-ic{width:42px;height:42px;flex:0 0 auto;border-radius:12px;display:grid;place-items:center;color:#fff}
.xfer-ic.up{background:linear-gradient(145deg,var(--accent-2),var(--accent-deep));box-shadow:0 0 22px rgba(124,110,246,.55)}
.xfer-ic.down{background:linear-gradient(145deg,var(--add),#1f9f6e);box-shadow:0 0 22px rgba(62,207,142,.45)}
.xfer-ic svg{width:22px;height:22px;animation:xbob 1.2s ease-in-out infinite}
@keyframes xbob{0%,100%{transform:translateY(0)}50%{transform:translateY(-3px)}}
.xfer-ic.down svg{animation:xbobd 1.2s ease-in-out infinite}
@keyframes xbobd{0%,100%{transform:translateY(0)}50%{transform:translateY(3px)}}
.xfer-ttl{display:flex;flex-direction:column;gap:2px;min-width:0}
.xfer-ttl b{font-size:14.5px}
.xfer-ttl span{font-size:12px;color:var(--faint);font-variant-numeric:tabular-nums}
.xfer-file{margin-top:14px;font-family:var(--mono);font-size:11.5px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.xfer-actions{margin-left:auto;flex:0 0 auto;align-self:flex-start;display:flex;align-items:center;gap:8px}
.xfer-cancel{flex:0 0 auto;font-size:11.5px;font-weight:600;cursor:pointer;
background:var(--panel-2);border:1px solid var(--border);color:var(--muted);border-radius:8px;padding:5px 11px;transition:.15s}
.xfer-cancel:hover:not(:disabled){color:#fff;background:var(--danger,#e5484d);border-color:var(--danger,#e5484d)}
.xfer-cancel:disabled{opacity:.55;cursor:default}
.xfer-min{flex:0 0 auto;width:26px;height:26px;display:grid;place-items:center;cursor:pointer;
background:var(--panel-2);border:1px solid var(--border);color:var(--muted);border-radius:8px;transition:.15s}
.xfer-min:hover{color:var(--txt);border-color:var(--accent)}
.xfer-min svg{width:15px;height:15px}
/* minimized transfer chip (bottom-right; sits above the build chip if both show) */
.xferchip{position:fixed;right:18px;bottom:18px;z-index:361;display:flex;align-items:center;gap:11px;
padding:9px 11px 9px 12px;border-radius:12px;cursor:pointer;background:var(--elevated);border:1px solid var(--border);
box-shadow:0 16px 40px -14px rgba(0,0,0,.55);animation:updin .25s ease;min-width:210px;max-width:320px;overflow:hidden}
.xferchip.up{border-color:rgba(124,110,246,.5)}
.xferchip.down{border-color:rgba(62,207,142,.5)}
.xferchip:hover{filter:brightness(1.06)}
.xc-ic{flex:0 0 auto;display:grid;place-items:center}
.xc-txt{display:flex;flex-direction:column;gap:1px;min-width:0;flex:1}
.xc-txt b{font-size:12.5px;font-weight:600}
.xc-txt span{font-size:11px;color:var(--faint);font-variant-numeric:tabular-nums;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.xc-cancel{flex:0 0 auto;width:22px;height:22px;border:none;background:none;color:var(--faint);border-radius:6px;cursor:pointer;display:grid;place-items:center}
.xc-cancel:hover:not(:disabled){background:var(--danger,#e5484d);color:#fff}
.xc-cancel:disabled{opacity:.5;cursor:default}
.xc-bar{position:absolute;left:0;bottom:0;height:3px;width:100%;background:transparent}
.xc-bar span{display:block;height:100%;background:linear-gradient(90deg,var(--accent-2),var(--accent-deep));transition:width .25s ease}
.xfer-bar{margin-top:14px;height:6px;border-radius:4px;background:var(--panel-3);overflow:hidden;position:relative}
.xfer-bar span{position:absolute;top:0;left:-35%;width:35%;height:100%;border-radius:4px;
background:linear-gradient(90deg,transparent,var(--accent),transparent);animation:shim 1.1s ease-in-out infinite}
/* determinate (known total): solid fill sized by inline width, no shimmer */
.xfer-bar.det span{position:absolute;left:0;top:0;width:0;animation:none;
background:linear-gradient(90deg,var(--accent-2),var(--accent-deep));transition:width .25s ease;box-shadow:0 0 10px rgba(124,110,246,.55)}
.xfer-log{margin-top:12px;height:132px;overflow-y:auto;overflow-x:hidden;border:1px solid var(--border);border-radius:9px;
background:var(--panel);padding:7px 10px;font-family:var(--mono);font-size:10.5px;line-height:1.55;color:var(--muted)}
.xfer-log div{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.xfer-log div:last-child{color:var(--txt)}
/* MSBuild output overlay */
.build{width:660px;max-width:calc(100vw - 40px);height:min(70vh,560px);display:flex;flex-direction:column;
background:var(--elevated);border:1px solid var(--border);border-radius:16px;box-shadow:var(--shadow);overflow:hidden;animation:updin .3s ease}
.build-head{flex:0 0 auto;display:flex;align-items:center;gap:12px;padding:13px 18px;border-bottom:1px solid var(--border-soft)}
.build-ic{width:34px;height:34px;flex:0 0 auto;border-radius:10px;display:grid;place-items:center;font-weight:700;font-size:16px;background:var(--panel-3);color:var(--muted)}
.build-ic.run{color:var(--accent-2)}
.build-ic.ok{background:rgba(62,207,142,.15);color:var(--add)}
.build-ic.fail{background:rgba(242,99,126,.15);color:var(--del)}
.build-ic svg{width:18px;height:18px}
.build-ttl{display:flex;flex-direction:column;gap:1px;min-width:0}
.build-ttl b{font-size:14px}
.build-ttl span{font-size:11.5px;color:var(--faint);font-family:var(--mono);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.build-x{margin-left:auto;width:28px;height:28px;flex:0 0 auto;border:1px solid var(--border);background:var(--panel);color:var(--muted);border-radius:8px;cursor:pointer;display:grid;place-items:center}
.build-x + .build-x{margin-left:6px}
.build-x:hover:not(:disabled){color:var(--txt);border-color:var(--accent)}
.build-x:disabled{opacity:.4;cursor:not-allowed}
/* minimized build chip */
.buildchip{position:fixed;right:18px;bottom:18px;z-index:360;display:flex;align-items:center;gap:10px;
padding:9px 10px 9px 13px;border-radius:12px;cursor:pointer;background:var(--elevated);border:1px solid var(--border);
box-shadow:0 16px 40px -14px rgba(0,0,0,.55);animation:updin .25s ease;max-width:300px}
.buildchip.run{border-color:rgba(124,110,246,.45)}
.buildchip.ok{border-color:rgba(62,207,142,.5)}
.buildchip.fail{border-color:rgba(242,99,126,.5)}
.buildchip:hover{filter:brightness(1.06)}
.bc-ic{width:20px;height:20px;flex:0 0 auto;display:grid;place-items:center;font-weight:700;font-size:14px}
.buildchip.run .bc-ic{color:var(--accent-2)}.buildchip.ok .bc-ic{color:var(--add)}.buildchip.fail .bc-ic{color:var(--del)}
.bc-txt{font-size:12.5px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.bc-x{width:22px;height:22px;flex:0 0 auto;border:none;background:none;color:var(--faint);border-radius:6px;cursor:pointer;display:grid;place-items:center}
.bc-x:hover{background:var(--hover);color:var(--txt)}
.build-body{flex:1;overflow:auto;min-height:0;padding:10px 14px;font-family:var(--mono);font-size:11.5px;line-height:1.6;background:var(--stage-bg)}
.build-ln{white-space:pre-wrap;word-break:break-word;color:var(--muted)}
.build-ln.err{color:var(--del)}
.build-ln.warn{color:var(--edit)}
.build-ln.ok{color:var(--add);font-weight:600}
.tzone.push .ic{color:var(--add)}
.tzone.push .val{color:var(--add)}
.commit .row{display:flex;gap:10px;align-items:center}
.avatar{width:30px;height:30px;border-radius:50%;flex:0 0 auto;background:linear-gradient(145deg,#6d5cf0,#b07bf7);display:grid;place-items:center;font-size:12px;font-weight:700;color:#fff}
.summary{flex:1;background:var(--panel);border:1px solid var(--border);border-radius:9px;padding:8px 11px;font-size:13px;color:var(--txt);outline:none}
.summary::placeholder{color:var(--faint)}
.desc{background:var(--panel);border:1px solid var(--border);border-radius:9px;padding:9px 11px;font-size:12.5px;color:var(--txt);min-height:46px;resize:none;outline:none;font-family:var(--font)}
.desc::placeholder{color:var(--faint)}
.summary:focus,.desc:focus{border-color:var(--accent);box-shadow:0 0 0 3px rgba(124,110,246,.14)}
.submit{border:none;border-radius:10px;padding:11px;font-size:13.5px;font-weight:600;color:#fff;cursor:pointer;
background:linear-gradient(135deg,var(--accent-2),var(--accent-deep));
box-shadow:0 8px 24px -6px rgba(124,110,246,.6),0 0 0 1px rgba(255,255,255,.08) inset;
display:flex;align-items:center;justify-content:center;gap:8px}
.submit:disabled{opacity:.5;cursor:not-allowed}
.submit:not(:disabled):hover{filter:brightness(1.08)}.submit svg{width:15px;height:15px}.submit b{font-weight:700}
/* right */
.diffhead{display:flex;align-items:center;gap:12px;padding:14px 20px;border-bottom:1px solid var(--border);flex:0 0 auto}
.diffhead .ttl{display:flex;flex-direction:column;gap:2px;min-width:0}
.diffhead .ttl .n{font-size:14px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.diffhead .ttl .n span{color:var(--faint);font-weight:500}
.diffhead .ttl .m{font-size:11.5px;color:var(--muted);display:flex;gap:10px;align-items:center}
.rev{font-family:var(--mono);font-variant-numeric:tabular-nums;color:var(--accent-2)}
.diffhead .tools{margin-left:auto;display:flex;gap:8px;flex:0 0 auto}
.gbtn{display:flex;align-items:center;gap:7px;font-size:12px;color:var(--muted);background:var(--panel);
border:1px solid var(--border);border-radius:9px;padding:7px 12px;cursor:pointer;transition:.15s}
.gbtn:hover{color:var(--txt);border-color:var(--accent)}.gbtn svg{width:14px;height:14px}
.gbtn.vsc svg{color:#3aa0ff}
.gbtn.vsc:hover{border-color:#3aa0ff;color:#3aa0ff}
.gbtn.icon{padding:7px;width:34px;height:32px;justify-content:center;gap:0}
.gbtn.icon svg{width:16px;height:16px}
/* code-editor picker in Settings */
.edsel{flex:none;min-width:170px;font-size:12.5px;font-family:var(--font);color:var(--txt);
background:var(--panel);border:1px solid var(--border);border-radius:8px;padding:7px 10px;cursor:pointer;transition:.15s}
.edsel:hover{border-color:var(--accent)}
.edsel:focus{outline:none;border-color:var(--accent)}
.edsel option{background:var(--panel);color:var(--txt)}
.asset{flex:1;min-height:0;display:grid;grid-template-rows:1fr auto}
.stage{position:relative;min-height:0;overflow:hidden;display:grid;place-items:center;
background:radial-gradient(700px 500px at 50% 40%,rgba(124,110,246,.10),transparent 65%),
repeating-linear-gradient(0deg,transparent,transparent 31px,var(--grid) 31px,var(--grid) 32px),
repeating-linear-gradient(90deg,transparent,transparent 31px,var(--grid) 31px,var(--grid) 32px),var(--stage-bg)}
.stage canvas{max-width:100%;max-height:100%;display:block}
.stage .lbl2{position:absolute;top:14px;left:14px;font-size:11px;color:var(--muted);background:var(--chip);
border:1px solid var(--border);border-radius:20px;padding:5px 11px;display:flex;align-items:center;gap:7px}
.stage .hint{position:absolute;bottom:14px;right:14px;font-size:11px;color:var(--faint)}
/* audio / video preview */
.mediaplayer{width:min(460px,86%)}
.mediaplayer.vid{width:auto;max-width:92%;max-height:88%;border-radius:12px;box-shadow:0 24px 60px -24px #000;background:#000}
.audiobox{display:flex;flex-direction:column;align-items:center;gap:16px;width:min(460px,86%)}
.audio-art{width:104px;height:104px;border-radius:22px;display:grid;place-items:center;color:#fff;
background:linear-gradient(140deg,var(--accent),var(--accent-deep));box-shadow:0 20px 46px -18px var(--accent)}
.audio-art svg{width:48px;height:48px}
.audio-name{font-size:14px;font-weight:600;color:var(--txt);text-align:center;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding:0 10px}
.audiobox audio{width:100%}
.assetmeta{border-top:1px solid var(--border);padding:15px 20px;display:grid;grid-template-columns:repeat(4,1fr);gap:13px 22px;background:var(--sunk)}
.mi{display:flex;flex-direction:column;gap:3px}
.mi .k{font-size:10.5px;color:var(--faint);text-transform:uppercase;letter-spacing:.6px}
.mi .v{font-size:13.5px;font-weight:600;font-variant-numeric:tabular-nums}.mi .v.acc{color:var(--accent-2)}
.nofile{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;color:var(--faint);font-size:13px}
.nofile svg{width:40px;height:40px;opacity:.4}
.files::-webkit-scrollbar{width:10px}
.files::-webkit-scrollbar-thumb{background:var(--panel-3);border-radius:8px}
/* connect screen */
.overlay{position:fixed;inset:0;z-index:100;display:grid;place-items:center;
background:radial-gradient(800px 600px at 50% 30%,rgba(124,110,246,.14),transparent 60%),var(--win-b)}
.card{width:400px;background:var(--elevated);border:1px solid var(--border);border-radius:16px;padding:30px 28px;box-shadow:var(--shadow)}
.card .clogo{width:52px;height:52px;border-radius:14px;background:linear-gradient(145deg,var(--accent-2),var(--accent-deep));
display:grid;place-items:center;margin:0 auto 16px;box-shadow:0 0 30px rgba(124,110,246,.5)}
.card .clogo svg{width:28px;height:28px}
.card h2{text-align:center;font-size:19px;font-weight:700;margin-bottom:4px}
.card .sub{text-align:center;font-size:12.5px;color:var(--muted);margin-bottom:22px}
.fld{display:flex;flex-direction:column;gap:6px;margin-bottom:14px}
.fld label{font-size:11px;color:var(--faint);text-transform:uppercase;letter-spacing:.6px}
.fld .inp{display:flex;align-items:center;gap:9px;background:var(--input-bg);border:1px solid var(--border);border-radius:10px;padding:10px 12px}
.fld .inp:focus-within{border-color:var(--accent);box-shadow:0 0 0 3px rgba(124,110,246,.15)}
.fld .inp svg{width:15px;height:15px;color:var(--faint);flex:0 0 auto}
.fld input,.fld select{border:none;background:none;outline:none;color:var(--txt);font-family:var(--font);font-size:13px;width:100%}
.fld select{cursor:pointer}.fld select option{background:var(--elevated)}
.err{background:rgba(242,99,126,.1);border:1px solid rgba(242,99,126,.3);color:var(--del);border-radius:10px;
padding:10px 12px;font-size:12px;margin-bottom:14px;display:flex;gap:8px;align-items:flex-start;line-height:1.5}
.connect{width:100%;border:none;border-radius:11px;padding:12px;font-size:14px;font-weight:600;color:#fff;cursor:pointer;
background:linear-gradient(135deg,var(--accent-2),var(--accent-deep));box-shadow:0 10px 30px -8px rgba(124,110,246,.6);
display:flex;align-items:center;justify-content:center;gap:9px}
.connect:disabled{opacity:.6;cursor:not-allowed}.connect:not(:disabled):hover{filter:brightness(1.08)}.connect svg{width:16px;height:16px}
.spin{animation:spin 1s linear infinite}
.ldr{display:inline-block;box-sizing:border-box;vertical-align:middle;width:24px;height:24px;border:2.5px solid var(--border);border-top-color:var(--accent);border-radius:50%;animation:spin .8s linear infinite;flex:0 0 auto}
/* diff view */
.diff{flex:1;overflow:auto;min-height:0;font-family:var(--mono);font-size:12.5px;line-height:1.85;padding:6px 0}
.dl{display:grid;grid-template-columns:4px 1fr;white-space:pre-wrap;word-break:break-word}
.dl .g{width:4px}
.dl .c{padding:0 16px 0 12px}
.dl.add{background:rgba(62,207,142,.10)}.dl.add .c{color:var(--diff-add-c)}.dl.add .g{background:var(--add)}
.dl.del{background:rgba(242,99,126,.10)}.dl.del .c{color:var(--diff-del-c)}.dl.del .g{background:var(--del)}
.dl.hunk{background:rgba(124,110,246,.08)}.dl.hunk .c{color:var(--accent-2)}
/* code viewer (GitHub-style content + line numbers) */
.right-body{flex:1;min-height:0;display:flex;flex-direction:column}
.codebar{flex:0 0 auto;display:flex;align-items:center;gap:10px;padding:8px 16px;border-bottom:1px solid var(--border-soft);font-size:12px}
.cb-badge{flex:0 0 auto;font-size:10.5px;font-weight:600;text-transform:uppercase;letter-spacing:.5px;color:var(--muted);
background:var(--panel-3);border-radius:7px;padding:2px 9px}
.cb-badge.add{color:var(--add);background:rgba(62,207,142,.14)}
.cb-badge.diff{color:var(--accent-2);background:rgba(124,110,246,.14)}
.cb-name{color:var(--txt);font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cb-lines{margin-left:auto;flex:0 0 auto;color:var(--faint);font-variant-numeric:tabular-nums}
.code{flex:1;min-height:0;overflow:auto;display:flex;font-family:var(--mono);font-size:12.5px;line-height:1.7}
.code-gutter{position:sticky;left:0;z-index:1;flex:0 0 auto;display:flex;flex-direction:column;text-align:right;
padding:10px 12px 10px 16px;color:var(--faint);background:var(--stage-bg);border-right:1px solid var(--border-soft);
user-select:none;font-variant-numeric:tabular-nums}
.code.added .code-gutter{color:var(--add);background:rgba(62,207,142,.06)}
.code-body{flex:1;margin:0;padding:10px 16px;white-space:pre;overflow:visible}
.code-body code{white-space:pre;font-family:inherit;background:none;padding:0}
.code.added .code-body{background:rgba(62,207,142,.04)}
/* built-in code editor */
.cb-badge.editing{color:var(--edit);background:rgba(232,176,75,.16)}
.ce-actions{margin-left:auto;display:flex;gap:8px;align-items:center}
.ce-btn{display:flex;align-items:center;gap:6px;font-size:11.5px;font-weight:600;font-family:var(--font);cursor:pointer;
color:var(--muted);background:var(--panel);border:1px solid var(--border);border-radius:8px;padding:5px 11px;transition:.15s}
.ce-btn:hover:not(:disabled){color:var(--txt);border-color:var(--accent)}
.ce-btn:disabled{opacity:.5;cursor:default}
.ce-btn.save{color:#fff;border:none;background:linear-gradient(135deg,var(--accent-2),var(--accent-deep))}
.ce-btn.save:hover:not(:disabled){filter:brightness(1.1)}
.ce-btn svg{width:13px;height:13px}
/* spec editors (client / job / .p4ignore): a clean editor surface, not a flat grey box */
.code-edit{flex:1;min-height:0;width:100%;resize:none;border:none;outline:none;
font-family:var(--mono);font-size:12.5px;line-height:1.7;tab-size:4;color:var(--txt);
background:var(--elevated);padding:12px 16px 14px 18px;white-space:pre;overflow:auto;
box-shadow:inset 3px 0 0 var(--border-soft)}
.code-edit:focus{box-shadow:inset 3px 0 0 var(--accent)}
/* workspace View include/exclude tree (P4V-style) */
.vt-modes{margin-left:auto;display:flex;gap:2px;background:var(--panel-3);border:1px solid var(--border);border-radius:9px;padding:2px}
.vt-modes button{width:28px;height:24px;display:grid;place-items:center;border:none;background:none;color:var(--faint);border-radius:7px;cursor:pointer;transition:.15s}
.vt-modes button svg{width:15px;height:15px}
.vt-modes button:hover{color:var(--txt)}
.vt-modes button.on{background:var(--elevated);color:var(--accent-2)}
.vt-tree{flex:1;min-height:0;overflow:auto;background:var(--elevated);padding:6px 4px}
.vt-node{user-select:none}
.vt-row{display:flex;align-items:center;gap:7px;height:26px;border-radius:7px;padding-right:8px;cursor:default}
.vt-row:hover{background:#ffffff08}
.vt-chev{width:16px;height:16px;flex:0 0 auto;display:grid;place-items:center;color:var(--faint);cursor:pointer}
.vt-chev svg{width:13px;height:13px;transition:transform .12s ease}
.vt-chk{width:16px;height:16px;flex:0 0 auto;border-radius:4px;border:1.5px solid var(--border);display:grid;place-items:center;cursor:pointer;transition:.12s;background:var(--panel)}
.vt-chk:hover{border-color:var(--accent)}
.vt-chk.on{background:var(--accent);border-color:var(--accent)}
.vt-chk.mixed{background:var(--faint);border-color:var(--faint)}
.vt-chk svg{width:12px;height:12px}
.vt-ic{width:16px;height:16px;flex:0 0 auto;display:grid;place-items:center;color:var(--accent-2)}
.vt-ic svg{width:15px;height:15px}
.vt-name{font-size:13px;color:var(--txt);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.vt-loading,.vt-empty{height:24px;display:flex;align-items:center;gap:7px;font-size:11.5px;color:var(--faint)}
/* themes modal */
.th-grid{flex:1;min-height:0;overflow:auto;display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:12px;padding:16px}
.th-card{position:relative;border:1.5px solid var(--border);border-radius:13px;overflow:hidden;cursor:pointer;background:var(--panel);transition:.15s}
.th-card:hover{border-color:var(--accent)}
.th-card.on{border-color:var(--accent);box-shadow:0 0 0 3px rgba(124,110,246,.2)}
.th-swatch{height:64px;display:flex;align-items:center;gap:7px;padding:0 14px}
.th-swatch span{width:20px;height:20px;border-radius:50%;box-shadow:0 2px 6px rgba(0,0,0,.35)}
.th-meta{padding:9px 12px 11px}
.th-meta b{display:block;font-size:13px;font-weight:600}
.th-meta span{font-size:11px;color:var(--faint)}
.th-on{position:absolute;top:8px;right:8px;width:22px;height:22px;border-radius:50%;background:var(--accent);color:#fff;display:grid;place-items:center}
.th-on svg{width:13px;height:13px}
.th-actions{position:absolute;top:7px;right:7px;display:none;gap:4px}
.th-card:hover .th-actions{display:flex}
.th-actions button{width:24px;height:24px;border:none;border-radius:7px;background:var(--chip);color:var(--txt);cursor:pointer;display:grid;place-items:center;backdrop-filter:blur(4px)}
.th-actions button svg{width:13px;height:13px}
.th-actions button:hover{background:var(--accent);color:#fff}
.th-actions button.danger:hover{background:var(--del)}
.th-edit{flex:1;min-height:0;overflow:auto;padding:16px}
.th-edit-row{display:flex;align-items:center;gap:12px;margin-bottom:18px;flex-wrap:wrap}
.th-edit-row label{font-size:12px;color:var(--muted);font-weight:600}
.th-edit-row input{flex:1;min-width:160px;background:var(--input-bg);border:1px solid var(--border);border-radius:9px;padding:9px 12px;color:var(--txt);font-size:14px;outline:none}
.th-edit-row input:focus{border-color:var(--accent)}
.th-base{display:flex;gap:2px;background:var(--panel-3);border-radius:9px;padding:2px}
.th-base button{display:flex;align-items:center;gap:5px;font-size:12px;font-weight:600;border:none;background:none;color:var(--muted);border-radius:7px;padding:7px 11px;cursor:pointer}
.th-base button svg{width:14px;height:14px}
.th-base button.on{background:var(--elevated);color:var(--accent-2)}
.th-group{margin-bottom:16px}
.th-group-h{font-size:11px;text-transform:uppercase;letter-spacing:.5px;color:var(--faint);font-weight:600;margin-bottom:9px}
.th-tokens{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:9px}
.th-token{display:flex;align-items:center;gap:9px;font-size:12.5px;color:var(--txt);cursor:pointer}
.th-token input[type=color]{width:30px;height:30px;flex:0 0 auto;border:1px solid var(--border);border-radius:8px;background:none;cursor:pointer;padding:2px}
.th-token input[type=color]::-webkit-color-swatch{border:none;border-radius:6px}
.th-token input[type=color]::-webkit-color-swatch-wrapper{padding:0}
/* plugins manager */
.pl-list{flex:1;min-height:0;overflow:auto;padding:14px;display:flex;flex-direction:column;gap:10px}
.pl-official-h{font-size:11px;text-transform:uppercase;letter-spacing:.5px;color:var(--faint);font-weight:700;margin:8px 2px 0;padding-top:10px;border-top:1px solid var(--border-soft);display:flex;align-items:baseline;gap:8px}
.pl-cat-sub{text-transform:none;letter-spacing:0;font-weight:500;color:var(--faint);opacity:.8}
.pl-card{display:flex;gap:12px;align-items:flex-start;border:1px solid var(--border);border-radius:12px;padding:13px 15px;background:var(--panel);transition:.15s}
.pl-card.off{opacity:.55}
.pl-main{flex:1;min-width:0}
.pl-top{display:flex;align-items:baseline;gap:9px}
.pl-top b{font-size:14px;font-weight:650}
.pl-ver{font-size:11px;color:var(--faint);font-variant-numeric:tabular-nums}
.pl-desc{font-size:12.5px;color:var(--muted);margin-top:3px;line-height:1.45}
.pl-meta{display:flex;flex-wrap:wrap;gap:6px;margin-top:9px}
.pl-tag{font-size:11px;color:var(--muted);background:var(--panel-3);border-radius:6px;padding:2px 8px}
.pl-perm{font-size:10.5px;font-weight:600;color:var(--accent-2);background:rgba(124,110,246,.12);border:1px solid rgba(124,110,246,.25);border-radius:6px;padding:2px 8px}
.pl-actions{flex:0 0 auto;display:flex;align-items:center;gap:8px}
.pl-toggle{width:38px;height:22px;border-radius:12px;border:none;background:var(--panel-3);cursor:pointer;position:relative;transition:.18s;padding:0}
.pl-toggle span{position:absolute;top:3px;left:3px;width:16px;height:16px;border-radius:50%;background:var(--faint);transition:.18s}
.pl-toggle.on{background:var(--accent)}
.pl-toggle.on span{left:19px;background:#fff}
.pl-del{width:30px;height:30px;border:none;background:none;color:var(--faint);border-radius:8px;cursor:pointer;display:grid;place-items:center}
.pl-del svg{width:15px;height:15px}
.pl-del:hover{background:rgba(242,99,126,.14);color:var(--del)}
.plugin-view{flex:1;min-height:0;min-height:340px;overflow:auto;padding:16px;color:var(--txt);font-size:13.5px}
/* settings — two-pane (left nav + content) */
.settings-modal{width:min(860px,94vw);height:min(620px,88vh);display:flex;background:var(--elevated);border:1px solid var(--border);border-radius:16px;box-shadow:var(--shadow);overflow:hidden;animation:updin .2s ease}
.set-nav{flex:0 0 210px;display:flex;flex-direction:column;gap:2px;padding:14px 10px;background:var(--panel);border-right:1px solid var(--border-soft)}
.set-nav-h{display:flex;align-items:center;gap:9px;padding:6px 10px 14px;font-size:14px;font-weight:650}
.set-nav-logo{display:grid;place-items:center;color:var(--accent-2)}
.set-nav-logo svg{width:18px;height:18px}
.set-nav-item{display:flex;align-items:center;gap:10px;padding:9px 11px;border:none;background:none;color:var(--muted);font-size:13.5px;font-weight:500;font-family:var(--font);border-radius:9px;cursor:pointer;text-align:left;transition:.12s}
.set-nav-item .sni-ic{display:grid;place-items:center;flex:0 0 auto}
.set-nav-item svg{width:16px;height:16px}
.set-nav-item:hover{background:var(--hover);color:var(--txt)}
.set-nav-item.on{background:var(--accent);color:#fff}
.set-nav-item.danger{color:var(--del)}
.set-nav-item.danger:hover{background:rgba(242,99,126,.14)}
.set-nav-sp{flex:1}
.set-main{flex:1;min-width:0;display:flex;flex-direction:column}
.set-main-h{display:flex;align-items:center;padding:16px 18px 12px;border-bottom:1px solid var(--border-soft)}
.set-main-h h3{font-size:16px;font-weight:650;flex:1}
.set-main .info-body{flex:1;min-height:0;padding:16px 20px}
.set-panel{flex:1;min-height:0;display:flex;flex-direction:column;overflow:hidden}
.set-sep{height:1px;background:var(--border-soft);margin:14px 0}
/* rich code editor: transparent textarea over a highlighted underlay + gutter */
.code.editing{overflow:hidden}
.code.editing .code-gutter{overflow:hidden}
.ce-wrap{position:relative;flex:1;min-width:0;background:transparent}
.ce-under,.ce-ta{margin:0;padding:10px 16px;border:0;font-family:var(--mono);font-size:12.5px;line-height:1.7;tab-size:4;white-space:pre;word-wrap:normal;letter-spacing:normal}
.ce-under{position:absolute;inset:0;overflow:hidden;pointer-events:none;background:none;color:var(--txt)}
.ce-under code{font-family:inherit;background:none;padding:0;white-space:pre}
.ce-ta{position:absolute;inset:0;width:100%;height:100%;resize:none;outline:none;overflow:auto;background:transparent;color:transparent;caret-color:var(--accent-2)}
.ce-ta::selection{background:rgba(124,110,246,.28);color:transparent}
.ce-ta::-moz-selection{background:rgba(124,110,246,.28);color:transparent}
/* highlight.js tokens mapped to the app palette (theme-aware) */
.hljs{color:var(--txt);background:none}
.hljs-comment,.hljs-quote{color:var(--faint);font-style:italic}
.hljs-keyword,.hljs-selector-tag,.hljs-built_in,.hljs-name,.hljs-tag{color:var(--accent-2)}
.hljs-string,.hljs-attr,.hljs-symbol,.hljs-bullet,.hljs-addition,.hljs-meta-string{color:var(--add)}
.hljs-number,.hljs-literal,.hljs-type,.hljs-params,.hljs-template-variable,.hljs-variable{color:var(--edit)}
.hljs-title,.hljs-title.function_,.hljs-section,.hljs-class .hljs-title{color:var(--txt);font-weight:600}
.hljs-attribute,.hljs-selector-id,.hljs-selector-class,.hljs-selector-attr{color:var(--accent)}
.hljs-meta,.hljs-comment.hljs-doctag{color:var(--muted)}
.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}
.hljs-deletion{color:var(--del)}
.diff::-webkit-scrollbar{width:10px}.diff::-webkit-scrollbar-thumb{background:var(--panel-3);border-radius:8px}
/* history */
.hrow{display:flex;gap:12px;align-items:flex-start;padding:12px 16px;border-bottom:1px solid var(--border-soft);position:relative}
.hrow.click{cursor:pointer}
.hrow:hover{background:var(--hover)}
.hrow.sel{background:rgba(124,110,246,.12);box-shadow:inset 2px 0 0 var(--accent)}
/* virtualized changelist-file row (History detail) */
.crow{position:absolute;left:0;right:0;height:52px;display:flex;gap:12px;align-items:center;padding:0 16px;border-bottom:1px solid var(--border-soft)}
.crow:hover{background:var(--hover)}
.crow.click{cursor:pointer}
.crow.click:hover .crow-go{opacity:1;transform:translateX(0)}
.crow.sel{background:rgba(124,110,246,.12);box-shadow:inset 2px 0 0 var(--accent)}
.crow-go{margin-left:auto;flex:0 0 auto;color:var(--faint);font-size:18px;line-height:1;opacity:0;transform:translateX(-4px);transition:opacity .12s,transform .12s;display:flex;align-items:center}
.crow-go svg{width:16px;height:16px}
.gbtn.back{padding:6px 8px}.gbtn.back svg{width:16px;height:16px}
/* History = GitHub-style split: changed-files list beside the file content (no covering) */
.histsplit{display:flex;min-width:0;min-height:0;overflow:hidden}
.histsplit>.right{flex:1 1 auto;min-width:0}
/* width comes from a direct inline style on the element (set in ChangeDetail) */
.histsplit>.histlist{min-width:0;border-right:1px solid var(--border)}
.histsplit.solo>.histlist{flex:1 1 auto;border-right:none} /* nothing open → list fills the panel */
/* plain in-flow 8px column between list and preview — only the cursor hints it's draggable.
position MUST override the base .vhandle{position:absolute}, or it falls out of the flex flow */
.histsplit>.histh{position:relative;flex:none;width:8px;align-self:stretch;cursor:col-resize;background:transparent;top:auto;bottom:auto}
.histsplit .histlist .crow-go{opacity:0}
.histsplit .histlist .crow.sel .crow-go{opacity:1;transform:translateX(0)}
/* ---- right-side view panel with tabs (File Viewer / File Tree) ---- */
.viewpanel{display:flex;flex-direction:column;min-width:0;min-height:0;overflow:hidden}
.vtabs{display:flex;align-items:stretch;gap:2px;padding:6px 8px 0;border-bottom:1px solid var(--border);background:var(--sunk);flex:0 0 auto;overflow-x:auto;overflow-y:hidden}
.vtab{display:flex;align-items:center;gap:7px;padding:7px 12px;border-radius:9px 9px 0 0;font-size:12.5px;font-weight:600;color:var(--muted);cursor:pointer;white-space:nowrap;border:1px solid transparent;border-bottom:none;position:relative;top:1px;transition:background .22s ease,border-color .22s ease,color .18s ease}
.vtab:active{transform:scale(.97)}
.vtab:hover{color:var(--txt);background:var(--hover)}
.vtab.on{color:var(--txt);background:var(--bg);border-color:var(--border)}
.vtab-ic{display:grid;place-items:center;color:var(--accent-2)}
.vtab-ic svg{width:15px;height:15px}
.vtab-x{margin-left:4px;width:17px;height:17px;display:grid;place-items:center;border-radius:5px;font-size:15px;line-height:1;color:var(--faint)}
.vtab-x:hover{background:var(--del);color:#fff}
.viewbody{flex:1;display:flex;min-height:0;min-width:0;position:relative}
.vpane{flex:1;min-width:0;min-height:0;animation:tabin .28s cubic-bezier(.4,0,.2,1)}
.vpane>.right,.vpane>.histsplit{flex:1 1 auto;min-width:0;min-height:0}
.vpane.tree{flex-direction:column}
.ft-bar{display:flex;align-items:center;gap:10px;padding:9px 14px;border-bottom:1px solid var(--border-soft);flex:0 0 auto}
.ft-total{margin-left:auto;font-size:12px;color:var(--muted);white-space:nowrap;font-variant-numeric:tabular-nums}
.ft-total b{color:var(--accent-2)}
.ft-new{display:flex;align-items:center;gap:5px;font-family:var(--font);font-size:11.5px;font-weight:600;color:var(--accent-2);
background:rgba(124,110,246,.1);border:1px solid rgba(124,110,246,.24);border-radius:8px;padding:4px 10px;cursor:pointer;flex:0 0 auto;transition:.14s}
.ft-new:hover{background:rgba(124,110,246,.18);border-color:rgba(124,110,246,.4)}
.ft-new svg{width:13px;height:13px}
/* folder properties dialog */
.fp-body{padding:18px 20px}
.fp-name{display:flex;align-items:center;gap:10px;font-size:15px;margin-bottom:16px}
.fp-name svg{width:20px;height:20px;color:var(--accent-2);flex:0 0 auto}
.fp-name b{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fp-grid{display:grid;grid-template-columns:auto 1fr;gap:10px 16px;font-size:13px}
.fp-grid .k{color:var(--faint)}
.fp-grid .v{color:var(--txt);min-width:0;overflow:hidden;text-overflow:ellipsis;font-variant-numeric:tabular-nums}
.fp-grid .v.mono{font-family:var(--mono);font-size:12px;word-break:break-all;white-space:normal}
.vpane.tree .exp-tree{flex:1;min-height:0}
.hnum{font-family:var(--mono);font-size:12px;color:var(--accent-2);font-variant-numeric:tabular-nums;flex:0 0 auto;padding-top:1px}
.hbody{display:flex;flex-direction:column;gap:3px;min-width:0}
.hdesc{font-size:13px;color:var(--txt);overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
.hmeta{font-size:11px;color:var(--faint)}
.hsize{margin-left:7px;padding:1px 6px;border-radius:6px;background:var(--chip);border:1px solid var(--border-soft);color:var(--muted);font-weight:600;font-variant-numeric:tabular-nums;white-space:nowrap}
.hnew{position:absolute;top:50%;right:14px;transform:translateY(-50%);padding:3px 10px;border-radius:7px;font-size:11px;font-weight:800;letter-spacing:.7px;color:#fff;pointer-events:none;
background:linear-gradient(135deg,var(--accent-2),var(--accent-deep));box-shadow:0 0 0 rgba(124,110,246,.5);animation:newpulse 2.2s ease-in-out infinite}
@keyframes newpulse{0%,100%{box-shadow:0 0 0 0 rgba(124,110,246,.45)}50%{box-shadow:0 0 0 4px rgba(124,110,246,0)}}
/* 3d viewer toolbar */
.v3d-tools{position:absolute;top:12px;right:12px;display:flex;gap:6px;z-index:2}
.v3d-btn{width:32px;height:32px;border-radius:9px;border:1px solid var(--border);background:var(--chip);color:var(--muted);
cursor:pointer;font-size:15px;line-height:1;display:grid;place-items:center;backdrop-filter:blur(6px);transition:.15s}
.v3d-btn:hover{color:var(--txt);border-color:var(--accent)}
.v3d-btn.on{color:#fff;background:linear-gradient(145deg,var(--accent-2),var(--accent-deep));border-color:var(--accent)}
/* viewer states */
.viewer-msg{position:absolute;display:flex;align-items:center;gap:10px;color:var(--muted);font-size:13px}
.viewer-msg.err{color:var(--del);max-width:80%;text-align:center}
.uasset-card{display:flex;flex-direction:column;align-items:center;gap:12px;text-align:center;max-width:340px;padding:20px}
.uasset-ic{width:64px;height:64px;border-radius:18px;display:grid;place-items:center;color:var(--accent-2);
background:rgba(124,110,246,.12);border:1px solid var(--border)}
.uasset-ic svg{width:34px;height:34px}
.uasset-name{font-size:15px;font-weight:600}
.uasset-note{font-size:12px;color:var(--muted);line-height:1.55}
/* picker / info modal (reuses modal-back) */
.picker{width:440px;max-width:92%;max-height:74vh;background:var(--elevated);border:1px solid var(--border);border-radius:18px;
box-shadow:0 30px 80px -20px rgba(0,0,0,.7);display:flex;flex-direction:column;overflow:hidden;animation:pop .18s cubic-bezier(.2,.9,.3,1.2)}
.picker-head{padding:18px 20px 14px;border-bottom:1px solid var(--border-soft);display:flex;align-items:center;gap:10px}
.picker-head h3{font-size:15px;font-weight:700}
.picker-head > svg{width:20px;height:20px;flex:0 0 auto;color:var(--accent-2)}
.picker-head .x,.set-main-h .x{margin-left:auto;width:28px;height:28px;border:none;background:var(--panel);border-radius:8px;color:var(--muted);cursor:pointer;display:grid;place-items:center;transition:.15s}
.picker-head .x:hover,.set-main-h .x:hover{color:var(--txt);background:var(--hover)}
.picker-head .x svg,.set-main-h .x svg{width:14px;height:14px}
.picker-list{overflow-y:auto;padding:8px}
.picker-item{display:flex;align-items:center;gap:12px;padding:11px 12px;border-radius:11px;cursor:pointer;transition:background .12s}
.picker-item:hover{background:var(--hover)}
.picker-item.on{background:rgba(124,110,246,.13);box-shadow:inset 0 0 0 1px rgba(124,110,246,.28)}
.picker-item .pi-ic{width:34px;height:34px;border-radius:9px;flex:0 0 auto;display:grid;place-items:center;color:var(--accent-2);background:rgba(124,110,246,.1)}
.picker-item .pi-ic svg{width:17px;height:17px}
.picker-item .pi-body{display:flex;flex-direction:column;gap:2px;min-width:0}
.picker-item .pi-name{font-size:13.5px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.picker-item .pi-sub{font-size:11.5px;color:var(--faint);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* recently-used working folders */
.pick-recent{border-bottom:1px solid var(--border-soft);margin-bottom:6px;padding-bottom:6px}
.pick-recent-h{font-size:10.5px;letter-spacing:.09em;text-transform:uppercase;color:var(--faint);padding:4px 12px 6px;font-weight:600}
.picker-item .pi-ic.clock,.picker-item .pi-ic.up{color:var(--muted);background:var(--panel-3)}
/* "local only, not in depot yet" tag */
.local-tag{margin-left:8px;font-size:9.5px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--warn);
background:rgba(232,176,75,.14);border:1px solid rgba(232,176,75,.32);border-radius:6px;padding:1px 6px;vertical-align:middle}
.picker-foot{padding:12px 20px;border-top:1px solid var(--border-soft);font-size:12px;color:var(--faint)}
.info-body{padding:20px;font-size:13px;line-height:1.6;color:var(--muted)}
.info-body b{color:var(--txt)}
.info-row{display:flex;justify-content:space-between;gap:16px;padding:7px 0;border-bottom:1px solid var(--border-soft)}
.info-row:last-child{border-bottom:none}
.info-row .rk{color:var(--faint)}.info-row .rv{color:var(--txt);font-weight:500;font-family:var(--mono);font-size:12px}
/* confirm modal */
.modal-back{position:fixed;inset:0;z-index:210;display:grid;place-items:center;
background:rgba(6,6,10,.55);backdrop-filter:blur(3px);animation:fadein .15s ease}
.modal-card{width:380px;max-width:90%;background:var(--elevated);border:1px solid var(--border);border-radius:18px;
padding:26px 26px 20px;box-shadow:0 30px 80px -20px rgba(0,0,0,.7);text-align:center;animation:pop .18s cubic-bezier(.2,.9,.3,1.2)}
.modal-icon{width:52px;height:52px;border-radius:14px;margin:0 auto 16px;display:grid;place-items:center;
background:rgba(124,110,246,.14);color:var(--accent-2)}
.modal-icon svg{width:26px;height:26px}
.modal-icon.danger{background:rgba(242,99,126,.14);color:var(--del)}
.modal-card h3{font-size:17px;font-weight:700;margin-bottom:8px}
.modal-card p{font-size:13px;line-height:1.55;color:var(--muted);white-space:pre-wrap;margin-bottom:22px}
.modal-actions{display:flex;gap:10px}
.mbtn{flex:1;display:inline-flex;align-items:center;justify-content:center;gap:8px;border:none;border-radius:11px;padding:11px;font-size:13.5px;font-weight:600;cursor:pointer;font-family:var(--font);transition:filter .15s,background .15s}
.mbtn svg{width:15px;height:15px;flex:0 0 auto}
.mbtn.ghost{background:var(--panel);border:1px solid var(--border);color:var(--txt)}
.mbtn.ghost:hover{background:var(--hover)}
.mbtn.primary{color:#fff;background:linear-gradient(135deg,var(--accent-2),var(--accent-deep));box-shadow:0 8px 22px -8px rgba(124,110,246,.7)}
.mbtn.danger{color:#fff;background:linear-gradient(135deg,#f2637e,#d23a5c);box-shadow:0 8px 22px -8px rgba(242,99,126,.6)}
.mbtn.primary:hover,.mbtn.danger:hover{filter:brightness(1.08)}
@keyframes fadein{from{opacity:0}to{opacity:1}}
@keyframes pop{from{opacity:0;transform:scale(.94) translateY(8px)}to{opacity:1;transform:scale(1) translateY(0)}}
/* drag & drop overlay */
.dropzone{position:fixed;inset:0;z-index:150;display:grid;place-items:center;
background:rgba(124,110,246,.14);backdrop-filter:blur(2px);pointer-events:none}
.dropinner{display:flex;flex-direction:column;align-items:center;gap:14px;color:var(--accent-2);
border:2px dashed var(--accent);border-radius:20px;padding:40px 60px;background:var(--elevated)}
.dropinner svg{width:44px;height:44px}
.dropinner span{font-size:15px;font-weight:600;color:var(--txt)}
/* re-auth: who we're signing back in as */
.reauth-who{display:flex;flex-wrap:wrap;gap:6px;margin:2px 0 14px}
.reauth-who span{font-family:var(--mono);font-size:11px;color:var(--muted);
background:var(--panel-3);border:1px solid var(--border);border-radius:6px;padding:3px 8px}
/* toast */
.toast{position:fixed;bottom:18px;left:50%;transform:translateX(-50%);z-index:200;max-width:72%;
background:var(--elevated);border:1px solid var(--border);color:var(--txt);
padding:11px 18px;border-radius:12px;font-size:12.5px;box-shadow:0 20px 50px -15px rgba(0,0,0,.6);
animation:toastin .25s ease;white-space:pre-wrap;text-align:center;
max-height:30vh;overflow-y:auto;overflow-wrap:anywhere}
.toast.err{border-color:rgba(242,99,126,.4);color:var(--del)}
@keyframes toastin{from{opacity:0;transform:translate(-50%,10px)}to{opacity:1;transform:translate(-50%,0)}}
/* ---------------- avatars ---------------- */
.avatar{position:relative;flex:0 0 auto;border-radius:50%;display:grid;place-items:center;color:#fff;font-weight:700;letter-spacing:.02em;text-transform:uppercase;box-shadow:inset 0 0 0 1px rgba(255,255,255,.14);user-select:none}
.adot{position:absolute;right:-1px;bottom:-1px;width:9px;height:9px;border-radius:50%;border:2px solid var(--elevated);background:var(--faint)}
.adot.active{background:#3ecb8f}.adot.recent{background:#f4c04e}.adot.idle{background:#6b6b7a}
/* ---------------- AI commit summary ---------------- */
.summrow{display:flex;gap:8px;align-items:stretch}
.aibtn{flex:0 0 auto;display:flex;align-items:center;gap:6px;border:1px solid var(--border);border-radius:9px;padding:0 12px;
font-size:12px;font-weight:600;font-family:var(--font);cursor:pointer;color:var(--accent-2);
background:linear-gradient(135deg,rgba(124,110,246,.16),rgba(124,110,246,.06));transition:.15s}
.aibtn:hover:not(:disabled){filter:brightness(1.12);border-color:rgba(124,110,246,.5)}
.aibtn:disabled{opacity:.5;cursor:default}
.aibtn svg{width:15px;height:15px}
.aibtn.busy{color:var(--faint)}
.aibtn.icon{padding:0;width:34px;justify-content:center}
/* code "Summary" button + AI explanation card in the preview header */
.gbtn.ai{color:var(--accent-2);border-color:rgba(124,110,246,.35);background:linear-gradient(135deg,rgba(124,110,246,.14),rgba(124,110,246,.05))}
.gbtn.ai:hover{filter:brightness(1.1);border-color:rgba(124,110,246,.55)}
.gbtn.ai.busy{color:var(--faint)}
.explain{flex:0 0 auto;display:flex;align-items:flex-start;gap:10px;margin:0;padding:12px 16px;
background:linear-gradient(135deg,rgba(124,110,246,.1),rgba(124,110,246,.03));border-bottom:1px solid var(--border-soft)}
.explain-ic{flex:0 0 auto;color:var(--accent-2);display:flex}
.explain-ic svg{width:17px;height:17px}
.explain-body{flex:1;font-size:12.5px;line-height:1.55;color:var(--txt);min-width:0}
.explain-load{display:flex;align-items:center;gap:8px;color:var(--faint)}
.explain-x{flex:0 0 auto;border:none;background:none;color:var(--faint);font-size:18px;line-height:1;cursor:pointer;padding:0 2px}
.explain-x:hover{color:var(--txt)}
/* "Load 3D model" button in the .uasset preview */
.load3d{position:absolute;bottom:16px;left:50%;transform:translateX(-50%);display:flex;align-items:center;gap:8px;
font-size:12.5px;font-weight:600;font-family:var(--font);color:#fff;cursor:pointer;padding:9px 16px;border-radius:10px;border:none;
background:linear-gradient(135deg,var(--accent-2),var(--accent-deep));box-shadow:0 8px 24px -8px rgba(124,110,246,.7);transition:.15s}
.load3d:hover:not(:disabled){filter:brightness(1.1)}
.load3d:disabled{opacity:.5;cursor:default;box-shadow:none}
.load3d svg{width:15px;height:15px}
/* ---------------- collaboration UI (locks / banners / search / blame / diff / resolve) ---------------- */
/* connection + resolve banners */
.netbar{display:flex;align-items:center;gap:10px;padding:8px 16px;font-size:12.5px;font-weight:600;flex:0 0 auto}
.netbar svg{width:16px;height:16px;flex:0 0 auto}
.netbar.off{background:rgba(242,99,126,.14);color:var(--del);border-bottom:1px solid rgba(242,99,126,.3)}
.netbar.warn{background:rgba(232,176,75,.14);color:var(--edit);border-bottom:1px solid rgba(232,176,75,.3);cursor:pointer}
.netbar.warn:hover{background:rgba(232,176,75,.2)}
/* explicit "Work Offline" mode — violet, calmer than the error-red disconnect bar */
.netbar.offmode{background:rgba(124,110,246,.13);color:var(--accent-2);border-bottom:1px solid rgba(124,110,246,.3)}
/* "you're behind the server" — informational blue, clickable to Get Latest */
.netbar.behind{background:rgba(90,160,255,.14);color:#4f8fe0;border-bottom:1px solid rgba(90,160,255,.32);cursor:pointer}
.netbar.behind:hover{background:rgba(90,160,255,.2)}
.behind-names{font-weight:500;opacity:.8;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
.netbar-btn{margin-left:auto;border:1px solid currentColor;background:none;color:inherit;font-size:11.5px;font-weight:700;
border-radius:7px;padding:4px 12px;cursor:pointer;font-family:var(--font)}
.netbar-btn+.netbar-btn{margin-left:0}
.netbar-btn:hover{background:currentColor}
.netbar-btn:hover{color:var(--bg)}
/* reconcile offline-work dialog */
.rec-summary{display:flex;align-items:center;gap:6px;padding:8px 16px;font-size:12px;color:var(--muted);border-bottom:1px solid var(--border-soft)}
.rec-all{margin-left:auto;color:var(--accent-2);font-weight:700;cursor:pointer}
.rec-all:hover{text-decoration:underline}
.rec-row{cursor:pointer}
.rec-row .chk{flex:0 0 16px}
/* "held by someone else" pill on a Changes row */
.held{display:flex;align-items:center;gap:4px;flex:0 0 auto;font-size:10.5px;font-weight:600;color:var(--muted);
background:var(--chip);border:1px solid var(--border-soft);border-radius:7px;padding:2px 7px;max-width:120px;overflow:hidden}
.held svg{width:12px;height:12px;flex:0 0 auto}
.held span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.held.locked{color:var(--del);border-color:rgba(242,99,126,.35);background:rgba(242,99,126,.1)}
/* search results / resolve list share the srch layout */
.srch-list{flex:1;overflow-y:auto;padding:6px 10px 12px}
.srch-row{display:flex;align-items:center;gap:8px;padding:8px 10px;border-radius:9px;transition:background .12s}
.srch-row:hover{background:var(--hover)}
.srch-row.on{background:rgba(124,110,246,.12);box-shadow:inset 0 0 0 1px rgba(124,110,246,.25)}
.srch-body{flex:1;display:flex;flex-direction:column;gap:1px;min-width:0}
.srch-body .n{font-size:13px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.srch-body .p{font-size:11px;color:var(--faint);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.srch-act{flex:0 0 auto;width:30px;height:28px;display:grid;place-items:center;border:1px solid var(--border);
background:var(--panel);border-radius:8px;cursor:pointer;color:var(--muted);font-size:13px}
.srch-act:hover{color:var(--txt);border-color:var(--accent)}.srch-act svg{width:15px;height:15px}
.rslv-bar{display:flex;gap:8px;padding:10px 16px;border-bottom:1px solid var(--border-soft);flex-wrap:wrap}
.rslv-act{flex:0 0 auto;border:1px solid var(--border);background:var(--panel);border-radius:7px;padding:5px 11px;
font-size:11.5px;font-weight:600;color:var(--muted);cursor:pointer;font-family:var(--font)}
.rslv-act:hover{color:var(--txt);border-color:var(--accent)}
.rslv-act.on{color:#fff;border-color:transparent;background:linear-gradient(135deg,var(--accent-2),var(--accent-deep))}
.rslv-act svg{width:14px;height:14px;display:block}
.lk-who{flex:0 0 auto;display:flex;flex-direction:column;align-items:flex-end;gap:1px;font-size:11.5px;color:var(--muted);max-width:170px}
.lk-client{font-size:10px;color:var(--faint);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:170px}
.tm-hint{padding:10px 16px;font-size:11.5px;line-height:1.5;color:var(--faint);border-bottom:1px solid var(--border-soft)}
/* file-history timeline */
.flog-body{flex:1;overflow:auto;padding:6px 14px 14px}
.flog-row{display:flex;gap:12px;align-items:flex-start;padding:8px 6px}
.flog-row:hover{background:var(--hover);border-radius:8px}
.flog-rail{flex:0 0 14px;display:flex;flex-direction:column;align-items:center;align-self:stretch;position:relative}
.flog-dot{width:11px;height:11px;border-radius:50%;flex:0 0 auto;margin-top:4px;background:var(--accent-2);box-shadow:0 0 0 3px rgba(124,110,246,.15)}
.flog-dot.st-a{background:var(--add)}.flog-dot.st-d{background:var(--del)}.flog-dot.st-e{background:var(--edit)}
.flog-line{flex:1;width:2px;background:var(--border);margin-top:2px}
.flog-main{flex:1;min-width:0}
.flog-head{display:flex;align-items:center;gap:8px;font-size:12px;flex-wrap:wrap}
.flog-head .rev{font-weight:700;color:var(--txt);font-variant-numeric:tabular-nums}
.flog-cl{color:var(--accent-2);font-variant-numeric:tabular-nums}
.flog-user{color:var(--muted)}.flog-time{color:var(--faint);margin-left:auto;font-variant-numeric:tabular-nums}
.flog-desc{font-size:12px;color:var(--muted);margin-top:3px;line-height:1.5;white-space:pre-wrap;word-break:break-word}
/* blame + diff panes */
.picker.blame{width:900px;height:640px}
.blame-body,.diff-body{flex:1;overflow:auto;padding:8px 0;font-family:var(--mono);font-size:12px;line-height:1.5;background:var(--stage-bg)}
.blame-row{display:flex;gap:0;padding:0 12px;white-space:pre}
.blame-row:hover{background:var(--hover)}
.bl-cl{flex:0 0 64px;color:var(--accent-2);font-variant-numeric:tabular-nums}
.bl-user{flex:0 0 110px;color:var(--edit);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.bl-code{flex:1;color:var(--txt);white-space:pre}
.diff-line{padding:0 14px;white-space:pre;color:var(--muted)}
.diff-line.add{background:rgba(62,207,142,.12);color:var(--diff-add-c)}
.diff-line.del{background:rgba(242,99,126,.12);color:var(--diff-del-c)}
.diff-line.hunk{background:rgba(124,110,246,.1);color:var(--accent-2)}
/* AI settings block inside Settings modal */
.ai-set{margin-top:16px;padding-top:14px;border-top:1px solid var(--border-soft)}
.ai-set-h{display:flex;align-items:center;gap:8px;font-size:12.5px;font-weight:700;color:var(--txt);margin-bottom:6px}
.ai-set-h svg{width:16px;height:16px;color:var(--accent-2)}
.keyfield{display:flex;align-items:center;gap:6px;flex:1;max-width:230px}
.kf-in{flex:1;min-width:0;background:var(--panel);border:1px solid var(--border);border-radius:8px;padding:6px 9px;font-size:12px;color:var(--txt);outline:none;font-family:var(--font)}
.kf-in.mono{font-family:var(--mono);font-size:11.5px}
.kf-in:focus{border-color:var(--accent)}
.kf-eye{flex:0 0 auto;width:28px;height:28px;border:1px solid var(--border);background:var(--panel);border-radius:8px;cursor:pointer;font-size:13px;line-height:1}
.ai-hint{font-size:11px;color:var(--faint);line-height:1.5;margin-top:8px}
/* ---------------- People & Roles ---------------- */
.picker.wide{width:720px;max-width:94%;height:560px;max-height:82vh;display:flex;flex-direction:column}
.picker.wide.tall{height:660px}
.ph-sub{margin-left:8px;font-size:11.5px;color:var(--faint);font-variant-numeric:tabular-nums}
.picker.wide .ph-sub{margin-right:auto}
/* ---- Depot & Workspace file/size explorer ---- */
.exp-tabs{display:flex;gap:4px;margin-left:14px;background:var(--sunk);padding:3px;border-radius:9px}
.exp-tab{border:none;background:none;color:var(--muted);font-size:12px;font-weight:600;padding:5px 14px;border-radius:7px;cursor:pointer;font-family:var(--font)}
.exp-tab:hover{color:var(--txt)}
.exp-tab.on{background:var(--accent);color:#fff}
.exp-total{display:flex;align-items:center;padding:10px 18px;border-bottom:1px solid var(--border-soft)}
.exp-total .n{font-size:13px;font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.exp-total .sz{margin-left:auto;font-size:13px;font-weight:700;color:var(--accent-2);font-variant-numeric:tabular-nums;white-space:nowrap;padding-left:12px}
.exp-tree{flex:1;overflow-y:auto;padding:6px 8px 12px}
.exp-node{display:flex;flex-direction:column}
.exp-row{display:flex;align-items:center;gap:7px;padding:5px 10px;border-radius:8px;cursor:default;transition:background .1s}
.exp-row.dir{cursor:pointer}
.exp-row:hover{background:var(--hover)}
.exp-row:hover .exp-open{opacity:1}
.exp-caret{width:14px;flex:0 0 14px;display:grid;place-items:center;color:var(--faint)}
.chevi{display:grid;place-items:center;transition:transform .12s}
.chevi svg{width:13px;height:13px}
.chevi.open{transform:rotate(90deg)}
.exp-ic{width:17px;height:17px;flex:0 0 auto;display:grid;place-items:center;color:var(--accent-2)}
.exp-ic svg{width:16px;height:16px}
.exp-name{font-size:13px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:60px}
.exp-count{font-size:10.5px;color:var(--faint);white-space:nowrap;flex:0 0 auto}
.exp-bar{margin-left:auto;flex:0 0 110px;height:6px;border-radius:4px;background:var(--sunk);overflow:hidden}
.exp-bar > span{display:block;height:100%;background:linear-gradient(90deg,var(--accent),var(--accent-2));border-radius:4px}
.exp-size{flex:0 0 68px;text-align:right;font-size:12px;font-weight:600;color:var(--muted);font-variant-numeric:tabular-nums}
.exp-open{flex:0 0 auto;width:22px;height:22px;display:grid;place-items:center;color:var(--faint);cursor:pointer;opacity:0;border-radius:6px;transition:opacity .1s,color .1s}
.exp-open svg{width:14px;height:14px}
.exp-open:hover{color:var(--accent-2);background:var(--panel)}
.ur-body{flex:1;display:flex;min-height:0}
.ur-list{flex:0 0 300px;display:flex;flex-direction:column;border-right:1px solid var(--border-soft);min-height:0}
.ur-filter{display:flex;align-items:center;gap:8px;padding:10px 12px;border-bottom:1px solid var(--border-soft)}
.ur-filter svg{width:15px;height:15px;color:var(--faint);flex:0 0 auto}
.ur-filter input{flex:1;background:none;border:none;outline:none;color:var(--txt);font-size:12.5px;font-family:var(--font)}
.ur-scroll{flex:1;overflow-y:auto;padding:6px}
.ur-row{display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:10px;cursor:pointer;transition:background .12s}
.ur-row:hover{background:var(--hover)}
.ur-row.on{background:rgba(124,110,246,.13);box-shadow:inset 0 0 0 1px rgba(124,110,246,.28)}
.ur-meta{display:flex;flex-direction:column;gap:1px;min-width:0;flex:1}
.ur-name{font-size:13px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:flex;align-items:center;gap:6px}
.ur-you{font-size:9.5px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;color:var(--accent-2);background:rgba(124,110,246,.16);border-radius:6px;padding:1px 6px}
.ur-sub{font-size:11px;color:var(--faint);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ur-actd{width:8px;height:8px;border-radius:50%;flex:0 0 auto;background:var(--faint)}
.ur-actd.active{background:#3ecb8f;box-shadow:0 0 0 3px rgba(62,203,143,.18)}
.ur-actd.recent{background:#f4c04e}.ur-actd.idle{background:#4b4b58}
.ur-empty{padding:16px;font-size:12px;color:var(--faint);text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;white-space:pre-line}
.ur-empty svg{width:34px;height:34px;opacity:.35;flex:0 0 auto}
.viewer-msg svg{width:36px;height:36px;opacity:.4;flex:0 0 auto}
.ur-detail{flex:1;display:flex;flex-direction:column;min-width:0;overflow-y:auto}
.ur-dhead{display:flex;align-items:center;gap:14px;padding:18px 20px 14px;border-bottom:1px solid var(--border-soft)}
.ur-dinfo{min-width:0}
.ur-dname{font-size:16px;font-weight:700}
.ur-dsub{font-size:12px;color:var(--faint);margin-top:2px}
.ur-grouphd{display:flex;align-items:center;gap:8px;padding:14px 20px 8px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--faint)}
.ur-groups{display:flex;flex-wrap:wrap;gap:8px;padding:0 20px}
.ur-chip{display:flex;align-items:center;gap:7px;border:1px solid var(--border);background:var(--panel);color:var(--muted);
border-radius:9px;padding:7px 11px;font-size:12.5px;font-weight:500;font-family:var(--font);cursor:pointer;transition:.14s}
.ur-chip:hover:not(:disabled){border-color:var(--accent);color:var(--txt)}
.ur-chip:disabled{opacity:.6;cursor:default}
.ur-chip.on{border-color:rgba(124,110,246,.5);background:rgba(124,110,246,.13);color:var(--txt)}
.urc-box{width:15px;height:15px;border-radius:5px;border:1.5px solid var(--border);display:grid;place-items:center;flex:0 0 auto;background:var(--panel)}
.ur-chip.on .urc-box{background:var(--accent);border-color:var(--accent);color:#fff}
.urc-box svg{width:11px;height:11px}
.ur-detail .ai-hint{padding:12px 20px 20px}