:root {
  --bg: #0b1220;
  --bg-alt: #121b2e;
  --border: #223049;
  --text: #e6edf7;
  --text-dim: #8ea0bd;
  --accent: #34d399;
  --danger: #f87171;
  --warn: #fbbf24;
  --safe: #34d399;
  --radius: 10px;
  --bg-alt-hi: #16213a;

  /* Escala de espaciado en múltiplos de 4. Antes había 18 valores distintos —7px, 9px, 11px,
     13px, 15px— puestos a ojo uno a uno, y por eso nada quedaba alineado con nada. Todo el
     espaciado de la app sale de aquí. */
  --e1: 4px;
  --e2: 8px;
  --e3: 12px;
  --e4: 16px;
  --e5: 20px;
  --e6: 24px;
  --e7: 32px;
}

/* Dark is the native register for a security console; light is the swapped-in variant. */
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) {
    --bg: #f3f5f9;
    --bg-alt: #ffffff;
    --bg-alt-hi: #eef2f8;
    --border: #d9dfe9;
    --text: #101828;
    --text-dim: #5b6478;
    --accent: #10b981;
    --danger: #dc2626;
    --warn: #b45309;
    --safe: #10b981;
  }
}
:root[data-theme="light"] {
  --bg: #f3f5f9;
  --bg-alt: #ffffff;
  --bg-alt-hi: #eef2f8;
  --border: #d9dfe9;
  --text: #101828;
  --text-dim: #5b6478;
  --accent: #10b981;
  --danger: #dc2626;
  --warn: #b45309;
  --safe: #10b981;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
}

body {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
}

.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--e3) var(--e4);
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  background: var(--bg);
  z-index: 10;
}

.brand {
  display: flex;
  align-items: center;
  gap: var(--e2);
  font-weight: 700;
  letter-spacing: 0.08em;
  font-size: 14px;
  cursor: pointer;
}

.topbar-actions {
  display: flex;
  align-items: center;
  gap: var(--e3);
}

.icon-btn {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text-dim);
  width: 34px;
  height: 34px;
  border-radius: 999px;
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
}

.badge-offline {
  font-size: 11px;
  color: var(--text-dim);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 3px 10px;
}
.badge-offline.online { color: var(--warn); border-color: var(--warn); }



.category { margin-bottom: var(--e7); }
.category:last-child { margin-bottom: 0; }

.category-title {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-dim);
  margin: 0 0 var(--e3);
}

.grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--e3);
}

.tool-card {
  background: var(--bg-alt);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: var(--e4);
  gap: var(--e1);
  min-height: 118px;
  justify-content: flex-start;
  transition: border-color 0.18s ease, background 0.18s ease, transform 0.12s ease;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--e1);
  text-align: left;
  cursor: pointer;
  font-weight: 400;
  color: var(--text);
}
.tool-card:active { transform: scale(0.97); }
@media (hover: hover) {
  .tool-card:hover { border-color: var(--accent); background: var(--bg-alt-hi); }
}
.tool-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.tool-card.disabled,
.tool-card:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}
/* Los iconos son SVG de trazo, todos con el mismo grosor y las mismas terminaciones, para que
   se lean como un conjunto. El color lo hereda del texto, así que el tema claro/oscuro y los
   estados los resuelve currentColor sin duplicar reglas. */
.tool-icon {
  width: 26px;
  height: 26px;
  fill: none;
  stroke: var(--accent);
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
  margin-bottom: 2px;
  transition: transform 0.18s ease;
}
.tool-card:active .tool-icon { transform: scale(0.9); }
.tool-label { font-size: 15px; font-weight: 600; letter-spacing: -0.01em; }
.tool-desc { font-size: 12px; color: var(--text-dim); line-height: 1.35; }

.icon-btn svg {
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.back-btn {
  background: transparent;
  border: none;
  color: var(--text-dim);
  font-size: 13px;
  padding: var(--e1) 0;
  margin: 0 0 var(--e3);
  cursor: pointer;
}
.back-btn:active { transform: none; opacity: 0.7; }

main {
  flex: 1;
  padding: var(--e4) var(--e4) var(--e7);
  max-width: 720px;
  width: 100%;
  margin: 0 auto;
}

.panel { display: none; }
.panel.active { display: block; }

h1 {
  font-size: 21px;
  letter-spacing: -0.02em;
  margin: 0 0 var(--e2);
}

.hint {
  color: var(--text-dim);
  font-size: 13px;
  line-height: 1.5;
  margin: 0 0 var(--e4);
}

/* Va después de .hint a propósito: con la misma especificidad manda la última, y antes .hint
   pisaba el color, así que la frase principal salía tan apagada como la letra pequeña. */
.hint.home-intro {
  margin: 0 0 var(--e6);
  font-size: 16px;
  line-height: 1.45;
  color: var(--text);
}
.hint.home-intro small {
  display: block;
  margin-top: var(--e2);
  font-size: 13px;
  line-height: 1.45;
  color: var(--text-dim);
}

.row {
  display: flex;
  gap: var(--e2);
  margin: 0 0 var(--e3);
}

input[type="text"],
input[type="password"] {
  flex: 1;
  background: var(--bg-alt);
  border: 1px solid var(--border);
  color: var(--text);
  padding: var(--e3) var(--e4);
  border-radius: var(--radius);
  font-size: 15px;
}
input[type="text"]:focus,
input[type="password"]:focus,
textarea:focus { outline: 2px solid var(--accent); }

textarea {
  width: 100%;
  background: var(--bg-alt);
  border: 1px solid var(--border);
  color: var(--text);
  padding: var(--e3) var(--e4);
  border-radius: var(--radius);
  font-size: 14px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  resize: vertical;
  margin: 0 0 var(--e3);
}

button {
  background: var(--accent);
  color: #06281c;
  border: none;
  padding: var(--e3) var(--e5);
  border-radius: var(--radius);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
}
button:active { transform: scale(0.98); }
button.secondary {
  background: transparent;
  color: var(--text);
  border: 1px solid var(--border);
}
button.danger-btn {
  background: var(--danger);
  color: #2a0a0a;
}

.sample-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--e2);
  margin: var(--e5) 0 var(--e3);
}

.sample-btn {
  background: transparent;
  border: 1px dashed var(--border);
  color: var(--text-dim);
  padding: var(--e2) var(--e3);
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
}
.sample-btn:active { transform: scale(0.97); }
.sample-btn.danger {
  border-color: rgba(248, 113, 113, 0.4);
  color: var(--danger);
}

.toggle {
  display: flex;
  align-items: center;
  gap: var(--e3);
  font-size: 13px;
  color: var(--text-dim);
  margin: var(--e4) 0 var(--e2);
  cursor: pointer;
}
/* Interruptor de verdad en vez de una casilla: el ajuste decide si los datos salen del
   dispositivo, y un control que se lee de un vistazo como encendido/apagado importa. */
.toggle input {
  appearance: none;
  -webkit-appearance: none;
  width: 44px;
  height: 26px;
  border-radius: 999px;
  background: var(--border);
  border: 1px solid var(--border);
  position: relative;
  flex-shrink: 0;
  cursor: pointer;
  transition: background 0.2s ease, border-color 0.2s ease;
  margin: 0;
}
.toggle input::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--text-dim);
  transition: transform 0.2s cubic-bezier(0.3, 0.9, 0.4, 1), background 0.2s ease;
}
.toggle input:checked {
  background: color-mix(in srgb, var(--accent) 35%, transparent);
  border-color: var(--accent);
}
.toggle input:checked::after {
  transform: translateX(18px);
  background: var(--accent);
}
.toggle input:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.netwarn {
  font-size: 12px;
  color: var(--warn);
  background: rgba(251, 191, 36, 0.08);
  border: 1px solid rgba(251, 191, 36, 0.3);
  border-radius: var(--radius);
  padding: var(--e3);
  margin: 0 0 var(--e4);
}

.dropzone {
  border: 2px dashed var(--border);
  border-radius: var(--radius);
  padding: var(--e7) var(--e4);
  text-align: center;
  color: var(--text-dim);
  margin: 0 0 var(--e4);
}
.dropzone.dragover {
  border-color: var(--accent);
  background: rgba(52, 211, 153, 0.06);
}

.filebtn {
  display: inline-block;
  margin-top: var(--e3);
  background: var(--bg-alt);
  border: 1px solid var(--border);
  color: var(--text);
  padding: var(--e3) var(--e4);
  border-radius: var(--radius);
  cursor: pointer;
  font-size: 13px;
}

.result {
  background: var(--bg-alt);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: var(--e4);
  margin: var(--e5) 0 0;
}
/* Las partes de un resultado se separan solas y siempre igual, en vez de que cada trozo de
   plantilla lleve su propio margen — que es como se habían ido descuadrando. */
.result > * { margin-bottom: var(--e3); }
.result > *:last-child { margin-bottom: 0; }

/* ---- Veredicto ----
   Es lo único que mucha gente va a leer, así que ocupa el espacio de lo que es: la respuesta.
   El medidor da la magnitud de un vistazo (un "60/100" suelto no significa nada para quien
   no vive de esto) y el texto dice qué hacer. La banda de color de la izquierda repite la
   señal para quien no distinga bien los colores del anillo. */
.verdict-block {
  display: flex;
  align-items: center;
  gap: var(--e3);
  padding: var(--e3);
  border-radius: 12px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-left: 4px solid var(--text-dim);
}
@media (min-width: 400px) {
  .verdict-block { gap: var(--e4); padding: var(--e4); }
}
.verdict-block.safe { border-left-color: var(--safe); }
.verdict-block.suspicious { border-left-color: var(--warn); }
.verdict-block.dangerous { border-left-color: var(--danger); }

.verdict-text { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.verdict-text strong {
  font-size: 17px;
  font-weight: 700;
  letter-spacing: -0.015em;
  line-height: 1.2;
}
.verdict-block.safe .verdict-text strong { color: var(--safe); }
.verdict-block.suspicious .verdict-text strong { color: var(--warn); }
.verdict-block.dangerous .verdict-text strong { color: var(--danger); }
.verdict-text span { font-size: 12.5px; color: var(--text-dim); line-height: 1.4; }

.gauge { width: 56px; height: 56px; flex-shrink: 0; }
@media (min-width: 400px) {
  .gauge { width: 62px; height: 62px; }
}
.gauge-track {
  fill: none;
  stroke: var(--border);
  stroke-width: 6;
}
.gauge-value {
  fill: none;
  stroke-width: 6;
  stroke-linecap: round;
  transform: rotate(-90deg);
  transform-origin: 50% 50%;
  stroke-dashoffset: var(--recorte);
}
.gauge-value.safe { stroke: var(--safe); }
.gauge-value.suspicious { stroke: var(--warn); }
.gauge-value.dangerous { stroke: var(--danger); }
.gauge-value.unknown { stroke: var(--text-dim); }
.gauge-num {
  fill: var(--text);
  font-size: 19px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* El anillo se dibuja al aparecer. Es el único movimiento de la pantalla y por eso funciona:
   lleva la mirada al dato que importa en vez de competir con él. */
@media (prefers-reduced-motion: no-preference) {
  .gauge-value {
    animation: barrido 0.75s cubic-bezier(0.22, 0.8, 0.3, 1) both;
  }
  @keyframes barrido {
    from { stroke-dashoffset: var(--vuelta); }
    to { stroke-dashoffset: var(--recorte); }
  }
}

.score {
  color: var(--text-dim);
  font-size: 13px;
}

.verdict {
  display: inline-block;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: var(--e1) var(--e3);
  border-radius: 999px;
}
.verdict.safe { background: rgba(52, 211, 153, 0.15); color: var(--safe); }
.verdict.suspicious { background: rgba(251, 191, 36, 0.15); color: var(--warn); }
.verdict.dangerous { background: rgba(248, 113, 113, 0.15); color: var(--danger); }
.verdict.unknown { background: rgba(142, 160, 189, 0.15); color: var(--text-dim); }

.chain {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 13px;
  word-break: break-all;
  background: var(--bg);
  border-radius: 9px;
  padding: var(--e3);
}
.chain .arrow { color: var(--text-dim); padding: 0 4px; }

/* El contenido literal del QR es lo primero que el usuario necesita ver: es exactamente lo
   que su móvil habría hecho sin preguntar. Se muestra tal cual, escapado y sin acortar. */
.qr-payload {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 13px;
  word-break: break-all;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 9px;
  padding: var(--e3);
}

.flags {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: var(--e2);
}
/* Las señales se ordenan por gravedad y se pintan con peso distinto. Antes todas se veían
   igual: "está en las listas de phishing" (80 puntos) parecía tan importante como "el TLD es
   barato" (15), y la que importaba se perdía. El punto de color acompaña al grosor del borde
   para no depender solo del color. */
.flags li {
  font-size: 13px;
  line-height: 1.45;
  padding: var(--e3);
  background: var(--bg);
  border-radius: 9px;
  border-left: 3px solid var(--border);
  position: relative;
}
@media (prefers-reduced-motion: no-preference) {
  .flags li {
    animation: aparece 0.32s ease both;
    animation-delay: calc(var(--i, 0) * 45ms + 120ms);
  }
  @keyframes aparece {
    from { opacity: 0; transform: translateY(4px); }
    to { opacity: 1; transform: none; }
  }
}

.flags li.sev-alta {
  border-left-width: 4px;
  border-left-color: var(--danger);
  background: color-mix(in srgb, var(--danger) 9%, var(--bg));
  font-weight: 500;
}
.flags li.sev-media { border-left-color: var(--warn); }
.flags li.sev-baja { border-left-color: var(--text-dim); }
/* 0 puntos: son límites de la app ("no se pudo resolver el destino"), no acusaciones al
   enlace, así que se pintan apagadas para que no se lean como una señal de peligro. */
.flags li.sev-nota {
  border-left-color: var(--border);
  color: var(--text-dim);
  font-size: 12.5px;
}
.flags li.sev-ninguna {
  border-left-color: var(--safe);
  color: var(--text-dim);
}

.flags li.bad { border-left-color: var(--danger); }
.flags li.warn { border-left-color: var(--warn); }
.flags li.info { border-left-color: var(--text-dim); }

.meta {
  font-size: 12px;
  line-height: 1.5;
  color: var(--text-dim);
}
.meta.mono {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  word-break: break-all;
}

.history-list {
  display: flex;
  flex-direction: column;
  gap: var(--e2);
}
.history-item {
  background: var(--bg-alt);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--e3);
  cursor: pointer;
}
.history-item .h-top {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--e2);
}
.history-item .h-input {
  font-size: 13px;
  word-break: break-all;
  flex: 1;
  display: flex;
  align-items: flex-start;
  gap: var(--e2);
}
.h-icon {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  margin-top: 2px;
  fill: none;
  stroke: var(--text-dim);
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.history-item .h-time {
  font-size: 11px;
  color: var(--text-dim);
  margin-top: var(--e1);
}
.history-item .h-del {
  background: transparent;
  border: none;
  color: var(--text-dim);
  font-size: 16px;
  padding: 2px 8px;
  cursor: pointer;
}
.empty {
  color: var(--text-dim);
  font-size: 13px;
  text-align: center;
  padding: var(--e6) 0;
}

.footer {
  text-align: center;
  font-size: 11px;
  line-height: 1.6;
  color: var(--text-dim);
  padding: var(--e4);
  border-top: 1px solid var(--border);
}

@media (min-width: 600px) {
  .row { flex-wrap: nowrap; }
}

.offline-notice {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--e3);
  margin-top: var(--e4);
}
.offline-notice .enable-net-btn {
  border-style: solid;
  border-color: var(--warn);
  color: var(--warn);
}

.preview-note {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--e3);
  margin-top: var(--e4);
}
.preview-note a {
  border-style: solid;
  border-color: var(--accent);
  color: var(--accent);
  text-decoration: none;
  display: inline-block;
}

/* ---- Texto: frase llana delante, detalle técnico plegado ----
   Los textos de cada herramienta eran exactos pero técnicos ("heurísticas de patrones,
   typosquatting y homógrafos"). Quien abre la app con un SMS raro en la mano no necesita eso
   para decidir; quien sí quiere saber qué se comprueba lo tiene a un toque. No se ha quitado
   nada, solo se ha ordenado. */
.hint.lead {
  font-size: 15px;
  line-height: 1.5;
  color: var(--text);
  margin: 0 0 var(--e2);
}

.detalle {
  margin: 0 0 var(--e5);
  font-size: 13px;
}
.detalle > summary {
  cursor: pointer;
  color: var(--text-dim);
  font-size: 13px;
  padding: var(--e1) 0;
  list-style: none;
  display: inline-flex;
  align-items: center;
  gap: var(--e2);
  user-select: none;
}
.detalle > summary::-webkit-details-marker { display: none; }
.detalle > summary::before {
  content: "";
  width: 6px;
  height: 6px;
  border-right: 1.6px solid currentColor;
  border-bottom: 1.6px solid currentColor;
  transform: rotate(45deg) translate(-1px, -1px);
  transition: transform 0.18s ease;
}
.detalle[open] > summary::before { transform: rotate(-135deg) translate(-2px, -2px); }
.detalle > summary:hover { color: var(--text); }
.detalle > p {
  margin: var(--e1) 0 0;
  color: var(--text-dim);
  line-height: 1.55;
  border-left: 2px solid var(--border);
  padding-left: var(--e3);
}

/* La etiqueta del interruptor dice el efecto arriba y la letra pequeña la consecuencia. */
.toggle span { display: flex; flex-direction: column; gap: 2px; }
.toggle span strong { font-size: 14px; font-weight: 600; color: var(--text); }
.toggle span small { font-size: 12px; color: var(--text-dim); line-height: 1.35; }

/* Una tarjeta impar dejaba un hueco a su lado que parecía un fallo de carga. */
/* Una tarjeta impar dejaba un hueco a su lado que parecía un fallo de carga. Ocupando el
   ancho, la retícula cierra sola y además da sitio a que la descripción quepa en una línea. */
.tool-card.ancha {
  grid-column: 1 / -1;
  min-height: 0;
  flex-direction: row;
  align-items: center;
  gap: 0 var(--e3);
  padding: var(--e4);
  flex-wrap: wrap;
}
.tool-card.ancha .tool-icon { margin-bottom: 0; }
.tool-card.ancha .tool-label { flex-shrink: 0; }
.tool-card.ancha .tool-desc { font-size: 12.5px; flex: 1 1 100%; }
@media (min-width: 420px) {
  .tool-card.ancha .tool-desc { flex: 1 1 auto; text-align: right; }
}

/* El aviso de "solo offline" es una advertencia sobre el alcance del análisis, no un hallazgo
   sobre el enlace. Antes iba en amarillo intenso y pesaba tanto como el veredicto. */
.offline-notice {
  margin-top: var(--e1);
  border-color: var(--border);
  color: var(--text-dim);
  background: var(--bg);
}
.offline-notice strong { color: var(--text); }
.offline-notice .enable-net-btn {
  border-color: var(--accent);
  color: var(--accent);
}
