/* Palette, rail, and panel tokens shared with the workspace app live in
 * css/tokens.css, linked by admin.html ahead of this file. Only admin-specific
 * tokens belong here.
 *
 * The chrome below mirrors css/dashboard.css on purpose: the admin console and
 * the workspace console are one product, so they draw the same dark rail, the
 * same sticky page header, and the same card. When one moves, move both. */
:root {
  --ok: #13795b;
  --ok-soft: #e4f6ef;
  --bad: #b42318;
  --bad-soft: #fff0ed;
  --warn: #9a5b00;
  --warn-soft: #fff5dc;
  --switch-bg: #10201f;
  --shadow: 0 18px 48px rgba(31, 41, 51, .1);
  /* The page header is sticky, so an anchor jump has to stop below it. */
  --topbar-scroll-offset: 92px;
}

* { box-sizing: border-box; }
[hidden] { display: none !important; }

body {
  margin: 0;
  min-height: 100vh;
  color: var(--text);
  background: var(--bg);
  /* docs/plans/ROADMAP.md §2.1 U-2 -- kept identical to css/base.css and
   * verticals/shared.css so the three surfaces don't drift apart again. See
   * base.css for the full rationale (Inter has no Hangul glyphs). */
  font-family: Pretendard, -apple-system, BlinkMacSystemFont, "Malgun Gothic", "Apple SD Gothic Neo", system-ui, sans-serif;
  font-size: var(--fs-4);
  line-height: var(--lh-base);
}

a { color: inherit; text-decoration: none; }

/* ---------- shell: dark rail (>=761px) / dark top bar (<761px) ---------- */
.topbar {
  position: sticky;
  top: 0;
  z-index: 10;
  width: 100%;
  display: grid;
  grid-template-columns: minmax(0, 1fr) max-content;
  align-items: center;
  gap: 10px 12px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--rail-line);
  background: var(--rail-bg);
}

.brand,
.actions,
.admin-nav,
.chips,
.checks {
  display: flex;
  align-items: center;
}

.brand {
  width: auto;
  max-width: 100%;
  gap: 10px;
  justify-self: start;
  padding: 4px 8px 4px 3px;
  border-radius: var(--rail-radius);
  color: #fff;
}
.brand:hover {
  background: rgba(255, 255, 255, .06);
}
.brand img { width: 32px; height: 32px; border-radius: 9px; background: #fff; box-shadow: 0 8px 20px rgba(10, 189, 163, .22); }
.brand span {
  min-width: 0;
}
.brand b,
.brand small {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.brand b { font-size: var(--fs-5); letter-spacing: .04em; }
.brand small { color: var(--rail-text-dim); font-size: var(--fs-1); letter-spacing: 0; }

.admin-nav {
  min-width: 0;
  width: 100%;
  gap: 4px;
  flex-wrap: nowrap;
  overflow-x: auto;
  scrollbar-width: none;
}

.admin-nav::-webkit-scrollbar { display: none; }

.nav-group-label {
  display: none;
  margin: 14px 0 4px;
  padding: 0 11px;
  color: var(--rail-text-dim);
  font-size: var(--fs-1);
  font-weight: 800;
  letter-spacing: .14em;
  text-transform: uppercase;
}

.admin-nav a,
.nav-group > summary,
.actions a,
button {
  border: 1px solid transparent;
  padding: 8px 10px;
  color: var(--muted);
  background: transparent;
  cursor: pointer;
  white-space: nowrap;
}

.admin-nav a,
.nav-group > summary {
  flex: 0 0 auto;
  min-width: max-content;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: var(--rail-text);
  border-radius: var(--rail-radius);
  padding: 9px 11px;
  overflow: visible;
  text-align: left;
  font-size: var(--fs-4);
  font-weight: 650;
  line-height: 1.25;
}

/* 워크스페이스 레일과 같은 아이콘 규칙이다(css/dashboard.css의 .nav-icon과 같은
 * 값). 예전에는 여기만 유니코드 글리프(◱ ▶ ⚙ …)였고, 그 대가로 두 가지를 감수하고
 * 있었다: 글리프는 블록마다 잉크 양과 기준선이 달라 왼쪽 열이 들쭉날쭉했고, 잉크가
 * 무거우니 라벨보다 한 단계 흐리게 눌러 둘 수밖에 없어서 hover·선택 상태가 라벨만
 * 밝혔다. 이제 admin.html의 마크도 24단위 아웃라인이라 굵기가 한 벌로 붙고, 색은
 * 줄에서 물려받아 세 상태를 라벨과 함께 지난다.
 *
 * 크기는 --rail-icon -- 15px/650 라벨에 맞춰 tokens.css에서 한 번 정한 값이고, 두
 * 콘솔이 같은 값을 읽는다. */
.nav-icon {
  width: var(--rail-icon);
  height: var(--rail-icon);
  flex: 0 0 auto;
  color: inherit;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.nav-group {
  position: relative;
  flex: 0 0 auto;
}

.nav-group > summary {
  list-style: none;
  user-select: none;
}

.nav-group > summary::-webkit-details-marker { display: none; }

.nav-group > summary::after {
  content: "";
  width: 6px;
  height: 6px;
  margin-top: -3px;
  border-right: 1.7px solid currentColor;
  border-bottom: 1.7px solid currentColor;
  transform: rotate(45deg);
}

.nav-group[open] > summary::after {
  margin-top: 3px;
  transform: rotate(-135deg);
}

.nav-submenu {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  z-index: 20;
  min-width: 168px;
  display: grid;
  gap: 2px;
  padding: 6px;
  border: 1px solid var(--rail-line);
  border-radius: var(--rail-radius);
  background: #1d2a28;
  box-shadow: var(--shadow);
}

.nav-submenu a {
  width: 100%;
  justify-content: flex-start;
  border-radius: 7px;
  padding: 8px 10px;
  font-size: var(--fs-3);
  text-align: left;
}

.actions a,
button {
  border-radius: var(--control-radius);
}

.admin-nav a:hover,
.nav-group > summary:hover {
  color: #fff;
  border-color: transparent;
  background: rgba(255, 255, 255, .06);
}

button:hover,
.actions a:hover {
  color: var(--text);
  border-color: var(--line);
  background: var(--surface-muted);
}

.admin-nav a.active,
.admin-nav a[aria-current="page"],
.nav-group.active > summary,
.nav-group[open] > summary {
  color: #fff;
  border-color: transparent;
  background: rgba(10, 189, 163, .22);
  font-weight: 800;
}

.admin-nav a.active .nav-icon,
.nav-group.active > summary .nav-icon { color: var(--brand); }

.actions {
  justify-self: end;
  min-width: 0;
  gap: 8px;
}

/* Cross-console link + account row: the exact same components as the
 * workspace rail (rail-admin-link / account-menu-*), so switching consoles
 * never changes how the chrome reads. */
.rail-admin-link {
  display: inline-flex;
  align-items: center;
  gap: 11px;
  min-height: 42px;
  padding: 0 11px;
  color: var(--rail-text);
  border: 1px solid var(--rail-line);
  border-radius: var(--rail-radius);
  background: rgba(255, 255, 255, .04);
  font-size: var(--fs-4);
  font-weight: 700;
  text-decoration: none;
}
.rail-admin-link:hover { color: #fff; background: rgba(255, 255, 255, .09); }
.rail-admin-link .nav-icon { color: var(--brand); }

.account-menu-wrap {
  position: relative;
  min-width: 0;
}

.account-menu-toggle {
  width: 100%;
  min-height: 38px;
  padding: 4px 10px 4px 4px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  border: 1px solid transparent;
  border-radius: 999px;
  color: #e4edeb;
  background: none;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.account-menu-toggle:hover,
.account-menu-toggle[aria-expanded="true"] {
  border-color: transparent;
  background: rgba(255, 255, 255, .06);
}

.account-menu-toggle[aria-expanded="true"] .mode-chevron { transform: rotate(180deg); }

.mode-chevron {
  margin-left: auto;
  color: var(--rail-text-dim);
  font-style: normal;
  line-height: 1;
  transition: transform .16s ease;
}

.account-avatar {
  width: 28px;
  height: 28px;
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  color: #fff;
  background: var(--brand-dark);
  font-size: var(--fs-2);
  font-weight: 800;
  line-height: 1;
  text-transform: uppercase;
}

.account-menu-copy {
  min-width: 0;
  display: grid;
  gap: 1px;
}

.account-menu-copy b,
.account-menu-copy small {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.account-menu-copy b { font-size: var(--fs-2); font-weight: 700; }
.account-menu-copy small { color: var(--rail-text-dim); font-size: var(--fs-1); }

.account-menu {
  position: absolute;
  z-index: 35;
  top: calc(100% + 8px);
  right: 0;
  width: 248px;
  padding: 7px;
  border: 1px solid var(--line);
  border-radius: var(--row-radius);
  background: #fff;
  box-shadow: var(--shadow);
}

.account-menu-head {
  padding: 8px 10px 10px;
  display: grid;
  gap: 3px;
  border-bottom: 1px solid var(--line);
  margin-bottom: 6px;
}

.account-menu-head b,
.account-menu-head small {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.account-menu-head b { color: var(--text); font-size: var(--fs-3); }
.account-menu-head small { color: var(--muted); font-size: var(--fs-1); }
.account-menu-head .badge {
  justify-self: start;
  margin-top: 3px;
  padding: 2px 8px;
  border-radius: 999px;
  color: var(--brand-dark);
  background: var(--brand-soft);
  font-size: var(--fs-1);
  font-weight: 800;
}

.account-menu-item {
  width: 100%;
  min-height: 40px;
  padding: 10px;
  display: flex;
  align-items: center;
  border: 0;
  border-radius: var(--control-radius);
  color: var(--text);
  background: transparent;
  font: inherit;
  font-weight: 700;
  text-align: left;
  text-decoration: none;
  cursor: pointer;
}

.account-menu-item:hover,
.account-menu-item:focus-visible { background: var(--brand-soft); }

.account-menu-actions {
  margin-top: 6px;
  padding-top: 6px;
  border-top: 1px solid var(--line);
}

#admin-logout { color: var(--muted); }

@media (min-width: 761px) {
  .nav-group-label { display: block; }

  .admin-nav {
    display: grid;
    /* Pack items to the top — never let leftover rail height stretch the
     * rows apart (same guard as the workspace rail). */
    align-content: start;
    gap: 4px;
    overflow-x: visible;
  }

  .admin-nav a,
  .nav-group > summary,
  .nav-group { width: 100%; }

  .actions {
    flex-direction: column;
    align-items: stretch;
    gap: 9px;
    margin-top: auto;
    padding-top: 14px;
    border-top: 1px solid var(--rail-line);
  }

  /* The account row sits at the foot of the rail, so its flyout opens upward
   * from the rail's left edge — same anchoring as the workspace console. */
  .account-menu {
    top: auto;
    bottom: calc(100% + 8px);
    right: auto;
    left: 0;
  }

  /* In the rail the API group is an accordion, not a dropdown: an absolutely
   * positioned menu inside a scrollable 244px column can only clip or overlap
   * the items under it. */
  .nav-submenu {
    position: static;
    min-width: 0;
    margin-top: 3px;
    padding: 4px;
    border-color: transparent;
    background: rgba(255, 255, 255, .04);
    box-shadow: none;
  }

  /* Column flex, not grid: `.actions` uses margin-top:auto to sit at the foot of
   * the rail, which a grid with align-content:start would ignore. */
  .topbar {
    position: fixed;
    inset: 0 auto 0 0;
    z-index: 20;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 18px;
    width: var(--rail);
    padding: 22px 14px 18px;
    border-right: 1px solid var(--rail-line);
    border-bottom: 0;
    overflow-y: auto;
  }
}

button { font: inherit; }
button:disabled {
  cursor: not-allowed;
  opacity: .48;
}

main {
  width: auto;
  margin: 0;
  padding: 0 clamp(20px, 3vw, 44px) 48px;
}

.heading {
  display: flex;
  align-items: end;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 18px;
  padding-top: 20px;
}

@media (min-width: 761px) {
  main {
    margin-left: var(--rail);
  }

  /* Same sticky page header as the workspace console. Opaque, not translucent:
   * panel kickers scrolling underneath show through a blur and read as a second
   * heading. */
  .heading {
    position: sticky;
    top: 0;
    z-index: 6;
    margin: 0 calc(clamp(20px, 3vw, 44px) * -1) 18px;
    /* 띠는 전폭 그대로 두고 제목만 #app 컬럼 좌측선에 앉힌다 -- 워크스페이스 콘솔의
     * #workspace > .title(css/dashboard.css)과 같은 계산이다. */
    padding: 20px calc(max(0px, (100% - var(--content-max)) / 2) + clamp(20px, 3vw, 44px)) 18px;
    border-bottom: 1px solid var(--line);
    background: var(--bg);
  }

  /* 상한만 있고 정렬이 없어 초광폭에서 본문이 왼쪽에 붙어 있었다. */
  #app { max-width: var(--content-max); margin-inline: auto; }
}

.heading small,
.panel-head small {
  color: var(--muted);
  font-size: var(--fs-2);
  font-weight: 600;
  letter-spacing: 0;
}

h1, h2, h3, p { margin: 0; }
h1 { font-size: var(--fs-6); line-height: 1.16; letter-spacing: -.02em; }

/* 페이지 제목 위의 머리말 -- 워크스페이스의 #view-section(css/workspace.css)과 같은
 * 것이고, 이제 같은 모양으로 선다. 예전에는 9px 대문자 영문(`PLATFORM ADMIN`)이었고
 * 두 가지가 함께 어긋나 있었다: 한국어 전용 콘솔에 남은 영문 문구였고(docs/README.md
 * UI Copy Conventions), 화면이 바뀌어도 늘 같은 말이라 지금 어디에 있는지를 말하지
 * 못했다. 이제 admin.js가 왼쪽 메뉴의 그룹 이름을 여기에 넣는다 -- 워크스페이스가
 * 제목 위에 상위 섹션 이름을 넣는 것과 같은 규칙이며, 제목과 같은 말이 되는 자리는
 * 비운다. */
#section-eyebrow {
  display: block;
  /* h1은 margin: 0이라(위의 초기화) 간격이 여기서만 나온다. */
  margin: 0 0 3px;
  color: var(--brand-dark);
  font-size: var(--fs-2);
  font-weight: 800;
  line-height: 1.3;
}
#section-eyebrow:empty { display: none; }

/* 25 → 18 → 15의 세 단계. 패널 제목이 23px이던 동안 페이지 제목(25px)과 두 단계가
 * 아니라 반 단계 차이였고, 그 밑의 h3(17px)까지 붙어서 셋이 거의 한 층으로 읽혔다.
 * 18px은 워크스페이스 .panel-head h2와 같은 값이다(css/dashboard.css). */
h2 { margin-top: 4px; font-size: var(--fs-6); line-height: 1.2; }
.panel-head h2 { margin: 0; font-size: var(--fs-5); line-height: 1.25; letter-spacing: -.02em; }
h3 { margin-bottom: 10px; font-size: var(--fs-4); letter-spacing: -.01em; }
.heading p { color: var(--text); font-size: var(--fs-3); }

#app {
  display: grid;
  gap: 14px;
}

#app > .panel {
  max-height: none;
  overflow: visible;
  scroll-margin-top: var(--topbar-scroll-offset);
}

.panel,
.state {
  min-width: 0;
  max-width: 100%;
  border: 1px solid var(--line);
  border-radius: var(--panel-radius);
  background: var(--surface);
  box-shadow: var(--panel-shadow);
}

.panel { padding: 20px 22px; }
.state { padding: 28px; text-align: center; }
.state h2 { margin-bottom: 8px; }
.state p { color: var(--text); }

.panel-head {
  min-width: 0;
  display: flex;
  align-items: start;
  justify-content: space-between;
  gap: 14px;
  margin-bottom: 14px;
}

.status,
.chips span {
  min-width: 0;
  max-width: 100%;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  border-radius: 999px;
  padding: 6px 10px;
  font-size: var(--fs-2);
  color: var(--muted);
  background: var(--surface-muted);
}

.status.ok { color: var(--ok); background: var(--ok-soft); }
.status.bad { color: var(--bad); background: var(--bad-soft); }
.status.checking { color: var(--warn); background: var(--warn-soft); }
.chips { min-width: 0; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }
.chips b { color: var(--text); font-weight: 800; }

.stacked {
  min-width: 0;
  display: grid;
  justify-items: end;
  gap: 6px;
}

.metrics {
  min-width: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(180px, 100%), 1fr));
  gap: 10px;
}

.telemetry-pressure-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
  margin-top: 14px;
}

.telemetry-pressure-card {
  display: grid;
  gap: 10px;
  padding: 14px 16px;
  border: 1px solid var(--line);
  border-radius: var(--card-radius);
  background: var(--surface-muted);
}

.telemetry-pressure-card span { display: flex; justify-content: space-between; gap: 10px; }
.telemetry-pressure-card small { color: var(--muted); }
.telemetry-pressure-card > i,
.telemetry-bar-row > i {
  height: 8px;
  overflow: hidden;
  border-radius: 999px;
  background: var(--line);
}
.telemetry-pressure-card > i > b,
.telemetry-bar-row > i > b {
  display: block;
  height: 100%;
  border-radius: inherit;
  background: var(--brand);
}

.telemetry-columns { margin-top: 18px; }
.telemetry-bars { display: grid; gap: 9px; }
.telemetry-bar-row {
  display: grid;
  grid-template-columns: minmax(90px, 1fr) minmax(100px, 2fr) auto;
  align-items: center;
  gap: 8px;
  font-size: var(--fs-2);
}
.telemetry-bar-row > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.telemetry-bar-row > strong { min-width: 32px; text-align: right; }
.telemetry-section { margin-top: 20px; }
.telemetry-section h3 { margin-bottom: 10px; }
.telemetry-context summary { cursor: pointer; color: var(--brand-dark); font-size: var(--fs-1); }
.telemetry-context pre {
  max-width: 680px;
  max-height: 260px;
  margin: 8px 0 0;
  padding: 10px;
  overflow: auto;
  border-radius: var(--row-radius);
  background: #18212f;
  color: #e7eef7;
  font-size: 11px;
  white-space: pre-wrap;
  word-break: break-word;
}
.telemetry-retention { margin: 16px 0 0; color: var(--muted); font-size: var(--fs-1); }

/* 아래부터 패널 안의 상자들은 css/tokens.css의 반경 계단을 따른다: 패널 안의
 * 카드는 --card-radius, 카드 안의 줄·띠·빈 상태는 --row-radius, 손으로 조작하는
 * 것은 --control-radius. 이 파일은 그 셋을 통째로 8px 하나로 적어 두었고, 그래서
 * 어드민에서는 패널·카드·줄이 한 겹으로 눌려 보였다 -- 워크스페이스 쪽은 같은
 * 구조를 세 단계로 그리고 있었으니, 두 콘솔이 같은 카드를 그린다는 이 파일 머리의
 * 약속이 정작 카드 안에서 지켜지지 않았다. */
.metric {
  min-width: 0;
  padding: 16px 18px;
  border: 1px solid var(--line);
  border-radius: var(--card-radius);
  background: var(--surface);
  box-shadow: var(--panel-shadow);
}

.metric small,
td small {
  display: block;
  color: var(--muted);
  font-size: var(--fs-2);
}

.metric small { font-size: var(--fs-1); font-weight: 700; }

.metric strong {
  display: block;
  margin: 6px 0 3px;
  font-size: var(--fs-6);
  letter-spacing: -.03em;
  line-height: 1.1;
  word-break: break-word;
}

.metric span {
  color: var(--muted);
  font-size: var(--fs-2);
}

.checks {
  min-width: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr));
  gap: 10px;
  margin-top: 14px;
}

/* Six readiness checks: pin the column count so wide screens get an even
 * 3x2 block instead of auto-fit's 5+1 wrap with one box dangling alone.
 * U-10: snapped from 1100px to 1181px, the complement of the console's
 * ≤1180px tier (docs/plans/ROADMAP.md §2.1). */
@media (min-width: 1181px) {
  .checks { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

.readiness-check { align-items: flex-start; }

.readiness-check {
  min-width: 0;
  max-width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  border: 1px solid var(--line);
  border-radius: var(--row-radius);
  padding: 11px 12px;
  color: var(--muted);
  background: var(--surface-soft);
}

.readiness-check.ok {
  border-color: rgba(8, 120, 95, 0.22);
  color: var(--ok);
  background: var(--ok-soft);
}

.readiness-check.bad {
  border-color: rgba(184, 64, 44, 0.24);
  color: var(--bad);
  background: var(--bad-soft);
}

.readiness-check span {
  min-width: 0;
}

.readiness-check strong {
  display: block;
  color: var(--text);
  font-size: var(--fs-4);
  line-height: 1.3;
}

.readiness-check small {
  display: block;
  margin-top: 3px;
  color: var(--muted);
  font-size: var(--fs-2);
  line-height: 1.35;
}

.readiness-check b {
  flex: 0 0 auto;
  color: currentColor;
  font-size: var(--fs-2);
  font-weight: 800;
  white-space: nowrap;
}

.reasons {
  margin: 12px 0 0;
  padding-left: 20px;
  color: var(--bad);
}

.system-drilldowns {
  min-width: 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
  margin-top: 14px;
}

.drilldown {
  min-width: 0;
  padding: 12px;
  border: 1px solid var(--line);
  border-radius: var(--card-radius);
  background: var(--surface-soft);
}

.drilldown-card {
  min-width: 0;
  display: grid;
  gap: 8px;
  padding: 12px;
  border: 1px solid var(--line);
  border-radius: var(--card-radius);
  text-align: left;
  color: var(--text);
  background: var(--surface-soft);
  white-space: normal;
}

.drilldown-card:hover {
  color: var(--text);
  border-color: rgba(10, 189, 163, .34);
  background: var(--surface-muted);
}

.drilldown-card.active {
  border-color: rgba(10, 189, 163, .46);
  background: var(--brand-soft);
  box-shadow: inset 0 0 0 1px rgba(10, 189, 163, .12);
}

.drilldown-head {
  min-width: 0;
  display: flex;
  align-items: start;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 10px;
}

.drilldown-head h3 {
  margin: 0;
}

.drilldown-card .drilldown-head {
  margin-bottom: 0;
}

/* 카드 이름은 h3와 같은 15px에 선다 -- 16px이던 동안 이 카드의 이름이 자기를
 * 담고 있는 섹션 제목보다 커서, 층위가 한 칸 뒤집혀 있었다. */
.drilldown-card .drilldown-head b {
  min-width: 0;
  color: var(--text);
  font-size: var(--fs-4);
  overflow-wrap: anywhere;
}

.drilldown-card .drilldown-head small {
  flex: 0 0 auto;
  color: var(--brand-dark);
  font-size: var(--fs-2);
  font-weight: 800;
}

.drilldown-card > span:last-child {
  color: var(--muted);
  font-size: var(--fs-2);
  line-height: 1.45;
}

.drilldown-head span,
.simple-list span {
  color: var(--muted);
  font-size: var(--fs-2);
}

.system-detail {
  min-width: 0;
  margin-top: 14px;
  padding: 14px 16px;
  border: 1px solid var(--line);
  border-radius: var(--card-radius);
  background: var(--surface);
}

.system-detail-head {
  display: flex;
  align-items: end;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 12px;
}

.system-detail-head h3 {
  margin: 0;
}

.system-detail-head span {
  color: var(--muted);
  font-size: var(--fs-2);
}

.simple-list b {
  font-size: var(--fs-4);
}

.simple-list {
  display: grid;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.simple-list li {
  min-width: 0;
  display: grid;
  gap: 3px;
  padding-top: 8px;
  border-top: 1px solid var(--line);
}

.simple-list li:first-child {
  padding-top: 0;
  border-top: 0;
}

.simple-list b,
.simple-list span {
  min-width: 0;
  overflow-wrap: anywhere;
}

.compact-empty {
  padding: 12px;
}

.columns {
  min-width: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 14px;
  margin-top: 14px;
}

.columns > * {
  min-width: 0;
}

.columns.wide-left {
  grid-template-columns: minmax(0, 1.4fr) minmax(280px, .6fr);
}

.tenant-toolbar {
  display: grid;
  grid-template-columns: minmax(220px, 1fr) minmax(140px, max-content) minmax(170px, max-content) minmax(130px, max-content) max-content max-content;
  gap: 8px;
  align-items: center;
  margin-bottom: 12px;
}

/* 워크스페이스 필터와 달리 칸 수가 고정이 아니라(실행 ID·엔진·쪽 크기·체크·버튼) 격자
   대신 흐름으로 둔다 -- 좁아지면 줄바꿈만 하면 되므로 반응형 단계가 따로 필요 없다. */
.failure-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-bottom: 12px;
}

/* 전역 input/select는 width:100%라 흐름 배치에서 한 줄을 통째로 먹는다. 실행 ID만 남는
   폭을 갖고, 나머지는 제 내용만큼만 차지하게 되돌린다. */
.failure-toolbar input[name="run_id"] {
  flex: 1 1 260px;
  min-width: 200px;
}

.failure-toolbar select {
  flex: 0 1 auto;
  width: auto;
  min-width: 150px;
}

.failure-toolbar .inline-check,
.failure-toolbar button {
  flex: 0 0 auto;
}

/* 일괄 재실행 진행 문구. .form-message를 쓰면 진행 상황이 붉게 나와 전부 실패한 것처럼
   읽히므로, 기본은 담담하게 두고 결과가 나왔을 때만 색을 입힌다. */
.retry-progress {
  min-height: 14px;
  margin: 0 0 10px;
  color: var(--muted);
  font-size: var(--fs-2);
}

.retry-progress.success { color: var(--ok); }
.retry-progress.bad { color: var(--bad); }

/* 표 안에서 값 자체를 누를 수 있게 하는 자리(실행 ID). 버튼처럼 보이면 행이 시끄러워지므로
   글자 모양은 그대로 두고 밑줄로만 누를 수 있음을 알린다. */
.inline-link {
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  text-decoration: underline dotted;
  text-underline-offset: 2px;
  cursor: pointer;
}

button.inline-link:hover {
  color: var(--text);
  text-decoration-style: solid;
}

.tenant-count,
.pager,
.row-actions {
  display: flex;
  align-items: center;
}

.tenant-count {
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 10px;
  color: var(--muted);
  font-size: var(--fs-3);
}

/* 정리 대상이 있을 때만 색으로 부른다 -- 늘 붉으면 배경이 되어 아무도 안 본다. */
.tenant-orphan-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 12px;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--surface-2, transparent);
}

.tenant-orphan-bar.has-orphans {
  border-color: var(--warn, #b45309);
}

.tenant-orphan-summary {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.tenant-orphan-summary small {
  color: var(--muted);
  font-size: var(--fs-3);
}

.tenant-orphan-bar .row-actions {
  gap: 8px;
  flex-wrap: wrap;
}

.member-invitations {
  margin-top: 18px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
}

.member-invitations h4 {
  margin: 0 0 2px;
}

.member-invitations > small {
  display: block;
  margin-bottom: 10px;
  color: var(--muted);
  font-size: var(--fs-3);
}

#tenants.tenant-panel-open .tenant-toolbar,
#tenants.tenant-panel-open .tenant-orphan-bar,
#tenants.tenant-panel-open .tenant-count {
  display: none;
}

#tenants.tenant-panel-open > .table-wrap {
  display: none;
}

#tenants.tenant-panel-open .tenant-panels {
  margin-top: 0;
  padding-top: 0;
  border-top: 0;
}

.pager,
.row-actions {
  gap: 6px;
}

.row-actions {
  flex-wrap: wrap;
}

.table-section-head {
  min-width: 0;
  display: flex;
  align-items: start;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 10px;
}

.table-section-head h3 {
  margin-bottom: 0;
}

.muted-row {
  color: var(--muted);
  background: var(--surface-muted);
}

/* 수집은 끝났는데 리포트가 발행되지 않은 실행. 값을 이미 치른 결과가 조용히 사라진
   상태라, 실행 목록에서 눈에 띄어야 한다(옆의 '리포트 발행' 버튼이 그 자리에서 살린다). */
.run-unpublished {
  display: block;
  margin: 2px 0 4px;
  color: var(--warn, #b26a00);
  font-weight: 600;
}

.tenant-panels {
  min-width: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 14px;
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
  align-items: start;
  scroll-margin-top: var(--topbar-scroll-offset);
}

.tenant-panels.single {
  grid-template-columns: minmax(0, 1fr);
}

.tenant-panels > * {
  min-width: 0;
}

.detail-panel {
  min-width: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
}

.detail-panel.empty {
  padding: 18px;
  border: 1px dashed var(--line-strong);
  border-radius: var(--row-radius);
  background: var(--surface-muted);
  color: var(--muted);
  text-align: center;
}

.metrics.compact {
  grid-template-columns: repeat(4, minmax(0, 1fr));
  margin-bottom: 12px;
}

.detail-note {
  display: grid;
  gap: 3px;
  margin-bottom: 12px;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: var(--row-radius);
  background: #fff;
  font-size: var(--fs-2);
}

.detail-note span {
  color: var(--muted);
}

.workspace-access-form {
  margin-bottom: 12px;
  padding: 14px 0 0;
  border-top: 1px solid var(--line);
}

.ticket-grant-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
  align-items: end;
}

.question-ticket-panel .ticket-metrics {
  margin-bottom: 4px;
}

.compact-head {
  margin-bottom: 8px;
}

.access-head,
.access-mode,
.access-plan {
  display: flex;
  align-items: center;
}

.access-head {
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 10px;
}

.access-head h3 { margin: 2px 0 0; }
.access-head small { color: var(--brand-dark); font-weight: 800; letter-spacing: 0; }

.access-plan {
  max-width: 280px;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 10px;
  color: var(--muted);
  font-size: var(--fs-1);
}

.access-plan select { min-width: 150px; }

.access-mode-grid {
  min-width: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr));
  gap: 4px 24px;
  padding: 8px 0;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}

.access-mode {
  min-width: 0;
  align-items: center;
  gap: 9px;
  padding: 8px 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  cursor: pointer;
}

.access-mode.enabled { cursor: default; }
.access-mode input {
  width: 20px;
  height: 20px;
  min-height: 20px;
  flex: 0 0 20px;
  padding: 0;
}
.access-mode span { min-width: 0; display: grid; gap: 3px; }
.access-mode b { font-size: var(--fs-3); }
.access-mode small,
.access-help { color: var(--muted); font-size: var(--fs-1); }
.access-mode small {
  line-height: 1.45;
  overflow-wrap: anywhere;
  word-break: keep-all;
}
.access-help { margin: 9px 0 0; }
.form-message { min-height: 14px; margin: 7px 0 0; color: var(--bad); font-size: var(--fs-2); }
.form-message.success { color: var(--ok); }

/* 워크스페이스별 AI 계열 배정. 플랜/특화 화면 배정과 같은 폼 어휘를 쓴다 -- 셋 다
 * "이 워크스페이스가 무엇에 닿을 수 있는가"를 정하는 같은 종류의 결정이다. */
.grant-family-grid {
  min-width: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr));
  gap: 2px 24px;
  padding: 8px 0;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}

.grant-family {
  min-width: 0;
  display: flex;
  align-items: flex-start;
  gap: 9px;
  padding: 7px 0;
  cursor: pointer;
}
.grant-family input {
  width: 18px;
  height: 18px;
  min-height: 18px;
  flex: 0 0 18px;
  margin-top: 2px;
  padding: 0;
}
.grant-family span { min-width: 0; display: grid; gap: 2px; }
.grant-family b { font-size: var(--fs-3); color: var(--muted); }
.grant-family.is-granted b { color: var(--text); }
.grant-family small,
.grant-family em {
  color: var(--muted);
  font-size: var(--fs-1);
  font-style: normal;
  line-height: 1.45;
  overflow-wrap: anywhere;
  word-break: keep-all;
}
.grant-family em { font-weight: 700; }

.access-request-action {
  min-width: min(260px, 100%);
  display: grid;
  gap: 8px;
}

.access-request-action input {
  width: 100%;
}

.detail-section {
  margin-top: 14px;
}

.account-grid {
  min-width: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
}

.account-card {
  min-width: 0;
  display: grid;
  gap: 10px;
  padding: 14px 16px;
  border: 1px solid var(--line);
  border-radius: var(--card-radius);
  background: var(--surface-soft);
}

.account-card h3 {
  margin-bottom: 2px;
}

.account-card label {
  min-width: 0;
  display: grid;
  gap: 5px;
  color: var(--muted);
  font-size: var(--fs-2);
  font-weight: 800;
}

.account-card button[type="submit"] {
  justify-self: start;
}

.platform-admin-form {
  min-width: 0;
  display: grid;
  grid-template-columns: minmax(260px, 1fr) max-content;
  gap: 8px;
  align-items: start;
  margin: 10px 0 12px;
}

.platform-admin-form .form-message {
  grid-column: 1 / -1;
}

.tenant-panels .member-panel {
  margin-top: 0;
}

.table-wrap {
  min-width: 0;
  max-width: 100%;
  overflow: auto;
  border: 1px solid var(--line);
  border-radius: var(--card-radius);
  background: var(--surface);
}

table {
  width: 100%;
  border-collapse: collapse;
  min-width: 720px;
  font-size: var(--fs-3);
}

table.compact-table {
  min-width: 0;
}

table.spacious-table {
  min-width: 900px;
}

table.wide-table {
  min-width: 1120px;
}

/* 18px is the UA default and undershoots the 24px minimum target size. admin.html does not
   load forms.css, so the workspace rule does not reach this page. */
input[type="checkbox"],
input[type="radio"] {
  width: 20px;
  height: 20px;
  margin: 2px;
  accent-color: var(--brand-dark);
}

th,
td {
  padding: 11px 12px;
  text-align: left;
  vertical-align: top;
  border-bottom: 1px solid var(--line);
  overflow-wrap: normal;
  word-break: keep-all;
}

th {
  position: sticky;
  top: 0;
  color: var(--muted-strong);
  background: var(--surface-soft);
  font-size: var(--fs-2);
  font-weight: 800;
  letter-spacing: 0;
}

tbody tr:hover {
  background: #fbfdfd;
}

tbody tr:last-child td { border-bottom: 0; }
td b { display: block; margin-bottom: 3px; }
td small {
  overflow-wrap: break-word;
}

.panel-head small,
.heading p,
.detail-note span,
.drilldown-card > span:last-child,
.empty {
  overflow-wrap: break-word;
  word-break: keep-all;
}

#tenants table.wide-table {
  min-width: 1260px;
  /* This is the only nine-column table whose first and last cells both have a
   * large min-content width (workspace identity and four action buttons). In
   * the automatic table algorithm those cells grow after the minimum below is
   * applied, pushing 관리 outside the wrapper; the squeezed action cell then
   * wraps one button per row. Keep the variable space in the identity column
   * and reserve the other columns explicitly. */
  table-layout: fixed;
}

#tenants th:nth-child(2),
#tenants td:nth-child(2) { width: 140px; }
#tenants th:nth-child(3),
#tenants td:nth-child(3),
#tenants th:nth-child(4),
#tenants td:nth-child(4) { width: 74px; }
#tenants th:nth-child(5),
#tenants td:nth-child(5),
#tenants th:nth-child(6),
#tenants td:nth-child(6) { width: 115px; }
#tenants th:nth-child(7),
#tenants td:nth-child(7) { width: 120px; }
#tenants th:nth-child(8),
#tenants td:nth-child(8) { width: 190px; }
#tenants th:nth-child(9),
#tenants td:nth-child(9) { width: 150px; }

#tenants td:first-child b,
#tenants td:first-child small {
  overflow-wrap: anywhere;
}

#tenants th:nth-child(2),
#tenants td:nth-child(2),
#tenants th:nth-child(7),
#tenants td:nth-child(7) {
  white-space: nowrap;
}

#tenants th:nth-child(8),
#tenants td:nth-child(8),
#runs th:nth-child(6),
#runs td:nth-child(6),
#provider-calls th:nth-child(6),
#provider-calls td:nth-child(6),
#account th:nth-child(3),
#account td:nth-child(3) {
  min-width: 150px;
  white-space: nowrap;
}

#tenants th:nth-child(8),
#tenants td:nth-child(8),
#runs th:nth-child(6),
#runs td:nth-child(6),
#provider-calls th:nth-child(6),
#provider-calls td:nth-child(6),
#account th:nth-child(3),
#account td:nth-child(3) {
  min-width: 190px;
}

/* 워크스페이스의 빈 상태(.panel-empty · reports.css의 .empty)와 같은 상자다:
 * 점선 --line-strong 테두리에 --surface-muted 바탕, 줄 층위 반경, 13px. 예전에는
 * 8px에 --surface-soft(청록기 있는 흰색)라서, 같은 "아직 없음"이 콘솔을 옮길 때마다
 * 다른 상자로 보였다. */
.empty {
  padding: 18px;
  border: 1px dashed var(--line-strong);
  border-radius: var(--row-radius);
  color: var(--muted);
  background: var(--surface-muted);
  font-size: var(--fs-2);
  text-align: center;
}

/* 파이프라인 산출물 sits in the narrow right column of the schema view, where the global 720px
   table floor forces a permanent horizontal scroll that hides the 상태 column. */
#tables .columns.wide-left {
  grid-template-columns: minmax(0, 1.25fr) minmax(330px, .75fr);
}

#tables .columns.wide-left table {
  min-width: 0;
}

#tables .columns.wide-left th:nth-child(4),
#tables .columns.wide-left td:nth-child(4) {
  min-width: 0;
  white-space: normal;
  word-break: keep-all;
}

.schema-map-shell {
  min-width: 0;
  display: grid;
  gap: 14px;
}

.schema-canvas-wrap {
  min-width: 0;
  max-width: 100%;
  overflow: auto;
  border: 1px solid var(--line);
  border-radius: var(--card-radius);
  background: var(--surface-soft);
}

.schema-canvas {
  display: block;
  width: 100%;
  min-width: 1080px;
  height: auto;
}

.schema-group-title {
  fill: var(--muted);
  font-size: var(--fs-3);
  font-weight: 800;
}

.schema-group-count {
  fill: var(--muted);
  font-size: var(--fs-1);
}

.schema-edge {
  fill: none;
  stroke: #9db1ba;
  stroke-width: 1.6;
  marker-end: url(#schema-arrow);
}

.schema-edge-loop {
  stroke-dasharray: 5 5;
}

.schema-edge-label {
  fill: var(--muted-strong);
  stroke: rgba(255, 255, 255, .94);
  stroke-linejoin: round;
  stroke-width: 4px;
  paint-order: stroke;
  pointer-events: none;
  font-size: var(--fs-1);
  font-weight: 800;
}

.schema-canvas marker path {
  fill: #9db1ba;
}

.schema-node-card {
  fill: #fff;
  stroke: var(--line-strong);
  stroke-width: 1;
}

.schema-node-accent {
  fill: var(--line-strong);
  stroke: none;
}

.schema-node-identity .schema-node-card {
  fill: #f7fbff;
}

.schema-node-identity .schema-node-accent {
  fill: #3981d8;
}

.schema-node-workspace .schema-node-card {
  fill: #fbfaf6;
}

.schema-node-workspace .schema-node-accent {
  fill: #b08b2e;
}

.schema-node-execution .schema-node-card {
  fill: #f7fbf8;
}

.schema-node-execution .schema-node-accent {
  fill: #16805f;
}

.schema-node-operations .schema-node-card {
  fill: #fbf8fb;
}

.schema-node-operations .schema-node-accent {
  fill: #9b5aaa;
}

.schema-node-pipeline .schema-node-accent,
.schema-node-other .schema-node-accent {
  fill: #6b7780;
}

.schema-node-title {
  fill: var(--text);
  font-size: var(--fs-3);
  font-weight: 800;
}

.schema-node-meta {
  fill: var(--muted);
  font-size: var(--fs-1);
}

.schema-node-keys {
  fill: var(--muted-strong);
  font-size: var(--fs-1);
  font-weight: 700;
}

.schema-code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
  overflow-wrap: break-word;
  word-break: normal;
}

#tables th,
#tables td {
  word-break: keep-all;
}

.schema-summary-grid {
  min-width: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(180px, 100%), 1fr));
  gap: 8px;
}

.schema-summary-item {
  min-width: 0;
  display: grid;
  gap: 3px;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: var(--row-radius);
  background: var(--surface-soft);
}

.schema-summary-item span {
  color: var(--muted);
  font-size: var(--fs-2);
}

.schema-relation-grid {
  min-width: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr));
  gap: 8px;
}

.schema-relation-card {
  min-width: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 78px minmax(0, 1fr);
  align-items: center;
  gap: 8px;
  padding: 10px;
  border: 1px solid var(--line);
  border-radius: var(--row-radius);
  background: var(--surface-soft);
}

.schema-relation-table {
  min-width: 0;
  display: grid;
  gap: 3px;
}

.schema-relation-table b,
.schema-relation-table small {
  min-width: 0;
  display: block;
}

.schema-relation-table b {
  color: var(--text);
  font-size: var(--fs-2);
  line-height: 1.25;
}

.schema-relation-table small {
  color: var(--muted);
  font-size: var(--fs-1);
  line-height: 1.2;
}

.schema-relation-key {
  min-width: 0;
  display: grid;
  justify-items: center;
  gap: 4px;
  color: var(--brand-dark);
  text-align: center;
}

.schema-relation-key > span {
  width: 28px;
  height: 28px;
  display: grid;
  place-items: center;
  border-radius: 999px;
  color: #fff;
  background: var(--brand-dark);
  font-weight: 900;
  line-height: 1;
}

.schema-relation-key small {
  max-width: 100%;
  color: var(--muted-strong);
  font-size: var(--fs-1);
  line-height: 1.2;
  overflow-wrap: anywhere;
}

.muted { color: var(--muted); }
.inline-actions { margin-top: 16px !important; }
/* 로그인 안내 카드의 단독 CTA. 워크스페이스의 .primary와 같은 버튼이므로 같은
 * 모서리에 선다 -- 알약이던 동안, 콘솔에서 유일하게 알약으로 서는 버튼이었다. */
.inline-actions a,
.inline-actions button {
  display: inline-flex;
  border: 0;
  border-radius: var(--control-radius);
  padding: 10px 14px;
  color: #fff;
  background: var(--brand-dark);
  font: inherit;
  font-weight: 800;
  cursor: pointer;
}

.inline-actions a:hover,
.inline-actions button:hover {
  color: #fff;
  background: #066b5e;
}

.inline-actions button { margin-left: 8px; }

/* 워크스페이스의 .secondary / .primary와 같은 두 버튼이다(css/forms.css). 표 안에
 * 여러 개가 나란히 서므로 여백만 6/10으로 좁다. 예전에는 hover가 회색(테두리
 * --line, 바탕 --surface-muted)이어서, 같은 버튼이 워크스페이스에서는 청록으로
 * 반응하고 어드민에서는 회색으로 반응했다 -- 어느 쪽이 눌러도 되는 것인지에 대한
 * 답이 화면마다 달랐던 셈이다. */
.small-button {
  padding: 6px 10px;
  border-color: var(--line);
  background: var(--surface);
  font-weight: 700;
}

/* 열려 있는 토글(.active / aria-expanded)은 hover보다 우선한다 -- 지금 펼쳐진
 * 패널이 무엇인지가 마우스가 어디 있는지보다 중요한 정보다. */
button.small-button:hover:not(:disabled):not(.active):not([aria-expanded="true"]) {
  color: var(--brand-dark);
  border-color: var(--brand);
  background: var(--surface);
}

.small-button.primary {
  color: #fff;
  border-color: var(--brand-dark);
  background: var(--brand-dark);
}

button.small-button.primary:hover:not(:disabled) {
  color: #fff;
  border-color: #066b5e;
  background: #066b5e;
}

button.small-button.danger:hover:not(:disabled) {
  color: var(--bad);
  border-color: var(--bad);
  background: #fff0ed;
}

.small-button.active,
.small-button[aria-expanded="true"] {
  color: var(--brand-dark);
  border-color: rgba(10, 189, 163, .46);
  background: var(--brand-soft);
  box-shadow: inset 0 0 0 1px rgba(10, 189, 163, .12);
}

.small-button.danger {
  color: var(--bad);
  border-color: #f1c8c8;
  background: #fff7f7;
}

.member-panel .badge {
  display: inline-block;
  margin-top: 3px;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: var(--fs-1);
  font-weight: 800;
  color: var(--brand-dark);
  background: var(--brand-soft);
}

.member-panel .badge.danger {
  color: var(--bad);
  background: #fff7f7;
}

.member-panel {
  min-width: 0;
  margin-top: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
}

.member-panel.empty {
  padding: 18px;
  border: 1px dashed var(--line-strong);
  border-radius: var(--row-radius);
  background: var(--surface-muted);
  color: var(--muted);
  text-align: center;
}

.member-head,
.member-form,
.inline-check {
  display: flex;
  align-items: center;
}

.member-head {
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 12px;
}

.member-head span,
.member-head small {
  color: var(--muted);
  font-size: var(--fs-1);
}

.member-form {
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 12px;
}

.provider-key-form,
.provider-runtime-form {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: 8px;
  align-items: center;
  margin-bottom: 12px;
}

.provider-key-form {
  grid-template-columns:
    minmax(150px, .75fr)
    minmax(190px, 1fr)
    minmax(190px, 1fr)
    minmax(280px, 1.35fr)
    max-content
    max-content;
  align-items: start;
  padding: 14px 16px;
  border: 1px solid var(--line);
  border-radius: var(--card-radius);
  background: var(--surface-soft);
}

.provider-key-form[data-provider-key-mode="multiple"] {
  grid-template-columns:
    minmax(160px, .75fr)
    minmax(220px, .95fr)
    minmax(0, 2.4fr)
    max-content
    max-content;
}

.provider-key-env-field,
.runtime-model-field {
  min-width: 0;
  display: grid;
  gap: 5px;
}

.provider-key-env-field small {
  color: var(--muted);
  font-size: var(--fs-1);
  line-height: 1.35;
}

.runtime-model-field {
  grid-template-columns: minmax(0, 1fr) minmax(150px, .75fr);
}

.runtime-model-field.compact {
  min-width: min(260px, 100%);
  grid-template-columns: minmax(0, 1fr);
}

.provider-runtime-form {
  grid-template-columns:
    minmax(200px, 1fr)
    minmax(320px, 1.25fr)
    minmax(200px, .9fr)
    minmax(120px, .42fr)
    minmax(120px, .42fr)
    minmax(120px, .42fr)
    max-content
    max-content;
  align-items: start;
}

.provider-key-form > select,
.provider-key-form > input,
.provider-key-form .provider-key-env-field,
.provider-key-form .provider-key-secret-fields,
.provider-key-form .secret-field,
.provider-key-form .inline-check,
.provider-key-form button[type="submit"] {
  grid-column: auto;
  min-width: 0;
}

.provider-key-form button[type="submit"] {
  min-height: 38px;
  justify-self: start;
}

.secret-field {
  min-width: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr) max-content;
  gap: 6px;
}

.secret-field input {
  min-width: 0;
}

.secret-field button {
  min-height: 38px;
}

/* The rail costs the content area 244px, plus main and panel padding: a panel's
 * inner width is roughly `viewport - 376`. The dense provider forms need ~1164px
 * of that, so the wide multi-column layout can only be offered from ~1540px up.
 * These thresholds are compensating for the shell, not for the viewport.
 * U-10 (docs/plans/ROADMAP.md §2.1): kept outside the console's 3-breakpoint
 * scheme (≤760/≤1180/>1180) on purpose -- this is a calculated threshold tied
 * to the exact shell overhead above, not an eyeballed one, and snapping it to
 * 1181px would offer the multi-column layout ~360px too early (content area
 * would be ~804px against the ~1164px this needs), a real overflow risk
 * rather than a cosmetic one. */
@media (min-width: 1541px) {
  .provider-key-form[data-provider-key-mode="multiple"] .key-active,
  .provider-key-form[data-provider-key-mode="multiple"] button[type="submit"] {
    margin-top: 32px;
  }
}

.provider-key-secret-fields {
  min-width: 0;
  display: grid;
  gap: 6px;
}

.provider-key-secret-fields[data-mode="multiple"] {
  grid-column: span 2;
  grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr));
}

.provider-key-form[data-provider-key-mode="multiple"] .provider-key-secret-fields[data-mode="multiple"] {
  grid-column: auto;
}

.provider-key-secret-row {
  min-width: 0;
  display: grid;
  gap: 4px;
}

.provider-key-secret-row > span {
  min-width: 0;
  color: var(--text);
  font-size: var(--fs-1);
  font-weight: 800;
  line-height: 1.25;
}

.provider-key-secret-row small {
  display: block;
  color: var(--muted);
  font-weight: 600;
  overflow-wrap: anywhere;
}

.table-secret {
  min-width: 220px;
}

.advanced-provider-options {
  grid-column: 1 / -1;
  align-self: start;
  padding: 2px 0 0;
  color: var(--muted);
  font-size: var(--fs-2);
}

.advanced-provider-options summary {
  width: max-content;
  cursor: pointer;
  font-weight: 800;
}

.advanced-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(170px, 220px));
  gap: 8px;
  margin-top: 8px;
}

.advanced-grid label {
  display: grid;
  gap: 5px;
  color: var(--muted);
  font-size: var(--fs-2);
  font-weight: 800;
}

.key-summary {
  flex-wrap: nowrap;
}

/* 점수 산식 설정 -- 표가 아니라 grid 행이다. 어드민 표(.table-wrap)는 좁아지면
   가로로 밀리는데, 여기서는 마지막 칸이 값을 바꾸는 입력이라 스크롤 뒤로 숨으면
   안 된다. 좁은 폭에서는 세 칸이 그대로 세로로 쌓인다. */
.scoring-list { display: grid; gap: 8px; margin-top: 10px; }
.scoring-row {
  display: grid;
  grid-template-columns: minmax(170px, 0.9fr) minmax(0, 1.9fr) minmax(150px, auto);
  gap: 6px 16px;
  align-items: start;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: var(--row-radius);
  background: var(--surface);
}
@media (max-width: 1080px) { .scoring-row { grid-template-columns: 1fr; } }
.scoring-name b { display: block; }
.scoring-name small,
.scoring-value small { display: block; color: var(--muted); font-size: var(--fs-1); }
.scoring-desc { margin: 0; color: var(--muted); font-size: var(--fs-1); line-height: 1.6; }
.scoring-number { max-width: 7.5rem; }
.scoring-value > small { margin-top: 4px; }
.scoring-value > .small-button { margin-top: 6px; }

.panel-foot {
  display: flex;
  justify-content: flex-end;
  padding-top: 0.75rem;
}

.provider-key-env-fallbacks {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 8px 0 14px;
}

.provider-key-env-fallbacks span {
  min-width: 180px;
  display: grid;
  gap: 3px;
  padding: 9px 11px;
  border: 1px solid var(--line);
  border-radius: var(--row-radius);
  background: var(--surface-soft);
}

.provider-key-env-fallbacks b {
  color: var(--text);
  font-size: var(--fs-2);
  line-height: 1.25;
  overflow-wrap: anywhere;
}

.provider-key-env-fallbacks small {
  color: var(--muted);
  font-size: var(--fs-1);
  line-height: 1.3;
}

.provider-runtime-form select[name="preset"],
.provider-runtime-form .runtime-model-field,
.provider-runtime-form input[name="label"],
.provider-runtime-form input[name="timeout_seconds"],
.provider-runtime-form input[name="max_tokens"],
.provider-runtime-form input[name="temperature"],
.provider-runtime-form .runtime-form-actions {
  grid-column: auto;
  min-width: 0;
}
.provider-runtime-form .runtime-advanced {
  grid-column: 1 / -1;
}
.provider-runtime-form .runtime-advanced-grid {
  grid-template-columns:
    minmax(240px, 1fr)
    minmax(280px, 1.4fr)
    minmax(130px, .45fr);
}
.runtime-synthesis-form {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: repeat(4, minmax(140px, 1fr));
  gap: 8px;
  padding-top: 4px;
}
.runtime-synthesis-cell {
  min-width: min(300px, 100%);
  color: var(--muted);
  font-size: var(--fs-1);
}
.runtime-synthesis-cell summary {
  max-width: 360px;
  cursor: pointer;
  color: var(--text);
  font-weight: 800;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.runtime-synthesis-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(135px, 1fr));
  gap: 6px;
  margin-top: 8px;
}
.runtime-synthesis-form label,
.runtime-synthesis-grid label {
  display: grid;
  gap: 4px;
  min-width: 0;
  color: var(--muted);
  font-size: var(--fs-1);
  font-weight: 800;
}
.provider-runtime-form .runtime-preset-note {
  grid-column: 1 / -1;
  margin: -2px 0 0;
  color: var(--muted);
  font-size: var(--fs-2);
  line-height: 1.45;
}
.provider-runtime-form .runtime-form-actions {
  grid-column: 1 / -1;
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: var(--row-radius);
  background: var(--surface-soft);
}
.provider-runtime-form .runtime-active-check {
  position: relative;
  min-height: 34px;
  gap: 9px;
  color: var(--muted-strong);
  font-weight: 800;
  cursor: pointer;
}
.provider-runtime-form .runtime-active-check input {
  width: 38px;
  height: 24px;
  min-height: 24px;
  flex: 0 0 38px;
  margin: 0;
  padding: 0;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  appearance: none;
  background: #c7d3d2;
  box-shadow: inset 0 1px 2px rgba(16, 32, 31, .12);
  cursor: pointer;
  transition: background .16s ease, border-color .16s ease;
}
.provider-runtime-form .runtime-active-check input::after {
  content: "";
  width: 16px;
  height: 16px;
  display: block;
  margin: 2px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 3px rgba(16, 32, 31, .22);
  transition: transform .16s ease;
}
.provider-runtime-form .runtime-active-check input:checked {
  border-color: var(--brand-dark);
  background: var(--brand-dark);
}
.provider-runtime-form .runtime-active-check input:checked::after {
  transform: translateX(16px);
}
.provider-runtime-form .runtime-active-check input:focus-visible {
  outline: 3px solid rgba(10, 189, 163, .2);
  outline-offset: 2px;
}
.provider-runtime-form .runtime-submit {
  min-width: 106px;
  min-height: 38px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  padding: 0 14px;
}
.provider-runtime-form .runtime-submit::before {
  content: "+";
  width: 16px;
  height: 16px;
  display: inline-grid;
  place-items: center;
  border-radius: 999px;
  background: rgba(255, 255, 255, .18);
  font-size: var(--fs-4);
  line-height: 1;
}

.provider-key-form .form-message,
.provider-runtime-form .form-message {
  grid-column: 1 / -1;
}

.runtime-model-preset-manager {
  display: grid;
  gap: 10px;
  margin: 14px 0;
  padding: 14px 16px;
  border: 1px solid var(--line);
  border-radius: var(--card-radius);
  background: var(--surface-soft);
}

.runtime-model-preset-form {
  display: grid;
  grid-template-columns:
    minmax(150px, .75fr)
    minmax(220px, 1.2fr)
    minmax(180px, 1fr)
    minmax(110px, .5fr)
    minmax(120px, .55fr)
    minmax(130px, .6fr)
    minmax(90px, .4fr)
    max-content;
  gap: 8px;
  align-items: start;
}

.runtime-model-preset-form > * {
  min-width: 0;
}

.runtime-model-preset-form .form-message {
  grid-column: 1 / -1;
}

.runtime-model-preset-table {
  min-width: 0;
}

.provider-key-pools {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr));
  align-items: start;
  gap: 8px;
  margin: 8px 0 14px;
}

.provider-key-pool {
  min-width: 0;
  display: grid;
  align-content: start;
  gap: 6px;
  padding: 10px;
  border: 1px solid var(--line);
  border-radius: var(--row-radius);
  background: var(--surface-soft);
}

.provider-key-pool > .status {
  justify-self: start;
}

.provider-key-pool[data-ready="false"] {
  background: #fffafa;
  border-color: rgba(180, 35, 24, .22);
}

.provider-key-pool-muted {
  grid-column: 1 / -1;
  border-style: dashed;
  background: #fbfdfd;
}

.provider-key-missing-list {
  width: 100%;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(180px, 100%), 1fr));
  gap: 5px;
  margin: 2px 0 0;
  padding: 0;
  list-style: none;
}

.provider-key-missing-list li {
  min-width: 0;
  display: grid;
  gap: 2px;
  padding: 6px 7px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--surface-strong);
}

.provider-key-missing-list b,
.provider-key-missing-list small {
  min-width: 0;
  overflow-wrap: anywhere;
}

.provider-key-missing-list b {
  font-size: var(--fs-1);
  line-height: 1.25;
}

.provider-key-pool b,
.provider-key-pool small {
  display: block;
  overflow-wrap: anywhere;
}

.provider-key-pool small {
  color: var(--muted);
  font-size: var(--fs-1);
  line-height: 1.35;
}

/* admin.html은 css/forms.css를 링크하지 않으므로(워크스페이스 앱의 엔트리 포인트만
 * 링크한다) 폼 크롬은 여기서 다시 정한다. 다시 정하더라도 재료는 같아야 한다:
 * 반경은 컨트롤 층위 토큰, 테두리는 --line-strong. 테두리가 --line이던 동안 어드민의
 * 입력칸은 옆에 놓인 카드 테두리와 같은 밝기여서, 어디가 눌리는 자리인지 테두리가
 * 말해 주지 못했다 -- 워크스페이스 폼은 한 단계 짙은 선으로 그것을 말한다.
 *
 * 높이와 여백만 일부러 다르다. 어드민은 한 줄에 예닐곱 칸이 들어가는 표·폼 화면이라
 * 34px/7-9px로 조밀하게 서고, 워크스페이스 폼은 12px 여백으로 넉넉하게 선다. 같은
 * 재료로 만든 같은 컨트롤의 밀도 차이지, 다른 컨트롤이 아니다. */
input,
select,
textarea {
  width: 100%;
  min-height: 34px;
  border: 1px solid var(--line-strong);
  border-radius: var(--control-radius);
  padding: 7px 9px;
  color: var(--text);
  background: var(--surface-strong);
  font: inherit;
}

textarea {
  resize: vertical;
}

input:focus-visible,
select:focus-visible,
textarea:focus-visible,
button:focus-visible,
a:focus-visible {
  outline: 3px solid rgba(10, 189, 163, .2);
  outline-offset: 2px;
  border-color: var(--brand);
}

.inline-check { gap: 6px; color: var(--muted); }
.inline-check {
  min-height: 34px;
  justify-content: flex-start;
  white-space: nowrap;
}
.inline-check input {
  width: 32px;
  height: 32px;
  min-height: 32px;
  flex: 0 0 32px;
  padding: 0;
}
.provider-key-form .key-active {
  min-height: 38px;
  align-self: start;
}
.provider-key-form .key-active input {
  width: 20px;
  height: 20px;
  min-height: 20px;
  flex-basis: 20px;
}
.bad-text { color: var(--bad) !important; }
.table-input {
  width: 100%;
  min-width: 130px;
  min-height: 30px;
  padding: 5px 7px;
  border-radius: 6px;
}
/* 임시 비밀번호 길이 안내. 비어 있을 때 자리를 차지하면 행 높이가 들썩인다. */
.member-password-error {
  display: block;
  margin-top: 4px;
  color: var(--neg, #c2410c);
}
.member-password-error:empty { display: none; }

/* 상태 칸: 활성 체크와 차단 배지가 세로로 쌓인다. 배지는 접히지 않는다. */
.member-state-cell .badge {
  display: inline-block;
  margin-top: 4px;
  white-space: nowrap;
}

/* 한국어는 어절 안에서 끊으면 읽기가 나빠진다("워크스페이스 멤버 / 십만"). */
.member-head small { word-break: keep-all; }

/* "2026. 8. 3. 17시 58분 17초"가 두 줄로 접히면 행 높이가 배로 뛴다. */
.member-created-cell { white-space: nowrap; }

/* 로그인 차단·삭제는 나란히 둔다 -- 줄이 갈리면 삭제가 아래로 떨어져 잘못 눌리기 쉽다. */
.member-panel .row-actions {
  display: flex;
  flex-wrap: nowrap;
  gap: 6px;
}
.member-panel .row-actions .small-button { white-space: nowrap; }

.table-input.wide { min-width: 260px; }
.table-input.small { min-width: 78px; max-width: 96px; }
.table-input.tiny { min-width: 64px; max-width: 88px; }

.provider-key-table {
  margin-top: 12px;
}

.provider-key-table table {
  min-width: 1080px;
}

.provider-key-table th:nth-child(3),
.provider-key-table th:nth-child(4),
.provider-key-table th:nth-child(5),
.provider-key-table th:nth-child(6),
.provider-key-table td:nth-child(3),
.provider-key-table td:nth-child(4),
.provider-key-table td:nth-child(5),
.provider-key-table td:nth-child(6) {
  width: 86px;
}

.provider-key-table th:nth-child(8),
.provider-key-table td:nth-child(8) {
  width: 280px;
}

.provider-key-status-cell,
.provider-key-control-cell {
  white-space: nowrap;
}

.provider-key-status-cell .status + .status {
  margin-left: 6px;
}

.provider-key-status-cell small {
  margin-top: 4px;
}

.provider-key-table .row-actions {
  flex-wrap: nowrap;
}

/* Below the rail breakpoint the chrome collapses to a dark top bar: brand and
 * actions on one row, the section list scrolling horizontally beneath them. The
 * group labels only make sense in the vertical rail, so they stay hidden here. */
@media (max-width: 760px) {
  :root { --topbar-scroll-offset: 148px; }

  .topbar {
    grid-template-columns: minmax(0, 1fr) max-content;
  }
  .brand { grid-column: 1; }
  .actions {
    grid-column: 2;
    grid-row: 1;
    width: auto;
    justify-content: flex-end;
    flex-wrap: wrap;
  }
  .admin-nav {
    grid-column: 1 / -1;
    flex-wrap: nowrap;
  }
  .admin-nav a,
  .nav-group > summary { padding: 8px 10px; }
  .admin-account { display: none; }
  .nav-submenu { right: 0; left: auto; }
}

/* U-10 (docs/plans/ROADMAP.md §2.1): kept at 1540px, matching the calculated
 * min-width:1541px pair above (.provider-key-form[data-provider-key-mode=
 * "multiple"] needs the content area's ~1164px, which only exists above
 * ~1540px viewport width once the rail is subtracted) -- see that rule's
 * comment. This block also carries several rules unrelated to that specific
 * math (.metrics, .system-drilldowns, .columns, .tenant-panels, etc.) that
 * could plausibly have been split out onto the ≤1180px tier instead; left
 * bundled here rather than split apart without visual verification of the
 * result. */
@media (max-width: 1540px) {
  .metrics { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .system-drilldowns { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .columns,
  .columns.wide-left,
  .account-grid,
  .tenant-panels { grid-template-columns: 1fr; }
  .access-mode-grid { grid-template-columns: 1fr; }
  .tenant-toolbar,
  .platform-admin-form,
  .provider-key-form,
  .provider-runtime-form,
  .runtime-model-preset-form { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .provider-key-form[data-provider-key-mode="multiple"] {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .platform-admin-form > *,
  .provider-key-form > *,
  .provider-runtime-form > *,
  .runtime-model-preset-form > * {
    grid-column: auto !important;
  }
  .provider-key-form .advanced-provider-options,
  .provider-key-form .provider-key-secret-fields[data-mode="multiple"],
  .provider-key-form .form-message,
  .provider-runtime-form .runtime-advanced,
  .provider-runtime-form .runtime-form-actions,
  .provider-runtime-form .runtime-synthesis-form,
  .provider-runtime-form .runtime-preset-note,
  .provider-runtime-form .form-message,
  .runtime-model-preset-form .form-message {
    grid-column: 1 / -1 !important;
  }
  .advanced-grid,
  .provider-runtime-form .runtime-advanced-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .runtime-synthesis-form { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Between the rail and mobile breakpoints the content column is much narrower
 * than the viewport: the 244px rail is still present. Two preset columns leave
 * less than the compact model control's 260px minimum, and two synthesis cards
 * leave less than their 300px preferred width. Fold only these dense API-model
 * controls before they can enlarge the page. */
@media (max-width: 1000px) {
  .telemetry-pressure-grid { grid-template-columns: minmax(0, 1fr); }
  .runtime-model-preset-form {
    grid-template-columns: minmax(0, 1fr);
  }

  .runtime-model-preset-form > * {
    grid-column: auto !important;
  }

  .runtime-model-preset-form .form-message,
  .provider-runtime-form .runtime-synthesis-form {
    grid-column: 1 / -1 !important;
  }

  .runtime-synthesis-form {
    grid-template-columns: minmax(0, 1fr);
  }

  .provider-runtime-form .runtime-advanced-grid {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* U-10: was 700px, with a further 460px step below it (merged in below) --
 * both collapsed onto the console's ≤760px tier (docs/plans/ROADMAP.md
 * §2.1). */
@media (max-width: 760px) {
  main { padding: 0 14px 36px; }
  #app > .panel {
    max-height: none;
    overflow: visible;
  }
  .heading,
  .panel-head {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    justify-content: stretch;
    justify-items: start;
  }
  .metrics { grid-template-columns: minmax(0, 1fr); }
  .system-drilldowns { grid-template-columns: 1fr; }
  .metrics.compact,
  .tenant-toolbar,
  .platform-admin-form,
  .provider-key-form,
  .provider-runtime-form,
  .runtime-model-preset-form { grid-template-columns: 1fr; }
  .provider-key-form[data-provider-key-mode="multiple"] {
    grid-template-columns: 1fr;
  }
  .platform-admin-form > *,
  .provider-key-form > *,
  .provider-runtime-form > *,
  .runtime-model-preset-form > * {
    grid-column: auto !important;
  }
  .provider-key-form .advanced-provider-options,
  .provider-key-form .provider-key-secret-fields,
  .provider-key-form .form-message,
  .provider-runtime-form .runtime-advanced,
  .provider-runtime-form .runtime-form-actions,
  .provider-runtime-form .runtime-synthesis-form,
  .provider-runtime-form .runtime-preset-note,
  .provider-runtime-form .form-message,
  .runtime-model-preset-form .form-message {
    grid-column: 1 / -1 !important;
  }
  .provider-key-secret-fields[data-mode="multiple"] {
    grid-template-columns: 1fr;
  }
  .provider-runtime-form .runtime-form-actions {
    align-items: stretch;
    flex-direction: column;
  }
  .provider-runtime-form .runtime-active-check {
    justify-content: space-between;
  }
  .provider-runtime-form .runtime-submit {
    width: 100%;
  }
  .advanced-grid,
  .provider-runtime-form .runtime-advanced-grid {
    grid-template-columns: 1fr;
  }
  .runtime-synthesis-form,
  .runtime-synthesis-grid { grid-template-columns: 1fr; }
  .runtime-synthesis-cell {
    min-width: 220px;
  }
  .key-summary { flex-wrap: wrap; }
  .tenant-count { display: grid; }
  .stacked,
  .chips {
    width: 100%;
    justify-items: start;
    justify-content: flex-start;
  }
  /* The action pills leave no room for the product descriptor next to the name. */
  .brand small { display: none; }
  h1 { font-size: var(--fs-6); }
}
