<?php
if (session_status() !== PHP_SESSION_ACTIVE) session_start();
if (!defined('BASE_PATH')) define('BASE_PATH', dirname(dirname(__DIR__)));
require_once BASE_PATH . '/database/connection.php';
require_once BASE_PATH . '/modules/shared/helpers.php';
require_once BASE_PATH . '/api/shared/ApiLoader.php';
if (!isLoggedIn()) { header('Location: ' . route_url(['module'=>'auth','action'=>'login'])); exit; }
$page_title = 'Checkout';
$active = 'checkout';
$init_methods = [];
$initial_markup = '';
$init_channels = [];
$init_countries = [];
$init_currencies = [];
try {
  $pdo = Database::getInstance()->getConnection();
  $client = ApiLoader::getIntegrationClient('key2pay', $pdo);
  if ($client) {
    $res = $client->getPaymentMethods([]);
    if (!empty($res['json']) && is_array($res['json'])) {
      $raw = $res['json'];
      $list = [];
      foreach (['items','paymentMethods','methods','data','results'] as $k) { if (isset($raw[$k]) && is_array($raw[$k])) { $list = $raw[$k]; break; } }
      if (!$list && is_array($raw)) { $list = $raw; }
      $init_methods = array_map(function($x){
        return [
          'uid' => $x['uid'] ?? ($x['id'] ?? null),
          'name' => $x['name'] ?? ($x['displayName'] ?? ''),
          'country' => $x['country'] ?? '',
          'channel' => $x['channel'] ?? '',
          'currencies' => $x['currencies'] ?? [],
          'currencyLimits' => $x['currencyLimits'] ?? [],
          'imageUrl' => $x['imageUrl'] ?? ($x['logoUrl'] ?? ($x['image'] ?? ($x['icon'] ?? ''))),
        ];
      }, $list);
      // derive filter options
      $chTmp = [];$coTmp=[];$cuTmp=[];
      foreach ($init_methods as $m) {
        if (!empty($m['channel'])) { $chTmp[] = strtoupper($m['channel']); }
        if (!empty($m['country'])) { $coTmp[] = strtoupper($m['country']); }
        if (!empty($m['currencies'])) { foreach ($m['currencies'] as $c) { if (!empty($c)) $cuTmp[] = strtoupper($c); } }
        if (!empty($m['currencyLimits'])) { foreach ($m['currencyLimits'] as $cl) { $code = strtoupper($cl['code'] ?? ''); if (!empty($code)) $cuTmp[] = $code; } }
      }
      $init_channels = array_values(array_unique($chTmp));
      $init_countries = array_values(array_unique($coTmp)); sort($init_countries);
      $init_currencies = array_values(array_unique($cuTmp)); sort($init_currencies);
      // server-side initial render
      if (!empty($init_methods)) {
        $tiles = '';
        foreach ($init_methods as $m) {
          $targetCur = isset($m['currencies'][0]) ? strtoupper($m['currencies'][0]) : '';
          $min = null; $max = null;
          if (!empty($m['currencyLimits']) && is_array($m['currencyLimits'])) {
            foreach ($m['currencyLimits'] as $cl) {
              if (strtoupper($cl['code'] ?? '') === $targetCur) { $min = $cl['min'] ?? null; $max = $cl['max'] ?? null; break; }
            }
          }
          $badge = $targetCur ? '<span class="badge badge-info">'.htmlspecialchars($targetCur).'</span>' : '';
          $logo = ($m['imageUrl'] ? ('<img class="method-logo" src="'.htmlspecialchars($m['imageUrl']).'" alt="'.htmlspecialchars($m['name']).'">') : '');
          $titleRow = '<div class="method-title-row"><span class="method-name">'.htmlspecialchars($m['name']).'</span>'.$badge.'</div>';
          $limits = '<div class="method-limits">'.($min!==null?('<span><span class="limit-icon">↓</span> Min '.htmlspecialchars((string)$min).'</span>'):'').($max!==null?('<span><span class="limit-icon">↑</span> Max '.htmlspecialchars((string)$max).'</span>'):'').'</div>';
          $channel = strtoupper($m['channel'] ?? '');
          $ribbon = $channel ? ('<div class="card-ribbon '.htmlspecialchars(strtolower($channel)).'">'.htmlspecialchars($channel).'</div>') : '';
          $tiles .= '<label class="method-card" data-uid="'.htmlspecialchars((string)$m['uid']).'">'.$ribbon.'<input type="radio" name="methodSel" class="method-input"><div class="card-top">'.$logo.'</div><div class="card-body">'.$titleRow.$limits.'</div></label>';
        }
        $initial_markup = '<div class="method-group"><div class="method-group-title"><span class="icon-list">●</span><span>Métodos</span></div><div class="method-tiles">'.$tiles.'</div></div>';
      }
    }
  }
} catch (Throwable $__) {}
ob_start();
?>
<section class="checkout-page">
  <div class="roles-header">
    <div class="header-left">
      <h1 class="page-title">
        <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="4" width="20" height="14" rx="2" ry="2"/><line x1="2" y1="10" x2="22" y2="10"/></svg>
        Checkout de Pagos
      </h1>
      <p class="page-subtitle">Métodos disponibles y filtros en tiempo real</p>
    </div>
  </div>
  <div class="card">
    <div class="card-body">
      <div class="filters-grid">
        <input id="amountInput" class="form-input" type="number" step="0.01" min="1" placeholder="Monto" />
        <input id="searchInput" class="form-input" placeholder="Buscar método" />
        <select id="channelSelect" class="form-select">
          <option value="">Todos los canales</option>
          <?php foreach ($init_channels as $ch): ?>
            <option value="<?php echo htmlspecialchars($ch); ?>"><?php echo htmlspecialchars($ch); ?></option>
          <?php endforeach; ?>
        </select>
        <select id="countrySelect" class="form-select">
          <option value="">Todos los países</option>
          <?php foreach ($init_countries as $co): ?>
            <option value="<?php echo htmlspecialchars($co); ?>"><?php echo htmlspecialchars($co); ?></option>
          <?php endforeach; ?>
        </select>
        <select id="currencySelect" class="form-select">
          <option value="">Todas las divisas</option>
          <?php foreach ($init_currencies as $cu): ?>
            <option value="<?php echo htmlspecialchars($cu); ?>"><?php echo htmlspecialchars($cu); ?></option>
          <?php endforeach; ?>
        </select>
        <select id="sortSelect" class="form-select">
          <option value="relevance">Relevancia</option>
          <option value="name">Nombre (A-Z)</option>
          <option value="min">Mínimo (asc)</option>
        </select>
        <button id="clearFiltersBtn" class="btn btn-secondary" type="button">Limpiar filtros</button>
        <button id="applyFiltersBtn" class="btn btn-primary" type="button">Aplicar filtros</button>
      </div>
      <div id="quickFilters" class="quick-filters" style="margin-top:8px"></div>
      <div id="methodsContainer" class="methods-grid"><?php echo $initial_markup; ?></div>
      <div class="checkout-actions">
        <button id="startCheckoutBtn" class="btn btn-primary">Iniciar Checkout</button>
      </div>
      <div id="statusBox" class="alert" style="display:none"></div>
    </div>
  </div>
</section>
<script>
const INIT_METHODS = <?php echo json_encode($init_methods, JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE); ?>
let METHODS = Array.isArray(INIT_METHODS) ? INIT_METHODS : []
let FILTERS = { search:'', channel:'', country:'', currency:'' }
let CHANNELS_ALL = []
let COUNTRIES_ALL = []
let CURRENCIES_ALL = []
let SORT_BY = 'relevance'
let SELECTED = null
const BASE_PFX = (location.pathname.indexOf('/simple_crm/') !== -1) ? '/simple_crm' : ''
let PER_PAGE = 9
let CURRENT_PAGE = 1
function qs(id){ return document.getElementById(id) }
function fetchMethods(showSk = true){
  const params = new URLSearchParams()
  if (FILTERS.channel) params.set('channel', FILTERS.channel)
  if (FILTERS.country) params.set('country', FILTERS.country)
  if (FILTERS.currency) params.set('currency', FILTERS.currency)
  const cont = qs('methodsContainer'); if (cont && showSk) cont.innerHTML = skeletonGrid()
  const qsStr = params.toString()?('&'+params.toString()):''
  const origin = location.origin
  const candidates = [ origin + BASE_PFX + '/modules/checkout/actions.php?action=list_key2pay_methods' + qsStr, origin + '/simple_crm/modules/checkout/actions.php?action=list_key2pay_methods' + qsStr, origin + '/modules/checkout/actions.php?action=list_key2pay_methods' + qsStr ]
  const tryFetch = async (urls) => {
    for (let i=0;i<urls.length;i++){
      try {
        const res = await fetch(urls[i], { method:'GET', credentials:'same-origin', headers:{'Accept':'application/json','X-Requested-With':'XMLHttpRequest'}, cache:'no-store' })
        if (!res.ok) continue
        const data = await res.json(); if (data && (Array.isArray(data.items) || data.success)) return data
      } catch(e){}
    }
    throw new Error('fetch_failed')
  }
  return tryFetch(candidates)
    .then(d=>{ METHODS = Array.isArray(d.items)? d.items: []; updateChannelOptions(METHODS); updateCountryOptions(METHODS); updateCurrencyOptions(METHODS); renderQuickFilters(); renderMethods() })
    .catch(e=>{ if(cont) cont.innerHTML = '<div class="alert alert-error">Error cargando métodos</div>'; const status = qs('statusBox'); if(status){ status.className='alert alert-error'; status.textContent='No se pudo cargar métodos'; status.style.display='block' } })
}
function updateChannelOptions(items){
  const sel = qs('channelSelect')
  if(!sel) return
  const chs = (items||[]).map(m => String(m.channel||'').toUpperCase()).filter(Boolean)
  let uniq = Array.from(new Set(chs))
  if (!uniq.length) uniq = ['ONLINE','CASH']
  CHANNELS_ALL = uniq
  const counts = {}
  chs.forEach(c => { counts[c] = (counts[c]||0)+1 })
  const cur = FILTERS.channel || ''
  sel.innerHTML = '<option value="">Todos los canales</option>' + uniq.map(ch => `<option value="${ch}" ${cur===ch?'selected':''}>${ch} (${counts[ch]||0})</option>`).join('')
}
function updateCountryOptions(items){
  const sel = qs('countrySelect')
  if(!sel) return
  let uniq = Array.from(new Set((items||[]).map(m => String(m.country||'').toUpperCase()).filter(Boolean))).sort()
  if (!uniq.length) uniq = ['MX','CO','PE','BR','AR','EC']
  COUNTRIES_ALL = uniq
  const cur = FILTERS.country || ''
  sel.innerHTML = '<option value="">Todos los países</option>' + uniq.map(code => `<option value="${code}" ${cur===code?'selected':''}>${code}</option>`).join('')
}
function updateCurrencyOptions(items){
  const sel = qs('currencySelect')
  if(!sel) return
  const set = new Set()
  (items||[]).forEach(m => {
    (m.currencies||[]).forEach(c => { const v = String(c||'').toUpperCase(); if(v) set.add(v) })
    (m.currencyLimits||[]).forEach(cl => { const v = String(cl.code||'').toUpperCase(); if(v) set.add(v) })
  })
  const uniq = Array.from(set).sort()
  CURRENCIES_ALL = uniq
  const cur = FILTERS.currency || ''
  sel.innerHTML = '<option value="">Todas las divisas</option>' + uniq.map(code => `<option value="${code}" ${cur===code?'selected':''}>${code}</option>`).join('')
}
function renderQuickFilters(){
  const box = qs('quickFilters'); if(!box) return
  const topCountries = COUNTRIES_ALL
  const chipsCountry = topCountries.map(c => `<button class="chip" data-type="country" data-val="${c}">${flagEmoji(c)} ${c}</button>`).join('')
  const chipsChannel = CHANNELS_ALL.map(c => `<button class="chip" data-type="channel" data-val="${c}">${c}</button>`).join('')
  const chipsCurrency = CURRENCIES_ALL.map(c => `<button class="chip" data-type="currency" data-val="${c}">${c}</button>`).join('')
  box.innerHTML = `<div class="chip-group chip-scroll"><span>País:</span>${chipsCountry}</div><div class="chip-group chip-scroll"><span>Canal:</span>${chipsChannel}</div><div class="chip-group chip-scroll"><span>Divisa:</span>${chipsCurrency}</div>`
  box.querySelectorAll('.chip').forEach(el=>{
    el.addEventListener('click', ()=>{ const t=el.getAttribute('data-type'), v=String(el.getAttribute('data-val')||'').trim().toUpperCase(); FILTERS[t]=v; const selId=t+'Select'; if(qs(selId)) qs(selId).value=v; CURRENT_PAGE=1; fetchMethods(true) })
  })
}
function applyFilters(arr){
  const t = (FILTERS.search||'').trim().toLowerCase()
  const matches = (m) => {
    const nameOk = !t || String(m.name||'').toLowerCase().includes(t) || String(m.country||'').toLowerCase().includes(t)
    const chOk = !FILTERS.channel || (String(m.channel||'').trim().toUpperCase() === FILTERS.channel)
    const coOk = !FILTERS.country || (String(m.country||'').trim().toUpperCase() === FILTERS.country)
    const cuOk = !FILTERS.currency || ((m.currencies||[]).map(x=>String(x).toUpperCase()).includes(FILTERS.currency))
    return nameOk && chOk && coOk && cuOk
  }
  let out = (arr||[]).filter(matches)
  if (SORT_BY === 'name') out = out.slice().sort((a,b)=>String(a.name||'').localeCompare(String(b.name||'')))
  if (SORT_BY === 'min') out = out.slice().sort((a,b)=>{
    const la = (a.currencyLimits||[]).find(x=>String(x.code||'').toUpperCase()===(FILTERS.currency||'').toUpperCase()) || (a.currencyLimits||[])[0] || {}
    const lb = (b.currencyLimits||[]).find(x=>String(x.code||'').toUpperCase()===(FILTERS.currency||'').toUpperCase()) || (b.currencyLimits||[])[0] || {}
    return (la.min??Infinity) - (lb.min??Infinity)
  })
  return out
}
function renderMethods(){
  const cont = qs('methodsContainer')
  if (!cont) return
  const arr = applyFilters(METHODS)
  if (!arr.length){ cont.innerHTML = '<div class="alert alert-info">Sin métodos disponibles</div>'; return }
  const total = arr.length
  const pages = Math.max(1, Math.ceil(total / PER_PAGE))
  if (CURRENT_PAGE < 1) CURRENT_PAGE = 1
  if (CURRENT_PAGE > pages) CURRENT_PAGE = pages
  const start = (CURRENT_PAGE - 1) * PER_PAGE
  const pageItems = arr.slice(start, start + PER_PAGE)
  const html = pageItems.map(m => {
    const curLimits = Array.isArray(m.currencyLimits)? m.currencyLimits: []
    const targetCur = FILTERS.currency || ((m.currencies||[])[0] || '')
    const findCur = curLimits.find(x => String(x.code||'').toUpperCase() === String(targetCur).toUpperCase()) || {}
    const min = (typeof findCur.min !== 'undefined' && findCur.min !== null) ? findCur.min : null
    const max = (typeof findCur.max !== 'undefined' && findCur.max !== null) ? findCur.max : null
    const checked = SELECTED && SELECTED.uid === m.uid ? 'selected' : ''
    const badge = targetCur ? `<span class=\"badge badge-info\">${String(targetCur).toUpperCase()}</span>` : ''
    const logo = m.imageUrl?`<img class=\"method-logo\" src=\"${m.imageUrl}\" alt=\"${m.name}\">`:''
    const titleRow = `<div class=\"method-title-row\"><span class=\"method-name\" title=\"${m.name}\">${m.name}</span>${badge}</div>`
    const limits = `<div class=\"method-limits\">${min!==null?`<span><span class=\"limit-icon\">↓</span> Min ${min}</span>`:''}${max!==null?`<span><span class=\"limit-icon\">↑</span> Max ${max}</span>`:''}</div>`
    const channel = String(m.channel||'').toUpperCase()
    const ribbon = channel?`<div class=\"card-ribbon ${channel.toLowerCase()}\">${channel}</div>`:''
    return `<label class=\"method-card ${checked}\" data-uid=\"${m.uid}\">\n${ribbon}\n<input type=\"radio\" name=\"methodSel\" class=\"method-input\">\n<div class=\"card-top\">${logo}</div>\n<div class=\"card-body\">${titleRow}${limits}</div>\n</label>`
  }).join('')
  const pager = `<div class=\"pager\">${pages>1?(`<button class=\"btn btn-outline\" id=\"pgPrev\">◀</button><span class=\"page\">${CURRENT_PAGE} / ${pages}</span><button class=\"btn btn-outline\" id=\"pgNext\">▶</button>`):''}</div>`
  cont.innerHTML = `<div class="method-group"><div class="method-group-title"><span class="icon-list">●</span><span>Métodos</span></div><div class="method-tiles">${html}</div>${pager}</div>`
  cont.querySelectorAll('.method-card').forEach(el=>{
    el.addEventListener('click', ()=>{
      cont.querySelectorAll('.method-card').forEach(x=>x.classList.remove('selected'))
      el.classList.add('selected')
      const uid = el.getAttribute('data-uid')
      SELECTED = METHODS.find(x => String(x.uid) === String(uid)) || null
    })
  })
  const prev = document.getElementById('pgPrev')
  const next = document.getElementById('pgNext')
  if (prev) prev.addEventListener('click', ()=>{ CURRENT_PAGE = Math.max(1, CURRENT_PAGE - 1); renderMethods() })
  if (next) next.addEventListener('click', ()=>{ CURRENT_PAGE = CURRENT_PAGE + 1; renderMethods() })
}
function onFilter(){ FILTERS.search = String(qs('searchInput').value||''); FILTERS.channel = String(qs('channelSelect').value||'').trim().toUpperCase(); FILTERS.country = String(qs('countrySelect').value||'').trim().toUpperCase(); FILTERS.currency = String(qs('currencySelect').value||'').trim().toUpperCase(); SORT_BY = qs('sortSelect').value; CURRENT_PAGE = 1; if ((window.CP_PROVIDER||'key2pay')==='key2pay') { fetchMethods(true) } }
function clearFilters(){ FILTERS = { search:'', channel:'', country:'', currency:'' }; CURRENT_PAGE = 1; const ids=['searchInput','channelSelect','countrySelect','currencySelect','sortSelect']; ids.forEach(id=>{ const el=qs(id); if (!el) return; if (id==='searchInput') el.value=''; else if (id==='sortSelect') el.value='relevance'; else el.value=''; }); if ((window.CP_PROVIDER||'key2pay')==='key2pay') { fetchMethods(true) } }
function applyFiltersNow(){ FILTERS.search = String(qs('searchInput').value||''); FILTERS.channel = String(qs('channelSelect').value||'').trim().toUpperCase(); FILTERS.country = String(qs('countrySelect').value||'').trim().toUpperCase(); FILTERS.currency = String(qs('currencySelect').value||'').trim().toUpperCase(); SORT_BY = qs('sortSelect').value; CURRENT_PAGE = 1; if ((window.CP_PROVIDER||'key2pay')==='key2pay') { fetchMethods(true) } }
document.addEventListener('DOMContentLoaded', ()=>{
  ['searchInput','channelSelect','countrySelect','currencySelect','sortSelect'].forEach(id=>{ qs(id).addEventListener(id==='searchInput'?'input':'change', onFilter) })
  const clr = qs('clearFiltersBtn'); if (clr) clr.addEventListener('click', clearFilters)
  const applyBtn = qs('applyFiltersBtn'); if (applyBtn) applyBtn.addEventListener('click', applyFiltersNow)
  qs('startCheckoutBtn').addEventListener('click', async ()=>{
    if ((window.CP_PROVIDER||'key2pay')!=='key2pay'){ const status = qs('statusBox'); status.className='alert alert-error'; status.textContent='Proveedor no soportado'; status.style.display='block'; return }
    const status = qs('statusBox'); status.style.display='none'
    const amt = parseFloat(qs('amountInput').value||'0')
    if (!SELECTED){ status.className='alert alert-error'; status.textContent='Selecciona un método'; status.style.display='block'; return }
    if (!Number.isFinite(amt) || amt<=0){ status.className='alert alert-error'; status.textContent='Monto inválido'; status.style.display='block'; return }
    try{
      const params = new URLSearchParams()
      params.set('currency', FILTERS.currency || (Array.isArray(SELECTED.currencies)? (SELECTED.currencies[0]||'USD') : 'USD'))
      params.set('amount_minor', String(Math.round(amt*100)))
      params.set('order_id', 'ORD_'+Date.now())
      params.set('description', 'Depósito')
      params.set('language', 'ES')
      params.set('country', SELECTED.country||'')
      if (window.CP_CLIENT_ID) params.set('client_id', String(window.CP_CLIENT_ID))
      if (window.CP_ACCOUNT_NUMBER) params.set('account_number', String(window.CP_ACCOUNT_NUMBER))
      const r = await fetch(BASE_PFX + '/modules/checkout/actions.php?action=create_key2pay_checkout', { method:'POST', headers:{'Content-Type':'application/x-www-form-urlencoded'}, body: params.toString() })
      const d = await r.json()
      if (d && d.success){
        const url = d.checkout_url || (d.json && (d.json.checkoutUrl || d.json.paymentPageUrl || d.json.paymentFormUrl))
        if (url){ window.open(url, '_blank', 'noopener'); status.className='alert alert-success'; status.textContent='Checkout iniciado'; status.style.display='block' } else { status.className='alert alert-error'; status.textContent='No se recibió URL de checkout'; status.style.display='block' }
      } else { status.className='alert alert-error'; status.textContent = d.message || 'Error iniciando checkout'; status.style.display='block' }
    }catch(e){ status.className='alert alert-error'; status.textContent='Error de conexión'; status.style.display='block' }
  })
  const qp = new URLSearchParams(location.search)
  const amtQ = qp.get('amount')
  const curQ = qp.get('currency')
  const clientQ = qp.get('client_id')
  const accQ = qp.get('account_number')
  const providerQ = (qp.get('provider')||'').toLowerCase()
  if (amtQ) { const a = parseFloat(amtQ); if (Number.isFinite(a) && a>0) { qs('amountInput').value = String(a) } }
  if (curQ) { FILTERS.currency = String(curQ).toUpperCase(); if (qs('currencySelect')) qs('currencySelect').value = FILTERS.currency }
  window.CP_CLIENT_ID = clientQ ? parseInt(clientQ,10) : null
  window.CP_ACCOUNT_NUMBER = accQ || null
  window.CP_PROVIDER = providerQ || 'key2pay'
  if (window.CP_PROVIDER==='key2pay'){
    if (METHODS.length) { updateChannelOptions(METHODS); updateCountryOptions(METHODS); updateCurrencyOptions(METHODS); renderQuickFilters(); renderMethods() } else { fetchMethods(true) }
  } else {
    const cont = qs('methodsContainer'); if (cont) cont.innerHTML = '<div class="alert alert-info">Este checkout lista Key2Pay. Proveedor: '+(providerQ||'')+'</div>'
  }
})
function flagEmoji(code){
  const c = String(code||'').toUpperCase(); if(c.length!==2) return ''
  const base = 127397; return String.fromCodePoint(c.charCodeAt(0)+base) + String.fromCodePoint(c.charCodeAt(1)+base)
}
function skeletonGrid(){
  return '<div class="skeleton-grid">'+Array.from({length:6}).map(()=>'<div class="sk-card"><div class="sk-logo"></div><div class="sk-line"></div><div class="sk-line small"></div></div>').join('')+'</div>'
}
</script>
<style>
.checkout-page .filters-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px;margin-bottom:10px}
.methods-grid{margin-top:8px}
.form-input,.form-select{padding:10px;border:1px solid #e5e7eb;border-radius:10px;background:#fff;color:#111}
.form-input::placeholder{color:#777}
.form-select option{color:#111}
.method-name{font-weight:700;font-size:13px}
.method-card{display:flex;flex-direction:column;gap:10px;background:linear-gradient(180deg, rgba(255,255,255,.08), rgba(255,255,255,.04));border:1px solid rgba(255,255,255,.14);border-radius:16px;padding:16px}
.method-card{position:relative; padding-top:42px}
.card-ribbon{position:absolute;left:0;right:0;top:0;transform:none;padding:6px 12px;border-radius:16px 16px 0 0;color:#fff;font-size:12px;font-weight:700;letter-spacing:.02em;text-align:center}
.card-ribbon.online{background:linear-gradient(180deg,#2ea6ff,#1b7bd3)}
.card-ribbon.cash{background:linear-gradient(180deg,#10b981,#058e63)}
.method-card:hover{border-color:#7bb6ff;box-shadow:0 0 0 2px rgba(46,166,255,.25)}
.method-card.selected{border-color:#2ea6ff;box-shadow:0 0 0 2px rgba(46,166,255,.35)}
.method-card input{display:none}
.card-top{display:flex;align-items:center;justify-content:center}
.method-logo{width:180px;height:48px;object-fit:contain}
.method-title-row{display:flex;align-items:center;justify-content:space-between;gap:8px}
.method-name{font-weight:700;font-size:14px;max-width:70%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.badge{display:inline-block;padding:2px 8px;border-radius:999px;background:#0b2136;color:#9ecbff;font-size:11px}
.method-limits{display:flex;align-items:center;gap:16px;color:#6c757d;font-size:12px;flex-wrap:nowrap;white-space:nowrap}
.method-limits span{white-space:nowrap}
.limit-icon{display:inline-block;color:#7bb6ff;margin-right:4px;font-weight:700}
.icon-list{color:#7bb6ff;margin-right:6px}
.pager{display:flex;justify-content:center;align-items:center;gap:10px;margin-top:16px}
.btn.btn-outline{background:transparent;border:1px solid #e5e7eb;border-radius:10px;padding:6px 10px;color:#1f2937}
.btn.btn-secondary{background:#fff;border:1px solid #e5e7eb;border-radius:10px;padding:10px 12px;color:#111}
.page{color:#6c757d;font-weight:700}
.method-tiles{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:12px}
@media (max-width: 1280px){.method-tiles{grid-template-columns:repeat(4,minmax(0,1fr))}}
@media (max-width: 1024px){.method-tiles{grid-template-columns:repeat(3,minmax(0,1fr))}}
@media (max-width: 768px){.method-tiles{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width: 480px){.method-tiles{grid-template-columns:1fr}}
.quick-filters{display:flex;gap:16px;flex-wrap:wrap}
.chip-group{display:flex;gap:8px;align-items:center}
.chip-group>span{color:#6c757d;font-weight:700}
.chip{border:1px solid #e5e7eb;background:#fff;border-radius:999px;padding:6px 10px;font-size:12px;cursor:pointer}
.chip-scroll{flex-wrap:wrap;row-gap:8px}
.skeleton-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px}
.sk-card{border:1px solid #eceff4;border-radius:10px;padding:10px;background:#fafafa}
.sk-logo{height:18px;background:linear-gradient(90deg,#eee,#f7f7f7,#eee);border-radius:6px;margin-bottom:8px}
.sk-line{height:12px;background:linear-gradient(90deg,#eee,#f7f7f7,#eee);border-radius:6px;margin-bottom:6px}
.sk-line.small{width:60%}
</style>
<?php
$content = ob_get_clean();
include BASE_PATH . '/modules/checkout/layout_public.php';
?>
