:root {
  --bg: #0d1117;
  --panel: #131a24;
  --line: #1f2833;
  --text: #d7dee8;
  --muted: #7d8895;
  --up: #2ebd85;
  --dn: #f0524d;
  --accent: #4aa3ff;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
  /* dvh, not vh: on a phone the URL bar is part of vh, so the layout is taller
     than the screen while the bar is showing and the bottom is clipped. */
  height: 100dvh;
  background: var(--bg);
  color: var(--text);
  font: 13px/1.45 -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
}

body { display: flex; flex-direction: column; }

/* ------------------------------------------------------------------ header */
header {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  background: var(--panel);
  border-bottom: 1px solid var(--line);
  flex: 0 0 auto;
}

.brand { font-size: 15px; letter-spacing: .3px; color: var(--muted); }
.brand b { color: var(--text); font-weight: 600; }
.spacer { flex: 1; }

.symbox input {
  width: 150px;
  padding: 5px 8px;
  background: #0b1017;
  border: 1px solid var(--line);
  border-radius: 5px;
  color: var(--text);
  font: 600 13px/1 ui-monospace, "Cascadia Mono", Consolas, monospace;
  letter-spacing: .5px;
  text-transform: uppercase;
}
.symbox input:focus { outline: none; border-color: var(--accent); }

.price { font: 600 15px/1 ui-monospace, Consolas, monospace; min-width: 96px; }
.price.up { color: var(--up); }
.price.dn { color: var(--dn); }

.tfgroup { display: flex; gap: 2px; align-items: center; }
.tfgroup button {
  background: transparent;
  border: 1px solid transparent;
  color: var(--muted);
  padding: 4px 7px;
  border-radius: 4px;
  cursor: pointer;
  font: 12px/1 inherit;
}
.tfgroup button:hover { color: var(--text); background: #1a2330; }
.tfgroup button.on { color: #fff; background: #23405f; border-color: #2f5b87; }

.btn {
  background: #1a2330; border: 1px solid var(--line); color: var(--muted);
  border-radius: 4px; padding: 4px 9px; cursor: pointer; font: 12px/1 inherit;
}
.btn:hover { color: var(--text); }
.btn.on { background: #23405f; color: #fff; border-color: #2f5b87; }

/* Folds the layer/indicator bars away. Only on narrow screens — on a desktop
   they cost one row each and are better left open. */
#barsBtn { display: none; }

#conn { width: 8px; height: 8px; border-radius: 50%; background: #55606d; }
#conn.on { background: var(--up); }
#conn.off { background: var(--dn); }

/* -------------------------------------------------------------------- main */
main { flex: 1 1 auto; display: flex; min-height: 0; overflow: hidden; }

#chartPane { flex: 1 1 auto; display: flex; flex-direction: column;
             min-width: 0; min-height: 0; }

#indicators {
  display: flex; gap: 8px; flex-wrap: wrap; align-items: center;
  padding: 6px 12px; border-bottom: 1px solid var(--line); background: #0e141c;
}
#indicators label { display: inline-flex; align-items: center; gap: 5px;
  color: var(--muted); cursor: pointer; font-size: 12px; }
#indicators select {
  background: #0b1017; border: 1px solid var(--line); border-radius: 4px;
  color: var(--text); font: 11px/1.4 inherit; padding: 2px 4px;
}
#indicators select:focus { outline: none; border-color: var(--accent); }
#indicators .sep { width: 1px; align-self: stretch; background: var(--line); margin: 0 4px; }
#indicators .note { color: #6d7784; font-size: 11px; }
/* The EMA toggles moved down here from the header; the swatch is a short line,
   not a dot, because that is what it stands for on the chart. */
#indicators label.ema i { width: 10px; height: 2px; display: inline-block; }
#indicators input { accent-color: var(--accent); }
/* The three pivot-S/R timeframes read as one control: a label and three boxes
   tight against each other, not three unrelated checkboxes. */
#indicators .srlab { color: var(--muted); font-size: 12px; cursor: help; }
#indicators label.srtf { gap: 3px; margin-left: -4px; }
/* One channel per row, inside the feed pane it filters. The pane is 340px, so
   the name and its floor box both fit a line and the eye reads the list of
   channels down the side instead of hunting a wrapped ribbon.
   `flex: 0 0 auto` and a pixel ceiling, NOT a percentage: the list below is a
   flex item whose content is thousands of pixels tall, so anything shrinkable
   here gets crushed to one row by the negative free space that content creates
   (measured — it looked like the toggles had vanished). Ten channels fit inside
   the ceiling outright; a shorter pane scrolls this block instead of pushing
   the alerts it is meant to filter off the screen. */
#layers {
  display: flex; flex-direction: column; gap: 3px; align-items: stretch;
  padding: 6px 10px; border-bottom: 1px solid var(--line); background: #10161f;
  flex: 0 0 auto; max-height: 246px; overflow-y: auto; scrollbar-width: thin;
}
#layers label {
  display: flex; align-items: center; gap: 5px;
  color: var(--muted); cursor: pointer; font-size: 12px;
}
#layers label .fname { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#layers label .dot {
  width: 9px; height: 9px; border-radius: 50%; display: inline-block; flex: 0 0 auto;
}
#layers input { accent-color: var(--accent); }

/* Per-feed floor, e.g. "≥ × median 5" on mk_liq-alert. Narrow on purpose: it
   sits inside the channel's own label so it reads as that channel's setting. */
#layers .minv {
  width: 62px; margin-left: auto; flex: 0 0 auto; padding: 2px 4px;
  background: #0b1017; border: 1px solid var(--line); border-radius: 4px;
  color: var(--text); font: 11px/1.3 ui-monospace, Consolas, monospace;
}
#layers .minv::placeholder { color: #4c5663; }
#layers .minv:focus { outline: none; border-color: var(--accent); width: 96px; }
#layers .minv:not(:placeholder-shown) { border-color: var(--accent); color: #fff; }

/* The chart canvas is transparent so the trend background can sit UNDER it —
   the same place Pine's bgcolor() draws. #chart carries the dark ground. */
#chart { position: relative; flex: 1 1 auto; min-height: 0; background: var(--bg); }

#trendLayer { position: absolute; inset: 0; z-index: 0; pointer-events: none; overflow: hidden; }
#trendLayer .band { position: absolute; top: 0; bottom: 0; }

#smcLayer { position: absolute; inset: 0; z-index: 2; pointer-events: none; overflow: hidden; }

/* Boom Hunter Pro pane. lightweight-charts 4 has no second pane, so this is a
   canvas under the chart that reads the chart's own time scale for x. */
#bhpPane { position: relative; flex: 0 0 186px; min-height: 0;
           border-top: 1px solid var(--line); background: var(--bg); }
/* The legend gets a strip of its own rather than floating over the canvas: the
   original hangs its Long/Short labels off the very top of the pane, which is
   exactly where a floating legend would sit. */
#bhpLegend { position: absolute; left: 8px; top: 0; height: 16px; line-height: 16px;
             font-size: 11px; color: var(--muted); pointer-events: none;
             white-space: nowrap; }
#bhpCanvas { position: absolute; left: 0; right: 0; top: 16px; bottom: 0;
             width: 100%; height: calc(100% - 16px); }
/* Volumetric order block: the zone the structure break was launched from. */
#smcLayer .ob {
  position: absolute; border: 1px solid var(--c);
  background: color-mix(in srgb, var(--c) 12%, transparent);
}
#smcLayer .ob b {
  position: absolute; right: 2px; top: -1px; font: 600 9px/1.4 ui-monospace, Consolas, monospace;
  color: var(--c); opacity: .85; font-weight: 600;
}
/* Structure break: the swept pivot level, from the pivot to the bar that broke it. */
#smcLayer .bos { position: absolute; height: 0; border-top: 1px dashed var(--c); }
#smcLayer .bos i {
  position: absolute; right: 0; top: -13px; white-space: nowrap;
  font: 600 9px/1.2 ui-monospace, Consolas, monospace; color: var(--c);
  font-style: normal; background: #0d1117cc; padding: 0 3px; border-radius: 2px;
}

/* Pivot S/R, one set per timeframe. Colour says what the level is (major or
   minor, support or resistance), the dash pattern says which timeframe it came
   from, and the opacity says how far down the list it is. */
#srtfLayer { position: absolute; inset: 0; z-index: 2; pointer-events: none; overflow: hidden; }
#srtfLayer .lvl {
  position: absolute; left: 0; right: 0; height: 0;
  border-top: var(--w, 1px) var(--dash, solid) var(--c);
  opacity: var(--o, 1);
}
#srtfLayer .lvl b {
  position: absolute; right: 2px; top: -12px; white-space: nowrap; font-weight: 600;
  font: 600 9px/1.2 ui-monospace, Consolas, monospace; color: var(--c);
  background: #0d1117cc; padding: 0 3px; border-radius: 2px;
}

#evtLayer { position: absolute; inset: 0; pointer-events: none; z-index: 3; }

/* Alert dots sit at their exact price/time — a chart marker can only attach to
   a bar, which would put an RSI print or a pivot touch on the wrong price. */
#evtLayer .evt {
  position: absolute;
  width: var(--sz, 9px);
  height: var(--sz, 9px);
  margin-left: calc(var(--sz, 9px) / -2);
  margin-top: calc(var(--sz, 9px) / -2);
  border-radius: 50%;
  background: var(--c, #fff);
  border: 1px solid rgba(0, 0, 0, .55);
  box-shadow: 0 0 5px var(--c, #fff);
  pointer-events: auto;
  cursor: help;
}
#evtLayer .evt.sq { border-radius: 2px; }
#evtLayer .evt.dia { border-radius: 2px; transform: rotate(45deg); }
#evtLayer .evt.mkt {
  width: 2px; margin-left: -1px; border-radius: 0; height: 14px;
  margin-top: 0; box-shadow: none; opacity: .8;
}

/* Measure tool. The capture layer only takes pointer events while the tool is
   armed — otherwise the drag would pan the chart instead of measuring. */
#measureCap { position: absolute; inset: 0; z-index: 5; pointer-events: none; }
#measureCap.armed { pointer-events: auto; cursor: crosshair; }

#measureBox {
  position: absolute; z-index: 5; pointer-events: none;
  border: 1px solid var(--m, #4aa3ff);
  background: color-mix(in srgb, var(--m, #4aa3ff) 14%, transparent);
}
#measureLbl {
  position: absolute; left: 50%; transform: translateX(-50%);
  bottom: 100%; margin-bottom: 5px; white-space: pre;
  background: var(--m, #4aa3ff); color: #06121f;
  font: 600 11px/1.35 ui-monospace, Consolas, monospace;
  padding: 3px 7px; border-radius: 4px; text-align: center;
}
#measureBox.flip #measureLbl { bottom: auto; top: 100%; margin: 5px 0 0; }

#legend {
  position: absolute; left: 10px; top: 8px; z-index: 4;
  color: var(--muted); font-size: 11px; pointer-events: none;
  display: flex; gap: 10px; flex-wrap: wrap;
}
#legend .sym { color: var(--text); font-weight: 600; letter-spacing: .4px; }
#legend .fl b { font-weight: 600; margin-left: 3px; }
#legend .fl b.zero { opacity: .45; font-weight: 400; }

#dotInfo {
  position: absolute; z-index: 6; max-width: 230px; white-space: pre-line;
  background: #0b1017ee; border: 1px solid var(--line); border-radius: 5px;
  padding: 6px 8px; font-size: 11px; color: var(--text); line-height: 1.4;
  box-shadow: 0 6px 18px rgba(0,0,0,.6);
}

/* --------------------------------------------------------------- feed pane */
#feedPane {
  flex: 0 0 340px; display: flex; flex-direction: column;
  border-left: 1px solid var(--line); background: var(--panel); min-height: 0;
}
#feedPane.collapsed { flex-basis: auto; }
/* Collapsing folds the whole pane, toggles included — otherwise "collapsed"
   would still be 340px of controls and the chart would gain nothing. */
#feedPane.collapsed #feed,
#feedPane.collapsed #layers { display: none; }

.feedHead {
  display: flex; align-items: center; gap: 8px;
  padding: 7px 10px; border-bottom: 1px solid var(--line);
  color: var(--muted); font-size: 12px;
}
.feedHead .onlySym { display: inline-flex; gap: 4px; align-items: center; cursor: pointer; }
.feedToggle {
  margin-left: auto; background: none; border: none; color: var(--muted);
  cursor: pointer; font-size: 14px;
}

/* basis stays `auto`: in the phone layout the pane is content-sized, and a
   basis of 0 makes the list report no height at all, so the pane shrinks to the
   toggles and the list disappears (measured: #feed 0px at 375px wide). What
   keeps the toggles from being crushed instead is `flex: 0 0 auto` on #layers,
   not anything here. */
#feed { flex: 1 1 auto; min-height: 0; overflow-y: auto; scrollbar-width: thin; }
#feed .row {
  display: grid;
  grid-template-columns: 14px 1fr auto;
  gap: 4px 8px;
  padding: 6px 10px;
  border-bottom: 1px solid #171f2a;
  cursor: pointer;
}
#feed .row:hover { background: #182130; }
#feed .row.cur { background: #14202e; }
#feed .g { grid-row: span 2; font-size: 12px; line-height: 1.2; }
#feed .s { font: 600 12px/1.3 ui-monospace, Consolas, monospace; letter-spacing: .3px; }
#feed .t { color: var(--muted); font-size: 11px; text-align: right; }
#feed .d { grid-column: 2 / span 2; color: var(--muted); font-size: 11px; }
#feed .empty { padding: 20px 12px; color: var(--muted); text-align: center; }

/* ------------------------------------------------------------ stats panel */
#statsPanel {
  position: absolute; right: 12px; top: 46px; z-index: 20; width: 330px;
  background: var(--panel); border: 1px solid var(--line); border-radius: 6px;
  padding: 10px 12px; font-size: 12px; box-shadow: 0 8px 24px rgba(0,0,0,.5);
}
#statsPanel h4 { margin: 0 0 6px; font-size: 12px; color: var(--muted); font-weight: 600; }
#statsPanel table { width: 100%; border-collapse: collapse; }
#statsPanel td { padding: 2px 0; }
#statsPanel td.n { text-align: right; font: 12px ui-monospace, Consolas, monospace; }
#statsPanel .note { color: var(--muted); margin-top: 8px; line-height: 1.5; }

/* ------------------------------------------------------------ sign-in page */
body.centred { display: flex; align-items: center; justify-content: center; }

.authbox {
  width: min(360px, calc(100vw - 32px));
  background: var(--panel); border: 1px solid var(--line); border-radius: 8px;
  padding: 22px 22px 26px; box-shadow: 0 10px 40px rgba(0, 0, 0, .5);
}
.authbox .brand { font-size: 26px; margin-bottom: 8px; letter-spacing: .2px; }
.authbox .sub { color: var(--muted); font-size: 12px; margin: 0 0 18px; line-height: 1.5; }
.authbox input {
  display: block; width: 100%; margin-bottom: 9px; padding: 9px 10px;
  background: #0b1017; border: 1px solid var(--line); border-radius: 5px;
  color: var(--text); font: 13px/1.2 inherit;
}
.authbox input:focus { outline: none; border-color: var(--accent); }
.authbox button {
  width: 100%; margin-top: 6px; padding: 9px; cursor: pointer;
  background: #23405f; border: 1px solid #2f5b87; border-radius: 5px;
  color: #fff; font: 600 13px/1.2 inherit;
}
.authbox button:hover { background: #2b4c70; }
.authbox .err { color: var(--dn); font-size: 12px; min-height: 17px; }

/* ------------------------------------------------------------- admin page */
header .who {
  color: var(--muted); font: 12px ui-monospace, Consolas, monospace;
  padding-right: 4px;
}
header a.btn { text-decoration: none; }

.admin {
  flex: 1 1 auto; overflow-y: auto; padding: 18px 20px 40px;
  max-width: 1100px; width: 100%; margin: 0 auto;
}
.admin section { margin-bottom: 30px; }
.admin h2 { font-size: 14px; font-weight: 600; margin: 0 0 4px; }
.admin .hint { color: var(--muted); font-size: 12px; margin: 0 0 10px; line-height: 1.5; max-width: 70ch; }

.admin .card {
  background: var(--panel); border: 1px solid var(--line); border-radius: 6px;
  padding: 12px; margin-bottom: 12px;
  /* Six columns do not fit a phone. The table scrolls inside its own card
     rather than making the whole page scroll sideways, which would otherwise
     hide the delete button off the right edge. */
  overflow-x: auto;
}
.admin .card.row { display: flex; gap: 12px; flex-wrap: wrap; align-items: flex-end; }
.admin label {
  display: flex; flex-direction: column; gap: 4px;
  color: var(--muted); font-size: 11px; text-transform: uppercase; letter-spacing: .4px;
}
.admin input, .admin select {
  padding: 6px 8px; background: #0b1017; border: 1px solid var(--line);
  border-radius: 4px; color: var(--text); font: 13px/1.2 inherit; min-width: 150px;
  text-transform: none; letter-spacing: 0;
}
.admin input.mono { font-family: ui-monospace, Consolas, monospace; }
.admin #srSymbol { text-transform: uppercase; }
.admin input:focus, .admin select:focus { outline: none; border-color: var(--accent); }
.admin button {
  background: #23405f; border: 1px solid #2f5b87; color: #fff;
  border-radius: 4px; padding: 7px 12px; cursor: pointer; font: 12px/1.2 inherit;
}
.admin button:hover { background: #2b4c70; }
.admin td button {
  background: #1a2330; border-color: var(--line); color: var(--muted);
  padding: 3px 8px; margin-right: 4px;
}
.admin td button:hover { background: #222c3b; color: var(--text); }
.admin td button.del:hover { color: var(--dn); border-color: var(--dn); }

.admin .filter { display: flex; align-items: center; gap: 12px; margin-bottom: 8px; }
.admin .filter label { flex-direction: row; align-items: center; gap: 6px; }
.admin .filter .hint { margin: 0; }

.admin table { width: 100%; min-width: 380px; border-collapse: collapse; font-size: 12px; }
.admin th {
  text-align: left; color: var(--muted); font-weight: 600; font-size: 11px;
  text-transform: uppercase; letter-spacing: .4px;
  padding: 4px 8px; border-bottom: 1px solid var(--line);
}
.admin td { padding: 5px 8px; border-bottom: 1px solid #171f2a; }
.admin tr:last-child td { border-bottom: none; }
.admin .n { text-align: right; }
.admin .mono { font-family: ui-monospace, Consolas, monospace; }
.admin .muted { color: var(--muted); }
.admin .empty { color: var(--muted); text-align: center; padding: 16px; }
.admin .tag {
  border-radius: 3px; padding: 1px 6px; font-size: 11px;
  background: #1a2330; color: var(--muted); border: 1px solid var(--line);
}
.admin .tag.admin { background: #2a2036; color: #c9a6ff; border-color: #4a3a62; }

#toast {
  position: fixed; left: 50%; bottom: 24px; transform: translateX(-50%);
  z-index: 50; padding: 8px 14px; border-radius: 5px; font-size: 12px;
  background: var(--panel); border: 1px solid var(--up); color: var(--text);
  box-shadow: 0 8px 24px rgba(0, 0, 0, .55);
}
#toast.bad { border-color: var(--dn); }

/* ------------------------------------------------------------------ mobile */
@media (max-width: 860px) {
  header { flex-wrap: wrap; gap: 8px 6px; }
  /* Only the toolbar's brand goes; the sign-in box IS its own title, and a
     narrow window used to leave that page with nothing but two input boxes. */
  header .brand { display: none; }
  .price { min-width: 0; }
  .tfgroup { order: 5; width: 100%; overflow-x: auto; }
  main { flex-direction: column; }

  /* THE reason this page was unusable on a phone. Both control bars used to be
     children of #chartPane, and at 375px the seven feed toggles (each with its
     own number box) wrapped to 258px while the indicator selects took another
     63px — together more than the pane's whole height, which left #chart with
     exactly 0px. #indicators still folds behind the ⚙ button and starts folded;
     #layers no longer competes for the chart's height at all, because it moved
     into the feed pane and scrolls inside it. */
  #barsBtn { display: inline-block; }
  #indicators { display: none; }
  body.showbars #indicators { display: flex; }

  /* Every box in the column may shrink; only the chart has a floor, so opening
     the controls costs the feed its space rather than the chart its existence. */
  #chartPane { flex: 1 1 auto; min-height: 0; }
  #chart { min-height: 240px; }
  /* The oscillator has to give way before the candles do on a phone. */
  #bhpPane { flex: 0 0 132px; }
  /* 38dvh was enough when the pane held nothing but the list. It now carries
     the channel toggles too, and at 38dvh they left the list exactly 0px — so
     the pane takes a little more and the toggles get a tighter ceiling than on
     a desktop. The chart still clears its 240px floor by a wide margin. */
  #feedPane { flex: 0 1 auto; min-height: 0; max-height: 46dvh;
              border-left: none; border-top: 1px solid var(--line); }
  #layers { max-height: 150px; }
  /* With the indicator bar open there is not enough screen for all three: the
     bar plus the chart's 220px floor plus the feed overflow a 812px phone, and
     `overflow:hidden` then draws the feed straight over the chart. The feed
     stands down while the bar is up — it comes back the moment it folds. That
     takes the channel toggles with it now, which is the trade: they belong to
     the feed, and the feed is what a phone has no room for beside the chart. */
  body.showbars #feedPane { display: none; }
  #statsPanel { left: 12px; right: 12px; width: auto; }
  /* The per-channel names wrap onto two lines and cover the candles; the
     coloured toggles right above the chart already say which feeds are on. */
  #legend .fl { display: none; }
}

/* A phone in portrait: the header itself was three rows (141px). The account
   name is the row that says least — the ⚙/status buttons and the exit link are
   all still there. */
@media (max-width: 560px) {
  header .who { display: none; }
  #chart { min-height: 220px; }
}
