/*
 * accum — monitoring surface.
 *
 * Built for how a trading screen is read, which is not how a marketing page is.
 *
 * Density is a feature. Generous whitespace costs rows, and a row you have to
 * scroll to is a row you do not see. Hierarchy comes from weight and colour.
 *
 * Numbers are typeset, not written: tabular figures, right-aligned, sign always
 * present. Digits that shift position between refreshes make a changing number
 * look like a different number.
 *
 * Risk is never colour alone. A position in trouble sorts to the top and grows a
 * heavy left edge; colour is confirmation, not the message. A reader who cannot
 * separate red from green still reads the screen correctly, and so does one
 * glancing at it in sunlight.
 *
 * Contrast measured against --bg, not eyeballed:
 *   --fg    15.8:1   numbers and anything load-bearing
 *   --fg-2   9.4:1   labels, secondary figures
 *   --fg-3   7.0:1   units, timestamps
 * Nothing sits below 6:1 and nothing is smaller than 13px. This is read on a
 * phone, at arm's length, to decide whether to stop the bot.
 */

:root {
  color-scheme: dark;
  --bg: #0a0b0d;
  --panel: #121419;
  --panel-2: #1a1d24;
  --line: #262b34;
  --line-strong: #3a4150;
  --fg: #f0f2f5;
  --fg-2: #b9c0cc;
  --fg-3: #99a0ae;
  --up: #3ddc84;
  --down: #ff6b6b;
  --warn: #ffc043;
  --accent: #5aa9ff;
  --idle: #6d7688;
  --mono: ui-monospace, "SF Mono", "Cascadia Mono", "Roboto Mono", Menlo, monospace;
  --sans: system-ui, -apple-system, "Segoe UI", "Noto Sans KR", sans-serif;
  --gap: 10px;
  --radius: 6px;
}

* { box-sizing: border-box; }

html, body {
  margin: 0; padding: 0;
  background: var(--bg); color: var(--fg);
  font-family: var(--sans); font-size: 15px; line-height: 1.45;
  -webkit-text-size-adjust: 100%;
}
/* Never shrink on a small screen — that is the screen being read one-handed to
   decide whether to stop the bot. Narrow layouts stack instead. */
@media (max-width: 640px) { html, body { font-size: 15px; } }

h1, h2, h3 { margin: 0; font-weight: 600; }

.top {
  position: sticky; top: 0; z-index: 20;
  background: var(--bg); border-bottom: 1px solid var(--line);
  padding: 8px 12px 6px;
}
.top-row { display: flex; align-items: center; gap: var(--gap); flex-wrap: wrap; }
.brand { font-family: var(--mono); font-size: 1.05rem; letter-spacing: 0.04em; }
.state-chip {
  font-family: var(--mono); font-size: 0.82rem; padding: 2px 8px;
  border-radius: 999px; border: 1px solid var(--line-strong);
  color: var(--fg-2); white-space: nowrap;
}
.state-chip.is-armed { border-color: var(--warn); color: var(--warn); font-weight: 600; }
.state-chip.is-idle { border-color: var(--line); color: var(--fg-3); }
.spacer { flex: 1 1 auto; }

.button {
  appearance: none; font: inherit; font-size: 0.9rem; font-weight: 600;
  padding: 5px 14px; border-radius: var(--radius);
  border: 1px solid var(--line-strong); background: var(--panel-2);
  color: var(--fg); cursor: pointer; white-space: nowrap;
}
.button:hover:not(:disabled) { background: #232833; }
.button:disabled { opacity: 0.55; cursor: default; }
.button.is-armed { border-color: var(--warn); color: var(--warn); }
.button-danger { border-color: var(--down); border-width: 2px; color: var(--down); }
.button-danger:hover:not(:disabled) { background: #2b1518; }

.venues {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(136px, 1fr));
  gap: 4px; margin-top: 7px;
}
.venue {
  display: flex; align-items: baseline; gap: 6px; padding: 3px 7px;
  border-radius: 4px; background: var(--panel);
  border-left: 3px solid var(--idle); font-size: 0.8rem; min-width: 0;
}
.venue.is-up { border-left-color: var(--up); }
.venue.is-down { border-left-color: var(--down); }
.venue-name {
  color: var(--fg-2); font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.venue-stat { font-family: var(--mono); color: var(--fg-3); margin-left: auto; }

.tabs {
  display: flex; gap: 2px; padding: 0 12px;
  border-bottom: 1px solid var(--line); background: var(--bg);
}
.tab {
  appearance: none; font: inherit; font-size: 0.95rem; font-weight: 600;
  padding: 9px 16px; background: none; border: none;
  border-bottom: 2px solid transparent; color: var(--fg-3); cursor: pointer;
}
.tab:hover { color: var(--fg-2); }
.tab.is-active { color: var(--fg); border-bottom-color: var(--accent); }
.tab-count { font-family: var(--mono); font-size: 0.78rem; color: var(--fg-3); margin-left: 5px; }

.panel-body { padding: 10px 12px 40px; }
[hidden] { display: none !important; }

.figures {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(112px, 1fr));
  gap: 1px; background: var(--line); border: 1px solid var(--line);
  border-radius: var(--radius); overflow: hidden; margin-bottom: var(--gap);
}
.figure { background: var(--panel); padding: 7px 10px; min-width: 0; }
.figure-label {
  font-size: 0.76rem; color: var(--fg-3);
  text-transform: uppercase; letter-spacing: 0.05em; white-space: nowrap;
}
.figure-value {
  font-family: var(--mono); font-size: 1.18rem; font-weight: 600;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.figure-sub { font-size: 0.76rem; color: var(--fg-3); font-family: var(--mono); }

.scroll-x { overflow-x: auto; border-radius: var(--radius); border: 1px solid var(--line); }
table { border-collapse: collapse; width: 100%; font-size: 0.86rem; }
thead th {
  background: var(--panel-2); color: var(--fg-3); font-weight: 600;
  font-size: 0.76rem; text-transform: uppercase; letter-spacing: 0.04em;
  text-align: left; padding: 6px 9px; border-bottom: 1px solid var(--line-strong);
  white-space: nowrap;
}
tbody td { padding: 5px 9px; border-bottom: 1px solid var(--line); white-space: nowrap; color: var(--fg-2); }
tbody tr { background: var(--panel); }
tbody tr:hover { background: var(--panel-2); }

.num { font-family: var(--mono); font-variant-numeric: tabular-nums; text-align: right; color: var(--fg); }
th.num { text-align: right; }
.key { font-family: var(--mono); color: var(--fg); font-weight: 600; }
.up { color: var(--up); }
.down { color: var(--down); }
.dim { color: var(--fg-3); }

tbody tr.is-alert td:first-child { box-shadow: inset 3px 0 0 var(--down); }
tbody tr.is-alert td { color: var(--fg); }
tbody tr.is-good td:first-child { box-shadow: inset 3px 0 0 var(--up); }

.bar-track {
  display: inline-block; width: 56px; height: 7px; border-radius: 2px;
  background: var(--line); vertical-align: middle; overflow: hidden;
}
.bar { display: block; height: 7px; border-radius: 2px; background: var(--accent); }
.bar.is-good { background: var(--up); }
.bar.is-bad { background: var(--down); }

.reasons { color: var(--fg-3); font-size: 0.8rem; }
.empty { padding: 18px 10px; color: var(--fg-3); text-align: center; font-size: 0.88rem; }

.cards {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(244px, 1fr));
  gap: var(--gap); margin-bottom: var(--gap);
}
.card { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); padding: 9px 11px; }
.card-head { display: flex; align-items: baseline; gap: 8px; margin-bottom: 6px; }
.card-title { font-family: var(--mono); font-weight: 600; color: var(--fg); }
.card-stage {
  margin-left: auto; font-size: 0.76rem; padding: 1px 7px; border-radius: 999px;
  border: 1px solid var(--line-strong); color: var(--fg-2); white-space: nowrap;
}
.card-stage.stage-live { border-color: var(--warn); color: var(--warn); }
.card-stage.stage-ready { border-color: var(--accent); color: var(--accent); }
.card-detail { font-size: 0.8rem; color: var(--fg-3); margin-bottom: 7px; }
.steps { display: flex; gap: 2px; margin-bottom: 7px; }
.step { flex: 1; height: 4px; border-radius: 2px; background: var(--line); }
.step.is-done { background: var(--accent); }
.step.is-live { background: var(--warn); }
.card-stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }
.card-stat-label { color: var(--fg-3); font-size: 0.72rem; }
.card-stat-value { color: var(--fg); font-family: var(--mono); font-variant-numeric: tabular-nums; font-size: 0.88rem; }

.banner {
  margin: 0 12px 8px; padding: 7px 11px; border-radius: var(--radius);
  border: 1px solid var(--line-strong); background: var(--panel);
  font-size: 0.86rem; color: var(--fg-2);
}
.banner.is-bad { border-color: var(--down); color: var(--fg); }

.section-title {
  font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--fg-3); margin: 16px 0 6px;
}

.login { max-width: 320px; margin: 14vh auto; padding: 0 16px; }
.login h1 { font-family: var(--mono); letter-spacing: 0.06em; margin-bottom: 4px; }
.login .tagline { color: var(--fg-3); font-size: 0.88rem; margin: 0 0 18px; }
.login input {
  display: block; width: 100%; font: inherit; padding: 9px 11px; margin-bottom: 8px;
  border-radius: var(--radius); border: 1px solid var(--line-strong);
  background: var(--panel); color: var(--fg);
}
.login button { width: 100%; padding: 9px; }
.login .error { color: var(--down); min-height: 1.4em; margin-top: 10px; }

/* A venue at its position cap. Colour is confirmation; the count next to it is
   the message, which is why it is rendered as n/max and not as a badge. */
.venue-stat.is-full { color: var(--warn); font-weight: 600; }

/* =========================================================================
   Responsive layer.

   The screen this runs on is not one screen. It is a 4K monitor at a desk, a
   laptop, and a phone held one-handed to decide whether to stop the bot — and
   the phone is the case that matters most, because that is when the decision
   is urgent and the screen is worst.

   Three things scale, in order of how much they matter:

   1. Type, fluidly. A fixed 15px is small at 4K and cramped at 360px. The
      clamp below tracks viewport width between those, so the same layout is
      read at arm's length on a phone and across a desk on a monitor.

   2. Columns, by priority. A table of eleven columns on a 390px screen is a
      horizontal scroll, and a number you have to scroll to is a number you do
      not read. Low-priority columns are dropped at each breakpoint rather than
      shrunk, so what remains stays full size. What survives to the narrowest
      width is what a stop-or-continue decision needs: which token, how
      one-directional, which way it is moving, and what the rule says.

   3. Density, mildly. Padding and gaps grow on large screens where there is
      room and tighten on small ones where rows are the scarce thing.

   Columns are hidden by position, and each rule names the column it drops so
   the mapping can be checked against index.html without counting cells.
   ========================================================================= */

html, body {
  /* 360px → 14px, 1440px → 16px, 2560px+ → 18px. */
  font-size: clamp(14px, 0.68vw + 11.6px, 18px);
}
@media (max-width: 640px) { html, body { font-size: clamp(14px, 3.6vw, 15.5px); } }

body {
  /* Ultra-wide gets a readable measure rather than 3,800px rows: tracking a
     value across that width costs more than the extra columns are worth. */
  max-width: 2200px;
  margin-inline: auto;
}

/* Density follows the room available. */
@media (min-width: 1600px) {
  :root { --gap: 14px; }
  .panel-body { padding: 14px 20px 48px; }
  .top { padding: 11px 20px 8px; }
  .tabs { padding: 0 20px; }
  tbody td { padding: 7px 12px; }
  thead th { padding: 8px 12px; }
}
@media (max-width: 520px) {
  :root { --gap: 8px; }
  .panel-body { padding: 8px 8px 40px; }
  .top { padding: 7px 9px 5px; }
  .tabs { padding: 0 4px; }
  .tab { padding: 9px 11px; }
  tbody td { padding: 6px 7px; }
  thead th { padding: 6px 7px; }
  .banner { margin-inline: 8px; }
}

/* A finger is not a cursor. */
@media (pointer: coarse) {
  .button { min-height: 44px; padding-inline: 16px; }
  .tab { min-height: 44px; }
}

/* Landscape phone: the header is competing with the rows for a 380px-tall
   viewport, and the rows win. */
@media (max-height: 520px) and (orientation: landscape) {
  .top { position: static; padding-bottom: 4px; }
  .venues { display: none; }
  .figures { display: none; }
}

/* The venue strip: eight cells stay legible by getting narrower, then fewer
   per row. Below 400px the stat drops and the name carries the state, which
   the left border already encodes. */
@media (max-width: 400px) {
  .venues { grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); }
  .venue-stat:not(.is-full) { display: none; }
}

/* --- column priority ---------------------------------------------------- */

/* 매집: 시장 토큰 나이 깊이 churn 상승 체결 지갑 최대매수 점수 판정 */
@media (max-width: 1000px) {
  #panel-flow > .scroll-x th:nth-child(9), #panel-flow > .scroll-x td:nth-child(9),  /* 최대매수 */
  #panel-flow > .scroll-x th:nth-child(8), #panel-flow > .scroll-x td:nth-child(8)   /* 지갑 */
  { display: none; }
}
@media (max-width: 700px) {
  #panel-flow > .scroll-x th:nth-child(10), #panel-flow > .scroll-x td:nth-child(10), /* 점수 */
  #panel-flow > .scroll-x th:nth-child(7), #panel-flow > .scroll-x td:nth-child(7),   /* 체결 */
  #panel-flow > .scroll-x th:nth-child(4), #panel-flow > .scroll-x td:nth-child(4)    /* 깊이 */
  { display: none; }
}
@media (max-width: 460px) {
  #panel-flow > .scroll-x th:nth-child(1), #panel-flow > .scroll-x td:nth-child(1)    /* 시장 */
  { display: none; }
}

/* 포지션: 시장 토큰 보유 미실현 최고 트레일까지 진입churn 진입상승 투입 */
@media (max-width: 1000px) {
  #panel-positions > .scroll-x:first-of-type th:nth-child(8),
  #panel-positions > .scroll-x:first-of-type td:nth-child(8),   /* 진입상승 */
  #panel-positions > .scroll-x:first-of-type th:nth-child(7),
  #panel-positions > .scroll-x:first-of-type td:nth-child(7)    /* 진입churn */
  { display: none; }
}
@media (max-width: 700px) {
  #panel-positions > .scroll-x:first-of-type th:nth-child(9),
  #panel-positions > .scroll-x:first-of-type td:nth-child(9),   /* 투입 = 클립, 항상 같다 */
  #panel-positions > .scroll-x:first-of-type th:nth-child(5),
  #panel-positions > .scroll-x:first-of-type td:nth-child(5)    /* 최고 — 트레일까지가 이미 담고 있다 */
  { display: none; }
}

/* 최근 청산: 시장 토큰 사유 보유 최고 회수 손익 */
@media (max-width: 700px) {
  #panel-positions > .scroll-x:last-of-type th:nth-child(5),
  #panel-positions > .scroll-x:last-of-type td:nth-child(5),    /* 최고 */
  #panel-positions > .scroll-x:last-of-type th:nth-child(4),
  #panel-positions > .scroll-x:last-of-type td:nth-child(4)     /* 보유 */
  { display: none; }
}

/* 섀도: 시장 토큰 churn 상승 통과 최고 현재 보유 */
@media (max-width: 700px) {
  #panel-shadow th:nth-child(8), #panel-shadow td:nth-child(8),  /* 보유 */
  #panel-shadow th:nth-child(6), #panel-shadow td:nth-child(6)   /* 최고 */
  { display: none; }
}

/* Cards stop being a grid before they get too narrow to hold three stats. */
@media (max-width: 420px) {
  .cards { grid-template-columns: 1fr; }
  .figures { grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); }
}

/* Wide enough that the tables never need their scroller: remove the border it
   would otherwise draw around content that fits. */
@supports (width: 1px) {
  .scroll-x { overscroll-behavior-x: contain; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}

/* viewport-fit=cover lets the page reach under a notch, which is what makes the
   sticky header sit flush at the top. The insets put the content back inside. */
.top { padding-left: max(12px, env(safe-area-inset-left)); padding-right: max(12px, env(safe-area-inset-right)); }
.panel-body { padding-bottom: max(40px, env(safe-area-inset-bottom)); }
