/* ═══════════════════════════════════════════════════════════════════════════
   /crypto/ and /crypto/{coin}/ — page-scoped layer on top of the landing theme.

   WHY THIS IS A SEPARATE FILE AND NOT PART OF index.css
   -----------------------------------------------------
   `css/style.min.css` is a GENERATED bundle (grid + index + hero-anim + btn-fx)
   and the build script that produces it does not live in this repo yet. Adding
   these rules to index.css would change a source the served bundle is NOT
   rebuilt from — the pages would render unstyled with nothing failing anywhere.
   So these routes ship their own stylesheet, linked only on them by the
   `[@page->pagecss]` branch in biiq.views.main.v2head.html. Same reasoning, and
   the same shape, as about.css.

   Everything below is ADDITIVE. The tokens (--blue2, --surface, --border, …),
   .glass, .container, .section/.section-label/.section-title, .pc-change and
   the whole nav/footer chrome come from the bundle and are reused as-is;
   nothing here overrides them. Classes are `.cx-`-prefixed so a future merge
   into index.css cannot collide.

   RTL: the document is dir="rtl". Every directional value here is a LOGICAL
   property (inset-inline-*, padding-inline-*, margin-inline-*, text-align:start)
   so the pages do not have to be re-mirrored if they are ever served LTR. The
   exceptions are deliberate and marked: a price, a ticker and a percentage are
   LTR runs inside RTL text and carry `direction: ltr` on purpose — the same
   thing .pc-price and .pc-ticker already do in the theme.

   NO INLINE STYLES ANYWHERE. Per-coin accent colours arrive as a
   `data-cx-accent` attribute and are applied by crypto.js via
   style.setProperty(), which keeps the markup free of `style=""`. The default
   below is a real design decision, not a placeholder: every surface must look
   finished with JavaScript disabled.
   ═══════════════════════════════════════════════════════════════════════════ */

.cx-hero,
.cx-top,
.cx-coin {
  --cx-accent: var(--blue2);
}

/* Screen-reader-only text. The bundle has no .sr-only, and the chart's
   <figcaption> is the one thing on these pages that must be announced without
   being drawn. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ─── BREADCRUMB ─── */
.cx-crumb {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  font-size: 13px;
  color: var(--text-muted);
  margin-bottom: 28px;
}
.cx-crumb a {
  color: var(--text-sub);
  text-decoration: none;
  transition: color 0.2s ease;
}
.cx-crumb a:hover { color: var(--blue2); }
.cx-crumb-sep { opacity: 0.4; }

/* ═══════════════════ LIST PAGE ═══════════════════ */

/* Deliberately NOT the landing hero: that one is a full-viewport pitch with a
   WebGL orb, and an interior page opening the same way reads as a second home
   page. This is a short banner. */
.cx-hero {
  padding: 64px 0 24px;
  position: relative;
}
.cx-hero::before {
  content: '';
  position: absolute;
  inset-block-start: -140px;
  inset-inline-start: -100px;
  width: 480px;
  height: 480px;
  background: radial-gradient(circle, rgba(61,123,255,0.12), transparent 70%);
  filter: blur(40px);
  pointer-events: none;
  z-index: -1;
}
.cx-hero-copy { max-width: 720px; }
.cx-h1 {
  font-size: clamp(30px, 4.2vw, 52px);
  font-weight: 900;
  letter-spacing: -0.5px;
  line-height: 1.2;
  margin: 18px 0 14px;
  color: var(--text);
}
.cx-lead {
  font-size: 16px;
  line-height: 1.9;
  color: var(--text-sub);
  margin-bottom: 20px;
}
.cx-hero-meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px 18px;
  font-size: 13px;
  color: var(--text-muted);
}
.cx-live {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  color: var(--text-sub);
}
.cx-live-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--green);
  box-shadow: 0 0 0 0 rgba(34,197,94,0.6);
  animation: cx-pulse 2.4s ease-out infinite;
}
@keyframes cx-pulse {
  0%   { box-shadow: 0 0 0 0 rgba(34,197,94,0.5); }
  70%  { box-shadow: 0 0 0 7px rgba(34,197,94,0); }
  100% { box-shadow: 0 0 0 0 rgba(34,197,94,0); }
}

/* ─── TOOLBAR ─── */
.cx-market { padding-block-start: 24px; }
.cx-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  padding: 12px 16px;
  border-radius: var(--radius);
  margin-bottom: 18px;
}
.cx-search {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 1 1 260px;
  min-width: 0;
}
.cx-search-icon {
  width: 18px;
  height: 18px;
  color: var(--text-muted);
  flex-shrink: 0;
}
.cx-search-input {
  flex: 1 1 auto;
  min-width: 0;
  background: transparent;
  border: 0;
  outline: 0;
  color: var(--text);
  font-family: inherit;
  font-size: 14px;
  padding: 6px 0;
}
.cx-search-input::placeholder { color: var(--text-muted); }
/* The UA's own clear button is a light-mode glyph that disappears on this
   background; the Escape key and clearing the field both still work. */
.cx-search-input::-webkit-search-cancel-button { display: none; }
.cx-count {
  font-size: 12px;
  color: var(--text-muted);
  white-space: nowrap;
}

/* ─── MARKET ROWS ───
   One grid template shared by the header strip and every row. Below 860px the
   row becomes a card and the header strip is removed entirely — a header for
   columns that no longer exist is worse than none.

   ⚠️ SHARING THE TEMPLATE IS NOT ENOUGH TO SHARE THE COLUMNS, and this comment
   used to claim it was. Two things made every heading sit somewhere its numbers
   did not, by 18px to 50px across the six columns:

     · The last track was `auto`. In a row it holds «مشاهده» and measures 60px;
       in the header that cell is EMPTY, so the track collapsed to 0 and the six
       fr tracks above it shared out 60px more width than the rows had. The
       header's columns were genuinely wider than the rows' — identical
       declaration, different result, because `auto` measures content and the
       two grids do not hold the same content. It is a FIXED width now, so the
       header reserves the space its rows spend.
     · `.cx-row` carries a 1px border and `.cx-head` did not, which insets the
       row's content box by one more pixel all the way round. The transparent
       border below costs nothing and makes the two content boxes identical.

   Neither is visible in a stylesheet read — both were found by measuring the
   rendered cell rectangles against each other. */
.cx-head,
.cx-row {
  display: grid;
  /* rank · coin · usd · toman · 24h · market cap · go */
  grid-template-columns:
    2.4rem minmax(0, 2fr) minmax(0, 1.1fr) minmax(0, 1.5fr) minmax(0, 0.9fr) minmax(0, 1.2fr) 64px;
  align-items: center;
  gap: 14px;
}
.cx-h-rank,
.cx-c-rank {
  font-size: 12px;
  font-weight: 700;
  color: var(--text-muted);
  text-align: center;
}
.cx-mcap {
  font-size: 12.5px;
  font-weight: 700;
  color: var(--text-sub);
}
/* A coin we do not sell still gets a row and a page — it just does not get the
   accent bar that marks the ones a visitor can act on. */
.cx-row.is-listed-only::before { background: var(--text-muted); }
.cx-head {
  padding: 0 18px 10px;
  /* Matches the 1px border on .cx-row — see the note on the shared grid above.
     Without it every heading sits one pixel off its column. */
  border: 1px solid transparent;
  border-block: 0;
  font-size: 12px;
  font-weight: 700;
  color: var(--text-muted);
  letter-spacing: 0.4px;
}
.cx-rows {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.cx-row {
  padding: 14px 18px;
  border-radius: var(--radius);
  text-decoration: none;
  color: inherit;
  position: relative;
  overflow: hidden;
  transition: transform 0.2s ease, border-color 0.2s ease, background 0.2s ease;
}
.cx-row::before {
  /* The coin's accent, as a hairline on the inline-start edge. Uses the
     --cx-accent JS sets from data-cx-accent; falls back to the brand blue. */
  content: '';
  position: absolute;
  inset-block: 0;
  inset-inline-start: 0;
  width: 3px;
  background: var(--cx-accent, var(--blue2));
  opacity: 0;
  transition: opacity 0.2s ease;
}
.cx-row:hover {
  transform: translateY(-1px);
  border-color: var(--border-h);
  background: var(--surface-h);
}
.cx-row:hover::before { opacity: 1; }
.cx-row:focus-visible {
  outline: 2px solid var(--blue2);
  outline-offset: 2px;
}
/* ⚠️ REQUIRED, NOT DEFENSIVE — WITHOUT IT THE SEARCH DOES NOTHING.
   The browser's own `[hidden] { display: none }` is a bare attribute rule, so
   the `display: grid` on `.cx-row` above outranks it on specificity. Setting
   row.hidden = true from JS then changes the attribute and NOTHING on screen:
   the filter runs correctly, the count updates, and every row stays visible.
   Measured in a browser before this was added — computed display on a row
   carrying [hidden] was still `grid`.
   Any element that both sets a display and gets toggled with .hidden needs its
   own rule like this one. */
.cx-row[hidden],
.cx-chip[hidden],
.cx-group-sep[hidden] { display: none; }

/* The labelled boundary between the coins with a written page and the rest of
   the market-cap ranking. Inserted by crypto.js — see the GROUP DIVIDER note
   there for why it cannot live in the view. */
.cx-group-sep {
  display: flex;
  align-items: center;
  gap: 14px;
  margin: 22px 2px 6px;
  color: rgba(233, 240, 255, .42);
  font-size: .82rem;
  letter-spacing: .01em;
}
.cx-group-sep::before,
.cx-group-sep::after {
  content: '';
  flex: 1;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(233, 240, 255, .14), transparent);
}
.cx-group-sep span { white-space: nowrap; }

.cx-c-coin {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
}
.cx-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 12px;
  background: var(--surface);
  border: 1px solid var(--border);
  flex-shrink: 0;
}
.cx-mark img { width: 26px; height: 26px; object-fit: contain; }
.cx-mark-sm { width: 34px; height: 34px; border-radius: 10px; }
.cx-mark-sm img { width: 20px; height: 20px; }
.cx-mark-xl { width: 68px; height: 68px; border-radius: 20px; }
.cx-mark-xl img { width: 42px; height: 42px; }

.cx-names {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.cx-name-fa {
  font-size: 15px;
  font-weight: 700;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* ⚠️ `direction: ltr` + `text-align: start` USED TO BE HERE, and the pair is a
   trap: `start` is resolved against the element's OWN direction, so declaring
   ltr flips start from right to left and the ticker slid out from under the
   Persian name it belongs to. The symbol needs an isolated LTR run so mixed
   tickers («1INCH», «FIGR_HELOC») keep their character order — that is what the
   <bdi> in the view does — but it must NOT change the alignment, so no
   direction is declared here and `start` stays the RTL start, i.e. the right
   edge the name above it sits on. Third time this pair has bitten this page. */
.cx-ticker {
  font-size: 11px;
  font-weight: 600;
  color: var(--text-muted);
  text-align: start;
}

/* The per-cell label is the mobile card's row heading. Hidden on desktop,
   where the column header carries it instead. */
.cx-lbl { display: none; }

.cx-c-usd,
.cx-c-toman,
.cx-c-change,
.cx-c-go { min-width: 0; }

/* THE TWO PRICE COLUMNS ALIGN ON THEIR LEFT EDGE, EVERY OTHER COLUMN ON ITS
   RIGHT. That is deliberate and it is not an RTL slip.
   The page is RTL, so `start` is the right edge and the coin name, the market
   cap («۲۲۴٫۱ میلیارد دلار») and the headings all belong there — they are
   Persian, read right to left, and their first character is on the right.
   A price is not: «$۶۲,۹۴۰» and «$۰/۳۲۴۷» are left-to-right runs whose first
   character is the «$». Aligned on the right, the figures ended flush but every
   «$» started somewhere different and the eye had no column to follow down.
   `end` resolves to the left edge here, so the dollar signs and the leading
   digits line up instead.
   The headings move with them — the two must share an edge, whichever edge that
   is, or the fix for the misaligned headers is undone one column at a time. */
.cx-h-usd,
.cx-c-usd,
.cx-h-toman,
.cx-c-toman { text-align: end; }

/* ⚠️ DO NOT ZERO .pc-change's INLINE PADDING HERE. It looks like dead space —
   the 24h figure sits 9px inside the edge every other column aligns on — but
   the 9px is the badge's pill and the pill's own box IS flush with that edge,
   so the column is already right and only the glyphs are inset, which is what a
   pill is for.
   Recorded because a check said otherwise and was wrong: it toggled `is-up` on
   the badge, but the class this page's JS actually sets is `up`/`down`, so no
   colour rule matched, the background computed to rgba(0,0,0,0), and the
   padding looked like it was wrapping nothing. Removing it squashed the text
   against the pill edge on every live row. Verify a badge with REAL data
   before deciding its padding is decorative. */

.cx-usd {
  font-size: 14px;
  font-weight: 700;
  color: var(--text-sub);
  direction: ltr;
  display: inline-block;
}
.cx-toman {
  font-size: 16px;
  font-weight: 800;
  color: var(--text);
  letter-spacing: -0.3px;
}
/* «تومان» beside every price — hidden at EVERY width, and the markup no longer
   emits one in a market row at all.
   Desktop: the column header already reads «قیمت خرید (تومان)». It also
   wandered — the word sits right beside the number, and these numbers run from
   5 digits to 14, so its x position moved by 64px down the column and gave the
   table a ragged edge that nothing in the alignment explained.
   Mobile: same call, made second. The card's own label now carries the unit
   («قیمت خرید (تومان)»), which is the same job the column header does on
   desktop — stated once per column, not once per row.
   The rule stays because .cx-unit is used elsewhere on these pages; only the
   list row dropped its instance. */
.cx-unit {
  display: none;
  font-size: 11px;
  color: var(--text-muted);
  margin-inline-start: 4px;
}
.cx-go {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 12px;
  font-weight: 700;
  color: var(--text-muted);
  white-space: nowrap;
  transition: color 0.2s ease;
}
.cx-go svg { width: 15px; height: 15px; }
.cx-row:hover .cx-go { color: var(--blue2); }

.cx-empty {
  text-align: center;
  color: var(--text-muted);
  font-size: 14px;
  padding: 40px 0;
}
.cx-note {
  font-size: 12.5px;
  line-height: 1.9;
  color: var(--text-muted);
  margin-top: 22px;
  max-width: 760px;
}

/* ═══════════════════ SINGLE COIN PAGE ═══════════════════ */

.cx-top { padding: 56px 0 8px; position: relative; }
.cx-top::before {
  content: '';
  position: absolute;
  inset-block-start: -160px;
  inset-inline-end: -120px;
  width: 520px;
  height: 520px;
  /* color-mix keeps this one bloom tied to the coin's own accent instead of
     shipping a second hardcoded blue. Browsers without it fall back to the
     declaration being dropped, which leaves the aurora behind — acceptable. */
  background: radial-gradient(circle, color-mix(in srgb, var(--cx-accent, var(--blue2)) 14%, transparent), transparent 70%);
  filter: blur(50px);
  pointer-events: none;
  z-index: -1;
}
.cx-top-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 420px);
  gap: 32px;
  align-items: center;
}
.cx-identity {
  display: flex;
  align-items: center;
  gap: 18px;
  min-width: 0;
}
/* Not a flex row any more: the symbol chip used to live in here and a long
   Persian title pushed it to the far end of the line. Plain block, plain text. */
.cx-coin-title {
  font-size: clamp(26px, 3.4vw, 42px);
  font-weight: 900;
  letter-spacing: -0.5px;
  line-height: 1.25;
  color: var(--text);
  margin: 0 0 10px;
}
/* Symbol + English name, one line, starting at the same edge as the title. */
.cx-coin-meta {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin: 0;
}
.cx-symbol-chip {
  font-size: 12px;
  font-weight: 700;
  color: var(--cx-accent, var(--blue2));
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 4px 11px;
  /* A ticker is a Latin token; isolate it so a symbol with a digit in it
     ("1INCH") cannot be reordered by the surrounding RTL text. Isolation only —
     NOT `direction: ltr`, which on a block would drag its alignment with it. */
  unicode-bidi: isolate;
}
/* The element is a <bdi>, which already isolates its own text direction. No
   `direction` property here on purpose — see the note in the view. */
.cx-coin-en {
  font-size: 13.5px;
  font-weight: 600;
  color: var(--text-muted);
}

/* ─── QUOTE CARD ─── */
.cx-quote {
  border-radius: var(--radius-lg);
  padding: 22px;
}
.cx-quote-label {
  font-size: 11px;
  font-weight: 700;
  color: var(--text-muted);
  letter-spacing: 0.4px;
  display: block;
  margin-bottom: 4px;
}
.cx-quote-toman {
  font-size: clamp(26px, 3vw, 34px);
  font-weight: 900;
  color: var(--text);
  letter-spacing: -1px;
  line-height: 1.2;
}
.cx-quote-toman em {
  font-size: 13px;
  font-weight: 600;
  font-style: normal;
  color: var(--text-muted);
  letter-spacing: 0;
}
/* Three stats now (global price, 24h change, 24h volume), so they space out
   rather than clustering at one end, and wrap instead of overflowing on a
   narrow card. */
.cx-quote-side {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 14px 20px;
  flex-wrap: wrap;
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
}
.cx-quote-usd span:last-child,
.cx-quote-vol span:last-child {
  font-size: 15px;
  font-weight: 700;
  color: var(--text-sub);
  display: inline-block;
}
/* The dollar figure is a Latin run; isolate it so the $ cannot be reordered by
   the RTL text around it. The volume may end in a Persian word («میلیارد») and
   is left in the page's own direction. */
.cx-quote-usd span:last-child { unicode-bidi: isolate; }
/* Keeps «۳۰۵ میلیارد دلار» on one line — the magnitude word and its number are
   one reading and splitting them across lines looks like two figures. */
.cx-quote-vol span:last-child { white-space: nowrap; }
.cx-quote-change .pc-change { margin-top: 0; }
.cx-quote-actions {
  display: flex;
  gap: 10px;
  margin-top: 18px;
}
.cx-quote-actions .btn { flex: 1 1 auto; justify-content: center; }
.cx-sell { flex: 0 0 auto; }
.cx-quote-note {
  font-size: 11.5px;
  color: var(--text-muted);
  margin: 12px 0 0;
}

/* ─── CARD (chart / tools / specs) ─── */
.cx-card {
  border-radius: var(--radius-lg);
  padding: 26px;
}
.cx-card-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 18px;
  flex-wrap: wrap;
  margin-bottom: 20px;
}
.cx-card-title {
  font-size: clamp(20px, 2.2vw, 26px);
  font-weight: 800;
  color: var(--text);
  margin: 0;
  letter-spacing: -0.3px;
}
.cx-chart-section { padding: 40px 0 0; }

/* ─── RANGE SWITCH ─── */
.cx-ranges,
.cx-seg {
  display: inline-flex;
  gap: 4px;
  padding: 4px;
  background: rgba(255,255,255,0.03);
  border: 1px solid var(--border);
  border-radius: 12px;
  flex-wrap: wrap;
}
.cx-range,
.cx-seg-btn {
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--text-muted);
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 700;
  padding: 7px 13px;
  border-radius: 9px;
  cursor: pointer;
  transition: background 0.2s ease, color 0.2s ease;
  white-space: nowrap;
}
.cx-range:hover,
.cx-seg-btn:hover { color: var(--text-sub); }
.cx-range.is-active,
.cx-seg-btn.is-active {
  background: var(--surface-h);
  color: var(--text);
}
.cx-range:focus-visible,
.cx-seg-btn:focus-visible {
  outline: 2px solid var(--blue2);
  outline-offset: 1px;
}

/* ─── CHART HEAD ─── */
.cx-chart-heading { min-width: 0; }
.cx-range-change {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 10px 0 0;
  flex-wrap: wrap;
}
.cx-range-change .pc-change { margin-top: 0; }
.cx-range-change-label {
  font-size: 11.5px;
  color: var(--text-muted);
}
.cx-chart-controls {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  justify-content: flex-end;
}
/* Segmented controls (chart type, price unit) share the range switch's shell so
   three groups sitting side by side read as one control strip rather than three
   unrelated widgets. */
.cx-seg[hidden] { display: none; }

/* ─── OHLC READOUT ───
   Follows the crosshair, and shows the last candle at rest. It is real text in
   the document rather than a hover-only tooltip, which is what keeps the chart
   readable without a pointer — the tooltip is an enhancement on top. */
.cx-ohlc {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 20px;
  padding: 12px 14px;
  margin-bottom: 14px;
  border-radius: 12px;
  background: rgba(255,255,255,0.03);
  border: 1px solid var(--border);
  font-size: 12.5px;
}
.cx-ohlc-cell {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  white-space: nowrap;
}
.cx-ohlc-cell b {
  font-weight: 700;
  color: var(--text-muted);
  font-size: 11px;
}
.cx-ohlc-cell span {
  font-weight: 700;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}

/* ─── CHART ───
   A fixed block height, not an aspect ratio: the SVG is drawn to whatever box
   it lands in, and a box that resizes with the viewport width would redraw on
   every resize tick.

   touch-action: pan-y is load-bearing. Without it the browser hands the whole
   gesture to the pointermove handler and a visitor who touches the chart while
   scrolling the page gets stuck on it. pan-y keeps vertical scrolling with the
   browser while a horizontal drag scrubs the crosshair. */
.cx-chart {
  position: relative;
  height: 360px;
  margin: 0;
  border-radius: var(--radius);
  overflow: hidden;
  touch-action: pan-y;
}
.cx-chart svg { display: block; width: 100%; height: 100%; }

/* SVG text does not inherit the page font, so the axis labels have to be told
   explicitly or they fall back to the UA serif and the numerals stop matching
   the rest of the page. */
.cx-axis {
  font-family: var(--font);
  font-size: 10.5px;
  fill: var(--text-muted);
  /* CSS `direction` inherits into SVG text and changes what text-anchor:start
     MEANS: under RTL the anchor lands at the text's right edge, so the price
     labels grew leftwards out of their gutter and over the plot. Forcing LTR
     here fixes the axis without touching the page: a label like «۱۱٫۵ میلیارد»
     still renders correctly, because the Persian word forms its own RTL bidi
     run inside an LTR line. */
  direction: ltr;
}
/* Deliberately NOT setting text-anchor here. A CSS declaration OUTRANKS the
   presentation attribute, so a rule on .cx-axis would silently override the
   text-anchor="middle" the time labels are drawn with and stack them all on
   one side. The anchors stay in the markup, per element. */
.cx-grid line { stroke: rgba(255,255,255,0.05); stroke-width: 1; }

/* ─── VOLUME BAND ───
   Was a row of flat rects at a fixed 22% opacity, which read as dead weight
   under the chart. Now: rounded tops, a gradient that fades toward the base, a
   staggered entrance, a live pulse on the newest bar, and a highlight that
   follows the crosshair.

   ⚠️ NOTHING HERE ANIMATES A BAR'S HEIGHT, AND THAT IS THE POINT. A bar's
   height IS the volume figure. A continuous "floating" drift — the idiom the
   landing's .float-p* cards use — would make every bar continuously misstate
   its own value, which is fine for a decorative price card and not fine for a
   data series. So the motion lives in opacity, glow and a one-shot entrance:
   the band feels alive without any frame of it being untrue. */
.cx-vol-base {
  stroke: rgba(255,255,255,0.07);
  stroke-width: 1;
}
.cx-vol-bar {
  transition: opacity 180ms ease, filter 180ms ease;
}
.cx-vol-bar.is-up   { fill: url(#cxVolUp); }
.cx-vol-bar.is-down { fill: url(#cxVolDown); }

/* Entrance: bars grow from the baseline, left to right. transform-box:fill-box
   is what makes transform-origin resolve against the shape's own box rather
   than the whole SVG canvas — without it every bar scales from the canvas
   corner and they fly in from off-screen. */
.cx-vol.is-entering .cx-vol-bar {
  transform-box: fill-box;
  transform-origin: 50% 100%;
  animation: cx-vol-rise 620ms cubic-bezier(0.22, 1, 0.36, 1) backwards;
  animation-delay: calc(var(--i, 0) * 18ms);
}
@keyframes cx-vol-rise {
  from { transform: scaleY(0.04); opacity: 0; }
  to   { transform: scaleY(1);    opacity: 1; }
}

/* The newest bar is the one still forming, so it is the only one that keeps
   moving. Opacity and glow only — see the note above on why not height. */
.cx-vol-bar.is-last {
  animation: cx-vol-live 2.4s ease-in-out 900ms infinite;
}
/* ⚠️ SPECIFICITY, NOT DECORATION. `.cx-vol.is-entering .cx-vol-bar` is 0,3,0
   and `.cx-vol-bar.is-last` is only 0,2,0 — so on a freshly loaded chart the
   entrance rule wins the `animation` property outright and the newest bar
   never pulses. The group keeps `is-entering` for the life of that SVG, so it
   would never have started pulsing either. Composing both animations in one
   declaration at 0,4,0 is what makes the last bar rise AND then breathe; the
   pulse is delayed past the end of the staggered entrance so the two do not
   overlap. */
.cx-vol.is-entering .cx-vol-bar.is-last {
  animation: cx-vol-rise 620ms cubic-bezier(0.22, 1, 0.36, 1) backwards,
             cx-vol-live 2.4s ease-in-out 1.6s infinite;
}
@keyframes cx-vol-live {
  0%, 100% { opacity: 1;    filter: none; }
  50%      { opacity: 0.62; filter: drop-shadow(0 0 6px currentColor); }
}
/* currentColor drives the glow above; fill is a gradient so it cannot. */
.cx-vol-bar.is-last.is-up   { color: #22c55e; }
.cx-vol-bar.is-last.is-down { color: #ef4444; }

/* While scrubbing, the band recedes and only the hovered bar stays lit, so the
   volume reading matches the candle the crosshair is on. */
.cx-chart.is-scrubbing .cx-vol-bar { opacity: 0.28; }
.cx-chart.is-scrubbing .cx-vol-bar.is-hot {
  opacity: 1;
  filter: drop-shadow(0 0 5px currentColor);
}
.cx-chart.is-scrubbing .cx-vol-bar.is-hot.is-up   { color: #22c55e; }
.cx-chart.is-scrubbing .cx-vol-bar.is-hot.is-down { color: #ef4444; }
/* The live pulse would fight the scrub highlight for the last bar. */
.cx-chart.is-scrubbing .cx-vol-bar.is-last { animation: none; }

/* ─── THE CURRENT ───
   A band of light sweeping UP through the green shapes and DOWN through the
   red ones. Two elements for the whole chart: each is clipped to a copy of one
   direction's geometry, so it only shows where it overlaps a candle body, a
   wick or a volume bar.

   `screen` blending is what makes it read as light passing THROUGH the shape
   rather than a grey rectangle sliding over it. Where it is unsupported the
   band still renders as a soft tint — dimmer, not broken.

   ⚠️ Only `transform` is animated — no width, height, x or y. Those are the
   properties that would force layout on an SVG every frame, and the shapes'
   dimensions are data besides. */
.cx-sheen {
  pointer-events: none;
  mix-blend-mode: screen;
  will-change: transform;
}
.cx-sheen-up {
  animation: cx-sheen-up 3.4s linear infinite;
}
.cx-sheen-down {
  animation: cx-sheen-down 3.4s linear infinite;
  /* Offset so the two directions do not cross the middle in lockstep, which
     reads as one pulsing chart rather than two opposing currents. */
  animation-delay: -1.1s;
}
/* --cx-h and --cx-sweep are set from JS off the rendered chart height. The
   fallbacks match the default .cx-chart height so a redraw that somehow lands
   before them still travels roughly the right distance. */
@keyframes cx-sheen-up {
  from { transform: translateY(var(--cx-h, 360px)); }
  to   { transform: translateY(calc(var(--cx-sweep, 198px) * -1)); }
}
@keyframes cx-sheen-down {
  from { transform: translateY(calc(var(--cx-sweep, 198px) * -1)); }
  to   { transform: translateY(var(--cx-h, 360px)); }
}
/* Reading a value takes precedence over ambience. */
.cx-chart.is-scrubbing .cx-sheen { animation-play-state: paused; opacity: 0.35; }

/* ─── CROSSHAIR ───
   Drawn once with the chart and moved by attribute afterwards; only its
   visibility is toggled here. */
.cx-cross-v,
.cx-cross-h {
  stroke: rgba(240,244,255,0.35);
  stroke-width: 1;
  stroke-dasharray: 3 3;
  opacity: 0;
  pointer-events: none;
}
.cx-cross-dot {
  fill: var(--text);
  stroke: var(--bg);
  stroke-width: 2;
  opacity: 0;
  pointer-events: none;
}
.cx-chart.is-scrubbing .cx-cross-v,
.cx-chart.is-scrubbing .cx-cross-h,
.cx-chart.is-scrubbing .cx-cross-dot { opacity: 1; }

/* ─── TOOLTIP ───
   Positioned with a transform set from JS. transform, not top/left: it moves on
   every pointermove, and only transform stays off the layout path. */
.cx-tip {
  position: absolute;
  top: 0;
  /* PHYSICAL `left`, not inset-inline-start — and this is one of the few places
     on these pages where a logical property is WRONG. The document is RTL, so
     inset-inline-start resolves to the RIGHT edge, while the transform JS sets
     is an offset measured from the SVG's LEFT edge (SVG coordinates have no
     text direction). Pairing the two sent the tooltip off the right side of the
     card at every position. */
  left: 0;
  z-index: 2;
  pointer-events: none;
  padding: 7px 11px;
  border-radius: 10px;
  background: rgba(11,13,16,0.92);
  border: 1px solid var(--border-h);
  box-shadow: 0 8px 24px rgba(0,0,0,0.5);
  white-space: nowrap;
  /* The element is measured by JS to clamp it inside the figure, so it must
     have a width before it is placed — hence no display:none while hidden. */
  will-change: transform;
}
.cx-tip[hidden] { visibility: hidden; display: block; }
.cx-tip-date {
  font-size: 10.5px;
  color: var(--text-muted);
  margin-bottom: 3px;
}
.cx-tip-price {
  font-size: 13px;
  font-weight: 800;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.cx-chart-state {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  color: var(--text-muted);
  text-align: center;
  padding: 0 20px;
}
.cx-chart-state[hidden] { display: none; }
.cx-chart-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 24px;
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid var(--border);
  font-size: 12.5px;
  color: var(--text-sub);
}
.cx-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 7px;
}
.cx-legend-key {
  color: var(--text-muted);
  font-weight: 700;
}
.cx-legend-unit { color: var(--text-muted); }
.cx-legend-unit:empty { display: none; }

/* ─── TOOLS ─── */
.cx-tools { padding: 40px 0 0; }
/* Back to an explicit two columns (Reza, 2026-08-02): the row is the converter
   and the calculator, side by side. Explicit rather than auto-fit — with only
   two cards, auto-fit's track count depends on the container width, so the pair
   would silently become a single column on a narrower desktop instead of at the
   breakpoint below, where the decision is written down. */
.cx-tools-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 18px;
}
.cx-tool-sub {
  font-size: 13.5px;
  line-height: 1.8;
  color: var(--text-sub);
  margin: 10px 0 18px;
}
.cx-tool-note {
  font-size: 11.5px;
  line-height: 1.8;
  color: var(--text-muted);
  margin: 16px 0 0;
}

/* ─── EQUAL-HEIGHT TOOL CARDS ───
   The three cards hold different amounts of content — a converter, a list that
   is one row for BTC and five for USDT, and a calculator — so left alone they
   end up ragged, or (with the grid stretching them) one card carries a pool of
   dead space under its content.

   Two rules fix it together, and neither works without the other:
     1. the card is a flex COLUMN, so its children can be told how to share the
        height the grid gives it;
     2. .cx-tool-body takes the leftover space and CENTRES its content, while
        the closing note stays last.
   The result is that the spare room in the shortest card is split above and
   below its content rather than dumped at the bottom, and the notes line up
   across all three. */
.cx-tool {
  display: flex;
  flex-direction: column;
}
.cx-tool-body {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 10px;
  min-height: 0;
}

/* ─── CONVERTER ─── */
/* STACKED, at every width — not a two-column row.
   The tools grid gives each card about 380px, so two side-by-side fields left
   roughly 150px each. A Toman price for bitcoin is eleven digits plus
   separators and simply does not fit: the field silently clipped it mid-number
   ("۱۱٬۵۳۳٬۶۸۱٬۱"), which on a price page is worse than showing nothing —
   a clipped number still reads as a number. Full width per field removes the
   constraint instead of shrinking the type to hide it. */
.cx-conv {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  justify-items: stretch;
  gap: 10px;
}
.cx-conv-field {
  display: flex;
  flex-direction: column;
  gap: 7px;
  min-width: 0;
}
.cx-conv-label {
  font-size: 11.5px;
  font-weight: 700;
  color: var(--text-muted);
}
.cx-conv-input {
  width: 100%;
  background: rgba(255,255,255,0.03);
  border: 1px solid var(--border);
  border-radius: 12px;
  color: var(--text);
  font-family: inherit;
  font-size: 15px;
  font-weight: 700;
  padding: 12px 14px;
  outline: 0;
  transition: border-color 0.2s ease, background 0.2s ease;
  /* Amounts are LTR runs: a number typed into an RTL field otherwise puts the
     caret and any minus sign on the wrong side. */
  direction: ltr;
  text-align: start;
}
.cx-conv-input:focus {
  border-color: var(--cx-accent, var(--blue2));
  background: var(--surface-h);
}
/* Sits between the two stacked fields, centred, pointing down the flow. */
.cx-conv-swap {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  justify-self: center;
  width: 30px;
  height: 30px;
  margin: -2px 0;
  border-radius: 50%;
  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--text-muted);
  flex-shrink: 0;
}
.cx-conv-swap svg { width: 16px; height: 16px; }

/* ─── RETURN CALCULATOR ─── */
.cx-calc {
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.cx-calc-out {
  margin: 0;
  border-radius: 12px;
  background: rgba(255,255,255,0.03);
  border: 1px solid var(--border);
  overflow: hidden;
}
.cx-calc-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 11px 14px;
}
.cx-calc-row + .cx-calc-row { border-top: 1px solid var(--border); }
.cx-calc-row dt {
  font-size: 12px;
  font-weight: 700;
  color: var(--text-muted);
  margin: 0;
}
.cx-calc-row dd {
  margin: 0;
  font-size: 14px;
  font-weight: 800;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  text-align: end;
}
.cx-calc-row dd .pc-change { margin-top: 0; }

/* ─── CONVERTER: side switch ───
   Not the plain .cx-seg the chart toggles use. This one picks between paying
   and receiving money, so it gets the weight to match: full width, a sliding
   thumb, and the side's own colour — green for buying, red for selling. The
   colour is the fastest read on the card and it matches the up/down language
   the chart already uses. */
.cx-side-switch {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0;
  padding: 4px;
  margin-bottom: 16px;
  background: rgba(255,255,255,0.035);
  border: 1px solid var(--border);
  border-radius: 14px;
  isolation: isolate;
}
.cx-side-thumb {
  position: absolute;
  z-index: 0;
  inset-block: 4px;
  /* LOGICAL offsets, and deliberately so: the document is RTL, the first
     button sits on the RIGHT, and a transform-based thumb would have to know
     that. inset-inline-start resolves per direction on its own, so the slide is
     correct in RTL and would stay correct if the page were ever served LTR.
     Transitioning an inset is less efficient than a transform — irrelevant for
     one 150px element moved on click, and worth it not to hardcode a side. */
  inset-inline-start: 4px;
  width: calc(50% - 4px);
  border-radius: 11px;
  background: rgba(34,197,94,0.16);
  border: 1px solid rgba(34,197,94,0.34);
  box-shadow: 0 4px 14px rgba(34,197,94,0.14);
  transition: inset-inline-start 260ms cubic-bezier(0.4, 0, 0.2, 1),
              background 220ms ease, border-color 220ms ease, box-shadow 220ms ease;
}
.cx-side-switch.is-sell .cx-side-thumb {
  inset-inline-start: 50%;
  background: rgba(239,68,68,0.16);
  border-color: rgba(239,68,68,0.34);
  box-shadow: 0 4px 14px rgba(239,68,68,0.14);
}
.cx-side-btn {
  position: relative;
  z-index: 1;
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--text-muted);
  font-family: inherit;
  font-size: 13.5px;
  font-weight: 800;
  padding: 10px 8px;
  border-radius: 11px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  transition: color 200ms ease;
}
.cx-side-btn svg {
  width: 15px;
  height: 15px;
  transition: transform 260ms cubic-bezier(0.4, 0, 0.2, 1);
}
.cx-side-btn:hover { color: var(--text-sub); }
.cx-side-btn[data-cx-side="buy"].is-active  { color: #22c55e; }
.cx-side-btn[data-cx-side="sell"].is-active { color: #ef4444; }
/* The arrow lifts on the active side — the same up/down language the candles
   and the volume sweep already speak. */
.cx-side-btn[data-cx-side="buy"].is-active svg  { transform: translateY(-1px); }
.cx-side-btn[data-cx-side="sell"].is-active svg { transform: translateY(1px); }
.cx-side-btn:focus-visible {
  outline: 2px solid var(--blue2);
  outline-offset: 2px;
}
@media (prefers-reduced-motion: reduce) {
  .cx-side-thumb, .cx-side-btn svg { transition: none; }
}
/* The NETWORKS card was removed on 2026-08-02 (Reza) and its rules went with
   it — including the wrapped-token warning styling. If the card ever returns,
   take BOTH back from git history together: the list without that styling puts
   a pegged token back on screen looking like an ordinary network. */

/* ─── SPECS ─── */
.cx-specs { padding: 40px 0 0; }
/* FLEX, NOT GRID — and the switch fixes two separate defects.

   1. auto-fit sized the tracks from a 190px minimum, so a wide card got five
      columns while the six specs (one of them spanning two) needed seven track
      units. The row broke, and «مکانیزم اجماع» and «حداکثر عرضه» dropped onto a
      second line. With `flex: 1 1 0` the cells simply divide whatever width
      there is, so the count of specs decides the layout instead of the
      container's arithmetic — which matters because the count VARIES: a coin
      with no recorded founder or max supply renders four cells, not six.
   2. The dividers used to be the parent's background showing through a 2px
      gap. That trick leaks: an incomplete last row has no cells to cover the
      background, which is where the empty grey slab came from. Dividers are
      now borders ON the cells, so there is nothing to leak. */
.cx-spec-grid {
  display: flex;
  flex-wrap: wrap;
  margin: 20px 0 0;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--bg2);
}
.cx-spec {
  flex: 1 1 0;
  min-width: 118px;
  background: var(--bg2);
  padding: 14px 14px;
  border-inline-start: 1px solid var(--border);
}
.cx-spec:first-child { border-inline-start: 0; }
.cx-spec dt {
  font-size: 11.5px;
  font-weight: 700;
  color: var(--text-muted);
  margin-bottom: 6px;
}
.cx-spec dd {
  font-size: 13.5px;
  font-weight: 700;
  color: var(--text);
  margin: 0;
  line-height: 1.6;
}
/* The network cell can carry a list — USDT names five — where every other spec
   is a word or a number. A bigger flex-grow gives it a larger share of the row
   without taking it out of the row, which `grid-column: span 2` did. */
.cx-spec-wide {
  flex-grow: 1.5;
  min-width: 170px;
}

/* TABLET: three per row.
   One row of six survives down to about 1200px, but below that each cell is
   narrow enough that a technical value breaks mid-token — «اثبات کار (SHA‑256)»
   split after the hyphen into "SHA-" and "256". Three per row gives roughly
   double the width and nothing breaks.
   The dividers have to turn with the layout: cells on the second row need a
   rule above them, and the first cell of each row must not draw one against the
   container's own border. Hence the two nth-child rules — they are the price of
   drawing dividers on the cells, which is what stopped the old background trick
   from leaking through an incomplete row. */
@media (min-width: 768px) and (max-width: 1199.98px) {
  .cx-spec {
    flex: 1 1 30%;
    border-top: 1px solid var(--border);
  }
  .cx-spec:nth-child(-n + 3) { border-top: 0; }
  .cx-spec:nth-child(3n + 1) { border-inline-start: 0; }
  /* The network cell gives up its extra share here: with three per row it would
     push the count to two-and-a-bit and break the rhythm the nth-child rules
     assume. */
  .cx-spec-wide { flex-grow: 1; min-width: 0; }
}

/* MOBILE: stacked, dividers horizontal. Stacking rather than a ragged 2-up —
   with a varying number of specs per coin, a 2-up leaves an orphan cell on the
   last row often enough to look accidental. */
@media (max-width: 767.98px) {
  .cx-spec {
    flex: 1 1 100%;
    border-inline-start: 0;
    border-top: 1px solid var(--border);
  }
  .cx-spec:first-child { border-top: 0; }
  .cx-spec-wide { flex-grow: 1; min-width: 0; }
}
.cx-links {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 20px;
}
.cx-link {
  font-size: 12.5px;
  font-weight: 700;
  color: var(--text-sub);
  text-decoration: none;
  padding: 8px 14px;
  border-radius: 999px;
  background: var(--surface);
  border: 1px solid var(--border);
  transition: color 0.2s ease, border-color 0.2s ease;
}
.cx-link:hover {
  color: var(--text);
  border-color: var(--border-h);
}

/* ─── ABOUT ─── */
.cx-about { padding: 64px 0 0; }
.cx-about-inner { max-width: 820px; }
.cx-about-title { margin-bottom: 22px; }
.cx-prose p {
  font-size: 15.5px;
  line-height: 2.1;
  color: var(--text-sub);
  margin: 0 0 20px;
}
.cx-prose p:last-child { margin-bottom: 0; }

/* ─── CONTENT SECTIONS ───
   The H2-led blocks under the intro prose (coin_sections). Each carries a
   heading that is a real question about THIS coin, which is the part search
   engines weigh most heavily after the title — so they are styled as genuine
   document structure, not as cards.

   The rule above each heading is a border on the block rather than an <hr>:
   the separation is presentational, and a horizontal rule would put a
   meaningless element into the document outline between two real ones. */
.cx-sec {
  margin-top: 40px;
  padding-top: 32px;
  border-top: 1px solid var(--border);
}
.cx-sec-h {
  font-size: clamp(19px, 2.1vw, 25px);
  font-weight: 800;
  line-height: 1.5;
  letter-spacing: -0.2px;
  color: var(--text);
  margin: 0 0 18px;
}
/* The heading gets the coin's accent as a short leading rule — enough to mark
   the start of a block without the weight of a full card border. */
.cx-sec-h::before {
  content: '';
  display: block;
  width: 34px;
  height: 3px;
  border-radius: 2px;
  background: var(--cx-accent, var(--blue2));
  margin-bottom: 14px;
  opacity: 0.85;
}

/* ─── FAQ ─── */
.cx-faq { padding: 64px 0 0; }
.cx-faq-inner { max-width: 820px; }
.cx-faq-title { margin-bottom: 22px; }
.cx-faq-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.cx-faq-item {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 2px 18px;
  transition: border-color 0.2s ease;
}
.cx-faq-item[open] { border-color: var(--border-h); }
.cx-faq-q {
  font-size: 14.5px;
  font-weight: 700;
  color: var(--text);
  padding: 16px 0;
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
}
.cx-faq-q::-webkit-details-marker { display: none; }
.cx-faq-q::after {
  content: '+';
  font-size: 20px;
  font-weight: 400;
  color: var(--text-muted);
  line-height: 1;
  flex-shrink: 0;
  transition: transform 0.2s ease, color 0.2s ease;
}
.cx-faq-item[open] .cx-faq-q::after {
  transform: rotate(45deg);
  color: var(--cx-accent, var(--blue2));
}
.cx-faq-a {
  font-size: 14px;
  line-height: 2;
  color: var(--text-sub);
  margin: 0;
  padding: 0 0 18px;
}

/* ─── OTHER COINS ─── */
.cx-others { padding: 64px 0 0; }
.cx-others-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  margin-bottom: 20px;
}
.cx-others-title { margin: 0; }
.cx-others-all {
  font-size: 13px;
  font-weight: 700;
  color: var(--blue2);
  text-decoration: none;
}
.cx-others-all:hover { text-decoration: underline; }
.cx-chips {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 10px;
}
.cx-chip {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 12px 14px;
  border-radius: var(--radius);
  text-decoration: none;
  color: inherit;
  transition: transform 0.2s ease, border-color 0.2s ease;
}
.cx-chip:hover {
  transform: translateY(-1px);
  border-color: var(--border-h);
}
.cx-chip-copy {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
  flex: 1 1 auto;
}
.cx-chip-name {
  font-size: 13.5px;
  font-weight: 700;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.cx-chip-toman { font-size: 11.5px; color: var(--text-muted); }
.cx-chip-change { margin-top: 0; font-size: 10.5px; padding: 2px 7px; }

/* ─── CTA ─── */
.cx-cta { padding: 80px 0 96px; }
.cx-cta-card {
  border-radius: var(--radius-xl);
  padding: 48px 40px;
  text-align: center;
}
.cx-cta-title {
  font-size: clamp(24px, 3vw, 36px);
  font-weight: 900;
  color: var(--text);
  margin: 0 0 12px;
  letter-spacing: -0.5px;
}
.cx-cta-sub {
  font-size: 15px;
  line-height: 1.9;
  color: var(--text-sub);
  margin: 0 auto 26px;
  max-width: 520px;
}
.cx-cta-actions {
  display: flex;
  justify-content: center;
  gap: 12px;
  flex-wrap: wrap;
}

/* ─── PRICE UPDATE FLASH ───
   Mirrors index.js's .price-flash, which lives in the bundle and is bound to
   the landing's own cards. Re-declared here under its own name so these pages
   do not depend on a selector in a file they do not control. */
@keyframes cx-flash {
  0%   { color: var(--blue2); }
  100% { color: inherit; }
}
.cx-updating { animation: cx-flash 0.6s ease-out; }
@media (prefers-reduced-motion: reduce) {
  .cx-updating { animation: none; }
  .cx-live-dot { animation: none; }
  .cx-row:hover, .cx-chip:hover { transform: none; }
  /* The volume band keeps its colour and its crosshair highlight — those carry
     meaning — and loses only the motion: no staggered entrance, no pulse. A
     visitor who asked the OS for less motion still gets the whole chart.
     ⚠️ The third selector is required, not redundant: a media query does not
     raise specificity, so without a 0,4,0 rule here the composed
     `.cx-vol.is-entering .cx-vol-bar.is-last` above would keep animating for
     exactly the visitor who asked it not to. */
  .cx-vol.is-entering .cx-vol-bar { animation: none; }
  .cx-vol-bar.is-last { animation: none; }
  .cx-vol.is-entering .cx-vol-bar.is-last { animation: none; }
  /* The sweep is pure motion with no informational content, so it is removed
     outright rather than slowed — leaving a stationary bright band parked over
     part of the chart would be worse than not having it. */
  .cx-sheen { display: none; }
}

/* ═══════════════════ RESPONSIVE ═══════════════════ */

@media (max-width: 991.98px) {
  .cx-top-grid { grid-template-columns: minmax(0, 1fr); }
  .cx-tools-grid { grid-template-columns: minmax(0, 1fr); }
}

/* The row stops being a table row and becomes a card. The column header strip
   goes with it — headings for columns that no longer exist mislabel the data
   underneath. Each cell's own .cx-lbl takes over. */
@media (max-width: 859.98px) {
  .cx-head { display: none; }
  .cx-row {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 14px 12px;
    padding: 16px;
  }
  /* The rank rides along with the coin name in the card layout rather than
     taking a cell of its own — a two-column card cannot spare one for a
     three-character number. */
  .cx-c-rank {
    grid-column: 1 / -1;
    text-align: start;
    margin-bottom: -8px;
  }
  .cx-c-coin { grid-column: 1 / -1; }
  .cx-c-go {
    grid-column: 1 / -1;
    justify-self: start;
  }
  .cx-lbl {
    display: block;
    font-size: 10.5px;
    font-weight: 700;
    color: var(--text-muted);
    margin-bottom: 4px;
  }
  /* The left-edge alignment above exists to build a column out of many rows.
     A card has no column: each price sits alone under its own «قیمت خرید»
     label, so it goes back to the start edge that label uses. */
  .cx-c-usd,
  .cx-c-toman { text-align: start; }
  .cx-row::before { opacity: 1; }
}

@media (max-width: 575.98px) {
  .cx-hero { padding-block-start: 40px; }
  .cx-identity { gap: 14px; }
  .cx-mark-xl { width: 54px; height: 54px; border-radius: 16px; }
  .cx-mark-xl img { width: 32px; height: 32px; }
  .cx-card { padding: 20px; }
  .cx-quote { padding: 18px; }
  .cx-chart { height: 260px; }
  /* The three control groups stop trying to sit on one right-aligned row and
     become a left-to-right strip under the title — at this width the alignment
     was pushing the range switch onto a line of its own anyway. */
  .cx-chart-controls { justify-content: flex-start; }
  .cx-range, .cx-seg-btn { padding: 6px 10px; font-size: 12px; }
  /* Two columns of label/value rather than one long wrapping row, so the
     readout stays scannable instead of becoming six stacked lines. */
  .cx-ohlc {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 8px 12px;
  }
  .cx-ohlc-cell { justify-content: space-between; }
  /* No .cx-conv override here on purpose: it is single-column at every width
     now (see the note on the rule itself). The block that used to sit here
     restated exactly that, which reads as load-bearing and is not. */
  .cx-cta-card { padding: 34px 22px; }
  .cx-quote-actions { flex-direction: column; }
}
