/* ==========================================================================
   MyRecon, motion layer
   Loaded after styles.css on every page. The site reads and works with this
   file missing, with JS off, and with prefers-reduced-motion set.

   Flat by rule (2026-09-25): no glows, no gradient lighting, no lit or
   animated outlines, no gradient text. Colour comes from the design tokens
   in styles.css as solid fills and 1px borders. Motion is kept to movement
   that carries meaning: the orbit, reveals, progress.

   Performance: only transform and opacity animate.
   ========================================================================== */

:root {
  --grid-line: rgba(74, 139, 247, 0.06);
}
:root[data-theme="light"] {
  --grid-line: rgba(37, 99, 235, 0.06);
}

/* ---------- Backdrop: a faint grid, fading out down the page ---------- */
body { position: relative; isolation: isolate; }
body::before {
  content: ""; position: fixed; inset: 0; z-index: -2; pointer-events: none;
  background-image:
    linear-gradient(var(--grid-line) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
  background-size: 44px 44px;
  -webkit-mask-image: linear-gradient(#000 0, #000 40%, transparent 90%);
          mask-image: linear-gradient(#000 0, #000 40%, transparent 90%);
}

/* Dot network canvas (drawn by fx.js). */
#fx-net {
  position: fixed; inset: 0; z-index: -1; pointer-events: none;
  width: 100vw; height: 100vh; opacity: 0.5;
}
:root[data-theme="light"] #fx-net { opacity: 0.35; }

/* Scroll progress along the top edge. */
#fx-progress {
  position: fixed; left: 0; top: 0; z-index: 300; height: 2px; width: 100%;
  transform-origin: 0 50%; transform: scaleX(0);
  background: var(--accent); pointer-events: none;
}

/* ---------- Nav ---------- */
.nav-links a { position: relative; }
.nav-links a::after {
  content: ""; position: absolute; left: 13px; right: 13px; bottom: 3px; height: 2px; border-radius: 2px;
  background: var(--accent);
  transform: scaleX(0); transform-origin: 0 50%; transition: transform 0.25s ease;
}
.nav-links a:hover::after, .nav-links a.active::after { transform: scaleX(1); }

/* ---------- Cards: lift on hover, nothing lit ---------- */
.feature, .step, .guide-card, .vs-card, .fx-card, #toolPanel { position: relative; }
.feature, .guide-card { transition: transform 0.25s ease, border-color 0.25s ease; }
.feature:hover, .guide-card:hover { border-color: var(--border-strong); }

/* ---------- Scroll reveal (classes added by fx.js, so no-JS shows all) ---------- */
.fx-reveal {
  opacity: 0; transform: translate3d(0, 18px, 0);
  transition: opacity 0.6s ease, transform 0.6s ease;
  transition-delay: var(--fx-delay, 0ms);
}
.fx-reveal.fx-in { opacity: 1; transform: none; }

/* Accent words in headings: solid colour, no gradient. */
.fx-grad { color: var(--accent-text, var(--accent)); }

@keyframes fx-spin { to { transform: rotate(360deg); } }
@keyframes fx-blink { 50% { opacity: 0; } }

/* ---------- Hero ---------- */
/* Not position:relative: app.js scrolls to #tool via offsetTop, which a
   positioned hero would turn into an offset from the hero, not the page. */
.hero { overflow: hidden; }
.eyebrow .dot { animation: none; }

/* Source marquee */
.fx-marquee {
  margin: 26px auto 0; max-width: 900px; overflow: hidden; position: relative;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
}
.fx-marquee-track { display: flex; gap: 10px; width: max-content; animation: fx-marquee 38s linear infinite; }
.fx-marquee:hover .fx-marquee-track { animation-play-state: paused; }
.fx-marquee .chip { font-family: var(--mono); font-size: 0.74rem; white-space: nowrap; }
.fx-marquee .chip::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--accent); }
@keyframes fx-marquee { to { transform: translateX(-50%); } }

/* ---------- Stat counters ---------- */
.fx-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 14px; }
.fx-stat {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 20px; text-align: left; overflow: hidden;
}
.fx-stat .n {
  font-family: var(--mono); font-size: clamp(1.7rem, 4vw, 2.3rem); font-weight: 700; line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.fx-stat .l { color: var(--text-dim); font-size: 0.86rem; margin-top: 6px; }
.fx-stat .bar { height: 3px; border-radius: 3px; margin-top: 14px; background: var(--surface-2); overflow: hidden; }
.fx-stat .bar span {
  display: block; height: 100%; transform-origin: 0 50%; transform: scaleX(0);
  background: var(--accent);
  transition: transform 1.4s ease .2s;
}
.fx-stat.fx-in .bar span { transform: scaleX(var(--fill, 1)); }

/* FAQ open animation */
.faq details[open] p { animation: fx-drop 0.3s ease; }
@keyframes fx-drop { from { opacity: 0; transform: translateY(-6px); } }

/* Phone mock rows appear one by one when scrolled in. */
.phone-mock.fx-in .phone-row { animation: fx-rowin 0.45s ease backwards; }
.phone-mock.fx-in .phone-row:nth-child(2) { animation-delay: .25s; }
.phone-mock.fx-in .phone-row:nth-child(3) { animation-delay: .5s; }
.phone-mock.fx-in .phone-row:nth-child(4) { animation-delay: .75s; }
.phone-mock.fx-in .phone-row:nth-child(5) { animation-delay: 1s; }
.phone-mock.fx-in .phone-row:nth-child(6) { animation-delay: 1.25s; }
.phone-mock.fx-in .phone-sum { animation: fx-rowin 0.45s 1.6s backwards; }
@keyframes fx-rowin { from { opacity: 0; transform: translateX(-12px); } }

/* ---------- Comparison pages (/vs/) ---------- */
.vs-hero { text-align: center; padding-top: 64px; padding-bottom: 26px; }
.vs-hero h1 { font-size: clamp(2rem, 5vw, 3.2rem); font-weight: 800; letter-spacing: -0.035em; line-height: 1.08; }
.vs-hero .lead { max-width: 660px; margin: 18px auto 0; color: var(--text-dim); font-size: 1.06rem; }
.vs-duel { display: flex; align-items: center; justify-content: center; gap: 18px; margin: 30px auto 0; flex-wrap: wrap; }
.vs-side {
  min-width: 200px; padding: 16px 22px; border-radius: 14px; border: 1px solid var(--border);
  background: var(--surface); font-weight: 700;
}
.vs-side small { display: block; font-weight: 500; font-size: 0.78rem; color: var(--text-mute); margin-top: 2px; }
.vs-side.us { border-color: var(--accent); }
.vs-badge {
  width: 52px; height: 52px; border-radius: 50%; display: grid; place-items: center;
  font-family: var(--mono); font-weight: 700; color: #fff; background: var(--accent-2);
}
.vs-verdict {
  border: 1px solid var(--border-strong); border-left: 3px solid var(--accent); border-radius: var(--radius);
  padding: 20px 22px; margin: 26px 0; background: var(--surface);
}
.vs-article .vs-verdict h2 { margin: 0 0 8px; font-size: 1.15rem; }
.vs-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 14px; margin: 18px 0; }
.vs-card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 20px; display: block; color: inherit;
  transition: transform 0.25s ease, border-color 0.25s ease;
}
a.vs-card:not(.btn), .prose a.vs-card:not(.btn) { color: var(--text); }
a.vs-card:hover { transform: translateY(-3px); border-color: var(--border-strong); }
.vs-card h3 { font-size: 1.05rem; margin-bottom: 6px; }
.vs-card p { color: var(--text-dim); font-size: 0.9rem; }
.vs-card .kind { font-family: var(--mono); font-size: 0.72rem; color: var(--accent-text, var(--accent)); text-transform: uppercase; letter-spacing: .08em; }
.vs-card .go { display: inline-block; margin-top: 12px; color: var(--accent-text, var(--accent)); font-weight: 600; font-size: 0.88rem; }
.vs-card .go::after { content: " →"; display: inline-block; transition: transform 0.2s; }
a.vs-card:hover .go::after { transform: translateX(4px); }

.vs-article { max-width: 880px; margin: 0 auto; padding-bottom: 40px; }
.vs-article h2 { font-size: clamp(1.3rem, 2.6vw, 1.7rem); font-weight: 800; letter-spacing: -0.02em; margin: 38px 0 12px; }
.vs-article h3 { font-size: 1.08rem; margin: 22px 0 8px; }
.vs-article p, .vs-article li { color: var(--text-dim); font-size: 1rem; line-height: 1.72; }
.vs-article p { margin: 0 0 14px; }
.vs-article ul { margin: 0 0 16px 20px; }
.vs-article li { margin: 6px 0; }
.vs-article strong { color: var(--text); }
.vs-article a:not(.btn):not(.vs-card) { color: var(--accent-text, var(--accent)); }
.vs-article code { font-family: var(--mono); font-size: 0.88em; background: var(--surface-2); padding: 1px 6px; border-radius: 5px; }

.vs-table-wrap { overflow-x: auto; margin: 16px 0 8px; -webkit-overflow-scrolling: touch; border-radius: var(--radius); border: 1px solid var(--border); }
.vs-table { border-collapse: collapse; width: 100%; min-width: 600px; font-size: 0.92rem; }
.vs-table th, .vs-table td { padding: 12px 14px; text-align: left; vertical-align: top; border-bottom: 1px solid var(--border); }
.vs-table thead th { background: var(--surface-2); color: var(--text); font-weight: 700; font-size: 0.82rem; text-transform: uppercase; letter-spacing: .06em; }
.vs-table tbody th { color: var(--text); font-weight: 600; white-space: nowrap; }
.vs-table td { color: var(--text-dim); background: var(--surface); }
.vs-table tbody tr:hover td { background: var(--surface-2); }
.vs-table tr:last-child th, .vs-table tr:last-child td { border-bottom: none; }
.vs-yes { color: var(--ok); font-weight: 600; }
.vs-no { color: var(--danger); font-weight: 600; }
.vs-mid { color: var(--warn); font-weight: 600; }
.vs-date { font-family: var(--mono); font-size: 0.78rem; color: var(--text-mute); }

.vs-cta {
  margin: 40px 0 0; padding: 28px; border-radius: var(--radius-lg); text-align: center;
  border: 1px solid var(--border); background: var(--surface);
}
.vs-cta h2 { margin-top: 0; }
.vs-cta p { max-width: 520px; margin: 8px auto 18px; }

/* ---------- Custom cursor ----------
   A real CSS cursor, drawn by the OS at pointer speed, so it never lags.
   Mouse devices only; text fields keep the I-beam. SVG attributes must use
   single quotes inside url("..."), or the whole declaration is dropped. */
@media (pointer: fine) {
  html, body { cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 32 32'%3E%3Cg fill='none' stroke-linecap='round'%3E%3Cg stroke='%23020617' stroke-width='4' opacity='.55'%3E%3Cpath d='M16 3v8M16 21v8M3 16h8M21 16h8'/%3E%3Ccircle cx='16' cy='16' r='6'/%3E%3C/g%3E%3Cg stroke='%234a8bf7' stroke-width='2'%3E%3Cpath d='M16 3v8M16 21v8M3 16h8M21 16h8'/%3E%3Ccircle cx='16' cy='16' r='6'/%3E%3C/g%3E%3C/g%3E%3Ccircle cx='16' cy='16' r='1.6' fill='%234a8bf7'/%3E%3C/svg%3E") 16 16, crosshair; }
  a, button, summary, label, select, [role="tab"], [role="button"], .tab, .chip, .pivot, .card-link { cursor: pointer; }
  input:not([type="checkbox"]):not([type="radio"]), textarea, [contenteditable="true"] { cursor: text; }
  button[disabled], .btn[disabled] { cursor: not-allowed; }
}

/* ---------- Reduced motion: keep the look, drop the movement ---------- */
@media (prefers-reduced-motion: reduce) {
  .fx-marquee-track { animation: none !important; flex-wrap: wrap; width: auto; justify-content: center; }
  .fx-marquee { -webkit-mask-image: none; mask-image: none; }
  .fx-reveal { opacity: 1; transform: none; transition: none; }
  #fx-net { display: none; }
}

@media print {
  body::before, #fx-net, #fx-progress { display: none !important; }
}

/* ==========================================================================
   Hero orbit: platforms circling a radar arm, marked as they are "found".
   Rings rotate as whole layers (one composited transform each); every icon
   counter-rotates by the same amount so it stays upright. Decorative, and
   paused by fx.js whenever the hero is off-screen.
   ========================================================================== */
.hero-grid { display: grid; grid-template-columns: 1fr; gap: 26px; align-items: center; }
.hero-copy { min-width: 0; }

@media (min-width: 1100px) {
  .hero-grid { grid-template-columns: minmax(0, 1.12fr) minmax(0, 0.88fr); gap: 34px; text-align: left; }
  .hero-copy .lead { margin-left: 0; }
}

.orbit {
  /* Absolute on purpose: --s is substituted into nested elements, where a
     percentage would resolve against the wrong box. */
  --s: 460px;
  --n: 42px;
  position: relative; width: var(--s); aspect-ratio: 1; margin: 0 auto;
  justify-self: center; contain: layout;
}
/* One thin radar arm, no lit wedge. */
.orbit-sweep {
  position: absolute; left: 50%; top: 50%; width: 47%; height: 1px; transform-origin: 0 50%;
  background: color-mix(in srgb, var(--accent) 55%, transparent);
  animation: fx-spin 6s linear infinite; will-change: transform;
}
.orbit-ring {
  --d: calc(var(--s) * var(--k));
  position: absolute; left: 50%; top: 50%; width: var(--d); height: var(--d);
  margin: calc(var(--d) / -2) 0 0 calc(var(--d) / -2);
  border-radius: 50%; border: 1px dashed var(--border-strong);
}
.orbit-ring.r1 { --k: .42; --dur: 34s; --dir: normal;  --rev: reverse; }
.orbit-ring.r2 { --k: .68; --dur: 52s; --dir: reverse; --rev: normal; border-style: solid; border-color: var(--border); }
.orbit-ring.r3 { --k: .94; --dur: 70s; --dir: normal;  --rev: reverse; }
.orbit-rot { position: absolute; inset: 0; animation: fx-spin var(--dur) linear infinite var(--dir); will-change: transform; }

.spoke {
  position: absolute; left: 50%; top: 50%; height: 1px; width: calc(var(--d) / 2);
  transform-origin: 0 50%; transform: rotate(var(--a));
  background: var(--border); opacity: 0; transition: opacity .3s;
}
.spoke.hit { opacity: 1; background: color-mix(in srgb, var(--c) 60%, var(--border)); }

.node {
  position: absolute; left: 50%; top: 50%; width: var(--n); height: var(--n);
  margin: calc(var(--n) / -2) 0 0 calc(var(--n) / -2);
  transform: rotate(var(--a)) translateX(calc(var(--d) / 2)) rotate(calc(-1 * var(--a)));
}
.node-in {
  position: relative; display: grid; place-items: center; width: 100%; height: 100%; border-radius: 50%;
  background: var(--surface); border: 1px solid var(--border-strong);
  color: var(--c);
  animation: fx-spin var(--dur) linear infinite var(--rev); will-change: transform;
  transition: border-color .3s, background .3s;
}
.node-in svg { width: 46%; height: 46%; fill: currentColor; transition: transform .3s ease; }
.node .tag {
  position: absolute; left: 50%; bottom: calc(100% + 6px); transform: translate(-50%, 4px);
  font: 700 .6rem/1 var(--mono); letter-spacing: .08em; padding: 4px 6px; border-radius: 5px; white-space: nowrap;
  color: #04121a; background: var(--ok);
  opacity: 0; transition: opacity .25s, transform .25s ease; pointer-events: none;
}
.node.hit .node-in { border-color: var(--c); background: color-mix(in srgb, var(--c) 14%, var(--surface)); }
.node.hit .node-in svg { transform: scale(1.12); }
.node.hit .tag { opacity: 1; transform: translate(-50%, 0); }

.orbit-core {
  position: absolute; left: 50%; top: 50%; width: 27%; aspect-ratio: 1; transform: translate(-50%, -50%);
  border-radius: 50%; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
  background: var(--surface); border: 1px solid var(--border-strong);
}
.orbit-core img { width: 32%; height: auto; }
.core-handle { font: 600 .74rem/1.1 var(--mono); color: var(--text); }
.core-count { font: 500 .64rem/1 var(--mono); color: var(--text-mute); }
.core-count b { color: var(--ok); }

.orbit.paused *, .orbit.paused *::before, .orbit.paused *::after { animation-play-state: paused !important; }

@media (min-width: 1100px) { .orbit { --s: 440px; --n: 42px; } }
@media (min-width: 1240px) { .orbit { --s: 490px; --n: 44px; } }
@media (max-width: 560px) {
  .orbit { --s: min(330px, calc(100vw - 56px)); --n: 34px; }
  .node .tag { font-size: .54rem; }
  .core-handle { font-size: .62rem; }
}
@media (prefers-reduced-motion: reduce) {
  .orbit *, .orbit *::before, .orbit *::after { animation: none !important; }
}

/* ==========================================================================
   Tool in the hero. The lookup is the product, so it sits above the fold on
   every screen size, beside the orbit on desktop and right under the
   headline on phones.
   ========================================================================== */
.hero { padding: 34px 0 20px; }
.hero h1 { font-size: clamp(2rem, 3.7vw, 3.05rem); }
.hero .eyebrow { margin-bottom: 16px; }
.hero .lead { margin-top: 12px; font-size: 1.02rem; max-width: 560px; }
.hero-tool { margin-top: 22px; text-align: left; }
@media (max-width: 1099px) {
  .hero-tool { max-width: 680px; margin-left: auto; margin-right: auto; }
  .hero-grid { gap: 8px; }
}
@media (max-width: 560px) {
  .hero { padding-top: 22px; }
  .hero .eyebrow { display: none; }
  .hero .lead { font-size: .95rem; }
  .hero-tool { margin-top: 16px; }
}

/* Tabs: a segmented control, the active segment filled. */
.hero-tool .tool-tabs { display: flex; width: 100%; margin-bottom: 10px; }
.hero-tool .tab { flex: 1 0 auto; justify-content: center; padding: 9px 13px; }
.hero-tool .tab[aria-selected="true"] { color: #fff; background: var(--accent-2); box-shadow: none; }
.hero-tool .tab[aria-selected="true"] .tab-ico { color: #fff; }

/* Panel */
.hero-tool .panel { padding: 20px 20px 18px; }
.hero-tool .panel-title {
  display: flex; align-items: center; gap: 9px;
  font: 600 .74rem/1 var(--mono); text-transform: uppercase; letter-spacing: .12em; color: var(--text-dim);
}
.pt-status { margin-left: auto; font-size: .68rem; color: var(--ok); }
.pt-status::before { content: "ready"; }
#toolPanel:has(#runBtn[disabled]) .pt-status { color: var(--accent-text, var(--accent)); }
#toolPanel:has(#runBtn[disabled]) .pt-status::before { content: "scanning"; }
.hero-tool .panel-sub { margin: 8px 0 14px; }

.hero-tool .input { font-family: var(--mono); font-size: 1rem; padding-top: 16px; padding-bottom: 16px; }
.hero-tool .input::placeholder { font-family: var(--font); }
.hero-tool #runBtn { padding-left: 26px; padding-right: 26px; }
.hero-tool #runBtn::after { content: "→"; font-weight: 700; transition: transform .2s; }
.hero-tool #runBtn:hover::after { transform: translateX(3px); }

/* While a lookup runs, a solid bar slides along the bottom of the input. */
.hero-tool .input-wrap { position: relative; overflow: hidden; border-radius: var(--radius-sm); }
#toolPanel:has(#runBtn[disabled]) .input-wrap::after {
  content: ""; position: absolute; left: 0; bottom: 0; width: 30%; height: 2px; pointer-events: none;
  background: var(--accent); animation: tool-bar 1.2s ease-in-out infinite;
}
@keyframes tool-bar { from { transform: translateX(-100%); } to { transform: translateX(340%); } }

.hero-tool .ex-chip { font-family: var(--mono); font-size: .76rem; }

.tool-foot { margin-top: 10px; font-size: .76rem; color: var(--text-mute); }
.tool-foot a { color: var(--accent-text, var(--accent)); }
.kbd {
  display: inline-block; font: 600 .68rem/1 var(--mono); padding: 3px 6px; border-radius: 5px;
  border: 1px solid var(--border-strong); border-bottom-width: 2px; color: var(--text-dim);
}
@media (max-width: 560px) {
  .hero-tool .field-row { flex-direction: column; }
  .hero-tool #runBtn { width: 100%; }
  .hero-tool .tab { flex: 0 0 auto; padding: 8px 11px; }
}
.results-section:has(.results:empty) { display: none; }
@media (prefers-reduced-motion: reduce) {
  #toolPanel:has(#runBtn[disabled]) .input-wrap::after { animation: none; }
}

/* ==========================================================================
   Running state and results. Styling only, so none of the result, export
   or password paths in app.js change.
   ========================================================================== */
.results-section { padding-top: 6px; }
.results { margin-top: 18px; }

/* The indeterminate bar moves by transform, not the old margin animation. */
.results .progress > i { animation: res-indet 1.3s ease-in-out infinite; }
@keyframes res-indet { from { transform: translateX(-100%); } to { transform: translateX(340%); } }
.results .progress.determinate > i { animation: none; }
.results .scan-pct { font-size: 1.4rem; }
.results .scan-meta #scanDetail { font-family: var(--mono); font-size: .78rem; color: var(--text-dim); }

/* Cards found during the sweep, shown under the progress while it runs. */
.live-found { margin-top: 18px; }
.live-found[hidden] { display: none; }
.live-found .section-label { display: flex; align-items: center; gap: 8px; }
.live-found .card { animation: rise .3s ease both; }

/* Result header */
.results .results-bar h2 { font-size: 1.08rem; }
.results .results-bar .hint { font-family: var(--mono); font-size: .76rem; padding: 3px 8px; border-radius: 6px; background: var(--surface-2); }

/* Stat tiles */
.results .stat { text-align: left; }

/* Profile cards: a confidence rail on the left edge, coloured by verdict. */
.results .card::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: var(--border-strong);
}
.results .card:has(.conf-high)::before { background: var(--ok); }
.results .card:has(.conf-medium)::before { background: var(--warn); }
.results .card:has(.conf-low)::before { background: var(--text-mute); }
.results .card:hover { box-shadow: none; }

/* Data tables */
.results .datarow:hover { background: var(--surface-2); }
.results .datarow .k { font-family: var(--mono); font-size: .78rem; text-transform: uppercase; letter-spacing: .04em; }

/* Verdict banners: a solid stripe down the side. */
.results .breach { position: relative; overflow: hidden; }
.results .breach::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 4px; background: var(--danger); }
.results .breach.clean::before { background: var(--ok); }
.results .breach.incomplete::before { background: var(--warn); }

/* "check breaches" beside a leaked address. app.js has always rendered
   .pivot-chip, but no stylesheet ever defined it, so it showed as the
   browser's default grey button. */
.pivot-chip {
  font: 600 .72rem/1 var(--mono); padding: 5px 10px; border-radius: 999px; cursor: pointer;
  color: var(--accent-text, var(--accent)); background: transparent;
  border: 1px solid var(--border-strong); transition: border-color .2s;
}
.pivot-chip:hover { border-color: var(--accent); }

@media (prefers-reduced-motion: reduce) {
  .results .progress > i, .live-found .card { animation: none !important; }
}
