<script setup lang="ts">
import { ref, computed, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { useI18n } from 'vue-i18n'
import { get, post, postForm, put } from '@/utils/request'
import TransferModal from '@/components/common/TransferModal.vue'
import { useToast } from '@/composables/useToast'

const router = useRouter()
const toast = useToast()
const { t, locale } = useI18n()

/** 与 locales 前缀对应，用于日期时间展示 */
function intlLocaleForApp(loc: string): string {
  const map: Record<string, string> = {
    'zh-CN': 'zh-CN',
    'zh-TW': 'zh-TW',
    en: 'en-US',
    ko: 'ko-KR',
    ja: 'ja-JP',
    hi: 'hi-IN',
    id: 'id-ID',
  }
  if (map[loc]) {
    return map[loc]
  }
  return loc.includes('-') ? loc : `${loc}-${String(loc).toUpperCase()}`
}

// ── Types ──────────────────────────────────────────────────────────────────
interface FollowWallet {
  cumulativePnl: number
  availableBalance: number
  equity: number
}

interface FollowedTrader {
  id: string | number
  traderId: string | number
  name: string
  avatar: string | null
  avatarError: boolean
  lossless: boolean
  myAmount: number
  tradingAmount: number
  profitAmount: number
  tradingDays: number
  followCustomer: number
  status: number
  levelName: string
  description: string
  tags: string[]
}

interface CopyPosition {
  id: string
  symbol: string
  direction: number
  positionType: string
  openPrice: number
  closePrice: number
  amount: number
  lever: number
  profit: number
  profitRate: number
  openTime: number
  closeTime?: number
  traderName?: string
  /** 无损跟单（specialTrader），与 App CopyPosition.isNoLoss 一致，不可手动平仓 */
  isNoLoss: boolean
}

// ── State ──────────────────────────────────────────────────────────────────
type MainTab = 'positions' | 'traders' | 'history'
const activeTab = ref<MainTab>('positions')

const wallet         = ref<FollowWallet | null>(null)
const walletLoading  = ref(true)
const traders        = ref<FollowedTrader[]>([])
const tradersLoading = ref(false)
const positions      = ref<CopyPosition[]>([])
const posLoading     = ref(false)
const history        = ref<CopyPosition[]>([])
const histLoading    = ref(false)
/** 正在市价全平的仓位 id（与 App closePosition 一致，POST swap/order/close-all） */
const closeBusyId = ref<string | null>(null)

// Transfer modal
const showTransfer = ref(false)

/** 后端保证金模式文案 → 当前语言展示 */
function normalizeMarginMode(raw: unknown): string {
  const s = String(raw ?? '').trim()
  const lower = s.toLowerCase()
  if (!s || s === '全仓' || lower === 'cross' || s === '全倉') {
    return t('copyTrade.marginCrossMode')
  }
  if (s === '逐仓' || lower === 'isolated') {
    return t('copyTrade.marginIsolatedMode')
  }
  return s
}

// ── Helpers ────────────────────────────────────────────────────────────────
function normSym(s: string) { return s.toUpperCase().replace(/[/\-_ ]/g, '') }

// "BTCUSDT" → "BTC/USDT"
function fmtSymbol(sym: string) {
  if (sym.endsWith('USDT')) return sym.slice(0, -4) + '/USDT'
  if (sym.endsWith('BTC'))  return sym.slice(0, -3) + '/BTC'
  if (sym.endsWith('ETH'))  return sym.slice(0, -3) + '/ETH'
  return sym
}

// "BTCUSDT" → "BTC"  (base asset for quantity label)
function baseAsset(sym: string) {
  if (sym.endsWith('USDT')) return sym.slice(0, -4)
  if (sym.endsWith('BTC'))  return sym.slice(0, -3)
  if (sym.endsWith('ETH'))  return sym.slice(0, -3)
  return sym
}

function fmtQty(v: number) {
  if (v === 0) return '0'
  return parseFloat(v.toFixed(4)).toString()
}

function fmtProfit(v: number) {
  return (v >= 0 ? '+' : '') + v.toLocaleString('en-US', { minimumFractionDigits: 4, maximumFractionDigits: 4 })
}

// ── Mappers ────────────────────────────────────────────────────────────────
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function mapFollowedTrader(r: any): FollowedTrader {
  return {
    id: r.id ?? Math.random(),
    traderId: r.traderId ?? r.id,
    name: r.nickname ?? r.nickName ?? r.traderName ?? r.name ?? t('copyTrade.defaultTraderName'),
    avatar: r.avatar ?? r.headImg ?? null,
    avatarError: false,
    lossless: !!(r.specialTrader ?? r.lossless),
    myAmount: parseFloat(r.tradingAmount ?? r.followAmount ?? '0') || 0,
    tradingAmount: parseFloat(r.tradingAmount ?? '0') || 0,
    profitAmount: parseFloat(r.profitAmount ?? '0') || 0,
    tradingDays: parseInt(r.tradingDays ?? '0', 10) || 0,
    followCustomer: parseInt(r.defaultFollowCustomer ?? '0', 10) + parseInt(r.followCustomer ?? '0', 10) || 0,
    status: parseInt(r.status ?? '1', 10) || 1,
    levelName: r.levelName ?? '',
    description: r.description ?? '',
    tags: (r.tags as any[] ?? []).map((t: any) => typeof t === 'string' ? t : t?.name ?? '').filter((s: string) => s),
  }
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
function mapPosition(r: any): CopyPosition {
  const pid =
    r.positionId != null && String(r.positionId) !== ''
      ? String(r.positionId)
      : (r.id != null && String(r.id) !== '' ? String(r.id) : '')
  return {
    id: pid || `row-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`,
    symbol: normSym(r.symbol ?? r.coin ?? ''),
    direction: parseInt(r.direction ?? '0', 10),
    positionType: normalizeMarginMode(r.positionType ?? r.marginMode),
    openPrice: parseFloat(r.openPrice ?? r.openRealPrice ?? '0') || 0,
    closePrice: parseFloat(r.closePrice ?? r.currentPrice ?? r.nowPrice ?? '0') || 0,
    amount: parseFloat(r.amount ?? r.volume ?? r.totalPosition ?? '0') || 0,
    lever: parseInt(r.lever ?? r.leverage ?? '1', 10) || 1,
    profit: parseFloat(r.profit ?? r.profitAmount ?? '0') || 0,
    profitRate: parseFloat(r.profitRate ?? r.yieldRate ?? '0') || 0,
    openTime: parseInt(r.openTime ?? r.createTime ?? '0', 10) || 0,
    closeTime: r.closeTime ? parseInt(r.closeTime, 10) : undefined,
    traderName: r.traderName ?? r.nickname ?? r.traderNickname ?? '',
    isNoLoss: !!(r.specialTrader ?? r.isNoLoss),
  }
}

/** 是否可用后端 positionId 调用平仓（排除列表占位 id） */
function canClosePosition(p: CopyPosition) {
  if (p.isNoLoss) {
    return false
  }
  if (!p.id || p.id.startsWith('row-')) {
    return false
  }
  return true
}

/**
 * 跟单市价全平：与 Flutter CopyTradingRepository.closeCopyPosition 一致
 * POST swap/order/close-all，application/x-www-form-urlencoded，参数 positionId
 */
async function closeFollowPosition(p: CopyPosition) {
  if (p.isNoLoss) {
    toast.error(t('assets.noLossPosition'))
    return
  }
  if (!canClosePosition(p)) {
    toast.error(t('assets.invalidPosition'))
    return
  }
  if (!confirm(t('assets.confirmClose'))) {
    return
  }
  const positionId = String(p.id)
  closeBusyId.value = positionId
  try {
    await postForm('/swap/order/close-all', { positionId })
    toast.success(t('assets.closeSuccess'))
    await Promise.all([loadPositions(), loadWallet()])
  } catch (e: unknown) {
    toast.error(e instanceof Error ? e.message : t('assets.closeFailed'))
  } finally {
    closeBusyId.value = null
  }
}

// ── API ────────────────────────────────────────────────────────────────────
async function loadWallet() {
  walletLoading.value = true
  try {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const res: any = await get('/swap/follow-wallet/get')
    wallet.value = {
      cumulativePnl:    parseFloat(res?.totalRevenue ?? res?.totalProfit ?? res?.cumulativePnl ?? '0') || 0,
      availableBalance: parseFloat(res?.availableBalance ?? res?.available ?? '0') || 0,
      equity:           parseFloat(res?.currentCapital ?? res?.balance ?? res?.totalBalance ?? '0') || 0,
    }
  } catch { /* silent */ } finally {
    walletLoading.value = false
  }
}

async function loadTraders() {
  tradersLoading.value = true
  try {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const res: any = await post('/follow/follow/following', { currentPage: 1, pageSize: 50 })
    const list = Array.isArray(res) ? res : (res?.records ?? res?.list ?? res?.data ?? [])
    traders.value = list.map(mapFollowedTrader)
  } catch { /* silent */ } finally {
    tradersLoading.value = false
  }
}

async function loadPositions() {
  posLoading.value = true
  try {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const res: any = await post('/follow/position/current-follow', { currentPage: 1, pageSize: 50 })
    const list = Array.isArray(res) ? res : (res?.records ?? res?.list ?? res?.data ?? [])
    positions.value = list.map(mapPosition)
  } catch { /* silent */ } finally {
    posLoading.value = false
  }
}

async function loadHistory() {
  if (history.value.length) return
  histLoading.value = true
  try {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const res: any = await post('/follow/position/history-follow', { currentPage: 1, pageSize: 50 })
    const list = Array.isArray(res) ? res : (res?.records ?? res?.list ?? res?.data ?? [])
    history.value = list.map(mapPosition)
  } catch { /* silent */ } finally {
    histLoading.value = false
  }
}

async function unfollow(trader: FollowedTrader) {
  if (!confirm(t('copyTrade.confirmStopFollow', { name: trader.name }))) {
    return
  }
  try {
    await put(`/follow/follow/unfollow/${trader.traderId}`)
    traders.value = traders.value.filter((row) => row.traderId !== trader.traderId)
  } catch (e: unknown) {
    toast.error((e as Error).message || t('common.operationFailed'))
  }
}

function switchTab(tab: MainTab) {
  activeTab.value = tab
  if (tab === 'positions' && positions.value.length === 0) loadPositions()
  if (tab === 'traders'   && traders.value.length   === 0) loadTraders()
  if (tab === 'history'   && history.value.length   === 0) loadHistory()
}

const unrealizedPnl = computed(() => positions.value.reduce((sum, p) => sum + p.profit, 0))

// ── Helpers ────────────────────────────────────────────────────────────────
function initials(name: string) { return name.charAt(0).toUpperCase() }

function fmtNum(v: number, d = 2) {
  return v.toLocaleString('en-US', { minimumFractionDigits: d, maximumFractionDigits: d })
}

function fmtPnl(v: number) {
  return (v >= 0 ? '+' : '') + fmtNum(v)
}

function fmtTime(ts: number) {
  if (!ts) {
    return '—'
  }
  return new Date(ts).toLocaleString(intlLocaleForApp(locale.value), {
    month: '2-digit',
    day: '2-digit',
    hour: '2-digit',
    minute: '2-digit',
  })
}

// ── Init ───────────────────────────────────────────────────────────────────
onMounted(async () => {
  await Promise.all([loadWallet(), loadTraders(), loadPositions()])
})
</script>

<template>
  <main class="mf-main">
    <!-- ── Page header ── -->
    <div class="mf-topbar">
      <div class="page-container topbar-inner">
        <button class="back-btn" @click="router.push('/copy-trade')">
          <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M19 12H5m0 0l7 7m-7-7l7-7"/></svg>
          {{ t('copyTrade.followingPlaza') }}
        </button>
        <h1 class="page-title">{{ t('copyTrade.myFollowing') }}</h1>
      </div>
    </div>

    <div class="page-container mf-layout">
      <!-- ── Wallet Card ── -->
      <div class="wallet-card">
        <div v-if="walletLoading" class="wallet-loading">
          <div class="sk sk-line" style="width:40%;height:32px;margin-bottom:12px" />
          <div class="sk sk-line" style="width:100%;height:60px" />
        </div>
        <template v-else-if="wallet">
            <div class="wallet-header">
            <div class="wallet-label">{{ t('copyTrade.copyWalletTitle') }}</div>
            <button class="wallet-btn" @click="showTransfer = true">{{ t('assets.transfer') }}</button>
          </div>
          <div class="wallet-stats">
            <div class="wstat">
              <div class="wstat-label">{{ t('copyTrade.cumulativePnlUsdt') }}</div>
              <div class="wstat-val num" :class="wallet.cumulativePnl >= 0 ? 'pnl-up' : 'pnl-down'">
                {{ fmtNum(wallet.cumulativePnl) }}
              </div>
            </div>
            <div class="wstat">
              <div class="wstat-label">{{ t('copyTrade.availableUsdt') }}</div>
              <div class="wstat-val num">{{ fmtNum(wallet.availableBalance) }}</div>
            </div>
            <div class="wstat">
              <div class="wstat-label">{{ t('copyTrade.unrealizedPnlUsdtShort') }}</div>
              <div class="wstat-val num" :class="unrealizedPnl >= 0 ? 'pnl-up' : 'pnl-down'">
                {{ fmtNum(unrealizedPnl) }}
              </div>
            </div>
          </div>
        </template>
        <div v-else class="wallet-empty">{{ t('copyTrade.followingWalletFail') }}</div>
      </div>

      <!-- ── Tabs ── -->
      <div class="mf-tabs">
        <button class="mf-tab" :class="{ active: activeTab === 'positions' }" @click="switchTab('positions')">
          {{ t('copyTrade.followingTabPositions') }}<span v-if="positions.length > 0">({{ positions.length }})</span>
        </button>
        <button class="mf-tab" :class="{ active: activeTab === 'traders' }" @click="switchTab('traders')">
          {{ t('copyTrade.followingTabTraders') }}<span v-if="traders.length > 0">({{ traders.length }})</span>
        </button>
        <button class="mf-tab" :class="{ active: activeTab === 'history' }" @click="switchTab('history')">{{ t('copyTrade.followingTabHistory') }}</button>
      </div>

      <!-- ── Current Positions ── -->
      <template v-if="activeTab === 'positions'">
        <div v-if="posLoading" class="sk-rows">
          <div v-for="i in 4" :key="i" class="sk sk-row" />
        </div>
        <div v-else-if="positions.length === 0" class="empty-state">
          <div class="empty-icon">📭</div>
          <div class="empty-text">{{ t('assets.noFollowPositions') }}</div>
        </div>
        <div v-else class="pos-table-wrap">
          <table class="pos-table">
            <thead>
              <tr>
                <th>{{ t('copyTrade.followingThContract') }}</th>
                <th>{{ t('copyTrade.followingThDirection') }}</th>
                <th>{{ t('copyTrade.followingThOpenPrice') }}</th>
                <th>{{ t('copyTrade.followingThCurPrice') }}</th>
                <th>{{ t('copyTrade.followingThQty') }}</th>
                <th>{{ t('copyTrade.followingThLever') }}</th>
                <th>{{ t('copyTrade.followingThUnrealized') }}</th>
                <th>{{ t('copyTrade.followingThOpenTime') }}</th>
                <th class="th-actions">{{ t('copyTrade.followingThAction') }}</th>
              </tr>
            </thead>
            <tbody>
              <tr v-for="p in positions" :key="p.id">
                <td class="td-symbol">{{ p.symbol }}</td>
                <td>
                  <span class="dir-badge" :class="p.direction === 0 ? 'dir-long' : 'dir-short'">
                    {{ p.direction === 0 ? t('assets.long') : t('assets.short') }}
                  </span>
                </td>
                <td class="num">{{ fmtNum(p.openPrice, 4) }}</td>
                <td class="num">{{ fmtNum(p.closePrice, 4) }}</td>
                <td class="num">{{ fmtNum(p.amount) }}</td>
                <td class="num">{{ p.lever }}x</td>
                <td class="num" :class="p.profit >= 0 ? 'text-up' : 'text-down'">
                  {{ fmtPnl(p.profit) }}
                  <span class="pnl-rate">({{ fmtPnl(p.profitRate) }}%)</span>
                </td>
                <td class="td-time">{{ fmtTime(p.openTime) }}</td>
                <td class="td-actions">
                  <button
                    type="button"
                    class="close-pos-btn"
                    :disabled="!canClosePosition(p) || closeBusyId !== null"
                    :title="p.isNoLoss ? t('copyTrade.noLossManualCloseTooltip') : ''"
                    @click="closeFollowPosition(p)"
                  >
                    {{ closeBusyId === String(p.id) ? t('assets.closing') : t('assets.closePosition') }}
                  </button>
                </td>
              </tr>
            </tbody>
          </table>
        </div>
      </template>

      <!-- ── My Traders ── -->
      <template v-else-if="activeTab === 'traders'">
        <div v-if="tradersLoading" class="card-grid">
          <div v-for="i in 3" :key="i" class="sk sk-card" />
        </div>
        <div v-else-if="traders.length === 0" class="empty-state">
          <div class="empty-icon">📭</div>
          <div class="empty-text">{{ t('copyTrade.followingNoTradersYet') }}</div>
          <button class="retry-btn" @click="router.push('/copy-trade')">{{ t('copyTrade.followingGoPlaza') }}</button>
        </div>
        <div v-else class="trader-list">
          <div v-for="row in traders" :key="row.id" class="trader-row dark-card">
            <div class="tr-left">
              <div class="tr-avatar-wrap">
                <img
                  v-if="row.avatar && !row.avatarError"
                  :src="row.avatar"
                  :alt="row.name"
                  class="tr-avatar-img"
                  referrerpolicy="no-referrer"
                  @error="row.avatarError = true"
                />
                <div v-else class="tr-avatar" :class="{ 'tr-avatar--lossless': row.lossless }">{{ initials(row.name) }}</div>
              </div>
              <div>
                <div class="tr-name">{{ row.name }}
                  <span v-if="row.lossless" class="badge-lossless">{{ t('copyTrade.badgeLossless') }}</span>
                  <span v-if="row.levelName" class="tr-level">{{ row.levelName }}</span>
                </div>
                <div v-if="row.description" class="tr-meta">{{ row.description }}</div>
                <div v-if="row.tags.length" class="tr-tags">
                  <span v-for="tag in row.tags" :key="tag" class="tr-tag">{{ tag }}</span>
                </div>
              </div>
            </div>
            <div class="tr-stats">
              <div class="tr-stat">
                <div class="ts-label">{{ t('copyTrade.profitUsdtBracket') }}</div>
                <div class="ts-val num" :class="row.profitAmount >= 0 ? 'pnl-up' : 'pnl-down'">
                  {{ row.profitAmount >= 0 ? '+' : '' }}{{ fmtNum(row.profitAmount) }}
                </div>
              </div>
              <div class="tr-stat-divider" />
              <div class="tr-stat">
                <div class="ts-label">{{ t('copyTrade.copyFollowersCount') }}</div>
                <div class="ts-val num">{{ row.followCustomer || '—' }}</div>
              </div>
              <div class="tr-stat-divider" />
              <div class="tr-stat">
                <div class="ts-label">{{ t('copyTrade.cumulativeTradingDays') }}</div>
                <div class="ts-val num">{{ row.tradingDays || '—' }}</div>
              </div>
            </div>
            <div class="tr-actions">
              <button class="btn-sm btn-danger-sm" @click="unfollow(row)">{{ t('copyTrade.stopFollowing') }}</button>
            </div>
          </div>
        </div>
      </template>

      <!-- ── History ── -->
      <template v-else>
        <div v-if="histLoading" class="sk-rows">
          <div v-for="i in 3" :key="i" class="sk sk-card-row" />
        </div>
        <div v-else-if="history.length === 0" class="empty-state">
          <div class="empty-icon">📭</div>
          <div class="empty-text">{{ t('copyTrade.followingHistEmpty') }}</div>
        </div>
        <div v-else class="order-cards">
          <div v-for="p in history" :key="p.id" class="order-card dark-card">
            <div class="oc-header">
              <span class="oc-symbol">{{ fmtSymbol(p.symbol) }}</span>
              <span class="oc-perp">{{ t('common.perpetual') }}</span>
              <span class="dir-badge" :class="p.direction === 0 ? 'dir-long' : 'dir-short'">{{ p.direction === 0 ? t('copyTrade.followingOpenLong') : t('copyTrade.followingOpenShort') }}</span>
              <span class="oc-pos-type">{{ p.positionType }}</span>
              <span class="oc-lever">{{ p.lever }}X</span>
            </div>
            <div class="oc-row">
              <div class="oc-col">
                <div class="oc-label">{{ t('copyTrade.closeQtyWithBase', { base: baseAsset(p.symbol) }) }}</div>
                <div class="oc-val num">{{ fmtQty(p.amount) }}</div>
              </div>
              <div class="oc-col oc-col-center">
                <div class="oc-label">{{ t('copyTrade.followingRealizedPnlUsdt') }}</div>
                <div class="oc-val num" :class="p.profit >= 0 ? 'pnl-up' : 'pnl-down'">{{ fmtProfit(p.profit) }}</div>
              </div>
              <div class="oc-col oc-col-right">
                <div class="oc-label">{{ t('copyTrade.followingYieldRate') }}</div>
                <div class="oc-val num" :class="p.profitRate >= 0 ? 'pnl-up' : 'pnl-down'">{{ fmtPnl(p.profitRate) }}%</div>
              </div>
            </div>
            <div class="oc-row oc-row-2col">
              <div class="oc-col">
                <div class="oc-label">{{ t('copyTrade.followingAvgOpenUsdt') }}</div>
                <div class="oc-val num">{{ fmtNum(p.openPrice, 2) }}</div>
              </div>
              <div class="oc-col oc-col-right">
                <div class="oc-label">{{ t('copyTrade.followingAvgCloseUsdt') }}</div>
                <div class="oc-val num">{{ fmtNum(p.closePrice, 2) }}</div>
              </div>
            </div>
            <div class="oc-footer">
              <span class="oc-time">{{ fmtTime(p.openTime) }}</span>
              <span class="oc-time-sep">→</span>
              <span class="oc-time">{{ fmtTime(p.closeTime ?? 0) }}</span>
              <span v-if="p.traderName" class="oc-trader">@{{ p.traderName }}</span>
            </div>
          </div>
        </div>
      </template>
    </div>

    <!-- ── Transfer Modal ── -->
    <Teleport to="body">
      <TransferModal
        v-if="showTransfer"
        default-from="SPOT"
        default-to="FOLLOW"
        @close="showTransfer = false"
        @success="loadWallet"
      />
    </Teleport>
  </main>
</template>

<style scoped>
.mf-main { padding-top: var(--header-height); background: var(--color-bg-primary); min-height: 100vh; }

/* ── Top bar ── */
.mf-topbar {
  background: var(--color-bg-secondary);
  border-bottom: 1px solid var(--color-border);
  padding: 12px 0;
}
.topbar-inner { display: flex; align-items: center; gap: 16px; }
.back-btn {
  display: flex; align-items: center; gap: 6px;
  color: var(--color-text-secondary); background: none; border: none; cursor: pointer;
  font-size: 14px; padding: 6px 0; transition: color 0.2s; white-space: nowrap;
}
.back-btn:hover { color: var(--color-text-primary); }
.page-title { font-size: 16px; font-weight: 600; color: var(--color-text-primary); flex: 1; }
.nav-btn {
  background: transparent; border: 1px solid var(--color-border);
  color: var(--color-text-muted); font-size: 13px; padding: 6px 14px;
  border-radius: 8px; cursor: pointer; transition: all 0.2s; white-space: nowrap;
}
.nav-btn:hover { border-color: var(--color-primary); color: var(--color-primary); }

.mf-layout { padding: 24px 0 48px; display: flex; flex-direction: column; gap: 20px; }

/* ── Wallet ── */
.wallet-card {
  background: var(--color-bg-card);
  border: 1px solid var(--color-border);
  border-radius: 12px;
  padding: 24px;
}
.wallet-loading { padding: 8px 0; }
.wallet-header { display: flex; align-items: flex-start; justify-content: space-between; margin-bottom: 20px; }
.wallet-label { font-size: 12px; color: var(--color-text-muted); margin-bottom: 6px; }
.wallet-balance { font-size: 32px; font-weight: 700; font-family: var(--font-family-num); color: var(--color-text-primary); }
.wallet-unit { font-size: 14px; color: var(--color-text-secondary); margin-left: 6px; }
.wallet-btn-group { display: flex; gap: 8px; align-items: flex-start; margin-top: 8px; }
.wallet-btn {
  padding: 8px 20px; background: var(--color-primary); color: #000;
  font-size: 13px; font-weight: 600; border-radius: 8px; border: none; cursor: pointer;
  transition: opacity 0.2s;
}
.wallet-btn:hover { opacity: 0.85; }
.wallet-btn--outline {
  background: transparent; color: var(--color-text-secondary);
  border: 1px solid var(--color-border);
}
.wallet-btn--outline:hover { border-color: var(--color-primary); color: var(--color-primary); opacity: 1; }
.wallet-stats { display: flex; gap: 0; border-top: 1px solid var(--color-border); padding-top: 16px; }
.wstat { flex: 1; padding: 0 16px; text-align: center; }
.wstat:not(:last-child) { border-right: 1px solid var(--color-border); }
.wstat:first-child { padding-left: 0; }
.wstat:last-child  { padding-right: 0; }
.wstat-label { font-size: 11px; color: var(--color-text-muted); margin-bottom: 5px; }
.wstat-val { font-size: 15px; font-weight: 600; color: var(--color-text-primary); }
.wallet-empty { color: var(--color-text-muted); font-size: 13px; text-align: center; padding: 16px 0; }

/* ── Tabs ── */
.mf-tabs {
  display: flex; border-bottom: 1px solid var(--color-border);
}
.mf-tab {
  padding: 12px 24px; font-size: 14px; font-weight: 500;
  color: var(--color-text-muted); background: transparent;
  border: none; cursor: pointer; border-bottom: 2px solid transparent;
  transition: all 0.2s;
}
.mf-tab:hover { color: var(--color-text-primary); }
.mf-tab.active { color: var(--color-primary); border-bottom-color: var(--color-primary); }

/* ── Skeleton ── */
.sk { background: rgba(255,255,255,0.06); border-radius: 8px; animation: sk-pulse 1.4s ease infinite; }
.sk-line { display: block; }
.sk-card { height: 120px; }
.sk-row  { height: 44px; margin-bottom: 8px; }
.sk-rows { display: flex; flex-direction: column; gap: 8px; padding-top: 12px; }
.card-grid { display: flex; flex-direction: column; gap: 12px; }
@keyframes sk-pulse { 0%,100% { opacity:1 } 50% { opacity:.35 } }

/* ── Trader list ── */
.trader-list { display: flex; flex-direction: column; gap: 12px; }
.trader-row {
  padding: 18px 20px; display: flex; align-items: center;
  gap: 20px; flex-wrap: wrap;
}
.tr-left { display: flex; align-items: center; gap: 14px; flex: 1; min-width: 200px; }
.tr-avatar-img { width: 44px; height: 44px; border-radius: 50%; object-fit: cover; flex-shrink: 0; }
.tr-avatar {
  width: 44px; height: 44px; border-radius: 50%; flex-shrink: 0;
  background: var(--color-primary); color: #000;
  font-size: 16px; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
}
.tr-avatar--lossless { background: #0ecb81; }
.tr-name { font-size: 15px; font-weight: 600; color: var(--color-text-primary); margin-bottom: 4px; }
.tr-meta { font-size: 12px; color: var(--color-text-muted); }
.badge-lossless {
  font-size: 10px; font-weight: 600;
  background: rgba(14,203,129,0.15); color: #0ecb81;
  border: 1px solid rgba(14,203,129,0.3); border-radius: 4px; padding: 1px 5px;
  margin-left: 5px; vertical-align: middle;
}
.tr-stats { display: flex; align-items: center; gap: 16px; }
.tr-stat { flex: 1; text-align: center; }
.tr-stat-divider { width: 1px; height: 32px; background: var(--color-border); flex-shrink: 0; }
.ts-label { font-size: 11px; color: var(--color-text-muted); margin-bottom: 4px; }
.ts-val { font-size: 14px; font-weight: 600; font-family: var(--font-family-num); color: var(--color-text-primary); }

.pnl-up   { color: var(--color-up) !important; }
.pnl-down { color: var(--color-down) !important; }
.tr-level {
  font-size: 11px; font-weight: 600; padding: 2px 8px; border-radius: 10px;
  background: rgba(240,185,11,0.12); color: var(--color-primary);
  margin-left: 6px; vertical-align: middle;
}
.tr-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.tr-tag {
  font-size: 11px; padding: 2px 10px; border-radius: 20px;
  background: rgba(82,130,255,0.12); color: #6b8cff;
  border: 1px solid rgba(82,130,255,0.3);
}
.tr-actions { display: flex; gap: 8px; flex-shrink: 0; }

/* ── Buttons ── */
.btn-sm {
  padding: 7px 14px; font-size: 12px; border-radius: 7px;
  background: transparent; border: 1px solid var(--color-border);
  color: var(--color-text-secondary); cursor: pointer; transition: all 0.2s;
}
.btn-sm:hover { border-color: var(--color-primary); color: var(--color-primary); }
.btn-danger-sm {
  border-color: rgba(246,70,93,0.4); color: #f6465d;
}
.btn-danger-sm:hover { background: rgba(246,70,93,0.08); }

/* ── Position table ── */
.pos-table-wrap { overflow-x: auto; margin-top: 8px; }
.pos-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.pos-table th {
  padding: 10px 14px; text-align: left; font-size: 11px; font-weight: 500;
  color: var(--color-text-muted); border-bottom: 1px solid var(--color-border);
  white-space: nowrap;
}
.pos-table td {
  padding: 13px 14px; color: var(--color-text-secondary);
  border-bottom: 1px solid rgba(255,255,255,0.04); white-space: nowrap;
}
.pos-table tr:hover td { background: rgba(255,255,255,0.02); }
.td-symbol { color: var(--color-text-primary) !important; font-weight: 600; }
.td-time   { color: var(--color-text-muted) !important; font-size: 12px; }
.th-actions, .td-actions { text-align: right; }
.close-pos-btn {
  padding: 6px 14px;
  font-size: 12px;
  font-weight: var(--fw-semibold);
  border: none;
  border-radius: var(--radius-sm);
  background: var(--color-primary);
  color: #000;
  cursor: pointer;
  white-space: nowrap;
  transition: opacity var(--transition);
}
.close-pos-btn:hover:not(:disabled) { opacity: 0.9; }
.close-pos-btn:disabled { opacity: 0.45; cursor: not-allowed; }
.pnl-rate  { font-size: 11px; opacity: .75; }
.dir-badge { display: inline-block; font-size: 11px; font-weight: 600; padding: 2px 8px; border-radius: 4px; }
.dir-long  { background: rgba(14,203,129,0.12); color: #0ecb81; }
.dir-short { background: rgba(246,70,93,0.12);  color: #f6465d; }

/* ── Empty ── */
.empty-state { text-align: center; padding: 60px 20px; }
.empty-icon { font-size: 36px; margin-bottom: 12px; }
.empty-text { color: var(--color-text-muted); font-size: 14px; margin-bottom: 16px; }
.retry-btn {
  padding: 8px 24px; border: 1px solid var(--color-border); border-radius: 8px;
  cursor: pointer; color: var(--color-text-secondary); background: transparent;
  font-size: 13px; transition: all 0.2s;
}
.retry-btn:hover { border-color: var(--color-primary); color: var(--color-primary); }

/* ── Transfer Modal ── */
.modal-mask {
  position: fixed; inset: 0; background: rgba(0,0,0,0.65);
  display: flex; align-items: center; justify-content: center;
  z-index: 1000; backdrop-filter: blur(4px);
}
.modal-box { background: var(--color-bg-card); border: 1px solid var(--color-border); border-radius: 16px; width: 400px; max-width: 95vw; }
.modal-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 18px 20px; border-bottom: 1px solid var(--color-border);
  font-size: 16px; font-weight: 600; color: var(--color-text-primary);
}
.modal-close { font-size: 22px; line-height: 1; color: var(--color-text-muted); background: none; border: none; cursor: pointer; }
.modal-close:hover { color: var(--color-text-primary); }
.modal-body { padding: 20px; display: flex; flex-direction: column; gap: 14px; }
.modal-footer { display: flex; gap: 10px; padding: 16px 20px; border-top: 1px solid var(--color-border); }
.modal-btn-secondary {
  flex: 1; padding: 10px; background: transparent; border: 1px solid var(--color-border);
  border-radius: 8px; color: var(--color-text-secondary); font-size: 14px; cursor: pointer;
}
.modal-btn-secondary:hover { border-color: var(--color-primary); color: var(--color-primary); }
.modal-btn-primary {
  flex: 2; padding: 10px; background: var(--color-primary); color: #000;
  font-size: 14px; font-weight: 600; border-radius: 8px; border: none; cursor: pointer;
}
.modal-btn-primary:disabled { opacity: .5; cursor: not-allowed; }
.form-group { display: flex; flex-direction: column; gap: 6px; }
.form-label { font-size: 12px; color: var(--color-text-muted); }
.form-input {
  padding: 9px 12px; background: rgba(255,255,255,0.05); border: 1px solid var(--color-border);
  border-radius: 8px; color: var(--color-text-primary); font-size: 14px; outline: none;
}
.form-input:focus { border-color: var(--color-primary); }
.form-error { font-size: 13px; color: #f6465d; padding: 8px 12px; background: rgba(246,70,93,0.08); border-radius: 6px; }
.transfer-hint { font-size: 13px; color: var(--color-text-muted); }

/* ── Order cards (history) ── */
.order-cards { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; }
.order-card  { padding: 16px; display: flex; flex-direction: column; gap: 10px; }

.oc-header { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.oc-symbol { font-size: 14px; font-weight: 700; color: var(--color-text-primary); }
.oc-perp   { font-size: 11px; color: var(--color-text-muted); }
.oc-pos-type { font-size: 11px; color: var(--color-text-muted); padding: 1px 6px; border: 1px solid var(--color-border); border-radius: 3px; }
.oc-lever    { font-size: 11px; color: var(--color-text-muted); padding: 1px 6px; border: 1px solid var(--color-border); border-radius: 3px; }

.oc-row     { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 4px; padding-top: 6px; border-top: 1px solid rgba(255,255,255,0.05); }
.oc-row-2col { grid-template-columns: 1fr 1fr; }
.oc-col { display: flex; flex-direction: column; gap: 4px; }
.oc-col-center { text-align: center; }
.oc-col-right  { text-align: right; }
.oc-label { font-size: 11px; color: var(--color-text-muted); white-space: nowrap; }
.oc-val   { font-size: 13px; font-weight: 600; color: var(--color-text-primary); }

.oc-footer { display: flex; align-items: center; gap: 6px; padding-top: 6px; border-top: 1px solid rgba(255,255,255,0.05); }
.oc-time   { font-size: 11px; color: var(--color-text-muted); }
.oc-time-sep { font-size: 11px; color: var(--color-text-muted); }
.oc-trader { font-size: 11px; color: var(--color-text-muted); margin-left: auto; }

.dir-badge { display: inline-block; font-size: 11px; font-weight: 600; padding: 2px 7px; border-radius: 3px; }
.dir-long  { background: rgba(14,203,129,0.12); color: #0ecb81; }
.dir-short { background: rgba(246,70,93,0.12);  color: #f6465d; }

.pnl-up   { color: var(--color-up) !important; }
.pnl-down { color: var(--color-down) !important; }

.sk-card-row { height: 120px; border-radius: 10px; }

/* ── Responsive ── */
@media (max-width: 900px) { .order-cards { grid-template-columns: 1fr; } }
@media (max-width: 768px) {
  .trader-row { flex-direction: column; align-items: flex-start; }
  .tr-stats   { flex-wrap: wrap; gap: 12px; }
  .wallet-stats { flex-wrap: wrap; }
  .wstat { flex: 0 0 50%; border-right: none !important; }
}
</style>
