/* Design tokens read off orbler.io, not invented. Flat surfaces, no
   shadows, cyan on near-black teal. */
:root {
  --page-bg: #0a1919;
  --card-bg: #071212;
  --card-border: #1c3b3b;
  --inset-bg: #0a1a1a;
  --brand-6: #00ffff;
  --brand-3: #64ffff;
  --brand-9: #00afb0;
  --text: #ccffff;
  --dimmed: #81b7b9;
  --muted: #4a6b6b;
  --danger: #ff8787;
  --danger-bg: #2a1414;
  --success: #38d9a9;
  --success-bg: #0b2620;
  --warn: #ffd43b;
  --warn-bg: #2a2410;
  --font-body: "Public Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --font-display: "Chillax", "Public Sans", -apple-system, sans-serif;
  --font-mono: ui-monospace, "SF Mono", "IBM Plex Mono", monospace;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--page-bg);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

.wrap { max-width: 1320px; margin: 0 auto; padding: 2rem 1.25rem 4rem; }

/* The two sections are laid out differently because they hold different
   things, not for symmetry.

   Ticker cards TILE. There are fifteen of them, each a price and a short
   metric grid, and they are what turned this page into something nobody
   scrolled to the end of. auto-fill with a min track rather than a fixed
   column count, so the same rule collapses to one column on a phone with no
   media query -- which is where the Mini App will actually render this. The
   track is min(320px, 100%), not a bare 320px: a bare minmax() track keeps
   forcing its full width once the viewport is narrower than it, and the whole
   page then scrolls sideways on a 375px screen.

   Coin cards do NOT tile. Each carries a chart, and the chart is the one
   thing here that genuinely wants width; two-up cut a ~1300px row down to
   ~600px cards and left the frame cramped for no gain, because a handful of
   coins was never the scrolling problem. */
#coins, #stocks {
  display: grid;
  gap: 12px;
  /* start, not stretch: a tall card must not drag every sibling in its row to
     the same height and leave them padded with dead space. */
  align-items: start;
}
#coins  { grid-template-columns: minmax(0, 1fr); }
#stocks { grid-template-columns: repeat(auto-fill, minmax(min(320px, 100%), 1fr)); }
#coins > .card, #stocks > .card { margin-bottom: 0; }

.page-title {
  font-family: var(--font-display);
  font-size: 26px;
  font-weight: 600;
  margin: 0 0 4px;
  letter-spacing: -0.01em;
}
.page-sub { color: var(--dimmed); font-size: 14px; margin: 0 0 28px; }

.section-head {
  font-family: var(--font-display);
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--brand-3);
  margin: 32px 0 12px;
}

.card {
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  border-radius: 16px;
  padding: 18px;
  margin-bottom: 12px;
}

.card-top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 4px;
}
.symbol { font-family: var(--font-display); font-size: 19px; font-weight: 600; }
.themes { color: var(--muted); font-size: 12px; letter-spacing: 0.04em; }

.price-row { display: flex; align-items: baseline; gap: 10px; margin: 6px 0 14px; }
.price { font-family: var(--font-mono); font-size: 24px; }
.delta { font-family: var(--font-mono); font-size: 14px; }
.up { color: var(--success); }
.down { color: var(--danger); }
.flat { color: var(--dimmed); }

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  /* Separators are drawn INSIDE each cell rather than as grid gaps showing a
     background through. With gaps, a partly-filled last row leaves a solid
     block of border colour that reads as a cell with no label -- an empty
     slot must look like empty space, not like missing data. */
  background: var(--inset-bg);
  border: 1px solid var(--card-border);
  border-radius: 8px;
  overflow: hidden;
}
.cell {
  padding: 10px 12px;
  box-shadow: inset -1px -1px 0 var(--card-border);
}
.cell-label {
  color: var(--muted);
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin-bottom: 3px;
}
.cell-value { font-family: var(--font-mono); font-size: 14px; }

/* Market-wide figures must not read as per-coin metrics -- the spec is
   explicit about this. A distinct border and an explicit label do it. */
.market-wide {
  border: 1px dashed var(--brand-9);
  border-radius: 8px;
  padding: 10px 12px;
  margin-top: 12px;
  background: transparent;
}
.market-wide .cell-label { color: var(--brand-9); }

.pill {
  display: inline-block;
  font-size: 11px;
  letter-spacing: 0.05em;
  padding: 3px 10px;
  border-radius: 100px;
  border: 1px solid var(--card-border);
  color: var(--dimmed);
}
.pill-stale { color: var(--warn); border-color: var(--warn); background: var(--warn-bg); }
.pill-unknown { color: var(--muted); border-color: var(--muted); }
.pill-fresh { color: var(--success); border-color: var(--success); background: var(--success-bg); }

.summary { margin: 14px 0 0; color: var(--text); font-size: 14px; }
.note {
  margin-top: 8px;
  font-size: 12px;
  color: var(--warn);
  border-left: 2px solid var(--warn);
  padding-left: 10px;
}
.muted-note { margin-top: 10px; font-size: 12px; color: var(--muted); }

.progress-track {
  height: 4px;
  background: var(--card-border);
  border-radius: 100px;
  overflow: hidden;
  margin: 10px 0 6px;
}
.progress-fill { height: 100%; background: var(--brand-9); border-radius: 100px; }

.sources { margin-top: 14px; font-size: 11px; color: var(--muted); }
.sources .failed { color: var(--danger); }

.credit {
  margin-top: 28px;
  padding-top: 14px;
  border-top: 1px solid var(--card-border);
  font-size: 11px;
  color: var(--muted);
}

.empty {
  border: 1px dashed var(--card-border);
  border-radius: 16px;
  padding: 22px;
  color: var(--dimmed);
  font-size: 14px;
}
.empty strong { color: var(--text); font-weight: 600; }

/* --- sentiment badge: driven by the JSON's `sentiment` field, never
   inferred client-side from prose --- */
.badge {
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 3px 10px;
  border-radius: 100px;
  border: 1px solid currentColor;
}
.badge-bullish { color: var(--success); background: var(--success-bg); }
.badge-bearish { color: var(--danger);  background: var(--danger-bg); }
.badge-neutral { color: var(--brand-6); background: transparent; }

/* --- "Checked N sources", expanding to name them --- */
.checked { margin: 2px 0 14px; font-size: 12px; }
.checked > summary {
  cursor: pointer;
  color: var(--brand-3);
  list-style: none;
}
.checked > summary::-webkit-details-marker { display: none; }
.checked > summary::before { content: "▸ "; }
.checked[open] > summary::before { content: "▾ "; }
.checked-list { color: var(--muted); padding: 6px 0 0 14px; }

/* --- TradingView embed --- */
.chart { margin: 4px 0 14px; }
.tv-mount {
  /* min-height, NOT height. The embed script writes `width:100%;height:100%`
     as an INLINE style on this element, and inline beats the stylesheet -- a
     `height` here is simply ignored. Worse, its 100% resolves against a parent
     with no height of its own, so the box collapsed to whatever the iframe
     defaulted to: measured at 152px, a candlestick chart in a letterbox.
     min-height is not overridden by that inline height, so it holds as a
     floor while the widget still autosizes.

     440px because TradingView draws its own axes, legend and toolbar inside
     this box; the space actually left for candles is well under the total. */
  min-height: 440px;
  border: 1px solid var(--card-border);
  border-radius: 8px;
  overflow: hidden;
  /* Flex, because the height above is a min-height and a min-height does not
     give a child a definite height to resolve a percentage against. The embed
     writes `height:100%` inline on its iframe; with an auto-height parent that
     percentage cannot resolve, so the iframe fell back to its own 150px
     default and sat in a 440px box with 290px of dead space under it.
     Stretching a flex child needs no percentage at all. */
  display: flex;
  flex-direction: column;
}
/* Whatever the widget leaves behind -- its own iframe, or the placeholder div
   before the script swaps it -- fills the box. min-height:0 so the child may
   shrink below its content size instead of forcing the container taller. */
.tv-mount > * { flex: 1 1 auto; min-height: 0; }
.chart .muted-note { margin-top: 6px; }

/* --- one-line labelled rows (trend, volume, positioning, ...) --- */
.srow {
  padding: 9px 0;
  border-top: 1px solid var(--card-border);
}
.srow-text { font-family: var(--font-mono); font-size: 13px; margin-top: 2px; }

/* Chart could not render here — say so and link out, never a blank box. */
.tv-fallback {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  height: 120px;
  border-style: dashed;
}
.tv-fallback a { color: var(--brand-3); font-size: 13px; text-decoration: none; }
.tv-fallback a:hover { text-decoration: underline; }
.tv-fallback .muted-note { margin: 0; }

.tv-link { color: var(--brand-3); text-decoration: none; }
.tv-link:hover { text-decoration: underline; }
/* The widget paints its own surface; give it a neutral one underneath so a
   slow first paint is not a white flash against a near-black page. */
.tv-mount { background: var(--inset-bg); }

/* --- watchlist picker --- */
.watchlist { margin: 0 0 14px; }
.watchlist-row { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.chip {
  font: inherit;
  font-size: 13px;
  padding: 5px 13px;
  border-radius: 999px;
  cursor: pointer;
  background: transparent;
  transition: border-color 0.12s, color 0.12s;
}
/* The on/off difference is border AND text colour, not colour alone -- a chip
   distinguished only by hue is unreadable to anyone who cannot separate those
   hues, and this control has no other state to read. */
.chip-on  { border: 1px solid var(--brand-6); color: var(--brand-6); font-weight: 600; }
.chip-off { border: 1px dashed var(--card-border); color: var(--muted); }
.chip:hover { border-color: var(--brand-3); }
.watchlist .muted-note { margin-top: 8px; }

/* --- headlines --- */
.news { margin-top: 14px; }
.news-list { margin: 6px 0 0; padding-left: 16px; font-size: 12px; line-height: 1.55; }
.news-list li { margin-bottom: 4px; }
.news-list a { color: var(--brand-6); text-decoration: none; }
.news-list a:hover { text-decoration: underline; }
.news-meta { color: var(--muted); }

/* --- our own chart: inline SVG, same-origin, nothing to block --- */
.own-chart { margin: 4px 0 14px; }
.spark {
  width: 100%;
  height: 198px;
  display: block;
  background: var(--inset-bg);
  border: 1px solid var(--card-border);
  border-radius: 8px;
}
.spark-line { stroke: var(--brand-6); stroke-width: 1.5; vector-effect: non-scaling-stroke; }
.spark-fill { fill: var(--brand-6); opacity: 0.10; stroke: none; }
.spark-bullish .spark-line { stroke: var(--success); }
.spark-bullish .spark-fill { fill: var(--success); }
.spark-bearish .spark-line { stroke: var(--danger); }
.spark-bearish .spark-fill { fill: var(--danger); }
.own-chart .muted-note { margin-top: 6px; }

/* Candles are coloured by the candle's OWN direction, not by the card's
   sentiment -- a red day inside a bullish week is still a red day. The
   viewBox is stretched (preserveAspectRatio="none"), so wick strokes must be
   non-scaling or they widen with the box. */
.candle-wick { stroke-width: 1; vector-effect: non-scaling-stroke; }
.candle-up .candle-wick { stroke: var(--success); }
.candle-up .candle-body { fill: var(--success); }
.candle-down .candle-wick { stroke: var(--danger); }
.candle-down .candle-body { fill: var(--danger); }
/* A doji closed exactly where it opened: neutral, because neither colour is
   true of it. It is drawn at a 1px floor, so it reads as a line, not a gap. */
.candle-flat .candle-wick { stroke: var(--muted); }
.candle-flat .candle-body { fill: var(--muted); }
.volume-bar { opacity: 0.45; }
.volume-bar.candle-up { fill: var(--success); }
.volume-bar.candle-down { fill: var(--danger); }
.volume-bar.candle-flat { fill: var(--muted); }

/* Stand-in for an embed that did not load: fills the same space, so the card
   keeps its shape and nothing looks broken. */
.tv-standin { height: auto; border: 0; }
.tv-standin .own-chart { margin: 0; }
