/* Tokens mirror predictivelayer.io: true black, stepped greys so panels
   separate without a visible border, and green kept for accents and data
   rather than for buttons. Values copied from the site's :root so the two
   surfaces stay in step. */
/* Same self-hosted wordmark faces as predictivelayer.io, so the app header
   reads as the same brand rather than a monospace stand-in. */
@font-face {
  font-family: "Wordmark";
  src: url("/static/wordmark.woff2") format("woff2");
  font-weight: 600; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "WordmarkZH";
  src: url("/static/wordmark-zh.woff2") format("woff2");
  font-weight: 600; font-style: normal; font-display: swap;
}

:root {
  --bg: #000;
  --surface: #0c0c0c;
  --surface-2: #131313;
  --border: #1e1e1e;
  --border-strong: #2a2a2a;
  --ink: #fff;
  --muted: #a3a3a3;
  --dim: #808080;
  --accent: #309d4b;
  --accent-hover: #277f3d;
  --accent-soft: rgba(48, 157, 75, 0.16);
  /* Lifted green. #309d4b on black is too dark to read at small sizes, so
     small text and links use this instead of --accent. */
  --accent-ink: #4fbc6c;
  --warn-bg: rgba(217, 150, 43, 0.13);
  --warn-border: rgba(217, 150, 43, 0.34);
  --warn-ink: #e9b84a;
  --err-bg: rgba(229, 72, 77, 0.12);
  --err-border: rgba(229, 72, 77, 0.34);
  --err-ink: #f08d90;
  --radius: 10px;
  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
}

* { box-sizing: border-box; }

/* .field and friends set display, which beats the [hidden] attribute from
   the UA stylesheet. Without this the target, task and mode fields show
   before any file is chosen. */
[hidden] { display: none !important; }

body {
  margin: 0;
  font-family: var(--font);
  background: var(--bg);
  color: var(--ink);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

.wrap { max-width: 1060px; margin: 0 auto; padding: 0 24px; }

/* Top bar */
.topbar {
  background: var(--surface);
  border-bottom: 1px solid var(--border);
}
.topbar-inner {
  display: flex;
  align-items: center;
  gap: 12px;
  height: 56px;
}
.wordmark {
  font-family: "Wordmark", var(--font);
  font-size: 1.13rem;
  font-weight: 600;
  color: var(--ink);
  letter-spacing: -0.005em;
}
:lang(zh) .wordmark {
  font-family: "WordmarkZH", "PingFang SC", "Microsoft YaHei", "Heiti SC", var(--font);
  letter-spacing: .02em;
}
.wordmark .tld { color: var(--accent-ink); }
.wordmark .wordmark-domain {
  margin-left: 8px;
  font-size: 11px;
  font-weight: 500;
  color: var(--muted);
}
.badge {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  padding: 2px 10px;
}

/* Intro */
.intro { padding: 48px 0 32px; max-width: 640px; }
.intro h1 { font-size: 28px; line-height: 1.25; margin: 0 0 12px; font-weight: 650; }
.intro p { margin: 0; color: var(--muted); font-size: 15px; }

/* Step cards */
.steps {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
  align-items: stretch;
}
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 20px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.card-head { display: flex; align-items: center; gap: 10px; }
.card-head h2 { font-size: 15px; margin: 0; font-weight: 650; }
.step-num {
  width: 24px; height: 24px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 6px;
  background: var(--accent-soft);
  color: var(--accent-ink);
  font-size: 13px; font-weight: 700;
  flex: none;
}
.card-sub { margin: 0; font-size: 13px; color: var(--muted); }

/* Dropzone */
.dropzone {
  border: 1.5px dashed var(--border-strong);
  border-radius: var(--radius);
  padding: 22px 16px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  text-align: center;
  cursor: pointer;
  color: var(--muted);
  transition: border-color 120ms ease, background 120ms ease;
}
.dropzone:hover { border-color: var(--accent); }
.dropzone.dragover { border-color: var(--accent); background: var(--accent-soft); }
.dropzone.has-file { border-style: solid; border-color: var(--accent); color: var(--ink); }
.dropzone .icon { width: 22px; height: 22px; color: var(--accent); }
.dz-title { font-size: 13.5px; }
.dz-title .link { color: var(--accent-ink); text-decoration: underline; }
.dz-meta { font-size: 12px; color: var(--muted); font-family: var(--mono); }
.dropzone.has-file .dz-meta { color: var(--ink); }

/* Fields */
.field { display: flex; flex-direction: column; gap: 6px; }
.field-label { font-size: 12.5px; font-weight: 600; color: var(--muted); }
select {
  font: inherit;
  font-size: 13.5px;
  padding: 8px 10px;
  border: 1px solid var(--border-strong);
  border-radius: 6px;
  background: var(--surface);
  color: var(--ink);
  width: 100%;
}
select:focus { outline: 2px solid var(--accent-soft); border-color: var(--accent-ink); }

/* Segmented control */
.segmented {
  display: flex;
  border: 1px solid var(--border-strong);
  border-radius: 6px;
  overflow: hidden;
}
.segmented button {
  flex: 1;
  font: inherit;
  font-size: 12.5px;
  padding: 7px 4px;
  background: var(--surface);
  color: var(--muted);
  border: none;
  cursor: pointer;
}
.segmented button + button { border-left: 1px solid var(--border-strong); }
.segmented button.active { background: var(--accent); color: #05170b; font-weight: 600; }
.segmented button:not(.active):hover { background: var(--surface-2); color: var(--ink); }

/* Buttons */
.btn {
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  border-radius: 6px;
  padding: 10px 16px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  border: 1px solid transparent;
}
.btn.primary { background: #fff; color: #000; width: 100%; }
.btn.primary:hover:not(:disabled) { background: #d9d9d9; }
.btn.primary:disabled { background: var(--surface-2); color: var(--dim); cursor: not-allowed; }
.btn.secondary { background: var(--surface); border-color: var(--border-strong); color: var(--ink); }
.btn.secondary:hover { border-color: var(--border-strong); background: var(--surface-2); }
.run-note { margin: 0; font-size: 12px; color: var(--muted); }

.spinner {
  width: 14px; height: 14px;
  border: 2px solid rgba(0, 0, 0, 0.25);
  border-top-color: #000;
  border-radius: 50%;
  animation: spin 700ms linear infinite;
  flex: none;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* Alerts */
.alert {
  border-radius: var(--radius);
  padding: 12px 14px;
  font-size: 13.5px;
  margin-top: 20px;
}
.alert.error { background: var(--err-bg); border: 1px solid var(--err-border); color: var(--err-ink); }
.alert.warn { background: var(--warn-bg); border: 1px solid var(--warn-border); color: var(--warn-ink); }
.alert ul { margin: 0; padding-left: 18px; }
.alert li + li { margin-top: 4px; }

/* Results */
#results { margin-top: 28px; }
.results-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 12px;
}
.results-head h2 { font-size: 17px; margin: 0; font-weight: 650; }
.chips { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 4px; }
.chip {
  font-size: 12.5px;
  font-family: var(--mono);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 4px 12px;
  color: var(--muted);
}

.table-wrap {
  margin-top: 12px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: auto;
  max-height: 480px;
}
table { border-collapse: collapse; width: 100%; font-size: 13px; }
thead th {
  position: sticky;
  top: 0;
  background: var(--surface);
  border-bottom: 1px solid var(--border-strong);
  text-align: left;
  font-weight: 650;
  padding: 9px 12px;
  white-space: nowrap;
}
tbody td {
  border-bottom: 1px solid var(--border);
  padding: 7px 12px;
  white-space: nowrap;
  max-width: 260px;
  overflow: hidden;
  text-overflow: ellipsis;
}
tbody tr:last-child td { border-bottom: none; }
tbody tr:hover td { background: var(--surface-2); }
.pred-col { background: var(--accent-soft); }
thead th.pred-col { color: var(--accent-ink); }
.table-note { font-size: 12.5px; color: var(--muted); margin: 8px 2px 0; }

/* Footer */
.footer {
  margin: 56px 0 32px;
  padding-top: 16px;
  border-top: 1px solid var(--border);
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px;
  font-size: 12.5px;
  color: var(--muted);
}
.footer a { color: var(--muted); }

.icon.small { width: 15px; height: 15px; }

/* Same-file scoring option */
.or-sep {
  text-align: center;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
}
.check {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  font-size: 13px;
  cursor: pointer;
}
.check input { margin-top: 2px; accent-color: var(--accent); }
.hint { margin: 0; font-size: 12px; color: var(--muted); }
.dropzone.disabled { opacity: 0.45; pointer-events: none; }

/* Metrics panel */
.metrics { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 14px; }
.stat {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 12px 18px;
  min-width: 140px;
}
.stat-label {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
}
.stat-value { font-family: var(--mono); font-size: 20px; margin-top: 3px; }
.metrics-caption { font-size: 12px; color: var(--muted); margin: 6px 2px 0; }

/* The verdict card. Wider than the plain numbers because it carries a
   sentence, and coloured so the reading is obvious before the words are. */
.stat.grade { min-width: 230px; flex: 0 1 320px; border-color: var(--border-strong); }
.stat.grade .stat-value { font-family: inherit; font-weight: 650; }
.grade-note { font-size: 12px; color: var(--muted); margin-top: 4px; line-height: 1.35; }
.grade-misconfigured { border-color: #7a2f2f; }
.grade-misconfigured .stat-value { color: #f08a8a; }
.grade-moderate .stat-value,
.grade-good .stat-value { color: var(--accent-ink); }
.grade-great .stat-value,
.grade-strong .stat-value,
.grade-excellent .stat-value { color: var(--accent); }
.grade-warning {
  flex-basis: 100%;
  margin: 0;
  font-size: 12px;
  color: #e8b96a;
}

/* Class picker, shown only when the target has more than two classes. */
.class-pick { flex-basis: 100%; }

/* Charts. Hand-written SVG on a 0-100 grid, stretched by the viewBox, so
   the stroke is set to stay one pixel wide however far it is stretched. */
.charts { display: flex; gap: 14px; flex-wrap: wrap; margin-top: 14px; }
.chart {
  margin: 0;
  flex: 1 1 240px;
  min-width: 220px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 12px 14px 10px;
}
.chart figcaption {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
  margin-bottom: 8px;
  display: flex;
  justify-content: space-between;
  gap: 8px;
}
.chart-sub { font-family: var(--mono); text-transform: none; letter-spacing: 0; color: var(--text); }
/* The y label is rotated text in the margin rather than SVG text, because
   the plot is stretched by its viewBox and any text inside would stretch
   with it. */
.chart-plot { display: flex; align-items: stretch; gap: 6px; }
.chart-plot svg { display: block; width: 100%; height: 120px; }
.axis-y {
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  font-size: 10px;
  color: var(--muted);
  text-align: center;
  white-space: nowrap;
}
.axis-x { font-size: 10px; color: var(--muted); text-align: center; margin-top: 5px; }
.chart-line { fill: none; stroke: var(--accent-ink); stroke-width: 1.6; vector-effect: non-scaling-stroke; }
.chart-ref { stroke: var(--border-strong); stroke-width: 1; stroke-dasharray: 3 3; vector-effect: non-scaling-stroke; }
.chart-bar { fill: var(--accent); }
.chart-dot { fill: var(--accent-ink); fill-opacity: 0.55; }
/* The scatter keeps its aspect ratio rather than filling the card. Stretched,
   its dots would come out as ellipses and its y=x line would not sit at 45
   degrees, which is the whole point of reading it. */
.chart.square svg { width: auto; margin: 0 auto; aspect-ratio: 1; }

/* Progress bar for a run that reports where it has got to. */
.progress { margin-top: 12px; }
.progress-track {
  height: 5px;
  border-radius: 3px;
  background: var(--border);
  overflow: hidden;
}
.progress-fill {
  height: 100%;
  width: 0;
  background: var(--accent);
  transition: width .3s ease;
}
.progress-step { margin: 7px 0 0; font-size: 12px; color: var(--muted); }

@media (max-width: 860px) {
  .steps { grid-template-columns: 1fr; }
  .intro { padding: 32px 0 24px; }
  .intro h1 { font-size: 23px; }
}

/* Sign-in (only rendered when the server sets a Clerk key) */
.auth-slot { margin-left: auto; display: flex; align-items: center; }
/* Written twice on purpose. Clerk overwrites the class attribute of the
   element it mounts into with its own cl-rootBox classes, so the class
   selector stops matching the moment the card appears and the card is left
   sitting against the left edge. The id survives, and an id also outranks
   the width Clerk's own rule puts on that element. */
.signin-gate,
#signin-gate { display: flex; justify-content: center; width: auto; padding: 3rem 0; }

/* Language switcher */
.lang-switch {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-left: 14px;
}
.lang-globe { color: var(--muted); flex: none; }
.lang-link {
  font-size: 12px;
  font-weight: 600;
  color: var(--muted);
  text-decoration: none;
}
.lang-link:hover { color: var(--accent-ink); }
.lang-link.current {
  color: var(--ink);
  opacity: 0.55;
  pointer-events: none;
  cursor: default;
}
.lang-divider {
  width: 1px;
  height: 12px;
  background: var(--border-strong);
}

/* Hidden until i18n.js has translated the page once, so English never
   flashes before a saved/URL Chinese preference is applied. */
body.i18n-pending { visibility: hidden; }

/* Local vs hosted copy. The server stamps <body class="is-hosted"> when a
   Clerk key is set, so the right wording is in place before first paint
   rather than swapping after the /api/config round trip. */
.hosted-only { display: none; }
body.is-hosted .local-only { display: none; }
body.is-hosted .hosted-only { display: revert; }

/* Logo mark in the top bar, same asset and size as the marketing site. */
.wordmark { display: inline-flex; align-items: center; text-decoration: none; }
.wordmark:hover { opacity: .82; }
.wordmark-mark { height: 20px; width: auto; margin-right: 9px; display: block; flex: none; }

/* Clerk's card renders into the light DOM with cl- class names, so hover
   states it will not take through the appearance object can be set here. */
.cl-formButtonPrimary:hover { background: #d9d9d9 !important; }
