:root {
  --color-bg: #0b1120;
  --color-bg-2: #0f172a;
  --color-card: #1e293b;
  --color-card-2: #243247;
  --color-border: #334155;
  --color-text: #e2e8f0;
  --color-text-2: #94a3b8;
  --color-primary: #3b82f6;
  --color-primary-hover: #60a5fa;
  --color-success: #10b981;
  --color-success-hover: #34d399;
  --color-warning: #f59e0b;
  --color-warning-hover: #fbbf24;
  --color-danger: #ef4444;
  --color-danger-hover: #f87171;
  --color-laser-red: #ff2d2d;
  --color-laser-green: #00e676;
  --radius-sm: 8px;
  --radius-md: 12px;
  --radius-lg: 20px;
  --shadow-md: 0 4px 20px rgba(0,0,0,0.35);
  --shadow-lg: 0 8px 40px rgba(0,0,0,0.45);
  --transition: 180ms cubic-bezier(.4,0,.2,1);
}

* { box-sizing: border-box; }
html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  background: radial-gradient(1200px 800px at 10% -10%, #1e3a8a33, transparent 60%),
              radial-gradient(1000px 700px at 110% 110%, #7c3aed33, transparent 60%),
              var(--color-bg);
  color: var(--color-text);
  font-family: 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--color-primary); }
button { font-family: inherit; }

.material-symbols-outlined {
  font-family: 'Material Symbols Outlined';
  font-weight: normal;
  font-style: normal;
  font-size: 24px;
  line-height: 1;
  letter-spacing: normal;
  text-transform: none;
  display: inline-block;
  white-space: nowrap;
  word-wrap: normal;
  direction: ltr;
  -webkit-font-feature-settings: 'liga';
  -webkit-font-smoothing: antialiased;
  vertical-align: middle;
}

.container {
  max-width: 1200px;
  margin: 0 auto;
  padding: 24px;
}

.auth-wrap {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}
.auth-card {
  width: 100%;
  max-width: 440px;
  background: var(--color-card);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: 32px;
  box-shadow: var(--shadow-lg);
  animation: fadeIn 320ms ease both;
}
.auth-brand {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 20px;
  justify-content: center;
}
.auth-brand .logo {
  width: 42px; height: 42px; border-radius: 12px;
  background: linear-gradient(135deg, #3b82f6, #7c3aed);
  display: grid; place-items: center;
  color: white; font-size: 22px;
}
.auth-brand h1 { margin: 0; font-size: 18px; letter-spacing: .2px; }
.auth-card h2 { margin: 0 0 20px; font-size: 20px; text-align: center; }

.field {
  display: block;
  margin-bottom: 16px;
}
.field label {
  display: block;
  font-size: 13px;
  color: var(--color-text-2);
  margin-bottom: 6px;
}
.field .input-wrap {
  position: relative;
  display: flex;
  align-items: center;
  background: var(--color-bg-2);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  transition: border-color var(--transition), box-shadow var(--transition);
}
.field .input-wrap:focus-within {
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px rgba(59,130,246,.22);
}
.field .input-wrap .material-symbols-outlined {
  padding: 0 10px 0 12px;
  color: var(--color-text-2);
}
.field input {
  flex: 1;
  background: transparent;
  border: none;
  outline: none;
  color: var(--color-text);
  padding: 12px 12px 12px 0;
  font-size: 15px;
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 12px 18px;
  border-radius: var(--radius-md);
  border: 1px solid transparent;
  cursor: pointer;
  font-size: 15px;
  font-weight: 600;
  color: #fff;
  transition: transform var(--transition), box-shadow var(--transition), background var(--transition), border-color var(--transition), opacity var(--transition);
  box-shadow: 0 2px 10px rgba(0,0,0,0.2);
  user-select: none;
}
.btn:hover { transform: translateY(-1px); box-shadow: 0 6px 20px rgba(0,0,0,0.3); }
.btn:active { transform: translateY(0); }
.btn:disabled { opacity: .55; cursor: not-allowed; transform: none !important; box-shadow: none !important; }

.btn-primary { background: var(--color-primary); border-color: #2563eb; }
.btn-primary:hover { background: var(--color-primary-hover); }
.btn-success { background: var(--color-success); border-color: #059669; }
.btn-success:hover { background: var(--color-success-hover); }
.btn-warning { background: var(--color-warning); border-color: #d97706; color: #111; }
.btn-warning:hover { background: var(--color-warning-hover); }
.btn-danger { background: var(--color-danger); border-color: #dc2626; }
.btn-danger:hover { background: var(--color-danger-hover); }
.btn-ghost { background: transparent; border-color: var(--color-border); color: var(--color-text); }
.btn-ghost:hover { background: var(--color-card-2); }
.btn-block { width: 100%; }
.btn-sm { padding: 8px 12px; font-size: 13px; border-radius: 10px; }

.error-text {
  color: #fca5a5;
  background: rgba(239,68,68,.14);
  border: 1px solid rgba(239,68,68,.35);
  padding: 10px 12px;
  border-radius: 10px;
  font-size: 13.5px;
  margin-bottom: 14px;
  animation: shake 320ms ease both;
}

/*
  Two-up where it fits, one-up where it does not.

  This was a bare `1fr 1fr`, which carries an automatic min-content minimum: a
  device card holding a long session id would force the track wider than the
  console is, and the pair would overflow. minmax(0, 1fr) states the floor
  explicitly at zero and lets the track be exactly half the row.
*/
.devices {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr));
  gap: 16px;
  margin-top: 8px;
}
.devices > * {
  min-width: 0;
}
.device-card {
  position: relative;
  background: var(--color-card-2);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: 28px 20px;
  text-align: center;
  cursor: pointer;
  transition: transform var(--transition), border-color var(--transition), background var(--transition), box-shadow var(--transition);
}
.device-card:hover {
  transform: translateY(-3px);
  border-color: var(--color-primary);
  background: #2a3a55;
  box-shadow: 0 10px 26px rgba(59,130,246,.18);
}
.device-card .material-symbols-outlined {
  font-size: 44px;
  background: linear-gradient(135deg, #3b82f6, #7c3aed);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  margin-bottom: 10px;
}
.device-card h3 { margin: 6px 0 4px; font-size: 18px; }
.device-card p { margin: 0; color: var(--color-text-2); font-size: 13px; }

.backdrop {
  position: fixed; inset: 0;
  background: rgba(2,6,23,0.65);
  backdrop-filter: blur(4px);
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  animation: fadeIn 180ms ease both;
}
.modal {
  width: 100%;
  max-width: 520px;
  background: var(--color-card);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: 26px;
  box-shadow: var(--shadow-lg);
  animation: modalIn 220ms cubic-bezier(.2,.8,.2,1) both;
}
.modal.lg { max-width: 700px; }
.modal h2 { margin: 0 0 10px; font-size: 20px; }
.modal p { color: var(--color-text-2); margin: 4px 0 14px; }
.modal-actions {
  display: flex;
  gap: 10px;
  justify-content: flex-end;
  margin-top: 18px;
  flex-wrap: wrap;
}
.code-box {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  background: var(--color-bg-2);
  border: 1px dashed var(--color-border);
  border-radius: var(--radius-md);
  padding: 14px 16px;
  margin: 10px 0 18px;
}
.code-box .code {
  font-family: 'Consolas', 'JetBrains Mono', monospace;
  font-size: 22px;
  letter-spacing: 3px;
  color: var(--color-primary-hover);
  font-weight: 700;
  user-select: all;
}

/*
  Bottom-right, not top-right.

  The navbar is position:sticky at the top with a higher z-index than nothing
  else in this area, so a top-right toast container sat directly on top of the
  tab strip and covered the controls an operator was reaching for. Anchoring to
  the bottom keeps toasts clear of the header at every width. The column is
  reversed so the newest toast, which is appended last, ends up nearest the
  corner the eye is drawn to.
*/
.toast-container {
  position: fixed;
  bottom: 20px;
  right: 20px;
  z-index: 200;
  display: flex;
  flex-direction: column-reverse;
  gap: 10px;
  pointer-events: none;
}
.toast {
  /* Clamped so a toast never forces a horizontal scrollbar on a narrow phone. */
  min-width: min(260px, calc(100vw - 32px));
  background: var(--color-card);
  border: 1px solid var(--color-border);
  border-left-width: 4px;
  border-left-color: var(--color-primary);
  padding: 12px 16px;
  border-radius: 10px;
  box-shadow: var(--shadow-md);
  animation: toastIn 260ms cubic-bezier(.2,.8,.2,1) both;
  display: flex;
  gap: 10px;
  align-items: center;
  pointer-events: auto;
}
.toast.success { border-left-color: var(--color-success); }
.toast.warning { border-left-color: var(--color-warning); }
.toast.error { border-left-color: var(--color-danger); }
.toast .material-symbols-outlined { color: var(--color-text-2); }
.toast.success .material-symbols-outlined { color: var(--color-success); }
.toast.warning .material-symbols-outlined { color: var(--color-warning); }
.toast.error .material-symbols-outlined { color: var(--color-danger); }
.toast .toast-msg { font-size: 14px; }

.navbar {
  position: sticky;
  top: 0;
  z-index: 30;
  background: rgba(15,23,42,0.8);
  backdrop-filter: saturate(140%) blur(10px);
  border-bottom: 1px solid var(--color-border);
}
.navbar-inner {
  max-width: 1280px;
  margin: 0 auto;
  padding: 12px 20px;
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
}
.navbar .brand {
  display: flex;
  align-items: center;
  gap: 10px;
  font-weight: 700;
  font-size: 16px;
}
.navbar .brand .logo {
  width: 32px; height: 32px; border-radius: 9px;
  background: linear-gradient(135deg, #3b82f6, #7c3aed);
  display: grid; place-items: center;
  color: white;
}
.tabs {
  display: flex;
  gap: 6px;
  padding: 4px;
  background: var(--color-card);
  border: 1px solid var(--color-border);
  border-radius: 999px;
  margin-left: 12px;
  flex-wrap: wrap;
}
.tab-btn {
  background: transparent;
  border: none;
  color: var(--color-text-2);
  padding: 8px 16px;
  border-radius: 999px;
  cursor: pointer;
  font-size: 14px;
  font-weight: 600;
  transition: color var(--transition), background var(--transition);
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.tab-btn:hover { color: var(--color-text); }
.tab-btn.active {
  background: linear-gradient(135deg, #3b82f6, #7c3aed);
  color: #fff;
  box-shadow: 0 3px 12px rgba(59,130,246,.35);
}
.nav-spacer { flex: 1; }

.pairing-state {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px;
  border-radius: 999px;
  border: 1px solid var(--color-border);
  font-size: 13px;
  color: var(--color-text-2);
}
.pairing-state .dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--color-text-2);
  box-shadow: 0 0 0 0 rgba(0,0,0,0);
}
.pairing-state.connected { color: #a7f3d0; border-color: rgba(16,185,129,.4); }
.pairing-state.connected .dot { background: var(--color-success); animation: pulse 1.4s ease-out infinite; }
.pairing-state.pending { color: #fde68a; border-color: rgba(245,158,11,.45); }
.pairing-state.pending .dot { background: var(--color-warning); }

.tab-panel { display: none; animation: fadeIn 200ms ease both; }
.tab-panel.active { display: block; }

.page-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 22px 0 18px;
  gap: 12px;
  flex-wrap: wrap;
}
.page-header h2 { margin: 0; font-size: 22px; }
.page-header .hint { color: var(--color-text-2); font-size: 13.5px; }

.card {
  background: var(--color-card);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: 20px;
  box-shadow: var(--shadow-md);
}

.drop-zone {
  border: 2px dashed var(--color-border);
  background: var(--color-card-2);
  border-radius: 18px;
  padding: 28px 18px;
  text-align: center;
  color: var(--color-text-2);
  transition: background var(--transition), border-color var(--transition), transform var(--transition);
  position: relative;
  overflow: hidden;
}
.drop-zone::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 18px;
  clip-path: polygon(0 18px, 18px 0, calc(100% - 18px) 0, 100% 18px, 100% calc(100% - 18px), calc(100% - 18px) 100%, 18px 100%, 0 calc(100% - 18px));
  pointer-events: none;
}
.drop-zone.drag-over { background: #31415f; border-color: var(--color-primary); }
.drop-zone .material-symbols-outlined { font-size: 36px; color: var(--color-primary); margin-bottom: 8px; }
.drop-zone h4 { margin: 0 0 4px; color: var(--color-text); font-size: 15px; }
.drop-zone .small { font-size: 12px; }
.drop-zone.loaded { border-color: var(--color-success); background: rgba(16,185,129,.08); }

.table-wrap {
  width: 100%;
  max-height: 62vh;
  overflow: auto;
  border-radius: var(--radius-md);
  border: 1px solid var(--color-border);
  background: var(--color-bg-2);
}
table.data {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}
table.data thead th {
  position: sticky;
  top: 0;
  background: var(--color-card);
  text-align: left;
  padding: 12px 16px;
  font-weight: 700;
  color: var(--color-text);
  border-bottom: 1px solid var(--color-border);
  z-index: 1;
}
table.data tbody td {
  padding: 10px 16px;
  border-bottom: 1px solid rgba(51,65,85,.6);
  color: var(--color-text);
}
table.data tbody tr:hover { background: rgba(59,130,246,.06); }
table.data tbody tr.highlight-row {
  animation: ticketRowPulse 2.4s cubic-bezier(0.16, 1, 0.3, 1);
}
@keyframes ticketRowPulse {
  0% { background: rgba(59, 130, 246, 0.45); }
  50% { background: rgba(16, 185, 129, 0.3); }
  100% { background: transparent; }
}
.check-control {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  user-select: none;
}
.ticket-checkbox {
  width: 18px;
  height: 18px;
  cursor: pointer;
  accent-color: var(--color-success);
  border-radius: 4px;
}
.badge-check {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 700;
}
.badge-check.yes { background: rgba(16,185,129,.15); color: #6ee7b7; }
.badge-check.no { background: rgba(239,68,68,.15); color: #fca5a5; }

/* --------------------------------------------------------------------------
   Realtime + deletion additions
   -------------------------------------------------------------------------- */

/* --- link state indicator in the navbar ---------------------------------- */
.link-state {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 5px 12px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 700;
  background: var(--color-card);
  border: 1px solid var(--color-border);
  color: var(--color-text-2);
  white-space: nowrap;
}
.link-state .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--color-text-2); flex: none; }
.link-state.live { color: #6ee7b7; border-color: rgba(16,185,129,.45); background: rgba(16,185,129,.10); }
.link-state.live .dot { background: var(--color-success); animation: linkPulse 2s infinite; }
.link-state.down { color: #fca5a5; border-color: rgba(239,68,68,.45); background: rgba(239,68,68,.10); }
.link-state.down .dot { background: var(--color-danger); }
.link-state.connecting .dot { background: var(--color-warning); animation: linkBlink 1.1s ease-in-out infinite; }
@keyframes linkPulse {
  0%   { box-shadow: 0 0 0 0 rgba(16,185,129,.55); }
  70%  { box-shadow: 0 0 0 7px rgba(16,185,129,0); }
  100% { box-shadow: 0 0 0 0 rgba(16,185,129,0); }
}
@keyframes linkBlink { 0%,100% { opacity: 1; } 50% { opacity: .25; } }

/* --- tab counter badge --------------------------------------------------- */
.tab-badge {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--color-primary);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  line-height: 1.5;
  vertical-align: 1px;
}

/* --- bulk action bar ----------------------------------------------------- */
.bulk-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin: 14px 0 0;
  padding: 10px 16px;
  border-radius: var(--radius-md);
  background: rgba(59,130,246,.10);
  border: 1px solid rgba(59,130,246,.35);
  animation: fadeIn 160ms ease both;
}
.bulk-count { font-size: 13px; color: var(--color-text); }
.bulk-count strong { color: var(--color-primary-hover); font-size: 15px; }
.bulk-actions { display: flex; gap: 8px; flex-wrap: wrap; }

/* --- table selection + row actions --------------------------------------- */
table.data th.col-select, table.data td.col-select { text-align: center; padding-left: 12px; padding-right: 6px; }
table.data th.col-act, table.data td.col-act { text-align: center; padding-left: 6px; padding-right: 12px; }
.row-select {
  width: 17px; height: 17px; cursor: pointer;
  accent-color: var(--color-primary);
  border-radius: 4px; vertical-align: middle;
}
table.data tbody tr.row-selected { background: rgba(59,130,246,.12); }
table.data tbody tr.row-selected:hover { background: rgba(59,130,246,.18); }
.row-del {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px;
  border: 1px solid transparent; border-radius: 8px;
  background: transparent; color: var(--color-text-2);
  cursor: pointer;
  transition: background 140ms ease, color 140ms ease, border-color 140ms ease;
}
.row-del .material-symbols-outlined { font-size: 18px; }
.row-del:hover { background: rgba(239,68,68,.16); color: #fca5a5; border-color: rgba(239,68,68,.4); }
.id-chip {
  background: rgba(59,130,246,.1);
  padding: 2px 8px;
  border-radius: 6px;
  font-size: 13px;
}

/* --- typed confirmation -------------------------------------------------- */
.confirm-word {
  background: rgba(239,68,68,.16);
  color: #fca5a5;
  padding: 2px 8px;
  border-radius: 5px;
  font-weight: 700;
  letter-spacing: .06em;
}

/* --- live scan feed ------------------------------------------------------ */
.feed-summary {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(150px, 100%), 1fr));
  gap: 12px;
  margin-bottom: 16px;
}
.feed-stat {
  background: var(--color-card);
  border: 1px solid var(--color-border);
  border-left-width: 3px;
  border-radius: var(--radius-md);
  padding: 12px 16px;
  display: flex; flex-direction: column; gap: 2px;
}
.feed-stat .n { font-size: 24px; font-weight: 800; line-height: 1.1; }
.feed-stat .l { font-size: 12px; color: var(--color-text-2); }
.feed-stat.ok    { border-left-color: var(--color-success); }
.feed-stat.ok .n { color: #6ee7b7; }
.feed-stat.warn  { border-left-color: var(--color-warning); }
.feed-stat.warn .n { color: #fcd34d; }
.feed-stat.bad   { border-left-color: var(--color-danger); }
.feed-stat.bad .n { color: #fca5a5; }
.feed-stat.total { border-left-color: var(--color-primary); }
.feed-stat.total .n { color: var(--color-primary-hover); }

.scan-feed { list-style: none; margin: 0; padding: 0; max-height: 58vh; overflow-y: auto; }
.feed-item {
  display: grid;
  grid-template-columns: 12px 78px 1fr auto;
  align-items: center;
  gap: 12px;
  padding: 11px 16px;
  border-bottom: 1px solid rgba(51,65,85,.6);
  animation: feedIn 260ms cubic-bezier(.16,1,.3,1) both;
}
.feed-item:last-child { border-bottom: 0; }
@keyframes feedIn {
  from { opacity: 0; transform: translateY(-8px); }
  to   { opacity: 1; transform: none; }
}
.feed-dot { width: 9px; height: 9px; border-radius: 50%; }
.feed-item.ok   .feed-dot { background: var(--color-success); }
.feed-item.warn .feed-dot { background: var(--color-warning); }
.feed-item.bad  .feed-dot { background: var(--color-danger); }
.feed-time {
  font-family: 'Consolas', 'JetBrains Mono', monospace;
  font-size: 12px;
  color: var(--color-text-2);
  font-variant-numeric: tabular-nums;
}
.feed-id {
  font-family: 'Consolas', 'JetBrains Mono', monospace;
  font-size: 13px;
  color: var(--color-text);
  background: rgba(59,130,246,.1);
  padding: 2px 8px;
  border-radius: 6px;
  justify-self: start;
  /* A scanned id is untrusted input and can be arbitrarily long. */
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.feed-tag { font-size: 12px; font-weight: 700; white-space: nowrap; }
.feed-item.ok   .feed-tag { color: #6ee7b7; }
.feed-item.warn .feed-tag { color: #fcd34d; }
.feed-item.bad  .feed-tag { color: #fca5a5; }
.feed-empty { padding: 34px 20px; text-align: center; color: var(--color-text-2); font-size: 13px; }

.stats-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr));
  gap: 14px;
  margin-bottom: 20px;
}
.stat-card {
  background: var(--color-card);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: 18px;
  display: flex;
  align-items: center;
  gap: 14px;
}
.stat-card .icon {
  width: 48px; height: 48px; border-radius: 14px;
  display: grid; place-items: center;
  color: white;
}
.stat-card.total .icon { background: linear-gradient(135deg, #3b82f6, #7c3aed); }
.stat-card.checked .icon { background: linear-gradient(135deg, #059669, #10b981); }
.stat-card.unchecked .icon { background: linear-gradient(135deg, #d97706, #f59e0b); color: #111; }
.stat-card .label { font-size: 13px; color: var(--color-text-2); margin-bottom: 2px; }
.stat-card .value { font-size: 24px; font-weight: 800; }
.stat-card .pct { font-size: 12px; color: var(--color-text-2); margin-left: 6px; }

.progress-track {
  height: 14px;
  background: var(--color-bg-2);
  border: 1px solid var(--color-border);
  border-radius: 999px;
  overflow: hidden;
  display: flex;
}
.progress-track > div {
  height: 100%;
  transition: width 500ms cubic-bezier(.2,.8,.2,1);
}
.progress-track .checked { background: linear-gradient(90deg, #059669, #10b981); }
.progress-track .unchecked { background: linear-gradient(90deg, #d97706, #f59e0b); }
.progress-legend {
  display: flex;
  gap: 16px;
  margin-top: 12px;
  color: var(--color-text-2);
  font-size: 13px;
  flex-wrap: wrap;
}
.progress-legend .sw { display: inline-block; width: 12px; height: 12px; border-radius: 4px; margin-right: 6px; vertical-align: middle; }
.progress-legend .sw.checked { background: #10b981; }
.progress-legend .sw.unchecked { background: #f59e0b; }

.donut-wrap {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 30px;
  margin-top: 20px;
  flex-wrap: wrap;
}
.donut {
  --size: 220px;
  width: var(--size); height: var(--size);
  border-radius: 50%;
  background: conic-gradient(
    var(--color-success) 0% var(--cp, 0%),
    var(--color-warning) var(--cp, 0%) 100%
  );
  display: grid; place-items: center;
  position: relative;
  box-shadow: 0 10px 30px rgba(0,0,0,.35);
}
.donut::after {
  content: '';
  position: absolute;
  inset: 22px;
  border-radius: 50%;
  background: var(--color-card);
  border: 1px solid var(--color-border);
}
.donut .center {
  position: relative;
  z-index: 1;
  text-align: center;
}
.donut .center .big { font-size: 28px; font-weight: 800; }
.donut .center .lbl { color: var(--color-text-2); font-size: 12px; }

.connecting-overlay {
  position: fixed; inset: 0;
  z-index: 60;
  display: none;
  align-items: center;
  justify-content: center;
  background: rgba(2,6,23,.7);
  backdrop-filter: blur(4px);
}
.connecting-overlay.active { display: flex; animation: fadeIn 180ms ease both; }
.connecting-box {
  background: var(--color-card);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: 30px;
  text-align: center;
  box-shadow: var(--shadow-lg);
  /* Same clamp: 280px would overflow a 320px viewport once padding is added. */
  min-width: min(280px, calc(100vw - 32px));
}
.connecting-box h3 { margin: 0 0 10px; }
.connecting-box p { color: var(--color-text-2); margin: 0 0 18px; }
.spinner {
  width: 48px; height: 48px;
  border-radius: 50%;
  border: 3px solid rgba(59,130,246,.2);
  border-top-color: var(--color-primary);
  animation: spin 900ms linear infinite;
  margin: 0 auto 14px;
}
.spinner.success {
  border-color: rgba(16,185,129,.2);
  border-top-color: var(--color-success);
  animation-duration: 500ms;
}

.success-banner {
  position: fixed;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%) scale(.8);
  opacity: 0;
  z-index: 120;
  padding: 22px 32px;
  border-radius: 18px;
  background: linear-gradient(135deg, rgba(16,185,129,.92), rgba(5,150,105,.92));
  color: white;
  font-weight: 700;
  font-size: 20px;
  display: flex;
  align-items: center;
  gap: 12px;
  pointer-events: none;
  box-shadow: 0 20px 60px rgba(16,185,129,.4);
  border: 1px solid rgba(255,255,255,.2);
}
.success-banner.show {
  animation: bannerIn 2.6s cubic-bezier(.2,.8,.2,1) both;
}

.result-modal .icon-wrap {
  width: 72px; height: 72px;
  margin: 4px auto 12px;
  border-radius: 50%;
  display: grid; place-items: center;
  color: white;
}
.result-modal.ok .icon-wrap { background: linear-gradient(135deg, #059669, #10b981); }
.result-modal.warn .icon-wrap { background: linear-gradient(135deg, #d97706, #f59e0b); color: #111; }
.result-modal.bad .icon-wrap { background: linear-gradient(135deg, #dc2626, #ef4444); }
.result-modal.ok { border-color: rgba(16,185,129,.4); }
.result-modal.warn { border-color: rgba(245,158,11,.45); }
.result-modal.bad { border-color: rgba(239,68,68,.45); }
.result-modal .msg {
  text-align: center;
  font-size: 18px;
  font-weight: 700;
  padding: 8px 0;
}

.grid2 {
  display: grid;
  grid-template-columns: 1fr 1.2fr;
  gap: 20px;
}
@media (max-width: 900px) {
  /* minmax(0, ...) not a bare 1fr: the automatic minimum still applies. */
  .grid2 { grid-template-columns: minmax(0, 1fr); }
}

.qr-layout-left, .qr-layout-right { display: flex; flex-direction: column; gap: 16px; }

.placeholder-canvas {
  position: relative;
  display: inline-block;
  border-radius: var(--radius-md);
  border: 1px solid var(--color-border);
  overflow: hidden;
  background: var(--color-bg-2);
  max-width: 100%;
}
.placeholder-canvas img {
  display: block;
  max-width: 100%;
  max-height: 520px;
  user-select: none;
  -webkit-user-drag: none;
}
.placeholder {
  position: absolute;
  border: 2px dashed #3b82f6;
  background: rgba(59,130,246,.1);
  border-radius: 6px;
  cursor: move;
  transition: box-shadow var(--transition), border-color var(--transition);
}
.placeholder:hover { box-shadow: 0 0 0 2px rgba(59,130,246,.25); }
.placeholder.selected {
  border-color: #60a5fa;
  box-shadow: 0 0 0 2px rgba(96,165,250,.55);
  background: rgba(59,130,246,.18);
}
.placeholder .num {
  position: absolute;
  top: -10px; left: -10px;
  background: var(--color-primary);
  color: white;
  font-size: 12px;
  font-weight: 800;
  width: 24px; height: 24px;
  border-radius: 50%;
  display: grid; place-items: center;
  box-shadow: 0 2px 8px rgba(0,0,0,.4);
}
/* Representative QR drawn inside an empty placeholder, so it reads as a QR
   rather than a blank square. Purely decorative: it never reaches the export,
   and it must not swallow the drag or click handling. */
.placeholder .ph-mockup {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  border-radius: 4px;
}
/* Shown only while an edge or corner is locked, so a snap is visible instead of
   the box just appearing to stop under the cursor. */
.snap-guide {
  position: absolute;
  background: #f97316;
  pointer-events: none;
  z-index: 50;
}
.placeholder .del {
  position: absolute;
  top: -10px; right: -10px;
  background: var(--color-danger);
  color: white;
  border: none;
  width: 24px; height: 24px;
  border-radius: 50%;
  display: grid; place-items: center;
  font-size: 16px;
  cursor: pointer;
  padding: 0;
  box-shadow: 0 2px 8px rgba(0,0,0,.4);
  opacity: 0;
  transition: opacity var(--transition);
}
.placeholder:hover .del { opacity: 1; }
.placeholder .handle {
  position: absolute;
  width: 12px; height: 12px;
  background: var(--color-primary);
  border: 2px solid white;
  border-radius: 3px;
}
.placeholder .handle.br { right: -6px; bottom: -6px; cursor: nwse-resize; }
.placeholder .handle.bl { left: -6px; bottom: -6px; cursor: nesw-resize; }
.placeholder .handle.tr { right: -6px; top: -6px; cursor: nesw-resize; }
.placeholder .handle.tl { left: -6px; top: -6px; cursor: nwse-resize; }

.thumb {
  margin-top: 10px;
  max-width: 100%;
  border-radius: 10px;
  border: 1px solid var(--color-border);
}

.progress-bar-wrap {
  height: 10px;
  background: var(--color-bg-2);
  border: 1px solid var(--color-border);
  border-radius: 999px;
  overflow: hidden;
}
.progress-bar-wrap > div {
  height: 100%;
  width: 0%;
  background: linear-gradient(90deg, #3b82f6, #7c3aed);
  transition: width 220ms ease;
}

@keyframes spin { to { transform: rotate(360deg); } }
@keyframes pulse {
  0% { box-shadow: 0 0 0 0 rgba(16,185,129,.45); }
  70% { box-shadow: 0 0 0 12px rgba(16,185,129,0); }
  100% { box-shadow: 0 0 0 0 rgba(16,185,129,0); }
}
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes modalIn { from { opacity: 0; transform: translateY(10px) scale(.96); } to { opacity: 1; transform: translateY(0) scale(1); } }
@keyframes toastIn { from { opacity: 0; transform: translateX(30px); } to { opacity: 1; transform: translateX(0); } }
@keyframes shake {
  0%,100% { transform: translateX(0); }
  25% { transform: translateX(-6px); }
  75% { transform: translateX(6px); }
}
@keyframes bannerIn {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(.8); }
  15%,80% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
  100% { opacity: 0; transform: translate(-50%, -50%) scale(1.04); }
}

.hidden { display: none !important; }
.row { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.mt-10 { margin-top: 10px; }
.mt-16 { margin-top: 16px; }
.mt-20 { margin-top: 20px; }
.mb-10 { margin-bottom: 10px; }
.flex-end { justify-content: flex-end; }
