/* search.css — the search-intelligence surface: search-first home (/), service
   search results (/search), and the entity detail pages (/host/:ip, /asn/:asn,
   /prefix/:cidr). Loaded only on those pages (mirrors the per-page proxies.css
   pattern). One visual language across all of them: a kind eyebrow + title
   header, a spec-sheet meta panel, and bordered "definitive" section panels with
   accent-tick headers. Token-driven, so it tracks the active accent + theme.
   gmicloud flat: 0px radius, hairline borders, Geist Mono labels, solid accent. */

/* ─────────────────────────────────────────────────────────────
   HOME — search-first landing (/)
   A vertically-centered fold (brand + smart search box + example
   chips + a thin live stat line) over a faint 3D globe backdrop,
   with the monochrome partners marquee pinned to the bottom.
   ───────────────────────────────────────────────────────────── */
.home {
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  min-height: calc(100svh - var(--topbar-h, 57px));
}
.home-fold {
  position: relative;
  z-index: 1;
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: 1.35rem;
  padding: 3rem 1.25rem 3rem;
}
.home-brand {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin: 0;
}
.home-wordmark {
  color: var(--accent);
}
.home-wordmark svg {
  height: clamp(48px, 11vw, 96px);
  width: auto;
  display: block;
}
.home-tagline {
  font-family: var(--font-mono);
  font-size: clamp(0.85rem, 2vw, 1rem);
  letter-spacing: 0.02em;
  color: var(--fg-dim);
  margin: 0 0 0.4rem;
}

/* staged entrance — brand, tagline, search, try-row rise in sequence on the
   first visit to a path this session (motion.js adds .no-entrance on repeat
   views, same convention as the other heroes). Gated on html.js so no-JS
   clients render everything immediately. .home-stats is excluded: it has its
   own data-pending fade tied to the live fetch. */
.js:not(.no-entrance) .home-fold > :not(.home-stats) {
  opacity: 0;
  transform: translateY(16px);
  animation: home-rise 0.65s cubic-bezier(0.2, 0.7, 0.2, 1) forwards;
}
.js:not(.no-entrance) .home-fold > :nth-child(1) { animation-delay: 0.05s; }
.js:not(.no-entrance) .home-fold > :nth-child(2) { animation-delay: 0.14s; }
.js:not(.no-entrance) .home-fold > :nth-child(3) { animation-delay: 0.23s; }
.js:not(.no-entrance) .home-fold > :nth-child(4) { animation-delay: 0.32s; }
/* the partners band eases in last, opacity-only (its track is already moving) */
.js:not(.no-entrance) .home > .partners-section {
  opacity: 0;
  animation: home-fade 0.9s ease 0.5s forwards;
}
@keyframes home-rise {
  to { opacity: 1; transform: translateY(0); }
}
@keyframes home-fade {
  to { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .js:not(.no-entrance) .home-fold > :not(.home-stats),
  .js:not(.no-entrance) .home > .partners-section {
    opacity: 1;
    transform: none;
    animation: none;
  }
}

/* big smart search box — reuses .lookup-row / .lookup-input-wrap / .lookup-input
   from app.css, scaled up for the hero. */
.home-search {
  width: 100%;
  max-width: 680px;
  margin: 0 auto;
}
.home-search .lookup-row { max-width: none; }
.home-search .lookup-input-wrap { padding-left: 18px; }
.home-search .lookup-prompt { font-size: 1rem; }
.home-search .lookup-input {
  font-size: 1.05rem;
  padding: 0.6rem 1rem;
}
.home-search-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--accent-2);
  color: var(--accent-ink);
  border: 1px solid var(--accent-2);
  padding: 0 1.5rem;
  cursor: pointer;
  transition: background 120ms, border-color 120ms, transform 120ms;
}
.home-search-btn:hover { background: var(--accent); border-color: var(--accent); }
.home-search-btn:active { transform: translateY(1px); }
.home-search-btn svg { width: 20px; height: 20px; display: block; }

/* "/" keyboard affordance inside the input (home.js focuses on / or Ctrl+K).
   Fades out once the box is focused or has text; hidden entirely on touch
   and narrow viewports where a hardware keyboard is unlikely. */
.home-kbd {
  flex: 0 0 auto;
  margin-right: 0.7rem;
  font-size: 0.7rem;
  line-height: 1;
  color: var(--fg-mute);
  border: 1px solid var(--border);
  padding: 0.3rem 0.55rem;
  pointer-events: none;
  user-select: none;
  transition: opacity 160ms ease;
}
.home-search .lookup-input-wrap:focus-within .home-kbd,
.home-search .lookup-input:not(:placeholder-shown) ~ .home-kbd { opacity: 0; }
@media (pointer: coarse), (max-width: 720px) {
  .home-kbd { display: none; }
}

/* one-click clear button inside the search input; only rendered when there's a
   query. Resets to the empty match-all browse at /search. */
.srch-clear {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.6rem;
  height: 1.6rem;
  margin: 0 0.4rem 0 0.2rem;
  font-size: 1.25rem;
  line-height: 1;
  color: var(--fg-mute);
  text-decoration: none;
  border-radius: 0;
  transition: color 120ms, background 120ms;
}
.srch-clear:hover { color: var(--fg); background: var(--bg-soft); }

/* subtle shine that travels around the search-bar border — a rotating conic
   "comet" masked down to a thin ring on the box edge. */
@property --home-search-ang {
  syntax: "<angle>";
  inherits: false;
  initial-value: 0deg;
}
.home-search, .srch-bar { position: relative; }
.home-search::before,
.srch-bar::before {
  content: "";
  position: absolute;
  inset: 0;
  padding: 1.5px;            /* ring thickness */
  pointer-events: none;
  z-index: 3;
  opacity: 0.85;
  background: conic-gradient(from var(--home-search-ang),
    transparent 0deg 248deg,
    color-mix(in srgb, var(--accent) 50%, transparent) 300deg,
    var(--accent) 336deg,
    #ffffff 350deg,
    var(--accent) 356deg,
    transparent 360deg);
  filter: drop-shadow(0 0 2px var(--accent-edge));
  /* keep only the padding-box ring; punch out the interior */
  -webkit-mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  animation: home-search-spin 4.5s linear infinite;
}
@keyframes home-search-spin {
  to { --home-search-ang: 360deg; }
}
/* focused box: the comet brightens and its halo widens — the ring visibly
   responds to the user's attention without restarting its orbit. */
.home-search::before,
.srch-bar::before { transition: opacity 200ms ease, filter 200ms ease; }
.home-search:focus-within::before,
.srch-bar:focus-within::before {
  opacity: 1;
  filter: drop-shadow(0 0 5px var(--accent-edge));
}
@media (prefers-reduced-motion: reduce) {
  .home-search::before, .srch-bar::before { animation: none; }
}

/* try-row / hint crossfade slot. While the box is empty the example chips
   show; as soon as it has text, home.js swaps in a hint declaring what Enter
   opens (host / network / prefix report, or a service search). The hint is
   absolutely positioned over the chip row so nothing below ever shifts. */
.home-tryline {
  position: relative;
  width: 100%;
  display: flex;
  justify-content: center;
}
.home-tryline .home-examples {
  transition: opacity 180ms ease, transform 180ms ease;
}
.home-tryline.is-hinting .home-examples {
  opacity: 0;
  transform: translateY(-5px);
  pointer-events: none;
}
.home-hint {
  position: absolute;
  inset: 0;
  margin: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  color: var(--fg-dim);
  opacity: 0;
  transform: translateY(5px);
  pointer-events: none;
  transition: opacity 200ms ease, transform 200ms ease;
}
.home-tryline.is-hinting .home-hint { opacity: 1; transform: translateY(0); }
.home-hint kbd {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  line-height: 1;
  color: var(--accent);
  border: 1px solid var(--accent-edge);
  background: var(--accent-soft);
  padding: 0.22rem 0.45rem;
}
.home-hint-kind { color: var(--fg); }
.home-hint-sep { color: var(--fg-mute); }
.home-hint-q { color: var(--accent); }
@media (prefers-reduced-motion: reduce) {
  .home-tryline .home-examples, .home-hint { transition: none; transform: none; }
}

/* example query chips (mix of entity + filter queries) */
.home-examples {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
  justify-content: center;
  align-items: center;
  max-width: 720px;
}
.home-examples .lbl {
  color: var(--fg-mute);
  font-family: var(--font-mono);
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.home-chip {
  border: 1px solid var(--border);
  padding: 0.26rem 0.6rem;
  color: var(--fg-dim);
  text-decoration: none;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  cursor: pointer;
  background: transparent;
  transition: border-color 140ms, color 140ms, background 140ms,
    transform 140ms cubic-bezier(0.2, 0.7, 0.2, 1);
}
.home-chip:hover {
  border-color: var(--accent-edge);
  color: var(--fg);
  background: var(--accent-soft);
  transform: translateY(-1px);
}
.home-chip:active { transform: translateY(0); transition-duration: 60ms; }
@media (prefers-reduced-motion: reduce) {
  .home-chip, .home-chip:hover, .home-chip:active { transform: none; transition: none; }
}
.home-syntax {
  margin-left: 0.25rem;
  padding: 0.26rem 0.7rem;
  border: 1px solid var(--accent-edge);
  color: var(--accent);
  background: var(--accent-soft);
  text-decoration: none;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  transition: border-color 120ms, color 120ms, background 120ms;
}
.home-syntax:hover { border-color: var(--accent); color: var(--accent-ink); background: var(--accent); }

/* thin live stat line (filled from /api/v1/stats by app.js; hidden until ready) */
.home-stats {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.1rem;
  justify-content: center;
  align-items: baseline;
  color: var(--fg-mute);
  font-family: var(--font-mono);
  font-size: 0.78rem;
  margin-top: 0.4rem;
  min-height: 1.1rem;
  opacity: 1;
  transition: opacity 400ms ease;
}
.home-stats[data-pending="true"] { opacity: 0; }
@media (prefers-reduced-motion: reduce) {
  .home-stats { transition: none; }
}
.home-stat b {
  color: var(--fg);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  /* inline-block + right-align lets JS reserve each number's final width so the
     labels don't shift sideways while the count-up adds digits. */
  display: inline-block;
  text-align: right;
}
/* pulsing accent square marking the stat line as live (app.js refreshes the
   numbers every 30s). Square, not a dot — 0px radius everywhere. */
.home-live {
  width: 6px;
  height: 6px;
  background: var(--accent);
  align-self: center;
  animation: home-live-pulse 2.6s ease-in-out infinite;
}
@keyframes home-live-pulse {
  0%, 100% { opacity: 0.35; }
  50%      { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .home-live { animation: none; opacity: 0.7; }
}

/* faint 3D globe backdrop, masked to fade at the edges, never interactive */
.home-globe {
  position: absolute;
  inset: 0;
  z-index: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  /* Hidden until initHomeGlobe reveals it (on the globe's first painted frame).
     Safe to gate on JS: the globe canvas is JS-rendered, so nothing shows here
     without JS regardless. */
  opacity: 0;
  transition: opacity 2600ms ease;
  will-change: opacity;
}
/* Reveal to full opacity (see initHomeGlobe / hero3d:ready). */
.home-globe.globe-in { opacity: 1; }
/* Repeat views this session: keep the reveal but make it quick. */
.home-globe.globe-quick { transition-duration: 600ms; }
/* Reduced motion: appear at once, no fade. */
.home-globe.globe-instant { transition: none; }
.home-globe .hero3d-mount {
  width: min(760px, 94vw);
  height: min(760px, 94vw);
  min-height: 0;
  opacity: 0.32;
  /* Fade must reach past the satellite shell: the scene shows ~±3.68 world
     units and satellites orbit at 2.9 (~79% of the half-frame) — ending the
     fade at 72% cropped them (and their relay packets) out entirely. */
  -webkit-mask-image: radial-gradient(circle at 50% 50%, #000 36%, transparent 88%);
  mask-image: radial-gradient(circle at 50% 50%, #000 36%, transparent 88%);
}
:root[data-theme="light"] .home-globe .hero3d-mount { opacity: 0.22; }
/* On phones the globe is smaller and more easily lost — let it sit a touch
   stronger, and widen it so it fills the fold. */
@media (max-width: 768px) {
  .home-globe .hero3d-mount { width: min(760px, 116vw); height: min(760px, 116vw); opacity: 0.42; }
}
@media (prefers-reduced-motion: reduce) {
  .home-globe .hero3d-mount { opacity: 0.18; }
}

/* partners marquee pinned to the bottom of the fold. Marquee mechanics
   (.partners-marquee / .partners-track / .partner-logo + the infinite-scroll
   keyframe) live in app.css; here we just place + frame the band on the home. */
.home > .partners-section {
  position: relative;
  z-index: 1;
  flex: 0 0 auto;
}
/* quiet mono caption naming what the logo band is */
.partners-eyebrow {
  margin: 0 0 16px;
  text-align: center;
  font-family: var(--font-mono);
  font-size: 0.62rem;
  font-weight: 500;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--fg-mute);
}

/* ═════════════════════════════════════════════════════════════
   SHARED DETAIL CHROME
   Used by /host, /asn, /prefix and the /search results header so
   every entity surface reads as one product. Three building blocks:
     · .host-head   — kind eyebrow + big mono title + subtitle
     · .ent-panel   — the spec sheet (label → value rows)
     · .sec         — a "definitive" bordered section panel
   ═════════════════════════════════════════════════════════════ */
.host-wrap { max-width: 1080px; margin: 0 auto; padding: 2rem 1.25rem 5rem; }

/* back link */
.host-back {
  display: inline-flex; align-items: center; gap: 0.35rem;
  color: var(--fg-mute); text-decoration: none; font-size: 0.78rem;
  font-family: var(--font-mono); letter-spacing: 0.02em; transition: color 120ms;
}
.host-back:hover { color: var(--fg); }

/* entity header — big mono title with the kind badge inline to its right */
.host-head { margin: 1.15rem 0 0; }
.host-id { display: flex; align-items: baseline; gap: 0.55rem 0.8rem; flex-wrap: wrap; }
.host-kind {
  font-family: var(--font-mono); font-size: 0.6rem; font-weight: 500;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--accent);
  border: 1px solid var(--accent-edge); background: var(--accent-soft);
  padding: 0.24rem 0.55rem; line-height: 1; white-space: nowrap;
}
.host-ip {
  font-size: clamp(1.7rem, 4.2vw, 2.35rem); line-height: 1.08; margin: 0;
  font-family: var(--font-mono); font-weight: 500; letter-spacing: -0.01em;
  word-break: break-all;
}
.host-rdns { color: var(--fg-dim); font-family: var(--font-mono); font-size: 0.9rem; word-break: break-all; }

/* header stat strip — the entity's headline figures as bordered tiles below the
   title, giving the detail pages an at-a-glance summary before the spec panel.
   A hairline grid that reflows from 4-up to 2-up on narrow viewports. */
.host-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 0; margin: 1.3rem 0 0;
  border: 1px solid var(--border); background: var(--bg-elev);
}
.hstat {
  position: relative; padding: 0.85rem 1.05rem;
  border-left: 1px solid var(--border-soft);
}
.hstat:first-child { border-left: 0; }
/* accent hairline that grows across the top of each tile on the whole strip's
   hover — quiet life without being noisy */
.hstat::before {
  content: ""; position: absolute; left: 0; right: 0; top: -1px; height: 2px;
  background: var(--accent); transform: scaleX(0); transform-origin: left;
  transition: transform 260ms cubic-bezier(0.2,0.7,0.2,1);
}
.host-stats:hover .hstat::before { transform: scaleX(1); }
.host-stats:hover .hstat:nth-child(2)::before { transition-delay: 40ms; }
.host-stats:hover .hstat:nth-child(3)::before { transition-delay: 80ms; }
.host-stats:hover .hstat:nth-child(4)::before { transition-delay: 120ms; }
.hs-v {
  display: block; font-family: var(--font-mono); font-weight: 500;
  font-size: 1.5rem; line-height: 1.1; color: var(--fg);
  font-variant-numeric: tabular-nums; letter-spacing: -0.01em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.hs-v.hs-accent { color: var(--accent); }
.hs-v .hs-flag { margin-right: 0.3rem; vertical-align: -1px; }
.hs-unit { font-size: 0.85rem; color: var(--fg-mute); font-weight: 400; margin-left: 0.05rem; }
.hs-l {
  display: block; margin-top: 0.28rem;
  font-family: var(--font-mono); font-size: 0.6rem; font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.11em; color: var(--fg-mute);
}
@media (prefers-reduced-motion: reduce) { .hstat::before { transition: none; } }
@media (max-width: 560px) {
  .host-stats { grid-template-columns: repeat(2, 1fr); }
  .hstat:nth-child(odd) { border-left: 0; }
  .hstat:nth-child(n+3) { border-top: 1px solid var(--border-soft); }
}

/* spec-sheet meta panel — aligned label → value rows (host / asn / prefix) */
.ent-panel { border: 1px solid var(--border); margin: 1.45rem 0 0; background: var(--bg-elev); }
.ent-row {
  display: grid; grid-template-columns: 168px 1fr; gap: 1rem;
  padding: 0.66rem 1.05rem; align-items: baseline;
}
.ent-row + .ent-row { border-top: 1px solid var(--border-soft); }
.ent-row .ek {
  color: var(--fg-mute); font-family: var(--font-mono); font-size: 0.64rem;
  text-transform: uppercase; letter-spacing: 0.09em; line-height: 1.55;
}
.ent-row .ev {
  font-family: var(--font-mono); font-size: 0.9rem; color: var(--fg);
  min-width: 0; overflow-wrap: anywhere;
}
.ent-row .ev.nowrap { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ent-row .ev a { color: var(--accent); text-decoration: none; }
.ent-row .ev a:hover { text-decoration: underline; }
@media (max-width: 560px) {
  .ent-row { grid-template-columns: 1fr; gap: 0.14rem; padding: 0.6rem 0.9rem; }
}

/* ── section panel — each content area is its own definitive block ── */
.sec { border: 1px solid var(--border); background: var(--bg-elev); margin-top: 1.25rem; }
.sec-h {
  display: flex; align-items: center; gap: 0.6rem; margin: 0;
  padding: 0.62rem 1.05rem; border-bottom: 1px solid var(--border-soft);
  background: var(--bg-soft);
  font-family: var(--font-mono); font-size: 0.7rem; font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.08em; color: var(--fg);
}
.sec-h::before { content: ""; flex: 0 0 auto; width: 3px; height: 0.92rem; background: var(--accent); }
/* per-section pastel ticks — colour-code each content area at a glance */
.sec-h.s-rep::before    { background: #fda4af; } /* rose   — reputation */
.sec-h.s-ports::before  { background: #7dd3fc; } /* sky    — open ports */
.sec-h.s-vulns::before  { background: #fca5a5; } /* red    — vulnerabilities */
.sec-h.s-names::before  { background: #86efac; } /* green  — hostnames */
.sec-h.s-tags::before   { background: #fcd34d; } /* amber  — tags */
.sec-h.s-cpe::before    { background: #c4b5fd; } /* violet — software (CPE) */
.sec-h.s-svc::before    { background: #93c5fd; } /* blue   — services */
.sec-h.s-hosts::before  { background: #5eead4; } /* teal   — observed hosts */
.sec-h.s-prefix::before { background: #93c5fd; } /* blue   — announced prefixes */
.sec-h.s-v4::before     { background: #7dd3fc; } /* sky    — ipv4 prefixes */
.sec-h.s-v6::before     { background: #a5b4fc; } /* indigo — ipv6 prefixes */
.sec-h.s-peers::before  { background: #fdba74; } /* orange — peers */
.sec-h.s-route::before  { background: #67e8f9; } /* cyan   — routing */
.sec-h .count {
  margin-left: auto; color: var(--fg-dim); background: var(--bg-alt);
  border: 1px solid var(--border-soft); padding: 0.05rem 0.5rem;
  font-size: 0.66rem; letter-spacing: 0.03em; font-weight: 400;
}
.sec-b { padding: 0.95rem 1.05rem; }
.sec-b > .host-note { border: 0; padding: 0.35rem 0; margin: 0; text-align: left; }
.prefix-more { font-size: 0.76rem; margin: 0.75rem 0 0; color: var(--fg-mute); }

/* chips & pills */
.chips { display: flex; flex-wrap: wrap; gap: 0.45rem; }
.chip {
  border: 1px solid var(--border); padding: 0.26rem 0.62rem; font-size: 0.78rem;
  color: var(--fg-dim); font-family: var(--font-mono); text-decoration: none;
  transition: border-color 120ms, color 120ms, background 120ms;
}
.chip:hover { border-color: var(--accent-edge); color: var(--fg); background: var(--bg-soft); }
/* a chip marking a domain that currently resolves */
.chip-on { color: var(--accent); border-color: var(--accent-edge); }
/* DNS records table on the domain page */
.dns-tbl { width: 100%; border-collapse: collapse; font-family: var(--font-mono); font-size: 0.8rem; }
.dns-tbl th { text-align: left; color: var(--fg-mute); font-weight: 500; font-size: 0.7rem;
  text-transform: uppercase; letter-spacing: 0.05em; padding: 0.3rem 0.6rem 0.3rem 0; border-bottom: 1px solid var(--border); }
.dns-tbl td { padding: 0.32rem 0.6rem 0.32rem 0; border-bottom: 1px solid var(--border); vertical-align: top; }
.dns-tbl .dns-t { color: var(--accent); white-space: nowrap; width: 4rem; }
.dns-tbl .dns-v { color: var(--fg-dim); word-break: break-all; }
.dns-tbl .dns-v a { color: var(--fg); text-decoration: none; }
.dns-tbl .dns-v a:hover { color: var(--accent); }

/* ASM dashboard / detail */
.asm-tbl { width: 100%; border-collapse: collapse; font-size: 0.82rem; }
.asm-tbl th { text-align: left; color: var(--fg-mute); font-weight: 500; font-size: 0.7rem;
  text-transform: uppercase; letter-spacing: 0.05em; padding: 0.35rem 0.7rem 0.35rem 0; border-bottom: 1px solid var(--border); }
.asm-tbl td { padding: 0.5rem 0.7rem 0.5rem 0; border-bottom: 1px solid var(--border); vertical-align: top; }
.asm-tbl td a { color: var(--fg); text-decoration: none; }
.asm-tbl td a:hover { color: var(--accent); }
.asm-tbl .sub { color: var(--fg-mute); font-size: 0.72rem; }
.asm-gone { opacity: 0.45; text-decoration: line-through; }
.rbadge { display: inline-block; padding: 0.1rem 0.45rem; font-family: var(--font-mono); font-size: 0.68rem;
  text-transform: uppercase; letter-spacing: 0.04em; border: 1px solid var(--border); margin-right: 0.3rem; }
.r-critical { color: #ff5b5b; border-color: #ff5b5b; }
.r-high { color: #ff8c42; border-color: #ff8c42; }
.r-medium { color: #e3b341; border-color: #e3b341; }
.r-low { color: var(--fg-dim); }
.r-info { color: var(--fg-mute); }
.asm-form { display: flex; flex-direction: column; gap: 0.6rem; max-width: 640px; }
.asm-form-row { display: flex; gap: 0.6rem; flex-wrap: wrap; }
.asm-input { background: var(--bg); border: 1px solid var(--border); color: var(--fg);
  padding: 0.45rem 0.6rem; font-family: var(--font-mono); font-size: 0.82rem; }
.asm-input:focus { outline: none; border-color: var(--accent-edge); }
.asm-grow { flex: 1; min-width: 12rem; }
.asm-events { list-style: none; margin: 0; padding: 0; font-size: 0.8rem; }
.asm-events li { padding: 0.3rem 0; border-bottom: 1px solid var(--border); display: flex; gap: 0.5rem; align-items: baseline; }
.ev-kind { font-family: var(--font-mono); font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--fg-mute); min-width: 8rem; }
.ev-asset_added { color: var(--accent); }
.ev-risk_increased { color: #ff8c42; }
.ev-asset_removed { color: var(--fg-mute); }
.ev-when { margin-left: auto; color: var(--fg-mute); font-family: var(--font-mono); font-size: 0.7rem; }
/* open-port chips */
.port-chip {
  display: inline-flex; align-items: baseline; gap: 0.42rem; border: 1px solid var(--border);
  padding: 0.3rem 0.62rem; text-decoration: none; font-family: var(--font-mono);
  color: var(--accent); transition: border-color 120ms, background 120ms;
}
.port-chip:hover { border-color: var(--accent-edge); background: var(--bg-soft); }
.port-chip .pp { color: var(--fg-mute); font-size: 0.66rem; text-transform: uppercase; letter-spacing: 0.05em; }
/* external-link glyph inside a prefix/port chip: keep the icon vertically
   aligned with the text and sized to match the chip's mono type. */
.port-chip svg {
  width: 0.82rem; height: 0.82rem; stroke: currentColor;
  align-self: center; margin-left: 0.08rem; opacity: 0.8; flex: none;
}
.port-chip:hover svg { opacity: 1; }
/* vulns */
.vchip {
  display: inline-flex; align-items: center; gap: 0.45rem; border: 1px solid var(--border);
  padding: 0.24rem 0.6rem; font-size: 0.78rem; font-family: var(--font-mono); text-decoration: none;
  transition: border-color 120ms, background 120ms;
}
.vchip:hover { background: var(--bg-soft); }
.vchip .cvss { font-size: 0.68rem; opacity: 0.85; }
.kev { background: var(--bad); color: #000; font-size: 0.6rem; font-weight: 700; letter-spacing: 0.04em; padding: 0.05rem 0.32rem; text-transform: uppercase; }
.sev-critical { color: #f87171; border-color: #f87171; }
.sev-high { color: #fb923c; border-color: #fb923c; }
.sev-medium { color: #fbbf24; border-color: #fbbf24; }
.sev-low { color: #60a5fa; border-color: #60a5fa; }
.sev-none { color: var(--fg-dim); }

/* Host-page service cards live in their own stylesheet (host.css), loaded only
   on the host detail page. `.banner` stays here because it is shared with the
   search results surface and the lookup console. */
.banner {
  margin: 0.3rem 0 0; padding: 0.7rem 0.8rem; background: var(--bg-code); border: 1px solid var(--border-soft);
  overflow: auto; max-height: 340px; font-family: var(--font-mono); font-size: 0.78rem;
  color: var(--fg-dim); white-space: pre-wrap; word-break: break-word;
}
/* standalone empty / error notes (invalid entity, no-data) */
.host-note { border: 1px solid var(--border); padding: 1.75rem; color: var(--fg-dim); text-align: center; margin-top: 1.25rem; }
.muted { color: var(--fg-mute); }

/* ═════════════════════════════════════════════════════════════
   SERVICE SEARCH RESULTS (/search)
   ═════════════════════════════════════════════════════════════ */
.srch-wrap { max-width: 1180px; margin: 0 auto; padding: 2rem 1.25rem 5rem; }
.srch-eyebrow {
  display: inline-block; font-family: var(--font-mono); font-size: 0.62rem;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--accent);
  margin: 0 0 0.5rem;
}
/* Constant header (same with or without a query) — the active query lives in the
   global header search box, so this stays put as filters are added/removed. */
.srch-title { font-size: clamp(1.6rem, 3.6vw, 2.05rem); margin: 0 0 0.35rem; letter-spacing: -0.01em; }

/* the page's own search bar — reuses .lookup-row / .lookup-input-wrap /
   .lookup-input from app.css, left-aligned and full-width under the header so a
   new query can be typed without returning home. */
.srch-bar { width: 100%; max-width: 760px; margin: 0.9rem 0 0; }
.srch-bar .lookup-row { max-width: none; }
.srch-bar .lookup-input-wrap { padding-left: 18px; }
.srch-bar .lookup-prompt { font-size: 1rem; }
.srch-bar .lookup-input { font-size: 1.05rem; padding: 0.6rem 1rem; }

/* ── below-the-bar: a single "Filters & syntax" help control ───────
   The only affordance under the bar. It's a compact pill; opening it drops a
   FLOATING popover (position: absolute) that overlays the results and never
   pushes them down. The panel holds three intuitive sections: add-a-filter
   chips, clickable example queries, and the operator/matcher reference. */
.srch-tools {
  display: flex; align-items: flex-start; flex-wrap: wrap; gap: 0.6rem;
  margin: 0.85rem 0 0; max-width: 760px;
}

/* ── country / continent chooser (search_geo.js) ───────────
   A trigger pill (matches the syntax pill) that opens a floating multi-select
   popover: search box, continent groups with per-group "All/Clear", country
   checkboxes with flags, and Apply. Selecting several composes a
   country:{A,B,…} set filter into the query. */
.srch-geo { position: relative; }
.geo-toggle {
  display: inline-flex; align-items: center; gap: 0.42rem; cursor: pointer;
  border: 1px solid var(--border); background: var(--bg-elev);
  padding: 0.4rem 0.8rem; color: var(--fg-dim);
  font-family: var(--font-mono); font-size: 0.78rem;
  transition: border-color 130ms, color 130ms, background 130ms;
}
.geo-toggle .geo-globe { display: inline-flex; width: 0.95rem; height: 0.95rem; color: var(--accent); }
.geo-toggle .geo-globe svg { width: 100%; height: 100%; }
.geo-toggle .geo-caret { display: inline-flex; width: 0.85rem; height: 0.85rem; opacity: 0.7; transition: transform 180ms; }
.geo-toggle .geo-trig-count {
  min-width: 1.15rem; text-align: center; padding: 0.02rem 0.32rem; line-height: 1.4;
  background: var(--accent); color: var(--accent-ink); font-size: 0.68rem; font-variant-numeric: tabular-nums;
}
.srch-geo:hover .geo-toggle,
.geo-toggle.is-on { border-color: var(--accent-edge); color: var(--fg); }
.srch-geo.is-open .geo-toggle { border-color: var(--accent-edge); color: var(--fg); background: var(--accent-soft); }
.srch-geo.is-open .geo-toggle .geo-caret { transform: rotate(180deg); }

.geo-pop {
  position: absolute; top: calc(100% + 6px); left: 0; z-index: 45;
  width: min(420px, 94vw); border: 1px solid var(--border); background: var(--bg-elev);
  box-shadow: 0 16px 48px rgba(0, 0, 0, 0.5);
  display: none; flex-direction: column;
  animation: srch-help-in 160ms cubic-bezier(0.2, 0.7, 0.2, 1);
}
:root[data-theme="light"] .geo-pop { box-shadow: 0 16px 48px rgba(0, 0, 0, 0.16); }
.srch-geo.is-open .geo-pop { display: flex; }
@media (prefers-reduced-motion: reduce) { .geo-pop { animation: none; } }
.geo-pop-head {
  display: flex; flex-direction: column; gap: 0.55rem;
  padding: 0.85rem 0.9rem; border-bottom: 1px solid var(--border-soft);
}
.geo-pop-title {
  font-family: var(--font-mono); font-size: 0.6rem; font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.12em; color: var(--fg-mute);
}
.geo-search {
  width: 100%; box-sizing: border-box; background: var(--bg); color: var(--fg);
  border: 1px solid var(--border); padding: 0.42rem 0.6rem;
  font-family: var(--font-mono); font-size: 0.82rem;
}
.geo-search:focus { outline: none; border-color: var(--accent); }
/* No top padding: a sticky header pins at `top`, which sits below any
   padding-top — leaving a strip above it where scrolled-past rows would flash
   through. Bottom padding only. */
.geo-list { max-height: min(48vh, 380px); overflow-y: auto; padding: 0 0 0.3rem;
  scrollbar-width: thin; scrollbar-color: var(--border-bold) transparent; }
.geo-group {
  display: flex; align-items: center; gap: 0.5rem;
  padding: 0.42rem 0.9rem 0.28rem; position: sticky; top: -1px;
  background: var(--bg-soft); border-bottom: 1px solid var(--border-soft);
  /* flag-icons spans are `position: relative`, so without a z-index here they'd
     paint on top of this sticky header as rows scroll under it (only the flags
     showed through). Lift the header above the rows' positioned flags. `top:-1px`
     tucks a hairline under the popover head so no sub-pixel seam flashes. */
  z-index: 2;
}
/* the flags/rows scroll beneath the sticky header */
.geo-opt { position: relative; z-index: 1; }
.geo-group-name {
  font-family: var(--font-mono); font-size: 0.6rem; font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.1em; color: var(--fg-dim);
}
.geo-group-n {
  color: var(--fg-mute); font-family: var(--font-mono); font-size: 0.62rem;
  font-variant-numeric: tabular-nums;
}
.geo-group-all {
  margin-left: auto; cursor: pointer; border: 1px solid var(--border);
  background: transparent; color: var(--fg-dim);
  font-family: var(--font-mono); font-size: 0.64rem; padding: 0.14rem 0.5rem;
  transition: border-color 120ms, color 120ms;
}
.geo-group-all:hover { border-color: var(--accent-edge); color: var(--accent); }
.geo-opt {
  display: flex; align-items: center; gap: 0.55rem; cursor: pointer;
  padding: 0.36rem 0.9rem; font-size: 0.82rem; color: var(--fg-dim);
  transition: background 110ms;
}
.geo-opt:hover { background: var(--bg-soft); color: var(--fg); }
.geo-opt input { accent-color: var(--accent); flex: none; margin: 0; }
.geo-opt-flag { flex: none; line-height: 1; }
.geo-opt-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.geo-opt-code { flex: none; color: var(--fg-mute); font-family: var(--font-mono); font-size: 0.7rem; }
.geo-empty { padding: 0.9rem; color: var(--fg-mute); font-size: 0.8rem; text-align: center; }
.geo-foot {
  display: flex; align-items: center; gap: 0.5rem;
  padding: 0.7rem 0.9rem; border-top: 1px solid var(--border-soft);
}
.geo-foot-count { font-family: var(--font-mono); font-size: 0.72rem; color: var(--fg-mute); }
.geo-foot-sp { flex: 1; }
.geo-clear {
  cursor: pointer; border: 1px solid var(--border); background: transparent; color: var(--fg-dim);
  font-family: var(--font-mono); font-size: 0.74rem; padding: 0.34rem 0.6rem;
  transition: border-color 120ms, color 120ms;
}
.geo-clear:hover { border-color: var(--fg-mute); color: var(--fg); }
.geo-apply {
  cursor: pointer; border: 1px solid var(--accent); background: var(--accent); color: var(--accent-ink);
  font-family: var(--font-mono); font-size: 0.74rem; padding: 0.34rem 0.85rem;
  transition: background 120ms, border-color 120ms;
}
.geo-apply:hover { background: var(--accent-2); border-color: var(--accent-2); }

.srch-syntax { position: relative; }
.srch-syntax-toggle {
  display: inline-flex; align-items: center; gap: 0.42rem; cursor: pointer;
  list-style: none; user-select: none; width: fit-content;
  border: 1px solid var(--border); background: var(--bg-elev);
  padding: 0.4rem 0.8rem; color: var(--fg-dim);
  font-family: var(--font-mono); font-size: 0.78rem;
  transition: border-color 130ms, color 130ms, background 130ms;
}
.srch-syntax-toggle::-webkit-details-marker { display: none; }
.srch-syntax-toggle > svg:first-child { width: 0.92rem; height: 0.92rem; flex: none; color: var(--accent); }
.srch-syntax-toggle .sx-caret { width: 0.85rem; height: 0.85rem; flex: none; opacity: 0.7; transition: transform 180ms; }
.srch-syntax:hover .srch-syntax-toggle,
.srch-syntax[open] .srch-syntax-toggle { border-color: var(--accent-edge); color: var(--fg); }
.srch-syntax[open] .srch-syntax-toggle { background: var(--accent-soft); }
.srch-syntax[open] .srch-syntax-toggle .sx-caret { transform: rotate(180deg); }

/* floating help popover — overlays the results, doesn't shift them down */
.srch-help {
  position: absolute; top: calc(100% + 6px); left: 0; z-index: 40;
  width: min(860px, 94vw); max-height: min(72vh, 600px); overflow-y: auto;
  border: 1px solid var(--border); background: var(--bg-elev);
  box-shadow: 0 16px 48px rgba(0, 0, 0, 0.5);
  padding: 1.1rem 1.2rem 1.2rem; display: flex; flex-direction: column; gap: 1.15rem;
  animation: srch-help-in 160ms cubic-bezier(0.2, 0.7, 0.2, 1);
  scrollbar-width: thin; scrollbar-color: var(--border-bold) transparent;
}
:root[data-theme="light"] .srch-help { box-shadow: 0 16px 48px rgba(0, 0, 0, 0.16); }
@keyframes srch-help-in { from { opacity: 0; transform: translateY(-6px); } }
@media (prefers-reduced-motion: reduce) { .srch-help { animation: none; } }
.srch-help-grid { display: grid; grid-template-columns: minmax(0, auto) minmax(0, 1fr); gap: 1.15rem 1.7rem; }
.help-sec { min-width: 0; }
.help-h {
  margin: 0 0 0.6rem; font-family: var(--font-mono); font-size: 0.6rem;
  font-weight: 500; text-transform: uppercase; letter-spacing: 0.12em;
  color: var(--fg-mute); display: flex; align-items: center; gap: 0.45rem;
}
.help-h::before { content: ""; width: 3px; height: 0.78rem; background: var(--accent); flex: none; }
.help-chips { display: flex; flex-wrap: wrap; gap: 0.4rem; max-width: 16rem; }

/* clickable example queries — full-width code lines that light up on hover */
.help-examples { display: flex; flex-direction: column; gap: 0.3rem; }
.srch-ex {
  display: block; text-decoration: none; border: 1px solid var(--border-soft);
  background: var(--bg); padding: 0.42rem 0.62rem;
  transition: border-color 130ms, background 130ms;
}
.srch-ex code { font-family: var(--font-mono); font-size: 0.8rem; color: var(--fg-dim); }
.srch-ex:hover { border-color: var(--accent-edge); background: var(--bg-soft); opacity: 1; }
.srch-ex:hover code { color: var(--fg); }

/* add-filter chip: accent-tinted "+ Foo" that appends a filter to the query */
.qf {
  display: inline-flex; align-items: center; gap: 0.3rem;
  border: 1px solid var(--accent-edge); background: var(--accent-soft);
  padding: 0.26rem 0.62rem; color: var(--accent); text-decoration: none;
  font-size: 0.78rem; font-family: var(--font-mono);
  transition: background 130ms, color 130ms, border-color 130ms, transform 130ms;
}
.qf:hover {
  background: var(--accent); color: var(--accent-ink); border-color: var(--accent);
  transform: translateY(-1px); opacity: 1;
}
.qf:active { transform: translateY(0); }
/* neutral outline chip — used on the syntax reference page (/search/syntax) */
.srch-chip {
  border: 1px solid var(--border); padding: 0.26rem 0.62rem; color: var(--fg-dim);
  text-decoration: none; font-family: var(--font-mono); font-size: 0.78rem;
  transition: border-color 130ms, color 130ms, background 130ms;
}
.srch-chip:hover { border-color: var(--accent-edge); color: var(--fg); background: var(--bg-soft); opacity: 1; }
@media (prefers-reduced-motion: reduce) {
  .qf { transition: background 130ms, color 130ms, border-color 130ms; }
  .qf:hover, .qf:active { transform: none; }
}

/* operator/matcher reference — borderless (the popover is the surface), 2 cols,
   each entry stacks the token over its description. */
.syntax-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 1.5rem; }
.syntax-grid > div {
  display: flex; flex-direction: column; gap: 0.18rem; align-content: start;
  padding: 0.42rem 0; border-bottom: 1px solid var(--border-soft);
}
.sx-code { display: flex; flex-wrap: wrap; gap: 0.35rem; }
.syntax-grid code {
  font-family: var(--font-mono); font-size: 0.78rem; color: var(--fg);
  background: var(--surface-2, rgba(127,127,127,0.10)); padding: 0.08rem 0.34rem;
}
.sx-desc { color: var(--fg-mute); font-size: 0.76rem; }
.srch-help-more {
  align-self: flex-start; font-family: var(--font-mono); font-size: 0.78rem;
  color: var(--accent); text-decoration: none; border-bottom: 1px solid transparent;
}
.srch-help-more:hover { border-bottom-color: var(--accent-edge); opacity: 1; }
@media (max-width: 640px) {
  .srch-help-grid { grid-template-columns: 1fr; gap: 1rem; }
  .help-chips { max-width: none; }
  .syntax-grid { grid-template-columns: 1fr; }
}

/* results layout */
.srch-layout { display: grid; grid-template-columns: 1fr 244px; gap: 1.6rem; margin-top: 1.5rem; align-items: start; }
/* Desktop: the facets disclosure is always-open chrome — hide its toggle and
   force the body visible regardless of the (default-closed) details state.
   !important is intentional: it overrides the UA `display:none` that a closed
   <details> applies to its non-summary children. */
@media (min-width: 861px) {
  .facet-collapse > summary { display: none; }
  /* old model: closed <details> sets display:none on non-summary children */
  .facet-collapse > .facet-collapse-body { display: block !important; }
  /* new model (Chrome 131+): closed <details> uses content-visibility:hidden on
     the ::details-content wrapper. Browsers without this pseudo drop the rule. */
  .facet-collapse::details-content { content-visibility: visible !important; }
}
@media (max-width: 860px) {
  .srch-layout { grid-template-columns: 1fr; gap: 1.1rem; }
  /* pull the refine panel above the results instead of burying it at the bottom */
  .srch-facets { order: -1; }
  .facet-toggle { display: flex; }
  .facet-card { margin-bottom: 0; }
  .facet-card + .facet-card { border-top: 0; }
  .facet-collapse[open] .facet-collapse-body { margin-top: 0.6rem; display: grid; gap: 0.6rem; }
}
.srch-count {
  color: var(--fg-dim); font-size: 0.82rem; font-family: var(--font-mono);
}
.srch-count strong { color: var(--fg); font-weight: 500; }

/* results toolbar: match count on the left, export + page-size on the right */
.srch-resbar {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  flex-wrap: wrap; margin-top: 1.5rem; margin-bottom: 0.4rem;
  padding-bottom: 0.7rem; border-bottom: 1px solid var(--border-soft);
}
.srch-resbar-tools { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; }
.srch-perpage { display: flex; align-items: center; gap: 0.4rem; }
.srch-perpage .lbl {
  font-size: 0.6rem; text-transform: uppercase; letter-spacing: 0.1em;
  color: var(--fg-mute); font-family: var(--font-mono);
}
.srch-perpage .pp {
  font-family: var(--font-mono); font-size: 0.78rem; line-height: 1;
  padding: 0.34rem 0.55rem; border: 1px solid var(--border); color: var(--fg-dim);
  text-decoration: none; transition: border-color 120ms, color 120ms, background 120ms;
}
.srch-perpage .pp:hover { border-color: var(--accent-edge); color: var(--fg); }
.srch-perpage .pp.active {
  border-color: var(--accent); background: var(--accent); color: var(--accent-ink);
}

/* paid-only export control — a compact <details> button in the results bar.
   Clicking reveals a small popover with the CSV/JSON links and the daily
   allowance note, so the download lives beside "Per page" instead of shoving a
   full-width warning band above every result. */
.srch-export { position: relative; }
.srch-export-toggle {
  display: inline-flex; align-items: center; gap: 0.4rem; cursor: pointer;
  list-style: none; user-select: none;
  font-family: var(--font-mono); font-size: 0.78rem; line-height: 1;
  padding: 0.34rem 0.6rem; border: 1px solid var(--border); color: var(--fg-dim);
  transition: border-color 120ms, color 120ms, background 120ms;
}
.srch-export-toggle::-webkit-details-marker { display: none; }
.srch-export-toggle svg { width: 0.9rem; height: 0.9rem; stroke: currentColor; }
.srch-export-toggle:hover { border-color: var(--accent-edge); color: var(--fg); }
.srch-export[open] .srch-export-toggle {
  border-color: var(--accent); color: var(--accent); background: var(--accent-soft);
}
.srch-export-menu {
  position: absolute; right: 0; top: calc(100% + 6px); z-index: 20;
  width: max-content; max-width: 280px;
  border: 1px solid var(--border); background: var(--bg-elev);
  padding: 0.75rem 0.85rem; display: flex; flex-direction: column; gap: 0.55rem;
  box-shadow: 0 8px 28px rgba(0,0,0,0.35);
}
:root[data-theme="light"] .srch-export-menu { box-shadow: 0 8px 28px rgba(0,0,0,0.12); }
.srch-export-hd { margin: 0; font-family: var(--font-mono); font-size: 0.8rem; color: var(--fg); }
.srch-export-hd strong { color: var(--accent); font-weight: 500; }
.srch-export-actions { display: flex; align-items: center; gap: 0.5rem; }
.srch-export-btn {
  flex: 1; text-align: center;
  font-family: var(--font-mono); font-size: 0.78rem; line-height: 1;
  padding: 0.42rem 0.7rem; border: 1px solid var(--accent); color: var(--accent-ink);
  background: var(--accent); text-decoration: none;
  transition: background 120ms, border-color 120ms;
}
.srch-export-btn:hover { background: var(--accent-2); border-color: var(--accent-2); opacity: 1; }
.srch-export-warn {
  margin: 0; font-size: 0.7rem; color: var(--fg-mute); font-family: var(--font-mono);
  line-height: 1.45;
}
.srch-export-warn strong { color: var(--fg-dim); font-weight: 500; }
@media (max-width: 600px) {
  .srch-export-menu { right: auto; left: 0; }
}

/* numbered pager under the host list */
.srch-pager {
  display: flex; flex-wrap: wrap; gap: 0.3rem; align-items: center;
  margin-top: 1.6rem;
}
.srch-pager .pg {
  font-family: var(--font-mono); font-size: 0.8rem; line-height: 1;
  min-width: 2rem; text-align: center; padding: 0.45rem 0.55rem;
  border: 1px solid var(--border); color: var(--fg-dim); text-decoration: none;
}
.srch-pager .pg:hover { border-color: var(--accent-edge); color: var(--fg); }
.srch-pager .pg.active {
  border-color: var(--accent); background: var(--accent); color: var(--accent-ink);
}
.srch-pager .pg.is-disabled { opacity: 0.4; pointer-events: none; }
.srch-pageinfo {
  margin-top: 0.6rem; color: var(--fg-mute); font-size: 0.72rem; font-family: var(--font-mono);
}

/* featured entity card (exact IP / ASN / prefix at the top of results) */
.feat {
  display: block; position: relative; border: 1px solid var(--accent-edge);
  background: var(--accent-soft); padding: 1.05rem 1.2rem 1.05rem 1.35rem;
  margin: 1.5rem 0 1.3rem; text-decoration: none; color: var(--fg);
  transition: border-color 120ms;
}
.feat::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; background: var(--accent); }
.feat:hover { border-color: var(--accent); }
.feat-head { display: flex; align-items: baseline; gap: 0.6rem; flex-wrap: wrap; }
.feat-kind {
  font-size: 0.6rem; text-transform: uppercase; letter-spacing: 0.1em;
  color: var(--accent-ink); background: var(--accent); padding: 0.16rem 0.45rem; font-family: var(--font-mono);
}
.feat-title { font-family: var(--font-mono); font-size: 1.18rem; font-weight: 500; word-break: break-all; }
.feat-sub { color: var(--fg-dim); font-size: 0.9rem; min-width: 0; overflow-wrap: anywhere; }
.feat-facts { display: flex; flex-wrap: wrap; gap: 0.45rem 1.6rem; margin-top: 0.75rem; }
.feat-fact { font-size: 0.84rem; }
.feat-fact .fl {
  color: var(--fg-mute); text-transform: uppercase; font-size: 0.6rem;
  letter-spacing: 0.07em; margin-right: 0.4rem; font-family: var(--font-mono);
}
.feat-fact .fv { font-family: var(--font-mono); color: var(--fg); }
.feat-cta { display: inline-block; margin-top: 0.85rem; color: var(--accent); font-size: 0.82rem; font-weight: 600; }

/* host result cards */
.hcard {
  position: relative; border: 1px solid var(--border); background: var(--bg-elev);
  margin-bottom: 0.72rem; transition: border-color 140ms, transform 140ms cubic-bezier(0.2,0.7,0.2,1);
}
/* accent edge tick that scales in on hover — the same left-tick language used by
   the section headers and facet rows */
.hcard::before {
  content: ""; position: absolute; left: -1px; top: -1px; bottom: -1px; width: 2px;
  background: var(--accent); transform: scaleY(0); transform-origin: center;
  transition: transform 160ms cubic-bezier(0.2,0.7,0.2,1);
}
.hcard:hover { border-color: var(--accent-edge); }
.hcard:hover::before { transform: scaleY(1); }
@media (prefers-reduced-motion: reduce) {
  .hcard, .hcard::before { transition: none; }
}
.hcard-top { display: flex; align-items: baseline; gap: 0.7rem; padding: 0.72rem 0.95rem 0.2rem; }
/* Pad the IP to a fixed monospace column (15ch = the widest IPv4) so the AS /
   geo info starts at the same x on every row instead of tracking IP length.
   A longer IPv6 address simply grows past the minimum for that row. */
.hcard-ip {
  font-family: var(--font-mono); font-size: 1.05rem; color: var(--accent);
  text-decoration: none; font-weight: 500; flex: none; min-width: 15ch;
}
.hcard-ip:hover { text-decoration: underline; }
/* Network/geo row: ASN, org name, and location as separate columns laid out
   left-to-right with a single uniform gap between every host's fields. The org
   name occupies a single fixed-width column so the location/flag always starts
   at the same x on every row — short names leave trailing space, long names
   ellipsize, but the flag column never shifts. */
.hcard-net {
  display: flex; align-items: baseline; gap: 0 0.95rem; flex: 1; min-width: 0;
  font-size: 0.82rem; overflow: hidden;
}
.hn-asn { flex: none; min-width: 8ch; font-family: var(--font-mono); color: var(--fg); white-space: nowrap; }
.hn-org {
  flex: none; width: 22ch; color: var(--fg-dim);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Location sits immediately after the org name (left-aligned), separated by the
   same gap as the other fields so spacing stays uniform across every host row. */
.hn-loc {
  flex: none; display: inline-flex; align-items: baseline;
  gap: 0.4rem; color: var(--fg-mute); white-space: nowrap;
}
.hn-loc .country-flag { line-height: 1; }
/* Fixed-width, right-aligned count column so the port count never shifts the
   location column left of it from row to row. */
.hcard-cnt {
  flex: none; min-width: 9ch; text-align: right;
  color: var(--fg-mute); font-size: 0.74rem; font-family: var(--font-mono); white-space: nowrap;
}
.hcard-svcs { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem; padding: 0.55rem 0.95rem 0.9rem; }
.svc-more {
  display: inline-flex; align-items: center; padding: 0.24rem 0.58rem;
  font-family: var(--font-mono); font-size: 0.76rem; color: var(--fg-mute);
  text-decoration: none; border: 1px dashed var(--border);
}
.svc-more:hover { color: var(--fg); border-color: var(--accent-edge); }
/* Compact port chip: just "port/proto" so many fit per row. The detected
   product/version is kept in the chip's title tooltip (and on the host page),
   not inline, since it bloated the chip and forced early wrapping. */
.svc-pill {
  display: inline-flex; align-items: baseline; gap: 0.28rem; border: 1px solid var(--border);
  padding: 0.2rem 0.5rem; text-decoration: none; font-family: var(--font-mono);
  font-size: 0.8rem; color: var(--fg); white-space: nowrap;
  transition: border-color 120ms, background 120ms;
}
.svc-pill:hover { border-color: var(--accent-edge); background: var(--bg-soft); }
.svc-pill .pn { color: var(--accent); }
.svc-pill .pr { color: var(--fg-mute); font-size: 0.66rem; text-transform: uppercase; letter-spacing: 0.04em; }

/* facets sidebar */
.facet-card { border: 1px solid var(--border); background: var(--bg-elev); margin-bottom: 1rem; }
.facet-h {
  display: flex; align-items: center; gap: 0.5rem;
  font-family: var(--font-mono); font-size: 0.64rem; text-transform: uppercase;
  letter-spacing: 0.08em; color: var(--fg-mute);
  padding: 0.5rem 0.7rem; border-bottom: 1px solid var(--border-soft); background: var(--bg-soft);
}
.facet-h::before { content: ""; flex: 0 0 auto; width: 3px; height: 0.8rem; background: var(--accent); }
/* total-bucket count, pushed to the right edge of the header — hints there's
   more to scroll when the body overflows its ~10-row cap. */
.facet-h-c {
  margin-left: auto; color: var(--fg-mute); background: var(--bg-alt);
  border: 1px solid var(--border-soft); padding: 0.02rem 0.4rem;
  font-size: 0.62rem; letter-spacing: 0.02em; font-variant-numeric: tabular-nums;
}
/* facet body: shows ~10 rows, then scrolls to reveal the rest (up to 50).
   A thin fade at the bottom edge signals more rows below the fold. */
.facet-body { position: relative; }
.facet-body.is-scroll {
  max-height: 21rem; overflow-y: auto; overscroll-behavior: contain;
  scrollbar-width: thin; scrollbar-color: var(--border-bold) transparent;
}
.facet-body.is-scroll::-webkit-scrollbar { width: 8px; }
.facet-body.is-scroll::-webkit-scrollbar-thumb {
  background: var(--border-bold); border: 2px solid var(--bg-elev);
}
.facet-body.is-scroll::-webkit-scrollbar-track { background: transparent; }
/* Each row carries a faint accent bar sized to --facet-share (its count as a
   share of the facet's busiest bucket) painted behind the text, so relative
   magnitude reads at a glance. A left accent tick scales in on hover. */
.facet-row {
  position: relative; overflow: hidden;
  display: flex; justify-content: space-between; gap: 0.5rem; padding: 0.44rem 0.7rem;
  color: var(--fg-dim); text-decoration: none; font-size: 0.82rem; font-family: var(--font-mono);
  transition: background 120ms, color 120ms;
}
.facet-row::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0;
  width: var(--facet-share, 0%);
  background: var(--accent-soft);
  transition: width 420ms cubic-bezier(0.2, 0.7, 0.2, 1);
  pointer-events: none;
}
.facet-row::after {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 2px;
  background: var(--accent); transform: scaleY(0); transform-origin: center;
  transition: transform 140ms cubic-bezier(0.2, 0.7, 0.2, 1);
}
.facet-row + .facet-row { border-top: 1px solid var(--border-soft); }
.facet-row:hover { background: var(--bg-soft); color: var(--fg); opacity: 1; }
.facet-row:hover::after { transform: scaleY(1); }
.facet-row > * { position: relative; z-index: 1; }
.facet-row .c { flex: none; color: var(--fg-mute); font-variant-numeric: tabular-nums; }
.facet-row:hover .c { color: var(--accent); }
/* min-width:0 lets the value actually shrink + ellipsize inside the flex row;
   without it a long value (product strings, org names) forces the row wider
   than its column and spills off-screen on narrow viewports. */
.facet-row .v { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (prefers-reduced-motion: reduce) {
  .facet-row::before, .facet-row::after { transition: none; }
}
/* Number-keyed facet value (port, ASN) gets a fixed-width column so the trailing
   note starts at the same x-position no matter how many digits the number has —
   a 2-digit port and a 5-digit port both leave the service name aligned. */
/* margin (not padding) for the gap: with the global `box-sizing: border-box`,
   padding would eat into min-width and let a 5-/6-digit number overflow the
   column, so the note would still shift. min-width covers a 6-digit ASN. */
.facet-num { display: inline-block; min-width: 6ch; margin-right: 0.6ch; }
/* Secondary annotation after a facet value: service name for a port, AS name for
   an ASN. A touch darker than the value so the primary number still reads first. */
.facet-note { color: color-mix(in srgb, var(--fg-mute) 68%, var(--bg)); font-size: 0.74rem; }

/* The facets sidebar is a collapsible "Refine results" disclosure. On desktop it
   is always-open chrome (toggle hidden, body forced visible); on mobile it becomes
   a tap-to-expand panel pulled above the results so filters aren't buried at the
   bottom of the list. */
.srch-facets { min-width: 0; }
.facet-collapse { border: 0; }
.facet-toggle {
  display: none; cursor: pointer; user-select: none; list-style: none;
  align-items: center; gap: 0.5rem; padding: 0.7rem 0.85rem;
  border: 1px solid var(--border); background: var(--bg-soft); color: var(--fg);
  font-family: var(--font-mono); font-size: 0.74rem; text-transform: uppercase;
  letter-spacing: 0.07em;
}
.facet-toggle::-webkit-details-marker { display: none; }
.facet-toggle::after {
  content: "▸"; margin-left: auto; color: var(--fg-mute);
  transition: transform 120ms; font-size: 0.85rem;
}
.facet-collapse[open] .facet-toggle::after { transform: rotate(90deg); }
.facet-toggle-c {
  color: var(--fg-mute); background: var(--bg-alt); border: 1px solid var(--border-soft);
  padding: 0.02rem 0.42rem; font-size: 0.66rem; letter-spacing: 0.03em;
}

/* search-page empty / error states */
.srch-note, .srch-error {
  border: 1px solid var(--border); background: var(--bg-elev); padding: 1.75rem;
  color: var(--fg-dim); text-align: center; margin-top: 1.5rem;
}
.srch-error { border-color: var(--bad); color: var(--bad); }
.srch-upsell {
  border: 1px solid var(--border); background: var(--bg-elev);
  padding: 1rem 1.25rem; color: var(--fg-dim); text-align: center;
  margin-top: 1.5rem; font-size: 0.9rem;
}
.srch-upsell a { color: var(--accent); }

/* ─────────────────────────────────────────────────────────────
   MOBILE / NARROW-VIEWPORT TUNING (shared by /search + detail pages)
   The detail chrome above already collapses .ent-row at 560px; this block
   handles the search results surface and the service .kv grid. Kept as one
   max-width sweep so the breakpoints stay legible.
   ───────────────────────────────────────────────────────────── */
@media (max-width: 600px) {
  .srch-wrap, .host-wrap { padding-left: 1rem; padding-right: 1rem; }

  /* host result card: stack IP+count on one line, network/geo on the next,
     instead of a rigid single-line flex row that clips or cramps on phones. */
  .hcard-top { flex-wrap: wrap; column-gap: 0.6rem; padding: 0.7rem 0.8rem 0.2rem; }
  .hcard-ip { font-size: 1rem; min-width: 0; word-break: break-all; }
  .hcard-cnt { margin-left: auto; min-width: 0; }
  /* network row drops to its own full-width line below the IP */
  .hcard-net { order: 3; flex-basis: 100%; gap: 0 0.7rem; flex-wrap: wrap; }
  .hn-asn { min-width: 0; }
  .hn-org { width: auto; flex: 0 1 auto; min-width: 0; }
  .hcard-svcs { padding: 0.5rem 0.8rem 0.8rem; }

  /* results toolbar: count over the page-size picker, both left-aligned */
  .srch-resbar { gap: 0.5rem; }
  .srch-perpage { width: 100%; }

  /* pager: collapse the numbered window to a single Prev · current · Next row.
     The full 7-wide window can't fit a phone, so hide every numbered link
     except the active page; "Page X of Y" below still gives the full context. */
  .srch-pager { flex-wrap: nowrap; justify-content: center; }
  .srch-pager .pg:not(:first-child):not(:last-child):not(.active) { display: none; }
  .srch-pageinfo { text-align: center; }

  /* roomier tap target for removing a filter pill */
  .pill { padding: 0.28rem 0.34rem 0.28rem 0.62rem; }
  .pill .x { width: 1.5rem; height: 1.5rem; }

  /* featured entity card: tighter padding, facts stack vertically */
  .feat { padding: 0.9rem 1rem 0.9rem 1.15rem; }
  .feat-facts { gap: 0.4rem 1rem; }
}

/* ─────────────────────────────────────────────────────────────
   SEARCH QUERY SYNTAX guide (/search/syntax)
   A reference page: operator + matcher tables, worked-example
   recipes, and the full field catalog grouped for scanning.
   ───────────────────────────────────────────────────────────── */
.syn-wrap {
  max-width: 940px; margin: 0 auto; padding: 2.4rem 1.2rem 4rem;
  --icon-link: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71'/%3E%3Cpath d='M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71'/%3E%3C/svg%3E");
}
.syn-hero { margin-bottom: 1.6rem; }
.syn-lede {
  color: var(--fg-dim); font-size: 0.96rem; line-height: 1.65;
  max-width: 70ch; margin: 0.6rem 0 1rem;
}
.syn-lede code, .syn-anatomy-note code, .syn-tip code {
  font-family: var(--font-mono); font-size: 0.85em; color: var(--fg);
  background: var(--bg-code, rgba(127,127,127,0.12)); padding: 0.04rem 0.3rem;
}
.syn-herolinks { display: flex; flex-wrap: wrap; gap: 0.5rem; }

/* anatomy callout: a worked clause broken into labelled tokens */
.syn-anatomy {
  border: 1px solid var(--border); background: var(--bg-soft);
  padding: 1.4rem 1.5rem 1.2rem; margin: 0 0 1rem;
}
.syn-anatomy-q {
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0.15rem 0.1rem;
  font-family: var(--font-mono); font-size: 1.5rem; line-height: 1.1;
}
.syn-tok { position: relative; padding: 0.1rem 0.1rem 1.55rem; }
.syn-tok-field { color: var(--accent); }
.syn-tok-op { color: var(--fg-mute); }
.syn-tok-val { color: var(--fg); }
.syn-tok-cap {
  position: absolute; left: 0; bottom: 0.2rem; white-space: nowrap;
  font-size: 0.66rem; letter-spacing: 0.03em; text-transform: uppercase;
  color: var(--fg-mute); border-top: 1px solid var(--border-bold);
  padding-top: 0.2rem; min-width: 100%;
}
.syn-anatomy-note {
  color: var(--fg-dim); font-size: 0.9rem; line-height: 1.6;
  margin: 0.4rem 0 0; max-width: 70ch;
}
.syn-anatomy-note strong { color: var(--fg); font-weight: 500; }

/* "examples are clickable" tip */
.syn-tip {
  display: flex; align-items: center; gap: 0.5rem;
  color: var(--fg-mute); font-size: 0.84rem; margin: 0 0 0.6rem;
}
.syn-tip-dot {
  width: 6px; height: 6px; background: var(--accent); flex: none;
}

.syn-section { margin-top: 2.6rem; }
.syn-h {
  font-size: 1.18rem; font-weight: 500; color: var(--fg); margin: 0 0 0.25rem;
  padding-bottom: 0.5rem; border-bottom: 1px solid var(--border);
}
.syn-h::before {
  content: ""; display: inline-block; width: 3px; height: 0.85em;
  background: var(--accent); margin-right: 0.55rem; vertical-align: -1px;
}
.syn-sub { color: var(--fg-mute); font-size: 0.85rem; margin: 0.55rem 0 1rem; }

/* operator + matcher tables: syntax token on the left, meaning on the right */
.syn-table { display: flex; flex-direction: column; }
.syn-row {
  display: grid; grid-template-columns: minmax(0, 220px) 1fr; gap: 0.4rem 1.4rem;
  padding: 0.85rem 0; border-bottom: 1px solid var(--border-soft); align-items: start;
}
.syn-syntax > code {
  font-family: var(--font-mono); font-size: 0.84rem; color: var(--fg);
  background: var(--bg-code, rgba(127,127,127,0.12)); padding: 0.18rem 0.45rem;
  display: inline-block; white-space: nowrap;
}
.syn-name { color: var(--fg); font-size: 0.92rem; font-weight: 500; }
.syn-desc { color: var(--fg-dim); font-size: 0.88rem; line-height: 1.55; margin-top: 0.2rem; }
.syn-ex { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-top: 0.55rem; }
.syn-egg {
  display: inline-flex; align-items: center; gap: 0.34rem;
  text-decoration: none; border: 1px solid var(--accent-edge);
  background: var(--accent-soft); padding: 0.12rem 0.45rem; line-height: 1.5;
  color: var(--accent);
}
/* link icon, masked so it inherits the accent (theme-driven, never hardcoded) */
.syn-egg::before {
  content: ""; width: 0.74em; height: 0.74em; flex: none; opacity: 0.8;
  background: currentColor;
  -webkit-mask: var(--icon-link) center / contain no-repeat;
  mask: var(--icon-link) center / contain no-repeat;
}
.syn-egg > code {
  font-family: var(--font-mono); font-size: 0.76rem; color: inherit;
  white-space: nowrap;
}
.syn-egg:hover { border-color: var(--accent); background: var(--accent); color: var(--accent-ink); }
.syn-egg:hover::before { opacity: 1; }

/* worked-example recipes: a two-up grid of clickable cards */
.syn-recipes { display: grid; grid-template-columns: 1fr 1fr; gap: 0.7rem; }
.syn-recipe {
  display: flex; flex-direction: column; gap: 0.35rem; text-decoration: none;
  border: 1px solid var(--border); padding: 0.75rem 0.85rem;
  transition: border-color 120ms, background 120ms;
}
.syn-recipe:hover { border-color: var(--accent-edge); background: var(--bg-soft); }
.syn-recipe-q {
  font-family: var(--font-mono); font-size: 0.82rem; color: var(--accent);
  word-break: break-word;
}
.syn-recipe-note { color: var(--fg-dim); font-size: 0.83rem; line-height: 1.45; }

/* value-type legend above the field catalog */
.syn-legend {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.45rem 1.1rem;
  border: 1px solid var(--border-soft); background: var(--bg-soft);
  padding: 0.7rem 0.9rem; margin: 0 0 1.4rem;
}
.syn-legend-h {
  font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.07em;
  text-transform: uppercase; color: var(--fg-mute); margin-right: 0.2rem;
}
.syn-legend-item {
  display: inline-flex; align-items: center; gap: 0.4rem;
  color: var(--fg-dim); font-size: 0.8rem;
}

/* field catalog: groups, each with a header and a list of field rows */
.syn-group { margin-top: 1.8rem; }
.syn-group-head {
  display: flex; align-items: baseline; gap: 0.7rem; flex-wrap: wrap;
  padding-bottom: 0.45rem; border-bottom: 1px solid var(--border-soft); margin-bottom: 0.3rem;
}
.syn-group-name {
  font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--accent);
}
.syn-group-blurb { color: var(--fg-mute); font-size: 0.8rem; }
.syn-fields { display: flex; flex-direction: column; }
.syn-field { padding: 0.7rem 0; border-bottom: 1px solid var(--border-soft); }
.syn-field-top { display: flex; align-items: center; flex-wrap: wrap; gap: 0.5rem; }
.syn-field-name {
  font-family: var(--font-mono); font-size: 0.9rem; color: var(--fg); font-weight: 500;
}
.syn-kind {
  font-family: var(--font-mono); font-size: 0.66rem; letter-spacing: 0.04em;
  text-transform: uppercase; padding: 0.05rem 0.35rem;
  border: 1px solid var(--border); color: var(--fg-mute);
}
.syn-kind.kb-text    { border-color: var(--accent-edge); color: var(--accent); }
.syn-kind.kb-keyword { border-color: var(--border-bold); color: var(--fg-dim); }
.syn-kind.kb-number  { color: var(--fg-dim); }
.syn-kind.kb-ip      { color: var(--fg-dim); }
.syn-kind.kb-datetime{ color: var(--fg-dim); }
.syn-kind.kb-hash    { color: var(--fg-dim); }
.syn-kind.kb-geo     { color: var(--fg-dim); }
.syn-aliases {
  font-family: var(--font-mono); font-size: 0.74rem; color: var(--fg-mute);
}
.syn-field-desc { color: var(--fg-dim); font-size: 0.88rem; line-height: 1.55; margin-top: 0.3rem; }
.syn-field .syn-ex { margin-top: 0.45rem; }

.syn-foot { margin-top: 2.6rem; }

@media (max-width: 640px) {
  .syn-row { grid-template-columns: 1fr; gap: 0.3rem; }
  .syn-recipes { grid-template-columns: 1fr; }
}

/* ═════════════════════════════════════════════════════════════
   External-link confirmation modal (host page "Open" buttons)
   A lightweight overlay: fixed full-viewport backdrop, centered flat
   card with a hairline border (no shadows, no radius), matching the
   GMI Cloud design tokens. Mirrors the prompts.js modal pattern.
   ═════════════════════════════════════════════════════════════ */
.open-link-modal {
  position: fixed; inset: 0; z-index: 1000;
  display: flex; align-items: center; justify-content: center;
  padding: 1.25rem;
  background: rgba(0, 0, 0, 0.62);
}
.open-link-modal[hidden] { display: none; }
.open-link-modal-card {
  max-width: 460px; width: 100%;
  background: var(--bg); border: 1px solid var(--border-bold);
  padding: 1.4rem 1.5rem 1.25rem;
}
.open-link-modal-h {
  margin: 0 0 0.7rem; font-size: 1.05rem; color: var(--fg);
  letter-spacing: -0.01em;
}
.open-link-modal-warn {
  margin: 0 0 0.9rem; font-size: 0.86rem; line-height: 1.55;
  color: var(--fg-dim);
}
.open-link-modal-url {
  display: block; margin: 0 0 1.2rem; padding: 0.55rem 0.62rem;
  background: var(--bg-code); border: 1px solid var(--border-soft);
  color: var(--accent); font-size: 0.78rem;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.open-link-modal-actions {
  display: flex; gap: 0.55rem; justify-content: flex-end;
}
.open-link-modal-actions .btn { font-family: var(--font-mono); font-size: 0.82rem; padding: 0.42rem 0.9rem; }
body.modal-open { overflow: hidden; }

/* Async results slot: the shell paints instantly, then search.js swaps the
   rendered fragment into #srch-results. This is the interim loading state. */
.srch-results { min-height: 120px; }
.srch-loading {
  display: flex; align-items: center; gap: 12px; padding: 24px 2px;
  color: var(--fg-mute); font-family: var(--font-mono); font-size: 13px;
}
.srch-ldbar { position: relative; width: 44px; height: 2px; background: var(--border); overflow: hidden; }
.srch-ldbar::after {
  content: ""; position: absolute; top: 0; bottom: 0; width: 40%;
  background: var(--accent); animation: srch-load 1.1s ease-in-out infinite;
}
@keyframes srch-load { 0% { left: -40%; } 100% { left: 100%; } }
