/* ==========================================================================
   xStocks Terminal — Components
   Depends on css/theme.css and css/base.css. Load those files first.
   The narrow screen rules live in css/mobile.css. Load that file last, so the
   narrow rules win the cascade.
   ========================================================================== */

/* --- Top bar -------------------------------------------------------------- */
.topbar {
  position: sticky;
  inset-block-start: 0;
  z-index: var(--z-sticky);
  /* The status bar sits over the page in a standalone web app. */
  padding-block-start: env(safe-area-inset-top);
  border-block-end: 1px solid var(--border);
  background: var(--bg-page);
}

.topbar__inner {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  min-height: 60px;
}

.brand {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-width: 0;
}

/* The brand mark holds a square view box and no clear space, so it needs no
   padding. The parent gap sets the space before the name. */
.brand__logo-link {
  display: flex;
  flex-shrink: 0;
  text-decoration: none;
}

.brand__logo {
  display: block;
  inline-size: 28px;
  block-size: 28px;
}

.brand__name {
  font-size: var(--text-md);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-tight);
  white-space: nowrap;
}

.brand__name span {
  color: var(--text-muted);
  font-weight: var(--weight-regular);
}

.topbar__meta {
  margin-inline-start: auto;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  color: var(--text-faint);
  font-size: var(--text-xs);
}

/* The brand mark links out. The text stays muted, so the rule drops the
   underline that the global anchor rule adds. */
.topbar__link {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  color: var(--text-faint);
  font-size: var(--text-md);
  text-decoration: none;
}

.topbar__icon {
  display: block;
  inline-size: 28px;
  block-size: 28px;
  opacity: 0.7;
}

/* --- Hero ----------------------------------------------------------------- */
.hero {
  padding-block: var(--space-8) var(--space-6);
}

.hero h1 {
  max-width: 22ch;
  margin-block-end: var(--space-4);
}

.hero__lede {
  color: var(--text-muted);
  font-size: var(--text-md);
  max-width: 54ch;
}

/* --- Grid ----------------------------------------------------------------- */
.grid {
  display: grid;
  gap: var(--space-4);
}

.grid--cards {
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr));
}

/* --- Card ----------------------------------------------------------------- */
.card {
  background: var(--bg-surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  padding: var(--space-5);
}

.card--raised {
  background: var(--bg-raised);
  border-color: var(--border);
}

/* A quiet accent border. One thickness on every edge. */
.card--accent {
  border-color: var(--accent-line);
}

/* The hero holds the three headline readings. Its small text takes the muted
   grey, one step lighter than the faint grey, so the label and the hint read
   clear against the bright border. */
.card--accent .eyebrow,
.card--accent .metric__hint {
  color: var(--text-muted);
}

.card__label {
  display: block;
  margin-block-end: var(--space-3);
}

/* --- Metric --------------------------------------------------------------- */
.metric__value {
  font-family: var(--font-mono);
  font-size: var(--text-xl);
  font-weight: var(--weight-medium);
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}

.metric__hint {
  margin-block-start: var(--space-3);
  color: var(--text-faint);
  font-size: var(--text-xs);
}

/* --- Stats strip ---------------------------------------------------------- */
/* One card holds every reading. A hard rule separates the items on a wide card.
   The items stack on a narrow card. */
.stats__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-5);
}

.stats__item {
  min-width: 0;
}

/* A wide screen takes three columns. The value clears the narrow query in
   css/mobile.css, so the 720px case takes the narrow rules. */
@media (min-width: 720.02px) {
  .stats__grid {
    grid-template-columns: repeat(3, 1fr);
    gap: 0;
  }

  .stats__item {
    padding-inline: var(--space-5);
  }

  .stats__item:first-child {
    padding-inline-start: 0;
  }

  .stats__item:last-child {
    padding-inline-end: 0;
  }

  .stats__item + .stats__item {
    border-inline-start: 1px solid var(--border-subtle);
  }
}

/* --- Button --------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: 0.6rem 1.1rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--bg-raised);
  color: var(--text-primary);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  white-space: nowrap;
  transition: background-color var(--duration-fast) var(--ease-out),
    border-color var(--duration-fast) var(--ease-out),
    transform var(--duration-fast) var(--ease-out);
}

.btn:active {
  transform: translateY(1px);
}

.btn--primary {
  border-color: var(--accent);
  background-color: var(--accent);
  color: var(--accent-contrast);
  font-weight: var(--weight-bold);
}

.btn--ghost {
  background: transparent;
}

/* --- Search --------------------------------------------------------------- */
.search {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  margin-block-end: var(--space-4);
}

.search__input {
  flex: 1 1 240px;
  min-width: 0;
  padding: 0.6rem 0.9rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--bg-surface);
  color: var(--text-primary);
  font-size: var(--text-sm);
  transition: border-color var(--duration-fast) var(--ease-out);
}

.search__input::placeholder {
  color: var(--text-faint);
}

/* The global teal focus ring is off here. A light grey line marks the focus. */
.search__input:focus-visible {
  outline: none;
  box-shadow: none;
  border-color: var(--grey-400);
}

/* --- Table ---------------------------------------------------------------- */
/* The table uses separate borders, not collapsed ones. Safari mispaints a
   sticky header cell in a collapsed table. It then shows a 1px strip of the
   moving rows above the header. The separate model puts the cell box on the
   edge of the scrollport. The spacing is zero, so the cells keep the look of
   one joined table. */
.table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: var(--text-sm);
}

.table th {
  text-align: start;
  padding: var(--space-3) var(--space-4);
  border-block-end: 1px solid var(--border);
  /* The label sits on a veiled fill. A bright color keeps it readable there. */
  color: var(--text-primary);
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  font-weight: var(--weight-medium);
  text-transform: uppercase;
  letter-spacing: var(--tracking-wide);
}

.table th.is-numeric,
.table td.is-numeric {
  text-align: end;
}

.table td {
  padding: var(--space-3) var(--space-4);
  border-block-end: 1px solid var(--border-subtle);
  color: var(--text-secondary);
}

.table tbody tr {
  transition: background-color var(--duration-fast) var(--ease-out);
}

/* The row holds the logo, the name, and the symbol in one flex line. The logo
   keeps its full size, whatever width the column takes. */
.table__asset {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  color: var(--text-primary);
}

.table__logo {
  inline-size: 40px;
  block-size: 40px;
  max-width: none;
  flex: none;
  object-fit: contain;
  border-radius: var(--radius-md);
  background: var(--bg-raised);
  border: 1px solid var(--border-subtle);
}

/* A missing file shows a letter tile, so a broken logo stays visible. */
.table__logo--empty {
  display: grid;
  place-items: center;
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: var(--text-md);
  text-transform: uppercase;
}

.table__name {
  color: var(--text-primary);
  font-size: var(--text-md);
  font-weight: var(--weight-medium);
  overflow-wrap: anywhere;
}

.table__sep {
  color: var(--text-faint);
  font-size: var(--text-md);
}

.table__sym {
  font-family: var(--font-mono);
  font-size: var(--text-md);
  color: var(--text-muted);
}

/* --- Market cap rank ------------------------------------------------------ */
/* The rank takes a narrow column. The two numbers use the mono face, so the
   digits line up down the column. */
.table .col-rank {
  inline-size: 1%;
  white-space: nowrap;
}

.table__rank {
  color: var(--text-faint);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
}

.table__cap {
  color: var(--text-primary);
  font-family: var(--font-mono);
  font-size: var(--text-md);
  white-space: nowrap;
}

.table__share {
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: var(--text-md);
  white-space: nowrap;
}

/* --- Sector rows and region rows ------------------------------------------ */
/* The sector table and the region table share one set of rules. Each rule lists
   both views, so the two tables stay in step.
   The whole row toggles the asset list below it. The button carries the state
   for the keyboard and for a screen reader. */
.sector-row,
.region-row {
  cursor: pointer;
}

.table .sector__toggle,
.table .region__toggle {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  inline-size: 100%;
  color: var(--text-primary);
  font-weight: var(--weight-medium);
  text-align: start;
}

.sector__caret,
.region__caret {
  flex: none;
  color: var(--text-faint);
  font-size: var(--text-sm);
  line-height: 1;
  transition: transform var(--duration-fast) var(--ease-out);
}

.sector__toggle[aria-expanded="true"] .sector__caret,
.region__toggle[aria-expanded="true"] .region__caret {
  transform: rotate(90deg);
}

.sector__toggle[aria-expanded="true"] .sector__label,
.region__toggle[aria-expanded="true"] .region__label {
  color: var(--accent-alt);
}

/* The detail row holds the assets of one group. The sunken fill groups the
   open list. The row takes no fill of its own. */
.table .sector__cell,
.table .region__cell {
  padding-block: var(--space-4);
  background: var(--bg-sunken);
}

.table .sector__assets,
.table .region__assets {
  display: grid;
  gap: var(--space-3);
  margin-inline-start: var(--space-2);
  padding-inline-start: var(--space-5);
  border-inline-start: 1px solid var(--border-subtle);
  list-style: none;
}

/* The line holds the asset block and the market cap value. The block takes the
   free space, so the value sits at the end of the line. The block may shrink,
   so a long name wraps and does not press the value out of the row. */
.table .sector__item,
.table .region__item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.table .sector__item .table__asset,
.table .region__item .table__asset {
  flex: 1 1 auto;
  min-inline-size: 0;
}

.table .sector__item .table__cap,
.table .region__item .table__cap {
  flex: none;
}

/* --- View panels ---------------------------------------------------------- */
/* One panel for each view button. The script shows the panel that pairs with
   the picked button and hides the rest. An empty panel takes no space, so the
   section measures the height of the open view. */
.view-panel[hidden] {
  display: none;
}

/* --- Asset list ----------------------------------------------------------- */
.table__status {
  margin-block-end: var(--space-3);
  color: var(--text-faint);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
}

/* The body scrolls. The header holds its place. */
/* The wrap has no top border. WebKit measures the sticky offset against the
   border box of the wrap. A top border then leaves a 1px band above the
   header. The moving rows show through that band. A zero top border removes
   the band, because the border box and the padding box then share one edge.
   The header cell draws the top line instead. */
.table-wrap {
  max-block-size: 70vh;
  overflow: auto;
  border: 0;
  border-inline: 1px solid var(--border-subtle);
  border-block-end: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  background: var(--bg-surface);
}

.table-wrap thead th {
  position: sticky;
  inset-block-start: 0;
  z-index: var(--z-raised);
  background: var(--bg-raised);
  /* The top border draws the top edge of the table. The cell holds that edge
     inside its own box. No paint then leaves the box, so the header cannot
     grow by one pixel while the body moves. The inset line draws the bottom
     edge and takes no space, so the header keeps its height. */
  border-block-start: 1px solid var(--border-subtle);
  border-block-end: none;
  box-shadow: inset 0 -1px 0 var(--border);
}

/* Glass header. The veil is light, so the rows stay visible through it. The
   blur softens those rows while they move under the header. The test covers
   both spellings, because older Safari ships the prefixed property only. A
   browser that fails the test keeps the opaque fill of the rule above. */
@supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .table-wrap thead th {
    background: var(--bg-veil);
    -webkit-backdrop-filter: blur(10px) saturate(120%);
    backdrop-filter: blur(10px) saturate(120%);
  }
}

/* Hidden rows leave the layout, so the scroll height follows the filter. */
.table tbody tr[hidden] {
  display: none;
}

/* The single column holds the whole entry: logo, name, and symbol. */
.table .col-asset {
  inline-size: 100%;
}

/* --- Asset detail ---------------------------------------------------------- */
/* The whole row opens the panel below it. The row shows the pointer, the same
   rule as a sector row. */
.asset-row {
  cursor: pointer;
}

/* The button fills the cell, so a press on the line lands. It carries the state
   for the keyboard and for a screen reader. */
.asset__toggle {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  inline-size: 100%;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  text-align: start;
  cursor: pointer;
}

/* The row content takes the free space, so a long name wraps instead of
   pressing a value out of the line. */
.asset__toggle .table__asset {
  flex: 1 1 auto;
  min-inline-size: 0;
}

/* The drawer line holds the button and nothing else. The button takes the free
   space, so the market cap value stays at the end of the line. */
.table .sector__item .asset__toggle,
.table .region__item .asset__toggle {
  flex: 1 1 auto;
  min-inline-size: 0;
}

/* The detail cell takes no inset of its own. The body holds the inset, so the
   panel fill runs the full width of the table. */
.table .asset__cell {
  padding: 0;
}

/* The panel body. The sunken fill groups the open panel, the same fill that the
   group lists take. */
.asset__body {
  padding: var(--space-3) var(--space-4);
  background: var(--bg-sunken);
}

/* The field list. One label takes each left cell and one value each right cell.
   The column takes the width of the longest label, so the values line up. */
.asset__fields {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-2) var(--space-4);
  margin: 0;
}

.asset__label {
  color: var(--text-faint);
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  font-weight: var(--weight-medium);
  text-transform: uppercase;
  letter-spacing: var(--tracking-wide);
}

/* The value clears the default inset of a definition value, so the grid cells
   hold the alignment. */
.asset__value {
  margin: 0;
  color: var(--text-primary);
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  font-variant-numeric: tabular-nums;
}

/* The link reads as the value text: one font, one size, and one color, with no
   border, no fill, and no underline. The pointer rule below adds the accent
   color and the underline, so the plain text still answers the mouse. */
.asset__link {
  color: inherit;
  text-decoration: none;
}

/* The detail node leaves the layout while it is closed. A list item needs the
   rule, because a display value on the node would beat the user agent style. */
.asset__detail[hidden] {
  display: none;
}

/* --- Footer --------------------------------------------------------------- */
.footer {
  margin-block-start: auto;
  padding-block: var(--space-6);
  /* The home indicator sits over the page on a modern phone. */
  padding-block-end: max(var(--space-6), env(safe-area-inset-bottom));
  /* iPad Safari lays the page out against the large viewport. The visible area
     is then shorter than that box by the height of the browser bars. The last
     band of the page can then hide at the bottom edge. This reserve covers
     that band, so the last line stays in view. Both units are constant, so the
     page does not shift while it moves. A browser without the units keeps the
     value above. */
  padding-block-end: calc(
    max(var(--space-6), env(safe-area-inset-bottom)) +
      clamp(0px, 100lvh - 100svh, 8rem)
  );
  /* The fill stays opaque, so the dot field never shows through the band. The
     value matches the top bar, so the two chrome bands read as one pair. */
  background: var(--bg-page);
  border-block-start: 1px solid var(--border-subtle);
  color: var(--text-faint);
  font-size: var(--text-xs);
}

.footer__inner {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  align-items: center;
  justify-content: space-between;
}

/* --- App state ------------------------------------------------------------ */
[data-app-state="loading"] .table__status {
  color: var(--text-muted);
}

[data-app-state="error"] .table-wrap {
  border-color: var(--negative);
}

[data-app-state="error"] .table__status {
  color: var(--negative);
}

/* --- Pointer -------------------------------------------------------------- */
/* Hover belongs to a mouse. A touch screen reads the pressed state only, so a
   tap never leaves a row lit after the finger lifts. */
@media (hover: hover) {
  a:hover {
    text-decoration-color: currentColor;
  }

  .topbar__link:hover {
    color: var(--text-muted);
  }

  .topbar__link:hover .topbar__icon {
    opacity: 1;
  }

  .btn:hover {
    background: var(--bg-hover);
    border-color: var(--border-strong);
  }

  .btn--primary:hover {
    border-color: var(--sol-purple-deep);
    background-color: var(--sol-purple-deep);
  }

  /* The EDGAR link. The color and the underline arrive together, so the link
     reads as plain text until the pointer reaches it. */
  .asset__link:hover {
    color: var(--accent-alt);
    text-decoration: underline;
    text-decoration-color: currentColor;
  }

  .section-head__btn:hover {
    border-color: var(--border-strong);
  }

  /* The selected toggle keeps its accent border under the pointer. The selected
     rule in base.css and the hover rule above carry the same specificity. The
     later file wins while the pointer is on the button, so the grey border
     would replace the accent and the selection would then look cleared. This
     rule outranks the hover rule, because it adds one more state. The border
     holds the accent. The selected control takes no hover fill, so its look
     stays constant under the pointer. */
  .section-head__btn[aria-pressed="true"]:hover {
    border-color: var(--accent-line);
  }

  .search__input:hover {
    border-color: var(--border-strong);
  }

  .table tbody tr:hover {
    background: var(--bg-raised);
  }

  .table tbody tr.sector__detail:hover,
  .table tbody tr.region__detail:hover {
    background: none;
  }
}

/* --- Pressed state -------------------------------------------------------- */
/* A tap must show an answer at once, because a touch screen holds no hover. */
.table tbody tr:active {
  background: var(--bg-raised);
}

.table tbody tr.sector__detail:active,
.table tbody tr.region__detail:active {
  background: none;
}

.section-head__btn:active {
  border-color: var(--border-strong);
}

/* The selected toggle keeps the accent while pressed. The reason matches the
   hover case above. */
.section-head__btn[aria-pressed="true"]:active {
  border-color: var(--accent-line);
}

/* --- Motion --------------------------------------------------------------- */
@keyframes rise {
  from {
    opacity: 0;
    transform: translateY(12px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.animate-rise {
  animation: rise var(--duration-slow) var(--ease-out) both;
}

/* --- Wide layout, one scroll area ----------------------------------------- */
/* A tablet in portrait is wider than 720px, so it takes the wide layout. That
   layout holds a second scroll area inside the table. The finger moves the
   table in place of the page, so the footer never arrives.
   The sector table carries 13 rows and stands about 890px tall. The cap holds
   717px at a 1024px viewport, so that table just overflows the cap. The page
   keeps almost no scroll room of its own.
   Two cases get one scroll area, as the narrow layout does. A touch screen
   reports hover: none. A viewport of 1024px or less leaves the page no room
   under the cap.
   A mouse on a wider screen keeps the two scroll areas, because the mouse
   reaches the page through the top bar and the search field. The cap also
   keeps the long list out of the page.
   The top bar holds 60px. The header pins below that bar. */
@media (min-width: 721px) and (hover: none),
  (min-width: 721px) and (max-width: 1024px) {
  .table-wrap {
    max-block-size: none;
    overflow: visible;
  }

  .table-wrap thead th {
    inset-block-start: calc(60px + env(safe-area-inset-top));
  }
}
