<!doctype html>
<html lang="<%= text.htmlLang %>">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title><%= text.explorerTitle %></title>
    <link rel="icon" type="image/png" href="/images/plai-symbol-mark-v1.png">
    <link rel="apple-touch-icon" sizes="180x180" href="/images/plai-icon-180.png">
    <link rel="manifest" href="/site.webmanifest">
    <meta name="theme-color" content="#087b73">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-title" content="PLAI Chain">
    <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
    <style>
      :root {
        color-scheme: light;
        --bg: #eef4f8;
        --panel: #ffffff;
        --line: #dce6ef;
        --ink: #0f172a;
        --muted: #64748b;
        --brand: #0f766e;
        --brand-2: #2563eb;
        --soft: #f8fafc;
        --good: #059669;
        --warn: #b45309;
        --bad: #dc2626;
      }
      * { box-sizing: border-box; }
      body {
        margin: 0;
        background: var(--bg);
        color: var(--ink);
        font-family: Arial, "Noto Sans KR", sans-serif;
      }
      a { color: inherit; text-decoration: none; }
      .topbar {
        background: linear-gradient(135deg, #0f766e, #1d4ed8);
        color: #fff;
      }
      .topbar-inner, .page {
        width: min(1280px, calc(100vw - 40px));
        margin: 0 auto;
      }
      .topbar-inner {
        display: flex;
        justify-content: space-between;
        align-items: center;
        gap: 20px;
        padding: 24px 0;
      }
      .brand {
        display: flex;
        align-items: center;
        gap: 12px;
      }
      .brand-symbol {
        width: 48px;
        height: 48px;
        border-radius: 10px;
        border: 1px solid rgba(255,255,255,.3);
        object-fit: cover;
        flex: 0 0 auto;
      }
      .brand-copy {
        display: flex;
        flex-direction: column;
        gap: 6px;
        min-width: 0;
      }
      .eyebrow {
        margin: 0;
        color: var(--brand);
        font-size: 12px;
        font-weight: 800;
        letter-spacing: .04em;
        text-transform: uppercase;
      }
      .topbar .eyebrow { color: #a7f3d0; }
      h1, h2, h3, p { margin-top: 0; }
      h1 { margin-bottom: 0; font-size: clamp(28px, 4vw, 42px); }
      h2 { margin-bottom: 14px; font-size: 22px; }
      h3 { margin-bottom: 10px; font-size: 17px; }
      .nav {
        display: flex;
        flex-wrap: wrap;
        justify-content: flex-end;
        gap: 10px;
      }
      .btn, button {
        border: 1px solid transparent;
        border-radius: 8px;
        background: var(--brand);
        color: #fff;
        cursor: pointer;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        min-height: 38px;
        padding: 0 14px;
        font-size: 14px;
        font-weight: 800;
      }
      .btn.secondary {
        background: rgba(255,255,255,.12);
        border-color: rgba(255,255,255,.3);
      }
      .btn.light {
        background: #fff;
        color: var(--brand);
        border-color: var(--line);
      }
      .status-pill {
        background: rgba(255,255,255,.14);
        border: 1px solid rgba(255,255,255,.25);
        border-radius: 999px;
        color: #e2e8f0;
        padding: 9px 13px;
        font-size: 13px;
      }
      .status-dot {
        display: inline-block;
        width: 8px;
        height: 8px;
        margin-right: 8px;
        border-radius: 50%;
        background: #34d399;
      }
      .page {
        padding: 24px 0 48px;
      }
      .hero, .panel, .metric, .table-card {
        background: var(--panel);
        border: 1px solid var(--line);
        border-radius: 8px;
      }
      .hero {
        display: grid;
        grid-template-columns: minmax(0, 1fr) 360px;
        gap: 22px;
        padding: 24px;
        background: linear-gradient(135deg, #ffffff, #eff6ff);
      }
      .hero h2 {
        font-size: clamp(24px, 3vw, 34px);
        line-height: 1.28;
      }
      .search {
        display: grid;
        grid-template-columns: 1fr auto;
        gap: 10px;
        margin-top: 20px;
      }
      input, select {
        width: 100%;
        min-height: 44px;
        border: 1px solid var(--line);
        border-radius: 8px;
        background: #fff;
        color: var(--ink);
        padding: 0 13px;
        font-size: 14px;
      }
      .hero-side {
        display: grid;
        grid-template-columns: 1fr 1fr;
        gap: 12px;
      }
      .mini {
        background: rgba(255,255,255,.75);
        border: 1px solid var(--line);
        border-radius: 8px;
        padding: 14px;
      }
      .mini span, .metric span, .node-card span {
        display: block;
        color: var(--muted);
        font-size: 13px;
      }
      .mini strong, .mini a {
        display: block;
        margin-top: 8px;
        font-size: 18px;
        font-weight: 900;
      }
      .metrics {
        display: grid;
        grid-template-columns: repeat(6, minmax(0, 1fr));
        gap: 14px;
        margin-top: 16px;
      }
      .metric {
        padding: 16px;
      }
      .metric strong {
        display: block;
        margin-bottom: 8px;
        font-size: 26px;
      }
      .panel {
        margin-top: 18px;
        padding: 20px;
      }
      .panel-title {
        display: flex;
        align-items: flex-start;
        justify-content: space-between;
        gap: 16px;
        margin-bottom: 16px;
      }
      .panel-title h2 { margin: 0; }
      .summary-grid {
        display: grid;
        grid-template-columns: repeat(6, minmax(0, 1fr));
        gap: 12px;
      }
      .node-card {
        border: 1px solid var(--line);
        border-radius: 8px;
        background: var(--soft);
        padding: 14px;
      }
      .node-card strong {
        display: block;
        margin-top: 8px;
        font-size: 22px;
      }
      .two-col {
        display: grid;
        grid-template-columns: 1fr 1fr;
        gap: 16px;
        margin-top: 18px;
      }
      .note {
        border: 1px solid var(--line);
        border-radius: 8px;
        background: #fff;
        padding: 16px;
        color: var(--muted);
        line-height: 1.65;
      }
      .note strong { color: var(--ink); }
      .recent-list {
        display: grid;
        gap: 8px;
      }
      .event-row {
        display: grid;
        grid-template-columns: 96px 1fr auto;
        gap: 12px;
        align-items: center;
        border-bottom: 1px solid var(--line);
        padding: 8px 0;
        font-size: 14px;
      }
      .event-row:last-child { border-bottom: 0; }
      .table-wrap {
        overflow-x: auto;
      }
      table {
        width: 100%;
        min-width: 980px;
        border-collapse: collapse;
      }
      th, td {
        border-top: 1px solid var(--line);
        padding: 12px 14px;
        text-align: left;
        vertical-align: top;
        font-size: 14px;
      }
      th {
        color: var(--muted);
        font-weight: 800;
        white-space: nowrap;
      }
      .badge {
        display: inline-flex;
        align-items: center;
        border-radius: 999px;
        padding: 5px 9px;
        font-size: 12px;
        font-weight: 900;
      }
      .badge.good { background: #dcfce7; color: #047857; }
      .badge.warn { background: #fef3c7; color: #92400e; }
      .badge.bad { background: #fee2e2; color: #b91c1c; }
      .reward-headline {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        gap: 16px;
        align-items: end;
        margin-bottom: 16px;
      }
      .reward-total {
        text-align: right;
      }
      .reward-total strong {
        display: block;
        font-size: clamp(28px, 4vw, 44px);
        line-height: 1;
      }
      .reward-breakdown {
        display: grid;
        grid-template-columns: repeat(5, minmax(0, 1fr));
        gap: 12px;
      }
      .reward-card {
        border: 1px solid var(--line);
        border-radius: 8px;
        background: var(--soft);
        padding: 14px;
      }
      .reward-card span {
        display: block;
        color: var(--muted);
        font-size: 13px;
      }
      .reward-card strong {
        display: block;
        margin-top: 8px;
        font-size: 21px;
      }
      .reward-row {
        display: grid;
        grid-template-columns: 170px minmax(0, 1fr) 130px 110px;
        gap: 12px;
        align-items: center;
        border: 1px solid var(--line);
        border-radius: 8px;
        background: var(--soft);
        padding: 12px;
      }
      .reward-row + .reward-row { margin-top: 10px; }
      .reward-kind {
        display: inline-flex;
        width: max-content;
        border-radius: 999px;
        padding: 6px 10px;
        background: #e0f2fe;
        color: #0369a1;
        font-size: 12px;
        font-weight: 900;
      }
      .reward-kind.storage { background: #dcfce7; color: #047857; }
      .reward-kind.node { background: #fef3c7; color: #92400e; }
      .reward-kind.app { background: #e0e7ff; color: #3730a3; }
      .reward-kind.correction { background: #fee2e2; color: #b91c1c; }
      .reward-main strong,
      .reward-main span {
        display: block;
      }
      .reward-amount {
        text-align: right;
        font-weight: 900;
      }
      .reward-anchor {
        text-align: right;
      }
      .progress {
        width: 130px;
        height: 8px;
        overflow: hidden;
        border-radius: 999px;
        background: #e5e7eb;
      }
      .progress span {
        display: block;
        height: 100%;
        background: linear-gradient(90deg, #34d399, #0f766e);
      }
      .muted { color: var(--muted); }
      .mono {
        font-family: Consolas, "Courier New", monospace;
        color: var(--brand);
        word-break: break-all;
      }
      .grid-2 {
        display: grid;
        grid-template-columns: 1.3fr .9fr;
        gap: 18px;
      }
      .list {
        display: grid;
        gap: 10px;
      }
      .list-row {
        border: 1px solid var(--line);
        border-radius: 8px;
        background: var(--soft);
        padding: 12px;
      }
      .list-row strong {
        display: block;
        margin-bottom: 5px;
      }
      .tabs {
        display: flex;
        flex-wrap: wrap;
        gap: 8px;
        margin-bottom: 14px;
      }
      .tab {
        border: 1px solid var(--line);
        border-radius: 999px;
        background: #fff;
        color: var(--muted);
        padding: 8px 12px;
        font-size: 13px;
        font-weight: 800;
      }
      .empty {
        color: var(--muted);
        margin: 0;
      }
      @media (max-width: 980px) {
        .topbar-inner, .hero, .panel-title { display: block; }
        .nav { justify-content: flex-start; margin-top: 16px; }
        .hero-side { margin-top: 18px; }
        .metrics, .summary-grid, .reward-breakdown { grid-template-columns: repeat(2, minmax(0, 1fr)); }
        .reward-headline, .reward-row { grid-template-columns: 1fr; }
        .reward-total, .reward-amount, .reward-anchor { text-align: left; }
        .two-col, .grid-2 { grid-template-columns: 1fr; }
      }
      @media (max-width: 620px) {
        .topbar-inner, .page { width: min(100% - 24px, 1280px); }
        .search { grid-template-columns: 1fr; }
        .hero-side, .metrics, .summary-grid, .reward-breakdown { grid-template-columns: 1fr; }
        .event-row { grid-template-columns: 1fr; }
      }
    </style>
  </head>
  <body>
    <%
      const locale = text.htmlLang === 'ko' ? 'ko-KR' : 'en-US';
      const n = (value, digits = 6) => Number(value || 0).toLocaleString('en-US', { maximumFractionDigits: digits });
      const coinAmount = (value) => typeof toDisplayAmount === 'function' ? toDisplayAmount(value) : n(value, 6);
      const link = (path) => typeof urlWithLang === 'function' ? urlWithLang(path) : path;
      const short = (value) => typeof shortHash === 'function' ? shortHash(value) : String(value || '-').slice(0, 12);
      const dt = (value) => {
        const d = new Date(value);
        return Number.isNaN(d.getTime()) ? '-' : d.toLocaleString(locale);
      };
      const badgeClass = (status) => {
        const s = String(status || '').toLowerCase();
        if (s.includes('active') || s.includes('confirmed') || s === 'ok' || s === 'in' || s === 'self') return 'good';
  if (s === 'out') return 'warn';
        if (s.includes('wait') || s.includes('pending')) return 'warn';
        return 'bad';
      };
      const statusLabel = (status) => (text.statusMap && text.statusMap[status]) || status || '-';
      const config = nodeExplorer && nodeExplorer.config ? nodeExplorer.config : {};
      const summary = nodeExplorer && nodeExplorer.summary ? nodeExplorer.summary : {};
      const nodeRows = nodeExplorer && nodeExplorer.rows ? nodeExplorer.rows : [];
      const recentEvents = nodeExplorer && nodeExplorer.recentEvents ? nodeExplorer.recentEvents : [];
      const dashboardTitle = nodeExplorer && nodeExplorer.isPersonal ? text.participantDashboard : text.networkDashboard;
      const walletCoin = (walletStats && walletStats.coin) || {};
      const testnetCoin = (testnet && testnet.coin) || {};
      const coinSymbol = walletCoin.symbol || testnetCoin.symbol || 'PLAI';
      const issuanceState = testnetCoin.issuance || (testnet && testnet.config && (testnet.config.issuance || testnet.config.coinIssuance)) || '-';
      const blockList = Array.isArray(blocks) ? blocks.slice(0, 8) : [];
      const transferExplorer = typeof walletTransferExplorer !== 'undefined' && walletTransferExplorer ? walletTransferExplorer : {};
      const transferSummary = transferExplorer.summary || {};
      const transferRows = transferExplorer.rows || [];
      const isKo = text.htmlLang === 'ko';
      const commonText = {
        active: isKo ? '활성' : 'active',
        nodes: isKo ? '노드' : 'nodes',
        pending: isKo ? '대기' : 'pending',
        uptime: isKo ? '가동' : 'uptime',
        last: isKo ? '최근' : 'last',
        heightFinality: isKo ? '높이 / 확정성' : 'height / finality'
      };
      const transferText = {
        ledger: 'WALLET TRANSFER LEDGER',
        mine: isKo ? '내 지갑 전송 현황' : 'My Wallet Transfers',
        all: isKo ? '전체 지갑 전송 현황' : 'Network Wallet Transfers',
        helpMine: isKo ? '내 지갑으로 들어오고 나간 PLAI 전송을 최신 순서로 확인합니다.' : 'Track PLAI transfers sent from and received by your wallet in latest order.',
        helpAll: isKo ? '네트워크 지갑 전송 흐름을 최신 순서로 확인합니다.' : 'Track the latest PLAI wallet transfer flow across the network.',
        count: isKo ? '전송 건수' : 'Transfers',
        received: isKo ? '받은 금액' : 'Received',
        sent: isKo ? '보낸 금액' : 'Sent',
        net: isKo ? '순변동' : 'Net Change',
        time: isKo ? '시간' : 'Time',
        type: isKo ? '유형' : 'Type',
        direction: isKo ? '방향' : 'Direction',
        amount: isKo ? '수량' : 'Amount',
        memo: isKo ? '메모' : 'Memo',
        from: isKo ? '보낸 지갑' : 'From',
        to: isKo ? '받는 지갑' : 'To',
        status: isKo ? '상태' : 'Status',
        ledgerHeight: 'Ledger',
        hash: 'Hash',
        noRows: isKo ? '표시할 전송 기록이 없습니다.' : 'No transfer records to display.',
        in: isKo ? '받음' : 'Received',
        out: isKo ? '보냄' : 'Sent',
        self: isKo ? '내부' : 'Internal',
        transfer: isKo ? '전송' : 'Transfer'
      };
      const transferTitle = transferExplorer.isPersonal ? transferText.mine : transferText.all;
      const transferHelp = transferExplorer.isPersonal ? transferText.helpMine : transferText.helpAll;
      const transferDirectionLabel = (direction) => {
        const key = String(direction || '').toLowerCase();
        return transferText[key] || direction || '-';
      };
      const rewardRows = rewardExplorer && rewardExplorer.recentRows ? rewardExplorer.recentRows : [];
      const rewardSummary = rewardExplorer && rewardExplorer.summary ? rewardExplorer.summary : { totalAmount: 0, totalCount: 0, byClass: {}, status: {} };
      const rewardClassSummary = (key) => (rewardSummary.byClass && rewardSummary.byClass[key]) || { amount: 0, count: 0 };
      const rewardText = {
        ledger: 'MAINNET-STYLE REWARD LEDGER',
        mine: isKo ? '내가 받은 코인 보상' : 'My Coin Rewards',
        all: isKo ? '전체 코인 보상 흐름' : 'Network Coin Reward Flow',
        help: isKo ? '앱 사용 active 보상, 스토리지 보상, 노드 active 보상을 메인넷과 같은 코인 보상 원장 방식으로 보여줍니다.' : 'App active, storage, and node active rewards are shown in the same mainnet-style coin reward ledger.',
        total: isKo ? '순 보상' : 'Net Rewards',
        items: isKo ? '건' : 'items',
        app: isKo ? '앱 사용 active' : 'App Active',
        storage: isKo ? '스토리지' : 'Storage',
        node: isKo ? '노드 active' : 'Node Active',
        other: isKo ? '감점 / 정정' : 'Penalty / Correction',
        review: isKo ? '정책 확인' : 'Policy Check',
        blockRecorded: isKo ? '블록 기록' : 'Block Recorded',
        rejected: isKo ? '거절' : 'Rejected',
        pending: isKo ? '보상 반영' : 'Reward Added',
        blockPending: isKo ? '블록 기록 대기' : 'Waiting for Block',
        recipient: isKo ? '받은 사람' : 'Recipient',
        noRows: isKo ? '표시할 보상 기록이 아직 없습니다.' : 'No reward records to display yet.'
      };
      const rewardStatusLabel = (status) => {
        if (status === 'anchored') return rewardText.blockRecorded;
        if (status === 'review') return rewardText.review;
        if (status === 'rejected') return rewardText.rejected;
        return rewardText.pending;
      };
      const rewardBadgeClass = (status) => {
        if (status === 'anchored') return 'good';
        if (status === 'rejected') return 'bad';
        return 'warn';
      };
      const rewardAnchorLabel = (reward) => {
        if (reward.blockHeight) return '#' + reward.blockHeight;
        const reference = short(reward.refId || reward.id, 8, 6);
        return reward.status === 'pending' ? rewardText.blockPending + ' / ' + reference : reference;
      };
    %>
    <header class="topbar">
      <div class="topbar-inner">
        <div class="brand">
          <img class="brand-symbol" src="/images/plai-symbol-mark-v1.png" alt="PLAI Chain symbol">
          <div class="brand-copy">
            <p class="eyebrow"><%= text.networkLabel %></p>
            <h1><%= text.explorerTitle %></h1>
          </div>
        </div>
        <nav class="nav" aria-label="Explorer navigation">
          <a class="btn secondary" href="/">Chain Home</a>
          <a class="btn secondary" href="https://aisfor.kr/home">PLAIFOR Home</a>
          <a class="btn secondary" href="https://aisfor.kr/chain-wallet?next=/wallet"><%= text.wallet %></a>
          <% if (isAdmin) { %><a class="btn secondary" href="<%= link('/admin') %>"><%= text.admin %></a><% } %>
          <a class="btn secondary" href="<%= langToggleUrl %>"><%= text.langToggle %></a>
          <span class="status-pill"><span class="status-dot"></span><%= service.port ? text.port + ' ' + service.port : testnet.config.networkId %></span>
        </nav>
      </div>
    </header>

    <main class="page">
      <section class="hero">
        <div>
          <p class="eyebrow"><%= text.networkLabel %></p>
          <h2><%= text.heroTitle %></h2>
          <p class="muted"><%= text.heroSubtitle %></p>
          <form class="search" action="<%= link('/explorer') %>" method="get">
            <input type="hidden" name="lang" value="<%= text.htmlLang %>">
            <input name="q" value="<%= typeof q !== 'undefined' ? q : '' %>" placeholder="<%= text.searchPlaceholder %>" aria-label="<%= text.searchPlaceholder %>">
            <button type="submit"><%= text.searchButton %></button>
          </form>
          <% if (notFound) { %><p class="muted"><%= text.notFoundLabel %>: <%= notFound %></p><% } %>
        </div>
        <div class="hero-side">
          <div class="mini"><span><%= text.latestBlock %></span><a href="<%= link('/explorer/block/' + encodeURIComponent(latestBlock ? latestBlock.height : 0)) %>">#<%= blockStats.latestHeight || 0 %></a></div>
          <div class="mini"><span><%= text.chainVerify %></span><strong><%= blockChain.ok ? 'OK' : 'CHECK' %></strong></div>
          <div class="mini"><span><%= text.readiness %></span><strong><%= testnet.readiness.score %>%</strong></div>
          <div class="mini"><span><%= text.network %></span><strong><%= testnet.config.networkId %></strong></div>
        </div>
      </section>

      <section class="metrics" aria-label="<%= text.metricsLabel %>">
        <article class="metric"><strong><%= walletStats.walletCount %></strong><span><%= text.wallets %></span></article>
        <article class="metric"><strong><%= coinAmount(walletStats.circulatingSupply) %> <%= coinSymbol %></strong><span><%= text.circulating %></span></article>
        <article class="metric"><strong><%= blocks.length %></strong><span><%= text.blocks %></span></article>
        <article class="metric"><strong><%= blockStats.finalizedBlocks || 0 %></strong><span><%= text.finalized %></span></article>
        <article class="metric"><strong><%= latestTransactions.length %></strong><span><%= text.recentTx %></span></article>
        <article class="metric"><strong><%= latestProofs.length %></strong><span><%= text.recentProofs %></span></article>
        <article class="metric"><strong><%= latestRewards.length %></strong><span><%= text.recentRewards %></span></article>
        <article class="metric"><strong><%= latestRewardAudits.length %></strong><span><%= text.rewardAudits %></span></article>
        <article class="metric"><strong><%= latestRewardReviewDecisions.length %></strong><span><%= text.rewardReviews %></span></article>
        <article class="metric"><strong><%= summary.totalNodes || 0 %></strong><span><%= text.validators %></span></article>
      </section>

      <section class="panel">
        <div class="reward-headline">
          <div>
            <p class="eyebrow">MAINNET-STYLE REWARD LEDGER</p>
            <h2><%= rewardExplorer && rewardExplorer.isPersonal ? rewardText.mine : rewardText.all %></h2>
            <p class="muted"><%= rewardText.help %></p>
          </div>
          <div class="reward-total">
            <span class="muted"><%= rewardText.total %></span>
            <strong><%= n(rewardSummary.totalAmount, 6) %> <%= coinSymbol %></strong>
            <span class="muted"><%= rewardSummary.totalCount || 0 %> <%= rewardText.items %></span>
          </div>
        </div>

        <div class="reward-breakdown">
          <article class="reward-card"><span><%= rewardText.app %></span><strong><%= n(rewardClassSummary('app').amount, 6) %> <%= coinSymbol %></strong><span><%= rewardClassSummary('app').count || 0 %> <%= rewardText.items %></span></article>
          <article class="reward-card"><span><%= rewardText.storage %></span><strong><%= n(rewardClassSummary('storage').amount, 6) %> <%= coinSymbol %></strong><span><%= rewardClassSummary('storage').count || 0 %> <%= rewardText.items %></span></article>
          <article class="reward-card"><span><%= rewardText.node %></span><strong><%= n(rewardClassSummary('node').amount, 6) %> <%= coinSymbol %></strong><span><%= rewardClassSummary('node').count || 0 %> <%= rewardText.items %></span></article>
          <article class="reward-card"><span><%= rewardText.other %></span><strong><%= n((rewardClassSummary('other').amount || 0) + (rewardClassSummary('correction').amount || 0), 6) %> <%= coinSymbol %></strong><span><%= (rewardClassSummary('other').count || 0) + (rewardClassSummary('correction').count || 0) %> <%= rewardText.items %></span></article>
          <article class="reward-card"><span><%= rewardText.review %></span><strong><%= rewardSummary.status.review || 0 %></strong><span><%= rewardText.blockRecorded %> <%= rewardSummary.status.anchored || 0 %> <%= rewardText.items %></span></article>
        </div>

        <div class="list" style="margin-top:16px">
          <% if (!rewardRows.length) { %>
            <p class="empty"><%= rewardText.noRows %></p>
          <% } %>
          <% rewardRows.forEach((reward) => { %>
            <a class="reward-row" href="<%= link('/explorer/reward/' + encodeURIComponent(reward.id)) %>">
              <span class="reward-kind <%= reward.classKey %>"><%= reward.label %></span>
              <span class="reward-main">
                <strong><%= reward.sourceService %> / <%= reward.actionType %></strong>
                <span class="muted"><%= rewardText.recipient %> <span class="mono"><%= short(reward.actorId, 12, 8) %></span> / <%= dt(reward.createdAt) %></span>
                <% if (reward.note) { %><span class="muted"><%= reward.note %></span><% } %>
              </span>
              <span class="reward-amount"><%= n(reward.amount, 6) %> <%= reward.symbol || coinSymbol %></span>
              <span class="reward-anchor">
                <span class="badge <%= rewardBadgeClass(reward.status) %>"><%= rewardStatusLabel(reward.status) %></span>
                <span class="muted"><%= rewardAnchorLabel(reward) %></span>
              </span>
            </a>
          <% }) %>
        </div>
      </section>

      <section class="panel">
        <div class="panel-title">
          <div>
            <p class="eyebrow"><%= text.participantLedger %></p>
            <h2><%= dashboardTitle %></h2>
          </div>
          <strong><%= summary.activeNodes || 0 %> <%= commonText.active %> / <%= summary.totalNodes || 0 %> <%= commonText.nodes %></strong>
        </div>

        <div class="summary-grid">
          <article class="node-card"><span><%= text.activeNodes %></span><strong><%= summary.activeNodes || 0 %></strong></article>
          <article class="node-card"><span><%= text.totalCapacity %></span><strong><%= summary.totalCapacityLabel || '-' %></strong></article>
          <article class="node-card"><span><%= text.requiredCollateral %></span><strong><%= n(summary.requiredCollateral, 6) %> TRX</strong></article>
          <article class="node-card"><span><%= text.confirmedCollateral %></span><strong><%= n(summary.confirmedCollateral, 6) %> TRX</strong></article>
          <article class="node-card"><span><%= text.pendingCollateral %></span><strong><%= n(summary.pendingCollateral, 6) %> TRX</strong></article>
          <article class="node-card"><span><%= text.coverage %></span><strong><%= summary.coverage || 0 %>%</strong></article>
        </div>

        <div class="two-col">
          <article class="note">
            <h3><%= text.policyTitle %></h3>
            <p><%= text.policyText.replace('%TRX%', n(config.trxPerTb || config.trxPerUnit || 0, 6)) %></p>
            <p><%= text.policySubtext %></p>
          </article>
          <article class="note">
            <h3><%= text.recentCollateral %></h3>
            <div class="recent-list">
              <% if (!recentEvents.length) { %><p class="empty"><%= text.noCollateral %></p><% } %>
              <% recentEvents.forEach((event) => { %>
                <div class="event-row">
                  <strong><%= n(event.amountTrx || event.amount || 0, 6) %> TRX</strong>
                  <span><%= statusLabel(event.status) %></span>
                  <span class="mono"><%= short(event.nodeId || event.memo || event.txHash || event.id) %></span>
                </div>
              <% }) %>
            </div>
          </article>
        </div>

        <div class="table-wrap" style="margin-top:18px">
          <table>
            <thead>
              <tr>
                <th><%= text.node %></th>
                <th><%= text.status %></th>
                <th><%= text.capacity %></th>
                <th><%= text.requiredCollateral %></th>
                <th><%= text.confirmedPending %></th>
                <th><%= text.coverage %></th>
                <th><%= text.uptimeVerify %></th>
                <th><%= text.collateralMemo %></th>
              </tr>
            </thead>
            <tbody>
              <% if (!nodeRows.length) { %>
                <tr><td colspan="8" class="muted"><%= text.noNodes %></td></tr>
              <% } %>
              <% nodeRows.forEach((node) => { %>
                <tr>
                  <td>
                    <strong><%= node.name || node.nodeName || node.id || '-' %></strong><br>
                    <span class="muted"><%= node.node.ownerUserId || node.node.userId || '-' %> / <span class="mono"><%= short(node.nodeId || node.node.id) %></span></span>
                  </td>
                  <td><span class="badge <%= badgeClass(node.status) %>"><%= statusLabel(node.status) %></span></td>
                  <td><%= node.capacityLabel || '-' %><br><span class="muted"><%= node.usedLabel ? text.usedPrefix + ' ' + node.usedLabel : '' %></span></td>
                  <td><strong><%= n(node.requiredCollateral, 6) %> TRX</strong></td>
                  <td><strong><%= n(node.confirmedCollateral, 6) %> TRX</strong><br><span class="muted"><%= n(node.pendingCollateral, 6) %> TRX <%= commonText.pending %></span></td>
                  <td>
                    <div class="progress"><span style="width:<%= Math.max(0, Math.min(100, Number(node.coverage || 0))) %>%"></span></div>
                    <span><%= node.coverage || 0 %>%</span>
                  </td>
                  <td><span class="muted"><%= commonText.uptime %> <%= node.node.uptime || 0 %></span><br><span class="muted"><%= commonText.last %> <%= dt(node.lastHeartbeatAt || node.node.lastSeen || node.node.updatedAt || node.node.createdAt) %></span></td>
                  <td class="mono"><%= node.memo || '-' %></td>
                </tr>
              <% }) %>
            </tbody>
          </table>
        </div>
      </section>

      <section class="panel">
        <div class="panel-title">
          <div>
            <p class="eyebrow"><%= transferText.ledger %></p>
            <h2><%= transferTitle %></h2>
            <p class="muted"><%= transferHelp %></p>
          </div>
          <strong><%= transferSummary.txCount || 0 %></strong>
        </div>
        <div class="summary-grid" style="grid-template-columns:repeat(4,minmax(0,1fr))">
          <div class="metric"><span><%= transferText.count %></span><strong><%= n(transferSummary.txCount || 0, 0) %></strong></div>
          <div class="metric"><span><%= transferText.received %></span><strong><%= n(transferSummary.received || 0, 6) %> <%= coinSymbol %></strong></div>
          <div class="metric"><span><%= transferText.sent %></span><strong><%= n(transferSummary.sent || 0, 6) %> <%= coinSymbol %></strong></div>
          <div class="metric"><span><%= transferText.net %></span><strong><%= n(transferSummary.net || 0, 6) %> <%= coinSymbol %></strong></div>
        </div>
        <div class="table-wrap wallet-transfer-table" style="margin-top:18px">
          <table>
            <thead>
              <tr>
                <th><%= transferText.time %></th>
                <th><%= transferText.type %></th>
                <th><%= transferText.direction %></th>
                <th><%= transferText.amount %></th>
                <th><%= transferText.memo %></th>
                <th><%= transferText.from %></th>
                <th><%= transferText.to %></th>
                <th><%= transferText.status %></th>
                <th><%= transferText.ledgerHeight %></th>
                <th><%= transferText.hash %></th>
              </tr>
            </thead>
            <tbody>
              <% if (!transferRows.length) { %>
                <tr><td colspan="10" class="muted"><%= transferText.noRows %></td></tr>
              <% } %>
              <% transferRows.forEach((tx) => { const explorerHash = tx.txHash || tx.chainHash || tx.id; %>
                <tr>
                  <td><%= dt(tx.createdAt) %></td>
                  <td><%= tx.type || '-' %></td>
                  <td><span class="badge <%= badgeClass(tx.direction) %>"><%= transferDirectionLabel(tx.direction) %></span></td>
                  <td><strong><%= n(tx.amount || 0, 6) %> <%= coinSymbol %></strong></td>
                  <td><%= tx.memo || '-' %></td>
                  <td class="mono"><%= short(tx.fromAddress) %></td>
                  <td class="mono"><%= short(tx.toAddress) %></td>
                  <td><span class="badge <%= badgeClass(tx.status) %>"><%= statusLabel(tx.status) %></span></td>
                  <td><%= tx.ledgerHeight ? '#' + tx.ledgerHeight : '-' %></td>
                  <td class="mono"><% if (explorerHash) { %><%- link(urlWithLang('/explorer/tx/' + encodeURIComponent(explorerHash)), short(explorerHash)) %><% } else { %>-<% } %></td>
                </tr>
              <% }) %>
            </tbody>
          </table>
        </div>
      </section>
      <section class="grid-2">
        <article class="panel">
          <div class="panel-title">
            <h2><%= text.latestBlocks || text.recentBlocks %></h2>
            <span class="muted"><%= commonText.heightFinality %></span>
          </div>
          <div class="list">
            <% blockList.forEach((block) => { %>
              <a class="list-row" href="<%= link('/explorer/block/' + encodeURIComponent(block.height || block.blockHash || block.hash)) %>">
                <strong>#<%= block.height %></strong>
                <span class="muted"><%= (block.proofIds || []).length %> proofs / <%= (block.transactionIds || block.txIds || []).length %> tx / <%= short(block.blockHash || block.hash) %></span>
              </a>
            <% }) %>
          </div>
        </article>

        <article class="panel">
          <div class="panel-title">
            <h2><%= text.testnet %></h2>
            <span class="muted"><%= testnet.config.state || testnet.config.mode %></span>
          </div>
          <div class="summary-grid" style="grid-template-columns:1fr 1fr">
            <article class="node-card"><span><%= text.symbol %></span><strong><%= coinSymbol %></strong></article>
            <article class="node-card"><span><%= text.issuance %></span><strong><%= issuanceState %></strong></article>
            <article class="node-card"><span><%= text.treasury %></span><strong><%= coinAmount(walletStats.treasuryBalance) %> <%= coinSymbol %></strong></article>
            <article class="node-card"><span><%= text.genesis %></span><strong class="mono"><%= short(testnet.genesis && testnet.genesis.hash) %></strong></article>
          </div>
        </article>
      </section>

      <section class="grid-2">
        <article class="panel">
          <div class="panel-title">
            <h2><%= text.recentTransactions %></h2>
            <span class="muted"><%= latestTransactions.length %></span>
          </div>
          <div class="list">
            <% latestTransactions.slice(0, 8).forEach((tx) => { %>
              <a class="list-row" href="<%= link('/explorer/tx/' + encodeURIComponent(tx.txHash || tx.txId || tx.id || tx.hash)) %>">
                <strong><%= tx.actionType || tx.type || 'TX' %> / <%= coinAmount(tx.amount || tx.value || 0) %> <%= coinSymbol %></strong>
                <span class="muted"><%= dt(tx.createdAt || tx.timestamp) %> / <span class="mono"><%= short(tx.txHash || tx.txId || tx.id || tx.hash) %></span></span>
              </a>
            <% }) %>
          </div>
        </article>

        <article class="panel">
          <div class="panel-title">
            <h2><%= text.recentProofs %></h2>
            <span class="muted"><%= latestProofs.length %></span>
          </div>
          <div class="list">
            <% latestProofs.slice(0, 8).forEach((proof) => { %>
              <a class="list-row" href="<%= link('/explorer/proof/' + encodeURIComponent(proof.id || proof.proofId || proof.proofHash || proof.hash)) %>">
                <strong><%= proof.service || proof.type || 'PROOF' %></strong>
                <span class="muted"><%= dt(proof.createdAt || proof.timestamp) %> / <span class="mono"><%= short(proof.proofHash || proof.hash || proof.id || proof.proofId) %></span></span>
              </a>
            <% }) %>
          </div>
        </article>
      </section>
    </main>
  </body>
</html>


