/* ===== Web fonts — SF Pro (Display / Text / Icons) =====
   Per Apple's optical-size guidance: Display for ≥20px, Text for <20px.
   `font-display:swap` keeps first paint instant; the browser only fetches
   the weights actually requested by the cascade. */
@font-face{font-family:'SF Pro Display';font-style:normal;font-weight:400;font-display:swap;
  src:url('fonts/sf-pro-display_regular.woff2')  format('woff2')}
@font-face{font-family:'SF Pro Display';font-style:normal;font-weight:600;font-display:swap;
  src:url('fonts/sf-pro-display_semibold.woff2') format('woff2')}
@font-face{font-family:'SF Pro Display';font-style:normal;font-weight:700;font-display:swap;
  src:url('fonts/sf-pro-display_bold.woff2')     format('woff2')}
@font-face{font-family:'SF Pro Text';   font-style:normal;font-weight:300;font-display:swap;
  src:url('fonts/sf-pro-text_light.woff2')       format('woff2')}
@font-face{font-family:'SF Pro Text';   font-style:normal;font-weight:400;font-display:swap;
  src:url('fonts/sf-pro-text_regular.woff2')     format('woff2')}
@font-face{font-family:'SF Pro Text';   font-style:normal;font-weight:600;font-display:swap;
  src:url('fonts/sf-pro-text_semibold.woff2')    format('woff2')}
@font-face{font-family:'SF Pro Icons';  font-style:normal;font-weight:300;font-display:swap;
  src:url('fonts/sf-pro-icons_light.woff2')      format('woff2')}

:root{
  /* Apple HIG-aligned tracking presets. Negative on display sizes for a
     denser, refined feel; ~0 on body; positive on small uppercase tags. */
  --tracking-display: -0.022em;
  --tracking-title:   -0.014em;
  --tracking-body:    -0.005em;
  --tracking-small:    0;
  --tracking-tag:      0.04em;

  --ff-display:'SF Pro Display',-apple-system,BlinkMacSystemFont,"Segoe UI",system-ui,Inter,sans-serif;
  --ff-text:   'SF Pro Text',   -apple-system,BlinkMacSystemFont,"Segoe UI",system-ui,Inter,sans-serif;
  --ff-icons:  'SF Pro Icons',-apple-system,sans-serif;
  --ff-mono:   ui-monospace,"SF Mono",Menlo,Consolas,monospace;
}

/* ===== Reset & base ===== */
*,*::before,*::after{box-sizing:border-box}
html,body{margin:0;padding:0}
body{
  font-family:var(--ff-text);
  font-size:17px;
  font-weight:400;
  line-height:1.55;
  letter-spacing:var(--tracking-body);
  font-feature-settings:"ss01","cv11";       /* SF round-zero + alt-4 */
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
  text-rendering:optimizeLegibility;
  background:#0b0613;
  color:#e9e6f5;
  min-height:100vh;
  position:relative;
  overflow-x:hidden;
}
/* SF Pro Display for any heading typically rendered ≥20px. */
h1,h2{font-family:var(--ff-display);letter-spacing:var(--tracking-display);font-weight:600}
h3,h4{font-family:var(--ff-text);   letter-spacing:var(--tracking-title);  font-weight:600}
/* Tabular figures everywhere a number sits in a column or chip. */
b,code,pre,.hash-tag,.score-pill,.risk-pill,.tl-count,.ip-chip,table.kv,
.module-num,.module-meta,.foot-bottom{font-variant-numeric:tabular-nums}
/* Helper for SF symbol glyphs if/when needed. */
.sfi{font-family:var(--ff-icons);font-weight:300;font-style:normal}
body::before{
  content:"";
  position:fixed;inset:0;
  background:
    radial-gradient(900px 600px at 80% 10%, rgba(124,77,255,.20), transparent 60%),
    radial-gradient(700px 500px at 10% 90%, rgba(91,46,178,.18), transparent 60%);
  pointer-events:none;z-index:-1;
}
a{color:inherit;text-decoration:none}
button{font:inherit;cursor:pointer;border:0;background:transparent;color:inherit}
hr{border:0;border-top:1px solid #1c1530;margin:24px 0}
code{font-family:var(--ff-mono);color:#c9bef3;font-size:0.92em}
pre{
  font-family:var(--ff-mono);
  background:#100920;border:1px solid #1f1535;border-radius:10px;
  padding:14px;color:#cfc4f5;font-size:15px;line-height:1.55;
  overflow:auto;max-height:520px;margin:0;
  white-space:pre-wrap;word-break:break-word;
  letter-spacing:0;
}

/* ===== Promo ===== */
#promo{
  display:flex;align-items:center;justify-content:center;gap:10px;
  background:linear-gradient(90deg,#1a0e2e,#241441,#1a0e2e);
  border-bottom:1px solid #2a1a4a;
  padding:9px 14px;font-size:15.5px;font-weight:400;color:#d8cdf6;position:relative;
  letter-spacing:var(--tracking-body);
}
.promo-icon{color:#a17dff}
#promo b{color:#fff;font-weight:600}
#promo-close{
  position:absolute;right:14px;top:50%;transform:translateY(-50%);
  font-size:21px;color:#a59bcf;
}
#promo.hidden{display:none}

/* ===== Header ===== */
header{
  display:flex;align-items:center;justify-content:space-between;
  padding:16px 36px;
}
.brand{display:flex;align-items:center;gap:10px;font-weight:600}
.logo{
  width:28px;height:28px;border-radius:8px;
  background:linear-gradient(135deg,#7c4dff,#5b2eb2);
  display:grid;place-items:center;font-size:18px;
}
.brand-name{
  font-family:var(--ff-display);font-size:18px;font-weight:600;
  letter-spacing:var(--tracking-title);
}
nav{display:flex;gap:28px;font-size:16.5px;color:#b9b0d8}
nav a{transition:color .15s}
nav a:hover{color:#fff}
.header-right{display:flex;gap:14px;align-items:center}
.lang-btn{color:#b9b0d8;font-size:15.5px}
.login-btn{color:#cfc4f5;font-size:15.5px}
.signup-btn{
  background:linear-gradient(135deg,#7c4dff,#5b2eb2);
  color:#fff;padding:8px 18px;border-radius:10px;
  font-weight:600;font-size:15.5px;letter-spacing:var(--tracking-small);
}
.signup-btn:hover{filter:brightness(1.1)}

/* ===== Main ===== */
main{max-width:1100px;margin:30px auto 60px;padding:0 24px}
.badge-pill{
  display:inline-flex;align-items:center;gap:8px;
  background:rgba(124,77,255,.12);
  border:1px solid rgba(124,77,255,.4);
  border-radius:999px;padding:6px 14px;
  font-size:14.5px;font-weight:500;color:#bfb0f0;
  letter-spacing:var(--tracking-tag);text-transform:uppercase;
  margin-bottom:14px;
}

/* ===== Hero ===== */
.hero{text-align:center;margin:18px 0 30px}
.warn-banner{
  display:inline-block;
  background:rgba(255,89,89,.10);
  border:1px solid rgba(255,89,89,.40);
  color:#ffb6b6;border-radius:10px;
  padding:9px 16px;font-size:16px;margin:8px 0 14px;
}
.warn-banner.hidden{display:none}
.warn-banner a{color:#ffd1d1;text-decoration:underline}
.ip-title{
  font-family:var(--ff-display);
  font-size:35px;font-weight:600;margin:6px 0;
  letter-spacing:var(--tracking-display);
  display:flex;justify-content:center;align-items:center;gap:14px;flex-wrap:wrap;
}
.flag{font-size:23px;color:#a594d6}
.copy-btn{
  background:#16102a;border:1px solid #2a1d4d;
  border-radius:8px;padding:6px 12px;font-size:15px;color:#cfc4f5;
  font-weight:500;letter-spacing:var(--tracking-small);
  transition:background .15s,border-color .15s;
}
.copy-btn:hover{background:#1f1638;border-color:#3a2a6a}
.city-text{color:#9c92bf;font-size:16.5px;margin:4px 0 18px;font-weight:300}

/* Dual IPv4 / IPv6 chips */
.ip-dual{
  display:flex;justify-content:center;gap:10px;flex-wrap:wrap;
  margin:6px 0 4px;
}
.ip-chip{
  display:inline-flex;align-items:center;gap:8px;
  background:rgba(124,77,255,.08);
  border:1px solid #2a1d4d;border-radius:10px;
  padding:5px 12px;font-size:15.5px;
  font-family:var(--ff-mono);
  color:#e9e6f5;letter-spacing:0;
}
.ip-chip .ip-fam{
  font-family:var(--ff-text);
  font-size:12.5px;font-weight:600;letter-spacing:var(--tracking-tag);
  text-transform:uppercase;
  background:linear-gradient(135deg,#7c4dff,#5b2eb2);
  color:#fff;padding:2px 7px;border-radius:6px;
}
.ip-chip.empty{opacity:.4}
.ip-chip.empty .ip-fam{background:#3a3060}
.score-row{display:flex;align-items:center;justify-content:center;gap:18px;flex-wrap:wrap;margin-top:14px}
.score-pill{
  background:rgba(124,77,255,.15);border:1px solid rgba(124,77,255,.4);
  border-radius:999px;padding:6px 14px;font-size:14.5px;
  font-weight:500;letter-spacing:var(--tracking-small);
}
.score-pill b{color:#fff;margin-left:4px;font-weight:600}
.view-link{color:#b9b0d8;font-size:15px;text-decoration:underline;text-underline-offset:3px}

/* IP risk pill with green→red gradient */
.risk-pill{
  display:inline-flex;align-items:center;gap:8px;
  background:rgba(0,0,0,.35);
  border:1px solid var(--risk-color,#3a3060);
  border-radius:999px;padding:6px 14px;font-size:14.5px;
  font-weight:500;letter-spacing:var(--tracking-small);
  transition:border-color .25s, box-shadow .25s;
  box-shadow:0 0 0 0 var(--risk-color,transparent);
}
.risk-pill[data-state="loaded"]{
  box-shadow:0 0 14px -2px var(--risk-color,transparent);
}
.risk-pill b{
  color:var(--risk-color,#fff);
  margin-left:2px;font-weight:700;
  text-shadow:0 0 8px var(--risk-color,transparent);
}
.risk-bar{
  position:relative;width:84px;height:6px;
  background:#1f1535;border:1px solid #2a1d4d;
  border-radius:999px;overflow:hidden;
}
.risk-bar-fill{
  display:block;height:100%;width:0;
  background:linear-gradient(90deg,#22c55e 0%,#a3e635 25%,#facc15 50%,#fb923c 75%,#ef4444 100%);
  transition:width .6s ease;
  border-radius:999px;
}

/* ===== Big info card ===== */
.info-card{
  background:linear-gradient(180deg,#130a26,#0e0721);
  border:1px solid #1d1336;border-radius:18px;
  padding:28px 30px;margin-top:20px;
}
.info-row{display:grid;grid-template-columns:280px 1fr;gap:30px;align-items:start}
.info-head{display:flex;gap:12px}
.info-ico{
  width:36px;height:36px;border-radius:10px;
  background:rgba(124,77,255,.12);border:1px solid #2a1d4d;
  display:grid;place-items:center;flex-shrink:0;font-size:19px;
}
.info-head h3{margin:0;font-size:18px;font-weight:600;letter-spacing:var(--tracking-title)}
.info-head p{margin:4px 0 0;color:#8e85ad;font-size:15px;font-weight:300}
.info-grid{
  display:grid;grid-template-columns:1fr 1fr;gap:14px 36px;
}
.info-grid .lbl{color:#8e85ad;font-size:15.5px;font-weight:300;margin-right:8px}
.info-grid b{color:#fff;font-weight:500;font-size:15.5px;letter-spacing:0}
.leak{color:#ff7b7b;font-size:14px;margin-left:8px;font-weight:500}
.os-mismatch{color:#ff9b5a !important;cursor:help}
.os-mismatch::after{content:" ⚠";font-size:14px}

/* ===== Highlighted info-row (issue detected) ===== */
/* Highlighted info-row — single source of truth.
   Uses padding + negative margin so the highlight surrounds the row content
   with 14px breathing room without shifting layout. The pulse animation
   drives BOTH an inset 1px ring and an outer glow in one box-shadow stack
   (no more outline/outline-offset clipping against <hr> separators). */
.info-row--warn,
.info-row--danger{
  position:relative;
  border-radius:14px;
  padding:14px 16px;
  margin:-14px -16px;
  transition:filter .2s, background .2s;
}
.info-row--warn{
  background:linear-gradient(180deg,rgba(255,184,0,.055),rgba(255,184,0,.015));
  animation:info-pulse-warn 2.6s ease-in-out infinite;
}
.info-row--danger{
  background:linear-gradient(180deg,rgba(255,89,89,.065),rgba(255,89,89,.020));
  animation:info-pulse-danger 2.6s ease-in-out infinite;
}
.info-row--warn:hover{
  animation:info-pulse-warn-vivid 1.5s ease-in-out infinite;
  background:linear-gradient(180deg,rgba(255,184,0,.10),rgba(255,184,0,.03));
  filter:brightness(1.10);
}
.info-row--danger:hover{
  animation:info-pulse-danger-vivid 1.4s ease-in-out infinite;
  background:linear-gradient(180deg,rgba(255,89,89,.11),rgba(255,89,89,.03));
  filter:brightness(1.10);
}
@keyframes info-pulse-warn{
  0%,100%{box-shadow:inset 0 0 0 1px rgba(255,184,0,.40),0 0 14px -4px rgba(255,184,0,.20)}
  50%    {box-shadow:inset 0 0 0 1px rgba(255,184,0,.70),0 0 30px -2px rgba(255,184,0,.42)}
}
@keyframes info-pulse-warn-vivid{
  0%,100%{box-shadow:inset 0 0 0 1.5px rgba(255,184,0,.65),0 0 26px -2px rgba(255,184,0,.48)}
  50%    {box-shadow:inset 0 0 0 1.5px rgba(255,184,0,.95),0 0 48px  0   rgba(255,184,0,.72)}
}
@keyframes info-pulse-danger{
  0%,100%{box-shadow:inset 0 0 0 1px rgba(255,89,89,.45),0 0 14px -4px rgba(255,89,89,.22)}
  50%    {box-shadow:inset 0 0 0 1px rgba(255,89,89,.75),0 0 30px -2px rgba(255,89,89,.46)}
}
@keyframes info-pulse-danger-vivid{
  0%,100%{box-shadow:inset 0 0 0 1.5px rgba(255,89,89,.70),0 0 26px -2px rgba(255,89,89,.52)}
  50%    {box-shadow:inset 0 0 0 1.5px rgba(255,89,89,1),  0 0 48px  0   rgba(255,89,89,.78)}
}
/* Alert badge injected next to the row heading */
.row-alert-tag{
  display:inline-flex;align-items:center;gap:4px;
  font-size:13.5px;font-weight:600;
  letter-spacing:var(--tracking-tag);text-transform:uppercase;
  background:rgba(255,184,0,.12);
  border:1px solid rgba(255,184,0,.38);
  border-radius:6px;padding:2px 8px;color:#ffc56b;
  margin-left:8px;vertical-align:middle;cursor:help;
  font-family:var(--ff-text);
}
.row-alert-tag--danger{
  background:rgba(255,89,89,.12);
  border-color:rgba(255,89,89,.38);
  color:#ff9b9b;
}

/* "View diff" toggle button next to the alert badge */
.row-diff-btn{
  display:inline-flex;align-items:center;gap:5px;
  font-size:14px;font-weight:500;
  font-family:var(--ff-text);letter-spacing:var(--tracking-small);
  background:rgba(124,77,255,.10);
  border:1px solid rgba(124,77,255,.40);
  border-radius:6px;padding:3px 9px;
  color:#cfc4f5;margin-left:6px;vertical-align:middle;
  cursor:pointer;
  transition:background .15s,border-color .15s;
}
.row-diff-btn:hover{
  background:rgba(124,77,255,.20);
  border-color:rgba(124,77,255,.60);
  color:#fff;
}
.row-diff-btn .chev{
  display:inline-block;font-size:12px;
  transition:transform .2s ease;
  color:#a594d6;
}
.row-diff-btn.open .chev{transform:rotate(90deg)}

/* Expandable diff panel — Detected (wrong) vs Expected (correct) */
.row-diff-panel{
  display:none;
  grid-column:1 / -1;
  margin-top:18px;
  padding:14px 16px;
  background:rgba(0,0,0,.28);
  border:1px dashed rgba(124,77,255,.35);
  border-radius:10px;
}
.row-diff-panel.open{display:block;animation:diff-slide .25s ease-out}
@keyframes diff-slide{
  from{opacity:0;transform:translateY(-4px)}
  to  {opacity:1;transform:translateY(0)}
}
.diff-issue{padding:10px 0}
.diff-issue + .diff-issue{border-top:1px dashed #2a1d4d;margin-top:4px}
.diff-issue-title{
  font-family:var(--ff-text);font-size:15px;font-weight:600;
  color:#ffc56b;margin:0 0 8px;
  letter-spacing:var(--tracking-title);
}
.diff-issue.danger .diff-issue-title{color:#ff9b9b}
.diff-cols{
  display:grid;grid-template-columns:1fr auto 1fr;
  gap:12px;align-items:stretch;
}
.diff-col{
  background:#100920;border:1px solid #1f1535;
  border-radius:8px;padding:9px 12px;
  display:flex;flex-direction:column;gap:4px;
  min-width:0;
}
.diff-col--wrong{
  background:rgba(255,89,89,.06);
  border-color:rgba(255,89,89,.32);
}
.diff-col--right{
  background:rgba(91,227,164,.06);
  border-color:rgba(91,227,164,.32);
}
.diff-col-label{
  font-family:var(--ff-text);
  font-size:12.5px;font-weight:600;
  letter-spacing:var(--tracking-tag);text-transform:uppercase;
  color:#8e85ad;
}
.diff-col--wrong .diff-col-label{color:#ff9b9b}
.diff-col--right .diff-col-label{color:#7be3b1}
.diff-col-value{
  font-family:var(--ff-mono);
  color:#e9e6f5;font-size:15.5px;
  word-break:break-all;letter-spacing:0;
  font-variant-numeric:tabular-nums;
}
.diff-arrow{
  font-family:var(--ff-mono);
  font-size:23px;font-weight:700;
  color:#ff7b7b;
  display:grid;place-items:center;
  padding:0 4px;
}
@media(max-width:600px){
  .diff-cols{grid-template-columns:1fr}
  .diff-arrow{transform:rotate(90deg);padding:6px 0}
}

/* ===== Inline details inside diagnostic cards (e.g. canvas signature) ===== */
.card .card-details{
  margin-top:6px;padding-top:10px;
  border-top:1px dashed #2a1d4d;
  font-size:14.5px;font-variant-numeric:tabular-nums;
}
.card .card-details table{width:100%;border-collapse:collapse}
.card .card-details td{padding:4px 0;vertical-align:top}
.card .card-details .cd-k{
  width:88px;color:#8e85ad;font-weight:300;
  letter-spacing:var(--tracking-small);padding-right:10px;
}
.card .card-details .cd-v{color:#e9e6f5;font-weight:500;letter-spacing:0;word-break:break-all}
.card .card-details .cd-mono{font-family:var(--ff-mono);color:#c9bef3}
.card .card-details .cd-upper{text-transform:uppercase}
.card .card-details .cd-error{color:#ff7b7b;font-weight:400}

/* ===== Diagnostics ===== */
.diag{margin-top:60px;text-align:center}
.diag h2{font-family:var(--ff-display);font-size:29px;font-weight:600;margin:6px 0;letter-spacing:var(--tracking-display)}
.diag-sub{color:#8e85ad;font-size:16px;font-weight:300;line-height:1.6;margin:0 0 28px}
.cards-grid{
  display:grid;grid-template-columns:repeat(3,1fr);gap:16px;
  text-align:left;
  align-items:start;            /* cards take natural height — one expanding doesn't stretch the row */
}
.card{
  background:linear-gradient(180deg,#130a26,#0e0721);
  border:1px solid #1d1336;border-radius:14px;
  padding:18px;display:flex;flex-direction:column;gap:10px;
  transition:border-color .15s, box-shadow .15s;
  min-width:0;                  /* allow long content to wrap within the grid cell */
}
.card.ok{
  border-color:rgba(91,227,164,.40);
  box-shadow:0 0 18px -6px rgba(91,227,164,.20);
}
/* Verified badge fills the bottom slot — matches the visual weight of
   the "View troubles" button on issue cards so OK + issue cards line up. */
.card.ok::after{
  content:"✓ Verified";
  order:99;margin-top:auto;
  display:block;text-align:center;
  padding:9px;border-radius:10px;
  font-size:13px;font-weight:600;
  letter-spacing:var(--tracking-tag);text-transform:uppercase;
  color:#7be3b1;
  background:rgba(91,227,164,.08);
  border:1px solid rgba(91,227,164,.32);
}
.card.has-issues{
  border-color:rgba(255,184,0,.45);
  box-shadow:0 0 18px -6px rgba(255,184,0,.18);
}
.card.has-errors{
  border-color:rgba(255,89,89,.45);
  box-shadow:0 0 18px -6px rgba(255,89,89,.25);
}
.card-ico{
  width:30px;height:30px;border-radius:8px;
  background:rgba(124,77,255,.10);
  border:1px solid #2a1d4d;
  display:grid;place-items:center;font-size:14px;color:#bfb0f0;
  flex-shrink:0;
}
.card h4{
  margin:0;font-size:16.5px;font-weight:600;letter-spacing:var(--tracking-title);
  word-break:break-word;
}
.card-status{
  margin:0;font-size:14.5px;color:#8e85ad;font-weight:400;
  word-break:break-word;overflow-wrap:anywhere;
  display:flex;align-items:center;gap:6px;
}
.card-status::before{flex-shrink:0}
.card.ok .card-status{color:#7be3b1}
.card.ok .card-status::before{content:"✓";color:#5be3a4;font-size:13px;font-weight:700}
.card.has-issues .card-status{color:#ffc56b}
.card.has-issues .card-status::before{content:"●";color:#ffb800;font-size:10px}
.card.has-errors .card-status{color:#ff9b9b}
.card.has-errors .card-status::before{content:"●";color:#ff5a5a;font-size:10px}
.card-btn{
  background:#16102a;border:1px solid #2a1d4d;border-radius:10px;
  padding:9px;font-size:15px;font-weight:500;color:#cfc4f5;
  letter-spacing:var(--tracking-small);transition:.15s;
  order:99;                     /* always render last regardless of DOM insertion order */
  margin-top:auto;
}
.card.has-issues .card-btn,.card.has-errors .card-btn{
  background:linear-gradient(135deg,#7c4dff,#5b2eb2);border-color:transparent;color:#fff;
}
.card-btn:hover{filter:brightness(1.15)}

/* Expandable troubles list — bounded height with internal scroll
   so a card with 30+ issues doesn't balloon and wreck row layout. */
.card-troubles{
  order:50;
  margin-top:4px;padding:10px 8px 4px;
  border-top:1px dashed #2a1d4d;
  font-size:13px;color:#cfc4f5;line-height:1.55;
  display:none;
  max-height:260px;overflow-y:auto;overflow-x:hidden;
  scrollbar-width:thin;scrollbar-color:#3a2a6a transparent;
}
.card-troubles::-webkit-scrollbar{width:6px}
.card-troubles::-webkit-scrollbar-track{background:transparent}
.card-troubles::-webkit-scrollbar-thumb{background:#3a2a6a;border-radius:3px}
.card-troubles::-webkit-scrollbar-thumb:hover{background:#4d3a8a}
.card-troubles.show{display:block}
.card-troubles ul{margin:0;padding:0;list-style:none}
.card-troubles li{
  margin:5px 0;padding:6px 9px 6px 10px;
  background:rgba(124,77,255,.04);
  border-left:2px solid #2a1d4d;
  border-radius:4px;
  word-break:break-word;overflow-wrap:anywhere;
  display:flex;gap:8px;align-items:flex-start;
}
.card-troubles li::first-letter{font-size:14px;line-height:1}
.card.has-issues .card-troubles li{
  background:rgba(255,184,0,.05);
  border-left-color:rgba(255,184,0,.45);
}
.card.has-errors .card-troubles li{
  background:rgba(255,89,89,.05);
  border-left-color:rgba(255,89,89,.45);
}

/* ===== WebRTC ===== */
.webrtc-block{margin-top:50px;padding:0 4px}
.webrtc-head{display:flex;justify-content:space-between;align-items:center;margin-bottom:8px}
.webrtc-head h3{margin:0;font-family:var(--ff-display);font-size:21px;font-weight:600;letter-spacing:var(--tracking-title)}
.restart-btn{
  background:#16102a;border:1px solid #2a1d4d;border-radius:8px;
  padding:6px 12px;font-size:15px;font-weight:500;color:#cfc4f5;
  letter-spacing:var(--tracking-small);transition:background .15s,border-color .15s;
}
.restart-btn:hover{background:#1f1638;border-color:#3a2a6a}
.ok{color:#5be3a4}
.bad{color:#ff7b7b}
.webrtc-grid{
  display:grid;grid-template-columns:1fr 1fr;gap:20px;margin:10px 0 14px;
  font-size:15px;color:#cfc4f5;line-height:1.7;
}
.rtc-cand-head{margin:18px 0 6px;font-size:16px;font-weight:500}
.muted-tag{font-size:14px;font-weight:300;color:#8e85ad;margin-left:6px;letter-spacing:0}

/* Prominent WebRTC leak risk banner */
.leak-banner{
  margin:14px 0;
  padding:14px 18px;
  border-radius:12px;
  background:linear-gradient(90deg, rgba(255,89,89,.12), rgba(255,123,123,.06));
  border:1px solid rgba(255,89,89,.45);
  color:#ffb6b6;
  font-size:16px;
  display:flex;align-items:flex-start;gap:12px;
  box-shadow:0 0 24px -4px rgba(255,89,89,.25);
  animation:pulse-leak 2.4s ease-in-out infinite;
}
.leak-banner.hidden{display:none}
.leak-banner .leak-ico{
  font-size:25px;line-height:1;flex-shrink:0;
  filter:drop-shadow(0 0 6px #ff5a5a);
}
.leak-banner h4{
  margin:0 0 4px;color:#ffd1d1;font-size:17px;font-weight:600;
  letter-spacing:var(--tracking-title);
}
.leak-banner p{margin:0;line-height:1.55;color:#ffb6b6;font-weight:400}
.leak-banner code{
  background:rgba(255,89,89,.15);
  border:1px solid rgba(255,89,89,.35);
  padding:1px 6px;border-radius:4px;
  color:#ffd1d1;font-size:15px;
}
.leak-banner.ok{
  background:linear-gradient(90deg, rgba(91,227,164,.10), rgba(91,227,164,.04));
  border-color:rgba(91,227,164,.45);
  color:#a8e6c9;
  box-shadow:none;animation:none;
}
.leak-banner.ok h4{color:#bef0d6}
.leak-banner.ok p{color:#a8e6c9}
.leak-banner.ok .leak-ico{filter:drop-shadow(0 0 6px #5be3a4)}
@keyframes pulse-leak{
  0%,100%{box-shadow:0 0 24px -4px rgba(255,89,89,.25)}
  50%   {box-shadow:0 0 36px -2px rgba(255,89,89,.45)}
}

/* Highlight modulation when fields just got updated */
@keyframes flash-update{
  0%   {background:rgba(124,77,255,.35)}
  100% {background:transparent}
}
.just-updated{animation:flash-update 1.6s ease-out}
.webrtc-cands{margin-top:14px}
.webrtc-cands summary{
  cursor:pointer;color:#8e85ad;font-size:15px;
  padding:6px 0;user-select:none;
}
.webrtc-cands summary:hover{color:#cfc4f5}
.webrtc-cands[open] summary{color:#bfb0f0;margin-bottom:6px}

/* ===== Modules ===== */
.modules{margin-top:60px}
.modules h2{font-family:var(--ff-display);font-size:27px;font-weight:600;margin:6px 0;letter-spacing:var(--tracking-display)}
.module{
  background:linear-gradient(180deg,#130a26,#0e0721);
  border:1px solid #1d1336;border-radius:14px;
  margin:10px 0;overflow:hidden;
}
.module-head{
  display:flex;justify-content:space-between;align-items:center;
  padding:14px 18px;cursor:pointer;user-select:none;
  transition:background .15s;
}
.module-head:hover{background:rgba(124,77,255,.05)}
.module-title{display:flex;gap:10px;align-items:center}
.module-num{
  width:24px;height:24px;border-radius:6px;
  background:rgba(124,77,255,.12);border:1px solid #2a1d4d;
  display:grid;place-items:center;font-size:14px;font-weight:500;color:#bfb0f0;
}
.module-title h4{margin:0;font-size:16.5px;font-weight:600;letter-spacing:var(--tracking-title)}
.module-title p{margin:0;font-size:14px;font-weight:300;color:#8e85ad}
.module-meta{display:flex;gap:10px;align-items:center;font-size:14px;color:#8e85ad}
.hash-tag{
  font-family:var(--ff-mono);
  background:rgba(124,77,255,.10);
  border:1px solid #2a1d4d;border-radius:6px;
  padding:2px 8px;color:#bfb0f0;letter-spacing:0;
}
.lied-tag{
  background:rgba(255,89,89,.10);border:1px solid rgba(255,89,89,.4);
  border-radius:6px;padding:2px 6px;color:#ff7b7b;
  font-size:13px;font-weight:600;letter-spacing:var(--tracking-tag);text-transform:uppercase;
  cursor:help;
}
.lied-tag--warn{
  background:rgba(255,184,0,.10);border-color:rgba(255,184,0,.4);color:#ffc56b;
}
.clean-tag{
  background:rgba(91,227,164,.10);border:1px solid rgba(91,227,164,.40);
  border-radius:6px;padding:2px 8px;color:#7be3b1;
  font-size:13px;font-weight:600;letter-spacing:var(--tracking-tag);text-transform:uppercase;
}
/* Module body field highlights — red row when a function has lies attached,
   green when clean. Applied to <tr> inside the kv summary table. */
.module-row--lied td{
  background:rgba(255,89,89,.06);
  border-left:3px solid rgba(255,89,89,.55);
}
.module-row--clean td{
  background:rgba(91,227,164,.04);
  border-left:3px solid rgba(91,227,164,.40);
}
.module-row--lied td:first-child,
.module-row--clean td:first-child{
  padding-left:8px !important;
}
/* "Diff check" toggle button injected next to the LIES tag in module-meta.
   Clicking expands a sibling .module-diff-panel between the head and body so
   the user can compare each lie against its canonical/expected value without
   opening the raw-JSON section. */
.module-diff-btn{
  display:inline-flex;align-items:center;gap:5px;
  font-size:13px;font-weight:600;
  font-family:var(--ff-text);
  letter-spacing:var(--tracking-tag);text-transform:uppercase;
  background:rgba(124,77,255,.12);
  border:1px solid rgba(124,77,255,.45);
  border-radius:6px;padding:3px 9px;
  color:#cfc4f5;cursor:pointer;
  transition:background .15s,border-color .15s,color .15s;
}
.module-diff-btn:hover{
  background:rgba(124,77,255,.22);
  border-color:rgba(124,77,255,.65);
  color:#fff;
}
.module-diff-btn .chev{
  display:inline-block;font-size:11px;
  transition:transform .2s ease;color:#a594d6;
}
.module-diff-btn.open .chev{transform:rotate(90deg)}

.module-diff-panel{
  display:none;
  margin:0 18px 14px;
  padding:14px 16px;
  background:rgba(0,0,0,.32);
  border:1px dashed rgba(124,77,255,.35);
  border-radius:10px;
  max-height:560px;overflow-y:auto;
}
.module-diff-panel.open{display:block;animation:diff-slide .25s ease-out}

/* "How to fix" — collapsible block under each diff-issue. Lists every
   platform/browser combo (Chromium / Gecko / WebKit + Windows/macOS/iOS/
   Android/Linux) with numbered fix steps. Expanded only on user click. */
.diff-fix{
  margin-top:12px;
  padding-top:10px;
  border-top:1px dashed #2a1d4d;
}
.diff-fix > summary{
  cursor:pointer;
  color:#bfb0f0;
  font-family:var(--ff-text);
  font-size:13.5px;font-weight:700;
  letter-spacing:var(--tracking-tag);text-transform:uppercase;
  user-select:none;
  list-style:none;
  padding:4px 0;
}
.diff-fix > summary::-webkit-details-marker{display:none}
.diff-fix > summary::before{
  content:'▶';
  display:inline-block;
  margin-right:8px;
  font-size:11px;
  color:#a594d6;
  transition:transform .2s;
}
.diff-fix[open] > summary::before{transform:rotate(90deg)}
.diff-fix > summary:hover{color:#fff}

.diff-fix-why{
  margin:10px 0 12px;
  font-size:14px;
  color:#b0a3d8;
  line-height:1.6;
  font-style:italic;
  border-left:2px solid rgba(124,77,255,.35);
  padding:4px 0 4px 12px;
}

.diff-fix-platforms{
  display:grid;
  gap:10px;
  margin-top:8px;
}
.diff-fix-platform{
  background:rgba(91,227,164,.04);
  border:1px solid rgba(91,227,164,.20);
  border-radius:8px;
  padding:10px 12px;
}
.diff-fix-platform-head{
  display:flex;
  flex-wrap:wrap;
  gap:6px 8px;
  align-items:center;
  margin-bottom:8px;
}
.diff-fix-engine{
  font-family:var(--ff-text);
  font-size:13.5px;font-weight:700;
  letter-spacing:var(--tracking-tag);text-transform:uppercase;
  color:#7be3b1;
}
.diff-fix-browsers{
  font-family:var(--ff-mono);
  font-size:12.5px;
  color:#cfc4f5;
  background:rgba(124,77,255,.12);
  border:1px solid #2a1d4d;
  border-radius:5px;
  padding:1px 6px;
}
.diff-fix-os{
  font-family:var(--ff-mono);
  font-size:12.5px;
  color:#8e85ad;
  background:rgba(0,0,0,.25);
  border:1px solid #1f1535;
  border-radius:5px;
  padding:1px 6px;
}
.diff-fix-steps{
  margin:0;
  padding-left:22px;
  font-family:var(--ff-text);
  font-size:14px;
  color:#d8d2ec;
  line-height:1.6;
}
.diff-fix-steps li{
  margin:5px 0;
}
.diff-fix-steps li::marker{
  color:#7be3b1;
  font-weight:600;
}
.diff-fix-steps code{
  font-family:var(--ff-mono);
  background:rgba(124,77,255,.10);
  border:1px solid #2a1d4d;
  border-radius:4px;
  padding:0 4px;
  font-size:13px;
  color:#cfc4f5;
}
@media(max-width:600px){
  .diff-fix-platform-head{flex-direction:column;align-items:flex-start;gap:4px}
}

/* Module-level highlights — red border/glow if any issues map here, green otherwise */
.module.module--has-lies{
  border-color:rgba(255,89,89,.40);
  box-shadow:0 0 16px -5px rgba(255,89,89,.20);
}
.module.module--has-lies .module-head{background:rgba(255,89,89,.03)}
.module.module--has-lies .module-head:hover{background:rgba(255,89,89,.06)}
.module.module--clean{
  border-color:rgba(91,227,164,.30);
}
.module.module--clean .module-head:hover{background:rgba(91,227,164,.04)}
.chevron{transition:transform .15s}
.module.open .chevron{transform:rotate(90deg)}
.module-body{display:none;padding:0 18px 16px}
.module.open .module-body{display:block}

.module-summary{margin-bottom:10px}
table.kv{width:100%;border-collapse:collapse;font-size:15px}
table.kv td{padding:6px 8px;border-bottom:1px dashed #1f1535;vertical-align:top;line-height:1.5}
table.kv td:first-child{color:#8e85ad;width:200px;font-weight:400;white-space:nowrap}
table.kv td:last-child{color:#e9e6f5;word-break:break-all}
table.kv code{color:#cfc4f5;background:transparent;font-size:14px;font-family:var(--ff-mono)}
table.kv .full-hash{color:#bfb0f0;font-size:13px}

.module-raw{margin-top:10px}
.module-raw summary{
  cursor:pointer;color:#8e85ad;font-size:15px;
  padding:6px 0;user-select:none;
}
.module-raw summary:hover{color:#cfc4f5}
.module-raw[open] summary{color:#bfb0f0;margin-bottom:6px}
.module-raw pre{max-height:300px}

.full-json{margin-top:30px;position:relative}
.full-json h3{margin:6px 0 10px;display:inline-block;margin-right:14px;font-family:var(--ff-display);font-size:21px;font-weight:600;letter-spacing:var(--tracking-title)}
.full-json .copy-btn{margin-right:8px}
.full-json pre{max-height:600px}

/* ===== CTA ===== */
.cta{
  margin-top:60px;display:flex;justify-content:space-between;align-items:center;
  padding:18px 8px;
}
.cta h2{
  font-family:var(--ff-display);font-size:51px;margin:0;color:#5b3aab;
  font-weight:700;letter-spacing:-0.03em;
}
.cta-btn{
  background:linear-gradient(135deg,#7c4dff,#5b2eb2);
  color:#fff;padding:14px 24px;border-radius:12px;
  font-weight:600;font-size:16px;letter-spacing:var(--tracking-small);
  transition:filter .15s,transform .15s;
}
.cta-btn:hover{filter:brightness(1.1);transform:translateY(-1px)}

/* ===== Footer ===== */
footer{
  border-top:1px solid #1d1336;
  padding:36px 36px 24px;color:#8e85ad;font-size:15px;font-weight:300;
  position:relative;overflow:hidden;
}
.foot-grid{
  display:grid;grid-template-columns:repeat(4,1fr) auto;gap:30px;max-width:1100px;margin:0 auto;
}
.foot-grid h5{
  margin:0 0 10px;color:#cfc4f5;
  font-size:14px;font-weight:600;letter-spacing:var(--tracking-tag);text-transform:uppercase;
}
.foot-grid a{display:block;margin:6px 0;color:#8e85ad;font-weight:400;transition:color .15s}
.foot-grid a:hover{color:#fff}
.socials{display:flex;gap:14px;align-items:flex-start}
.socials a{font-size:21px;margin-top:6px}
.foot-bottom{max-width:1100px;margin:24px auto 0;padding-top:14px;border-top:1px solid #1d1336;font-size:14px;font-weight:300;letter-spacing:0}
.foot-watermark{
  position:absolute;right:-30px;bottom:-40px;
  font-family:var(--ff-display);
  font-size:163px;font-weight:700;color:#150a2a;
  letter-spacing:-0.06em;line-height:1;pointer-events:none;
}

/* ===== Responsive ===== */
@media(max-width:900px){
  .info-row{grid-template-columns:1fr}
  .info-grid{grid-template-columns:1fr}
  .cards-grid{grid-template-columns:1fr 1fr}
  .webrtc-grid{grid-template-columns:1fr}
  .foot-grid{grid-template-columns:1fr 1fr}
  nav{display:none}
}
@media(max-width:600px){
  .cards-grid{grid-template-columns:1fr}
  header{padding:14px 18px;flex-wrap:wrap;gap:10px}
  .ip-title{font-size:27px}
  .diag h2,.modules h2{font-size:23px}
  .cta{flex-direction:column;gap:14px;text-align:center}
  .cta h2{font-size:37px;letter-spacing:-0.025em}
  .foot-watermark{font-size:99px}
}

/* ===== Skeleton / running progressbar =====
 * Inline indeterminate progress bar used as placeholder for any data field
 * before its real value arrives. Looks like an iOS-style running bar: a
 * narrow highlight slides across a faint track. Size variants mirror the
 * typographic scale (sm = inline tag, default = body value, md = chip,
 * lg = subtitle, xl = hero IP). Block variants fill larger empty areas. */
.skel{
  display:inline-block;position:relative;
  min-width:80px;height:10px;border-radius:6px;
  background:rgba(124,77,255,.08);
  border:1px solid rgba(124,77,255,.18);
  overflow:hidden;vertical-align:middle;
  letter-spacing:0;color:transparent;
}
.skel::after{
  content:"";position:absolute;top:0;left:-40%;
  width:40%;height:100%;
  background:linear-gradient(90deg,
    transparent 0%,
    rgba(170,130,255,.55) 45%,
    rgba(170,130,255,.85) 50%,
    rgba(170,130,255,.55) 55%,
    transparent 100%);
  animation:skel-run 1.25s cubic-bezier(.4,0,.2,1) infinite;
}
.skel-sm{min-width:48px;height:8px;border-radius:5px}
.skel-md{min-width:110px;height:12px;border-radius:6px}
.skel-lg{min-width:160px;height:14px;border-radius:7px}
.skel-xl{min-width:220px;height:22px;border-radius:8px}
.skel-block{
  display:block;width:100%;min-width:0;height:64px;border-radius:10px;
  margin:6px 0;
}
.skel-block-tall{
  display:block;width:100%;min-width:0;height:240px;border-radius:14px;
  margin:10px 0;
}
@keyframes skel-run{
  0%   {left:-40%}
  100% {left:100%}
}
@media (prefers-reduced-motion:reduce){
  .skel::after{animation:none;left:30%;opacity:.6}
}
/* Skel inside a code/mono container should still feel inline-aligned. */
code .skel,pre .skel{vertical-align:baseline}

/* ============================================================
   Unified pulse-glow animation system for highlight states
   ------------------------------------------------------------
   Mirrors the rhythm of .leak-banner's pulse so every red/amber/green
   highlight breathes consistently across the page. On :hover each element
   swaps to a `*-vivid` variant — wider glow, brighter color, faster cadence —
   for a "siêu xịn" focus effect.
   ============================================================ */
@keyframes pulse-danger{
  0%,100%{box-shadow:0 0 14px -4px rgba(255,89,89,.22)}
  50%   {box-shadow:0 0 28px -2px rgba(255,89,89,.42)}
}
@keyframes pulse-danger-vivid{
  0%,100%{box-shadow:0 0 26px -2px rgba(255,89,89,.45),0 0 0 1px rgba(255,89,89,.55)}
  50%   {box-shadow:0 0 48px  0   rgba(255,89,89,.70),0 0 0 1px rgba(255,89,89,.90)}
}
@keyframes pulse-warn{
  0%,100%{box-shadow:0 0 14px -4px rgba(255,184,0,.20)}
  50%   {box-shadow:0 0 28px -2px rgba(255,184,0,.40)}
}
@keyframes pulse-warn-vivid{
  0%,100%{box-shadow:0 0 26px -2px rgba(255,184,0,.45),0 0 0 1px rgba(255,184,0,.55)}
  50%   {box-shadow:0 0 48px  0   rgba(255,184,0,.70),0 0 0 1px rgba(255,184,0,.90)}
}
@keyframes pulse-success{
  0%,100%{box-shadow:0 0 12px -4px rgba(91,227,164,.18)}
  50%   {box-shadow:0 0 24px -2px rgba(91,227,164,.34)}
}
@keyframes pulse-success-vivid{
  0%,100%{box-shadow:0 0 24px -2px rgba(91,227,164,.42),0 0 0 1px rgba(91,227,164,.55)}
  50%   {box-shadow:0 0 44px  0   rgba(91,227,164,.62),0 0 0 1px rgba(91,227,164,.85)}
}

/* --- DANGER surfaces (red) --- */
.card.has-errors,
.module.module--has-lies,
.diff-col--wrong,
.row-alert-tag--danger,
.lied-tag.from-issues:not(.lied-tag--warn){
  animation:pulse-danger 2.6s ease-in-out infinite;
  transition:filter .2s, transform .2s;
}
.card.has-errors:hover,
.module.module--has-lies:hover,
.diff-col--wrong:hover,
.row-alert-tag--danger:hover,
.lied-tag.from-issues:not(.lied-tag--warn):hover{
  animation:pulse-danger-vivid 1.4s ease-in-out infinite;
  filter:brightness(1.15);
}

/* --- WARN surfaces (amber) --- */
.card.has-issues,
.lied-tag.from-issues.lied-tag--warn,
.row-alert-tag:not(.row-alert-tag--danger){
  animation:pulse-warn 2.6s ease-in-out infinite;
  transition:filter .2s, transform .2s;
}
.card.has-issues:hover,
.lied-tag.from-issues.lied-tag--warn:hover,
.row-alert-tag:not(.row-alert-tag--danger):hover{
  animation:pulse-warn-vivid 1.4s ease-in-out infinite;
  filter:brightness(1.15);
}

/* --- SUCCESS surfaces (green) --- */
.card.ok,
.module.module--clean,
.clean-tag.from-issues,
.diff-col--right{
  animation:pulse-success 3.2s ease-in-out infinite;
  transition:filter .2s, transform .2s;
}
.card.ok:hover,
.module.module--clean:hover,
.clean-tag.from-issues:hover,
.diff-col--right:hover{
  animation:pulse-success-vivid 1.6s ease-in-out infinite;
  filter:brightness(1.18);
}

/* --- Module summary kv rows pulse on hover only (avoid 25 nested loops) --- */
.module-row--lied{transition:background .2s, box-shadow .25s}
.module-row--lied:hover td{
  background:rgba(255,89,89,.12);
  box-shadow:inset 4px 0 0 0 rgba(255,89,89,.85), 0 0 12px -2px rgba(255,89,89,.35);
}
.module-row--clean{transition:background .2s, box-shadow .25s}
.module-row--clean:hover td{
  background:rgba(91,227,164,.10);
  box-shadow:inset 4px 0 0 0 rgba(91,227,164,.75), 0 0 10px -2px rgba(91,227,164,.30);
}

/* (info-row uses its own info-pulse-* keyframes that combine inset ring +
   outer glow — defined near the .info-row--warn rule. Don't override here.) */

/* --- Leak banner already pulses; align to the unified red rhythm --- */
.leak-banner:not(.ok){animation:pulse-danger 2.4s ease-in-out infinite}
.leak-banner:not(.ok):hover{animation:pulse-danger-vivid 1.4s ease-in-out infinite;filter:brightness(1.15)}

/* Respect reduced-motion preferences */
@media (prefers-reduced-motion: reduce){
  .card.has-errors,.card.has-issues,.card.ok,
  .module.module--has-lies,.module.module--clean,
  .diff-col--wrong,.diff-col--right,
  .row-alert-tag,.lied-tag.from-issues,.clean-tag.from-issues,
  .info-row--warn,.info-row--danger,.leak-banner{animation:none !important}
}

/* ===== Misc ===== */
.hidden{display:none !important}
::selection{background:#5b2eb2;color:#fff}
::-webkit-scrollbar{width:10px;height:10px}
::-webkit-scrollbar-track{background:#0b0613}
::-webkit-scrollbar-thumb{background:#2a1d4d;border-radius:6px}
::-webkit-scrollbar-thumb:hover{background:#3d2a6e}
