
/* ---------------------------------------------------------------- focus */
/* Visible keyboard focus everywhere. :focus-visible, not :focus, so a mouse
   click doesn't leave a ring on a button — that difference is why the old
   sites that used :focus ended up removing focus styling altogether.
   Two-tone ring (accent + offset) so it reads on any surface in either
   theme; a single colour disappears against the accent-tinted cards. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--acc);
  outline-offset: 2px;
  border-radius: 4px;
}
/* Never remove the outline without replacing it. Kept as an explicit rule so
   a future 'outline:none' shows up as a conflict rather than silently
   winning. */
:focus:not(:focus-visible) { outline: none; }

/* Skip link: the first tab stop on every page, hidden until focused. A
   keyboard user should not have to tab the whole nav on 1,197 pages. */
.skip-link {
  position: absolute; left: 8px; top: -60px; z-index: 999;
  padding: 10px 16px; border-radius: 8px;
  background: var(--acc); color: var(--acc-ink);
  font-weight: 600; font-size: 14px;
  transition: top .12s ease-out;
}
.skip-link:focus { top: 8px; }

/* ---------------------------------------------------------- tap targets */
/* WCAG 2.5.8 asks for 24x24 minimum; 44px is the comfortable thumb target.
   The theme toggle shipped at 30x30 in six separate files. Raised here once,
   and the visual size is preserved by keeping the icon small — the target
   grows, the button doesn't look chunky. */
.theme-toggle,
.lang-picker summary {
  min-width: 44px;
  min-height: 44px;
}
/* Small inline controls that can't grow (table row actions, chips) get the
   target extended past their painted box instead. */
.tap-pad { position: relative; }
.tap-pad::after {
  content: ""; position: absolute;
  top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: max(100%, 44px); height: max(100%, 44px);
}

/* ------------------------------------------------------------ mobile */
@media (max-width: 640px) {
  /* iOS zooms the viewport when a focused input is under 16px. Every form
     field on the site was 13-14px, so tapping any of them yanked the page.
     16px on the CONTROL only — display type is untouched. */
  input, select, textarea { font-size: 16px !important; }

  /* Nothing may scroll the page sideways. Wide content scrolls inside its
     own container (below), never by moving the document. */
  html, body { overflow-x: hidden; }
}

/* Wide content — tables, charts, code — scrolls in its own box. Without this
   a 6-column table sets the page width on a phone and every other element
   inherits the overflow. */
.table-wrap,
.scroll-x {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  max-width: 100%;
}
/* Focusable so a keyboard user can scroll it; tabindex is set in markup, this
   just makes the affordance visible. */
.table-wrap:focus-visible,
.scroll-x:focus-visible { outline: 2px solid var(--acc); outline-offset: 2px; }

/* ------------------------------------------------------- state clarity */
/* Consistent loading / empty / stale / error treatments, so the same
   condition looks the same on every surface instead of each renderer
   inventing its own grey box. */
.state {
  display: flex; align-items: center; gap: 10px;
  padding: 14px 16px; border-radius: 10px;
  border: 1px solid var(--line);
  font-size: 13px; color: var(--ink-2); line-height: 1.5;
}
.state-loading { color: var(--ink-3); }
.state-empty   { color: var(--ink-3); }
.state-stale   { border-color: var(--deg); color: var(--deg); }
.state-error   { border-color: var(--down); color: var(--down); }
/* A spinner is decorative; the adjacent text is what a screen reader gets. */
.state-spin {
  width: 14px; height: 14px; flex-shrink: 0;
  border: 2px solid var(--line-2); border-top-color: var(--acc);
  border-radius: 50%; animation: state-spin .7s linear infinite;
}
@keyframes state-spin { to { transform: rotate(360deg); } }

/* --------------------------------------------------- reduced motion */
/* Honour the OS setting rather than assuming everyone wants the animation.
   Not "animation: none" globally — that would stop a spinner mid-frame and
   leave a static broken arc; slowed right down instead. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
  .state-spin { animation: none; border-top-color: var(--line-2); }
}

/* ------------------------------------------------------ screen readers */
/* Visually hidden but still announced. The clip-path form, not
   display:none (which removes it from the accessibility tree entirely) and
   not width:0 (which some readers skip). */
.sr-only {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

    /* === TOKENS === */
    /* Light is the default (no data-theme attr). Dark is opt-in via
       :root[data-theme="dark"]. Mirror of src/render/theme-tokens.js -
       keep the two blocks identical. Theme-independent tokens (radii,
       fonts, shadows) live once in :root. */
    :root {
      color-scheme: light;
      --bg: #f8fafc;
      --bg-1: #ffffff;
      --bg-2: #f1f5f9;
      --bg-3: #e2e8f0;
      --line: #e2e8f0;
      --line-2: #cbd5e1;
      --ink: #0c0f15;
      --ink-2: #475569;
      --ink-3: #6d7689;
      --ink-4: #94a3b8;

      --acc: #16a34a;
      --acc-soft: rgba(22,163,74,0.10);
      --acc-line: rgba(22,163,74,0.35);
      --acc-ink: #ffffff;

      --up: #16a34a;
      --down: #dc2626;
      --deg: #d97706;
      --up-soft: rgba(22,163,74,0.10);
      --down-soft: rgba(220,38,38,0.10);
      --deg-soft: rgba(217,119,6,0.10);

      --r: 10px;
      --r-sm: 6px;
      --r-lg: 18px;
      --shadow-1: 0 1px 2px rgba(15,23,42,0.06), 0 1px 3px rgba(15,23,42,0.10);
      --shadow-2: 0 12px 40px rgba(15,23,42,0.14);

      --f-sans: "Inter", ui-sans-serif, system-ui, sans-serif;
      --f-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
      --f-display: "Inter", ui-sans-serif, system-ui, sans-serif;
    }
    :root[data-theme="dark"] {
      color-scheme: dark;
      --bg: #07090d;
      --bg-1: #0c0f15;
      --bg-2: #11151d;
      --bg-3: #171c26;
      --line: #1f2532;
      --line-2: #2a3142;
      --ink: #eef2f8;
      --ink-2: #b7c0d0;
      --ink-3: #6d7689;
      --ink-4: #454c5c;

      --acc: #58f29a;
      --acc-soft: #58f29a22;
      --acc-line: #58f29a44;
      --acc-ink: #07090d;

      --up: #58f29a;
      --down: #ff5c6c;
      --deg: #ffc14d;
      --up-soft: rgba(88,242,154,.13);
      --down-soft: rgba(255,92,108,.14);
      --deg-soft: rgba(255,193,77,.14);
      --shadow-1: 0 1px 2px rgba(0,0,0,0.4);
      --shadow-2: 0 12px 40px rgba(0,0,0,0.5);
    }

    *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
    html, body { background: var(--bg); color: var(--ink); font-family: var(--f-sans); -webkit-font-smoothing: antialiased; }
    body { overflow-x: hidden; min-height: 100vh; line-height: 1.5; }
    a { color: inherit; text-decoration: none; }
    button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
    input { font: inherit; }

    /* Grid backdrop */
    .bg-grid {
      position: fixed; inset: 0; pointer-events: none; z-index: 0;
      background-image:
        linear-gradient(to right, var(--line) 1px, transparent 1px),
        linear-gradient(to bottom, var(--line) 1px, transparent 1px);
      background-size: 56px 56px;
      opacity: .35;
      mask-image: radial-gradient(ellipse 80% 60% at 50% 35%, #000 30%, transparent 75%);
      -webkit-mask-image: radial-gradient(ellipse 80% 60% at 50% 35%, #000 30%, transparent 75%);
    }

    .shell { position: relative; z-index: 1; max-width: 1280px; margin: 0 auto; padding: 0 24px; }

    @keyframes pulse { 0%,100% { opacity:1 } 50% { opacity:.35 } }
    @keyframes ringpulse { 0% { transform: scale(.6); opacity:.8; } 100% { transform: scale(1.25); opacity:0; } }
    @keyframes pop { from { transform: translateY(8px); opacity: 0; } to { transform: none; opacity: 1; } }
    @keyframes spin { to { transform: rotate(360deg); } }
    @keyframes scroll-up { 0% { transform: translateY(0); } 100% { transform: translateY(-50%); } }

    /* === TOP NAV === */
    .topbar {
      display: grid; grid-template-columns: 1fr auto 1fr; align-items: center;
      column-gap: 28px;
      padding: 14px 24px; border-bottom: 1px solid var(--line);
      position: sticky; top: 0; z-index: 20;
      background: color-mix(in oklab, var(--bg) 82%, transparent);
      backdrop-filter: blur(12px);
    }
    .mark { display: flex; align-items: center; gap: 10px; font-family: var(--f-mono); font-size: 13px; letter-spacing: -0.01em; }
    .mark .dot { width: 9px; height: 9px; border-radius: 50%; background: var(--acc); box-shadow: 0 0 10px var(--acc); animation: pulse 2.2s ease-in-out infinite; }
    .mark b { font-weight: 700; color: var(--ink); }
    .mark span { color: var(--ink-3); }
    .topbar .center { font-family: var(--f-mono); font-size: 11px; color: var(--ink-3); display: flex; gap: 16px; justify-content: center; letter-spacing: .04em; }
    .topbar .center b { color: var(--ink); font-weight: 500; }
    .topbar .center .stat-dot { display: inline-block; width: 6px; height: 6px; border-radius: 50%; background: var(--up); margin-right: 6px; vertical-align: middle; box-shadow: 0 0 0 0 var(--up); animation: statPulse 2.4s ease-out infinite; }
    @keyframes statPulse { 0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--up) 55%, transparent); } 70% { box-shadow: 0 0 0 5px transparent; } 100% { box-shadow: 0 0 0 0 transparent; } }
    @media (prefers-reduced-motion: reduce) { .topbar .center .stat-dot { animation: none; } }
    .topbar .right { display: flex; justify-content: flex-end; align-items: center; gap: 18px; font-size: 13px; color: var(--ink-2); }
    .topbar .right a:hover { color: var(--ink); }
    .theme-toggle {
      background: transparent; border: 1px solid var(--line); color: var(--ink-2);
      padding: 6px; border-radius: 6px; cursor: pointer;
      display: inline-flex; align-items: center; justify-content: center;
      width: 30px; height: 30px; flex-shrink: 0;
    }
    .theme-toggle:hover { color: var(--ink); border-color: var(--line-2); }
    .theme-toggle svg { width: 14px; height: 14px; display: block; }
    :root:not([data-theme="dark"]) .theme-toggle .ico-moon { display: none; }
    :root[data-theme="dark"] .theme-toggle .ico-sun { display: none; }
    /* Language picker, <details> dropdown in the nav. Click summary to
       open, click an item to navigate. No JS needed. */
    .lang-picker { position: relative; font-family: var(--f-mono); }
    .lang-picker summary {
      list-style: none; cursor: pointer; user-select: none;
      display: inline-flex; align-items: center; gap: 6px;
      padding: 5px 9px; border: 1px solid var(--line); border-radius: 6px;
      font-size: 11px; color: var(--ink-2); height: 30px;
    }
    .lang-picker summary::-webkit-details-marker { display: none; }
    .lang-picker summary:hover { color: var(--ink); border-color: var(--line-2); }
    .lang-picker .lang-flag { font-size: 13px; line-height: 1; }
    .lang-picker .lang-cur { letter-spacing: .02em; }
    .lang-picker .lang-menu {
      position: absolute; top: calc(100% + 4px); right: 0;
      min-width: 160px; padding: 4px;
      background: var(--bg-1); border: 1px solid var(--line); border-radius: 8px;
      display: flex; flex-direction: column; z-index: 30;
      box-shadow: 0 8px 24px rgba(0,0,0,0.25);
    }
    .lang-item {
      display: flex; align-items: center; gap: 8px;
      padding: 7px 10px; border-radius: 5px;
      font-size: 12px; color: var(--ink-2);
    }
    .lang-item:hover { background: var(--bg-2); color: var(--ink); }
    .lang-item.on { color: var(--ink); background: var(--bg-2); font-weight: 500; }
    @media (max-width: 640px) {
      .lang-picker summary { padding: 5px 8px; font-size: 10px; height: 30px; }
      .lang-picker .lang-cur { display: none; }
    }

    /* === ABOVE-THE-FOLD PROTECTION ZONE ===
       The header, hero, protocol tabs, input and Check button are the
       product. Nothing may be painted over them.

       AdSense runs in Auto-ads mode here (no explicit <ins> slots anywhere),
       which means Google picks placements — including in-page units injected
       into the DOM after load. Those are ordinary in-flow/absolute elements
       and WILL sit above content that has no stacking context of its own,
       which is how an ad ends up across the checker.

       So the fold elements each get their own stacking context at a z-index
       above any injected in-flow content. This does NOT touch Google's
       fixed-position anchor/vignette formats: hiding or repositioning a
       served ad is a policy violation and would put the account at risk.
       Those two formats are switched off in the AdSense dashboard, not here
       (Ad formats -> Anchor ads / Vignettes). See docs/ADS.md.

       `isolation:isolate` rather than a big z-index race: it creates the
       stacking context without inviting an escalation war with injected
       inline styles. */
    .topbar, .hero, .search-wrap, .proto-pills {
      position: relative;
      isolation: isolate;
      z-index: 10;
    }
    .topbar { z-index: 20; }        /* sticky, must outrank the hero */
    .search-wrap { z-index: 15; }   /* autocomplete opens over the hero */

    /* Reserved ad region. Auto ads that land here fill a box that already
       occupies its final height, so the fill causes no layout shift. Below
       the fold by construction: it sits after the checker in source order.
       Collapses to nothing for visitors with no ads (Pro, or a blocker) so
       we never leave a dead gap. */
    .ad-reserve {
      min-height: 280px;
      margin: 28px auto 0;
      width: min(970px, 100%);
      display: flex; align-items: center; justify-content: center;
      contain: layout;
    }
    .ad-reserve:empty { min-height: 0; margin: 0; }
    @media (max-width: 640px) { .ad-reserve { min-height: 250px; } }

    /* === HERO === */
    .hero { padding: 48px 0 20px; text-align: center; }
    .eyebrow {
      display: inline-flex; align-items: center; gap: 10px;
      font-family: var(--f-mono); font-size: 11px; color: var(--ink-3);
      padding: 6px 12px; border: 1px solid var(--line); border-radius: 999px;
      background: var(--bg-1);
    }
    .eyebrow .ping { width: 6px; height: 6px; border-radius: 50%; background: var(--up); box-shadow: 0 0 8px var(--up); }
    .h1 {
      font-family: var(--f-display);
      font-size: clamp(38px, 5.5vw, 72px);
      font-weight: 700;
      letter-spacing: -0.04em;
      line-height: 1.0;
      margin-top: 22px;
      color: var(--ink);
    }
    .h1 em { font-style: normal; color: var(--acc); }
    .h1-sub {
      max-width: 520px; margin: 22px auto 0; color: var(--ink-2);
      font-size: 15px; line-height: 1.55;
    }

    /* === SEARCH === */
    .search-wrap { position: relative; margin: 32px auto 0; width: min(720px, 100%); z-index: 5; }
    /* Subtle on-scroll reveal for below-the-fold sections. */
    .reveal { opacity: 0; transform: translateY(16px); transition: opacity .55s ease, transform .55s cubic-bezier(.22,.61,.36,1); will-change: opacity, transform; }
    .reveal.in { opacity: 1; transform: none; }
    @media (prefers-reduced-motion: reduce) { .reveal { opacity: 1; transform: none; transition: none; } }
    .search {
      display: grid; grid-template-columns: auto 1fr auto;
      align-items: stretch;
      background: var(--bg-1);
      border: 1px solid var(--line-2);
      border-radius: 14px;
      box-shadow: 0 30px 80px -20px rgba(0,0,0,.5), 0 0 0 6px color-mix(in oklab, var(--acc) 10%, transparent);
      overflow: hidden;
      transition: box-shadow .2s, border-color .2s;
    }
    .search:focus-within {
      border-color: var(--acc-line);
      box-shadow: 0 30px 80px -20px rgba(0,0,0,.5), 0 0 0 6px color-mix(in oklab, var(--acc) 22%, transparent);
    }
    .search .prefix {
      display: flex; align-items: center; gap: 10px; padding: 0 18px;
      font-family: var(--f-mono); font-size: 13px; color: var(--ink-3);
      border-right: 1px solid var(--line);
    }
    .search .prefix .g { width: 7px; height: 7px; border-radius: 50%; background: var(--acc); box-shadow: 0 0 8px var(--acc); animation: pulse 1.8s ease-in-out infinite; }
    .search input {
      border: 0; outline: 0; background: transparent; padding: 20px 16px;
      font-size: 17px; color: var(--ink); width: 100%;
      font-family: var(--f-sans);
      letter-spacing: -0.01em;
    }
    .search input::placeholder { color: var(--ink-4); }
    /* Catalog autocomplete dropdown, absolute below the form, hidden
       by default. Renders 1-8 suggestions filtered from the live
       dashboard payload so we don't need a separate /api/search call. */
    .autocomplete {
      position: absolute; left: 0; right: 0; top: calc(100% + 6px);
      list-style: none; padding: 6px; margin: 0;
      background: var(--bg-1); border: 1px solid var(--line-2);
      border-radius: 12px; box-shadow: 0 24px 48px -12px rgba(0,0,0,0.55);
      max-height: 360px; overflow-y: auto;
      z-index: 30;
    }
    .autocomplete[hidden] { display: none; }
    .autocomplete .ac-item {
      display: flex; align-items: center; gap: 10px;
      padding: 9px 12px; border-radius: 8px;
      cursor: pointer; color: var(--ink-2); transition: background .1s;
    }
    .autocomplete .ac-item:hover, .autocomplete .ac-item.on {
      background: var(--bg-2); color: var(--ink);
    }
    .autocomplete .ac-fav {
      width: 20px; height: 20px; border-radius: 4px;
      flex-shrink: 0; background: var(--bg-3); display: flex;
      align-items: center; justify-content: center; overflow: hidden;
    }
    .autocomplete .ac-fav img { width: 100%; height: 100%; object-fit: contain; }
    .autocomplete .ac-name { font-size: 14px; font-weight: 500; flex-shrink: 0; }
    .autocomplete .ac-dom {
      font-family: var(--f-mono); font-size: 11px; color: var(--ink-3);
      flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }
    .autocomplete .ac-state {
      width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0;
    }
    .autocomplete .ac-state.up { background: var(--up); box-shadow: 0 0 4px var(--up); }
    .autocomplete .ac-state.down { background: var(--down); box-shadow: 0 0 4px var(--down); }
    .autocomplete .ac-state.degraded { background: var(--deg); box-shadow: 0 0 4px var(--deg); }
    .autocomplete .ac-state.unknown { background: var(--ink-4); }
    .autocomplete b { color: var(--acc); font-weight: 600; }
    .search button.go {
      padding: 0 32px; font-family: var(--f-mono); font-size: 13px; font-weight: 700;
      letter-spacing: .10em; text-transform: uppercase;
      background: var(--acc); color: var(--acc-ink);
      display: flex; align-items: center; gap: 10px; white-space: nowrap;
    }
    .search button.go:hover { filter: brightness(1.05); }
    .search button.go:disabled { opacity: .7; cursor: wait; }

    /* === PROTOCOL PILLS === */
    .proto-pills {
      display: flex; gap: 6px; flex-wrap: wrap; justify-content: center;
      margin-bottom: 14px;
      font-family: var(--f-mono);
    }
    .proto-pill {
      padding: 8px 14px; border-radius: 999px;
      border: 1px solid var(--line); background: var(--bg-1); color: var(--ink-2);
      font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
      cursor: pointer; transition: all .15s;
      display: inline-flex; align-items: center; gap: 6px;
    }
    .proto-pill:hover { border-color: var(--line-2); color: var(--ink); }
    .proto-pill:focus-visible { outline: 2px solid var(--acc); outline-offset: 2px; }
    .proto-pill.on {
      background: color-mix(in oklab, var(--acc) 14%, var(--bg-1));
      border-color: var(--acc-line); color: var(--ink);
    }
    .proto-pill .pk {
      width: 6px; height: 6px; border-radius: 50%; background: var(--ink-4);
    }
    .proto-pill.on .pk { background: var(--acc); box-shadow: 0 0 6px var(--acc); }

    /* === HELPER TEXT UNDER SEARCH === */
    .search-helper {
      margin-top: 12px; text-align: center;
      font-family: var(--f-mono); font-size: 11px; color: var(--ink-3);
      letter-spacing: .02em;
      min-height: 16px; /* prevent layout shift when swapping copy */
    }
    .search-helper kbd {
      font-family: var(--f-mono); font-size: 10px; color: var(--ink-2);
      padding: 2px 6px; border-radius: 4px;
      background: var(--bg-2); border: 1px solid var(--line);
    }

    /* === EXAMPLES CHIP STRIP (under search) === */
    .ex-row {
      display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
      justify-content: center;
      margin: 14px auto 0; max-width: 720px;
    }
    .ex-row .ex-lbl {
      font-family: var(--f-mono); font-size: 10px; color: var(--ink-3);
      letter-spacing: .1em; text-transform: uppercase; margin-right: 4px;
    }
    .ex-chip {
      display: inline-flex; align-items: center; gap: 6px;
      font-family: var(--f-mono); font-size: 11px; color: var(--ink-2);
      padding: 5px 10px; border-radius: 6px;
      background: var(--bg-1); border: 1px solid var(--line);
      cursor: pointer; transition: border-color .12s, color .12s, background .12s;
    }
    .ex-chip:hover {
      color: var(--ink); border-color: var(--acc-line);
      background: var(--bg-2);
    }
    .ex-chip:focus-visible {
      outline: 2px solid var(--acc); outline-offset: 1px;
    }
    .ex-chip .ex-ico {
      width: 13px; height: 13px;
      color: var(--ink-3); stroke: currentColor;
      fill: none; stroke-width: 1.5;
      stroke-linecap: round; stroke-linejoin: round;
      flex-shrink: 0;
    }
    .ex-chip:hover .ex-ico,
    .ex-chip:focus-visible .ex-ico { color: var(--acc); }
    .ex-chip .ex-text { font-family: var(--f-mono); font-size: 11px; }
    @media (max-width: 520px) {
      .ex-row { gap: 5px; }
      .ex-chip { font-size: 10px; padding: 4px 8px; }
      .ex-chip .ex-ico { width: 11px; height: 11px; }
    }

    /* === HERO LIVE-PREVIEW CARD === */
    /* A miniature /check/ result rendered from real /api/dashboard data,
       rotated every 6s through 4 popular hot services. Hidden by default
       (hidden attr removed once data arrives) so the layout doesn't
       reflow or show an empty box during first load. */
    .hero-preview {
      display: grid; grid-template-columns: auto 1fr auto;
      align-items: center; gap: 16px;
      max-width: 720px; margin: 18px auto 0; padding: 14px 18px;
      border: 1px solid var(--line); border-radius: var(--r);
      background: var(--bg-1); color: inherit; text-decoration: none;
      transition: border-color .12s, background .12s, transform .08s;
    }
    .hero-preview:hover { border-color: var(--line-2); background: var(--bg-2); }
    .hero-preview:focus-visible { outline: 2px solid var(--acc); outline-offset: 1px; }
    .hero-preview.up    { box-shadow: inset 3px 0 0 var(--up); }
    .hero-preview.deg   { box-shadow: inset 3px 0 0 var(--deg); }
    .hero-preview.down  { box-shadow: inset 3px 0 0 var(--down); }
    .hero-preview .pv-id { display: flex; align-items: center; gap: 12px; min-width: 0; }
    .hero-preview .pv-logo {
      width: 34px; height: 34px; border-radius: 8px;
      background: var(--bg-3); border: 1px solid var(--line);
      display: flex; align-items: center; justify-content: center;
      flex-shrink: 0; overflow: hidden; position: relative;
    }
    .hero-preview .pv-logo img { width: 22px; height: 22px; border-radius: 4px; display: block; }
    .hero-preview .pv-logo .mono {
      position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
      font-family: var(--f-mono); font-size: 11px; font-weight: 700; color: var(--ink-3);
    }
    .hero-preview .pv-logo img + .mono { display: none; }
    /* Column flex so .pv-name and .pv-line stack vertically; min-width:0
       lets each child's overflow:hidden + ellipsis actually clip rather
       than letting inline text bleed into the .pv-regions grid cell. */
    .hero-preview .pv-text { display: flex; flex-direction: column; min-width: 0; }
    .hero-preview .pv-name { display: block; font-size: 13px; font-weight: 600; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .hero-preview .pv-line {
      display: block;
      font-family: var(--f-mono); font-size: 10px; color: var(--ink-3); margin-top: 2px;
      text-transform: uppercase; letter-spacing: .08em;
      overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }
    .hero-preview .pv-line .live { color: var(--acc); }
    .hero-preview .pv-line .pv-unchecked { color: var(--ink-3); }
    .hero-preview .pv-regions {
      display: grid; grid-template-columns: repeat(4, auto); gap: 14px;
      font-family: var(--f-mono); font-size: 10px; color: var(--ink-2);
      letter-spacing: .04em;
    }
    .hero-preview .pv-r { display: flex; align-items: center; gap: 5px; white-space: nowrap; }
    .hero-preview .pv-r .d { width: 6px; height: 6px; border-radius: 50%; background: var(--ink-4); flex-shrink: 0; }
    .hero-preview .pv-r .d.up   { background: var(--up);   box-shadow: 0 0 5px var(--up); }
    .hero-preview .pv-r .d.down { background: var(--down); box-shadow: 0 0 5px var(--down); }
    .hero-preview .pv-r .d.deg  { background: var(--deg);  box-shadow: 0 0 5px var(--deg); }
    .hero-preview .pv-r .ms { color: var(--ink); font-variant-numeric: tabular-nums; margin-left: 2px; }
    .hero-preview .pv-arrow { color: var(--ink-3); font-family: var(--f-mono); font-size: 11px; padding-left: 6px; }
    .hero-preview:hover .pv-arrow { color: var(--acc); }
    @media (max-width: 720px) {
      .hero-preview { grid-template-columns: auto 1fr; gap: 12px; padding: 12px 14px; }
      .hero-preview .pv-arrow { display: none; }
      .hero-preview .pv-regions { grid-column: 1 / -1; grid-template-columns: 1fr 1fr; gap: 8px 14px; margin-top: 4px; }
      .hero-preview .pv-line { font-size: 9px; }
    }

    /* === HOMEPAGE TRUST STRIP === */
    .trust-strip.home {
      display: flex; align-items: center; gap: 12px;
      max-width: 720px; margin: 18px auto 0; padding: 11px 16px;
      border: 1px solid var(--acc-line); background: var(--acc-soft, rgba(34,197,94,0.06));
      border-radius: var(--r);
      font-family: var(--f-mono); font-size: 11px; color: var(--ink-2);
      letter-spacing: .01em;
    }
    .trust-strip.home .ts-dot {
      width: 7px; height: 7px; border-radius: 50%;
      background: var(--acc); box-shadow: 0 0 6px var(--acc);
      flex-shrink: 0;
    }
    .trust-strip.home .ts-txt { flex: 1; min-width: 0; line-height: 1.55; }
    .trust-strip.home .ts-txt b { color: var(--ink); font-weight: 600; }
    .trust-strip.home .ts-link { color: var(--acc); font-weight: 600; white-space: nowrap; }
    .trust-strip.home .ts-link:hover { color: var(--ink); }
    @media (max-width: 640px) {
      .trust-strip.home { flex-wrap: wrap; font-size: 10px; }
    }

    /* === RESULT CARD === */
    .result { margin: 28px auto 0; width: min(720px, 100%); }
    .result-card {
      background: var(--bg-1); border: 1px solid var(--line);
      border-radius: var(--r-lg); overflow: hidden;
      animation: pop .35s cubic-bezier(.2,.9,.3,1.2);
    }
    .rc-top { display: grid; grid-template-columns: auto 1fr auto; gap: 20px; padding: 24px 24px 18px; align-items: center; }
    .verdict {
      width: 72px; height: 72px; border-radius: 18px;
      display: flex; align-items: center; justify-content: center; position: relative;
    }
    .verdict.up { background: var(--up-soft); border: 1px solid color-mix(in oklab, var(--up) 40%, transparent); color: var(--up); }
    .verdict.down { background: var(--down-soft); border: 1px solid color-mix(in oklab, var(--down) 40%, transparent); color: var(--down); }
    .verdict.deg { background: var(--deg-soft); border: 1px solid color-mix(in oklab, var(--deg) 40%, transparent); color: var(--deg); }
    .verdict .big { font-family: var(--f-mono); font-weight: 700; font-size: 22px; letter-spacing: -0.02em; }
    .verdict.up::after { content:""; position:absolute; inset:-6px; border-radius: 22px; border:1px solid var(--up); opacity:.3; animation: ringpulse 2.4s ease-out infinite; }
    .rc-title { min-width: 0; }
    .rc-title h3 { font-size: 20px; font-weight: 600; letter-spacing: -0.01em; display: flex; align-items: center; gap: 10px; }
    .rc-title h3 .fav { width: 18px; height: 18px; border-radius: 4px; background: var(--bg-3); display: inline-block; overflow: hidden; }
    .rc-title h3 .fav img { width: 100%; height: 100%; object-fit: contain; }
    .rc-title .sub { font-family: var(--f-mono); font-size: 12px; color: var(--ink-3); margin-top: 6px; display: flex; gap: 14px; flex-wrap: wrap; }
    .rc-title .sub b { color: var(--ink-2); font-weight: 500; }
    .rc-time { text-align: right; font-family: var(--f-mono); font-size: 11px; color: var(--ink-3); letter-spacing: .04em; }
    .rc-time span { color: var(--ink); }
    .regions { display: grid; grid-template-columns: repeat(4, 1fr); border-top: 1px solid var(--line); }
    .region { padding: 16px; border-right: 1px solid var(--line); display: flex; flex-direction: column; gap: 6px; }
    .region:last-child { border-right: 0; }
    .region .r-top { display: flex; align-items: center; gap: 8px; font-family: var(--f-mono); font-size: 10px; color: var(--ink-3); letter-spacing: .06em; text-transform: uppercase; }
    .region .r-top .d { width: 6px; height: 6px; border-radius: 50%; }
    .region .r-top .d.up { background: var(--up); box-shadow: 0 0 6px var(--up); }
    .region .r-top .d.down { background: var(--down); box-shadow: 0 0 6px var(--down); }
    .region .r-top .d.deg { background: var(--deg); box-shadow: 0 0 6px var(--deg); }
    .region .ms { font-family: var(--f-mono); font-size: 18px; color: var(--ink); font-variant-numeric: tabular-nums; letter-spacing: -0.02em; }
    .region .ms span { color: var(--ink-3); font-size: 11px; margin-left: 3px; }
    .rc-note {
      padding: 12px 24px; border-top: 1px solid var(--line);
      background: var(--deg-soft); color: var(--ink-2);
      font-size: 12.5px; line-height: 1.55;
    }
    .rc-note b { color: var(--ink); font-weight: 600; }
    .rc-note a { color: var(--acc); text-decoration: underline; text-decoration-thickness: 1px; }
    /* Vendor status strip. Its own block layout because it carries three
       lines — the vendor's headline, their incident titles, and the note
       reconciling their verdict with ours — and they must not run together. */
    .rc-vendor { display: flex; flex-direction: column; gap: 5px; }
    .rc-vendor .rc-inc { font-family: var(--f-mono); font-size: 11.5px; color: var(--ink-2); }
    .rc-cta { padding: 14px 24px; border-top: 1px solid var(--line); display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap; }
    .rc-cta .left { display: flex; gap: 8px; }
    .rc-cta a.sml {
      font-family: var(--f-mono); font-size: 11px; color: var(--ink-2);
      padding: 7px 12px; border: 1px solid var(--line); border-radius: var(--r-sm);
      transition: all .12s; cursor: pointer;
    }
    .rc-cta a.sml:hover { border-color: var(--line-2); color: var(--ink); }
    .rc-cta a.detail { color: var(--acc); font-family: var(--f-mono); font-size: 12px; font-weight: 500; display: inline-flex; align-items: center; gap: 6px; }
    .rc-cta a.detail:hover { gap: 10px; }

    /* Skeleton of the RESULT CARD while the 4 probes run. The card's shape
       is fully known in advance (verdict block, title, four method cells),
       which is exactly the case skeletons beat spinners: the wait reads as
       "your result is assembling", not "the page stalled". The caption
       still says what's actually happening. */
    .result-loading { padding: 12px 0 0; }
    .sk { background: var(--bg-3); border-radius: 8px; position: relative; overflow: hidden; }
    .sk::after { content:""; position:absolute; inset:0; transform: translateX(-100%);
      background: linear-gradient(90deg, transparent, color-mix(in oklab, var(--ink) 7%, transparent), transparent);
      animation: sk-sweep 1.4s ease-in-out infinite; }
    @media (prefers-reduced-motion: reduce) { .sk::after { animation: none; } }
    @keyframes sk-sweep { to { transform: translateX(100%); } }
    .sk-top { display: grid; grid-template-columns: auto 1fr auto; gap: 20px; padding: 24px 24px 18px; align-items: center; }
    .sk-verdict { width: 72px; height: 72px; border-radius: 18px; }
    .sk-line { height: 14px; }
    .sk-line.w60 { width: 60%; margin-bottom: 10px; }
    .sk-line.w40 { width: 40%; height: 10px; }
    .sk-time { width: 74px; height: 26px; }
    .sk-cells { display: grid; grid-template-columns: repeat(4, 1fr); border-top: 1px solid var(--line); }
    .sk-cell { padding: 16px; border-right: 1px solid var(--line); }
    .sk-cell:last-child { border-right: 0; }
    .sk-cell .sk-line { width: 70%; height: 9px; margin-bottom: 10px; }
    .sk-cell .sk-ms { width: 46px; height: 18px; }
    .sk-caption { padding: 12px 24px 14px; border-top: 1px solid var(--line); color: var(--ink-3); font-family: var(--f-mono); font-size: 11px; letter-spacing: .04em; }
    .result-error { padding: 20px; text-align: center; color: var(--down); font-family: var(--f-mono); font-size: 12px; border: 1px solid color-mix(in oklab, var(--down) 30%, var(--line)); border-radius: var(--r-lg); background: var(--down-soft); }

    /* === SERVICES GRID === */
    /* === HUB SHOWCASE, the specialty checkers (crypto / MC / games /
       AI / infra / tools) surfaced on the homepage body instead of
       living footer-only. Cards use the same token palette as the
       service grid so the row reads as part of one system. === */
    .hubs-section { margin-top: 56px; }
    .hubs-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 10px; margin-top: 14px; }
    .hub-card { position: relative; display: flex; flex-direction: column; gap: 10px; padding: 16px 18px; border: 1px solid var(--line); border-radius: 12px; background: var(--bg-1); overflow: hidden; }
    .hub-card:hover { border-color: var(--line-2); background: var(--bg-2); }
    .hub-top { display: flex; align-items: center; gap: 10px; }
    .hub-ico { width: 34px; height: 34px; border-radius: 9px; background: var(--bg-2); border: 1px solid var(--line); display: flex; align-items: center; justify-content: center; color: var(--acc); flex-shrink: 0; }
    .hub-ico svg { width: 17px; height: 17px; }
    .hub-name { font-size: 14px; font-weight: 600; color: var(--ink); letter-spacing: -0.01em; }
    .hub-live { margin-left: auto; width: 7px; height: 7px; border-radius: 50%; background: var(--up); flex-shrink: 0; }
    .hub-desc { font-size: 12px; color: var(--ink-3); line-height: 1.5; }
    .hub-go { font-family: var(--f-mono, 'JetBrains Mono', monospace); font-size: 10px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-3); margin-top: auto; }
    .hub-card:hover .hub-go { color: var(--acc); }
    @media (prefers-reduced-motion: no-preference) {
      .hub-card { transition: border-color .15s, background .15s, transform .1s; }
      .hub-card:hover { transform: translateY(-2px); }
      .hub-live { box-shadow: 0 0 0 0 rgba(34,197,94,0.5); animation: hub-pulse 2.2s ease-out infinite; }
      @keyframes hub-pulse { 0% { box-shadow: 0 0 0 0 rgba(34,197,94,0.45); } 70% { box-shadow: 0 0 0 6px rgba(34,197,94,0); } 100% { box-shadow: 0 0 0 0 rgba(34,197,94,0); } }
    }
    @media (max-width: 640px) { .hubs-grid { grid-template-columns: repeat(2, 1fr); gap: 8px; } .hub-card { padding: 13px 14px; } .hub-desc { font-size: 11px; } }

    /* === CONVERSION BAND — single honest upsell, brand-consistent === */
    .convert-band {
      margin-top: 56px; display: grid; grid-template-columns: 1.4fr 1fr; gap: 28px;
      align-items: center; padding: 28px 30px; border: 1px solid var(--line);
      border-radius: 14px; background: var(--bg-1);
    }
    .convert-band .cb-title { font-size: 22px; font-weight: 700; letter-spacing: -0.02em; color: var(--ink); margin: 0 0 8px; }
    .convert-band .cb-sub { font-size: 13.5px; color: var(--ink-2); line-height: 1.6; margin: 0 0 14px; }
    .convert-band .cb-sub b { color: var(--ink); font-weight: 600; }
    .convert-band .cb-list { list-style: none; padding: 0; margin: 0; display: flex; flex-wrap: wrap; gap: 8px 18px; }
    .convert-band .cb-list li { font-family: var(--f-mono); font-size: 11px; color: var(--ink-3); padding-left: 16px; position: relative; }
    .convert-band .cb-list li::before { content: "✓"; position: absolute; left: 0; color: var(--acc); font-weight: 700; }
    .convert-band .cb-action { display: flex; flex-direction: column; align-items: stretch; gap: 10px; }
    .convert-band .cb-btn {
      display: inline-flex; align-items: center; justify-content: center;
      min-height: 48px; padding: 0 26px; border-radius: 10px;
      background: var(--acc); color: var(--acc-ink);
      font-family: var(--f-mono); font-size: 13px; font-weight: 700;
      letter-spacing: .08em; text-transform: uppercase; text-decoration: none;
    }
    .convert-band .cb-btn:hover { filter: brightness(1.05); }
    .convert-band .cb-btn:focus-visible { outline: 2px solid var(--acc); outline-offset: 2px; }
    .convert-band .cb-fine { font-size: 11px; color: var(--ink-3); line-height: 1.5; text-align: center; }
    .convert-band .cb-fine a { color: var(--acc); font-weight: 600; }
    .convert-band .cb-fine a:hover { color: var(--ink); }
    @media (prefers-reduced-motion: no-preference) { .convert-band .cb-btn { transition: filter .15s; } }
    @media (max-width: 720px) {
      .convert-band { grid-template-columns: 1fr; gap: 18px; padding: 22px 20px; }
      .convert-band .cb-title { font-size: 19px; }
    }

    .services-section { margin-top: 64px; }
    .sec-head {
      display: flex; align-items: baseline; justify-content: space-between;
      padding: 0 4px; margin-bottom: 18px; flex-wrap: wrap; gap: 10px;
    }
    .sec-head .t {
      font-family: var(--f-display); font-size: 28px; font-weight: 700;
      letter-spacing: -0.025em;
    }
    .sec-head .m {
      font-family: var(--f-mono); font-size: 11px; color: var(--ink-3);
      letter-spacing: .08em; text-transform: uppercase;
    }
    .sec-head .m .mk { color: var(--acc); }
    .sec-head-right {
      display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
    }
    .refresh-btn {
      display: inline-flex; align-items: center; gap: 6px;
      padding: 5px 10px; border-radius: 6px;
      background: transparent; border: 1px solid var(--line);
      color: var(--ink-2); cursor: pointer;
      font-family: var(--f-mono); font-size: 10px; font-weight: 600;
      letter-spacing: .08em; text-transform: uppercase;
      transition: color .12s, border-color .12s, background .12s;
    }
    .refresh-btn:hover:not(:disabled) {
      color: var(--ink); border-color: var(--line-2); background: var(--bg-2);
    }
    .refresh-btn:disabled { cursor: progress; opacity: .85; }
    .refresh-btn .refresh-ico { display: block; }
    .refresh-btn.spinning .refresh-ico { animation: refresh-spin 0.9s linear infinite; }
    @keyframes refresh-spin { to { transform: rotate(360deg); } }

    /* min-height RESERVES the row before the client fills it.
       #countryRow and #filterRow ship EMPTY and are populated from
       /api/dashboard, so each collapsed to zero height on first paint and then
       jumped to a full chip row — about 70px of the page sliding down a
       fraction of a second after it appeared, which is what "the landing page
       is glitchy" looked like from the outside.
       32px is one chip row. The category row wraps to two on a wide viewport,
       so a little shift remains; the complete fix is server-rendering the
       chips, which is possible (getMonitoredHttpServices() is available to the
       renderer) and is a larger change than reserving space. */
    .filter-row { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 16px; min-height: 32px; }
    .filter {
      padding: 7px 14px; border: 1px solid var(--line); border-radius: 999px;
      background: var(--bg-1); color: var(--ink-2);
      font-size: 12px; font-weight: 500; cursor: pointer; transition: all .12s;
      display: inline-flex; align-items: center; gap: 7px;
      font-family: var(--f-sans);
    }
    .filter:hover { border-color: var(--line-2); color: var(--ink); }
    .filter.on { background: var(--ink); color: var(--bg); border-color: var(--ink); }
    .filter .count { font-family: var(--f-mono); font-size: 10px; color: var(--ink-3); }
    .filter.on .count { color: var(--bg-3); }
    /* Country row sits above the category row, same chip shape, extra
       leading flag emoji, and a "see all countries" jump button at the end. */
    .country-row { margin-bottom: 8px; }
    .country-row .filter .flag { font-size: 13px; line-height: 1; }
    .country-row .filter.more {
      color: var(--ink-3); border-style: dashed;
    }
    .country-row .filter.more:hover { color: var(--acc); border-color: var(--acc-line); }

    .svc-more { display: flex; justify-content: center; margin-top: 16px; }
    .svc-more:empty { display: none; }
    .svc-more-btn { padding: 10px 22px; border: 1px solid var(--line-2); border-radius: 999px; background: var(--bg-1); color: var(--ink-2); font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 12px; font-weight: 600; letter-spacing: 0.04em; cursor: pointer; transition: border-color .12s, background .12s, color .12s; }
    .svc-more-btn:hover { color: var(--ink); border-color: var(--acc-line); background: var(--bg-2); }
    .svc-grid {
      display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
      gap: 6px;
    }
    .svc {
      display: grid;
      grid-template-columns: auto 1fr auto;
      align-items: center; gap: 12px;
      padding: 14px 16px;
      border: 1px solid var(--line); border-radius: var(--r);
      background: var(--bg-1);
      cursor: pointer; transition: all .15s;
      position: relative; overflow: hidden;
    }
    .svc:hover { border-color: var(--line-2); background: var(--bg-2); transform: translateY(-1px); }
    .svc .fav { width: 22px; height: 22px; border-radius: 5px; background: var(--bg-3); overflow: hidden; flex-shrink: 0; display: flex; align-items: center; justify-content: center; font-family: var(--f-mono); font-weight: 700; font-size: 11px; color: var(--ink-2); }
    .svc .fav img { width: 100%; height: 100%; object-fit: contain; }
    .svc .name { font-size: 14px; font-weight: 500; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .svc .dom { font-family: var(--f-mono); font-size: 10px; color: var(--ink-3); margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .svc .st { display: flex; flex-direction: column; align-items: flex-end; gap: 3px; font-family: var(--f-mono); font-size: 10px; color: var(--ink-3); }
    .svc .st .d { width: 7px; height: 7px; border-radius: 50%; background: var(--ink-4); }
    .svc .st .d.up { background: var(--up); box-shadow: 0 0 6px var(--up); }
    .svc .st .d.down { background: var(--down); box-shadow: 0 0 6px var(--down); }
    .svc .st .d.deg { background: var(--deg); box-shadow: 0 0 6px var(--deg); }
    /* Pending/unknown, explicit muted dot, no glow. Differentiates a service
       we haven't probed yet from a confirmed-up one. */
    .svc .st .d.unknown { background: var(--ink-4); box-shadow: none; }
    .svc.unknown { opacity: 0.85; }
    /* Inline latency sparkline along the bottom edge of each card. Only
       rendered when the service has 2+ recent probes so flat / pending
       cards stay clean. Down probes show as gaps in the polyline. */
    .svc-spark {
      position: absolute; left: 0; right: 0; bottom: 0;
      height: 12px; width: 100%; pointer-events: none;
      opacity: 0.55;
    }
    .svc:hover .svc-spark { opacity: 0.85; }
    .svc-spark path { fill: none; stroke-width: 1.4; vector-effect: non-scaling-stroke; }
    .svc-spark .ln-up   { stroke: var(--up); }
    .svc-spark .ln-deg  { stroke: var(--deg); }
    .svc-spark .ln-down { stroke: var(--down); }
    .svc-spark .ln-mix  { stroke: var(--acc); }
    .svc-spark .dt-down { fill: var(--down); }
    .svc .st .n { font-variant-numeric: tabular-nums; }
    .svc.down::after { content:""; position:absolute; inset: 0 auto 0 0; width: 3px; background: var(--down); }
    .svc.deg::after { content:""; position:absolute; inset: 0 auto 0 0; width: 3px; background: var(--deg); }
    /* Partner cards (sister-site cross-promo), softer accent border, no
       coloured side-bar (status colour still wins if down/deg via class
       order: ".svc.partner.down" matches both rules, .down wins on left bar). */
    .svc.partner { border-color: var(--acc-line); background: linear-gradient(180deg, var(--bg-1), color-mix(in oklab, var(--acc-soft, rgba(34,197,94,0.06)) 60%, transparent)); }
    .svc.partner:hover { border-color: var(--acc); }
    .svc .name .partner-tag {
      display: inline-block; vertical-align: 1px; margin-left: 6px;
      font-family: var(--f-mono); font-size: 8px; font-weight: 600;
      letter-spacing: .12em; padding: 2px 5px; border-radius: 3px;
      background: var(--bg-3); color: var(--acc);
      border: 1px solid var(--acc-line);
    }

    /* === PUBLISHER STATUS === */
    .pub-section { margin-top: 48px; }
    .pub-grid {
      display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
      gap: 6px;
    }
    .pub {
      display: grid; grid-template-columns: auto 1fr auto;
      align-items: center; gap: 12px;
      padding: 14px 16px;
      border: 1px solid var(--line); border-radius: var(--r);
      background: var(--bg-1); position: relative; overflow: hidden;
      color: inherit; text-decoration: none;
      transition: border-color .12s, background .12s;
    }
    a.pub:hover { border-color: var(--line-2); background: var(--bg-2); }
    a.pub:focus-visible { outline: 2px solid var(--acc); outline-offset: 1px; }
    .pub .icon {
      width: 28px; height: 28px; border-radius: 6px;
      display: flex; align-items: center; justify-content: center;
      font-family: var(--f-mono); font-size: 11px; font-weight: 700;
      background: var(--bg-3); color: var(--ink-2);
      flex-shrink: 0; overflow: hidden; position: relative;
    }
    .pub .icon img { width: 18px; height: 18px; border-radius: 3px; display: block; }
    .pub .icon .mono { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; }
    .pub .icon img + .mono { display: none; }
    .pub .pub-name { font-size: 13px; font-weight: 500; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .pub .pub-desc { font-family: var(--f-mono); font-size: 10px; color: var(--ink-3); margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .pub .pub-st { display: flex; align-items: center; gap: 6px; font-family: var(--f-mono); font-size: 10px; color: var(--ink-3); text-transform: uppercase; letter-spacing: .05em; }
    .pub .pub-st .d { width: 7px; height: 7px; border-radius: 50%; background: var(--ink-4); }
    .pub .pub-st .d.up { background: var(--up); box-shadow: 0 0 6px var(--up); }
    .pub .pub-st .d.down { background: var(--down); box-shadow: 0 0 6px var(--down); }
    .pub .pub-st .d.deg { background: var(--deg); box-shadow: 0 0 6px var(--deg); }
    .pub.down::after, .pub.deg::after { content:""; position:absolute; inset: 0 auto 0 0; width: 3px; }
    .pub.down::after { background: var(--down); }
    .pub.deg::after { background: var(--deg); }

    /* === OUTAGE STRIP === */
    .outage-strip {
      margin-top: 48px;
      border: 1px solid color-mix(in oklab, var(--down) 40%, var(--line));
      background: linear-gradient(90deg, var(--down-soft), transparent 60%);
      border-radius: var(--r);
      padding: 14px 18px;
      display: none; align-items: center; gap: 14px;
      flex-wrap: wrap;
    }
    .outage-strip.on { display: flex; }
    .outage-strip .tag {
      font-family: var(--f-mono); font-size: 10px; letter-spacing: .14em;
      padding: 4px 8px; border-radius: 4px; background: var(--down); color: #fff;
      font-weight: 700;
    }
    .outage-strip .msg { flex: 1; min-width: 200px; font-size: 13px; color: var(--ink); }
    .outage-strip .msg b { color: var(--down); }
    .outage-strip .t { font-family: var(--f-mono); font-size: 11px; color: var(--ink-3); }
    .outage-strip .outage-row { display: flex; align-items: center; gap: 8px; min-width: 0; flex: 1 1 220px; padding: 4px 8px; border-radius: 6px; transition: background .12s; color: inherit; }
    .outage-strip .outage-row:hover { background: rgba(239,68,68,0.08); }
    .outage-strip .outage-more { font-family: var(--f-mono); font-size: 11px; color: var(--down); font-weight: 600; padding: 4px 8px; }
    .outage-strip .outage-more:hover { text-decoration: underline; }
    /* Distinct banner for when OUR monitoring infrastructure can't
       reach upstream services, sandbox / CI / restricted egress /
       real ISP outage on our side. Different color from the red
       outage strip so users can tell it's an issue with us, not the
       services. */
    .mon-offline {
      display: none; flex-wrap: wrap; align-items: center; gap: 14px;
      margin-top: 16px; padding: 14px 18px;
      border: 1px solid color-mix(in oklab, var(--deg) 45%, var(--line));
      background: linear-gradient(90deg, color-mix(in oklab, var(--deg) 12%, transparent), transparent 60%);
      border-radius: var(--r);
    }
    .mon-offline.on { display: flex; }
    .mon-offline .tag {
      font-family: var(--f-mono); font-size: 10px; letter-spacing: .14em;
      padding: 4px 8px; border-radius: 4px; background: var(--deg); color: #000;
      font-weight: 700;
    }
    .mon-offline .msg { flex: 1; min-width: 200px; font-size: 13px; color: var(--ink); }
    .mon-offline .msg b { color: var(--deg); }
    .mon-offline .t { font-family: var(--f-mono); font-size: 11px; color: var(--ink-3); }
    .nav-outages { position: relative; }
    .nav-outage-dot {
      display: inline-block; width: 7px; height: 7px; border-radius: 50%;
      background: var(--down); margin-left: 6px; vertical-align: 1px;
      box-shadow: 0 0 0 0 rgba(239,68,68,0.55); animation: nav-outage-pulse 1.6s ease-out infinite;
    }
    @keyframes nav-outage-pulse {
      0%   { box-shadow: 0 0 0 0 rgba(239,68,68,0.55); }
      70%  { box-shadow: 0 0 0 6px rgba(239,68,68,0); }
      100% { box-shadow: 0 0 0 0 rgba(239,68,68,0); }
    }

    /* === FOOTER === */
    footer { margin-top: 96px; padding: 48px 0 32px; border-top: 1px solid var(--line); }
    .foot-grid { display: grid; grid-template-columns: 2fr 1fr 1fr 1fr 1fr; gap: 32px; padding: 0 4px; }
    .foot-grid .col h3 {
      font-family: var(--f-mono); font-size: 10px; color: var(--ink-3);
      letter-spacing: .12em; text-transform: uppercase;
      margin-bottom: 14px; font-weight: 600;
    }
    .foot-grid ul { list-style: none; display: flex; flex-direction: column; gap: 8px; }
    .foot-grid li { font-size: 13px; }
    .foot-grid a { color: var(--ink-2); }
    .foot-grid a:hover { color: var(--ink); }
    .foot-brand .lrg {
      font-family: var(--f-display); font-size: 44px; font-weight: 700;
      letter-spacing: -0.035em; line-height: 1;
    }
    .foot-brand .lrg em { font-style: normal; color: var(--acc); }
    .foot-brand p { color: var(--ink-3); font-size: 13px; margin-top: 14px; max-width: 280px; line-height: 1.6; }
    .foot-bot { padding: 24px 4px 0; margin-top: 36px; border-top: 1px solid var(--line); display: flex; justify-content: space-between; flex-wrap: wrap; gap: 10px; font-family: var(--f-mono); font-size: 11px; color: var(--ink-3); }

    /* === RESPONSIVE === */
    @media (max-width: 860px) {
      .foot-grid { grid-template-columns: 1fr 1fr; }
      .regions { grid-template-columns: repeat(2, 1fr); }
      .regions .region:nth-child(2) { border-right: 0; }
      .topbar .center { display: none; }
      .topbar { grid-template-columns: auto 1fr; }
      .topbar .right { display: flex; gap: 8px; }
      .topbar .right a { display: none; }
      .topbar .right .theme-toggle { display: inline-flex; }
      .rc-top { grid-template-columns: auto 1fr; }
      .rc-time { grid-column: 1 / -1; text-align: left; }
      .hero { padding: 32px 0 12px; }
      .proto-pill { padding: 7px 11px; font-size: 10px; letter-spacing: .04em; }
      .search input { padding: 16px 14px; font-size: 15px; }
      .search button.go { padding: 0 18px; font-size: 11px; }
      .search-helper { font-size: 10px; }
      /* Trim prose-heavy blocks on phones, the chip row + services grid
         carry the same signal in fewer pixels. */
      .h1-sub { display: none; }
      .trust-strip.home { display: none; }
      .search-helper { display: none; }
    }

    /* === MOBILE POLISH (≤520px / phones) ===
       Edits below tighten tap targets, kill horizontal scroll, and
       cut visual noise that doesn't carry information at narrow widths.
       Together they bring the homepage to "actually pleasant on a
       320×568 iPhone SE" rather than "fits, technically." */
    @media (max-width: 520px) {
      /* Tighter outer padding so cards don't crowd the viewport edge */
      .page { padding: 0 14px; }

      /* Hero preview is eye-candy that fragments below 520px, every
         label collides with the regions grid. Hide it; the static
         services grid below tells the same story. */
      .hero-preview { display: none !important; }

      /* H1 line-height + size, was wrapping awkwardly */
      .h1 { font-size: 36px; line-height: 1.05; letter-spacing: -0.025em; }

      /* Search bar: bigger tap target, full-width CTA below input */
      .search { grid-template-columns: 1fr; border-radius: 12px; }
      .search .prefix { display: none; }
      .search input { padding: 18px 16px; font-size: 16px; }
      .search button.go { width: 100%; min-height: 48px; padding: 14px; font-size: 12px; border-radius: 0 0 12px 12px; }

      /* Services grid: each card spans the full row + has more vertical
         room to tap. The previous layout produced 230px cards with
         tight 14px padding, tappable but cramped. */
      .svc-grid { gap: 8px; grid-template-columns: 1fr; }
      .svc { min-height: 56px; padding: 14px 16px; }
      .svc .name { font-size: 15px; }
      .svc .dom { font-size: 11px; }

      /* Outage strip + monitoring-offline banner: column-stacked when
         the row would wrap awkwardly */
      .outage-strip { gap: 8px; padding: 12px 14px; }
      .outage-strip .outage-row { flex: 1 1 100%; }
      .mon-offline { gap: 8px; padding: 12px 14px; }

      /* Filter / country chip rows scroll horizontally instead of
         wrapping to 4+ rows. Touch-friendly. */
      .filter-row { flex-wrap: nowrap; overflow-x: auto; padding-bottom: 4px; -webkit-overflow-scrolling: touch; }
      .filter-row::-webkit-scrollbar { display: none; }
      .filter-row .filter { flex-shrink: 0; }

      /* Refresh button alongside "updated", lets the row stack
         vertically rather than wrap into two crowded lines */
      .sec-head { flex-direction: column; align-items: flex-start; gap: 8px; }
      .sec-head-right { width: 100%; justify-content: space-between; }

      /* Footer: collapse to single column at the very narrowest widths
         so each link list stays scannable */
      .foot-grid { grid-template-columns: 1fr !important; gap: 24px; }

      /* Sec-head H2 ("Monitoring 109+ services"), smaller on mobile
         so it doesn't crowd the meta line */
      .sec-head .t { font-size: 22px; }

    }

    /* Phone landscape / very small tablets, keep the H1 from
       overflowing the viewport on iPhone SE landscape (568px) */
    @media (max-width: 380px) {
      .h1 { font-size: 30px; }
      .sec-head .t { font-size: 19px; }
    }
  