/* Market Hours Dashboard — Phase C styles
 *
 * Layout: sticky shared timeline axis + 17 market rows.
 * Color tokens follow design.md D-8.
 * Responsive breakpoints follow design.md D-10.
 */

:root {
  /* Status colors (design.md D-8) */
  --c-closed:      #6b7280;  /* gray-500   — 休市 / 节假日 */
  --c-pre-market:  #3b82f6;  /* blue-500   — 盘前 / 集合竞价 */
  --c-regular:     #10b981;  /* emerald-500 — 盘中 */
  --c-lunch-break: #d1d5db;  /* gray-300   — 午休 (使用斜纹背景) */
  --c-post-market: #f59e0b;  /* amber-500  — 盘后 / 收盘竞价 */
  --c-overnight:   #8b5cf6;  /* violet-500 — 夜盘 */
  --c-half-day:    #10b981;  /* same as regular + ⏰ icon */
  --c-cursor:      #ef4444;  /* red-500    — "现在"游标 */

  /* Surface tokens — light scheme */
  --c-bg:        #ffffff;
  --c-fg:        #111827;
  --c-muted:     #6b7280;
  --c-border:    #e5e7eb;
  --c-row-bg:    #f9fafb;
  --c-row-hover: #eef2ff;
  --c-axis-bg:   #ffffff;
  --c-axis-tick: #9ca3af;
  --c-axis-label:#374151;
  --c-control-bg: #f3f4f6;
  --c-segment-edge: rgba(255, 255, 255, 0.75);

  /* Layout tokens */
  --left-info-px: 280px;
  --row-height: 56px;
  --axis-height: 36px;
  --header-pad: 16px;
  /* Horizontal breathing room at the very left/right edges of the timeline
   * area. Shifts the [0..1] axis inward so segments at 00:00 / 24:00 don't
   * hug the borders. Mobile overrides this to 0 because cards already supply
   * their own 12px horizontal padding (see the media query below). */
  --axis-edge-pad: 12px;
}

@media (prefers-color-scheme: dark) {
  :root {
    --c-bg:     #0f172a;  /* slate-900 */
    --c-fg:     #f1f5f9;  /* slate-100 */
    --c-muted:  #94a3b8;  /* slate-400 */
    --c-border: #1e293b;  /* slate-800 */
    --c-row-bg: #111827;  /* gray-900  */
    --c-row-hover: #1f2937;
    --c-axis-bg: #0b1220;
    --c-axis-tick: #475569;
    --c-axis-label: #cbd5e1;
    --c-control-bg: #1e293b;
    --c-segment-edge: rgba(255, 255, 255, 0.4);

    --c-lunch-break: #4b5563;
  }
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
}

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
               "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
  background: var(--c-bg);
  color: var(--c-fg);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

/* ─── Loading state ─────────────────────────────────────────────────────── */
.loading {
  padding: 40px 24px;
  color: var(--c-muted);
  text-align: center;
}

/* ─── Header (controls bar) ─────────────────────────────────────────────── */

header {
  padding: 12px 24px;
  border-bottom: 1px solid var(--c-border);
  background: var(--c-bg);
}

header h1 {
  margin: 0 0 8px 0;
  font-size: 18px;
  font-weight: 600;
}

.controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  font-size: 13px;
  color: var(--c-muted);
}

.controls label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.controls select {
  appearance: none;
  background: var(--c-control-bg);
  color: var(--c-fg);
  border: 1px solid var(--c-border);
  border-radius: 6px;
  padding: 4px 24px 4px 8px;
  font-size: 13px;
  font-family: inherit;
  cursor: pointer;
  background-image: linear-gradient(45deg, transparent 50%, var(--c-muted) 50%),
                    linear-gradient(135deg, var(--c-muted) 50%, transparent 50%);
  background-position: calc(100% - 12px) 50%, calc(100% - 8px) 50%;
  background-size: 4px 4px, 4px 4px;
  background-repeat: no-repeat;
}

.controls select:focus {
  outline: 2px solid var(--c-pre-market);
  outline-offset: 1px;
}

#local-now {
  font-variant-numeric: tabular-nums;
  color: var(--c-fg);
  font-weight: 500;
}

/* ─── Shared axis (sticky on scroll) ─────────────────────────────────────── */

.shared-axis {
  display: flex;
  position: sticky;
  top: 0;
  z-index: 5;
  height: var(--axis-height);
  background: var(--c-axis-bg);
  border-bottom: 1px solid var(--c-border);
}

.axis-info-spacer {
  flex: 0 0 var(--left-info-px);
  border-right: 1px solid var(--c-border);
}

/* ─── Splitter (resizable info column) ──────────────────────────────────── */

.splitter {
  flex: 0 0 8px;
  margin-left: -4px;       /* visually centered on the spacer's right edge   */
  margin-right: -4px;
  position: relative;
  z-index: 6;              /* above shared-axis siblings                     */
  cursor: col-resize;
  background: transparent;
  user-select: none;
  touch-action: none;
}

.splitter::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 6px;
  bottom: 6px;
  transform: translateX(-50%);
  width: 2px;
  border-radius: 1px;
  background: var(--c-border);
  transition: background 0.12s ease, box-shadow 0.12s ease;
}

.splitter:hover::before,
.splitter.dragging::before {
  background: var(--c-cursor);
}

.splitter:focus { outline: none; }
.splitter:focus-visible::before {
  background: var(--c-cursor);
  box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.25);
}

/* Apply the col-resize cursor across the whole viewport while dragging so the
 * pointer doesn't flicker when it briefly leaves the 8px gutter. */
body.splitter-dragging,
body.splitter-dragging * {
  cursor: col-resize !important;
  user-select: none !important;
}

.axis-scale {
  flex: 1;
  position: relative;
  height: 100%;
}

.axis-scale .tick {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 1px;
  background: var(--c-axis-tick);
  opacity: 0.4;
  /* `--t` is a unitless [0..1] tick fraction (set inline by render.js). The
   * calc maps it into the padded inner range so ticks stay aligned with
   * segments and the now-cursor when --axis-edge-pad is non-zero. */
  left: calc(var(--axis-edge-pad) + var(--t, 0) * (100% - 2 * var(--axis-edge-pad)));
}

.axis-scale .tick.major {
  opacity: 0.7;
}

.axis-scale .tick-label {
  position: absolute;
  top: 50%;
  transform: translate(-50%, -50%);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  color: var(--c-axis-label);
  background: var(--c-axis-bg);
  padding: 0 4px;
  pointer-events: none;
  left: calc(var(--axis-edge-pad) + var(--t, 0) * (100% - 2 * var(--axis-edge-pad)));
}

/* ─── Market list container ─────────────────────────────────────────────── */

.market-list-wrap {
  position: relative;
}

#market-list {
  position: relative;
}

/* ─── Market row ────────────────────────────────────────────────────────── */

.market-row {
  display: flex;
  align-items: stretch;
  border-bottom: 1px solid var(--c-border);
  height: var(--row-height);
  transition: background-color 0.12s ease;
}

.market-row:hover {
  background: var(--c-row-hover);
}

/* Highlight ALL cross-day segments on the row when ANY of them are hovered.
 * Per design.md D-11 Phase B implementation note: two cross-day segments in a
 * 24h window come from different physical trading days, so they don't share
 * original UTC bounds. We use row-wide highlight to signal "this market crosses
 * the base-tz midnight" rather than pair-up siblings. */
.market-row:has(.segment[data-cross-day="true"]:hover) {
  background: var(--c-row-hover);
}

.market-row:has(.segment[data-cross-day="true"]:hover) .segment[data-cross-day="true"] {
  outline: 2px solid var(--c-cursor);
  outline-offset: -1px;
  z-index: 2;
}

.row-info {
  flex: 0 0 var(--left-info-px);
  display: grid;
  grid-template-columns: 24px 1fr auto;
  grid-template-rows: auto auto;
  grid-template-areas:
    "flag title status"
    "flag time countdown";
  column-gap: 10px;
  row-gap: 2px;
  align-items: center;
  padding: 6px 12px;
  border-right: 1px solid var(--c-border);
  min-width: 0;
}

.row-info .flag {
  grid-area: flag;
  font-size: 22px;
  line-height: 1;
}

.row-info .title {
  grid-area: title;
  display: flex;
  align-items: baseline;
  gap: 6px;
  min-width: 0;
}

.row-info .title h2 {
  margin: 0;
  font-size: 14px;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.row-info .title .full-name {
  color: var(--c-muted);
  font-size: 11px;
  font-weight: 400;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.row-info .local-time {
  grid-area: time;
  font-size: 11px;
  color: var(--c-muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.row-info .status-badge {
  grid-area: status;
  justify-self: end;
  font-size: 11px;
  font-weight: 600;
  color: #ffffff;
  padding: 2px 8px;
  border-radius: 10px;
  white-space: nowrap;
}

.row-info .countdown {
  grid-area: countdown;
  justify-self: end;
  font-size: 11px;
  color: var(--c-muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Status badge color variants */
.status-badge.closed       { background: var(--c-closed); }
.status-badge.pre-market   { background: var(--c-pre-market); }
.status-badge.regular      { background: var(--c-regular); }
.status-badge.lunch-break  { background: var(--c-lunch-break); color: #1f2937; }
.status-badge.post-market  { background: var(--c-post-market); color: #1f2937; }
.status-badge.overnight    { background: var(--c-overnight); }
.status-badge.half-day     { background: var(--c-regular); }

/* ─── Row timeline (right side, [0,1] coordinate space) ─────────────────── */

.row-timeline {
  flex: 1;
  position: relative;
  height: 100%;
  background: var(--c-row-bg);
  overflow: hidden;
}

/* Faint vertical guide lines every 3h, aligned with the axis ticks. */
.row-timeline::before {
  content: '';
  position: absolute;
  /* Inset by --axis-edge-pad so the guides span exactly the same inner range
   * as the ticks/segments above. The gradient repeats at 12.5% of this inner
   * box, which corresponds to every 3h on the axis. */
  inset: 0 var(--axis-edge-pad);
  background-image:
    linear-gradient(to right,
      transparent 0,
      transparent calc(12.5% - 1px),
      var(--c-border) calc(12.5% - 1px),
      var(--c-border) 12.5%,
      transparent 12.5%,
      transparent 100%);
  background-size: 12.5% 100%;
  pointer-events: none;
  opacity: 0.6;
}

.segment {
  position: absolute;
  top: 10px;
  bottom: 10px;
  border-radius: 4px;
  background: var(--c-closed);
  cursor: help;
  transition: transform 0.08s ease, box-shadow 0.08s ease;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  padding: 0 4px;
  overflow: hidden;
  min-width: 2px;
  /* `--seg-left` / `--seg-width` are unitless [0..1] fractions of the base-tz
   * day (set inline by render.js). The calcs map them into the padded inner
   * range so segments align with ticks/guides/cursor under any
   * --axis-edge-pad. */
  left: calc(var(--axis-edge-pad) + var(--seg-left, 0) * (100% - 2 * var(--axis-edge-pad)));
  width: calc(var(--seg-width, 0) * (100% - 2 * var(--axis-edge-pad)));
}

.segment:hover {
  transform: translateY(-1px);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.18);
  z-index: 3;
}

.segment.pre-market   { background: var(--c-pre-market); }
.segment.regular      { background: var(--c-regular); }
.segment.post-market  { background: var(--c-post-market); }
.segment.overnight    { background: var(--c-overnight); }
.segment.half-day     { background: var(--c-half-day); }

/* Lunch break: diagonal stripes on light gray base. */
.segment.lunch-break {
  background:
    repeating-linear-gradient(
      45deg,
      var(--c-lunch-break),
      var(--c-lunch-break) 4px,
      rgba(255, 255, 255, 0.5) 4px,
      rgba(255, 255, 255, 0.5) 8px
    );
}

/* Mark cross-day segments with a vertical white "torn-edge" hint at the
 * clipped boundary. Left-edge segments are clipped on the LEFT; right-edge on
 * the RIGHT. We approximate by adding subtle inset borders to both sides; the
 * non-clipped side just has the normal background. */
.segment[data-cross-day="true"]::before,
.segment[data-cross-day="true"]::after {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  width: 2px;
  pointer-events: none;
}

.segment[data-cross-day="true"][data-clip-left="true"]::before {
  left: 0;
  background: var(--c-segment-edge);
  box-shadow: 1px 0 0 rgba(0, 0, 0, 0.05);
}

.segment[data-cross-day="true"][data-clip-right="true"]::after {
  right: 0;
  background: var(--c-segment-edge);
  box-shadow: -1px 0 0 rgba(0, 0, 0, 0.05);
}

/* ─── Segment hover tooltip (desktop — instant, no delay) ───────────────── */

.segment-tooltip {
  position: fixed;
  z-index: 50;
  min-width: 200px;
  max-width: 340px;
  padding: 8px 10px;
  background: var(--c-bg);
  color: var(--c-fg);
  border: 1px solid var(--c-border);
  border-radius: 6px;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.18);
  font-size: 12px;
  line-height: 1.45;
  pointer-events: none;
  /* No transition — must appear instantly on mouseover. */
}

.segment-tooltip[hidden] { display: none; }

.segment-tooltip .st-title {
  font-weight: 600;
  margin-bottom: 4px;
  display: flex;
  align-items: baseline;
  gap: 6px;
}

.segment-tooltip .st-flag {
  font-size: 14px;
  line-height: 1;
}

.segment-tooltip .st-type {
  margin-left: auto;
  font-size: 11px;
  font-weight: 500;
  padding: 1px 6px;
  border-radius: 3px;
  color: #ffffff;
  white-space: nowrap;
}
.segment-tooltip .st-type.regular     { background: var(--c-regular); }
.segment-tooltip .st-type.pre-market  { background: var(--c-pre-market); }
.segment-tooltip .st-type.post-market { background: var(--c-post-market); }
.segment-tooltip .st-type.overnight   { background: var(--c-overnight); }
.segment-tooltip .st-type.lunch-break { background: var(--c-closed); }
.segment-tooltip .st-type.closed      { background: var(--c-closed); }
.segment-tooltip .st-type.half-day    { background: var(--c-regular); }

.segment-tooltip .st-row {
  color: var(--c-muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.segment-tooltip .st-row strong {
  color: var(--c-fg);
  font-weight: 500;
  margin-right: 4px;
}

.segment-tooltip .st-flags {
  margin-top: 4px;
  color: var(--c-muted);
  font-size: 11px;
}

/* On mobile the bottom-sheet takes over; the tooltip must never show. */
@media (max-width: 767px) {
  .segment-tooltip { display: none !important; }
}

/* Half-day clock icon inside the segment (top-right corner). */
.segment[data-half-day="true"]::after {
  content: '\23F0';
  position: absolute;
  top: 1px;
  right: 3px;
  font-size: 10px;
  line-height: 1;
  color: #ffffff;
  opacity: 0.9;
  pointer-events: none;
}

/* ─── Now cursor (vertical red line across the timeline) ────────────────── */

#now-cursor {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 2px;
  margin-left: -1px;
  /* The cursor lives in .market-list-wrap (full-row width) but must align
   * with .row-timeline content, which starts at --left-info-px. JS sets
   * --cursor-x ∈ [0,1] = fraction of the base-tz day; CSS offsets by the
   * info column so dragging the splitter re-aligns the cursor with zero JS.
   * Also pads by --axis-edge-pad on both sides so cursor-x=0 lands at the
   * first tick (00:00) and cursor-x=1 lands at the last tick (24:00). */
  left: calc(var(--left-info-px) + var(--axis-edge-pad) + var(--cursor-x, 0) * (100% - var(--left-info-px) - 2 * var(--axis-edge-pad)));
  background: var(--c-cursor);
  pointer-events: none;
  z-index: 8;
  box-shadow: 0 0 6px rgba(239, 68, 68, 0.6);
}

#now-cursor::before {
  content: '';
  position: absolute;
  top: -4px;
  left: -3px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--c-cursor);
}

/* ─── Footer ────────────────────────────────────────────────────────────── */

footer {
  padding: 12px 24px;
  color: var(--c-muted);
  border-top: 1px solid var(--c-border);
  font-size: 12px;
}

.legend {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
  margin-top: 8px;
}

.legend-item {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 11px;
}

.legend-swatch {
  width: 14px;
  height: 10px;
  border-radius: 2px;
}

.legend-swatch.closed       { background: var(--c-closed); }
.legend-swatch.pre-market   { background: var(--c-pre-market); }
.legend-swatch.regular      { background: var(--c-regular); }
.legend-swatch.lunch-break  {
  background: repeating-linear-gradient(45deg,
    var(--c-lunch-break), var(--c-lunch-break) 3px,
    rgba(255,255,255,0.5) 3px, rgba(255,255,255,0.5) 6px);
}
.legend-swatch.post-market  { background: var(--c-post-market); }
.legend-swatch.overnight    { background: var(--c-overnight); }

/* ─── Desktop defaults for mobile-only widgets ───────────────────────────── */

/* The mobile tz/sort buttons and the full-screen pickers live in the DOM all
 * the time but only render on touch viewports. The CSS hides them by default;
 * the @media (max-width: 767px) block below flips them on. !important guards
 * against any later cascade ordering issue (.controls inherits and could win
 * the `display` race on some user-agents). */
.tz-button,
.sort-button {
  display: none !important;
}
.tz-picker[hidden],
.sort-picker[hidden],
.bottom-sheet[hidden] {
  display: none;
}

/* On desktop, hide the bottom sheet and pickers entirely — even if JS were
 * to clear the `hidden` attribute (defensive). The desktop UX uses native
 * `title` hover tooltips and the inline <select>. */
@media (min-width: 768px) {
  .bottom-sheet,
  .tz-picker,
  .sort-picker {
    display: none !important;
  }
}

/* ─── Responsive (design.md D-10) ───────────────────────────────────────── */

@media (max-width: 1023px) {
  :root {
    --left-info-px: 200px;
  }

  /* Below the resizable breakpoint, drop the splitter — layout is fixed. */
  .splitter {
    display: none;
  }

  .row-info {
    grid-template-columns: 22px 1fr auto;
    grid-template-areas:
      "flag title status"
      "flag countdown countdown";
    column-gap: 8px;
    padding: 6px 10px;
  }

  .row-info .local-time {
    display: none;
  }

  .row-info .title .full-name {
    display: none;
  }
}

/* ─── Mobile (≤ 767px): true mobile layout ───────────────────────────────
 *
 * Layout shift from desktop:
 *   • Each market row becomes a vertical card: info-line on top, full-width
 *     mini timeline below.
 *   • The shared-axis stays at the top but its left spacer collapses so the
 *     scale spans the full viewport width — aligning visually with each card's
 *     timeline column underneath.
 *   • The now-cursor stays in the absolute layer (.market-list-wrap), driven
 *     by the --cursor-x CSS var (0..1) and offset by --left-info-px via calc()
 *     so it tracks the timeline column exactly. On mobile --left-info-px is 0,
 *     so the calc reduces to `left: cursor-x * 100%`. The cursor still spans
 *     full height (Scheme A — simple vertical line over every row).
 *   • The native <select id="tz-select"> is hidden; the styled <button id=
 *     "tz-button"> shows instead, launching the full-screen #tz-picker on
 *     tap. Sort <select> stays native (only 3 options).
 *   • Hover tooltips are replaced by `click → #bottom-sheet` (wired in app.js).
 * --------------------------------------------------------------------- */

@media (max-width: 767px) {
  :root {
    --left-info-px: 0px;
    --row-height: auto;
    --axis-height: 28px;
    /* Mobile cards already provide 12px horizontal padding, so the timeline
     * inside each card visually has breathing room. Zeroing this out keeps
     * the cursor (positioned against .market-list-wrap) aligned with the
     * segments inside each card's full-width .row-timeline. */
    --axis-edge-pad: 0px;
  }

  /* Header collapses to two stacked lines: title + controls row. */
  header {
    padding: 10px 12px;
  }
  header h1 {
    font-size: 16px;
    margin-bottom: 6px;
  }
  .controls {
    gap: 8px;
    font-size: 12px;
    flex-wrap: wrap;
  }
  .controls label,
  .controls select {
    font-size: 12px;
  }

  /* Hide native tz-select; show the styled tz-button instead. The button
   * label is updated by JS (syncTzButtonLabel). Same pattern for sort. */
  .tz-select-label,
  .sort-select-label {
    display: none !important;
  }
  .tz-button,
  .sort-button {
    display: inline-flex !important;
    align-items: center;
    gap: 6px;
    padding: 6px 10px;
    background: var(--c-control-bg);
    border: 1px solid var(--c-border);
    border-radius: 8px;
    color: var(--c-fg);
    font: inherit;
    font-size: 12px;
    min-height: 36px;
    cursor: pointer;
  }
  .tz-button .tz-button-prefix,
  .sort-button .sort-button-prefix {
    color: var(--c-muted);
  }
  .tz-button .tz-button-label,
  .sort-button .sort-button-label {
    font-variant-numeric: tabular-nums;
    font-weight: 600;
  }
  .tz-button .tz-button-chevron,
  .sort-button .sort-button-chevron {
    color: var(--c-muted);
    font-size: 10px;
  }

  .clock-wrap {
    width: 100%;
    order: 99;        /* push the clock onto its own line, below the pickers */
    font-size: 11px;
  }

  /* Shared axis: spacer collapses, scale spans full width. */
  .shared-axis {
    height: 28px;
    padding: 0;
  }
  .axis-info-spacer { display: none; }
  .splitter { display: none; }
  .axis-scale .tick-label {
    font-size: 10px;
    padding: 0 3px;
  }

  /* Each market row becomes a vertical card: info-line + mini timeline. */
  .market-row {
    display: block;
    align-items: initial;
    height: auto;
    padding: 8px 12px;
  }

  /* Info area uses CSS grid for a 2-row layout matching the design mockup:
   *
   *   [flag] [name]                  [badge] [countdown]      ← line 1
   *   [   ] [local-time]                                       ← line 2
   *
   * The flag spans both rows so the card has a clear visual "avatar" gutter.
   * Hidden elements (.title .full-name) still occupy zero space.
   */
  .row-info {
    flex: none;
    width: 100%;
    border-right: 0;
    padding: 0;
    background: transparent;
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto auto;
    grid-template-rows: auto auto;
    grid-template-areas:
      "flag title  status countdown"
      "flag time   .      .";
    column-gap: 8px;
    row-gap: 1px;
    align-items: center;
  }
  .row-info .flag {
    grid-area: flag;
    align-self: center;
    font-size: 18px;
    line-height: 1;
  }
  .row-info .title {
    grid-area: title;
    display: flex;
    align-items: baseline;
    min-width: 0;
  }
  .row-info .title h2 {
    font-size: 13px;
    font-weight: 600;
    line-height: 1.2;
  }
  .row-info .title .full-name {
    display: none;
  }
  .row-info .local-time {
    grid-area: time;
    display: inline;
    font-size: 11px;
    color: var(--c-muted);
    line-height: 1.2;
    white-space: nowrap;
  }
  .row-info .status-badge {
    grid-area: status;
    justify-self: end;
    font-size: 10px;
    padding: 1px 6px;
  }
  .row-info .countdown {
    grid-area: countdown;
    justify-self: end;
    font-size: 11px;
    white-space: nowrap;
  }

  /* Mini timeline: full-width, taller touch target (24px), gap from info line. */
  .row-timeline {
    flex: none;
    width: 100%;
    height: 24px;
    min-width: 0;            /* override the desktop overflow-hidden density */
    margin-top: 6px;
    overflow: visible;       /* segments paint within, but the row clips none */
    border-radius: 4px;
  }

  /* Tappable hit area: segments shouldn't be sub-pixel; enforce 6px min-width
   * on mobile for finger taps. */
  .segment {
    top: 4px;
    bottom: 4px;
    min-width: 6px;
    cursor: pointer;        /* hint to the user a tap will open the sheet */
  }

  /* Now-cursor on mobile: --left-info-px is 0, so the desktop calc()
   * collapses to `left: var(--cursor-x) * 100%` and the cursor naturally
   * lines up with each card's full-width timeline. No mobile-specific
   * position override needed — just leave it `display: block`. */
  #now-cursor {
    display: block;
  }

  /* Market list wrapper: no horizontal scroll on mobile — timelines are full
   * width so no overflow needed. */
  .market-list-wrap {
    overflow: visible;
  }

  /* Footer + legend: compact. */
  footer {
    padding: 8px 12px;
    font-size: 11px;
  }
  .legend {
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 6px;
  }
}

/* ─── Extra-narrow phones (≤ 380px) ──────────────────────────────────────
 * Hide the countdown to save horizontal space; the user can tap the segment
 * to see full details in the bottom sheet. */
@media (max-width: 380px) {
  .row-info .countdown {
    display: none;
  }
  .row-info .local-time {
    font-size: 10px;
  }
  .controls {
    font-size: 11px;
  }
}

/* ─── Bottom sheet (mobile: segment detail) ─────────────────────────────── */

.bottom-sheet {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: flex-end;
  justify-content: center;
}

.bottom-sheet-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.45);
  opacity: 0;
  animation: bs-backdrop-in 0.18s ease forwards;
}

.bottom-sheet-panel {
  position: relative;
  width: 100%;
  max-width: 480px;
  margin: 0 auto;
  background: var(--c-bg);
  color: var(--c-fg);
  border-radius: 16px 16px 0 0;
  padding: 8px 16px calc(24px + env(safe-area-inset-bottom, 0px));
  transform: translateY(100%);
  animation: bs-panel-in 0.22s cubic-bezier(0.2, 0.9, 0.3, 1) forwards;
  box-shadow: 0 -8px 32px rgba(0, 0, 0, 0.25);
}

@keyframes bs-backdrop-in {
  to { opacity: 1; }
}
@keyframes bs-panel-in {
  to { transform: translateY(0); }
}

.bottom-sheet-handle {
  width: 36px;
  height: 4px;
  margin: 4px auto 12px;
  background: var(--c-muted);
  opacity: 0.5;
  border-radius: 2px;
}

.bottom-sheet-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 12px;
  padding: 0;
  border: 0;
  background: transparent;
}

.bottom-sheet-header h3 {
  margin: 0;
  font-size: 15px;
  font-weight: 600;
}

.bottom-sheet-close {
  background: transparent;
  border: none;
  color: var(--c-muted);
  font-size: 18px;
  line-height: 1;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  cursor: pointer;
}

.bottom-sheet-close:hover,
.bottom-sheet-close:focus {
  color: var(--c-fg);
  background: var(--c-row-hover);
  outline: none;
}

.bottom-sheet-body dl {
  margin: 0;
  display: grid;
  grid-template-columns: 84px 1fr;
  gap: 8px 12px;
  font-size: 13px;
}
.bottom-sheet-body dt {
  color: var(--c-muted);
  font-weight: 500;
}
.bottom-sheet-body dd {
  margin: 0;
  font-variant-numeric: tabular-nums;
  word-break: break-word;
}

/* ─── Full-screen pickers (mobile) ──────────────────────────────────────── */
/* Shared by .tz-picker (timezone) and .sort-picker (sort mode). Selectors use
 * :where() so they keep specificity 0,1,0 — easy to override and consistent
 * with the original .tz-picker rules. */

:where(.tz-picker, .sort-picker) {
  position: fixed;
  inset: 0;
  z-index: 110;
  background: var(--c-bg);
  color: var(--c-fg);
  display: flex;
  flex-direction: column;
}

:where(.tz-picker-header, .sort-picker-header) {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: calc(12px + env(safe-area-inset-top, 0px)) 16px 12px;
  border-bottom: 1px solid var(--c-border);
  background: var(--c-bg);
  position: sticky;
  top: 0;
  z-index: 1;
}
:where(.tz-picker-header, .sort-picker-header) h3 {
  margin: 0;
  font-size: 15px;
  font-weight: 600;
}
:where(.tz-picker-close, .sort-picker-close) {
  background: transparent;
  border: none;
  color: var(--c-fg);
  font-size: 18px;
  line-height: 1;
  width: 36px;
  height: 36px;
  cursor: pointer;
  border-radius: 50%;
}
:where(.tz-picker-close, .sort-picker-close):hover,
:where(.tz-picker-close, .sort-picker-close):focus {
  background: var(--c-row-hover);
  outline: none;
}

:where(.tz-picker-list, .sort-picker-list) {
  list-style: none;
  margin: 0;
  padding: 0 0 env(safe-area-inset-bottom, 0px) 0;
  overflow-y: auto;
  flex: 1;
  -webkit-overflow-scrolling: touch;
}

:where(.tz-picker-group, .sort-picker-group) {
  padding: 8px 16px 4px;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--c-muted);
  background: var(--c-row-bg);
  position: sticky;
  top: 0;
  z-index: 0;
}

:where(.tz-picker-item, .sort-picker-item) {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 16px;
  border-bottom: 1px solid var(--c-border);
  cursor: pointer;
  min-height: 48px;
  gap: 12px;
}
:where(.tz-picker-item, .sort-picker-item):active {
  background: var(--c-row-hover);
}
:where(.tz-picker-item, .sort-picker-item):focus {
  outline: 2px solid var(--c-pre-market);
  outline-offset: -2px;
}
:where(.tz-picker-item, .sort-picker-item).active {
  background: var(--c-row-hover);
  font-weight: 600;
}
:where(.tz-picker-item-main, .sort-picker-item-main) {
  display: flex;
  flex-direction: column;
  min-width: 0;
}
:where(.tz-picker-item-name, .sort-picker-item-name) {
  font-size: 14px;
  font-variant-numeric: tabular-nums;
}
:where(.tz-picker-item-offset, .sort-picker-item-desc) {
  font-size: 11px;
  color: var(--c-muted);
  font-variant-numeric: tabular-nums;
  margin-top: 2px;
}
:where(.tz-picker-item-check, .sort-picker-item-check) {
  color: var(--c-regular);
  font-size: 18px;
  font-weight: 600;
}

/* Lock body scroll while any full-screen picker is up. */
body.tz-picker-open,
body.sort-picker-open {
  overflow: hidden;
}
