/* PONDELTA — application chrome and the /pools surfaces. */

/* ------------------------------------------------------------------ base */

*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  -webkit-font-smoothing: antialiased;
  background: var(--bg);
  color-scheme: dark;
}
:root[data-theme='light'] {
  color-scheme: light;
}

body {
  color: var(--text);
  font-family: var(--f-sans);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

a {
  color: var(--lime);
  text-decoration: none;
}
a:hover {
  text-decoration: underline;
}
::selection {
  background: var(--lime);
  color: var(--on-lime);
}
:focus-visible {
  outline: 2px solid var(--lime);
  outline-offset: 2px;
}
h1,
h2,
h3,
h4 {
  font-family: var(--f-sans);
  font-weight: 600;
}
h3 {
  font-size: var(--fs-h3);
  letter-spacing: -0.01em;
}
button {
  font-family: inherit;
}
img {
  max-width: 100%;
}

/* One weight for every icon, so a stroke-width typo in one SVG cannot make a
   single icon look bolder than its neighbours. */
svg[class*='lucide'] {
  stroke-width: 1.75;
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* ------------------------------------------------------------ background */

.bg-wash,
.bg-field {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
}
.bg-field {
  width: 100%;
  height: 100%;
}
.bg-wash {
  background:
    radial-gradient(120% 120% at 100% 0, rgba(212, 252, 80, 0.09) 0, transparent 46%),
    radial-gradient(120% 120% at 0 100%, rgba(242, 242, 242, 0.04) 0, transparent 50%);
}
.bg-wash::after {
  content: '';
  position: absolute;
  inset: -25%;
  background:
    radial-gradient(34% 40% at 72% 18%, rgba(212, 252, 80, 0.05), transparent 60%),
    radial-gradient(30% 38% at 22% 76%, rgba(159, 224, 122, 0.04), transparent 58%);
  filter: blur(40px);
}
:root[data-theme='light'] .bg-wash::after {
  background:
    radial-gradient(34% 40% at 72% 18%, rgba(125, 156, 20, 0.07), transparent 60%),
    radial-gradient(30% 38% at 22% 76%, rgba(125, 156, 20, 0.05), transparent 58%);
}

/* ----------------------------------------------------------------- shell */

.shell-main {
  width: min(1280px, 100% - 2rem);
  margin: 0 auto;
  padding: 1.1rem 0 4rem;
  flex: 1 1;
  position: relative;
}
.shell-main::before {
  content: '';
  position: absolute;
  top: -3rem;
  left: 0;
  right: 0;
  height: 460px;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(46% 62% at 24% 18%, rgba(212, 252, 80, 0.09), transparent 62%),
    radial-gradient(42% 58% at 78% 8%, rgba(159, 224, 122, 0.07), transparent 60%);
}
:root[data-theme='light'] .shell-main::before {
  background:
    radial-gradient(46% 62% at 24% 18%, rgba(125, 156, 20, 0.08), transparent 62%),
    radial-gradient(42% 58% at 78% 8%, rgba(125, 156, 20, 0.05), transparent 60%);
}

.app-rail-shift {
  padding-left: var(--rail-w);
}

/* ---------------------------------------------------------------- topbar */

.topbar {
  position: sticky;
  top: 0;
  z-index: 70;
  background: rgba(13, 13, 13, 0.92);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--line);
}
:root[data-theme='light'] .topbar {
  background: rgba(242, 243, 240, 0.92);
}
.topbar::after {
  content: '';
  position: absolute;
  bottom: -1px;
  left: 8%;
  right: 8%;
  height: 1px;
  pointer-events: none;
  background: linear-gradient(
    90deg,
    transparent 0,
    var(--edge-glow) 35%,
    var(--edge-glow) 65%,
    transparent 100%
  );
}

/*
  Grid, not absolute positioning.

  TRAP: the brand used to be `position: absolute` so the search could be centred
  over the content column independently of it. But an absolutely positioned
  element reserves no space, so the search's centring maths could put it
  underneath the brand - and it did, by 3px, across every width from 1024 to
  1280. Three separate media queries existed to paper over it.

  Three grid tracks make the overlap impossible to express: the brand owns its
  column, the search owns the middle, and the actions own the right.
*/
.topbar-inner {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  height: calc(var(--topbar-h) - 1px);
  width: 100%;
  margin: 0;
  padding: 0 1.25rem 0 16px;
  column-gap: 1.1rem;
}

.brand {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--text);
  font-weight: 700;
  font-size: 15px;
  letter-spacing: 0.34em;
  white-space: nowrap;
}
.brand,
.brand:hover {
  text-decoration: none;
}
.topbar .brand svg {
  width: 32px;
  height: auto;
  display: block;
  transition: filter var(--dur) var(--ease);
}
.topbar .brand:hover svg {
  filter: drop-shadow(0 0 6px rgba(212, 252, 80, 0.55));
}
.brand .net-tag {
  font-size: 9px;
  letter-spacing: var(--track);
  color: var(--ink-2);
  border: 1px solid var(--line-2);
  padding: 1px 5px;
  text-transform: uppercase;
}

.topbar-actions {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  justify-self: end;
}


.g-search {
  position: relative;
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  max-width: 560px;
  margin: 0;
  justify-self: center;
  background: var(--panel);
  border: 1px solid var(--line);
  padding: 8px 14px;
  color: var(--text-3);
  border-radius: var(--r-full);
  font-family: var(--f-mono);
  transition: border-color var(--dur) var(--ease);
}
.g-search:focus-within {
  border-color: var(--lime);
}
.g-search input {
  background: none;
  border: 0;
  outline: none;
  color: var(--text);
  font: inherit;
  font-size: 13px;
  width: 100%;
  font-family: var(--f-mono);
}
.g-search input::placeholder {
  color: var(--text-3);
}

/* search dropdown */
.tok-search-drop {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  right: 0;
  z-index: 80;
  background: var(--panel);
  border: 1px solid var(--line-2);
  border-radius: var(--r-md);
  box-shadow: var(--glass-shadow);
  overflow: hidden;
  max-height: 60vh;
  overflow-y: auto;
}
.g-group {
  font-family: var(--f-mono);
  font-size: 8.5px;
  letter-spacing: var(--track);
  text-transform: uppercase;
  color: var(--ink-3);
  padding: 8px 12px 4px;
}
.tok-search-hit {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 7px 12px;
  background: none;
  border: 0;
  cursor: pointer;
  text-align: left;
  color: var(--text);
}
.tok-search-hit:hover,
.tok-search-hit.sel {
  background: var(--raised);
}
.tok-search-hit .tok-sym {
  font-family: var(--f-mono);
  font-size: 12px;
  font-weight: 700;
}
.tok-search-hit .tok-name {
  font-size: 11.5px;
  color: var(--ink-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tok-search-hit .tok-addr {
  margin-left: auto;
  font-family: var(--f-mono);
  font-size: 10px;
  color: var(--ink-3);
}
.tok-search-note {
  padding: 12px;
  font-size: 12px;
  color: var(--ink-2);
}

/* header stats */
.header-stats {
  display: flex;
  align-items: stretch;
  gap: 0;
  margin-right: 0.6rem;
  background-color: var(--panel);
  background-image: var(--card-wash);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.035);
  overflow: hidden;
}
:root[data-theme='light'] .header-stats {
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.9);
}
.header-stats .hstat {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 13px;
  border-left: 1px solid var(--line);
}
.header-stats .hstat:first-child {
  border-left: 0;
}
.header-stats .hstat-ico {
  color: var(--lime);
  flex: 0 0 auto;
}
.header-stats .hstat-body {
  display: flex;
  flex-direction: column;
  gap: 1px;
  line-height: 1.1;
}
.header-stats .hstat-label {
  font-family: var(--f-mono);
  font-size: 8.5px;
  font-weight: 500;
  letter-spacing: var(--track);
  text-transform: uppercase;
  color: var(--ink-2);
  white-space: nowrap;
}
.header-stats .hstat-value {
  font-family: var(--f-mono);
  font-size: 12.5px;
  font-weight: 700;
  font-feature-settings: 'tnum';
  font-variant-numeric: tabular-nums;
  color: var(--ink-bright);
  white-space: nowrap;
}

.theme-toggle {
  width: 30px;
  height: 30px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: var(--r-full);
  background: transparent;
  color: var(--ink-2);
  cursor: pointer;
  flex: 0 0 auto;
  transition: color var(--dur) var(--ease);
}
.theme-toggle:hover {
  color: var(--ink-bright);
}

/* ---------------------------------------------------------------- buttons */

.btn {
  font-family: var(--f-mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding: 9px 16px;
  border-radius: var(--r-md);
  cursor: pointer;
  border: 1px solid color-mix(in srgb, var(--lime) 45%, var(--line));
  background: color-mix(in srgb, var(--lime) 12%, var(--panel));
  color: var(--lime);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);
  transition:
    background var(--dur) var(--ease),
    border-color var(--dur) var(--ease),
    color var(--dur) var(--ease);
}
.btn:hover:not(:disabled) {
  background: color-mix(in srgb, var(--lime) 22%, var(--panel));
  border-color: var(--lime);
  color: var(--ink-bright);
}
.btn:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}
.btn.btn-ghost {
  border-color: var(--line-2);
  background: var(--panel);
  color: var(--ink-bright);
}
.btn.btn-ghost:hover:not(:disabled) {
  border-color: var(--lime);
  color: var(--lime);
}
/* The primary action is the one place the lime is used as a fill, so it reads
   as the single strongest element on the page. */
.btn.btn-primary {
  background: var(--lime);
  border-color: var(--lime);
  color: var(--on-lime);
}
.btn.btn-primary:hover:not(:disabled) {
  background: var(--lime-bright);
  border-color: var(--lime-bright);
  color: var(--on-lime);
}

.net-warn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--f-mono);
  font-size: 11px;
  letter-spacing: var(--track);
  text-transform: uppercase;
  color: var(--neg);
  background: none;
  border: 1px solid var(--neg);
  padding: 6px 10px;
  cursor: pointer;
  border-radius: var(--r-full);
}
.net-warn:hover {
  background: rgba(255, 107, 94, 0.12);
}

/* -------------------------------------------------------------- siderail */

.siderail {
  position: fixed;
  top: var(--topbar-h);
  left: 0;
  bottom: 0;
  width: var(--rail-w);
  z-index: 60;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  padding: 10px 0;
  gap: 2px;
  overflow: hidden;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.025) 0, transparent 42%),
    var(--bg);
  border-right: 1px solid var(--line);
  transition: width var(--dur) var(--ease);
}
.siderail:hover,
.siderail:focus-within {
  width: var(--rail-w-open);
  box-shadow: var(--glass-shadow);
}
.rail-group {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.rail-group--end {
  margin-top: auto;
}
.rail-sep {
  height: 1px;
  margin: 8px 12px;
  background: var(--line);
}
.rail-item {
  display: flex;
  align-items: center;
  gap: 14px;
  height: 40px;
  padding: 0 0 0 19px;
  color: var(--ink-2);
  white-space: nowrap;
  position: relative;
  transition: color var(--dur) var(--ease);
}
.rail-item:hover {
  color: var(--ink-bright);
  text-decoration: none;
  background: var(--lime-tint);
}
.rail-item.active {
  color: var(--lime);
}
/* An active-state marker that does not rely on colour alone. */
.rail-item.active::before {
  content: '';
  position: absolute;
  left: 0;
  top: 8px;
  bottom: 8px;
  width: 2px;
  background: var(--lime);
}
.rail-ico {
  flex: 0 0 auto;
  display: inline-flex;
  width: 18px;
  justify-content: center;
}
.rail-label {
  font-family: var(--f-mono);
  font-size: 10.5px;
  letter-spacing: var(--track);
  text-transform: uppercase;
  opacity: 0;
  transition: opacity var(--dur) var(--ease);
}
.siderail:hover .rail-label,
.siderail:focus-within .rail-label {
  opacity: 1;
}
.rail-social {
  display: flex;
  align-items: center;
  gap: 14px;
  height: 34px;
  padding-left: 19px;
  color: var(--ink-3);
}
.rail-social:hover {
  color: var(--ink-bright);
}

/* --------------------------------------------------------------- panels */

.xpanel,
.panel {
  background-color: var(--panel);
  background-image: var(--card-wash);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
  position: relative;
}
.xpanel--lime {
  box-shadow: var(--glow-lime);
}
.panel-head,
.ap-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--line);
}
.panel-head h3,
.ap-head h3,
.ap-title {
  font-family: var(--f-mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: var(--track);
  text-transform: uppercase;
  color: var(--ink-2);
}
.panel-pad {
  padding: 14px 16px;
}

/* ---------------------------------------------------------- explore grid */

.explore-page {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.mband {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
}
.mband-side {
  display: grid;
  grid-template-rows: 1fr 1fr;
  gap: 14px;
}
.explore-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
}

/* market spot cards */
.mspot {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: 14px 16px;
  background-color: var(--panel);
  background-image: var(--card-wash);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
  color: inherit;
}
.mspot:hover {
  text-decoration: none;
  border-color: var(--line-2);
}
.mspot--hero {
  min-height: 232px;
}
.mspot--sm {
  min-height: 109px;
}
.mspot-art {
  position: absolute;
  inset: auto 0 0 0;
  height: 70%;
  pointer-events: none;
  opacity: 0.55;
}
.mspot--hero .mspot-art {
  height: 58%;
}
.mspot-k {
  font-family: var(--f-mono);
  font-size: 8.5px;
  font-weight: 500;
  letter-spacing: var(--track);
  text-transform: uppercase;
  color: var(--ink-3);
}
.mspot-id {
  display: flex;
  align-items: center;
  gap: 10px;
  position: relative;
  z-index: 1;
}
.mspot-sym {
  font-family: var(--f-display);
  font-size: 30px;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.1;
}
.mspot--hero .mspot-sym {
  font-size: 42px;
}
.mspot-v {
  font-family: var(--f-mono);
  font-size: 15px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.mspot-mc {
  font-family: var(--f-mono);
  font-size: 11px;
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}
.mspot-foot {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: baseline;
  gap: 10px;
}
.mspot-hero-stats {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px 18px;
  margin-top: auto;
}
.mspot-hero-stats .k {
  font-family: var(--f-mono);
  font-size: 8.5px;
  letter-spacing: var(--track);
  text-transform: uppercase;
  color: var(--ink-3);
  display: block;
}
.mspot-hero-stats .v {
  font-family: var(--f-mono);
  font-size: 15px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--ink-bright);
}
.mspot--lime .mspot-v,
.mspot--vol .mspot-v {
  color: var(--lime);
}

/* sparklines */
.spark {
  display: block;
  overflow: visible;
}
.spark-fill {
  opacity: 0.9;
}
.spark-dot {
  fill: currentColor;
}
.spark-wide {
  width: 68px;
  height: 22px;
}

/* ---------------------------------------------------------------- tables */

.ftable {
  width: 100%;
  border-collapse: collapse;
  table-layout: fixed;
}
.ftable thead th {
  font-family: var(--f-mono);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-2);
  text-align: right;
  padding: 8px 10px;
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
  background: var(--panel);
}
.ftable thead th:first-child {
  text-align: left;
  padding-left: 16px;
}
.ftable thead th.sortable {
  cursor: pointer;
  user-select: none;
}
.ftable thead th.sortable:hover {
  color: var(--ink-bright);
}
.ftable thead th[aria-sort='ascending']::after {
  content: ' ▲';
  font-size: 7px;
}
.ftable thead th[aria-sort='descending']::after {
  content: ' ▼';
  font-size: 7px;
}
.ftable tbody td {
  padding: 9px 10px;
  text-align: right;
  border-bottom: 1px solid var(--line);
  font-family: var(--f-mono);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  overflow: hidden;
}
.ftable tbody td:first-child {
  text-align: left;
  padding-left: 16px;
}
.ftable tbody tr:last-child td {
  border-bottom: 0;
}
.ftable tbody tr:hover td {
  background: var(--lime-tint);
}

.tok-link {
  display: flex;
  align-items: center;
  gap: 9px;
  color: inherit;
  min-width: 0;
  overflow: hidden;
}
.tok-link:hover {
  text-decoration: none;
}
.tok-ico {
  width: 22px;
  height: 22px;
  border-radius: var(--r-full);
  flex: 0 0 auto;
  background: var(--raised-2);
  object-fit: cover;
  display: block;
}
.tok-ico-fallback {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--f-mono);
  font-size: 9px;
  font-weight: 700;
  color: var(--ink-2);
  letter-spacing: 0;
}
.tok-text {
  display: flex;
  align-items: baseline;
  gap: 7px;
  min-width: 0;
  overflow: hidden;
}
/*
  The symbol truncates too, not just the name.

  TRAP: `.ftable` is `table-layout: fixed` with `white-space: nowrap`, so a cell
  that runs out of room does not wrap or scroll - it silently overprints its
  neighbour. A long symbol like STONKBROKER rendered straight through the market
  cap column. Only the name had an ellipsis, which is no help when it is the
  symbol that is long.
*/
.tok-sym {
  font-family: var(--f-mono);
  font-size: 12.5px;
  font-weight: 700;
  color: var(--ink-bright);
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tok-name {
  font-size: 11.5px;
  color: var(--ink-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-family: var(--f-sans);
}

.chg.up {
  color: var(--pos);
}
.chg.down {
  color: var(--neg);
}
.chg.up::before {
  content: '▲ ';
  font-size: 7px;
}
.chg.down::before {
  content: '▼ ';
  font-size: 7px;
}
.cell-age.fresh {
  color: var(--lime);
}

/* filters */
.quote-switch,
.win-filter {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  background: var(--raised);
  border: 1px solid var(--line);
  border-radius: var(--r-full);
  padding: 2px;
}
.qs-btn,
.win-btn {
  font-family: var(--f-mono);
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-2);
  background: none;
  border: 0;
  border-radius: var(--r-full);
  padding: 4px 10px;
  cursor: pointer;
  transition:
    background var(--dur) var(--ease),
    color var(--dur) var(--ease);
}
.qs-btn:hover,
.win-btn:hover {
  color: var(--ink-bright);
}
.qs-btn.on,
.win-btn.on {
  background: var(--lime);
  color: var(--on-lime);
}
.table-toolbar {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-left: auto;
}

/* A timeframe change dims the body rather than blanking it, so the table does
   not jump while the new window loads. */
.tbl-swap tbody {
  opacity: 0.45;
  transition: opacity 0.18s ease;
}

/*
  Entrance animation on the PANEL, never on the rows.

  TRAP: `animation: row-in .42s both` on tbody tr looks fine until the table is
  driven by a live feed. Every repaint replaces the rows, which restarts the
  animation from opacity 0 - and when ticks arrive faster than 0.42s the rows
  never finish fading in and the table renders permanently blank. The panel is
  not re-created per tick, so animating it is safe.
*/
@media (prefers-reduced-motion: no-preference) {
  .explore-grid .panel,
  .app-page .panel,
  .mband .mspot {
    animation: panel-in 0.36s var(--ease) both;
  }
}
@keyframes panel-in {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* ------------------------------------------------------------- empty/misc */

.empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 6px;
  padding: 3rem 1.5rem;
  color: var(--text-2);
}
.empty .e-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--ink-3);
}
.subnote {
  font-size: 12px;
  line-height: 1.45;
  color: var(--ink-2);
}
.subnote strong {
  color: var(--ink);
  font-weight: 700;
}
.mlabel {
  font-family: var(--f-mono);
  font-size: 8.5px;
  letter-spacing: var(--track);
  text-transform: uppercase;
  color: var(--ink-3);
}
.stat .k {
  font-family: var(--f-mono);
  font-size: 8.5px;
  letter-spacing: var(--track);
  text-transform: uppercase;
  color: var(--ink-3);
  display: block;
}
.stat .v {
  font-family: var(--f-mono);
  font-size: 15px;
  font-weight: 700;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.stat .v .unit {
  font-size: 10px;
  font-weight: 400;
  color: var(--text-3);
}

/* ---------------------------------------------------------------- toasts */

.toasts {
  position: fixed;
  right: 16px;
  bottom: 16px;
  z-index: 90;
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-width: min(420px, calc(100vw - 32px));
}
.toast {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 11px 13px;
  background: var(--panel);
  border: 1px solid var(--line-2);
  border-left-width: 3px;
  border-radius: var(--r-md);
  box-shadow: var(--glass-shadow);
  font-size: 12.5px;
  line-height: 1.45;
  animation: toast-in 0.22s var(--ease) both;
}
.toast.ok {
  border-left-color: var(--pos);
}
.toast.err {
  border-left-color: var(--neg);
}
.toast.info {
  border-left-color: var(--lime);
}
.toast-body {
  min-width: 0;
  overflow-wrap: anywhere;
}
.toast-title {
  font-family: var(--f-mono);
  font-size: 10px;
  letter-spacing: var(--track);
  text-transform: uppercase;
  color: var(--ink-3);
  display: block;
  margin-bottom: 2px;
}
.toast a {
  color: var(--lime);
}
.toast-close {
  margin-left: auto;
  background: none;
  border: 0;
  color: var(--ink-3);
  cursor: pointer;
  font-size: 14px;
  line-height: 1;
}
@keyframes toast-in {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* --------------------------------------------------------------- notices */

.notice {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 9px 13px;
  border: 1px solid var(--line-2);
  border-radius: var(--r-md);
  background: var(--raised);
  font-size: 12.5px;
  color: var(--text-2);
}
.notice.warn {
  border-color: color-mix(in srgb, var(--warn) 50%, var(--line));
  color: var(--warn);
}
.notice.err {
  border-color: color-mix(in srgb, var(--neg) 50%, var(--line));
  color: var(--neg);
}

.skel {
  background: linear-gradient(90deg, var(--raised) 25%, var(--raised-2) 37%, var(--raised) 63%);
  background-size: 400% 100%;
  animation: skel 1.4s ease infinite;
  border-radius: var(--r-sm);
  color: transparent;
}
@keyframes skel {
  from {
    background-position: 100% 50%;
  }
  to {
    background-position: 0 50%;
  }
}

/* ----------------------------------------------------------- responsive */

@media (max-width: 1100px) {
  .explore-grid,
  .mband {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 1000px) {
  .header-stats .hstat.hstat-wide {
    display: none;
  }
}

@media (max-width: 720px) {
  /* Brand and actions share the top row, search takes the one below. Named
     areas rather than wrapping, so the order cannot depend on source order. */
  .topbar-inner {
    grid-template-columns: auto minmax(0, 1fr);
    grid-template-areas:
      'brand actions'
      'search search';
    height: auto;
    row-gap: 8px;
    padding: 10px 16px 12px;
  }
  .topbar-inner .brand {
    grid-area: brand;
  }
  .topbar-inner .topbar-actions {
    grid-area: actions;
  }
  .topbar-inner .g-search {
    grid-area: search;
    max-width: none;
  }
  .header-stats {
    display: none;
  }

  /* The rail becomes a bottom tab bar; the labels come out of hiding because
     there is no hover on touch. */
  .siderail {
    top: auto;
    left: 0;
    right: 0;
    bottom: 0;
    width: 100%;
    height: calc(58px + env(safe-area-inset-bottom, 0px));
    flex-direction: row;
    align-items: stretch;
    padding: 0 0 env(safe-area-inset-bottom, 0px);
    border-right: 0;
    border-top: 1px solid var(--line);
    transition: none;
  }
  .siderail:hover,
  .siderail:focus-within {
    width: 100%;
    box-shadow: none;
  }
  .rail-group {
    flex-direction: row;
    flex: 1;
  }
  .rail-group--end,
  .rail-sep {
    display: none;
  }
  .rail-item {
    flex: 1;
    flex-direction: column;
    gap: 3px;
    height: 100%;
    justify-content: center;
    padding: 0;
  }
  .rail-item.active::before {
    top: 0;
    bottom: auto;
    left: 20%;
    right: 20%;
    width: auto;
    height: 2px;
  }
  .rail-label {
    opacity: 1;
    font-size: 8.5px;
    letter-spacing: 0.08em;
  }
  /*
    Clearance for the bottom tab bar, plus a real gap.

    TRAP: padding-bottom exactly equal to the bar height leaves zero room, so at
    full scroll the last panel's border sits under the bar. It also replaces
    .shell-main's own 4rem bottom padding, which made the page end TIGHTER than
    it did on desktop. The bar is 58px; this reserves that plus a gap.
  */
  .app-rail-shift {
    padding-left: 0;
    padding-bottom: calc(58px + env(safe-area-inset-bottom, 0px) + 2rem);
  }
  .shell-main {
    width: min(1280px, 100% - 1.5rem);
  }
  .mspot--hero .mspot-sym {
    font-size: 32px;
  }
  .mspot-hero-stats {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  /* Drop the two least load-bearing columns rather than letting the table
     scroll sideways off the page. */
  .ftable :is(th, td):nth-child(4),
  .ftable :is(th, td):nth-child(5) {
    display: none;
  }
}

/* ================================================================ /stakes */
/* Appended for the Stakes surface. Everything above is untouched.          */

.stakes-page {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
/* The APR caveat is prose, not a table cell, so it gets a measure. */
.stakes-lede {
  max-width: 86ch;
}

/* The four totals above the table. One bordered block with hairlines between
   the cells rather than four floating cards, so it reads as a single strip and
   does not compete with the panel below it. auto-fit lets it fold to two rows
   on a narrow screen without a second breakpoint. */
.stats-strip {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  background-color: var(--panel);
  background-image: var(--card-wash);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
}
.stats-strip .cell {
  display: flex;
  flex-direction: column;
  gap: 5px;
  padding: 12px 16px;
  border-right: 1px solid var(--line);
}
.stats-strip .cell:last-child {
  border-right: 0;
}
/* How much of the index a total actually covers, when it is not all of it. */
.stats-strip .cell .tnote {
  font-family: var(--f-mono);
  font-size: 10px;
  letter-spacing: 0.03em;
  color: var(--ink-3);
}

/* .ftable is table-layout:fixed, so eight equal columns would truncate the
   pair symbols. The two ends are pinned and the numeric middle divides up
   whatever is left. */
.stakes-table th:first-child,
.stakes-table td:first-child {
  width: 26%;
}
.stakes-table th:last-child,
.stakes-table td:last-child {
  width: 104px;
}
.cell-tier {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 7px;
}

/* The pair's two discs overlap by a third, ringed in the panel colour so the
   back one reads as behind rather than merged. */
.pair-art {
  display: inline-flex;
  align-items: center;
  flex: 0 0 auto;
}
.pair-art .tok-ico + .tok-ico {
  margin-left: -8px;
  box-shadow: 0 0 0 2px var(--panel);
}

.cell-apr {
  color: var(--lime);
  font-weight: 700;
}
/* An APR we cannot measure is an em dash, and an em dash should not be lime. */
.cell-apr.unknown {
  color: var(--ink-3);
  font-weight: 400;
}

.provide-link {
  display: inline-block;
  font-family: var(--f-mono);
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-2);
  border: 1px solid var(--line-2);
  border-radius: var(--r-full);
  padding: 4px 11px;
  transition:
    background var(--dur) var(--ease),
    border-color var(--dur) var(--ease),
    color var(--dur) var(--ease);
}
.provide-link:hover {
  text-decoration: none;
  background: var(--lime);
  border-color: var(--lime);
  color: var(--on-lime);
}

@media (max-width: 720px) {
  /* The title and the two filter groups cannot share a line at this width. */
  .stakes-page .panel-head {
    flex-wrap: wrap;
  }
  .stakes-page .table-toolbar {
    margin-left: 0;
    width: 100%;
  }

  /* TRAP: .ftable is table-layout:fixed with white-space:nowrap, so a column
     that runs out of room does not wrap or scroll - it silently overprints its
     neighbour. Eight columns will never fit 350px, so four of them go: tier and
     the two raw fee figures are the detail behind Fee APR, and Provide is
     redundant because the pair cell already links to the same pool page. The
     four that remain get explicit widths wide enough for their longest real
     value ("$149.46K", "181.18K%"). */
  .stakes-table :is(th, td):nth-child(2),
  .stakes-table :is(th, td):nth-child(4),
  .stakes-table :is(th, td):nth-child(5),
  .stakes-table :is(th, td):nth-child(8) {
    display: none;
  }
  .stakes-table th:first-child,
  .stakes-table td:first-child {
    width: 42%;
    padding-left: 12px;
  }
  .stakes-table :is(th, td):nth-child(3) {
    width: 24%;
  }
  .stakes-table :is(th, td):nth-child(6) {
    width: 22%;
  }
  .stakes-table :is(th, td):nth-child(7) {
    width: 12%;
  }
  .stakes-table :is(thead th, tbody td) {
    padding-left: 8px;
    padding-right: 8px;
    font-size: 11px;
  }
  /* The pair needs every pixel for the symbols; the long token name is the
     first thing an LP can do without. */
  .stakes-table .tok-name {
    display: none;
  }
}

/* A trailing APR from a near-empty pool is noise wearing a yield's clothes.
   It still renders - hiding real data is worse - but in the muted tier with a
   marker, so it cannot be mistaken for the headline rates above it. */
.cell-apr.thin {
  color: var(--ink-2);
}
/* Scoped to nothing in particular on purpose: the same marker appears in the
   lede, where it is the legend for this column. Both have to look alike or the
   sentence explaining the asterisk does not visibly refer to the asterisk. */
.thin-flag {
  color: var(--warn);
  margin-left: 2px;
  font-weight: 700;
}
