{{define "console"}}
<div class="stats">
  <div class="stat">设备 <strong>{{len .ConsoleDevices}}</strong></div>
  <div class="stat">视频源 <strong>{{len .ConsoleAllVideoSources}}</strong></div>
  <div class="stat">未分配 <strong>{{len .ConsoleVideoSources}}</strong></div>
</div>

<div class="card-tabs console-tabs-wrap" style="margin-top:16px">
  <ul class="nav nav-tabs" role="tablist" style="display:flex;align-items:center">
    <li class="nav-item" role="presentation">
      <a class="nav-link active console-tab" data-panel="device" role="tab" aria-selected="true">📋 设备视图</a>
    </li>
    <li class="nav-item" role="presentation">
      <a class="nav-link console-tab" data-panel="video" role="tab" aria-selected="false">🎥 视频视图</a>
    </li>
    <li style="margin-left:auto;display:flex;gap:10px;align-items:center;padding:0 12px">
      <span id="console-status" class="muted small"></span>
      <button id="console-save-btn" class="btn" type="button" disabled style="padding:4px 14px;font-size:12px;opacity:0.5">保存并下发</button>
    </li>
  </ul>
  <div class="tab-content" style="padding:0">

<div id="console-panel-device" class="card tab-pane active show" style="padding:16px;margin:0;border-top-left-radius:0">
<form id="console-form" method="post" action="/ui/console" style="display:contents">

{{range $i, $cd := .ConsoleDevices}}
<div class="console-device-row">
  <div class="console-header">
    <span class="status-dot {{if $cd.Device.Online}}ok{{else}}bad{{end}}"></span>
    <span class="console-device-name">{{$cd.Device.DisplayName}}</span>
    <span class="console-device-meta">{{$cd.Device.IP}} | {{len $cd.Channels}}/{{$cd.MaxUnits}} 路</span>
    <span class="console-cam-add" style="margin-top:0;padding-top:0;font-size:11px;cursor:pointer" onclick="showUnassignedForDevice('{{$cd.Device.DeviceID}}')">＋ 从未分配添加</span>
  </div>
  <div class="console-body">
    <!-- LEFT: Preview tiles in one row -->
    <div class="console-preview">
      {{if $cd.Channels}}
      {{range $ch := $cd.Channels}}
      <div class="preview-tile" data-device-id="{{$cd.Device.DeviceID}}" data-channel="{{$ch.Name}}">
        <video class="console-video" muted playsinline preload="none"></video>
        <span class="preview-label">{{$ch.Display}}</span>
      </div>
      {{end}}
      {{else}}
      <div class="preview-tile empty">
      </div>
      {{end}}
      {{$remaining := sub $cd.MaxUnits (len $cd.Channels)}}
      {{if gt $remaining 0}}
      {{range $j := loop $remaining}}
      <div class="preview-tile empty"></div>
      {{end}}
      {{end}}
    </div>

    <!-- RIGHT: Features and Cameras side by side -->
    <div class="console-controls">
      <div class="console-section">
        <div class="console-section-title">检测功能</div>
        <table class="console-feature-table">
          {{range $f := $cd.Features}}
          <tr>
            <td class="console-feature-check"><input type="checkbox" name="device_{{$cd.Device.DeviceID}}_feature" value="{{$f.Key}}"{{if $f.Enabled}} checked{{end}}{{if not $f.Available}} disabled{{end}}></td>
            <td class="console-feature-label{{if $f.Conflict}} text-danger{{else if not $f.Available}} text-muted{{end}}" title="{{$f.Description}}{{if $f.Conflict}} (设备已不支持){{else if not $f.Available}} (设备不支持){{end}}">
              {{$f.Label}}{{if $f.Conflict}} ⚠{{end}}
            </td>
          </tr>
          {{end}}
        </table>
      </div>
      <div class="console-section">
        <div class="console-section-title">设备负载</div>
        <div class="console-metrics">
          <div class="metric-row" style="font-size:9px"><span>CPU</span><span>{{printf "%.0f%%" $cd.CPUUsage}}</span></div>
          <div class="console-metric-bar"><div style="height:100%;border-radius:2px;width:{{printf "%.0f%%" $cd.CPUUsage}};background:{{if gt $cd.CPUUsage 80.0}}var(--bar-red){{else if gt $cd.CPUUsage 50.0}}var(--bar-amber){{else}}var(--bar-green){{end}}"></div></div>
          <div class="metric-row" style="font-size:9px"><span>内存</span><span>{{printf "%.0f%%" $cd.MemUsage}}</span></div>
          <div class="console-metric-bar"><div style="height:100%;border-radius:2px;width:{{printf "%.0f%%" $cd.MemUsage}};background:{{if gt $cd.MemUsage 80.0}}var(--bar-red){{else if gt $cd.MemUsage 50.0}}var(--bar-amber){{else}}var(--bar-green){{end}}"></div></div>
          <div class="metric-row" style="font-size:9px"><span>NPU</span><span>{{printf "%.0f%%" $cd.NPUUsage}}</span></div>
          <div class="console-metric-bar"><div style="height:100%;border-radius:2px;width:{{printf "%.0f%%" $cd.NPUUsage}};background:{{if gt $cd.NPUUsage 80.0}}var(--bar-red){{else if gt $cd.NPUUsage 50.0}}var(--bar-amber){{else}}var(--bar-green){{end}}"></div></div>
          <div class="metric-row" style="font-size:9px"><span>磁盘</span><span>{{printf "%.0f%%" $cd.DiskUsage}}</span></div>
          <div class="console-metric-bar"><div style="height:100%;border-radius:2px;width:{{printf "%.0f%%" $cd.DiskUsage}};background:{{if gt $cd.DiskUsage 80.0}}var(--bar-red){{else if gt $cd.DiskUsage 50.0}}var(--bar-amber){{else}}var(--bar-green){{end}}"></div></div>
          <div class="metric-row" style="font-size:9px"><span>温度</span><span>{{printf "%.0f°C" $cd.Temperature}}</span></div>
          <div class="console-metric-bar"><div style="height:100%;border-radius:2px;width:{{printf "%.0f%%" $cd.Temperature}};background:{{if gt $cd.Temperature 60.0}}var(--bar-red){{else if gt $cd.Temperature 40.0}}var(--bar-amber){{else}}var(--bar-green){{end}}"></div></div>
        </div>
      </div>
    </div>
    <!-- hidden: assigned video sources for this device -->
    {{range $ch := $cd.Channels}}
    <input type="hidden" name="device_{{$cd.Device.DeviceID}}_source" value="{{$ch.SourceName}}">
    {{end}}
  </div>
</div>
{{else}}
<div class="empty-state" style="padding:0;border:none;background:transparent">
  <div class="empty-title">暂无可管理设备</div>
  <div class="muted">请先在"设备"页添加或发现设备。</div>
</div>
{{end}}

<!-- Unassigned pool -->
<div style="margin-top:16px">
  <div class="section-title">
    <div>
      <h3 class="title-with-icon">{{icon "device"}}<span>未分配视频源（{{len .ConsoleVideoSources}}路）</span></h3>
    </div>
  </div>
  <div style="display:flex;gap:10px;flex-wrap:wrap;margin-top:8px">
    {{range $s := .ConsoleVideoSources}}
    <div class="console-source-card">
      <div class="console-source-name">{{$s.Name}}</div>
      <div class="console-source-meta">{{if $s.Area}}{{$s.Area}} · {{end}}{{$s.SourceSummary}}</div>
      <div class="console-source-assign" data-source="{{$s.Name}}" onclick="assignSourceToDevice('{{$s.Name}}')">＋ 分配到设备</div>
    </div>
    {{else}}
    <span class="muted small">暂无未分配视频源</span>
    {{end}}
  </div>
</div>

</form>
</div><!-- end device panel -->

<div id="console-panel-video" class="card tab-pane" style="padding:16px;margin:0;border-top-left-radius:0">
  <div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:12px">
    {{range $cd := $.ConsoleDevices}}
    {{range $ch := $cd.Channels}}
    <div class="video-card">
      <div class="video-card-preview" data-device-id="{{$cd.Device.DeviceID}}" data-channel="{{$ch.Name}}">
        <video class="video-card-video" muted playsinline preload="none"></video>
      </div>
      <div class="video-card-info">
        <div class="video-card-name">{{$ch.SourceName}}</div>
        <div class="video-card-device">{{$cd.Device.DisplayName}}</div>
      </div>
    </div>
    {{end}}
    {{end}}
    {{range $s := $.ConsoleVideoSources}}
    <div class="video-card" style="border:1px dashed #555">
      <div style="background:#000;aspect-ratio:16/9;display:flex;align-items:center;justify-content:center;overflow:hidden">
        <span style="color:#666;font-size:12px">⏹ {{$s.Name}}</span>
      </div>
      <div style="padding:8px 10px">
        <div style="font-size:13px;font-weight:500;margin-bottom:2px">{{$s.Name}}</div>
        <a href="#" style="font-size:11px;color:var(--primary);text-decoration:none">＋ 分配到设备</a>
      </div>
    </div>
    {{end}}
  </div>
</div>

  </div><!-- tab-content -->
</div><!-- card-tabs -->

<script src="/ui/assets/vendor/hls.min.js"></script>
<script>
(function() {
  // Tab switching
  document.querySelectorAll('.console-tab').forEach(function(tab) {
    tab.addEventListener('click', function(e) {
      e.preventDefault();
      document.querySelectorAll('.console-tab').forEach(function(t) {
        t.classList.remove('active');
        t.setAttribute('aria-selected', 'false');
      });
      document.querySelectorAll('.tab-pane').forEach(function(p) {
        p.classList.remove('active', 'show');
      });
      tab.classList.add('active');
      tab.setAttribute('aria-selected', 'true');
      var panel = document.getElementById('console-panel-' + tab.getAttribute('data-panel'));
      if (panel) {
        panel.classList.add('active', 'show');
        // Initialize video view players on first switch
        if (tab.getAttribute('data-panel') === 'video' && !tab._videoInit) {
          tab._videoInit = true;
          initVideoPlayers('.video-card-preview[data-device-id]');
        }
      }
    });
  });

  function initVideoPlayers(selector) {
    var tiles = document.querySelectorAll(selector);
    var deviceChannels = {};
    tiles.forEach(function(tile) {
      var did = tile.getAttribute('data-device-id');
      var ch = tile.getAttribute('data-channel');
      if (!did || !ch) return;
      if (!deviceChannels[did]) deviceChannels[did] = {};
      deviceChannels[did][ch] = tile.querySelector('video');
    });

    var deviceIds = Object.keys(deviceChannels);
    deviceIds.forEach(function(did) {
      fetch('/ui/api/monitor/channels?device_id=' + encodeURIComponent(did))
        .then(function(r) { return r.json(); })
        .then(function(data) {
          if (!data.channels) return;
          data.channels.forEach(function(ch) {
            var video = deviceChannels[did][ch.name];
            if (!video) return;
            var proxyUrl = '/ui/hls/' + encodeURIComponent(did) + '/hls/' + encodeURIComponent(ch.name) + '/index.m3u8';
            if (Hls.isSupported()) {
              var hls = new Hls();
              hls.loadSource(proxyUrl);
              hls.attachMedia(video);
              video.play().catch(function(){});
            } else if (video.canPlayType('application/vnd.apple.mpegurl')) {
              video.src = proxyUrl;
              video.play().catch(function(){});
            }
          });
        })
        .catch(function() {});
    });
  }

  // Init device view players immediately
  initVideoPlayers('.preview-tile[data-device-id]');

  // Source assignment
  window.assignSourceToDevice = function(sourceName) {
    // Check if a specific device context exists
    var ctx = this._assignContext;
    if (ctx && ctx.deviceID) {
      addSourceToDeviceForm(ctx.deviceID, sourceName);
      document.querySelector('.source-assign-overlay').remove();
      return;
    }
    showDevicePicker(sourceName);
  };

  window.showUnassignedForDevice = function(deviceID) {
    var cards = document.querySelectorAll('.console-source-card');
    var visible = [];
    cards.forEach(function(card) {
      if (card.style.display !== 'none') {
        var nameEl = card.querySelector('.console-source-name');
        if (nameEl) visible.push(nameEl.textContent.trim());
      }
    });
    if (visible.length === 0) { alert('暂无未分配视频源'); return; }
    var html = '<div class="source-assign-overlay" style="position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.5);z-index:9999;display:flex;align-items:center;justify-content:center" onclick="this.remove()"><div style="background:var(--surface);border-radius:8px;padding:20px;min-width:300px" onclick="event.stopPropagation()"><div style="font-size:14px;font-weight:600;margin-bottom:12px">为设备添加视频源</div>';
    visible.forEach(function(name) {
      html += '<div style="padding:8px 12px;cursor:pointer;border-radius:4px;margin-bottom:4px" onmouseover="this.style.background=\'var(--surface-soft)\'" onmouseout="this.style.background=\'transparent\'" onclick="addSourceToDeviceForm(\'' + deviceID + '\', \'' + name + '\');this.closest(\'.source-assign-overlay\').remove()">' + name + '</div>';
    });
    html += '<div style="margin-top:12px;text-align:right"><button class="btn" style="font-size:12px" onclick="this.closest(\'.source-assign-overlay\').remove()">取消</button></div></div></div>';
    var div = document.createElement('div');
    div.innerHTML = html;
    document.body.appendChild(div.firstElementChild);
  };

  function addSourceToDeviceForm(deviceID, sourceName) {
    var row = document.querySelector('.console-device-row[data-device-id="' + deviceID + '"]');
    if (!row) return;
    var existing = row.querySelector('input[name="device_' + deviceID + '_source"][value="' + sourceName + '"]');
    if (existing) return;
    var input = document.createElement('input');
    input.type = 'hidden';
    input.name = 'device_' + deviceID + '_source';
    input.value = sourceName;
    row.appendChild(input);
    // Hide source card
    var card = document.querySelector('.console-source-assign[data-source="' + sourceName + '"]');
    if (card) {
      var sc = card.closest('.console-source-card');
      if (sc) sc.style.display = 'none';
    }
  }

  function showDevicePicker(sourceName) {
    var rows = document.querySelectorAll('.console-device-row');
    if (rows.length === 0) { alert('暂无可分配设备'); return; }
    var html = '<div class="source-assign-overlay" style="position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.5);z-index:9999;display:flex;align-items:center;justify-content:center" onclick="this.remove()"><div style="background:var(--surface);border-radius:8px;padding:20px;min-width:300px;max-width:400px" onclick="event.stopPropagation()"><div style="font-size:14px;font-weight:600;margin-bottom:12px">分配 \'' + sourceName + '\' 到设备</div>';
    rows.forEach(function(row) {
      var did = row.getAttribute('data-device-id');
      var nameEl = row.querySelector('.console-device-name');
      var dname = nameEl ? nameEl.textContent : did;
      html += '<div style="padding:8px 12px;cursor:pointer;border-radius:4px;margin-bottom:4px" onmouseover="this.style.background=\'var(--surface-soft)\'" onmouseout="this.style.background=\'transparent\'" onclick="addSourceToDeviceForm(\'' + did + '\', \'' + sourceName + '\');this.closest(\'.source-assign-overlay\').remove()">' + dname + ' <span style="font-size:11px;color:var(--muted)">' + did + '</span></div>';
    });
    html += '<div style="margin-top:12px;text-align:right"><button class="btn" style="font-size:12px" onclick="this.closest(\'.source-assign-overlay\').remove()">取消</button></div></div></div>';
    var div = document.createElement('div');
    div.innerHTML = html;
    document.body.appendChild(div.firstElementChild);
  }

  // ---- dirty state tracking ----
  var initialFeatures = {};
  var initialSources = {};
  document.querySelectorAll('.console-device-row').forEach(function(row) {
    var did = row.getAttribute('data-device-id');
    initialFeatures[did] = [];
    initialSources[did] = [];
    row.querySelectorAll('input[type=checkbox]').forEach(function(cb) {
      if (cb.checked) initialFeatures[did].push(cb.value);
    });
    row.querySelectorAll('input[type=hidden][name^=device_]').forEach(function(h) {
      initialSources[did].push(h.value);
    });
  });

  function isDirty() {
    var rows = document.querySelectorAll('.console-device-row');
    for (var i = 0; i < rows.length; i++) {
      var did = rows[i].getAttribute('data-device-id');
      var feats = [];
      rows[i].querySelectorAll('input[type=checkbox]:checked').forEach(function(cb) { feats.push(cb.value); });
      if (feats.sort().join(',') !== (initialFeatures[did]||[]).sort().join(',')) return true;
      var srcs = [];
      rows[i].querySelectorAll('input[type=hidden][name^=device_]').forEach(function(h) { srcs.push(h.value); });
      if (srcs.sort().join(',') !== (initialSources[did]||[]).sort().join(',')) return true;
    }
    return false;
  }

  function updateSaveButton() {
    var btn = document.getElementById('console-save-btn');
    if (isDirty()) {
      btn.disabled = false;
      btn.style.opacity = '1';
      btn.style.cursor = 'pointer';
    } else {
      btn.disabled = true;
      btn.style.opacity = '0.5';
      btn.style.cursor = 'default';
    }
  }

  // Listen for changes
  document.querySelectorAll('.console-device-row input[type=checkbox]').forEach(function(cb) {
    cb.addEventListener('change', updateSaveButton);
  });

  // Override addSourceToDeviceForm to also trigger dirty check
  var _origAddSource = addSourceToDeviceForm;
  addSourceToDeviceForm = function(did, src) {
    _origAddSource(did, src);
    updateSaveButton();
  };

  // Confirmation dialog (one-shot listener using {once:true})
  var saveBtn = document.getElementById('console-save-btn');
  var confirmHandler = function() {
    if (!isDirty()) return;
    var summary = '';
    document.querySelectorAll('.console-device-row').forEach(function(row) {
      var did = row.getAttribute('data-device-id');
      var nameEl = row.querySelector('.console-device-name');
      var dname = nameEl ? nameEl.textContent : did;
      summary += '<div style="font-weight:600;margin:8px 0 4px">' + dname + '</div>';
      row.querySelectorAll('input[type=checkbox]:checked').forEach(function(cb) {
        summary += '<div style="font-size:12px;padding-left:12px">☑ ' + cb.value + '</div>';
      });
      row.querySelectorAll('input[type=hidden][name^=device_]').forEach(function(h) {
        summary += '<div style="font-size:12px;padding-left:12px;color:var(--muted)">🎥 ' + h.value + '</div>';
      });
    });
    if (!summary) { alert('未选择任何检测功能或视频源'); return; }
    var hasFeature = false;
    document.querySelectorAll('.console-device-row input[type=checkbox]:checked').forEach(function() { hasFeature = true; });
    if (!hasFeature) { alert('请至少选择一项检测功能'); return; }
    var overlay = document.createElement('div');
    overlay.className = 'confirm-overlay';
    overlay.style.cssText = 'position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.5);z-index:9999;display:flex;align-items:center;justify-content:center';
    overlay.innerHTML = '<div style="background:var(--surface);border-radius:8px;padding:24px;min-width:360px;max-width:500px" onclick="event.stopPropagation()">' +
      '<div style="font-size:16px;font-weight:600;margin-bottom:4px">确认下发配置</div>' +
      '<div style="font-size:12px;color:var(--muted);margin-bottom:16px">以下配置将被渲染并下发到设备，media-server 将热更新。</div>' +
      summary +
      '<div style="margin-top:16px;display:flex;gap:8px;justify-content:flex-end">' +
      '<button class="btn secondary" style="font-size:12px" onclick="this.closest(\'.confirm-overlay\').remove()">取消</button>' +
      '<button class="btn" style="font-size:12px" id="confirm-deploy-btn">确认下发</button>' +
      '</div></div>';
    overlay.addEventListener('click', function() { overlay.remove(); });
    document.body.appendChild(overlay);
    document.getElementById('confirm-deploy-btn').addEventListener('click', function() {
      overlay.remove();
      document.getElementById('console-form').submit();
    }, {once: true});
  };
  saveBtn.addEventListener('click', confirmHandler);

  // Show status from URL param, then clear the param so refresh doesn't repeat it.
  (function() {
    var m = location.search.match(/[?&]task=([^&]+)/);
    var msg = location.search.match(/[?&]msg=([^&]+)/);
    if (m) {
      document.getElementById('console-status').innerHTML = '⏳ 任务 ' + m[1].substring(0,8) + ' 执行中，' + (msg ? decodeURIComponent(msg[1]) : '页面将自动刷新...');
      setTimeout(function(){ location.href = '/ui/console'; }, 8000);
    } else if (msg) {
      document.getElementById('console-status').innerHTML = decodeURIComponent(msg[1]);
      setTimeout(function(){ document.getElementById('console-status').innerHTML = ''; }, 5000);
    }
    // Clear URL params so refresh doesn't re-show stale messages.
    if (location.search) {
      var url = new URL(location.href);
      url.searchParams.delete('msg');
      url.searchParams.delete('task');
      url.searchParams.delete('error');
      history.replaceState(null, '', url.href);
    }
  })();
})();
</script>
<style>
.console-section-title { font-size: 10px; color: var(--muted); margin-bottom: 8px; text-transform: uppercase; letter-spacing: .8px; font-weight: 600; }
.console-section { background: var(--surface-soft); border-radius: 6px; padding: 10px 12px; width: 50%; overflow: hidden; }
.console-device-row { background: var(--surface); border: 1px solid var(--border); border-left: 3px solid var(--border); border-radius: 8px; padding: 14px; margin-bottom: 12px; }
.console-header { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.console-device-name { font-weight: 600; font-size: 14px; }
.console-device-meta { font-size: 11px; color: var(--muted); }
.console-body { display: flex; gap: 14px; min-height: 80px; }

/* Preview: single row, 4 equal tiles */
.console-preview { flex: 1; min-width: 350px; background: #0d0d0d; border-radius: 6px; padding: 4px; display: flex; gap: 4px; }
.preview-tile { background: #000; border-radius: 4px; width: 25%; aspect-ratio: 16/9; position: relative; overflow: hidden; }
.preview-tile.empty { background: #080808; }
.preview-tile video { width: 100%; height: 100%; object-fit: cover; display: block; }
.preview-label { position: absolute; bottom: 3px; left: 4px; background: rgba(0,0,0,0.7); color: #aaa; padding: 1px 5px; border-radius: 3px; font-size: 9px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: calc(100% - 8px); pointer-events: none; z-index: 1; }

/* Controls: side by side, 50/50 */
.console-controls { width: 460px; flex-shrink: 0; display: flex; gap: 10px; }
.console-section { background: var(--surface-soft); border-radius: 6px; padding: 10px 12px; width: 50%; overflow: hidden; }

.console-feature-table { width: 100%; border-collapse: collapse; border: none; background: transparent; }
.console-feature-table tr { border: none; }
.console-feature-table td { border: none; padding: 2px 0; vertical-align: middle; background: transparent; }
.console-feature-check { width: 18px; }
.console-feature-check input { margin: 0; display: block; }
.console-feature-label { font-size: 12px; white-space: nowrap; }


.console-cam-add { margin-top: auto; padding-top: 6px; font-size: 11px; color: var(--primary); cursor: pointer; display: inline-flex; align-items: center; gap: 3px; }

/* Metrics in console */
.console-metrics { display: flex; flex-direction: column; gap: 2px; }
.metric-row { display: flex; justify-content: space-between; font-size: 11px; padding: 1px 0; }
.console-controls { --bar-green: #66c98f; --bar-amber: #d8a657; --bar-red: #e46f72; }
.console-metric-bar { height: 3px; background: #c0c0c0; margin-bottom: 1px; border-radius: 2px; overflow: hidden; }

/* Console tabs flush */
.card-tabs.console-tabs-wrap .nav-tabs { margin-bottom: 0; }
.card-tabs.console-tabs-wrap .tab-content { padding: 0; }
.card-tabs.console-tabs-wrap .tab-content > .card { margin-top: -1px; border-top-left-radius: 0; border-top-right-radius: 0; }
.card-tabs.console-tabs-wrap .nav-tabs .nav-link { padding: 8px 20px; font-size: 13px; }

.console-source-card { background: var(--surface-soft); border: 1px dashed var(--border); border-radius: 8px; padding: 12px; width: 180px; }
.console-source-name { font-size: 13px; font-weight: 500; margin-bottom: 4px; }
.console-source-meta { font-size: 11px; color: var(--muted); }
.console-source-assign { margin-top: 6px; font-size: 11px; color: var(--primary); cursor: pointer; }

.video-card { background: var(--surface); border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }
.video-card-preview { background: #000; aspect-ratio: 16/9; display: flex; align-items: center; justify-content: center; overflow: hidden; position: relative; }

.video-card-preview video { width: 100%; height: 100%; object-fit: cover; display: block; }

.video-card-info { padding: 8px 10px; }
.video-card-name { font-size: 13px; font-weight: 500; }
.video-card-device { font-size: 11px; color: var(--primary); margin-top: 2px; }
.video-card-device.muted { color: var(--muted); }

</style>
{{end}}
