/* ============================================================
   Pipeline Admin · hi-fi design system
   IBM Plex Sans (UI) + IBM Plex Mono (codes/values/logs)
   ============================================================ */

/* ---------- TOKENS ---------- */
:root{
  --bg: oklch(0.984 0.002 250);
  --surface: oklch(1 0 0);
  --surface-2: oklch(0.974 0.003 250);
  --surface-3: oklch(0.952 0.004 250);
  --border: oklch(0.912 0.005 250);
  --border-strong: oklch(0.855 0.006 250);
  --text: oklch(0.27 0.012 264);
  --text-2: oklch(0.44 0.012 264);
  --text-3: oklch(0.585 0.010 264);
  --text-faint: oklch(0.70 0.008 264);

  --accent-h: 256; --accent-c: 0.155;
  --accent: oklch(0.55 var(--accent-c) var(--accent-h));
  --accent-strong: oklch(0.47 var(--accent-c) var(--accent-h));
  --accent-fg: oklch(0.99 0 0);
  --accent-soft: oklch(0.55 var(--accent-c) var(--accent-h) / 0.10);
  --accent-line: oklch(0.55 var(--accent-c) var(--accent-h) / 0.35);

  --ok: oklch(0.58 0.13 155);   --ok-soft: oklch(0.58 0.13 155 / 0.12);
  --warn: oklch(0.66 0.13 67);  --warn-soft: oklch(0.66 0.13 67 / 0.14);
  --err: oklch(0.56 0.20 27);   --err-soft: oklch(0.56 0.20 27 / 0.11);
  --ai: oklch(0.55 0.19 295);   --ai-soft: oklch(0.55 0.19 295 / 0.11); --ai-line: oklch(0.55 0.19 295 / 0.38);

  --shadow-sm: 0 1px 2px oklch(0.2 0.02 264/0.06), 0 1px 1px oklch(0.2 0.02 264/0.04);
  --shadow: 0 4px 14px -3px oklch(0.2 0.02 264/0.10), 0 2px 5px -2px oklch(0.2 0.02 264/0.06);
  --shadow-lg: 0 22px 50px -12px oklch(0.2 0.02 264/0.22), 0 6px 16px -8px oklch(0.2 0.02 264/0.12);

  --r-sm: 7px; --r: 11px; --r-lg: 16px; --r-xl: 22px;
  --pad: 18px;
  --side-w: 244px;
  --fs-base: 14px;
  --ff: 'IBM Plex Sans', system-ui, sans-serif;
  --mono: 'IBM Plex Mono', ui-monospace, monospace;
}
[data-theme="dark"]{
  --bg: oklch(0.168 0.008 264);
  --surface: oklch(0.205 0.010 264);
  --surface-2: oklch(0.237 0.011 264);
  --surface-3: oklch(0.275 0.012 264);
  --border: oklch(0.305 0.012 264);
  --border-strong: oklch(0.38 0.014 264);
  --text: oklch(0.945 0.006 250);
  --text-2: oklch(0.745 0.011 260);
  --text-3: oklch(0.625 0.012 260);
  --text-faint: oklch(0.50 0.012 260);

  --accent: oklch(0.70 0.14 var(--accent-h));
  --accent-strong: oklch(0.78 0.13 var(--accent-h));
  --accent-fg: oklch(0.16 0.02 264);
  --accent-soft: oklch(0.70 0.14 var(--accent-h) / 0.16);
  --accent-line: oklch(0.70 0.14 var(--accent-h) / 0.42);

  --ok: oklch(0.73 0.14 155);   --ok-soft: oklch(0.73 0.14 155 / 0.16);
  --warn: oklch(0.80 0.13 75);  --warn-soft: oklch(0.80 0.13 75 / 0.18);
  --err: oklch(0.68 0.18 27);   --err-soft: oklch(0.68 0.18 27 / 0.18);
  --ai: oklch(0.74 0.15 295);   --ai-soft: oklch(0.74 0.15 295 / 0.18); --ai-line: oklch(0.74 0.15 295 / 0.45);

  --shadow-sm: 0 1px 2px oklch(0 0 0/0.30);
  --shadow: 0 6px 18px -4px oklch(0 0 0/0.45), 0 2px 6px -2px oklch(0 0 0/0.35);
  --shadow-lg: 0 26px 56px -14px oklch(0 0 0/0.62);
}
/* accent presets */
[data-accent="indigo"]{ --accent-h:276; --accent-c:0.16; }
[data-accent="teal"]{ --accent-h:192; --accent-c:0.12; }
[data-accent="amber"]{ --accent-h:62; --accent-c:0.14; }

*{box-sizing:border-box}
html,body{margin:0;height:100%}
body{
  background:var(--bg); color:var(--text); font-family:var(--ff);
  font-size:var(--fs-base); line-height:1.5; -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility; overflow:hidden; word-break:keep-all;
}
.mono{font-family:var(--mono); font-feature-settings:"tnum" 1}
.tnum{font-variant-numeric:tabular-nums}
::selection{background:var(--accent-soft)}
button{font-family:inherit}
:focus-visible{outline:2px solid var(--accent); outline-offset:2px}

/* density */
[data-density="compact"]{ --pad:12px; --fs-base:13px; }

/* ---------- APP SHELL ---------- */
.app{display:grid; grid-template-columns:var(--side-w) 1fr; height:100vh; transition:grid-template-columns .18s ease}
body.rail .app{grid-template-columns:66px 1fr}

/* sidebar */
.side{background:var(--surface); border-right:1px solid var(--border); display:flex; flex-direction:column; min-width:0}
.brand{display:flex; align-items:center; gap:11px; padding:18px 18px 16px; white-space:nowrap; text-decoration:none; color:inherit; cursor:pointer}
.brand:hover .nm{color:var(--accent-strong)}
.brand .logo{width:30px; height:30px; flex:none; border-radius:9px; background:linear-gradient(140deg, var(--accent), var(--accent-strong)); display:grid; place-items:center; color:var(--accent-fg); font-weight:600; box-shadow:var(--shadow-sm)}
.brand .nm{font-weight:600; font-size:14.5px; letter-spacing:-.01em}
.brand .nm small{display:block; font-weight:400; font-size:11px; color:var(--text-3); letter-spacing:0}
body.rail .brand .nm{display:none}
.nav{padding:6px 10px; display:flex; flex-direction:column; gap:1px; overflow:auto; flex:1}
.nav .grp{font-size:10.5px; font-weight:600; letter-spacing:.06em; text-transform:uppercase; color:var(--text-faint); padding:14px 10px 5px}
body.rail .nav .grp{height:10px; overflow:hidden; color:transparent}
.nlink{display:flex; align-items:center; gap:11px; padding:8px 10px; border-radius:var(--r-sm); color:var(--text-2); cursor:pointer; font-size:13.5px; font-weight:500; white-space:nowrap; border:1px solid transparent; transition:background .12s, color .12s; text-decoration:none}
.nlink .ic{width:18px; height:18px; flex:none; display:grid; place-items:center; color:var(--text-3)}
.nlink:hover{background:var(--surface-2); color:var(--text)}
.nlink:hover .ic{color:var(--text-2)}
.nlink.active{background:var(--accent-soft); color:var(--accent-strong); font-weight:600}
.nlink.active .ic{color:var(--accent)}
.nlink .badge{margin-left:auto; font-size:10.5px; font-weight:600; padding:1px 7px; border-radius:20px; background:var(--surface-3); color:var(--text-2); font-family:var(--mono)}
.nlink .badge.ai{background:var(--ai-soft); color:var(--ai)}
body.rail .nlink .txt, body.rail .nlink .badge{display:none}
.side-foot{margin-top:auto; padding:12px 16px; border-top:1px solid var(--border); display:flex; align-items:center; gap:9px; font-size:11.5px; color:var(--text-3); white-space:nowrap}
.pulse{width:8px;height:8px;border-radius:50%;background:var(--ok);flex:none; box-shadow:0 0 0 0 var(--ok-soft); animation:pulse 2.4s infinite}
@keyframes pulse{0%{box-shadow:0 0 0 0 var(--ok-soft)}70%{box-shadow:0 0 0 6px transparent}100%{box-shadow:0 0 0 0 transparent}}
body.rail .side-foot .txt{display:none}

/* main */
.main{display:flex; flex-direction:column; min-width:0; overflow:hidden}
.topbar{display:flex; align-items:center; gap:14px; padding:13px 22px; border-bottom:1px solid var(--border); background:color-mix(in oklch, var(--surface) 70%, transparent); backdrop-filter:blur(8px)}
.icon-btn{width:32px; height:32px; flex:none; border-radius:var(--r-sm); border:1px solid var(--border); background:var(--surface); color:var(--text-2); cursor:pointer; display:grid; place-items:center; transition:.12s}
.icon-btn:hover{background:var(--surface-2); color:var(--text); border-color:var(--border-strong)}
.crumb{display:flex; align-items:center; gap:8px; font-size:13px; color:var(--text-3); white-space:nowrap; min-width:0; overflow:hidden}
.crumb b{white-space:nowrap; overflow:hidden; text-overflow:ellipsis}
.crumb b{color:var(--text); font-weight:600}
.crumb .sep{color:var(--text-faint)}
.searchbtn{display:flex; align-items:center; gap:8px; padding:6px 11px; border-radius:var(--r-sm); border:1px solid var(--border); background:var(--surface-2); color:var(--text-3); cursor:pointer; font-size:12.5px; transition:.12s}
.searchbtn:hover{border-color:var(--border-strong); color:var(--text-2)}
.searchbtn kbd{font-family:var(--mono); font-size:11px; background:var(--surface); border:1px solid var(--border); border-radius:5px; padding:0 5px; color:var(--text-3)}

/* review subtoolbar */
.subbar{display:flex; align-items:center; gap:14px; padding:11px 22px; border-bottom:1px solid var(--border); background:var(--surface); flex-wrap:wrap}
.subbar .lbl{font-size:11.5px; color:var(--text-3); font-weight:500}
.seg{display:inline-flex; background:var(--surface-3); border-radius:9px; padding:3px; gap:2px}
.seg button{border:0; background:transparent; color:var(--text-2); font-size:12.5px; font-weight:500; padding:6px 13px; border-radius:7px; cursor:pointer; display:flex; align-items:center; gap:7px; transition:.12s; white-space:nowrap}
.seg button .ic{width:15px;height:15px;display:grid;place-items:center}
.seg button:hover{color:var(--text)}
.seg button.on{background:var(--surface); color:var(--text); box-shadow:var(--shadow-sm); font-weight:600}
.swatches{display:flex; gap:6px}
.sw{width:20px;height:20px;border-radius:6px;cursor:pointer;border:2px solid transparent; position:relative}
.sw.on{border-color:var(--text)}
.sw[data-a="blue"]{background:oklch(0.55 0.155 256)} .sw[data-a="indigo"]{background:oklch(0.55 0.16 276)}
.sw[data-a="teal"]{background:oklch(0.55 0.12 192)} .sw[data-a="amber"]{background:oklch(0.62 0.14 62)}

/* content scroller */
.content{flex:1; overflow:auto; padding:22px}
.scrollwrap{height:100%; overflow:auto}

/* ---------- PRIMITIVES ---------- */
.card{background:var(--surface); border:1px solid var(--border); border-radius:var(--r-lg); box-shadow:var(--shadow-sm)}
.btn{display:inline-flex; align-items:center; gap:8px; font-size:13px; font-weight:600; padding:8px 14px; border-radius:var(--r-sm); border:1px solid var(--border-strong); background:var(--surface); color:var(--text); cursor:pointer; transition:.12s; white-space:nowrap}
.btn:hover{background:var(--surface-2)}
.btn.pri{background:var(--accent); border-color:var(--accent); color:var(--accent-fg)} .btn.pri:hover{background:var(--accent-strong)}
.btn.ai{background:var(--ai); border-color:var(--ai); color:oklch(0.99 0 0)} .btn.ai:hover{filter:brightness(1.06)}
.btn.danger{color:var(--err); border-color:color-mix(in oklch,var(--err) 40%, var(--border))} .btn.danger:hover{background:var(--err-soft)}
.btn.ghost{border-color:transparent; background:transparent; color:var(--text-2)} .btn.ghost:hover{background:var(--surface-2); color:var(--text)}
.btn.sm{font-size:12px; padding:5px 10px}
.btn kbd{font-family:var(--mono); font-size:10.5px; padding:0 5px; border-radius:4px; background:color-mix(in oklch, currentColor 14%, transparent); border:1px solid color-mix(in oklch, currentColor 22%, transparent)}
.btn.pri kbd, .btn.ai kbd{background:oklch(1 0 0/0.18); border-color:oklch(1 0 0/0.3)}

.tag{display:inline-flex; align-items:center; gap:5px; font-size:11px; font-weight:600; padding:2px 9px; border-radius:20px; border:1px solid var(--border); color:var(--text-2); background:var(--surface-2)}
.tag.ai{color:var(--ai); border-color:var(--ai-line); background:var(--ai-soft)}
.tag.ok{color:var(--ok); border-color:color-mix(in oklch,var(--ok) 35%,var(--border)); background:var(--ok-soft)}
.tag.warn{color:var(--warn); border-color:color-mix(in oklch,var(--warn) 40%,var(--border)); background:var(--warn-soft)}
.tag.err{color:var(--err); border-color:color-mix(in oklch,var(--err) 40%,var(--border)); background:var(--err-soft)}

/* confidence pill */
.conf{display:inline-flex; align-items:center; gap:5px; font-size:11px; font-weight:600; font-family:var(--mono); padding:2px 8px; border-radius:6px; border:1px solid}
.conf .bars{display:inline-flex; gap:1.5px; align-items:flex-end; height:11px}
.conf .bars i{width:2.5px; background:currentColor; border-radius:1px; opacity:.35}
.conf.hi{color:var(--ok); border-color:color-mix(in oklch,var(--ok) 30%,transparent); background:var(--ok-soft)}
.conf.hi .bars i{opacity:1}
.conf.mid{color:var(--warn); border-color:color-mix(in oklch,var(--warn) 32%,transparent); background:var(--warn-soft)}
.conf.mid .bars i:nth-child(-n+2){opacity:1}
.conf.lo{color:var(--err); border-color:color-mix(in oklch,var(--err) 30%,transparent); background:var(--err-soft)}
.conf.lo .bars i:first-child{opacity:1}
.conf.nl{color:var(--text-faint); border-color:var(--border); background:var(--surface-2)}

h1,h2,h3{margin:0; letter-spacing:-.015em}
.muted{color:var(--text-3)} .faint{color:var(--text-faint)}

/* ---------- STATES: loading / empty / error ---------- */
.statelayer{display:none; flex:1; min-height:0}
body[data-state="loading"] .review-wrap,
body[data-state="empty"] .review-wrap,
body[data-state="error"] .review-wrap{display:none}
body[data-state="loading"] #state-loading{display:flex}
body[data-state="empty"] #state-empty{display:flex}
body[data-state="error"] #state-error{display:flex}
body:not([data-state="data"]):not([data-state]) .rhead{} /* default keeps */
body[data-state="loading"] .rhead, body[data-state="empty"] .rhead, body[data-state="error"] .rhead{display:none}

@keyframes shimmer{100%{background-position:-200% 0}}
.skel{border-radius:8px; background:linear-gradient(90deg, var(--surface-2) 0%, var(--surface-3) 40%, var(--surface-2) 80%); background-size:200% 100%; animation:shimmer 1.3s linear infinite}

/* 지연 로드 자리표시(무거운 집계) — 인디터미닛 진행바 + 스켈레톤 */
.loadbox{display:flex; flex-direction:column; gap:14px; padding:6px 2px}
.loadbox .lrow{display:flex; align-items:center; gap:8px; color:var(--text-3); font-size:13px; font-weight:500}
@keyframes indet{0%{left:-35%; width:35%} 60%{width:55%} 100%{left:100%; width:35%}}
.ibar{position:relative; height:3px; border-radius:3px; background:var(--surface-3); overflow:hidden}
.ibar i{position:absolute; top:0; height:100%; background:var(--accent); border-radius:3px; animation:indet 1.05s ease-in-out infinite}
.skelgrid{display:grid; grid-template-columns:repeat(4,1fr); gap:12px}
@media(max-width:1080px){ .skelgrid{grid-template-columns:repeat(2,1fr)} }
.skel-row{display:flex; gap:18px; height:100%}
.skel-card{background:var(--surface); border:1px solid var(--border); border-radius:var(--r-lg); padding:18px; display:flex; flex-direction:column; gap:12px}

.state-empty, .state-error{flex:1; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:14px; text-align:center; padding:40px}
.state-ic{width:64px; height:64px; border-radius:18px; display:grid; place-items:center; font-size:28px}
.state-ic.ok{background:var(--ok-soft); color:var(--ok)}
.state-ic.err{background:var(--err-soft); color:var(--err)}
.state-empty h3, .state-error h3{font-size:18px; font-weight:600}
.state-empty p, .state-error p{font-size:13.5px; color:var(--text-3); max-width:380px; line-height:1.6; margin:0}
.state-error .code{font-family:var(--mono); font-size:11.5px; color:var(--text-faint); background:var(--surface-2); border:1px solid var(--border); border-radius:8px; padding:8px 12px; margin-top:4px}

/* state preview control */
.statesel{display:flex; align-items:center; gap:6px}
.statesel select{font-family:var(--ff); font-size:12px; padding:5px 8px; border-radius:var(--r-sm); border:1px solid var(--border); background:var(--surface-2); color:var(--text-2); cursor:pointer}

/* ---------- MOBILE / RESPONSIVE ---------- */
.scrim{display:none; position:fixed; inset:0; background:oklch(0.2 0.02 264/0.42); backdrop-filter:blur(2px); z-index:39}
@media (max-width:860px){
  .app{grid-template-columns:1fr !important}
  .side{position:fixed; left:0; top:0; bottom:0; width:min(80vw,280px); z-index:40; transform:translateX(-100%); transition:transform .2s ease; box-shadow:var(--shadow-lg)}
  body.nav-open .side{transform:translateX(0)}
  body.nav-open .scrim{display:block}
  body.rail .side .nm, body.rail .nlink .txt, body.rail .nlink .badge, body.rail .side-foot .txt{display:revert}
  .topbar{padding:11px 14px}
  .subbar{padding:10px 14px; gap:10px}
  .subbar .lbl{display:none}
  .subbar .swatches{display:none}
  .content{padding:14px}
  .content.review{padding:14px}
}
@media (max-width:560px){
  .seg button{padding:6px 10px}
  .seg button .ic{display:none}
  .rhead .progress{display:none}
  .searchbtn span:not(.mono){display:none}
}

/* ===== 커스텀 확인 다이얼로그 (네이티브 confirm 대체) ===== */
.cdlg-wrap{position:fixed; inset:0; z-index:90; display:none; align-items:center; justify-content:center;
  background:oklch(0.2 0.02 264/0.42); backdrop-filter:blur(4px); padding:24px}
.cdlg-wrap.open{display:flex; animation:cdlgFade .13s ease}
.cdlg{width:min(440px,94vw); padding:22px 22px 16px; box-shadow:var(--shadow-lg);
  display:grid; grid-template-columns:auto 1fr; gap:2px 16px; align-items:start; animation:cdlgPop .15s cubic-bezier(.2,.9,.3,1.2)}
.cdlg-ic{grid-row:1 / 3; width:38px; height:38px; border-radius:50%; display:grid; place-items:center;
  font-size:19px; font-weight:700; background:var(--accent-soft); color:var(--accent); border:1px solid var(--accent-line)}
.cdlg-tt{font-size:15px; font-weight:700; color:var(--text); margin-bottom:5px}
.cdlg-msg{font-size:13px; line-height:1.55; color:var(--text-2); white-space:pre-line}
.cdlg-act{grid-column:1 / 3; display:flex; justify-content:flex-end; gap:9px; margin-top:18px}
.cdlg-wrap.danger .cdlg-ic{background:var(--err-soft); color:var(--err);
  border-color:color-mix(in oklch, var(--err) 40%, var(--border))}
@keyframes cdlgFade{from{opacity:0} to{opacity:1}}
@keyframes cdlgPop{from{opacity:0; transform:translateY(-4px) scale(.985)} to{opacity:1; transform:none}}

/* ===== 로그인 페이지 ===== */
.loginbody{margin:0; min-height:100vh; color:var(--text); font-family:'IBM Plex Sans',system-ui,sans-serif;
  background:radial-gradient(1100px 560px at 50% -12%, var(--accent-soft), transparent 62%), var(--bg)}
.loginwrap{min-height:100vh; display:flex; align-items:center; justify-content:center; padding:24px}
.loginTheme{position:fixed; top:18px; right:18px}
.logincard{width:min(396px,94vw); background:var(--surface); border:1px solid var(--border);
  border-radius:var(--r-xl); box-shadow:var(--shadow-lg); padding:36px 32px}
.loginbrand{display:flex; align-items:center; gap:13px; margin-bottom:24px}
.loginbrand .logo{width:42px; height:42px; display:grid; place-items:center; border-radius:12px;
  background:var(--accent); color:var(--accent-fg); font-size:21px; box-shadow:var(--shadow-sm)}
.loginbrand .nm{display:flex; flex-direction:column; font-weight:700; font-size:18px; letter-spacing:-.012em; line-height:1.22}
.loginbrand .nm small{font-weight:500; font-size:11.5px; color:var(--text-3); letter-spacing:0; margin-top:2px}
.loginfield{display:flex; flex-direction:column; gap:6px; margin-bottom:15px}
.loginfield label{font-size:12.5px; color:var(--text-2); font-weight:500}
.loginfield input{height:42px; padding:0 13px; border:1px solid var(--border-strong); border-radius:var(--r-sm);
  background:var(--surface-2); color:var(--text); font-size:14px; font-family:inherit; transition:.12s}
.loginfield input:focus{outline:none; border-color:var(--accent); background:var(--surface); box-shadow:0 0 0 3px var(--accent-soft)}
.btn.block{width:100%; justify-content:center; height:44px; font-size:14px; margin-top:6px}
.loginerr{background:var(--err-soft); color:var(--err); border:1px solid color-mix(in oklch,var(--err) 30%, transparent);
  border-radius:var(--r-sm); padding:10px 12px; font-size:12.5px; margin-bottom:16px}
.loginfoot{text-align:center; color:var(--text-faint); font-size:11.5px; margin-top:18px}
