/* TopBar — brand, primary nav and the market-status cluster.
 *
 * Every colour, type size, spacing, radius and motion value comes from the
 * custom properties in tokens.css, with the few homepage-redesign sizes that
 * have no token (15px body, 18px bar padding, 7px dot and Login padding) raw
 * and commented at their rules — as in views/landing.css. The root reuses
 * styles.css `.topbar` (flex, surface, sticky, wrap) and only adds rules
 * styles.css does not have. The dots reuse styles.css `.dot` /
 * `.dot.on|.warn|.err` and `.conn-ok|.conn-warn|.conn-bad`; the focus ring
 * is styles.css `:focus-visible`.
 *
 * The public front door's bar (homepage redesign §3) wears its own chrome in
 * the `.tb-public` rules at the end of the file; the signed-in bar keeps
 * everything above them unchanged. */

/* Brand: logo mark + wordmark, links to the dashboard. */
.tb-brand {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  color: var(--ink);
  font-size: var(--fs-body);
  font-weight: var(--fw-semibold);
  white-space: nowrap;
}

.tb-brand:hover { color: var(--ink-strong); text-decoration: none; }

.tb-brand svg { display: block; color: var(--muted); flex: none; }
.tb-brand svg .tb-mark-bar { fill: currentColor; opacity: 0.55; }
.tb-brand svg .tb-mark-peak { fill: var(--accent); opacity: 1; }

/* Primary nav. */
.tb-nav {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  margin-left: var(--space-4);
  white-space: nowrap;
}

.tb-nav-link {
  display: inline-flex;
  align-items: center;
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-pill);
  color: var(--ink-2);
  font-size: var(--fs-small);
  font-weight: var(--fw-medium);
}

.tb-nav-link:hover { background: var(--panel-2); color: var(--ink); text-decoration: none; }

.tb-nav-link[aria-current="page"] {
  background: var(--accent-tint);
  color: var(--accent);
  font-weight: var(--fw-semibold);
}

/* Right cluster. */
.tb-right {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  white-space: nowrap;
}

/* Market-phase pill (state colouring on top of the shared .dot). */
.tb-phase {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-1) var(--space-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  background: var(--surface-2);
  color: var(--ink-2);
  font-size: var(--fs-label);
  font-weight: var(--fw-medium);
}

.tb-phase-open {
  border-color: var(--up);
  background: var(--up-bg);
  color: var(--up-fg);
}

.tb-phase-pre,
.tb-phase-post {
  border-color: var(--warn-border);
  background: var(--warn-bg);
  color: var(--warn-fg);
}

/* Connection state (text colour from styles.css .conn-ok|.warn|.bad). */
.tb-conn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  color: var(--muted);
  font-size: var(--fs-label);
}

/* Feed badge, e.g. "IEX". */
.tb-feed {
  display: inline-flex;
  align-items: center;
  padding: var(--space-1) var(--space-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  color: var(--ink-2);
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-label);
}

/* Last-updated stamp; the value itself is .num (mono) from styles.css. */
.tb-updated {
  display: inline-flex;
  align-items: baseline;
  gap: var(--space-1);
  color: var(--muted);
  font-size: var(--fs-label);
}

.tb-updated .num { color: var(--ink-2); }

/* Refresh and theme icon buttons — one rule so the two share the exact same
 * size and hit area. The focus ring is styles.css :focus-visible (not
 * suppressed here). */
.tb-refresh,
.tb-theme {
  appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface-2);
  color: var(--ink-2);
  cursor: pointer;
  transition: color var(--dur-fast) ease, border-color var(--dur-fast) ease,
    background var(--dur-fast) ease;
}

.tb-refresh:hover,
.tb-theme:hover { color: var(--ink); border-color: var(--panel-border-strong); }
.tb-refresh:disabled { opacity: 0.5; cursor: default; }
.tb-refresh:disabled:hover { border-color: var(--border); color: var(--ink-2); }

.tb-refresh[aria-busy="true"] svg {
  animation: tb-spin var(--dur) linear infinite;
}

@keyframes tb-spin {
  to { transform: rotate(360deg); }
}

/* Account area (AccountMenu) and the local-mode Settings gear. */
.tb-account { display: inline-flex; align-items: center; }

.tb-gear {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: var(--radius);
  border: 1px solid transparent;
  background: none;
  color: var(--ink-2);
}

.tb-gear:hover { background: var(--panel-2); color: var(--ink); text-decoration: none; }

/* The Login action — what a visitor WITHOUT an account gets instead of the
 * account menu (public volume plan §6). The homepage redesign §3 makes it
 * the bar's only filled item: small, radius-sm, no border — the mockups'
 * 7px 14px padding (14px has no spacing token; space-3 + 2px is its size). */
.tb-login {
  display: inline-flex;
  align-items: center;
  padding: 7px calc(var(--space-3) + 2px);
  border: 0;
  border-radius: var(--radius-sm);
  background: var(--accent);
  color: var(--accent-fg);
  font-size: var(--fs-small);
  font-weight: var(--fw-medium);
  line-height: 1.4;
  text-decoration: none;
}

.tb-login:hover { text-decoration: none; }

/* Capability switches (public volume plan §6): a control the visitor may
 * not use must REALLY disappear. The class rules above set `display`, which
 * would otherwise beat the user agent's [hidden] rule. */
.tb-nav[hidden],
.tb-refresh[hidden],
.tb-gear[hidden],
.tb-login[hidden] { display: none; }

/* =========================================================================
   Phone chrome (MOBILE_PLAN.md §2.3, P7)
   ========================================================================= */

/* Status chip — phones only (shown in the breakpoint block below). Same dot
   palette as the desktop cluster; the phase classes colour it like the pill.
   Its detail is a components/popover.js toggletip. */
.tb-status {
  appearance: none;
  position: relative;
  display: none;
  align-items: center;
  gap: var(--space-1);
  height: 32px;
  padding: 0 var(--space-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  background: var(--surface-2);
  color: var(--ink-2);
  font: inherit;
  font-size: var(--fs-label);
  font-weight: var(--fw-medium);
  cursor: pointer;
}

/* Hit-area extension (pattern 1, §2.9): the chip is 32 px tall by design; a
   square, transparent overlay lifts the tap target to 44 px without changing
   the visual. No radius on the overlay, so the corners of the 44 px box are
   hittable too. */
.tb-status::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: max(100%, var(--hit-min));
  height: max(100%, var(--hit-min));
  transform: translate(-50%, -50%);
}

.tb-status:hover { border-color: var(--panel-border-strong); color: var(--ink); }

/* The chip takes the phase pill's state colours (these follow .tb-status so
   they win over its neutral skin). */
.tb-status.tb-phase-open {
  border-color: var(--up);
  background: var(--up-bg);
  color: var(--up-fg);
}

.tb-status.tb-phase-pre,
.tb-status.tb-phase-post {
  border-color: var(--warn-border);
  background: var(--warn-bg);
  color: var(--warn-fg);
}

/* Toggletip body (rendered inside the Popover bubble). */
.tb-status-detail {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-width: 0;
}

.tb-status-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-4);
  color: var(--ink-2);
}

.tb-status-row-label { color: var(--muted); }
.tb-status-row-value { color: var(--ink); font-weight: var(--fw-medium); }

.tb-status-message {
  margin: 0;
  color: var(--ink-2);
}

/* =========================================================================
   More sheet body (P7). The sheet itself is a components/sheet.js
   BottomSheet (`dialog.sheet.tb-more-sheet`); only its rows are styled here.
   ========================================================================= */

.tb-more-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding-bottom: var(--space-2);
}

.tb-more-account {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) 0 var(--space-3);
  margin-bottom: var(--space-1);
  border-bottom: 1px solid var(--border-subtle);
  min-width: 0;
}

.tb-more-avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--accent-tint);
  color: var(--accent);
  font-size: var(--fs-small);
  font-weight: var(--fw-semibold);
}

.tb-more-who {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.tb-more-name {
  color: var(--ink);
  font-size: var(--fs-small);
  font-weight: var(--fw-semibold);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tb-more-email {
  color: var(--muted);
  font-size: var(--fs-label);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tb-more-role {
  color: var(--muted);
  font-size: var(--fs-label);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.tb-more-local {
  margin: 0;
  padding: var(--space-2);
  color: var(--muted);
  font-size: var(--fs-label);
}

/* Rows: Settings link, theme toggle, Sign out — 44 px tall (§2.9 pattern 2). */
.tb-more-item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  min-height: var(--hit-min);
  padding: var(--space-2);
  border: 0;
  border-radius: var(--radius);
  background: none;
  color: var(--ink-2);
  font: inherit;
  font-size: var(--fs-small);
  font-weight: var(--fw-medium);
  text-align: left;
  cursor: pointer;
  text-decoration: none;
}

.tb-more-item[hidden] { display: none; }
.tb-more-item:hover { background: var(--panel-2); color: var(--ink); text-decoration: none; }
.tb-more-item[aria-current="page"] { color: var(--accent); }
.tb-more-item svg { display: block; flex: none; }
.tb-more-glyph { display: inline-flex; flex: none; }
.tb-more-signout:hover { color: var(--neg); }

/* The More sheet has no footer actions: keep the footer's safe-bottom
   padding (home indicator) but drop its divider and top padding. */
dialog.sheet.tb-more-sheet .sheet-foot:empty {
  border-top: 0;
  padding-top: 0;
}

/* =========================================================================
   Phone breakpoint (MOBILE_PLAN.md §2.3).
   ========================================================================= */

@media (max-width: 767.98px) {
  /* The bottom nav replaces the primary nav; the status chip replaces the
     connection / phase / feed / updated items; theme and account move into
     the More sheet. Refresh stays: the same button, 36 px visual. */
  .tb-nav,
  .tb-right > .tb-conn,
  .tb-right > .tb-phase,
  .tb-right > .tb-feed,
  .tb-right > .tb-updated,
  .tb-right > .tb-theme,
  .tb-right > .tb-account { display: none; }

  /* Brand | chip (centred in the free space) | Refresh. The row never wraps;
     the chip is the element that gives way. No overflow clip here: it would
     cut the 44 px hit overlay (the text span clips its own overflow). */
  .tb-status {
    display: inline-flex;
    margin-inline: auto;
    min-width: 0;
    max-width: 100%;
  }

  .tb-status-text {
    font-variant-numeric: tabular-nums;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .tb-right {
    margin-left: 0;
    flex: none;
  }

  /* Hit-area extension (pattern 1, §2.9): 36 px visual, 44 px target. The
     overlay is square (no radius) so the 44 px box's corners stay hittable. */
  .tb-right > .tb-refresh {
    position: relative;
    width: 36px;
    height: 36px;
    flex: none;
  }

  .tb-right > .tb-refresh::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: var(--hit-min);
    height: var(--hit-min);
    transform: translate(-50%, -50%);
  }

  /* §2.3: the phone bar is 48 px + safe-top. styles.css pads the bar
     7 px + 7 px, so the block padding is replaced by a fixed box: the notch
     inset on top, then 48 px (border included) with the row centred in it. */
  .topbar.tb-topbar {
    flex-wrap: nowrap;
    padding-top: var(--safe-top);
    padding-bottom: 0;
    min-height: calc(var(--topbar-h-phone) + var(--safe-top));
    height: calc(var(--topbar-h-phone) + var(--safe-top));
  }

  /* Brand stays at the left (§2.3): mark + wordmark from 375 px, the mark
     alone below (rule further down). 44 px hit area via pattern 1. */
  .tb-brand {
    position: relative;
    flex: none;
  }
  .tb-brand::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: max(100%, var(--hit-min));
    height: max(100%, var(--hit-min));
    transform: translate(-50%, -50%);
  }
}

@media (max-width: 374.98px) {
  /* xs: the mark only; the link keeps its "VolScope home" label. */
  .tb-wordmark { display: none; }
}

/* =========================================================================
   Tablet (768-1023): one row, always.
   =========================================================================
   styles.css `.topbar` is a wrapping flex row. The desktop content (brand +
   four nav links + the conn/phase/feed/updated cluster) needs ~876 px, so at
   768 the right cluster wrapped onto a second line and the bar grew to
   ~90 px. Nothing here is dropped: the row simply tightens (bar gap, nav
   margin and link padding, right-cluster gap, pill padding) and the
   "Updated" label word folds away — the timestamp itself stays. A rare long
   status label ("Authentication Failed") ellipsises instead of wrapping, so
   the bar can never grow a second row again. */

@media (min-width: 768px) and (max-width: 1023.98px) {
  .topbar.tb-topbar {
    flex-wrap: nowrap;
    gap: var(--space-2);
  }

  .tb-nav {
    margin-left: var(--space-2);
    gap: 0;
    min-width: 0;
  }

  .tb-nav-link {
    padding: var(--space-1);
  }

  .tb-right {
    gap: var(--space-2);
    min-width: 0;
  }

  /* The stamp is the datum; the word "Updated" is the luxury. */
  .tb-updated-label {
    display: none;
  }

  .tb-conn,
  .tb-phase,
  .tb-updated {
    min-width: 0;
  }

  /* The variable-width status words are the only parts that can blow the
     row out; they shrink with an ellipsis, the row never wraps. */
  .tb-conn-text,
  .tb-phase-text {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .tb-phase,
  .tb-feed {
    padding: var(--space-1);
  }
}

/* =========================================================================
   The public front door's bar (homepage redesign §3).
   =========================================================================
   A visitor without an account gets the header the approved homepage
   mockups show: a small status dot with "Market open" in body size (no pill
   chrome), "Updated 13:45 ET" in meta/quiet on the same line with plain
   spacing (no middle dots), a bare theme icon button and the small filled
   Login. The bar root carries .tb-public — components/top-bar.js sets it
   with the visitor capability set — so the signed-in bar keeps its own
   chrome (everything above this section) unchanged. */

/* The phase: the dot carries the state, the words read plain ink at body
   size. The compound .tb-phase.tb-phase-* selectors reach the desktop pill
   only — the phone status chip (tb-status + the same phase classes) keeps
   its own skin. */
.tb-public .tb-phase {
  gap: var(--space-2);
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  color: var(--ink);
  font-size: 15px;
  font-weight: var(--fw-regular);
}

.tb-public .tb-phase.tb-phase-open,
.tb-public .tb-phase.tb-phase-pre,
.tb-public .tb-phase.tb-phase-post {
  border: 0;
  background: none;
  color: var(--ink);
}

.tb-public .tb-phase .dot {
  width: 7px;
  height: 7px;
}

/* The freshness stamp in meta/quiet, sans: the dot carries the colour duty,
 * so the stamp stays quiet (the redesign keeps mono off the data labels). */
.tb-public .tb-updated {
  font-size: var(--fs-small);
  color: var(--muted);
}

.tb-public .tb-updated .num {
  color: var(--muted);
  font-family: inherit;
}

/* Desktop (≥1024): the mockup's header geometry. The contents sit on the
   page's content edge — the same column views/landing.css paints (a 1120px
   frame with 24px gutters inside the shell's 16px) — the 1px hairline spans
   that column rather than the window, and the bar stands on the page ground.
   The phone and tablet bars keep their pinned chrome (the blocks above). */
@media (min-width: 1024px) {
  .topbar.tb-topbar.tb-public {
    /* Content edge: below 1152 the landing column fills its frame and the
       edge is the shell's 16px plus the frame's 24px; above, the frame is
       centred and the edge is half of what is left over. */
    --tb-edge: max(calc(var(--space-4) + var(--space-6)), calc((100% - 1120px) / 2 + var(--space-6)));
    padding-block: 18px;
    padding-inline: var(--tb-edge);
    border-bottom: 0;
    background: var(--bg);
  }

  .topbar.tb-topbar.tb-public::after {
    content: "";
    position: absolute;
    left: var(--tb-edge);
    right: var(--tb-edge);
    bottom: 0;
    height: 1px;
    background: var(--border-subtle);
  }

  .tb-public .tb-right {
    gap: var(--space-5);
  }

  /* The mockup's bare theme icon button (the shared Refresh/theme rule
     keeps its pinned 30px box for the signed-in bar). */
  .tb-public .tb-theme {
    width: var(--space-7);
    height: var(--space-7);
    border-radius: var(--radius-sm);
    background: none;
    color: var(--ink);
  }
}
