theseus/popover.html

133 lines
8.6 KiB
HTML
Raw Permalink Normal View History

<!doctype html>
<html><head><meta charset="utf-8">
<style>
:root { color-scheme: light dark; font-family: system-ui, sans-serif; }
html, body { margin: 0; background: transparent; }
.card { display: flex; flex-direction: column; background: #1c222c;
border: 1px solid #ffffff26; border-radius: 8px; box-shadow: 0 12px 34px #000c; overflow: hidden; color: #e7eaf1; }
.close { position: absolute; top: 6px; right: 8px; border: none; background: transparent; color: #8b98a9;
cursor: pointer; font-size: 13px; border-radius: 5px; padding: 1px 6px; z-index: 2; }
.close:hover { background: #ffffff14; color: #fff; }
/* Firefox-style hero: big lock/shield + status + host */
.hero { display: flex; gap: 12px; padding: 15px 16px 13px; align-items: flex-start; }
.hero .ico { flex: none; width: 26px; height: 26px; display: grid; place-items: center; }
.hero .ico svg { width: 22px; height: 22px; fill: none; stroke-width: 1.4; stroke-linecap: round; stroke-linejoin: round; }
.hero .ico .kh { fill: #1c222c; stroke: none; }
.hero.secure .ico svg { stroke: #4fd1a5; } .hero.secure .ico .bdy { fill: #4fd1a5; stroke: none; }
.hero.warn .ico svg { stroke: #f6ad55; }
.hero.neutral .ico svg { stroke: #9aa6b6; } .hero.neutral .ico .bdy { fill: #9aa6b6; stroke: none; }
.hero .status { font-weight: 600; font-size: 13.5px; }
.hero .host { color: #b9c2d0; font-size: 12px; margin-top: 2px; font-family: ui-monospace, monospace; word-break: break-all; }
.hero .sub { color: #8b98a9; font-size: 12px; margin-top: 7px; line-height: 1.5; }
.details { border-top: 1px solid #ffffff12; padding: 11px 16px 13px; display: grid; grid-template-columns: auto 1fr; gap: 7px 14px; font-size: 12px; }
.details .k { color: #7f8aa0; } .details .v { color: #e7eaf1; }
.details .v code { font-family: ui-monospace, monospace; color: #bfeae4; word-break: break-all; }
/* Collision switcher — only shown when the host could be BCNR OR ICANN */
.switcher { border-top: 1px solid #ffffff12; padding: 10px 16px 12px; font-size: 12px; }
.switcher .title { color: #7f8aa0; margin-bottom: 6px; }
.switcher .row { display: flex; gap: 6px; }
.switcher button { flex: 1; background: transparent; color: #e7eaf1; border: 1px solid #ffffff26; border-radius: 6px; padding: 6px 8px; cursor: pointer; font-size: 12px; }
.switcher button:hover { background: #ffffff10; }
.switcher button.active { background: #f5c51820; border-color: #f5c518; color: #f5c518; cursor: default; }
.switcher button.active.icann { background: #4c9eff20; border-color: #4c9eff; color: #4c9eff; }
.switcher .rem { display: flex; gap: 10px; margin-top: 8px; color: #7f8aa0; }
.switcher .rem label { display: flex; gap: 4px; align-items: center; cursor: pointer; }
.switcher .rem input { accent-color: #f5c518; }
/* light theme (placed last so it wins over the dark base rules) */
@media (prefers-color-scheme: light) {
.card { background: #ffffff; border-color: rgba(0,0,0,.15); color: #1a1f28; }
.close { color: #697280; } .close:hover { background: rgba(0,0,0,.06); }
.hero .host { color: #3c4453; } .hero .sub { color: #697280; }
.details { border-top-color: rgba(0,0,0,.10); } .details .k { color: #7b8494; } .details .v { color: #1a1f28; }
.details .v code { color: #0a7d73; }
.hero.neutral .ico svg { stroke: #697280; } .hero.neutral .ico .bdy { fill: #697280; }
.hero .ico .kh { fill: #ffffff; }
.switcher { border-top-color: rgba(0,0,0,.10); }
.switcher .title, .switcher .rem { color: #7b8494; }
.switcher button { color: #1a1f28; border-color: rgba(0,0,0,.15); }
.switcher button:hover { background: rgba(0,0,0,.05); }
.switcher button.active { background: #f5c51830; }
.switcher button.active.icann { background: #4c9eff30; }
}
</style></head>
<body>
<div class="card">
<button class="close" id="x" title="Close"></button>
<div class="hero" id="hero">
<div class="ico" id="ico"></div>
<div><div class="status" id="status"></div><div class="host" id="host"></div><div class="sub" id="sub"></div></div>
</div>
<div class="details" id="details"></div>
<div class="switcher" id="switcher" style="display:none">
<div class="title">Open this name with</div>
<div class="row">
<button id="sw-bcnr" data-choice="bcnr">⛓ BCDN</button>
<button id="sw-icann" data-choice="icann" class="icann">🌐 ICANN</button>
</div>
<div class="rem">
<label><input type="radio" name="sw-rem" value="no" checked> Just this once</label>
<label><input type="radio" name="sw-rem" value="name"> Remember for <b id="sw-host"></b></label>
<label><input type="radio" name="sw-rem" value="tld"> All <b id="sw-tld"></b></label>
</div>
</div>
</div>
<script>
const $ = (id) => document.getElementById(id);
$("x").onclick = () => window.pop.close();
const esc = (s) => String(s || "").replace(/</g, "&lt;");
const LOCK = `<svg viewBox="0 0 24 24"><path class="shk" fill="none" d="M8 10.5 V8 a4 4 0 0 1 8 0 V10.5"/><rect class="bdy" x="5.5" y="10.5" width="13" height="9" rx="2.4"/><circle class="kh" cx="12" cy="15" r="1.4"/></svg>`;
const WARN = `<svg viewBox="0 0 24 24"><path d="M12 3 L22 20 H2 Z"/><path d="M12 9 V14 M12 17 v.4"/></svg>`;
const GLOBE = `<svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="M3 12 h18 M12 3 a14 14 0 0 1 0 18 a14 14 0 0 1 0 -18"/></svg>`;
window.pop.onData((d) => {
const hero = $("hero");
let cls = "hero secure", ico = LOCK, status = "Connection secure", sub = "", details = "";
const row = (k, v) => `<span class="k">${k}</span><span class="v">${v}</span>`;
$("host").textContent = (d && d.host) || "";
if (!d || d.kind === "home") {
cls = "hero neutral"; ico = GLOBE; status = "Theseus"; $("host").textContent = "";
sub = "The decentralized-web navigator. It resolves BCDN names straight from the blockchain.";
} else if (d.kind === "resolving") {
cls = "hero neutral"; ico = GLOBE; status = "Resolving…"; sub = "Looking this name up on the Bitcoin Cash chain.";
} else if (d.kind === "nxdomain") {
cls = "hero warn"; ico = WARN; status = "Not registered"; sub = "This name is not registered on BCDN (the on-chain registry).";
} else if (d.kind === "error") {
cls = "hero warn"; ico = WARN; status = "Resolution error"; sub = esc(d.error || "The name could not be resolved.");
} else if (d.kind === "web") {
cls = "hero neutral"; ico = LOCK; status = "Connection"; sub = "A standard web page, resolved through ICANN DNS.";
details = row("Registry", "ICANN");
} else { // ok — a resolved BCNR name
status = "Connection secure";
sub = "Served over an encrypted connection from the <b>decentralized web</b> — no host, no registrar, no certificate authority.";
details = row("Served from", esc(d.source) || "chain")
+ row("Registry", "BCDN — Bitcoin Cash Domain Names")
+ (d.records && d.records.length ? row("Records", `<code>${esc(d.records.join(", "))}</code>`) : "")
+ (d.dns && d.dns.length ? row("Signed DNS", `<code>${esc(d.dns.join(", "))}</code>`) : "")
+ (d.category ? row("Certificate", `<code>${esc(String(d.category).slice(0, 20))}…</code>`) : "");
}
hero.className = cls; $("ico").innerHTML = ico; $("status").textContent = status; $("sub").innerHTML = sub;
$("details").innerHTML = details; $("details").style.display = details ? "grid" : "none";
// ---- collision switcher: only visible when this host is a collision candidate
// (loaded via BCNR or ICANN under a non-BCNR-native TLD) so flipping is meaningful.
const sw = $("switcher"), isCand = d && d.host && d.tld && (d.kind === "ok" || d.kind === "web") && !d.bcnrNativeTld;
if (isCand) {
const active = d.kind === "ok" ? "bcnr" : "icann";
$("sw-bcnr").classList.toggle("active", active === "bcnr");
$("sw-icann").classList.toggle("active", active === "icann");
$("sw-host").textContent = d.host;
$("sw-tld").textContent = "." + d.tld;
sw.style.display = "block";
} else { sw.style.display = "none"; }
requestAnimationFrame(() => { try { window.pop.resize(document.querySelector(".card").offsetHeight); } catch (e) {} });
});
// Live switcher — click the OTHER registry to flip the tab; the active one is a no-op.
for (const id of ["sw-bcnr", "sw-icann"]) $(id).onclick = (e) => {
const b = e.currentTarget; if (b.classList.contains("active")) return;
const rem = document.querySelector('input[name="sw-rem"]:checked')?.value || "no";
window.pop.switchTo(b.dataset.choice, rem);
window.pop.close();
};
</script>
</body></html>