/* ============================================================
   NetScan UK — Cyberpunk Neon Theme
   v1.0.5
   ============================================================ */

:root {
  --bg: #07070f;
  --bg-2: #0a0a14;
  --bg-3: #11112090;
  --panel: rgba(15, 15, 28, 0.78);
  --panel-2: rgba(20, 20, 36, 0.85);
  --border: rgba(0, 240, 255, 0.18);
  --border-strong: rgba(0, 240, 255, 0.5);

  --neon-cyan: #00f0ff;
  --neon-magenta: #ff00e1;
  --neon-green: #00ff88;
  --neon-purple: #a200ff;
  --neon-yellow: #ffe600;

  --text: #e4e6ff;
  --text-dim: #8c8fb3;
  --text-faint: #5a5d80;
  /* Referenced by .districts-prose, which fell back to rgba(255,255,255,.55)
     because this was never defined. Same value, now actually a token so a
     theme can override it. */
  --text-muted: rgba(255, 255, 255, 0.55);

  --radius: 4px;
  --radius-lg: 8px;

  --font-display: 'Orbitron', 'Segoe UI', system-ui, sans-serif;
  --font-mono: 'Share Tech Mono', 'JetBrains Mono', Consolas, monospace;
  --font-body: 'Rajdhani', 'Segoe UI', system-ui, sans-serif;

  --shadow-cyan: 0 0 12px rgba(0, 240, 255, 0.45), 0 0 32px rgba(0, 240, 255, 0.15);
  --shadow-magenta: 0 0 12px rgba(255, 0, 225, 0.45), 0 0 32px rgba(255, 0, 225, 0.15);

  /* Surface tints used by the per-template style blocks (browse, calculator).
     They live here rather than as literals in those templates so a theme can
     actually reach them. */
  --tint: rgba(0, 240, 255, 0.04);
  --tint-strong: rgba(0, 240, 255, 0.08);
  --tint-accent: rgba(255, 0, 225, 0.06);
  --border-accent: rgba(255, 0, 225, 0.25);
  --accent-grad: linear-gradient(135deg, #00f0ff, #ff00e1);
  --on-accent: #08081a;
}


/* ============================================================
   LIGHT THEME  —  opt in with <html data-theme="light">
   ------------------------------------------------------------
   Added on `develop` 2026-08-26 so a lighter look can be compared
   side by side against the dark original before either is chosen.

   Two things this is NOT: it is not the dark palette with a pale
   background, and it is not the same neons on white. Pure neon
   (#00f0ff) is close to unreadable on a light ground — roughly 1.5:1
   against white — so each brand hue is taken to a darker, more
   saturated version of ITSELF. Same hue family, same identity,
   legible contrast.

   The glows are the other half. Twenty selectors carry neon
   text-shadow/box-shadow that reads as a smudge on light, so they are
   neutralised here rather than left to blur. Structure, weight and
   colour carry the emphasis instead.
   ============================================================ */
:root[data-theme="light"] {
  --bg: #F1F4F7;
  --bg-2: #FFFFFF;
  --bg-3: #E7ECF1;
  --panel: rgba(255, 255, 255, 0.96);
  --panel-2: #FFFFFF;
  --border: rgba(10, 80, 95, 0.16);
  --border-strong: rgba(10, 80, 95, 0.42);

  /* Same hues, taken deep enough to read on a light ground */
  --neon-cyan: #00707F;
  --neon-magenta: #B4008C;
  --neon-green: #0B7A45;
  --neon-purple: #6320B0;
  --neon-yellow: #8A6A00;

  --text: #0E141A;
  --text-dim: #46525C;
  --text-faint: #78838D;

  /* Real drop shadows, not glows */
  --shadow-cyan: 0 1px 2px rgba(14, 20, 26, .06), 0 4px 14px rgba(0, 112, 127, .12);
  --shadow-magenta: 0 1px 2px rgba(14, 20, 26, .06), 0 4px 14px rgba(180, 0, 140, .12);
}

/* Kill the neon bloom — on light it reads as a printing error. */
:root[data-theme="light"] .logo-net,
:root[data-theme="light"] .logo-scan,
:root[data-theme="light"] .hero-title-neon,
:root[data-theme="light"] .t-cyan,
:root[data-theme="light"] .t-magenta,
:root[data-theme="light"] .t-green,
:root[data-theme="light"] .winner-name,
:root[data-theme="light"] .winner-score-num,
:root[data-theme="light"] .rank-card .rk-overall,
:root[data-theme="light"] .rank-card.is-winner .rk-overall,
:root[data-theme="light"] .deal-price { text-shadow: none; }

:root[data-theme="light"] .chip:hover,
:root[data-theme="light"] .deal-tab.is-active,
:root[data-theme="light"] .section-title::after,
:root[data-theme="light"] .deals-freshness .freshness-live { box-shadow: none; }

/* Score bars keep their colour coding but become solid, not luminous.
   The dark theme fades each bar to a pale tint at its right end, which works as
   a glow on black and vanishes on white — a 100% bar literally disappeared into
   the page. Solid fills, and a track with a real edge so an empty bar is still
   visibly a bar. */
:root[data-theme="light"] .bar-5g,
:root[data-theme="light"] .bar-4g,
:root[data-theme="light"] .bar-3g { box-shadow: none; }
:root[data-theme="light"] .bar-5g { background: var(--neon-cyan); }
:root[data-theme="light"] .bar-4g { background: var(--neon-magenta); }
:root[data-theme="light"] .bar-3g { background: var(--neon-green); }
:root[data-theme="light"] .bar-track {
  background: rgba(10, 80, 95, .09);
  border: 1px solid rgba(10, 80, 95, .10);
}

/* The money button stays the loudest thing on the page, just without the halo */
:root[data-theme="light"] .switch-primary {
  color: #FFFFFF;
  box-shadow: 0 1px 2px rgba(14, 20, 26, .10), 0 6px 18px rgba(0, 112, 127, .22);
}
:root[data-theme="light"] .switch-primary:hover,
:root[data-theme="light"] .switch-primary:focus-visible {
  box-shadow: 0 2px 4px rgba(14, 20, 26, .12), 0 10px 26px rgba(0, 112, 127, .30);
}

/* Panels were translucent over a dark page; on light they need a real edge */
:root[data-theme="light"] .how-card,
:root[data-theme="light"] .rank-card,
:root[data-theme="light"] .deal-card,
:root[data-theme="light"] .op-card {
  background: var(--panel-2);
  border: 1px solid var(--border);
  box-shadow: 0 1px 2px rgba(14, 20, 26, .05);
}

:root[data-theme="light"] .site-header,
:root[data-theme="light"] .site-footer {
  background: var(--bg-2);
  border-color: var(--border);
}

/* The dark page paints its background with three full-page DIVS in the markup —
   .bg-grid, .bg-scanlines and .bg-glow — not with body::before/::after. They sit
   over the body, so without this the light body was completely hidden and the
   headings rendered near-black on near-black. Found by asking the browser what it
   had actually painted, after the computed body background came back correctly
   light and the page still looked dark. */
:root[data-theme="light"] .bg-scanlines,
:root[data-theme="light"] .bg-glow { display: none; }

/* Keep a whisper of the grid so the page is not a flat white sheet, but at an
   intensity that reads as paper texture rather than as a screen. */
:root[data-theme="light"] .bg-grid {
  background-image:
    linear-gradient(180deg, #FFFFFF 0%, #EDF1F5 100%),
    linear-gradient(rgba(10, 80, 95, .045) 1px, transparent 1px),
    linear-gradient(90deg, rgba(10, 80, 95, .045) 1px, transparent 1px);
  background-size: auto, 44px 44px, 44px 44px;
}

/* ============================================================
   BIG NUMBER EDITORIAL  —  opt in with <html data-theme="editorial">
   ------------------------------------------------------------
   Chosen by Cezary on 2026-08-26 from ten directions. The brief it has to
   answer is that the first light theme was "white and quite boring", so this
   one cannot rely on the background being pale to feel different. Three rules
   carry it instead:

   1. THE NUMBER IS THE DESIGN. A coverage score is the only thing a visitor
      came for, so it is set in Fraunces at up to 9rem — larger than the page
      title. Nothing else on the page is allowed to compete with it.

   2. RED IS RESERVED. Exactly one hue is spent, and it is spent only on the
      winner and the button that earns money. Signal bars are a tonal ramp of
      ink instead of three competing colours, which also encodes the hierarchy
      honestly: 5G reads darkest because 5G matters most.

   3. RULES, NOT CARDS. Hairline dividers and generous space replace panels,
      borders and shadows. On a light ground a bordered box reads as clutter;
      a rule reads as a broadsheet.

   The neon tokens are reused rather than renamed so every existing component
   inherits the theme without being touched — --neon-cyan becomes ink,
   --neon-magenta becomes the single red.
   ============================================================ */
:root[data-theme="editorial"] {
  --bg: #FBFAF8;
  --bg-2: #FFFFFF;
  --bg-3: #F3F0EA;
  --panel: #FFFFFF;
  --panel-2: #FFFFFF;
  --border: rgba(20, 17, 13, 0.13);
  --border-strong: rgba(20, 17, 13, 0.85);

  /* Ink for structure, one red for money. The green is a muted olive used only
     where the dark theme signals "live" — it must never read as a fourth accent. */
  --neon-cyan: #14110D;
  /* Same vermilion, one shade deeper. #C8452C passed on paper (4.63) but not
     on the tinted panel (4.25) for small text; this clears both and also
     improves white-on-red from 4.83 to 5.38. */
  --neon-magenta: #BE3E25;
  --neon-green: #4A5C3D;
  --neon-purple: #14110D;
  --neon-yellow: #8A6A00;

  --text: #14110D;
  --text-dim: #5C564C;
  /* #8A8378 measured 3.3-3.75:1 against the three grounds this theme actually
     paints -- under AA for the 11-13px labels that use it. #706A5E clears 4.5
     on all three (5.15 paper / 4.72 tint / 5.37 white). */
  --text-faint: #706A5E;
  --text-muted: #5C564C;

  --radius: 0px;
  --radius-lg: 2px;

  --font-display: 'Fraunces', Georgia, 'Times New Roman', serif;
  --font-body: 'Inter', 'Segoe UI', system-ui, sans-serif;
  --font-mono: 'Inter', 'Segoe UI', system-ui, sans-serif;

  --shadow-cyan: none;
  --shadow-magenta: none;

  /* The ink ramp the signal bars are drawn from */
  --ink-5g: #14110D;
  --ink-4g: #6E6558;
  --ink-3g: #B7AFA2;

  /* On paper a tint is a lighter paper, not a coloured film, and the gradient
     collapses to the one reserved red. */
  --tint: #FFFFFF;
  --tint-strong: #F3F0EA;
  --tint-accent: rgba(190, 62, 37, 0.05);
  --border-accent: rgba(190, 62, 37, 0.30);
  --accent-grad: #BE3E25;
  --on-accent: #FFFFFF;
}

/* ---- Ground: flat warm paper. No grid, no scanlines, no glow. ------------- */
:root[data-theme="editorial"] .bg-scanlines,
:root[data-theme="editorial"] .bg-glow { display: none; }
:root[data-theme="editorial"] .bg-grid {
  background: #FBFAF8;
  background-image: none;
}
:root[data-theme="editorial"] .bg-grid::before { display: none; }

/* ---- Kill every neon bloom -------------------------------------------------
   Same selector list as the light theme: these carry text-shadow or box-shadow
   that reads as a printing fault on paper. */
:root[data-theme="editorial"] .logo-net,
:root[data-theme="editorial"] .logo-scan,
:root[data-theme="editorial"] .hero-title-neon,
:root[data-theme="editorial"] .t-cyan,
:root[data-theme="editorial"] .t-magenta,
:root[data-theme="editorial"] .t-green,
:root[data-theme="editorial"] .winner-name,
:root[data-theme="editorial"] .winner-score-num,
:root[data-theme="editorial"] .rank-card .rk-overall,
:root[data-theme="editorial"] .rank-card.is-winner .rk-overall,
:root[data-theme="editorial"] .deal-price,
:root[data-theme="editorial"] a:hover { text-shadow: none; }

:root[data-theme="editorial"] .chip:hover,
:root[data-theme="editorial"] .deal-tab.is-active,
:root[data-theme="editorial"] .section-title::after,
:root[data-theme="editorial"] .deals-freshness .freshness-live,
:root[data-theme="editorial"] .hero-trust-dot,
:root[data-theme="editorial"] .hero-badge .dot,
:root[data-theme="editorial"] .logo-mark,
:root[data-theme="editorial"] .logo-img { box-shadow: none; filter: none; }

/* The winner panel sweeps a moving highlight across itself. On paper that is a
   smear travelling over the one number the page exists to show. */
:root[data-theme="editorial"] .winner::before { display: none; animation: none; }

/* ---- Body + links ---------------------------------------------------------
   Editorial links are ink with a rule under them, not a coloured word. The red
   is held back for the button, so hovering promotes rather than recolours. */
:root[data-theme="editorial"] body {
  font-family: var(--font-body);
  font-size: 17px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}
:root[data-theme="editorial"] a {
  color: var(--text);
  text-decoration: underline;
  text-decoration-color: rgba(20, 17, 13, 0.28);
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
}
:root[data-theme="editorial"] a:hover {
  color: var(--neon-magenta);
  text-decoration-color: var(--neon-magenta);
}
/* Anchors that are really components must not be underlined as prose. */
:root[data-theme="editorial"] a.deal-card,
:root[data-theme="editorial"] a.region-card,
:root[data-theme="editorial"] a.area-card,
:root[data-theme="editorial"] a.rank-card,
:root[data-theme="editorial"] a.winner-cta,
:root[data-theme="editorial"] a.switch-primary,
:root[data-theme="editorial"] a.switch-alt,
:root[data-theme="editorial"] a.chip,
:root[data-theme="editorial"] .logo,
:root[data-theme="editorial"] .site-header a,
:root[data-theme="editorial"] .site-footer a { text-decoration: none; }
:root[data-theme="editorial"] .site-footer a:hover,
:root[data-theme="editorial"] .site-header a:hover { text-decoration: underline; }

/* ---- Masthead: a newspaper nameplate, not a logotype --------------------- */
:root[data-theme="editorial"] .site-header,
:root[data-theme="editorial"] .site-footer {
  background: var(--bg);
  border-color: rgba(20, 17, 13, 0.16);
}
:root[data-theme="editorial"] .logo-text {
  font-family: var(--font-display);
  font-variation-settings: 'opsz' 144;
  font-weight: 700;
  letter-spacing: -0.02em;
  font-size: 23px;
}
:root[data-theme="editorial"] .logo-net { color: var(--text); }
:root[data-theme="editorial"] .logo-scan { color: var(--neon-magenta); }
:root[data-theme="editorial"] .logo-tld {
  color: var(--text-faint);
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 13px;
}

/* ---- Hero ---------------------------------------------------------------- */
:root[data-theme="editorial"] .hero-badge {
  border: none;
  background: none;
  padding: 0;
  color: var(--text-faint);
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 11px;
  letter-spacing: 0.18em;
}
:root[data-theme="editorial"] .hero-badge .dot {
  background: var(--neon-magenta);
  width: 6px; height: 6px;
  animation: none;
}
:root[data-theme="editorial"] .hero-title {
  font-family: var(--font-display);
  font-variation-settings: 'opsz' 144;
  font-weight: 700;
  font-size: clamp(2.3rem, 6.4vw, 4.4rem);
  line-height: 0.98;
  letter-spacing: -0.03em;
  text-wrap: balance;
}
:root[data-theme="editorial"] .hero-title-neon { color: var(--neon-magenta); }
:root[data-theme="editorial"] .hero-title-sub {
  color: var(--text-dim);
  font-weight: 400;
  font-style: italic;
}
:root[data-theme="editorial"] .hero-sub {
  font-size: 1.06rem;
  max-width: 62ch;
  color: var(--text-dim);
}
:root[data-theme="editorial"] .hero-trust strong { color: var(--text); }
:root[data-theme="editorial"] .hero-trust-dot { background: var(--neon-magenta); }

/* ---- THE VERDICT — the whole point of the theme -------------------------- */
:root[data-theme="editorial"] .winner {
  background: none;
  border: none;
  border-top: 2px solid var(--text);
  border-bottom: 1px solid rgba(20, 17, 13, 0.16);
  padding: 26px 0 30px;
  box-shadow: none;
}
:root[data-theme="editorial"] .winner-badge {
  background: none;
  color: var(--neon-magenta);
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 11px;
  letter-spacing: 0.2em;
  padding: 0;
  margin-bottom: 10px;
}
:root[data-theme="editorial"] .winner-name {
  font-family: var(--font-display);
  font-variation-settings: 'opsz' 144;
  font-weight: 600;
  font-size: clamp(2.4rem, 7vw, 4.2rem);
  line-height: 1;
  letter-spacing: -0.03em;
  color: var(--text);
}
:root[data-theme="editorial"] .winner-score {
  font-family: var(--font-display);
  text-align: right;
}
/* The number, set larger than the headline. This is the design. */
:root[data-theme="editorial"] .winner-score-num {
  font-family: var(--font-display);
  font-variation-settings: 'opsz' 144;
  font-weight: 600;
  font-size: clamp(4.6rem, 15vw, 9rem);
  line-height: 0.82;
  letter-spacing: -0.055em;
  color: var(--neon-magenta);
  font-variant-numeric: lining-nums tabular-nums;
  display: block;
}
:root[data-theme="editorial"] .winner-score-pct {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.8rem;
  letter-spacing: 0.16em;
  color: var(--text-faint);
  display: block;
  margin-top: 6px;
}
:root[data-theme="editorial"] .winner-blurb {
  font-size: 1.02rem;
  color: var(--text-dim);
  max-width: 64ch;
  margin-top: 6px;
}

/* ---- Signal bars: one ink ramp, no competing hues ------------------------ */
:root[data-theme="editorial"] .bar-track {
  background: rgba(20, 17, 13, 0.075);
  border: none;
  height: 6px;
  border-radius: 0;
}
:root[data-theme="editorial"] .bar-fill { border-radius: 0; }
:root[data-theme="editorial"] .bar-5g { background: var(--ink-5g); box-shadow: none; }
:root[data-theme="editorial"] .bar-4g { background: var(--ink-4g); box-shadow: none; }
:root[data-theme="editorial"] .bar-3g { background: var(--ink-3g); box-shadow: none; }
:root[data-theme="editorial"] .bar-label {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 11px;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--text-faint);
}
:root[data-theme="editorial"] .bar-val {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 12.5px;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}

/* ---- Ranked operators: a table of results, not four boxes ---------------- */
:root[data-theme="editorial"] .rank-card {
  background: none;
  border: none;
  border-top: 1px solid rgba(20, 17, 13, 0.16);
  padding: 20px 0 22px;
  box-shadow: none;
}
:root[data-theme="editorial"] .rank-card:hover { border-color: var(--text); }
:root[data-theme="editorial"] .rank-card.is-winner {
  border-top: 2px solid var(--neon-magenta);
  box-shadow: none;
}
:root[data-theme="editorial"] .rank-card .rk-rank {
  font-family: var(--font-display);
  font-variation-settings: 'opsz' 144;
  font-weight: 400;
  font-size: 15px;
  color: var(--text-faint);
  top: 20px;
}
:root[data-theme="editorial"] .rank-card .rk-name {
  font-family: var(--font-display);
  font-variation-settings: 'opsz' 144;
  font-weight: 600;
  font-size: 1.5rem;
  letter-spacing: -0.02em;
}
:root[data-theme="editorial"] .rank-card .rk-meta {
  font-family: var(--font-body);
  font-size: 11.5px;
  letter-spacing: 0.02em;
  color: var(--text-faint);
}
:root[data-theme="editorial"] .rank-card .rk-overall {
  font-family: var(--font-display);
  font-variation-settings: 'opsz' 144;
  font-weight: 600;
  font-size: 3.4rem;
  line-height: 0.9;
  letter-spacing: -0.045em;
  color: var(--text);
  font-variant-numeric: lining-nums tabular-nums;
}
:root[data-theme="editorial"] .rank-card.is-winner .rk-overall { color: var(--neon-magenta); }

/* ---- Section headings ---------------------------------------------------- */
:root[data-theme="editorial"] .section-title {
  font-family: var(--font-display);
  font-variation-settings: 'opsz' 144;
  font-weight: 600;
  letter-spacing: -0.02em;
}

/* ---- The money button: the one solid red on the page --------------------- */
:root[data-theme="editorial"] .winner-cta,
:root[data-theme="editorial"] .switch-primary {
  background: var(--neon-magenta);
  border: 1px solid var(--neon-magenta);
  color: #FFFFFF;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 0.95rem;
  letter-spacing: 0.02em;
  text-transform: none;
  border-radius: 2px;
  box-shadow: none;
  padding: 13px 24px;
}
:root[data-theme="editorial"] .winner-cta:hover,
:root[data-theme="editorial"] .winner-cta:focus-visible,
:root[data-theme="editorial"] .switch-primary:hover,
:root[data-theme="editorial"] .switch-primary:focus-visible {
  background: #9E3019;
  border-color: #9E3019;
  color: #FFFFFF;
  transform: none;
}
:root[data-theme="editorial"] .switch-alt {
  background: none;
  border: 1px solid var(--border-strong);
  color: var(--text);
  border-radius: 2px;
}

/* ---- Remaining surfaces: panels become ruled blocks ---------------------- */
:root[data-theme="editorial"] .how-card,
:root[data-theme="editorial"] .deal-card,
:root[data-theme="editorial"] .op-card {
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: 2px;
  box-shadow: none;
}
:root[data-theme="editorial"] .deal-price {
  font-family: var(--font-display);
  font-variation-settings: 'opsz' 144;
  font-weight: 600;
  letter-spacing: -0.03em;
  color: var(--text);
}
:root[data-theme="editorial"] .chip {
  border-radius: 2px;
  font-family: var(--font-body);
  font-weight: 500;
}
:root[data-theme="editorial"] .skip-link {
  background: var(--text);
  color: #FBFAF8;
  font-family: var(--font-body);
}

/* Prose inside guides gets a measure and a serif drop for its lead paragraph. */
:root[data-theme="editorial"] .guide-body h2,
:root[data-theme="editorial"] .guide-body h3 {
  font-family: var(--font-display);
  font-variation-settings: 'opsz' 144;
  font-weight: 600;
  letter-spacing: -0.02em;
}
:root[data-theme="editorial"] .guide-body p { max-width: 68ch; }

/* ---- The scanner ----------------------------------------------------------
   The dark theme's input is a neon-edged terminal field with an uppercase mono
   placeholder. On paper that reads as a form to be filled in; here it becomes a
   single ruled line with the button as the only colour. */
:root[data-theme="editorial"] .scan-input-wrap {
  background: var(--bg-2);
  border: 1px solid rgba(20, 17, 13, 0.30);
  border-radius: 2px;
  box-shadow: none;
  overflow: hidden;
}
:root[data-theme="editorial"] .scan-input-wrap:focus-within {
  border-color: var(--text);
  box-shadow: none;
}
:root[data-theme="editorial"] .scan-input-icon {
  color: var(--text-faint);
  font-size: 17px;
  padding: 0 12px 0 14px;
}
:root[data-theme="editorial"] #postcode,
:root[data-theme="editorial"] #zip {
  font-family: var(--font-body);
  font-size: 1rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  padding: 15px 4px;
}
:root[data-theme="editorial"] #postcode::placeholder,
:root[data-theme="editorial"] #zip::placeholder {
  color: var(--text-faint);
  letter-spacing: 0;
  font-weight: 400;
}
:root[data-theme="editorial"] .btn-scan {
  background: var(--neon-magenta);
  color: #FFFFFF;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 13px;
  letter-spacing: 0.08em;
  padding: 0 20px;
  flex: 0 0 auto;
}
:root[data-theme="editorial"] .btn-scan:hover {
  background: #A83521;
  filter: none;
}
:root[data-theme="editorial"] .scan-help,
:root[data-theme="editorial"] .scan-examples {
  font-family: var(--font-body);
  font-size: 12.5px;
}

/* ---- Operator names -------------------------------------------------------
   Every operator name carries an inline brand colour from the server, e.g.
   style="color:#00b388" on EE. Two problems on paper: #00b388 measures about
   2.3:1 against #FBFAF8, well under the 4.5:1 needed for text, and four brand
   hues at once breaks the one rule this theme is built on -- red is reserved
   for the winner and the button that earns money. !important is the only thing
   that beats an inline style, so it is used deliberately and only here. */
:root[data-theme="editorial"] .winner-name,
:root[data-theme="editorial"] .rank-card .rk-name,
:root[data-theme="editorial"] .op-card .op-name { color: var(--text) !important; }
:root[data-theme="editorial"] .rank-card.is-winner .rk-name { color: var(--neon-magenta) !important; }

/* The ranking row: give the rank number presence and the meta line less. */
:root[data-theme="editorial"] .rank-card .rk-rank {
  font-size: 13px;
  letter-spacing: 0.06em;
}

/* ---- Effects that only make sense on a screen ----------------------------
   .glitch draws the headline three times -- once in ink, once offset in cyan,
   once offset in magenta -- to fake an RGB-split on a CRT. Against black that
   reads as interference. On paper it reads as a printing misregistration, and
   on the homepage it rendered the words "Find the best" visibly doubled.

   The hero logo pulses a cyan-and-magenta drop-shadow on a 4s loop. On a light
   ground that is a pastel smudge spreading behind the artwork. */
:root[data-theme="editorial"] .glitch::before,
:root[data-theme="editorial"] .glitch::after { display: none; }
:root[data-theme="editorial"] .glitch { color: inherit; }

:root[data-theme="editorial"] .hero-logo-right {
  filter: none;
  animation: none;
}
/* The homepage hero artwork is a class-less <img> carrying that same glow as an
   inline style attribute, so the rule above never reaches it -- the pastel
   smudge survived a first attempt at this. Inline styles only yield to
   !important, which is why it appears here. */
:root[data-theme="editorial"] .hero img {
  filter: none !important;
  animation: none !important;
}

/* The masthead icon is 36x36. The paper mark is fine line art, and at 36px
   those hairlines collapse into a grey smudge that reads as a rendering fault
   rather than a logo -- worse than showing nothing. A newspaper solves this the
   same way: the nameplate is the wordmark, set in the display face, with no
   icon beside it. NETSCAN in Fraunces already does that job here.

   Reversible in one line: delete this rule and the mark returns. */
:root[data-theme="editorial"] .logo-img { display: none; }
:root[data-theme="editorial"] .logo { gap: 0; }
:root[data-theme="editorial"] .logo-text { letter-spacing: -.015em; }

/* Inline band colours in running prose -- "5G . 4G . 3G" arrives with a
   different hue per band. Three hues inside one sentence pulls the eye off the
   sentence, and one of them is the reserved red. Weight carries the emphasis
   instead. */
:root[data-theme="editorial"] .t-cyan,
:root[data-theme="editorial"] .t-magenta,
:root[data-theme="editorial"] .t-green {
  color: var(--text);
  font-weight: 600;
}

/* ---- The browse pages' own nav ------------------------------------------
   .main-nav / .nav-link have no rules in this stylesheet at all, so the links
   inherit body type at 17px. Rajdhani is condensed and fits; Inter is not and
   wraps the nav onto two lines. Styled here rather than in the base sheet so
   the dark theme is left exactly as it was. */
:root[data-theme="editorial"] .main-nav {
  display: flex; align-items: center; gap: 20px; flex-wrap: wrap;
}
:root[data-theme="editorial"] .main-nav .nav-link {
  font-family: var(--font-body);
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--text-dim);
  text-decoration: none;
}
:root[data-theme="editorial"] .main-nav .nav-link:hover,
:root[data-theme="editorial"] .main-nav .nav-link.active {
  color: var(--neon-magenta);
}

/* ---- Section headings inside the browse/calculator templates ------------- */
:root[data-theme="editorial"] .browse-hero h1,
:root[data-theme="editorial"] .region-hero h1 {
  color: var(--text);
  font-variation-settings: 'opsz' 144;
  font-weight: 600;
  letter-spacing: -.02em;
}
:root[data-theme="editorial"] .region-card .label,
:root[data-theme="editorial"] .area-card .code {
  color: var(--text);
  font-variation-settings: 'opsz' 144;
  font-weight: 600;
}
:root[data-theme="editorial"] .region-card .count {
  color: var(--neon-magenta);
}

/* ---- The inline-styled "Scan my postcode" CTA ---------------------------
   Two guide templates hardcode a cyan-to-magenta gradient with #08081a text in
   a style attribute. Tokenised at source, but the gradient token still needs
   the button to sit on one flat red here, and an inline style only yields to
   !important. */
:root[data-theme="editorial"] a[href="/#scan"] {
  background: var(--neon-magenta) !important;
  color: #FFFFFF !important;
  font-family: var(--font-body) !important;
  font-weight: 700 !important;
  letter-spacing: .02em !important;
  border-radius: 2px !important;
}

/* ...but that selector matches EVERY link to the scanner, including one sitting
   mid-sentence in body copy, which came out as a red block inside a paragraph.
   The reserved red is meant to mark the coverage winner and the button that
   earns money; a prose link is neither. .inline-link is the opt-out, and any
   future in-copy link to /#scan should carry it. The extra class outranks the
   rule above, so both can keep their !important. */
:root[data-theme="editorial"] a.inline-link[href="/#scan"] {
  background: none !important;
  color: var(--neon-cyan) !important;
  font-weight: 600 !important;
  padding: 0 !important;
  border-radius: 0 !important;
  text-decoration: underline !important;
}

/* At 390px the wordmark plus three nav links plus the Facebook icon cannot
   share one row, so .main-nav wrapped underneath and collided with the logo.
   The base sheet solves this for .site-nav by hiding it below 780px; hiding
   navigation is worse than moving it, so here it drops to its own full-width
   row under a hairline. */
@media (max-width: 780px) {
  :root[data-theme="editorial"] .header-inner {
    flex-wrap: wrap;
    row-gap: 10px;
    padding-bottom: 12px;
  }
  :root[data-theme="editorial"] .main-nav {
    width: 100%;
    justify-content: flex-start;
    gap: 18px;
    padding-top: 10px;
    border-top: 1px solid var(--border);
  }
  :root[data-theme="editorial"] .main-nav .nav-link { font-size: 11.5px; }
}

/* Several templates thin their body copy with an inline opacity:.85/.9. On a
   dark ground that reads as a soft secondary tone; on paper it just lifts ink
   off the page and cost one paragraph AA (3.89:1). Weight and colour carry
   secondary emphasis in this theme, so the opacity is returned to 1. */
:root[data-theme="editorial"] p[style*="opacity"],
:root[data-theme="editorial"] li[style*="opacity"],
:root[data-theme="editorial"] span[style*="opacity"] { opacity: 1 !important; }

@media (max-width: 640px) {
  :root[data-theme="editorial"] .winner-score { text-align: left; }
  :root[data-theme="editorial"] .winner-score-num { font-size: clamp(4rem, 22vw, 6rem); }
}


/* ---------- Reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
html { scroll-behavior: smooth; }
body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 17px;
  line-height: 1.55;
  min-height: 100vh;
  position: relative;
  overflow-x: hidden;
}
img, svg { display: block; max-width: 100%; }
button { font-family: inherit; cursor: pointer; }
a { color: var(--neon-cyan); text-decoration: none; transition: color .15s, text-shadow .15s; }
a:hover { color: var(--neon-magenta); text-shadow: 0 0 8px currentColor; }

.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;
}
.skip-link {
  position: absolute; top: -100px; left: 16px;
  background: var(--neon-cyan); color: #000; padding: 8px 14px; z-index: 100;
  font-family: var(--font-display); font-weight: 700;
}
.skip-link:focus { top: 12px; }

.container { width: 100%; max-width: 1180px; margin: 0 auto; padding: 0 24px; }

/* ---------- Background layers ---------- */
.bg-grid {
  position: fixed; inset: 0; z-index: -3;
  background:
    linear-gradient(180deg, #06060d 0%, #0a0a18 60%, #050510 100%);
}
.bg-grid::before {
  content: ""; position: absolute; inset: 0;
  background-image:
    linear-gradient(rgba(0, 240, 255, 0.045) 1px, transparent 1px),
    linear-gradient(90deg, rgba(0, 240, 255, 0.045) 1px, transparent 1px);
  background-size: 48px 48px;
  mask-image: radial-gradient(ellipse at top, rgba(0,0,0,1) 0%, rgba(0,0,0,0.5) 60%, rgba(0,0,0,0.15) 100%);
}
.bg-scanlines {
  position: fixed; inset: 0; z-index: -2; pointer-events: none;
  background: repeating-linear-gradient(
    0deg,
    rgba(255,255,255,0.012) 0,
    rgba(255,255,255,0.012) 1px,
    transparent 1px,
    transparent 3px
  );
  opacity: 0.6;
}
.bg-glow {
  position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background:
    radial-gradient(60vmin 60vmin at 12% 18%, rgba(255, 0, 225, 0.18), transparent 60%),
    radial-gradient(70vmin 70vmin at 88% 22%, rgba(0, 240, 255, 0.16), transparent 60%),
    radial-gradient(80vmin 80vmin at 50% 110%, rgba(162, 0, 255, 0.18), transparent 60%);
  filter: blur(2px);
}

/* ---------- Header ---------- */
.site-header {
  position: sticky; top: 0; z-index: 30;
  backdrop-filter: blur(10px);
  background: linear-gradient(180deg, rgba(7,7,15,0.85), rgba(7,7,15,0.6));
  border-bottom: 1px solid var(--border);
}
.header-inner {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 24px;
}
.logo {
  display: inline-flex; align-items: center; gap: 10px;
  color: var(--neon-cyan); text-decoration: none;
}
.logo-mark { width: 28px; height: 28px; filter: drop-shadow(0 0 6px var(--neon-cyan)); }
.logo-img { width: 36px; height: 36px; object-fit: contain; filter: drop-shadow(0 0 8px rgba(0,240,255,.5)); border-radius: 6px; }
.logo-text { font-family: var(--font-display); font-weight: 900; letter-spacing: 1px; font-size: 20px; }
.logo-net { color: var(--neon-cyan); text-shadow: 0 0 8px rgba(0,240,255,.6); }
.logo-scan { color: var(--neon-magenta); text-shadow: 0 0 8px rgba(255,0,225,.6); }
.logo-tld { color: var(--text-dim); font-weight: 500; }

.site-nav { display: flex; gap: 22px; }
.site-nav a {
  font-family: var(--font-display); font-weight: 500; letter-spacing: 1px;
  color: var(--text-dim); font-size: 13px; text-transform: uppercase;
}
.site-nav a:hover { color: var(--neon-cyan); }

@media (max-width: 640px) {
  .site-nav { display: none; }
}

/* ---------- Hero ---------- */
.hero { position:relative; padding: 24px 0 30px; }
.hero-badge {
  display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--font-mono); font-size: 12px; letter-spacing: 2px;
  padding: 5px 12px; border: 1px solid var(--border-strong); margin-bottom: 8px;
  color: var(--neon-cyan); background: rgba(0, 240, 255, 0.06);
  text-transform: uppercase;
}
.hero-badge .dot {
  width: 8px; height: 8px; border-radius: 50%; background: var(--neon-green);
  box-shadow: 0 0 8px var(--neon-green); animation: pulse 1.4s infinite;
}
@keyframes pulse { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: .5; transform: scale(0.85); } }

.hero-title {
  font-family: var(--font-display); font-weight: 900;
  font-size: clamp(1.8rem, 5vw, 3.6rem); line-height: 1.05;
  margin: 12px 0 8px; letter-spacing: -1px;
}
.hero-title span { display: block; }
.hero-title-neon {
  color: var(--neon-magenta);
  text-shadow: 0 0 18px rgba(255, 0, 225, 0.55), 0 0 36px rgba(255, 0, 225, 0.25);
}
.hero-title-sub { color: var(--text-dim); font-weight: 700; font-size: 0.75em; }
.hero-sub {
  color: var(--text-dim); max-width: 620px; font-size: 1rem;
  margin: 0 0 20px;
}
.hero-trust {
  color: var(--text-dim); font-size: 0.82rem; letter-spacing: .2px;
  line-height: 1.5;
  margin: -8px 0 22px;
}
.hero-trust strong { color: var(--neon-green); font-weight: 700; }
.hero-trust-dot {
  display: inline-block; width: 6px; height: 6px; border-radius: 50%;
  background: var(--neon-green); box-shadow: 0 0 8px var(--neon-green);
  margin-right: 8px; vertical-align: middle;
}
.t-cyan { color: var(--neon-cyan); text-shadow: 0 0 8px rgba(0,240,255,.5); }
.t-magenta { color: var(--neon-magenta); text-shadow: 0 0 8px rgba(255,0,225,.5); }
.t-green { color: var(--neon-green); text-shadow: 0 0 8px rgba(0,255,136,.5); }

/* Glitch */
.glitch { position: relative; color: var(--text); }
.glitch::before, .glitch::after {
  content: attr(data-text); position: absolute; top: 0; left: 0; width: 100%;
  overflow: hidden;
}
.glitch::before { color: var(--neon-cyan); transform: translate(-2px, 0); clip-path: polygon(0 0, 100% 0, 100% 45%, 0 45%); animation: glitch-1 3s infinite linear alternate; opacity: .8; }
.glitch::after  { color: var(--neon-magenta); transform: translate(2px, 0); clip-path: polygon(0 55%, 100% 55%, 100% 100%, 0 100%); animation: glitch-2 2.4s infinite linear alternate; opacity: .8; }
@keyframes glitch-1 { 0% { transform: translate(-2px,0);} 20% { transform: translate(-2px,1px);} 40% { transform: translate(-3px,-1px);} 60% { transform: translate(-1px,1px);} 100% { transform: translate(-2px,0);} }
@keyframes glitch-2 { 0% { transform: translate(2px,0);} 20% { transform: translate(2px,-1px);} 40% { transform: translate(3px,1px);} 60% { transform: translate(1px,-1px);} 100% { transform: translate(2px,0);} }

/* Scan form */
.scan-form { max-width: 760px; }
.scan-input-wrap {
  position: relative; display: flex; align-items: stretch;
  background: var(--panel);
  border: 1px solid var(--border-strong);
  box-shadow: var(--shadow-cyan);
  border-radius: var(--radius);
}
.scan-input-wrap:focus-within { border-color: var(--neon-magenta); box-shadow: var(--shadow-magenta); }
.scan-input-icon {
  display: flex; align-items: center; justify-content: center;
  padding: 0 16px; color: var(--neon-cyan); font-size: 22px; font-family: var(--font-mono);
}
#postcode, #zip {
  flex: 1; min-width: 0; background: transparent; border: 0; outline: 0;
  color: var(--text); font-family: var(--font-mono); font-size: 1.05rem;
  padding: 18px 4px; letter-spacing: 1.2px; text-transform: uppercase;
}
#postcode::placeholder, #zip::placeholder { color: var(--text-faint); text-transform: none; letter-spacing: 1px; }
.btn-scan {
  display: inline-flex; align-items: center; gap: 10px;
  background: linear-gradient(135deg, var(--neon-cyan), var(--neon-magenta));
  color: #08081a; font-family: var(--font-display); font-weight: 900;
  letter-spacing: 2px; font-size: 14px;
  padding: 0 26px; border: 0; cursor: pointer;
  position: relative;
  transition: transform .1s, filter .15s;
}
.btn-scan:hover { filter: brightness(1.15); }
.btn-scan:active { transform: translateY(1px); }
.btn-scan-arrow { font-size: 12px; }

.scan-help { color: var(--text-faint); font-family: var(--font-mono); font-size: 12px; margin: 10px 2px 14px; }
.scan-examples { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; color: var(--text-dim); font-size: 13px; font-family: var(--font-mono); }
.chip {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text-dim);
  padding: 6px 12px; border-radius: 999px;
  font-family: var(--font-mono); font-size: 12px;
  transition: all .15s;
}
.chip:hover { border-color: var(--neon-cyan); color: var(--neon-cyan); box-shadow: 0 0 8px rgba(0,240,255,.3); }

.scan-error {
  color: #ff5b6e; font-family: var(--font-mono); font-size: 14px;
  margin: 18px 0 0; min-height: 1.2em;
}

/* ---------- Loading / Radar ---------- */
.loading { padding: 60px 0; }
.loading-inner { display: flex; gap: 36px; align-items: center; flex-wrap: wrap; }
.radar {
  width: 220px; height: 220px; border-radius: 50%; position: relative;
  background: radial-gradient(circle, rgba(0,240,255,.08), transparent 70%);
  border: 1px solid var(--border);
  flex-shrink: 0;
}
.radar-ring {
  position: absolute; inset: 0; margin: auto; border-radius: 50%;
  border: 1px solid rgba(0,240,255,.25);
}
.radar-ring.r1 { width: 70%; height: 70%; }
.radar-ring.r2 { width: 45%; height: 45%; }
.radar-ring.r3 { width: 20%; height: 20%; border-color: var(--neon-magenta); }
.radar-sweep {
  position: absolute; inset: 0;
  background: conic-gradient(from 0deg, transparent 0deg, rgba(0,240,255,.5) 30deg, transparent 60deg);
  border-radius: 50%;
  animation: sweep 1.8s linear infinite;
  filter: blur(.4px);
}
@keyframes sweep { to { transform: rotate(360deg); } }
.radar-dot {
  position: absolute; width: 8px; height: 8px; border-radius: 50%;
  background: var(--neon-green); box-shadow: 0 0 10px var(--neon-green);
}
.radar-dot.d1 { top: 22%; left: 28%; animation: blink 1.8s infinite; }
.radar-dot.d2 { top: 60%; left: 64%; animation: blink 1.8s .4s infinite; background: var(--neon-magenta); box-shadow: 0 0 10px var(--neon-magenta); }
.radar-dot.d3 { top: 38%; left: 76%; animation: blink 1.8s .8s infinite; background: var(--neon-cyan); box-shadow: 0 0 10px var(--neon-cyan); }
.radar-dot.d4 { top: 72%; left: 30%; animation: blink 1.8s 1.2s infinite; background: var(--neon-yellow); box-shadow: 0 0 10px var(--neon-yellow); }
@keyframes blink { 0%, 100% { opacity: 1; } 50% { opacity: .2; } }

.loading-log {
  flex: 1; min-width: 280px;
  background: var(--panel); border: 1px solid var(--border);
  padding: 18px 22px; font-family: var(--font-mono); font-size: 14px;
  color: var(--neon-green);
}
.loading-log p { margin: 4px 0; opacity: 0; transform: translateX(-8px); transition: all .35s; }
.loading-log p.shown { opacity: 1; transform: translateX(0); }

/* ---------- Results ---------- */
.results { padding: 50px 0 80px; }
.results-head { margin-bottom: 30px; }
.kicker {
  font-family: var(--font-mono); font-size: 12px; letter-spacing: 3px;
  color: var(--neon-cyan); text-transform: uppercase;
}
.results-title {
  font-family: var(--font-display); font-weight: 900;
  font-size: clamp(1.6rem, 3.5vw, 2.4rem);
  margin: 8px 0 4px;
}
.results-meta { color: var(--text-dim); font-family: var(--font-mono); font-size: 13px; margin: 0; }

.winner {
  position: relative;
  border: 1px solid var(--neon-magenta);
  background: linear-gradient(135deg, rgba(255,0,225,.08), rgba(0,240,255,.06));
  padding: 32px;
  box-shadow: var(--shadow-magenta);
  margin-bottom: 36px;
  overflow: hidden;
}
.winner::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background:
    linear-gradient(90deg, transparent 0%, rgba(0,240,255,.05) 50%, transparent 100%);
  animation: shine 4s infinite linear;
}
@keyframes shine { from { transform: translateX(-100%); } to { transform: translateX(100%); } }

.winner-badge {
  display: inline-block; padding: 5px 12px;
  background: var(--neon-magenta); color: #08081a;
  font-family: var(--font-display); font-weight: 900; font-size: 11px; letter-spacing: 2px;
  margin-bottom: 18px;
}
.winner-inner { display: grid; grid-template-columns: 1fr auto; gap: 24px; align-items: center; }
.winner-name {
  font-family: var(--font-display); font-weight: 900;
  font-size: clamp(2.2rem, 6vw, 4rem);
  color: var(--neon-cyan); text-shadow: 0 0 24px rgba(0,240,255,.6);
  letter-spacing: -1px;
}
.winner-score { font-family: var(--font-display); font-weight: 900; text-align: right; }
.winner-score-num {
  font-size: 4rem; color: var(--neon-green); text-shadow: 0 0 18px rgba(0,255,136,.5);
}
.winner-score-pct { color: var(--text-dim); font-size: 1.4rem; }
.winner-blurb { grid-column: 1 / -1; color: var(--text-dim); margin: 0; max-width: 720px; }
.winner-bars { grid-column: 1 / -1; display: flex; flex-direction: column; gap: 10px; margin-top: 12px; }
.bar { display: grid; grid-template-columns: 40px 1fr 56px; align-items: center; gap: 12px; }
.bar-label { font-family: var(--font-mono); color: var(--text-dim); font-size: 13px; }
.bar-track { background: rgba(255,255,255,.05); height: 8px; border-radius: 3px; overflow: hidden; border: 1px solid rgba(255,255,255,.05); }
.bar-fill { height: 100%; width: 0%; transition: width .9s cubic-bezier(.22,.61,.36,1); border-radius: 3px; }
.bar-5g { background: linear-gradient(90deg, var(--neon-cyan), #6effff); box-shadow: 0 0 10px rgba(0,240,255,.6); }
.bar-4g { background: linear-gradient(90deg, var(--neon-magenta), #ff8aec); box-shadow: 0 0 10px rgba(255,0,225,.6); }
.bar-3g { background: linear-gradient(90deg, var(--neon-green), #82ffba); box-shadow: 0 0 10px rgba(0,255,136,.6); }
.bar-val { font-family: var(--font-mono); color: var(--text); font-size: 13px; text-align: right; }

@media (max-width: 640px) {
  .winner-inner { grid-template-columns: 1fr; }
  .winner-score { text-align: left; }
  .winner-score-num { font-size: 3rem; }
}


/* Winner CTA — link to operator live deals */
.winner-cta {
  display: inline-flex; align-items: center; gap: 10px;
  margin-top: 18px; padding: 12px 22px;
  background: rgba(0, 240, 255, 0.06);
  border: 1px solid var(--neon-cyan);
  color: var(--text);
  text-decoration: none;
  font-family: var(--font-display); font-weight: 700;
  font-size: 0.95rem; letter-spacing: 1.5px; text-transform: uppercase;
  transition: all .15s;
  position: relative;
  z-index: 1;
}
.winner-cta:hover {
  background: rgba(0, 240, 255, 0.15);
  transform: translateY(-1px);
  color: var(--neon-cyan);
  text-shadow: 0 0 8px currentColor;
}
.winner-cta-arrow { font-size: 1.05rem; line-height: 1; }

/* Deal card as anchor — make clickability obvious */
a.deal-card {
  display: flex; flex-direction: column;
  color: inherit; text-decoration: none;
  cursor: pointer;
}
a.deal-card:hover { color: inherit; }
.deal-cta-row {
  margin-top: auto; padding-top: 14px;
  border-top: 1px dashed rgba(0,240,255,.15);
  display: flex; justify-content: space-between; align-items: center;
  font-family: var(--font-mono); font-size: 12px; color: var(--text-dim);
}
.deal-cta {
  color: var(--neon-cyan);
  font-family: var(--font-display); font-weight: 700;
  letter-spacing: 1px; text-transform: uppercase;
  transition: text-shadow .15s;
}
a.deal-card:hover .deal-cta {
  text-shadow: 0 0 8px currentColor;
}

/* Ranking */
.section-h {
  font-family: var(--font-display); font-weight: 700; letter-spacing: 1px;
  font-size: 1.25rem; color: var(--text); text-transform: uppercase;
  margin: 0 0 16px;
}
.ranking-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 14px;
  margin-bottom: 40px;
}
.rank-card {
  background: var(--panel); border: 1px solid var(--border);
  padding: 18px 18px 20px; position: relative; transition: all .2s;
}
.rank-card:hover { border-color: var(--neon-cyan); }
.rank-card.is-winner { border-color: var(--neon-magenta); box-shadow: var(--shadow-magenta); }
.rank-card .rk-rank {
  position: absolute; top: 12px; right: 14px;
  font-family: var(--font-display); font-weight: 900; color: var(--text-faint); font-size: 14px;
}
.rank-card .rk-name {
  font-family: var(--font-display); font-weight: 900; font-size: 1.4rem;
  color: var(--text); margin-bottom: 4px;
}
.rank-card .rk-meta { font-family: var(--font-mono); font-size: 12px; color: var(--text-dim); margin-bottom: 14px; }
.rank-card .rk-overall {
  font-family: var(--font-display); font-weight: 900; font-size: 2.4rem;
  color: var(--neon-cyan); text-shadow: 0 0 12px rgba(0,240,255,.4);
  line-height: 1; margin-bottom: 10px;
}
.rank-card.is-winner .rk-overall { color: var(--neon-magenta); text-shadow: 0 0 12px rgba(255,0,225,.4); }
.rank-card .rk-bars { display: flex; flex-direction: column; gap: 6px; }
.rk-bars .bar { grid-template-columns: 30px 1fr 38px; gap: 8px; }
.rk-bars .bar-label, .rk-bars .bar-val { font-size: 11px; }
.rk-bars .bar-track { height: 5px; }

/* Deals */
.deals-section { margin-top: 8px; }
.deals-head {
  display: flex; justify-content: space-between; align-items: flex-end;
  gap: 16px; flex-wrap: wrap; margin-bottom: 18px;
}
.deals-controls { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }

/* v1.1.0 — Live-feed freshness badge */
.deals-freshness {
  width: 100%;
  margin: -4px 0 0;
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--text-dim);
  letter-spacing: 0.05em;
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
.deals-freshness .freshness-dot {
  display: inline-block; width: 8px; height: 8px; border-radius: 50%;
}
.deals-freshness .freshness-live {
  background: #00ff9c;
  box-shadow: 0 0 8px #00ff9c, 0 0 16px rgba(0,255,156,.5);
  animation: pulse-live 2.4s ease-in-out infinite;
}
.deals-freshness .freshness-seed {
  background: var(--text-dim);
}
.deals-freshness .freshness-tag {
  color: var(--neon-cyan); opacity: 0.7;
}
@keyframes pulse-live {
  0%,100% { opacity: 1; }
  50%     { opacity: 0.4; }
}
.select {
  background: var(--panel); border: 1px solid var(--border-strong);
  color: var(--text); padding: 8px 12px; font-family: var(--font-mono); font-size: 13px;
  border-radius: var(--radius); cursor: pointer;
}
.select:focus { outline: 0; border-color: var(--neon-magenta); }
.deal-tabs { display: flex; gap: 4px; }
.deal-tab {
  background: transparent; border: 1px solid var(--border);
  color: var(--text-dim); padding: 7px 12px; font-family: var(--font-display); font-weight: 700;
  font-size: 11px; letter-spacing: 1.5px; cursor: pointer; transition: all .15s;
}
.deal-tab:hover { color: var(--neon-cyan); border-color: var(--neon-cyan); }
.deal-tab.is-active {
  background: var(--neon-cyan); color: #08081a; border-color: var(--neon-cyan);
  box-shadow: 0 0 12px rgba(0,240,255,.5);
}

.deals-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 16px;
}
.deal-card {
  background: var(--panel); border: 1px solid var(--border);
  padding: 20px; transition: all .2s; position: relative; overflow: hidden;
  display: flex; flex-direction: column;
}
.deal-card:hover { border-color: var(--neon-cyan); transform: translateY(-2px); box-shadow: var(--shadow-cyan); }
.deal-card.is-best::before {
  content: "★ BEST VALUE"; position: absolute; top: 0; right: 0;
  background: var(--neon-yellow); color: #08081a;
  font-family: var(--font-display); font-weight: 900; font-size: 10px; letter-spacing: 2px;
  padding: 4px 10px;
}
.deal-brand {
  font-family: var(--font-mono); font-size: 11px; color: var(--text-faint); letter-spacing: 2px;
  text-transform: uppercase; margin-bottom: 4px;
}
.deal-phone {
  font-family: var(--font-display); font-weight: 700; font-size: 1.15rem;
  color: var(--text); line-height: 1.25; margin-bottom: 14px;
}
.deal-price {
  font-family: var(--font-display); font-weight: 900;
  color: var(--neon-magenta); text-shadow: 0 0 8px rgba(255,0,225,.4);
  font-size: 2rem; line-height: 1;
}
.deal-price-sub { color: var(--text-dim); font-size: .85rem; font-family: var(--font-mono); margin-bottom: 14px; }
.deal-meta { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 14px; margin-bottom: 14px; font-size: 13px; font-family: var(--font-mono); }
.deal-meta .k { color: var(--text-faint); font-size: 11px; letter-spacing: 1px; text-transform: uppercase; }
.deal-meta .v { color: var(--text); }
.deal-total { margin-top: auto; font-family: var(--font-mono); font-size: 12px; color: var(--text-dim); padding-top: 14px; border-top: 1px dashed rgba(0,240,255,.15); }
.deal-total strong { color: var(--neon-cyan); }
.deal-tag {
  display: inline-block; margin-top: 10px; padding: 3px 8px;
  font-family: var(--font-mono); font-size: 10px; letter-spacing: 1px; text-transform: uppercase;
  background: rgba(0,240,255,.1); color: var(--neon-cyan);
  border: 1px solid var(--border);
}

/* ---------- How it works ---------- */
.how, .operators, .faq { padding: 70px 0; border-top: 1px solid var(--border); }
.section-title {
  font-family: var(--font-display); font-weight: 900; letter-spacing: -.5px;
  font-size: clamp(1.6rem, 3.5vw, 2.4rem);
  margin: 0 0 30px; color: var(--text);
}
.section-title::after {
  content: ""; display: block; width: 60px; height: 3px; margin-top: 10px;
  background: linear-gradient(90deg, var(--neon-cyan), var(--neon-magenta));
  box-shadow: 0 0 12px rgba(0,240,255,.5);
}
.how-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 16px;
}
.how-card {
  background: var(--panel); border: 1px solid var(--border); padding: 22px;
  transition: all .2s;
}
.how-card:hover { border-color: var(--neon-cyan); transform: translateY(-2px); }
.how-num {
  font-family: var(--font-mono); font-size: 12px; color: var(--neon-magenta);
  letter-spacing: 3px; margin-bottom: 8px;
}
.how-card h3 { font-family: var(--font-display); font-weight: 700; font-size: 1.1rem; margin: 0 0 8px; color: var(--text); }
.how-card p { color: var(--text-dim); font-size: .96rem; margin: 0; }

/* ---------- Operators ---------- */
.op-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 16px;
}
.op-tile {
  background: var(--panel); border: 1px solid var(--border); padding: 22px;
  position: relative; transition: all .2s;
}
.op-tile:hover { border-color: var(--neon-cyan); }
.op-dot {
  display: inline-block; width: 12px; height: 12px; border-radius: 50%;
  margin-bottom: 12px; box-shadow: 0 0 10px currentColor;
}
.op-tile h3 { font-family: var(--font-display); font-weight: 900; font-size: 1.6rem; margin: 0 0 6px; color: var(--text); }
.op-tile p { color: var(--text-dim); margin: 0; }

/* ---------- FAQ ---------- */
.faq-q {
  background: var(--panel); border: 1px solid var(--border);
  padding: 18px 22px; margin-bottom: 10px; cursor: pointer;
}
.faq-q[open] { border-color: var(--neon-cyan); }
.faq-q summary {
  font-family: var(--font-display); font-weight: 600; font-size: 1rem;
  color: var(--text); list-style: none; position: relative; padding-right: 28px;
}
.faq-q summary::after {
  content: "+"; position: absolute; right: 0; top: 0; color: var(--neon-cyan);
  font-family: var(--font-display); font-weight: 900; transition: transform .15s;
}
.faq-q[open] summary::after { content: "−"; }
.faq-q p { color: var(--text-dim); margin: 12px 0 0; }

/* ---------- Footer ---------- */
.site-footer {
  border-top: 1px solid var(--border);
  background: linear-gradient(180deg, rgba(7,7,15,0.4), rgba(7,7,15,0.9));
  padding: 40px 0; margin-top: 40px;
}
.footer-inner {
  display: grid; grid-template-columns: 1fr 2fr; gap: 30px;
}
.footer-brand p { color: var(--text-faint); font-family: var(--font-mono); font-size: 12px; margin-top: 8px; }
.footer-meta p { color: var(--text-faint); font-size: 13px; margin: 0 0 6px; }
.footer-meta a { color: var(--neon-cyan); }
@media (max-width: 640px) {
  .footer-inner { grid-template-columns: 1fr; }
}

/* ---------- Utility ---------- */
[hidden] { display: none !important; }

/* ─── Districts / Siblings Nav ─────────────────────────────────────────────── */
.districts-nav { padding: 2.5rem 0; border-top: 1px solid rgba(255,255,255,.06); }
.districts-nav .section-heading { font-size: 1.1rem; margin-bottom: .5rem; }
.districts-intro { color: var(--text-dim); font-size: .9rem; margin-bottom: 1rem; }
.districts-list { list-style: none; display: flex; flex-wrap: wrap; gap: .5rem; padding: 0; }
.district-link {
  display: inline-block; padding: .3rem .75rem;
  background: rgba(0,229,255,.06); border: 1px solid rgba(0,229,255,.2);
  border-radius: 20px; color: var(--accent); font-size: .82rem;
  text-decoration: none; transition: background .15s, border-color .15s;
}
.district-link:hover { background: rgba(0,229,255,.14); border-color: rgba(0,229,255,.5); }
.districts-area-link { margin-top: .75rem; font-size: .85rem; }
.districts-area-link a { color: var(--accent); }

/* ── Data trust signal (v1.3.0) ─────────────────────────────────────── */
.footer-trust {
  display: block;
  margin-top: 0.35rem;
  font-size: 0.72rem;
  opacity: 0.55;
  font-style: italic;
}
/* ── Local Coverage Directory prose block ───────────────────────────── */
.districts-prose {
  font-size: 0.85rem;
  color: var(--text-muted, rgba(255,255,255,0.55));
  line-height: 1.7;
  margin-bottom: 1.25rem;
}
.districts-prose a {
  color: var(--neon-cyan, #00f0ff);
  text-decoration: none;
}
.districts-prose a:hover {
  text-decoration: underline;
}

/* ── Hero logo — right column ───────────────────────────────── */
/* ── Hero logo — top-right corner ───────────────────────────── */
.hero-logo-corner {
  float: right;
  margin: 0 0 1.5rem 2rem;
  clear: right;
}
.hero::after { content: ''; display: table; clear: both; }
.hero-logo-right {
  width: 160px; height: 160px; object-fit: contain;
  filter: drop-shadow(0 0 28px rgba(0,240,255,.6)) drop-shadow(0 0 56px rgba(255,0,225,.3));
  animation: pulse-logo 4s ease-in-out infinite;
}
@keyframes pulse-logo {
  0%, 100% { filter: drop-shadow(0 0 28px rgba(0,240,255,.6)) drop-shadow(0 0 56px rgba(255,0,225,.3)); }
  50%       { filter: drop-shadow(0 0 42px rgba(0,240,255,.9)) drop-shadow(0 0 72px rgba(255,0,225,.5)); }
}
@media (max-width: 640px) {
  .hero-logo-corner { top:1rem; right:1rem; }
  .hero-logo-right { width:80px; height:80px; }
}

/* Coverage-led outbound CTA (replaces the old static deal cards) */
.switch-primary {
  display:inline-flex; align-items:center; gap:.5rem;
  padding:.95rem 1.6rem; border-radius:6px;
  background:linear-gradient(92deg,var(--neon-cyan),var(--neon-magenta));
  color:#05080d; text-decoration:none; border:0;
  font-family:var(--font-display,var(--font-mono)); font-weight:700;
  font-size:.95rem; letter-spacing:.04em; text-transform:uppercase;
  box-shadow:0 0 22px rgba(0,255,255,.28);
  transition:transform .15s ease, box-shadow .15s ease, filter .15s ease;
}
.switch-primary:hover, .switch-primary:focus-visible {
  transform:translateY(-1px); filter:brightness(1.08);
  box-shadow:0 0 30px rgba(0,255,255,.42);
}
.switch-primary:focus-visible { outline:2px solid var(--neon-cyan); outline-offset:3px; }
@media (prefers-reduced-motion:reduce){ .switch-primary{transition:none} .switch-primary:hover{transform:none} }

.switch-cta { display:flex; flex-wrap:wrap; gap:.9rem; align-items:center; margin-top:1.5rem; }
.switch-alt {
  display:inline-flex; align-items:center; padding:.7rem 1.1rem; border-radius:6px;
  border:1px solid rgba(255,255,255,.18); color:var(--neon-cyan); text-decoration:none;
  font-family:var(--font-mono); font-size:.85rem;
  transition:border-color .15s ease, background .15s ease;
}
.switch-alt:hover, .switch-alt:focus-visible { border-color:var(--neon-cyan); background:rgba(0,255,255,.06); }
.affiliate-note {
  margin-top:1.1rem; font-size:.78rem; line-height:1.6; opacity:.6;
  font-family:var(--font-mono); max-width:62ch;
}


/* ------------------------------------------------------------------
   Guide comparison tables
   Added 2026-08-27. "cheapest payg sim" and friends are comparative
   queries; the PAYG guide answered them in prose and sat at position
   19-20. Every colour here is a themed var so the table reads correctly
   in editorial (light) and the original dark theme alike.
   ------------------------------------------------------------------ */
.guide-table-wrap {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  margin: 0 0 1.1rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--panel);
}
.guide-table {
  width: 100%;
  border-collapse: collapse;
  font-family: var(--font-body);
  font-size: 0.97rem;
  line-height: 1.5;
  min-width: 520px;
}
.guide-table th,
.guide-table td {
  padding: 0.7rem 0.85rem;
  text-align: left;
  border-bottom: 1px solid var(--border);
  vertical-align: top;
}
.guide-table thead th {
  font-family: var(--font-display);
  font-size: 0.72rem;
  font-weight: 900;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--neon-cyan);
  background: var(--tint-strong);
  border-bottom: 1px solid var(--border-strong);
  white-space: nowrap;
}
.guide-table tbody tr:last-child td { border-bottom: none; }
.guide-table tbody tr:nth-child(even) { background: var(--tint); }
.guide-table td:first-child { font-weight: 700; color: var(--text); }
/* Prices must not wrap mid-value - "£5.00 — 5GB" splitting across two lines
   made the table look broken and pushed a column off the edge. */
.guide-table td:nth-child(3),
.guide-table td:nth-child(4) { white-space: nowrap; }
.guide-table-note {
  margin: -0.4rem 0 1.4rem;
  font-size: 0.85rem;
  opacity: 0.75;
}
/* On a phone a 4-column table pushes the price columns off-screen, and the
   price is the whole reason the table exists. Below 560px each row becomes a
   stacked card with its column name as the label, so every value is visible
   without sideways scrolling. NetScan's traffic is mostly mobile. */
@media (max-width: 560px) {
  .guide-table-wrap { overflow-x: visible; background: transparent; border: none; }
  .guide-table { min-width: 0; font-size: 0.95rem; display: block; }
  .guide-table thead {
    position: absolute; width: 1px; height: 1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
  }
  .guide-table tbody, .guide-table tr, .guide-table td { display: block; width: 100%; }
  .guide-table tbody tr {
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    background: var(--panel);
    margin: 0 0 0.7rem;
    padding: 0.2rem 0.1rem;
  }
  .guide-table tbody tr:nth-child(even) { background: var(--panel); }
  .guide-table td {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 1rem;
    padding: 0.5rem 0.85rem;
    border-bottom: 1px solid var(--border);
    white-space: normal;
  }
  .guide-table td:last-child { border-bottom: none; }
  .guide-table td::before {
    content: attr(data-label);
    font-family: var(--font-display);
    font-size: 0.62rem;
    font-weight: 900;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--neon-cyan);
    flex: 0 0 auto;
  }
  .guide-table td:first-child { font-size: 1.05rem; }
}

/* ── NetScanAI US (2026-09-19) ─────────────────────────────────────────────
   US bar labels ("Outdoor", "In car", "5G 35/3") are wider than the UK's
   "5G"/"4G", and overlapped the track on a phone. */
.bar { grid-template-columns: 76px 1fr 56px; }
.rk-bars .bar { grid-template-columns: 62px 1fr 44px; }
.bar-label { white-space: nowrap; }
#results { scroll-margin-top: 90px; }
