/* #530: interactive :hover rules are individually wrapped in
   @media (hover: hover) and (pointer: fine) below/above — without the guard,
   mobile browsers emulate hover on tap and the style STICKS until the next tap
   (order buttons kept their hover skin after use). Deliberately NOT wrapped:
   scrollbar :hover (no scrollbar hover exists on touch) and the .has-tip /
   .order-insight-wrap reveal rules — on touch, the emulated tap-hover is the
   ONLY way those tooltips/popups can be opened at all. */
/* ========== GLOBAL SCROLLBAR (dark theme) ========== */
* {
  scrollbar-width: thin;
  scrollbar-color: rgba(var(--app-content-overlay-rgb), 0.15) transparent;
}
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: rgba(var(--app-content-overlay-rgb), 0.15); border-radius: 3px; }
::-webkit-scrollbar-thumb:hover { background: rgba(var(--app-content-overlay-rgb), 0.25); }

/* ========== INSTRUMENT INFO BAR ========== */
.instrument-bar {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  padding: 16px 32px 14px;
  background: var(--app-surface-1);
  border-bottom: 1px solid rgba(var(--app-content-overlay-rgb),0.06);
}

.inst-breadcrumb {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 8px;
  font-size: 12px;
}

.inst-breadcrumb a {
  color: #5a5a6a;
  text-decoration: none;
  transition: color 0.15s;
}

@media (hover: hover) and (pointer: fine) {
.inst-breadcrumb a:hover {
  color: var(--app-primary);
}
}

.inst-breadcrumb svg {
  color: #3a3a4a;
}

.inst-breadcrumb-current {
  color: var(--app-text-muted-2);
}

.inst-bar-title-row {
  display: flex;
  align-items: center;
  gap: 10px;
}

.inst-bar-symbol {
  font-family: 'Inter', -apple-system, sans-serif;
  font-size: 20px;
  font-weight: 700;
  color: var(--app-text-1);
  letter-spacing: -0.3px;
}

.exchange-badge {
  font-size: 11px;
  font-weight: 600;
  color: var(--app-text-muted-2);
  background: rgba(var(--app-content-overlay-rgb),0.06);
  padding: 3px 10px;
  border-radius: 4px;
  letter-spacing: 0.3px;
}

/* Contract Type Tags (Options) */
.type-tag {
  font-size: 11px;
  font-weight: 700;
  padding: 3px 10px;
  border-radius: 4px;
  letter-spacing: 0.3px;
  text-transform: uppercase;
}
.type-tag.call { color: var(--app-primary); background: rgba(92, 184, 230, 0.1); }
.type-tag.put { color: var(--app-sell); background: rgba(224, 160, 80, 0.1); }

.inst-bar-metrics {
  display: flex;
  align-items: flex-end;
  gap: 0;
}

.inst-metric {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  justify-content: flex-start;
  padding: 0 20px;
  min-height: 48px;
}

.inst-metric:last-child {
  padding-right: 0;
}

.inst-metric-divider {
  width: 1px;
  height: 32px;
  background: rgba(var(--app-content-overlay-rgb),0.06);
  flex-shrink: 0;
}

.metric-label {
  font-size: 10px;
  font-weight: 600;
  color: #4a4a5a;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  margin-bottom: 4px;
}

.metric-value {
  font-size: 15px;
  font-weight: 600;
  color: var(--app-text-1);
  font-variant-numeric: tabular-nums;
}

.metric-sub {
  font-size: 11px;
  font-weight: 500;
  margin-top: 2px;
}

/* #535: signed values share ONE token pair with the instrument picker
   (.inst-dd-item-change.positive/.negative in trade-futures.css): up = --app-buy,
   down = --app-sell. On Vestex --app-primary === --app-buy, so this is zero-diff;
   on light partner themes (Ultimo) --app-primary is the brand gold, which made
   metrics-bar positives a third colour system beside the picker's blue. */
.metric-sub.positive { color: var(--app-buy); }
.metric-sub.negative { color: var(--app-sell); }

.expiry-countdown {
  color: var(--app-primary) !important;
}

/* ========== GREEKS BAR ========== */
.greeks-bar {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0;
  padding: 0 32px;
  height: 40px;
  background: rgba(26, 26, 31, 0.6);
  border-bottom: 1px solid rgba(var(--app-content-overlay-rgb),0.04);
}

.greek-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0 20px;
  border-right: 1px solid rgba(var(--app-content-overlay-rgb),0.04);
}

.greek-item:last-child {
  border-right: none;
}

.greek-label {
  font-size: 11px;
  font-weight: 500;
  color: #5a5a6a;
}

.greek-value {
  font-size: 12px;
  font-weight: 600;
  color: var(--app-text-muted-3);
  font-variant-numeric: tabular-nums;
}

.greek-value.negative { color: var(--app-sell); }

/* ========== TRADE MAIN ========== */
.trade-main {
  padding: 28px 40px 80px;
}

.trade-card {
  background: var(--app-surface-1);
  border: 1px solid rgba(var(--app-content-overlay-rgb),0.06);
  border-radius: 12px;
  padding: 20px;
}

.trade-card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 14px;
}

.trade-card-title {
  font-size: 15px;
  font-weight: 600;
  color: var(--app-text-1);
}

/* ========== CHART + ORDER TOP GRID ========== */
.trade-top-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  margin-bottom: 16px;
  align-items: stretch;
}
.trade-top-grid > .trade-chart-card {
  flex: 1 1 500px;
  min-width: 0;
}
.trade-top-grid > .trade-orderbook {
  flex: 0 0 240px;
  min-width: 200px;
}
.trade-top-grid > .trade-order-panel {
  flex: 0 0 340px;
  min-width: 280px;
}

/* ===== TRADE PAGE RESPONSIVE ===== */

/* Option page legacy responsive — kept for trade-option.html only.
   Spot/Futures/Equity (body.trade-page-3up) get the new 3-tier layout below. */

/* Tablet: hide orderbook, stack chart and order panel side by side */
@media (max-width: 1100px) {
  .trade-top-grid > .trade-orderbook {
    display: none;
  }
  .trade-top-grid > .trade-chart-card {
    flex: 1 1 400px;
  }
  .trade-top-grid > .trade-order-panel {
    flex: 0 0 320px;
    min-width: 280px;
  }
  .trade-main {
    padding: 20px 20px 80px;
  }
}

/* Narrow tablet / large mobile: stack everything vertically */
@media (max-width: 860px) {
  .trade-top-grid {
    flex-direction: column;
  }
  .trade-top-grid > .trade-chart-card {
    flex: none;
    width: 100%;
    height: clamp(320px, 55vh, 480px);
    min-height: 300px;
  }
  .trade-top-grid > .trade-chart-card #futuresChart,
  .trade-top-grid > .trade-chart-card #optionsChart,
  .trade-top-grid > .trade-chart-card .chart-area {
    height: 100% !important;
    min-height: 0 !important;
  }
  .trade-top-grid > .trade-order-panel {
    flex: none;
    width: 100%;
    max-width: none;
  }
  .trade-top-grid > .trade-orderbook {
    display: none;
  }
  /* #543: this block used to re-declare the .instrument-bar column flip
     (flex-direction / align-items / gap, metrics wrap, divider none) a THIRD
     time. Identical values already apply from the 1024px block below —
     with !important, over a superset of this range — so the copy here was
     shadowed weight and is gone. */
}

/* ===== BUG #15: Spot / Futures / Equity unified responsive layout =====
   - Wide (>=1440px): 3-column flex (Chart | OrderBook | OrderPanel) — inherits base
   - Mid  (1024-1439px): CSS Grid 2x2 — Chart top-left, OrderBook bottom-left
                         (280px), OrderPanel right spanning 2 rows.
   - Narrow (<1024px): vertical stack Chart -> OrderPanel -> OrderBook.
   Scoped to body.trade-page-3up so trade-option.html is unaffected.
*/

/* Mid: 1024-1439px */
@media (min-width: 1024px) and (max-width: 1439px) {
  body.trade-page-3up .trade-top-grid {
    display: grid;
    grid-template-columns: 1fr 340px;
    grid-template-rows: auto auto;
    gap: 16px;
    align-items: stretch;
  }
  body.trade-page-3up .trade-top-grid > .trade-chart-card,
  body.trade-page-3up .trade-top-grid > .spot-chart-card {
    grid-column: 1; grid-row: 1;
    flex: none;
    min-width: 0;
    height: clamp(460px, 58vh, 620px) !important;
  }
  body.trade-page-3up .trade-top-grid > .trade-orderbook,
  body.trade-page-3up .trade-top-grid > .spot-orderbook {
    grid-column: 1; grid-row: 2;
    display: block !important;
    flex: none;
    width: auto;
    height: 280px !important;
    max-height: 280px;
    overflow-y: auto;
  }
  body.trade-page-3up .trade-top-grid > .trade-order-panel,
  body.trade-page-3up .trade-top-grid > .spot-order-panel {
    grid-column: 2;
    grid-row: 1 / span 2;
    flex: none;
    max-width: none;
  }
}

/* Narrow: <1024px — vertical stack Chart -> OrderPanel -> OrderBook
   Chart card lower bound (420px) is set above the inner #spotTvChart
   min-height (400px) so the TradingView iframe never overflows. */
@media (max-width: 1023px) {
  body.trade-page-3up .trade-top-grid {
    display: flex;
    flex-direction: column;
  }
  body.trade-page-3up .trade-top-grid > .trade-chart-card,
  body.trade-page-3up .trade-top-grid > .spot-chart-card {
    flex: none;
    width: 100%;
    height: clamp(420px, 55vh, 540px) !important;
    min-height: 420px;
    order: 1;
  }
  body.trade-page-3up .trade-top-grid > .trade-order-panel,
  body.trade-page-3up .trade-top-grid > .spot-order-panel {
    flex: none;
    width: 100%;
    max-width: none;
    order: 2;
  }
  body.trade-page-3up .trade-top-grid > .trade-orderbook,
  body.trade-page-3up .trade-top-grid > .spot-orderbook {
    display: block !important;
    flex: none;
    width: 100%;
    height: 320px !important;
    max-height: 320px;
    order: 3;
  }

  /* #320: iOS Safari + TradingView Advanced Charts measure container size
     synchronously at widget construction. With only `flex: 1` on the inner
     chart div, iOS sometimes reports 0 height because flex basis hasn't
     propagated yet on mobile Safari. Force explicit `flex: 1 1 0` AND a
     concrete `min-height: 380px` fallback so the rect is always non-zero —
     even if the parent's vh-derived height hasn't finalized. 380px sits
     comfortably under the 420px parent min-height (no overflow). Card
     `position: relative` is a defensive anchor for absolutely-positioned
     children (BUG #80 loading overlay). Attribution typography is
     intentionally untouched — binding to TradingView's external DOM is
     fragile. */
  body.trade-page-3up .trade-top-grid > .trade-chart-card,
  body.trade-page-3up .trade-top-grid > .spot-chart-card {
    position: relative;
  }
  body.trade-page-3up .trade-top-grid > .trade-chart-card > #futuresChart,
  body.trade-page-3up .trade-top-grid > .spot-chart-card > #spotTvChart {
    flex: 1 1 0 !important;
    width: 100% !important;
    min-height: 380px !important;
  }

  /* #523: the Futures V.2 chart div (#futures2Chart) was missing from the
     list above, so its inline min-height:400px stood while the card height
     is clamp(420px, 55vh, 540px) — 20px padding ×2 + attribution (~21px) +
     400px = ~461px of content in a 420-448px card, i.e. the measured 25px of
     chart spilling past the card on every phone. Same flex-basis treatment
     as its v1 siblings (#320: iOS needs a concrete non-zero min-height at
     widget construction), but the floor is 340px so the worst case —
     40 + 340 + 21 = 401px — fits the 420px minimum card with room to spare;
     at larger viewports flex-grow gives the chart every spare pixel. */
  body.trade-page-3up .trade-top-grid > .trade-chart-card > #futures2Chart {
    flex: 1 1 0 !important;
    width: 100% !important;
    min-height: 340px !important;
  }
}

/* Chart Card */
.trade-chart-card, .spot-chart-card {
  display: flex;
  flex-direction: column;
}

/* TradingView attribution backlink (required by license) */
.tradingview-attribution {
  text-align: center;
  padding: 10px 0 0;
  margin: 4px 0 -6px;
  font-size: 12px;
  color: rgba(var(--app-content-overlay-rgb),0.4);
  line-height: 1;
  border-top: 1px solid rgba(var(--app-content-overlay-rgb),0.06);
}
.tradingview-attribution a {
  color: var(--app-primary);
  text-decoration: none;
}
@media (hover: hover) and (pointer: fine) {
.tradingview-attribution a:hover {
  text-decoration: underline;
}
}

.chart-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 12px;
}

.chart-type-tabs {
  display: flex;
  gap: 2px;
  background: rgba(var(--app-content-overlay-rgb),0.03);
  border-radius: 6px;
  padding: 2px;
}

.chart-type-btn {
  background: none;
  border: none;
  color: var(--app-text-muted-2);
  font-size: 12px;
  font-weight: 500;
  padding: 6px 14px;
  border-radius: 4px;
  cursor: pointer;
  transition: all 0.15s;
}

@media (hover: hover) and (pointer: fine) {
.chart-type-btn:hover {
  color: var(--app-text-1);
}
}

.chart-type-btn.active {
  color: var(--app-text-1);
  background: rgba(var(--app-content-overlay-rgb),0.06);
}

.trade-chart-area {
  display: flex;
  flex: 1;
  min-height: 0;
}

/* ========== ORDER PANEL ========== */
.trade-order-panel {
  display: flex;
  flex-direction: column;
}

.order-side-toggle {
  display: flex;
  gap: 4px;
  margin-bottom: 20px;
  background: rgba(var(--app-content-overlay-rgb),0.03);
  border-radius: 8px;
  padding: 3px;
}

.order-side-btn {
  flex: 1;
  padding: 10px;
  border: none;
  border-radius: 6px;
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
  transition: all 0.15s;
  background: transparent;
  color: var(--app-text-muted-2);
}

.order-side-btn.buy.active {
  background: rgba(92, 184, 230, 0.15);
  color: var(--app-primary);
}

.order-side-btn.sell.active {
  background: rgba(224, 160, 80, 0.15);
  color: var(--app-sell);
}

@media (hover: hover) and (pointer: fine) {
.order-side-btn:hover:not(.active) {
  color: var(--app-text-muted-3);
}
}

.order-type-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 16px;
}

.order-type-label {
  font-size: 12px;
  color: var(--app-text-muted-2);
  font-weight: 500;
}

.order-type-tabs {
  display: flex;
  gap: 2px;
  background: rgba(var(--app-content-overlay-rgb),0.03);
  border-radius: 4px;
  padding: 2px;
}

.order-type-btn {
  background: none;
  border: none;
  color: var(--app-text-muted-2);
  font-size: 11px;
  font-weight: 600;
  padding: 5px 12px;
  border-radius: 3px;
  cursor: pointer;
  transition: all 0.15s;
}

.order-type-btn.active {
  color: var(--app-text-1);
  background: rgba(var(--app-content-overlay-rgb),0.06);
}

.order-field {
  margin-bottom: 14px;
}

.order-field label {
  display: block;
  font-size: 12px;
  color: var(--app-text-muted-2);
  font-weight: 500;
  margin-bottom: 6px;
}

.order-input-wrap {
  display: flex;
  align-items: center;
  background: rgba(var(--app-content-overlay-rgb),0.04);
  border: 1px solid rgba(var(--app-content-overlay-rgb),0.08);
  border-radius: 8px;
  overflow: hidden;
  transition: border-color 0.15s;
}

.order-input-wrap:focus-within {
  border-color: rgba(92, 184, 230, 0.3);
}

.order-step-btn {
  background: none;
  border: none;
  color: var(--app-text-muted-2);
  font-size: 16px;
  padding: 10px 14px;
  cursor: pointer;
  transition: all 0.15s;
  user-select: none;
}

@media (hover: hover) and (pointer: fine) {
.order-step-btn:hover {
  color: var(--app-text-1);
  background: rgba(var(--app-content-overlay-rgb),0.04);
}
}

.order-input {
  flex: 1;
  background: none;
  border: none;
  color: var(--app-text-1);
  font-size: 15px;
  font-weight: 600;
  text-align: center;
  padding: 10px 0;
  outline: none;
  font-variant-numeric: tabular-nums;
  font-family: inherit;
}

.order-field-sub {
  font-size: 11px;
  color: #5a5a6a;
  margin-top: 4px;
  text-align: right;
}

.order-quick-btns {
  display: flex;
  gap: 4px;
  margin-top: 6px;
}

.quick-btn {
  flex: 1;
  background: rgba(var(--app-content-overlay-rgb),0.03);
  border: 1px solid rgba(var(--app-content-overlay-rgb),0.06);
  color: var(--app-text-muted-2);
  font-size: 11px;
  font-weight: 600;
  padding: 5px 0;
  border-radius: 4px;
  cursor: pointer;
  transition: all 0.15s;
}

@media (hover: hover) and (pointer: fine) {
.quick-btn:hover {
  color: var(--app-text-1);
  border-color: rgba(var(--app-content-overlay-rgb),0.12);
}
}

.quick-btn.active {
  color: var(--app-primary);
  border-color: rgba(92, 184, 230, 0.3);
  background: rgba(92, 184, 230, 0.06);
}

.order-options {
  display: flex;
  gap: 16px;
  margin-bottom: 16px;
}

.order-checkbox {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--app-text-muted-2);
  cursor: pointer;
}

.order-checkbox input[type="checkbox"] {
  width: 14px;
  height: 14px;
  accent-color: var(--app-primary);
}

.order-summary {
  padding: 12px 0;
  border-top: 1px solid rgba(var(--app-content-overlay-rgb),0.06);
  border-bottom: 1px solid rgba(var(--app-content-overlay-rgb),0.06);
  margin-bottom: 16px;
}

.order-summary-row {
  display: flex;
  justify-content: space-between;
  font-size: 12px;
  color: var(--app-text-muted-2);
  padding: 4px 0;
}

.order-summary-row.total {
  color: var(--app-text-1);
  font-weight: 600;
  font-size: 13px;
  padding-top: 8px;
}

.order-submit-btn {
  width: 100%;
  padding: 14px;
  border: none;
  border-radius: 8px;
  font-size: 15px;
  font-weight: 700;
  cursor: pointer;
  transition: all 0.2s;
  letter-spacing: 0.3px;
  margin-bottom: 12px;
}

.order-submit-btn.buy, .order-submit-btn.long {
  background: linear-gradient(135deg, var(--app-buy), #4aa8d6);
  color: var(--app-text-white);
}

@media (hover: hover) and (pointer: fine) {
.order-submit-btn.buy:hover:not(:disabled), .order-submit-btn.long:hover:not(:disabled) {
  background: linear-gradient(135deg, #6ec4f0, var(--app-buy));
  box-shadow: 0 4px 20px rgba(92, 184, 230, 0.3);
}
}

.order-submit-btn.sell, .order-submit-btn.short {
  background: linear-gradient(135deg, var(--app-sell), #d08e40);
  color: var(--app-text-white);
}

@media (hover: hover) and (pointer: fine) {
.order-submit-btn.sell:hover:not(:disabled), .order-submit-btn.short:hover:not(:disabled) {
  background: linear-gradient(135deg, #eaaf60, var(--app-sell));
  box-shadow: 0 4px 20px rgba(224, 160, 80, 0.3);
}
}

/* Bug #278: make the disabled state unmistakable when the JS gates submission
   (e.g. "Exceeds Usable Margin", "Enter Amount", "Insufficient balance for
   margin + fee"). Inline opacity is set by trading-*.js — kept JS-controlled
   per existing convention. */
.order-submit-btn:disabled {
  cursor: not-allowed;
  /* #493: a disabled button that keeps its full-colour gradient reads as broken,
     not as refused — Minamide clicked one and asked whether the page had failed.
     Spot and Withdraw have greyed theirs out for a long time; this brings the
     shared control into line, which also fixes the v1 Futures and Options panels
     that had the same silent state. */
  opacity: 0.45;
  filter: saturate(0.4);
  box-shadow: none;
}

/* The shortfall case additionally drops the side colour entirely: the label
   becomes "Insufficient Balance", and a blue "buy" gradient behind that sentence
   is a mixed message. */
.order-submit-btn.is-insufficient:disabled {
  background: var(--app-surface-3, #2a2a35);
  color: var(--app-text-muted-2, #8a8a9a);
}

.order-balance-info {
  display: flex;
  justify-content: space-between;
  font-size: 11px;
  color: #5a5a6a;
}

/* ========== INFO GRID (OB + TRADES + POSITION) ========== */
.trade-info-grid {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 16px;
  margin-bottom: 16px;
}

/* ========== ORDER BOOK ========== */
.ob-spread {
  font-size: 11px;
  color: #5a5a6a;
}

/* #527 (ULT-MARGIN-24), 2026-08-31: the order-book column headers — the unit
   suffixes a customer reads a price against ("USDT", "(BTC)") — sat at 10px at
   EVERY width, with no mobile override at all, so they were three of the seven
   nodes still under the 11px floor on a phone. Raised at the base rule rather
   than patched in a media block: a floor that is only restated at one
   breakpoint is exactly how this bug survived two rounds of "fixed". */
.ob-header-row {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  font-size: 11px;
  font-weight: 600;
  color: #4a4a5a;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  padding-bottom: 8px;
  border-bottom: 1px solid rgba(var(--app-content-overlay-rgb),0.04);
  margin-bottom: 4px;
}
.ob-header-row span:nth-child(1) { text-align: left; }
.ob-header-row span:nth-child(2) { text-align: right; }
.ob-header-row span:nth-child(3) { text-align: right; }

.ob-row {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  align-items: center;
  padding: 5px 0;
  position: relative;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}

.ob-price {
  text-align: left;
  font-weight: 500;
}

.ob-row.ask .ob-price { color: var(--app-sell); }
.ob-row.bid .ob-price { color: var(--app-primary); }

/* #536: rows are click-to-fill while a limit-capable order type is selected.
   The class is applied per-paint by js/futures-v2-orderbook.js — pages whose
   ladders are not clickable never emit it. */
.ob-row.ob-fillable { cursor: pointer; }

.ob-size {
  text-align: right;
  color: var(--app-text-muted-3);
}

.ob-total {
  text-align: right;
  color: var(--app-text-muted-2);
  position: relative;
  z-index: 1;
}

.ob-bar {
  position: absolute;
  right: 0;
  top: 0;
  bottom: 0;
  pointer-events: none;
  border-radius: 2px;
  z-index: 0;
}

.ob-bar.ask {
  background: rgba(224, 160, 80, 0.06);
}

.ob-bar.bid {
  background: rgba(92, 184, 230, 0.06);
}

.ob-spread-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 0;
  margin: 4px 0;
  border-top: 1px solid rgba(var(--app-content-overlay-rgb),0.06);
  border-bottom: 1px solid rgba(var(--app-content-overlay-rgb),0.06);
}

.ob-mid-price {
  font-size: 16px;
  font-weight: 700;
  color: var(--app-text-1);
}

.ob-spread-val {
  font-size: 11px;
  color: #5a5a6a;
}

/* ========== RECENT TRADES ========== */
.rt-header-row {
  display: flex;
  justify-content: space-between;
  font-size: 10px;
  font-weight: 600;
  color: #4a4a5a;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  padding-bottom: 8px;
  border-bottom: 1px solid rgba(var(--app-content-overlay-rgb),0.04);
  margin-bottom: 4px;
}

.rt-list {
  max-height: 280px;
  overflow-y: auto;
}

.rt-list::-webkit-scrollbar {
  width: 3px;
}

.rt-list::-webkit-scrollbar-thumb {
  background: rgba(92, 184, 230, 0.3);
  border-radius: 2px;
}
.rt-list::-webkit-scrollbar-thumb:hover {
  background: rgba(92, 184, 230, 0.5);
}

.rt-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 5px 0;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}

.rt-price {
  width: 80px;
  font-weight: 500;
}

.rt-row.buy .rt-price { color: var(--app-primary); }
.rt-row.sell .rt-price { color: var(--app-sell); }

.rt-size {
  width: 50px;
  text-align: center;
  color: var(--app-text-muted-3);
}

.rt-time {
  width: 70px;
  text-align: right;
  color: #5a5a6a;
  font-size: 11px;
}

/* ========== YOUR POSITION ========== */
.trade-your-position .trade-card-header {
  margin-bottom: 16px;
}

.pos-detail-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
  margin-bottom: 16px;
}

.pos-detail-item {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.pos-detail-label {
  font-size: 11px;
  font-weight: 500;
  color: #5a5a6a;
  text-transform: uppercase;
  letter-spacing: 0.3px;
}

.pos-detail-value {
  font-size: 14px;
  font-weight: 600;
  color: var(--app-text-1);
  font-variant-numeric: tabular-nums;
}

.pos-detail-value.positive { color: var(--app-primary); }
.pos-detail-value.negative { color: var(--app-sell); }

.pos-action-row {
  display: flex;
  gap: 8px;
  padding-top: 14px;
  border-top: 1px solid rgba(var(--app-content-overlay-rgb),0.06);
}

.pos-action-btn {
  flex: 1;
  padding: 9px 0;
  border: none;
  border-radius: 6px;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.15s;
}

.pos-action-btn.close {
  background: rgba(224, 160, 80, 0.1);
  color: var(--app-sell);
}

@media (hover: hover) and (pointer: fine) {
.pos-action-btn.close:hover {
  background: rgba(224, 160, 80, 0.18);
}
}

.pos-action-btn.modify {
  background: rgba(var(--app-content-overlay-rgb),0.04);
  color: var(--app-text-muted-2);
}

@media (hover: hover) and (pointer: fine) {
.pos-action-btn.modify:hover {
  background: rgba(var(--app-content-overlay-rgb),0.08);
  color: var(--app-text-1);
}
}

/* ========== OPTION CHAIN ========== */
.trade-option-chain {
  overflow: hidden;
}

.chain-expiry-tabs {
  display: flex;
  gap: 4px;
}

.chain-exp-btn {
  background: none;
  border: none;
  color: var(--app-text-muted-2);
  font-size: 12px;
  font-weight: 600;
  padding: 6px 14px;
  border-radius: 6px;
  cursor: pointer;
  transition: all 0.15s;
}

@media (hover: hover) and (pointer: fine) {
.chain-exp-btn:hover {
  color: var(--app-text-1);
  background: rgba(var(--app-content-overlay-rgb),0.04);
}
}

.chain-exp-btn.active {
  color: var(--app-primary);
  background: rgba(92, 184, 230, 0.1);
}

.chain-scroll {
  overflow-x: auto;
}

.chain-table {
  min-width: 900px;
}

.chain-header {
  display: flex;
  align-items: center;
  padding: 0 0 10px;
  border-bottom: 1px solid rgba(var(--app-content-overlay-rgb),0.08);
  margin-bottom: 2px;
}

.chain-calls-header,
.chain-puts-header {
  flex: 1;
  display: flex;
  justify-content: space-between;
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  padding: 0 12px;
}

.chain-calls-header {
  color: var(--app-primary);
}

.chain-puts-header {
  color: var(--app-sell);
}

.chain-strike-header {
  width: 90px;
  text-align: center;
  font-size: 10px;
  font-weight: 700;
  color: var(--app-text-muted-2);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  flex-shrink: 0;
}

.chain-row {
  display: flex;
  align-items: center;
  transition: background 0.1s;
}

@media (hover: hover) and (pointer: fine) {
.chain-row:hover {
  background: rgba(var(--app-content-overlay-rgb),0.02);
}
}

.chain-calls,
.chain-puts {
  flex: 1;
  display: flex;
  justify-content: space-between;
  padding: 9px 12px;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  color: var(--app-text-muted-2);
}

.chain-calls span,
.chain-puts span {
  width: 18%;
  text-align: right;
}

.chain-strike {
  width: 90px;
  text-align: center;
  font-size: 13px;
  font-weight: 700;
  color: var(--app-text-1);
  flex-shrink: 0;
  position: relative;
  padding: 9px 0;
}

/* ITM call rows */
.chain-row.itm-call .chain-calls {
  background: rgba(92, 184, 230, 0.03);
}

/* ATM row */
.chain-row.atm {
  border-top: 1px solid rgba(92, 184, 230, 0.15);
  border-bottom: 1px solid rgba(92, 184, 230, 0.15);
}

.chain-row.atm .chain-strike {
  color: var(--app-primary);
}

.atm-label {
  display: block;
  font-size: 9px;
  font-weight: 600;
  color: var(--app-primary);
  letter-spacing: 0.5px;
}

/* Current strike (your position) */
.chain-row.current-strike {
  background: rgba(92, 184, 230, 0.04);
  border-left: 3px solid var(--app-primary);
}

.chain-row.current-strike .chain-strike {
  color: var(--app-primary);
}

.current-label {
  display: block;
  font-size: 9px;
  font-weight: 700;
  color: var(--app-primary);
  letter-spacing: 0.5px;
}

.chain-last-highlight {
  color: var(--app-text-1) !important;
  font-weight: 600;
}

/* Alternate row shading */
.chain-row:nth-child(even) {
  background: rgba(var(--app-content-overlay-rgb),0.01);
}

.chain-row.current-strike:nth-child(even) {
  background: rgba(92, 184, 230, 0.04);
}

/* ========== EDUCATION TOOLTIPS ========== */
.has-tip {
  position: relative;
  cursor: help;
}

.tip-icon {
  opacity: 0.35;
  vertical-align: middle;
  margin-left: 2px;
  transition: opacity 0.15s;
}

.has-tip:hover .tip-icon {
  opacity: 0.7;
}

.has-tip::after {
  content: attr(data-tip);
  position: absolute;
  bottom: calc(100% + 10px);
  left: 50%;
  transform: translateX(-50%);
  background: #2a2a32;
  color: #d0d0d8;
  font-size: 12px;
  font-weight: 400;
  line-height: 1.5;
  padding: 12px 16px;
  border-radius: 10px;
  border: 1px solid rgba(var(--app-content-overlay-rgb),0.08);
  box-shadow: 0 8px 32px rgba(0,0,0,0.5);
  width: 260px;
  pointer-events: none;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.2s, visibility 0.2s;
  z-index: 100;
  white-space: normal;
}

.has-tip::before {
  content: '';
  position: absolute;
  bottom: calc(100% + 4px);
  left: 50%;
  transform: translateX(-50%);
  border: 6px solid transparent;
  border-top-color: #2a2a32;
  pointer-events: none;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.2s, visibility 0.2s;
  z-index: 101;
}

.has-tip:hover::after,
.has-tip:hover::before {
  opacity: 1;
  visibility: visible;
}

/* ========== ORDER MODE TOGGLE ========== */
.order-mode-toggle {
  display: flex;
  gap: 4px;
  margin-bottom: 20px;
  background: rgba(var(--app-content-overlay-rgb),0.03);
  border-radius: 8px;
  padding: 3px;
}

.mode-btn {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 10px;
  border: none;
  border-radius: 6px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.15s;
  background: transparent;
  color: var(--app-text-muted-2);
  font-family: inherit;
}

@media (hover: hover) and (pointer: fine) {
.mode-btn:hover {
  color: var(--app-text-muted-3);
}
}

.mode-btn.active {
  background: rgba(92, 184, 230, 0.12);
  color: var(--app-primary);
}

.mode-btn svg {
  flex-shrink: 0;
}

/* ========== AI GUIDE MODE ========== */
.order-mode {
  /* container for guide/advanced */
}

.guide-step {
  animation: fadeIn 0.2s ease;
}

@keyframes fadeIn {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: translateY(0); }
}

.guide-greeting {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  margin-bottom: 20px;
}

.guide-greeting p {
  margin: 0;
  font-size: 14px;
  color: var(--app-text-muted-3);
  line-height: 1.5;
}

.guide-greeting strong {
  color: var(--app-text-1);
}

.guide-ai-avatar {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: linear-gradient(135deg, rgba(92,184,230,0.2), rgba(92,184,230,0.08));
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  color: var(--app-primary);
}

.guide-ai-avatar.small {
  width: 24px;
  height: 24px;
}

.guide-goals {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.guide-goal-btn {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 14px 16px;
  background: rgba(var(--app-content-overlay-rgb),0.03);
  border: 1px solid rgba(var(--app-content-overlay-rgb),0.06);
  border-radius: 10px;
  cursor: pointer;
  transition: all 0.15s;
  text-align: left;
  font-family: inherit;
  color: inherit;
}

@media (hover: hover) and (pointer: fine) {
.guide-goal-btn:hover {
  background: rgba(var(--app-content-overlay-rgb),0.06);
  border-color: rgba(92, 184, 230, 0.2);
  transform: translateX(2px);
}
}

.goal-icon {
  font-size: 20px;
  flex-shrink: 0;
  width: 28px;
  text-align: center;
}

.goal-text {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.goal-text strong {
  font-size: 13px;
  font-weight: 600;
  color: var(--app-text-1);
}

.goal-text small {
  font-size: 11px;
  color: var(--app-text-muted-2);
}

.guide-goal-btn svg {
  color: #4a4a5a;
  flex-shrink: 0;
  transition: color 0.15s, transform 0.15s;
}

@media (hover: hover) and (pointer: fine) {
.guide-goal-btn:hover svg {
  color: var(--app-primary);
  transform: translateX(2px);
}
}

/* Guide Step 2: Recommendation */
.guide-back {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--app-text-muted-2);
  cursor: pointer;
  margin-bottom: 16px;
  transition: color 0.15s;
}

@media (hover: hover) and (pointer: fine) {
.guide-back:hover {
  color: var(--app-primary);
}
}

.guide-rec {
  background: rgba(92, 184, 230, 0.06);
  border: 1px solid rgba(92, 184, 230, 0.12);
  border-radius: 12px;
  padding: 16px;
  margin-bottom: 16px;
}

.guide-rec-header {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 10px;
}

.guide-rec-title {
  font-size: 12px;
  font-weight: 700;
  color: var(--app-primary);
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.guide-rec-body {
  font-size: 13px;
  color: var(--app-text-muted-3);
  line-height: 1.5;
}

.guide-rec-body strong {
  color: var(--app-text-1);
}

.guide-rec-details {
  margin-bottom: 16px;
}

.rec-action {
  font-size: 16px;
  font-weight: 700;
  color: var(--app-text-1);
  margin-bottom: 4px;
}

.rec-instrument {
  font-size: 12px;
  color: var(--app-text-muted-2);
  font-family: 'Inter', monospace;
  letter-spacing: 0.3px;
  margin-bottom: 14px;
}

.rec-details-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}

.rec-detail {
  background: rgba(var(--app-content-overlay-rgb),0.03);
  border: 1px solid rgba(var(--app-content-overlay-rgb),0.06);
  border-radius: 8px;
  padding: 10px 12px;
}

.rec-detail.full {
  grid-column: 1 / -1;
}

.rec-detail span {
  display: block;
  font-size: 10px;
  font-weight: 600;
  color: #5a5a6a;
  text-transform: uppercase;
  letter-spacing: 0.3px;
  margin-bottom: 4px;
}

.rec-detail strong {
  font-size: 13px;
  font-weight: 600;
  color: var(--app-text-1);
}

.guide-place-btn {
  margin-top: 4px;
}

/* ========== OPTIONS WIZARD CTA ========== */
.options-wizard-cta {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  background: linear-gradient(135deg, rgba(92,184,230,0.08), rgba(224,160,80,0.08));
  border: 1px solid rgba(92,184,230,0.2);
  border-radius: 8px;
  margin-bottom: 12px;
  cursor: default;
}
.wizard-cta-icon { font-size: 20px; }
.wizard-cta-text { flex: 1; }
.wizard-cta-text strong { display: block; font-size: 12px; color: var(--app-text-1); }
.wizard-cta-text span { font-size: 11px; color: var(--app-text-muted-2); }
.wizard-cta-btn {
  padding: 6px 14px;
  background: linear-gradient(135deg, var(--app-primary), #4aa0d0);
  color: var(--app-text-white);
  border: none;
  border-radius: 6px;
  font-size: 11px;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  transition: all 0.15s;
}
@media (hover: hover) and (pointer: fine) {
.wizard-cta-btn:hover { transform: scale(1.05); box-shadow: 0 2px 8px rgba(92,184,230,0.3); }
}

/* ========== AI CHAT WIDGET ========== */
.ai-chat-fab {
  position: fixed;
  /* #522: + safe-area inset. env() is 0px everywhere except devices with a
     home indicator / notch on a page served with viewport-fit=cover, so this
     computes to the same 24px it always was on every other page/device.
     TWO-LINE DECLARATIONS ON PURPOSE: a browser without env() SYNTAX drops
     the whole calc() declaration (the env() second argument only covers an
     unknown variable name, not unsupported syntax) — the plain 24px line
     before it is what such a browser keeps. Order matters: fallback first. */
  bottom: 24px;
  bottom: calc(24px + env(safe-area-inset-bottom, 0px));
  right: 24px;
  right: calc(24px + env(safe-area-inset-right, 0px));
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--app-primary), var(--app-primary-grad-end));
  color: var(--app-text-white);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: 0 4px 20px rgba(92, 184, 230, 0.35);
  transition: all 0.2s;
  z-index: 1000;
}

@media (hover: hover) and (pointer: fine) {
.ai-chat-fab:hover {
  transform: scale(1.08);
  box-shadow: 0 6px 28px rgba(92, 184, 230, 0.5);
}
}

/* `.hidden` is toggled when the panel opens. `.yields-to-submit` is set
   independently by the overlap watcher in ai-chat-widget.js (#48), so the two
   must stay SEPARATE classes: the open/close path uses classList.toggle, which
   would flip a shared class back on at the worst moment. Same visual state. */
.ai-chat-fab.hidden,
.ai-chat-fab.yields-to-submit {
  opacity: 0;
  transform: scale(0.5);
  pointer-events: none;
}

.ai-chat-panel {
  position: fixed;
  bottom: 24px;
  right: 24px;
  width: 380px;
  height: 520px;
  background: var(--app-surface-1);
  border: 1px solid rgba(var(--app-content-overlay-rgb),0.08);
  border-radius: 16px;
  display: flex;
  flex-direction: column;
  box-shadow: 0 12px 48px rgba(0,0,0,0.6);
  z-index: 1001;
  opacity: 0;
  transform: translateY(20px) scale(0.95);
  pointer-events: none;
  transition: opacity 0.25s, transform 0.25s;
  overflow: hidden;
}

.ai-chat-panel.open {
  opacity: 1;
  transform: translateY(0) scale(1);
  pointer-events: auto;
}

.chat-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 20px;
  background: linear-gradient(135deg, rgba(92,184,230,0.12), rgba(92,184,230,0.04));
  border-bottom: 1px solid rgba(var(--app-content-overlay-rgb),0.06);
}

.chat-header-left {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 14px;
  font-weight: 600;
  color: var(--app-text-1);
}

.chat-ai-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--app-primary);
  box-shadow: 0 0 6px rgba(92, 184, 230, 0.4);
}

.chat-header-right {
  display: flex;
  align-items: center;
  gap: 4px;
}

.chat-close, .chat-clear {
  background: none;
  border: none;
  color: var(--app-text-muted-2);
  cursor: pointer;
  padding: 4px;
  transition: color 0.15s;
}

@media (hover: hover) and (pointer: fine) {
.chat-close:hover, .chat-clear:hover {
  color: var(--app-text-1);
}
}

.chat-messages {
  flex: 1;
  overflow-y: auto;
  padding: 16px 20px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.chat-messages::-webkit-scrollbar {
  width: 4px;
}

.chat-messages::-webkit-scrollbar-thumb {
  background: rgba(92, 184, 230, 0.3);
  border-radius: 2px;
}
.chat-messages::-webkit-scrollbar-thumb:hover {
  background: rgba(92, 184, 230, 0.5);
}

.chat-msg {
  display: flex;
  gap: 10px;
  align-items: flex-start;
}

.chat-msg.user {
  justify-content: flex-end;
}

.chat-msg-avatar {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: linear-gradient(135deg, rgba(92,184,230,0.2), rgba(92,184,230,0.08));
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  color: var(--app-primary);
}

.chat-msg-bubble {
  max-width: 280px;
  padding: 12px 16px;
  border-radius: 14px;
  font-size: 13px;
  line-height: 1.55;
  color: #c8c8d0;
}

.chat-msg.ai .chat-msg-bubble {
  background: rgba(var(--app-content-overlay-rgb),0.04);
  border: 1px solid rgba(var(--app-content-overlay-rgb),0.06);
  border-top-left-radius: 4px;
}

.chat-msg.ai .chat-msg-bubble strong {
  color: var(--app-text-1);
}

.chat-msg.user .chat-msg-bubble {
  background: linear-gradient(135deg, rgba(92,184,230,0.15), rgba(92,184,230,0.08));
  border: 1px solid rgba(92,184,230,0.15);
  border-top-right-radius: 4px;
  color: var(--app-text-1);
}

/* Typing indicator */
.typing-dots { display: inline-flex; gap: 4px; }
.typing-dots span { display: inline-block; width: 6px; height: 6px; border-radius: 50%; background: #5a5a6a; animation: typingBounce 1.2s ease-in-out infinite; }
.typing-dots span:nth-child(2) { animation-delay: 0.2s; }
.typing-dots span:nth-child(3) { animation-delay: 0.4s; }
@keyframes typingBounce { 0%, 60%, 100% { transform: translateY(0); } 30% { transform: translateY(-4px); } }

.chat-insight {
  display: block;
  margin-top: 10px;
  padding: 10px 12px;
  background: rgba(92, 184, 230, 0.08);
  border: 1px solid rgba(92, 184, 230, 0.12);
  border-radius: 8px;
  font-size: 12px;
  color: var(--app-primary);
  line-height: 1.4;
}

.chat-input-area {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 14px 16px;
  border-top: 1px solid rgba(var(--app-content-overlay-rgb),0.06);
  background: rgba(var(--app-content-overlay-rgb),0.02);
}

.chat-input {
  flex: 1;
  background: rgba(var(--app-content-overlay-rgb),0.04);
  border: 1px solid rgba(var(--app-content-overlay-rgb),0.08);
  border-radius: 20px;
  padding: 10px 16px;
  color: var(--app-text-1);
  font-size: 13px;
  font-family: inherit;
  outline: none;
  transition: border-color 0.15s;
}

.chat-input::placeholder {
  color: #4a4a5a;
}

.chat-input:focus {
  border-color: rgba(92, 184, 230, 0.3);
}

.chat-send {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--app-primary), var(--app-primary-grad-end));
  border: none;
  color: var(--app-text-white);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: all 0.15s;
  flex-shrink: 0;
  /* #328: remove legacy iOS 300ms tap delay + give visible tap feedback. */
  touch-action: manipulation;
  -webkit-tap-highlight-color: rgba(92,184,230,0.3);
}

@media (hover: hover) and (pointer: fine) {
.chat-send:hover {
  transform: scale(1.06);
  box-shadow: 0 2px 12px rgba(92, 184, 230, 0.3);
}
}

/* Ultimo: the floating AI-chat panel is a DARK ISLAND — it must stay dark on
   Ultimo's light shell to match the always-dark ai-chat-widget.js used on
   Buy&Sell + other pages (Ultimo flips the :root neutrals to light via
   brand-boot.js, which otherwise turns this panel white). Re-map the neutral
   tokens back to their Vestex dark values WITHIN the panel scope; every child
   uses var(--app-*) so they all flip to dark automatically. Brand accents
   (--app-primary/buy/sell) are left inherited (Ultimo gold), same as the
   Buy&Sell dark widget. Scoped to html[data-brand="ultimo"] → Vestex zero-diff.
   Covers spot/futures/equity (all load this file). Matches the existing
   dark-island pattern (.spot-symbol-dropdown / .spot-confirm-modal, audit 2026-06-25). */
html[data-brand="ultimo"] .ai-chat-panel {
  --app-surface-1: #1a1a1f;
  --app-surface-2: #111827;
  --app-surface-card: #1a1a2e;
  --app-text-strong: #e2e8f0;
  --app-text-1: #e0e0e8;
  --app-text-muted: #8a94a6;
  --app-text-muted-2: #8a8a9a;
  --app-text-muted-3: #a8a8b8;
  --app-border: rgba(255, 255, 255, 0.06);
  --app-content-overlay-rgb: 255, 255, 255;
}

/* ========== CHART TIMEFRAMES ========== */
.chart-timeframes {
  display: flex;
  gap: 2px;
  min-width: 0;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.tf-btn {
  background: none;
  border: none;
  color: var(--app-text-muted-2);
  font-size: 11px;
  white-space: nowrap;
  flex: 0 0 auto;
  font-weight: 600;
  padding: 5px 10px;
  border-radius: 4px;
  cursor: pointer;
  transition: all 0.15s;
  letter-spacing: 0.3px;
  font-family: inherit;
}

@media (hover: hover) and (pointer: fine) {
.tf-btn:hover {
  color: var(--app-text-1);
  background: rgba(var(--app-content-overlay-rgb),0.04);
}
}

.tf-btn.active {
  color: var(--app-primary);
  background: rgba(92, 184, 230, 0.1);
}

/* ========== RESPONSIVE ========== */
/* #543: THE INSTRUMENT-BAR COLUMN FLIP LIVES HERE, AND ONLY HERE.
   Four blocks used to declare it (this file's 1200 / 1024 / 860px blocks +
   trade-futures.css's 1023px block); the 860px and 1023px copies were exact
   duplicates of the 1024px block and were removed (zero computed change at
   every width). Two blocks remain because their values genuinely differ:
   1200px is the roomier tablet spacing (gap 16 / 8), 1024px tightens it
   (gap 10 / 6). The !important on the 1024px block is load-bearing — without
   it the higher-specificity `.futures2-page .instrument-bar` row-gap/
   column-gap (trade-futures.css) would win and widen the stacked gaps. */
@media (max-width: 1200px) {
  .instrument-bar {
    flex-direction: column;
    align-items: flex-start;
    gap: 16px;
  }
  .inst-bar-metrics {
    flex-wrap: wrap;
    gap: 8px;
  }
  .inst-metric-divider {
    display: none;
  }
  .inst-metric {
    padding: 0 16px 0 0;
  }
}

@media (max-width: 1024px) {
  .instrument-bar { padding: 16px 20px 14px; }
  .greeks-bar { padding: 0 20px; flex-wrap: wrap; height: auto; padding: 8px 20px; gap: 4px; }
  .greek-item { padding: 6px 12px; }
  .trade-main { padding: 16px 20px 60px; }
  .trade-order-panel { max-width: none; }
  .pos-table { font-size: 11px; }
  .pos-table thead th, .pos-table tbody td { padding: 8px 6px; }
  .instrument-bar { flex-direction: column !important; align-items: flex-start !important; gap: 10px !important; }
  .inst-bar-metrics { flex-wrap: wrap !important; gap: 6px !important; }
  .inst-metric-divider { display: none !important; }
}

@media (max-width: 768px) {
  .instrument-bar { padding: 12px 16px !important; }
  .inst-bar-symbol { font-size: 16px !important; }
  .trade-main { padding: 12px 16px 60px !important; }
  .greeks-bar { padding: 8px 16px; }
  .trade-order-panel { padding: 16px !important; }
  .pos-table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .pos-table { min-width: 600px; }
  .pos-table thead th, .pos-table tbody td { padding: 8px 8px; font-size: 11px; }
  .chain-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  /* #328: two-line declaration so non-svh browsers fall back to vh (no regression on
     older iOS / older Android). svh excludes the on-screen keyboard area so the Send
     button stays tappable on iPhone Safari. */
  .ai-chat-panel { width: calc(100vw - 32px) !important; right: 16px !important; bottom: 70px !important; max-height: 60vh !important; max-height: min(60vh, 60svh) !important; }
}

@media (max-width: 480px) {
  .trade-main { padding: 8px 8px 60px !important; }
  .inst-bar-symbol { font-size: 14px !important; }
  /* #527: 9px is below any readable floor on a phone — 11px, font-size only
     (the metric row's layout is owned elsewhere). */
  .metric-label { font-size: 11px !important; }
  .metric-value { font-size: 12px !important; }
  .greeks-bar { padding: 6px 8px; gap: 2px; }
  .greek-item { padding: 4px 8px; font-size: 10px; }
  .greek-label { font-size: 9px; }
  .greek-value { font-size: 10px; }
  .price-row-with-bbo { flex-direction: column; gap: 6px; }
  .bbo-btn { width: 100%; padding: 8px 0; text-align: center; }
  /* #328: see comment at @1023 — svh keeps Send button above iOS keyboard. */
  .ai-chat-panel { width: calc(100vw - 16px) !important; right: 8px !important; left: 8px !important; bottom: 60px !important; max-height: 70vh !important; max-height: min(70vh, 70svh) !important; }
}

/* ===== Bug #193 — Order Panel narrow-viewport overflow fix (v2) =====
   Prior art: PR #262 (commit 54b7186) added a partial fix scoped to
   body.trade-page-3up that shrank some internal flex children at <=768px.
   Re-verification (2026-05-19) found the panel still overflowed — that fix
   never addressed the upstream root cause.

   Root cause: .app-body is `display:flex`; .app-sidebar is `position:fixed`
   (out of flow); .app-content-wrapper is the sole in-flow flex item, with
   `flex:1` and the default `min-width:auto`. `min-width:auto` pins a flex
   item to its content's min-content width, so on a ~544px viewport the
   Order Panel's non-wrapping flex rows (order-type tabs, quick-amount
   buttons, leverage marks, label/value summary rows) forced the wrapper —
   and therefore the `width:100%` panel inside it — wider than the viewport.
   Every right-side UI element was pushed off-screen at the same edge.

   Fix: (1) let the content flex-item shrink to the viewport with
   `min-width:0`; (2) let every internal flex row shrink/wrap so no
   descendant re-introduces an over-wide min-content.
   Scope: body.trade-page-3up only — /trade-futures + /trade-spot.
   trade-option.html (no trade-page-3up body class) is intentionally
   unaffected. Verified at 360 / 480 / 544 / 640 / 768 / 1024px. */

/* (1) Root cause — let the content flex-item shrink to the viewport.
   No-op at desktop widths (content fits the viewport there). */
body.trade-page-3up .app-content-wrapper { min-width: 0; }

/* (2) Stacked layout (<=1023px) — allow the panel + its flex rows to shrink. */
@media (max-width: 1023px) {
  body.trade-page-3up .trade-order-panel,
  body.trade-page-3up .spot-order-panel { min-width: 0; }
}

@media (max-width: 768px) {
  body.trade-page-3up .order-side-toggle { gap: 2px; }
  /* #525: Long/Short measured ~27-33px tall on phones — under both the Apple
     HIG 44pt and Material 48dp floors, on the one control where a mis-tap
     places the WRONG-SIDE order. min-height grows the hit area at touch
     widths only; desktop keeps its compact size. */
  body.trade-page-3up .order-side-btn { min-width: 0; min-height: 44px; padding: 8px 4px; font-size: 12px; }

  /* Order Type row + tabs (Limit / Market / Stop Market / Stop Limit) */
  body.trade-page-3up .order-type-row { flex-wrap: wrap; gap: 6px; }
  body.trade-page-3up .order-type-tabs { flex-wrap: wrap; }
  /* #24: these buttons say WHICH KIND of order is being sent (Limit / Market /
     Stop Market / Stop Limit) — 11px floor, matching the #527 metric and tick
     labels. #22: and they measured ~19px tall at 480px, on the same control —
     min-height carries the 44px floor down through the 480px block below, the
     same pattern .order-side-btn already uses. The row wraps (.order-type-tabs
     flex-wrap above), so the cost is an extra line, never a clipped label. */
  body.trade-page-3up .order-type-btn { min-width: 0; min-height: 44px; padding: 5px 8px; font-size: 11px; }

  body.trade-page-3up .input-mode-toggle { gap: 2px; }
  body.trade-page-3up .input-mode-btn { min-width: 0; padding: 6px 2px; font-size: 11px; }

  body.trade-page-3up .leverage-marks { padding: 0; }
  /* #527: leverage tick labels rendered at 9px — 11px floor, font-size only. */
  body.trade-page-3up .leverage-marks > span { min-width: 0; font-size: 11px; white-space: nowrap; }

  /* Price / amount inputs shrink instead of overflowing the panel */
  body.trade-page-3up .order-input { min-width: 0; }

  /* Quick-amount buttons (100..10,000) wrap to 3 per row */
  /* MCP Phase 3 (Codex Medium + Gemini Low): use calc((100% - 8px) / 3)
     instead of 33.333% — derives basis from parent gap directly (4px gap × 2
     gaps in 3-col row = 8px), avoids fractional rounding that sometimes drops
     buttons to 2-col, and makes the gap relation obvious for maintenance. */
  body.trade-page-3up .order-quick-btns { flex-wrap: wrap; gap: 4px; }
  /* #24: 11px floor here too — the chips set the ORDER SIZE. Already wrapping
     (flex-wrap above), so the extra glyph width costs a row at worst. */
  body.trade-page-3up .quick-btn { flex: 1 1 calc((100% - 8px) / 3); min-width: 0; padding: 5px 2px; font-size: 11px; }

  body.trade-page-3up .margin-calc-result { flex-wrap: wrap; }
  body.trade-page-3up .tpsl-toggle { min-width: 0; padding: 6px 4px; font-size: 11px; }
  body.trade-page-3up .more-options-summary { font-size: 11px; }

  /* Label/value rows — keep label intact; value span may shrink (no clipping:
     a long value degrades by wrapping, never by being hidden). */
  body.trade-page-3up .order-summary-row,
  body.trade-page-3up .order-balance-info,
  body.trade-page-3up .order-balance-info-secondary { gap: 8px; }
  body.trade-page-3up .order-summary-row > span:last-child,
  body.trade-page-3up .order-balance-info > span:last-child,
  body.trade-page-3up .order-balance-info-secondary > span:last-child { min-width: 0; text-align: right; }
}

@media (max-width: 480px) {
  /* #525: keep the 44px floor at the smallest widths too. */
  body.trade-page-3up .order-side-btn { min-height: 44px; padding: 7px 2px; font-size: 11px; }
  /* #527 (ULT-MARGIN-24), 2026-08-31: was 10px. The 11px floor was added at
     the 768px breakpoint (~:1994) but this 480px rule still won on every real
     phone, so the fix read as done between 480 and 768 and was still broken at
     406px and below. The floor has to be restated at the NARROWEST breakpoint
     that sets the property, not only at the widest. */
  body.trade-page-3up .input-mode-btn { padding: 5px 2px; font-size: 11px; }
  /* #24: 9px on the order-KIND buttons and the size chips — the two rows that
     decide what order leaves the page — was the smallest type on the screen,
     below the 11px floor #527 already set for the metric and tick labels.
     #22: the 44px floor is repeated here alongside it so the pair stays
     together if this block is ever edited on its own (it is also inherited
     from the 768px rule above; declaring it twice mirrors .order-side-btn). */
  body.trade-page-3up .order-type-btn { min-height: 44px; padding: 4px 6px; font-size: 11px; }
  body.trade-page-3up .quick-btn { font-size: 11px; padding: 4px 1px; }
}

/* ===== #53: keyboard focus must be VISIBLE on the money controls ===========
   .leverage-slider carried `outline: none` (trade-futures.css ~74) with no
   replacement anywhere, and neither trading stylesheet had a focus rule for
   the order-type tabs, the quick-amount chips, the submit button or the
   position tabs. On that slider the ARROW KEYS CHANGE LEVERAGE — so a keyboard
   user could move the leverage of a live order with no idea where focus was.
   One shared ring for all five, declared once.

   :focus-visible, NOT :focus — the ring appears for keyboard and AT focus and
   stays invisible to a mouse user, so nothing about the pointer experience
   changes. (`:focus-visible` on a range input also fires on click in some
   engines, which is correct: the control is then keyboard-operable.)

   COLOUR: var(--app-text-1), the token each brand already guarantees is
   legible ON its own surface — it is the body text colour. That is what makes
   the 2px ring clear 3:1 against the card on BOTH brands without inventing a
   third accent (Vestex near-white on #1a1a1f; Ultimo near-black on white),
   and it stays correct if a brand re-tints its surfaces.

   Specificity (0,2,0) beats the base `.leverage-slider { outline: none }`
   (0,1,0) regardless of which stylesheet loads last, so the ring wins without
   an !important.

   OFFSET: outward for the panel controls; INSET on .pos-tab, whose row is an
   `overflow-x: auto` scroller (trade-futures.css ~2216) that would clip an
   outward ring on the first and last tab — exactly the two most likely to be
   focused first.

   #53 (second half): .order-input — Amount, Limit Price, Trigger Price — was
   the other target named in the report and was missed the first time. It
   carries its own `outline: none` (line ~612) and the only replacement was
   `.order-input-wrap:focus-within { border-color: rgba(92,184,230,0.3) }`
   (line ~581), a 1px 30%-alpha cyan that composites to ~1.2:1 against the
   field on Ultimo — below the 3:1 floor of WCAG 2.1 SC 1.4.11.

   WHY :focus-visible ON THE INPUT, not a stronger :focus-within on the wrap:
   `:focus-within` has no modality awareness at all, so raising it to a 3:1
   indicator would hand every mouse user a hard ring on click. `:focus-visible`
   is the modality-aware selector, and it is the token/rule already shared by
   the other five controls — one focus style for the panel, not two.
   Specificity (0,2,0) beats the base `.order-input { outline: none }` (0,1,0),
   same as the slider, so no !important. The 1px focus-within tint stays as the
   soft "this field is active" affordance it always was; it is simply no longer
   carrying the accessibility job on its own.

   INSET here too, for the same reason as .pos-tab: .order-input-wrap sets
   `overflow: hidden` (line ~577) to clip the −/+ stepper corners, and an
   ancestor's overflow clips a descendant's outline — an outward ring on the
   input would be cut off on both sides. Inset, it is drawn inside the field's
   own box, which is also the more honest indicator: the text field has focus,
   not the whole wrapper including the steppers.

   CONTRAST of the inset ring: var(--app-text-1) against the field surface
   rgba(--app-content-overlay-rgb, 0.04) over --app-surface-1 — Vestex #e0e0e8
   on ~#232328 (~12.6:1), Ultimo #1a1a1a on ~#f5f5f5 (~15.9:1). Both clear 3:1
   with an order of magnitude to spare, and it is the same token the input's
   own text already uses, so it cannot drift out of contrast when a brand
   re-tints. (--app-primary was rejected for this ring: gold on Ultimo white is
   ~1.75:1.) */
.leverage-slider:focus-visible,
.order-type-btn:focus-visible,
.quick-btn:focus-visible,
.order-submit-btn:focus-visible,
.order-input:focus-visible,
.pos-tab:focus-visible {
  outline: 2px solid var(--app-text-1);
  outline-offset: 2px;
}
.pos-tab:focus-visible { outline-offset: -2px; }
.order-input:focus-visible { outline-offset: -2px; }

/* Ultimo orderbook: SELL = red, BUY = cyan (Quy 2026-06-25). Default bid price
   uses --app-primary → gold on Ultimo (indistinguishable from the amber ask).
   Switch sell→red + buy→cyan (--app-buy, kept both brands); align the ask depth
   bar to a red tint (bid bar is already cyan). Scoped → vestex zero-diff. */
html[data-brand="ultimo"] .ob-row.ask .ob-price { color: #ef4444; }
html[data-brand="ultimo"] .ob-row.bid .ob-price { color: var(--app-buy); }
html[data-brand="ultimo"] .ob-bar.ask { background: rgba(239, 68, 68, 0.07); }

/* ===== #520: Positions / Open Orders / Order History tables on a phone =====
   The tables scroll horizontally on purpose (.pos-table min-width 600/700px
   inside .pos-table-wrap { overflow-x: auto }), but two things drowned in
   that scroll:

   1. THE EMPTY STATE. "No open positions" is one <td colspan="11"> spanning
      the full ~742px table, with inline text-align:center — so the message
      rendered at x≈371px while the viewport showed 332-354px. The user saw a
      blank panel, or just "No" hanging at the right edge. The cell now
      becomes a block pinned to the scrollport's left edge (position: sticky),
      sized to the WRAPPER's width (100cqw via container-type on the wrapper)
      so "centered" means centered in what the user actually sees. The
      width: fit-content line before it is the fallback for engines without
      container-query units: left-pinned rather than centered, but VISIBLE.
      `text-align: center !important` because the markup centers via an
      inline style, which would otherwise beat any stylesheet rule.

   2. WHICH ROW IS WHICH. Scrolled right, every cell is a number with no
      symbol in sight. The first column (Symbol / Time) now sticks to the
      left edge, with the card's own surface behind it so scrolled cells
      pass under, not through. Empty rows are excluded — their cell is the
      block above.

   Mobile only (≤768px): desktop tables are wide enough and stay untouched. */
@media (max-width: 768px) {
  .pos-table-wrap { container-type: inline-size; }
  .pos-table .pos-empty-row td {
    display: block;
    position: sticky;
    left: 0;
    box-sizing: border-box;
    width: fit-content;   /* fallback: pinned left, always on screen */
    width: 100cqw;        /* container units: centered in the visible area */
    text-align: center !important;
  }
  .pos-table thead th:first-child,
  .pos-table tbody tr:not(.pos-empty-row) td:first-child {
    position: sticky;
    left: 0;
    z-index: 2;
    background: var(--app-surface-1);
  }
}
/* ^ THIS BRACE WAS MISSING. The @media (max-width: 768px) opened above for
   #520 was never closed, so the file ended at brace depth 1 and EVERYTHING
   after it — the whole #518/#524 Ultimo contrast block below — was silently
   trapped inside a phone-width media query. Those are brand contrast fixes for
   WCAG AA failures with no width component in their intent (their own comment
   scopes them by BRAND, not by viewport), so on Ultimo desktop the selected
   Long/Short/By-Amount/MAX controls still rendered the 1.83:1 / 2.02:1 states
   #518/#524 were filed against. Closing here — immediately after the last rule
   the #520 comment describes as "Mobile only (<=768px)" — restores each rule's
   stated intent: #520 stays phone-only, the brand contrast fixes go global.
   It also means anything appended to this file from now on lands at top level
   instead of inside a mobile media query. */

/* ===== Bugs #518 / #524 — Ultimo selected-state legibility ==================
   On Ultimo light the default selected states put a warm accent ON a faint
   warm tint: Long/By-Amount/MAX read gold #f5b50a on near-white (1.83:1) and
   Short reads amber #e0a050 on its own 15%-alpha tint (2.02:1) — both WCAG AA
   fails, and the two side buttons become adjacent warm hues that cannot be
   told apart at a glance (wrong-side order risk).

   Fix, WITHIN the brand tokens (owner constraint: NO green/red switch — the
   warm palette is deliberate): the selected control inverts to a SOLID token
   fill with the brand's dark on-accent foreground (--app-primary-fg = #1a1a1a
   on Ultimo → ≥7.7:1 on every fill below), plus a dark inset ring as the
   non-color differentiator, so "which one is selected" survives color-blind
   rendering as a shape/luminance cue, not a hue one. Long keeps the cyan
   --app-buy (kept on both brands, and already the bid color in the Ultimo
   order book above); Short keeps the amber --app-sell — so Long vs Short is
   cyan-fill vs amber-fill, never two warm tints.

   Scoped to html[data-brand="ultimo"] → Vestex dark is untouched (its selected
   states pass AA and its Long cyan / Short amber are already distinct).
   These out-specificity the base .active rules (trade-option.css /
   trade-futures.css) regardless of stylesheet load order. */
html[data-brand="ultimo"] .order-side-btn.long.active,
html[data-brand="ultimo"] .order-side-btn.buy.active {
  background: var(--app-buy);
  color: var(--app-primary-fg);
  box-shadow: inset 0 0 0 2px rgba(0, 0, 0, 0.45);
}
html[data-brand="ultimo"] .order-side-btn.short.active,
html[data-brand="ultimo"] .order-side-btn.sell.active {
  background: var(--app-sell);
  color: var(--app-primary-fg);
  box-shadow: inset 0 0 0 2px rgba(0, 0, 0, 0.45);
}
/* #524: By Amount / By Margin, guide-mode toggle and the quick-amount chips
   (incl. MAX) — same inversion onto the brand gold, dark label ≥9.5:1. */
html[data-brand="ultimo"] .input-mode-btn.active,
html[data-brand="ultimo"] .mode-btn.active {
  background: var(--app-primary);
  color: var(--app-primary-fg);
}
html[data-brand="ultimo"] .quick-btn.active {
  background: var(--app-primary);
  border-color: var(--app-primary-hover);
  color: var(--app-primary-fg);
}
