/* Exchange — prices-page market surface riding the app shell.
   The shell owns the rails; this file owns the market elements inside them. */

.shell-main--exchange {
  max-width: var(--foinse-breakpoint-2xl);
}

.xchange-sr {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
}

/* Page head */
.xchange-head {
  display: flex;
  align-items: center;
  gap: var(--foinse-space-6);
  flex-wrap: wrap;
  margin: 0 0 var(--foinse-space-2);
}
.xchange-head h1 {
  margin: 0;
  font-size: var(--foinse-font-size-heading-2);
  line-height: var(--foinse-font-line-heading-2);
  font-weight: var(--foinse-font-weight-semibold);
  letter-spacing: -0.01em;
}

/* Stat strip — market vitals beside the title (overrides shell dl chrome) */
.xchange-head dl.xchange-stats {
  display: flex;
  gap: var(--foinse-space-8);
  margin: 0 0 0 auto;
  padding: 0;
  background: none;
  border-radius: 0;
}
.xchange-stats div { text-align: right; }
.xchange-stats dt {
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--foinse-text-muted);
}
.xchange-stats dd {
  margin: 0;
  font-family: var(--foinse-font-family-mono);
  font-size: var(--foinse-font-size-label);
  font-weight: var(--foinse-font-weight-semibold);
  color: var(--foinse-text-primary);
  font-variant-numeric: var(--foinse-font-feature-numeric);
}

/* Tape: one quiet status line */
.xchange-tape {
  display: flex;
  flex-wrap: wrap;
  gap: var(--foinse-space-2) var(--foinse-space-5);
  margin: 0 0 var(--foinse-space-4);
  padding: 0 var(--foinse-space-1);
  font-size: 12px;
  color: var(--foinse-text-muted);
  font-variant-numeric: var(--foinse-font-feature-numeric);
}
.xchange-tape #exchange-status { color: var(--foinse-text-secondary); }
.xchange-tape #exchange-status[data-tone="success"] { color: var(--foinse-color-reserve); }
.xchange-tape #exchange-status[data-tone="warning"] { color: var(--foinse-color-caution); }
.xchange-tape #exchange-status[data-tone="error"] { color: var(--foinse-color-error); }
.xchange-tape span:empty { display: none; }
.xchange-tape:not(:has(span:not(:empty))) { display: none; }
#exchange-rail-state, #exchange-backing-state {
  font-family: var(--foinse-font-family-mono);
  font-size: 11px;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}

/* Book panel — full width of the main rail */
.xchange-book {
  padding: 0;
  overflow: hidden;
}
.xchange-book__head {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  padding: var(--foinse-space-2) var(--foinse-space-4);
  border-bottom: var(--foinse-border);
}
.xchange-book__head .foinse-btn { min-height: 32px; }
/* The book refreshes itself; no manual control on the surface.
   The button stays in the DOM for the engine. */
#exchange-refresh-book { display: none; }

/* Price is the lead number in every row. */
#book-board .xchange-table td:nth-child(3) {
  font-size: var(--foinse-font-size-body);
  font-weight: var(--foinse-font-weight-semibold);
  color: var(--foinse-text-primary);
}

/* Prices table — coin rows, sticky header */
.xchange-book__board { overflow-x: auto; }
.xchange-book .xchange-table,
.xchange-desk .xchange-table {
  width: 100%;
  margin-top: 0;
  border-collapse: collapse;
  font-size: var(--foinse-font-size-label);
  font-variant-numeric: var(--foinse-font-feature-numeric);
}
.xchange-table thead th {
  position: sticky;
  top: 0;
  background: var(--foinse-surface-card);
  z-index: 1;
  text-align: left;
  font-size: 11px;
  font-weight: var(--foinse-font-weight-semibold);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--foinse-text-muted);
  padding: var(--foinse-space-3);
  border-bottom: var(--foinse-border);
  white-space: nowrap;
}
.xchange-table th.num, .xchange-table td.num { text-align: right; }
.xchange-table td {
  padding: var(--foinse-space-4) var(--foinse-space-3);
  border-bottom: var(--foinse-border);
  vertical-align: middle;
}
.xchange-table tbody tr { transition: background var(--foinse-motion-duration-ui) var(--foinse-motion-easing); }
.xchange-table tbody tr:hover { background: var(--foinse-surface-recessed); }
.xchange-table tbody tr.is-selected { background: var(--foinse-color-accent-tint); }
.xchange-table tbody tr:last-child td { border-bottom: 0; }
.xchange-table td span { display: block; }
.xchange-table .exchange-empty-cell {
  color: var(--foinse-text-muted);
  font-size: 12px;
}
.xchange-table .exchange-reason { color: var(--foinse-color-caution); }

/* First cell becomes a coin identity: icon + name */
#book-rows td:first-child {
  display: flex;
  align-items: center;
  gap: var(--foinse-space-3);
}
.xchange-coin-icon {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  object-fit: contain;
  flex: none;
}
#book-rows td:first-child strong {
  font-size: var(--foinse-font-size-body);
  font-weight: var(--foinse-font-weight-semibold);
  letter-spacing: -0.01em;
}

/* Numeric cells read like prices */
#book-rows td[data-label="Price / 1M tokens"] span,
#book-rows td[data-label="Available, backed"] span {
  font-family: var(--foinse-font-family-mono);
  font-size: var(--foinse-font-size-body);
  font-weight: var(--foinse-font-weight-medium);
}
#book-rows td[data-label="Against provider list"] span:first-child {
  font-family: var(--foinse-font-family-mono);
  font-size: 12px;
  color: var(--foinse-text-muted);
}
#book-rows td[data-label="Against provider list"] .exchange-empty-cell {
  display: inline-block;
  color: var(--foinse-color-reserve);
  background: var(--foinse-color-reserve-tint);
  font-weight: var(--foinse-font-weight-semibold);
  font-size: 12px;
  padding: 2px 8px;
  border-radius: var(--foinse-radius-badge);
}

/* Trade pill */
.exchange-row-button {
  min-height: 36px;
  padding: 0 var(--foinse-space-5);
  border-radius: 999px;
  font-size: var(--foinse-font-size-label);
  font-weight: var(--foinse-font-weight-semibold);
}

/* Placeholder asset rows when the book is empty */
.xchange-placeholder-row { cursor: pointer; }
.xchange-placeholder-row .xchange-coin-name {
  color: var(--foinse-text-primary);
  font-size: var(--foinse-font-size-body);
  font-weight: var(--foinse-font-weight-semibold);
  letter-spacing: -0.01em;
}
.xchange-placeholder-row td[data-ph="units"],
.xchange-placeholder-row td[data-ph="price"],
.xchange-placeholder-row td[data-ph="vs"] {
  text-align: right;
  font-family: var(--foinse-font-family-mono);
}

/* Rail column stays in the DOM for the engine but never renders. */
#book-board .xchange-table th:nth-child(5),
#book-board .xchange-table td:nth-child(5) { display: none; }

/* Empty state text (kept for error paths) */
.xchange-empty {
  padding: var(--foinse-space-8) var(--foinse-space-6);
  text-align: center;
}
.xchange-empty__title {
  margin: 0 0 var(--foinse-space-2);
  font-size: var(--foinse-font-size-heading-3);
  font-weight: var(--foinse-font-weight-semibold);
}
.xchange-empty p { color: var(--foinse-text-secondary); }

/* Tabs (ticket rail and desk) */
.xchange-tabs {
  display: flex;
  border-bottom: var(--foinse-border);
}
.xchange-ticket .xchange-tabs {
  background: var(--foinse-surface-page);
  border: var(--foinse-border);
  border-radius: var(--foinse-radius-card);
  overflow: hidden;
  margin-bottom: var(--foinse-space-2);
}
.xchange-tab {
  flex: 1;
  padding: var(--foinse-space-4) var(--foinse-space-3);
  border: 0;
  background: none;
  font: inherit;
  font-size: var(--foinse-font-size-label);
  font-weight: var(--foinse-font-weight-semibold);
  color: var(--foinse-text-muted);
  cursor: pointer;
  border-bottom: 2px solid transparent;
  transition: color var(--foinse-motion-duration-ui) var(--foinse-motion-easing);
}
.xchange-tab:hover { color: var(--foinse-text-primary); }
.xchange-tab.is-active {
  color: var(--foinse-text-primary);
  border-bottom-color: var(--foinse-color-accent);
}
.xchange-tab:focus-visible {
  outline: var(--foinse-focus-ring);
  outline-offset: calc(-1 * var(--foinse-focus-width));
}
.xchange-ticket h2 {
  margin: 0 0 var(--foinse-space-2);
  font-size: var(--foinse-font-size-heading-3);
  line-height: var(--foinse-font-line-heading-3);
}
.xchange-ticket .ticket-hint p {
  margin: 0;
  font-size: var(--foinse-font-size-label);
  color: var(--foinse-text-secondary);
}

/* Desk: full-width tabbed panel under the book */
.xchange-desk {
  margin-top: var(--foinse-space-5);
  background: var(--foinse-surface-card);
  border: var(--foinse-border);
  border-radius: var(--foinse-radius-card);
  overflow: hidden;
}
.xchange-desk section { padding: var(--foinse-space-5); }
/* Balances live in the sell flow and the wallet, not on the book.
   The desk stays in the DOM for the engine; it never renders here. */
.shell-main--exchange > .xchange-desk { display: none; }
.xchange-form-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--foinse-space-3);
  max-width: 640px;
}
.xchange-form-state {
  font-size: 12px;
  color: var(--foinse-text-muted);
}
.xchange-desk dl, .exchange-holdings dl {
  font-size: 12px;
  word-break: break-word;
}
.xchange-desk dt, .exchange-holdings dt { color: var(--foinse-text-muted); }
.xchange-desk dd, .exchange-holdings dd {
  margin: 0 0 var(--foinse-space-1);
  font-family: var(--foinse-font-family-mono);
}
.exchange-holdings {
  border: var(--foinse-border);
  border-radius: var(--foinse-radius-control);
  padding: var(--foinse-space-3);
  margin: var(--foinse-space-3) 0;
}
.form-note { font-size: 12px; color: var(--foinse-text-muted); }

/* Ticket stages — the card reads top to bottom: amount, action, detail.
   The engine owns the ids; the stages own the layout. */
.ticket-stage--amount { padding: var(--foinse-space-4) 0; }
.ticket-amount { display: block; }
.ticket-amount__label {
  display: block;
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--foinse-text-muted);
  margin-bottom: var(--foinse-space-1);
}
.ticket-amount input {
  width: 100%;
  font-family: var(--foinse-font-family-mono);
  font-size: 28px;
  font-weight: var(--foinse-font-weight-semibold);
  font-variant-numeric: var(--foinse-font-feature-numeric);
  letter-spacing: -0.01em;
  padding: var(--foinse-space-3) var(--foinse-space-4);
}
.ticket-summary {
  margin: var(--foinse-space-3) 0 0;
  padding: var(--foinse-space-3) var(--foinse-space-4);
  background: var(--foinse-surface-recessed);
  border-radius: var(--foinse-radius-control);
  font-size: var(--foinse-font-size-label);
}
.ticket-summary:empty { display: none; }
.ticket-summary dd { font-family: var(--foinse-font-family-mono); }
.ticket-stage--action {
  display: flex;
  flex-direction: column;
  gap: var(--foinse-space-2);
  margin: var(--foinse-space-2) 0 var(--foinse-space-3);
}
.ticket-buy {
  width: 100%;
  min-height: 52px;
  font-size: var(--foinse-font-size-body);
}
.ticket-clear { align-self: center; }
.ticket-stage--detail {
  border-top: var(--foinse-border);
  padding-top: var(--foinse-space-3);
  font-size: 12px;
  color: var(--foinse-text-muted);
}
.ticket-stage--detail dl { font-size: 12px; }
.ticket-stage--detail dd { margin: 0; font-family: var(--foinse-font-family-mono); }

/* Narrow viewports: the shell folds the action rail under the main column */
@media (max-width: 1100px) {
  .xchange-form-row { grid-template-columns: 1fr; }
  .xchange-head { gap: var(--foinse-space-4); }
  .xchange-head dl.xchange-stats { margin-left: 0; gap: var(--foinse-space-4); }
}

/* ============================================================
   EXCHANGE PAGE PASS — scoped overrides for this page only.
   Shell overrides live under body.app-shell--exchange so the
   other shell pages are untouched. Nothing here renames or
   restructures; every rule works against the frozen DOM ids.
   ============================================================ */

/* --- Top bar and side rail off on this page: the exchange is the
   page. The grid is one column; the ticket is a sheet that slides
   over it on Trade intent instead of squatting as a column. --- */
body.app-shell--exchange {
  --shell-top-height: 0px;
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: minmax(0, 1fr);
  grid-template-areas: "main";
}
body.app-shell--exchange .shell-top,
body.app-shell--exchange .shell-rail { display: none; }

body.app-shell--exchange .shell-actions {
  position: fixed;
  top: 0;
  right: 0;
  z-index: 60;
  flex-direction: column;
  flex-wrap: nowrap;
  width: min(420px, 100vw);
  height: 100vh;
  max-height: none;
  overflow-y: auto;
  background: var(--foinse-surface-card);
  border-left: var(--foinse-border);
  box-shadow: -16px 0 40px rgb(28 25 23 / 0.12);
  transform: translateX(105%);
  transition: transform 180ms ease;
}
body.app-shell--exchange.exchange-ticket-open .shell-actions { transform: translateX(0); }
body.app-shell--exchange.exchange-ticket-open { overflow: hidden; }

.exchange-scrim {
  position: fixed;
  inset: 0;
  z-index: 50;
  background: rgb(28 25 23 / 0.32);
  opacity: 0;
  pointer-events: none;
  transition: opacity 180ms ease;
}
body.exchange-ticket-open .exchange-scrim {
  opacity: 1;
  pointer-events: auto;
}

.exchange-sheet-close {
  align-self: flex-end;
  margin: 0 0 var(--foinse-space-2);
  padding: 0;
  border: 0;
  background: none;
  color: var(--foinse-text-muted);
  font: inherit;
  font-size: var(--foinse-font-size-label);
  cursor: pointer;
}
.exchange-sheet-close:hover { color: var(--foinse-text-primary); }

/* shell.css re-asserts the grid at 1024px and 640px; mirror both. */
@media (max-width: 1024px) {
  body.app-shell--exchange {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: minmax(0, 1fr);
    grid-template-areas: "main";
  }
}
@media (max-width: 640px) {
  body.app-shell--exchange {
    --shell-top-height: 0px;
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: minmax(0, 1fr);
    grid-template-areas: "main";
  }
  body.app-shell--exchange .shell-actions {
    width: 100vw;
    border-left: 0;
  }
}

/* --- Ticket/desk state labels vanish until they carry text.
   The state span is not the paragraph's only child ("Row: ",
   "Order: " lead it), so scope the emptiness test to the ids. --- */
.xchange-form-state:has(> #trade-row-state:empty),
.xchange-form-state:has(> #trade-order-state:empty):has(> #trade-order-message:empty),
.xchange-form-state:has(> #supply-result-state:empty),
.xchange-form-state:has(> #sell-result-state:empty) {
  display: none;
}

/* --- Units field: typed value stays 28px/600 mono, the empty
   state reads as an invitation instead of data. --- */
.ticket-amount input::placeholder {
  color: var(--foinse-text-disabled);
  font-weight: var(--foinse-font-weight-regular);
  opacity: 1;
}

/* --- Unified quiet underline tabs. The ticket tabs lose their
   boxed segmented-card chrome and match the desk tabs: 14px/600,
   muted, ink when .is-active, 2px accent underline. --- */
.xchange-ticket .xchange-tabs {
  background: none;
  border: 0;
  border-bottom: var(--foinse-border);
  border-radius: 0;
  margin-bottom: var(--foinse-space-3);
}
.xchange-desk .xchange-tabs { gap: var(--foinse-space-5); }
.xchange-desk .xchange-tab { flex: 0 0 auto; }
/* "List supply" is a seller feature in a buyer's first-run view;
   keep it a step quieter than its peer, active state included. */
#xchange-tab-supply {
  font-size: 13px;
  color: var(--foinse-text-disabled);
}
#xchange-tab-supply:hover { color: var(--foinse-text-muted); }
#xchange-tab-supply.is-active { color: var(--foinse-text-secondary); }

/* --- Status tape: one quiet line. The rail/backing fragments
   drop the mono-uppercase telemetry look; #exchange-status keeps
   its tone colors so errors and success still read. --- */
#exchange-rail-state,
#exchange-backing-state {
  font-family: inherit;
  font-size: 11px;
  letter-spacing: 0;
  text-transform: none;
  color: var(--foinse-text-disabled);
}

/* --- Search in its new home: the book head, next to Refresh.
   Recessed pill, single clean accent ring on focus. --- */
.xchange-book__head {
  gap: var(--foinse-space-3);
  flex-wrap: wrap;
}
body.app-shell--exchange .shell-search {
  --foinse-input-height: 40px;
  grid-template-columns: auto 1fr;
  flex: 0 1 400px;
  max-width: 400px;
  min-height: 40px;
  padding: 0 var(--foinse-space-4);
  border: 1px solid transparent;
  border-radius: 999px;
  background: var(--foinse-surface-recessed);
  color: var(--foinse-text-muted);
}
body.app-shell--exchange .shell-search:focus-within {
  background: var(--foinse-surface-card);
  border-color: var(--foinse-color-accent);
  outline: none;
}
body.app-shell--exchange .shell-search input {
  font-size: var(--foinse-font-size-body);
  font-weight: var(--foinse-font-weight-regular);
  color: var(--foinse-text-primary);
}

/* --- Row trade pills: quiet outline, accent on hover. --- */
.exchange-row-button.foinse-btn--tertiary {
  color: var(--foinse-text-secondary);
  border-color: var(--foinse-color-rule-200);
  background: transparent;
}
.exchange-row-button.foinse-btn--tertiary:hover {
  color: var(--foinse-color-accent);
  border-color: var(--foinse-color-accent);
  background: var(--foinse-color-accent-tint);
}

/* --- Mobile: the book table becomes a stack of cards. --- */
@media (max-width: 640px) {
  .xchange-book__head {
    flex-wrap: nowrap;
  }
  .xchange-book__head .shell-search {
    flex: 1 1 0;
    min-width: 0;
    max-width: none;
  }
  .xchange-book__head .shell-search input {
    min-width: 0;
  }

  #book-board .xchange-table,
  #book-board .xchange-table tbody {
    display: block;
  }
  #book-board .xchange-table thead { display: none; }
  #book-board .xchange-table tbody tr {
    display: block;
    margin: var(--foinse-space-3);
    padding: var(--foinse-space-2) var(--foinse-space-4) var(--foinse-space-3);
    border: var(--foinse-border);
    border-radius: var(--foinse-radius-card);
    background: var(--foinse-surface-card);
  }
  #book-board .xchange-table tbody tr:hover {
    background: var(--foinse-surface-card);
  }
  #book-board .xchange-table td {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--foinse-space-3);
    padding: var(--foinse-space-2) 0;
    border-bottom: 0;
    text-align: left;
  }
  /* Live rows label from data-label; placeholder rows map below. */
  #book-board .xchange-table td::before {
    content: attr(data-label);
    flex: none;
    font-size: 11px;
    font-weight: var(--foinse-font-weight-semibold);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--foinse-text-muted);
  }
  #book-board td[data-ph="units"]::before { content: "Available"; }
  #book-board td[data-ph="price"]::before { content: "Price / 1M"; }
  #book-board td[data-ph="vs"]::before,
  #book-board td[data-ph="list"]::before { content: "List"; }

  /* First cell is the card header: coin + name, no label. */
  #book-board .xchange-table td:first-child {
    justify-content: flex-start;
    padding: var(--foinse-space-2) 0 var(--foinse-space-3);
    margin-bottom: var(--foinse-space-1);
    border-bottom: var(--foinse-border);
  }
  #book-board .xchange-table td:first-child::before { content: none; }

  /* Rail column stays hidden in card mode too. */
  #book-board td[data-ph="rail"],
  #book-board .xchange-table td:nth-child(5) {
    display: none;
  }

  /* Trade pill spans the card, no label. */
  #book-board .xchange-table td:has(.exchange-row-button) {
    display: block;
    padding-top: var(--foinse-space-3);
  }
  #book-board .xchange-table td:has(.exchange-row-button)::before {
    content: none;
  }
  #book-board .exchange-row-button {
    width: 100%;
    justify-content: center;
  }
}

/* Signed out: the Buy button doubles as the sign-in door.
   The paragraph line is folded away and the engine-held disabled
   state keeps its click behavior but not its disabled look. */
body.app-shell--exchange #trade-sign-in { display: none; }

body.app-shell--exchange #trade:has(#trade-sign-in:not([hidden])) #trade-create:disabled,
body.app-shell--exchange #trade:has(#trade-sign-in:not([hidden])) #trade-create:disabled:hover {
  color: var(--foinse-color-paper);
  background: var(--foinse-color-accent);
  border-color: var(--foinse-color-accent);
  cursor: pointer;
}

/* The input lives inside the recessed pill: strip its own box. */
body.app-shell--exchange .shell-search input,
body.app-shell--exchange .shell-search input:focus {
  background: transparent;
  border: 0;
  box-shadow: none;
  outline: none;
}

/* The hint belongs whenever no row is picked, not only when the
   ticket is hidden — the book can be empty with the ticket open. */
body.app-shell--exchange .shell-actions:has(#trade-row-state:empty) .ticket-hint {
  display: block;
}

/* Empty-search note sits quiet under the table. */
#xchange-no-matches {
  margin: var(--foinse-space-4) 0 0;
  text-align: center;
}

/* The sheet is a fixed-height flex column; the tab bar must not shrink. */
.xchange-ticket .xchange-tabs { flex: 0 0 auto; }

/* The book breathes here too: the same slow wash as the front page. */
@keyframes xchange-row-breathe {
  0%, 100% { background-color: transparent; }
  50% { background-color: rgb(22 82 240 / 0.045); }
}
#book-board .xchange-table tbody tr { animation: xchange-row-breathe 9s ease-in-out infinite; }
#book-board .xchange-table tbody tr:nth-child(2) { animation-delay: 1.1s; }
#book-board .xchange-table tbody tr:nth-child(3) { animation-delay: 2.2s; }
#book-board .xchange-table tbody tr:nth-child(4) { animation-delay: 3.3s; }
#book-board .xchange-table tbody tr:nth-child(5) { animation-delay: 4.4s; }
#book-board .xchange-table tbody tr:nth-child(6) { animation-delay: 5.5s; }
#book-board .xchange-table tbody tr:nth-child(7) { animation-delay: 6.6s; }
#book-board .xchange-table tbody tr:nth-child(8) { animation-delay: 7.7s; }
@media (prefers-reduced-motion: reduce) {
  #book-board .xchange-table tbody tr { animation: none; }
}
