/* =====================================================================
 * Internet Times — Public site stylesheet
 * ---------------------------------------------------------------------
 * Single source of truth for everything served at:
 *   - /                       homepage
 *   - /<tool-slug>            all 11 tool pages
 *   - /blog, /blog/<slug>, /blog/category/<slug>, /blog/tag/<slug>
 *   - /about, /privacy, /terms, /contact
 *
 * Loaded only by templates/header.php — admin/account/auth surfaces
 * use panel.css, never this file.
 *
 * Design language: matches the auth/admin/account look the user
 * approved on /login — Linear-blue indigo accent (#5e6ad2), hairline
 * borders, no neon, no glass blur, light-default with manual dark
 * toggle.
 * =================================================================== */

/* ---------------------------------------------------------------------
 * 1. DESIGN TOKENS
 * ------------------------------------------------------------------- */

:root,
html[data-theme="light"] {
    /* Surfaces */
    --bg:           #fbfbfd;
    --surface:      #ffffff;
    --surface-2:    #f6f7f9;
    --surface-3:    #f0f1f4;
    --surface-hover:#f0f1f4;

    /* Lines */
    --border:        rgba(15, 17, 21, 0.06);
    --border-2:      rgba(15, 17, 21, 0.10);
    --border-strong: rgba(15, 17, 21, 0.18);
    --divider:       rgba(15, 17, 21, 0.05);

    /* Text */
    --text:      #0f1115;
    --text-2:    #52555c;
    --text-3:    #84878d;
    --text-mono: #1d2026;

    /* Brand accent — Linear-blue indigo, used sparingly */
    --accent:        #5e6ad2;
    --accent-strong: #4f5bc6;
    --accent-soft:   rgba(94, 106, 210, 0.10);
    --accent-ring:   rgba(94, 106, 210, 0.32);
    --accent-text:   #4d57c0;

    /* Semantic */
    --ok:        #16a34a;
    --ok-soft:   rgba(22, 163, 74, 0.10);
    --warn:      #d97706;
    --warn-soft: rgba(217, 119, 6, 0.10);
    --err:       #dc2626;
    --err-soft:  rgba(220, 38, 38, 0.10);

    /* Code syntax highlight — for the .api-codeblock .t-* tokens. The
       light-theme values are dark-on-light-gray (surface-2 background)
       so all three meet WCAG AA contrast (≥4.5:1). Dark-mode equivalents
       are defined in the html[data-theme="dark"] block below. */
    --code-key:  #1d4ed8;   /* blue-700  — JSON keys */
    --code-str:  #15803d;   /* green-700 — string values */
    --code-num:  #b45309;   /* amber-700 — numeric values */

    /* Effects */
    --shadow-sm: 0 1px 2px rgba(15, 17, 21, 0.04);
    --shadow-md: 0 4px 12px rgba(15, 17, 21, 0.06), 0 1px 3px rgba(15, 17, 21, 0.04);
    --shadow-lg: 0 16px 32px rgba(15, 17, 21, 0.10), 0 4px 8px rgba(15, 17, 21, 0.05);

    /* Radius */
    --radius-sm: 6px;
    --radius:    8px;
    --radius-md: 10px;
    --radius-lg: 12px;

    /* Type stacks */
    --font-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    --font-mono: "JetBrains Mono", ui-monospace, "SFMono-Regular", "SF Mono", Menlo, Consolas, monospace;

    /* Type scale — 9 fixed steps + 2 fluid hero steps.
       The xs/sm/md/lg/xl/2xl/3xl ramp is the everyday vocabulary;
       2xs/3xs cover micro UI (kbd chips, eyebrow labels, cmdk hints);
       4xl/5xl are pure marketing-display sizes;
       --fs-hero is the shared fluid clamp used by every interior page hero
       (tool pages, blog post hero, blog taxonomy hero) so the size is
       defined exactly once. --fs-hero-xl is the homepage hero: deliberately close to
       --fs-hero, because a headline that fills the viewport pushes the
       audit input below the fold, which is the one thing it must not do. */
    --fs-2xs: 10px;
    --fs-3xs: 11px;
    --fs-xs:  12px;
    --fs-sm:  13px;
    --fs-md:  14px;
    --fs-lg:  16px;
    --fs-xl:  20px;
    --fs-2xl: 24px;
    --fs-3xl: 32px;
    --fs-4xl: 44px;
    --fs-5xl: 56px;
    --fs-hero:    clamp(28px, 4vw, 38px);
    --fs-hero-xl: clamp(30px, 3.4vw, var(--fs-4xl));

    /* Spacing — 4px base */
    --sp-1:  4px;
    --sp-2:  8px;
    --sp-3:  12px;
    --sp-4:  16px;
    --sp-5:  20px;
    --sp-6:  24px;
    --sp-8:  32px;
    --sp-10: 40px;
    --sp-12: 48px;
    --sp-16: 64px;
    --sp-20: 80px;

    /* Layout */
    --site-max:   1180px;
    --header-h:   60px;

    color-scheme: light;
}

html[data-theme="dark"] {
    --bg:           #0a0b0e;
    --surface:      #111316;
    --surface-2:    #16191d;
    --surface-3:    #1c1f24;
    --surface-hover:#1c1f24;

    --border:        rgba(255, 255, 255, 0.06);
    --border-2:      rgba(255, 255, 255, 0.10);
    --border-strong: rgba(255, 255, 255, 0.18);
    --divider:       rgba(255, 255, 255, 0.05);

    --text:      #e9eaec;
    --text-2:    #a1a3a8;
    --text-3:    #6e7177;
    --text-mono: #d3d5d8;

    --accent:        #7c84e0;
    --accent-strong: #6c75d8;
    --accent-soft:   rgba(124, 132, 224, 0.14);
    --accent-ring:   rgba(124, 132, 224, 0.38);
    --accent-text:   #9ca3eb;

    --ok:        #22c55e;
    --ok-soft:   rgba(34, 197, 94, 0.14);
    --warn:      #f59e0b;
    --warn-soft: rgba(245, 158, 11, 0.14);
    --err:       #ef4444;
    --err-soft:  rgba(239, 68, 68, 0.14);

    /* Code syntax highlight — bright on dark surface-2 (#16191d). */
    --code-key:  #93c5fd;   /* blue-300  — JSON keys */
    --code-str:  #86efac;   /* green-300 — string values */
    --code-num:  #fbbf24;   /* amber-400 — numeric values */

    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);
    --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.4), 0 1px 3px rgba(0, 0, 0, 0.25);
    --shadow-lg: 0 16px 32px rgba(0, 0, 0, 0.5), 0 4px 8px rgba(0, 0, 0, 0.3);

    color-scheme: dark;
}

/* ---------------------------------------------------------------------
 * 2. RESET & BASE
 * ------------------------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; tab-size: 4; scroll-behavior: smooth; }

body {
    margin: 0;
    background: var(--bg);
    color: var(--text);
    font-family: var(--font-sans);
    font-size: var(--fs-md);
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
    font-feature-settings: "ss01" on, "cv11" on;
    min-height: 100vh;
}

img, picture, svg, video { display: block; max-width: 100%; height: auto; }

h1, h2, h3, h4, h5, h6 {
    margin: 0;
    font-weight: 600;
    color: var(--text);
    letter-spacing: -0.01em;
    line-height: 1.25;
}
h1 { font-size: var(--fs-3xl); letter-spacing: -0.02em; }
h2 { font-size: var(--fs-2xl); letter-spacing: -0.015em; }
h3 { font-size: var(--fs-xl); }
h4 { font-size: var(--fs-lg); }

p { margin: 0; }

/* ---------------------------------------------------------------------
 * 2b. TYPOGRAPHIC "VOICES" — one source of truth for secondary text.
 *
 * Two named voices cover ~95% of the small text used outside body copy
 * and headings. The intent is that any new feature reaches for one of
 * these instead of hardcoding font-size + family + weight + color
 * combos that drift across the codebase over time.
 *
 *   .txt-eyebrow  — section labels: footer column titles, sidebar
 *                   widget titles, cmdk group titles, TOC heading,
 *                   "Related articles" / "Categories" / "Tags"
 *
 *   .txt-meta     — metadata strings: breadcrumbs, post-meta row,
 *                   recent-post date, sidebar tool-list descriptions,
 *                   cmdk-item descriptions, footer bottom strip
 *
 * Component rules below extend these voices by re-stating the same
 * declarations (rather than `@extend` which doesn't exist in plain
 * CSS) — search for "VOICE: txt-meta" / "VOICE: txt-eyebrow" comment
 * markers when grepping for drift.
 * ------------------------------------------------------------------- */
.txt-eyebrow {
    font-family: var(--font-mono);
    font-size: var(--fs-3xs);
    font-weight: 600;
    letter-spacing: 0.10em;
    text-transform: uppercase;
    color: var(--text-3);
    line-height: 1;
}
.txt-meta {
    font-family: var(--font-mono);
    font-size: var(--fs-xs);
    font-weight: 400;
    color: var(--text-3);
    line-height: 1.5;
}

a { color: var(--accent-text); text-decoration: none; transition: color 120ms ease; }
a:hover { color: var(--accent); }

code, kbd, pre, samp { font-family: var(--font-mono); font-feature-settings: normal; }
code {
    font-size: 0.9em;
    padding: 0.1em 0.4em;
    background: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    color: var(--text-mono);
}

::selection { background: var(--accent-soft); color: var(--text); }

/* Skip link */
.skip-link {
    position: absolute;
    top: -40px;
    left: 8px;
    z-index: 100;
    padding: 8px 12px;
    background: var(--accent);
    color: #fff;
    border-radius: var(--radius);
    text-decoration: none;
    font-weight: 600;
}
.skip-link:focus { top: 8px; }

/* Focus rings — keyboard only */
:focus { outline: none; }
:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: var(--radius-sm);
}
button:focus-visible,
.btn:focus-visible,
a.btn:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 3px;
    box-shadow: 0 0 0 4px var(--accent-soft);
}

/* Visually-hidden helper */
.visually-hidden,
.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;
}

/* Reduce motion */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.001ms !important;
        transition-duration: 0.001ms !important;
    }
}

/* ---------------------------------------------------------------------
 * 3. LAYOUT PRIMITIVES
 * ------------------------------------------------------------------- */

.container {
    width: 100%;
    max-width: var(--site-max);
    margin: 0 auto;
    padding: 0 var(--sp-5);
}

main, .main-content { display: block; }

main:focus { outline: none; }

/* ---------------------------------------------------------------------
 * 4. BUTTONS
 * ------------------------------------------------------------------- */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-2);
    height: 38px;
    padding: 0 var(--sp-4);
    background: var(--surface);
    color: var(--text);
    border: 1px solid var(--border-2);
    border-radius: var(--radius);
    font-family: var(--font-sans);
    font-size: var(--fs-md);
    font-weight: 500;
    line-height: 1;
    text-decoration: none;
    cursor: pointer;
    white-space: nowrap;
    user-select: none;
    transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease, box-shadow 120ms ease, transform 120ms ease;
}
.btn:hover { background: var(--surface-hover); border-color: var(--border-strong); }
.btn:disabled, .btn[aria-disabled="true"] { opacity: 0.6; cursor: not-allowed; }

.btn-primary {
    background: var(--accent);
    color: #ffffff;
    border-color: var(--accent);
}
.btn-primary:hover { background: var(--accent-strong); border-color: var(--accent-strong); color: #fff; }

.btn-secondary { /* alias of base */ }

.btn-ghost {
    /* Outlined "secondary" button. Previously had `border-color: transparent`
       which left ghost buttons sitting on the page as bald text next to a
       solid primary button — visually unrecognisable as buttons. A visible
       border at rest matches the convention used by Tailwind, shadcn,
       Linear, etc. for outline / secondary buttons. */
    background: transparent;
    border-color: var(--border-strong);
    color: var(--text);
}
.btn-ghost:hover {
    background: var(--surface-hover);
    border-color: var(--text-3);
    color: var(--text);
}

.btn-sm  { height: 30px; padding: 0 var(--sp-3); font-size: var(--fs-sm); }
.btn-lg  { height: 44px; padding: 0 var(--sp-5); font-size: var(--fs-lg); }

.btn svg { width: 16px; height: 16px; flex-shrink: 0; }

/* Loading state — shimmer + cursor:progress */
@keyframes btn-shimmer {
    0%   { background-position: -200% 0; }
    100% { background-position:  200% 0; }
}
.btn[disabled],
.btn-primary[disabled] {
    cursor: progress;
    opacity: 1;
    background: linear-gradient(
        100deg,
        var(--accent) 0%,
        var(--accent) 25%,
        var(--accent-strong) 50%,
        var(--accent) 75%,
        var(--accent) 100%
    );
    background-size: 200% 100% !important;
    animation: btn-shimmer 1.6s linear infinite;
    color: #ffffff;
    border-color: var(--accent);
    transform: none !important;
}
.btn-spinner {
    /* Single canonical loading spinner — used in two call patterns:
         1. utils.setButtonLoading() in main.js, which writes the literal
            `<span class="btn-spinner"></span>Loading…` into the button
            innerHTML for tools/dns-checker.php, dns-lookup.php, etc.
         2. tools/speed-test.php's persistent-span pattern, where the
            same empty span sits inside the button and is toggled via
            display: none / inline-block by setButtonLoading().
       The <span> IS the spinner — its CSS borders draw the ring; no
       inner SVG or runtime style injection is involved. `currentColor`
       inherits the button text color (white on primary, dark on ghost),
       so the spinner reads correctly in light + dark themes with no
       per-context overrides. Reuses the existing @keyframes spin defined
       below at line ~390 and shared with the .spinner class. */
    display: inline-block;
    width: 14px;
    height: 14px;
    border: 2px solid currentColor;
    border-right-color: transparent;
    border-radius: 50%;
    animation: spin 700ms linear infinite;
    margin-right: var(--sp-2);
    vertical-align: -2px;
    flex-shrink: 0;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ---------------------------------------------------------------------
 * 5. HEADER — slim, hairline, modern-SaaS
 * ------------------------------------------------------------------- */

.header {
    position: sticky;
    top: 0;
    z-index: 50;
    background: var(--bg);
    border-bottom: 1px solid var(--border);
}
.header > .container {
    height: var(--header-h);
    display: flex;
    align-items: center;
    gap: var(--sp-5);
}
.header-content {
    width: 100%;
    height: var(--header-h);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-5);
}

/* Logo — text-only wordmark. The favicon (assets/images/favicon.svg) is
 * the only graphic mark; here we use a two-weight wordmark with a single
 * indigo dot as the brand cue. Three spans:
 *   .logo-word-soft   "Internet" — text-2, regular weight (the prefix)
 *   .logo-word-strong "Times"    — text, semibold (the emphasis)
 *   .logo-dot         "."        — indigo accent (the brand graphic)
 */
.logo a,
.logo .logo-text {
    display: inline-flex;
    align-items: baseline;
    gap: 0;
    text-decoration: none !important;
    color: var(--text) !important;
    font-family: var(--font-sans);
    font-size: 17px;
    line-height: 1;
    letter-spacing: -0.015em;
    -webkit-font-smoothing: antialiased;
}
.logo .logo-word { display: inline-block; }
.logo .logo-word-soft {
    color: var(--text-2);
    font-weight: 400;
    margin-right: 0.18em;
}
.logo .logo-word-strong {
    color: var(--text);
    font-weight: 600;
}
.logo .logo-dot {
    display: inline-block;
    color: var(--accent);
    font-weight: 700;
    margin-left: 0.04em;
}
.logo .logo-text:hover .logo-dot { color: var(--accent-strong); }
.logo .logo-text:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 4px;
    border-radius: var(--radius-sm);
}
/* Admin-uploaded image logo path — keep modest and aligned */
.logo a img { display: block; height: 28px; width: auto; }

/* Nav */
.header-right {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
}
.main-nav-list {
    display: flex;
    align-items: center;
    gap: var(--sp-1);
    margin: 0;
    padding: 0;
    list-style: none;
}
.main-nav-list > li { position: relative; }
.main-nav-list > li > a {
    display: inline-flex;
    align-items: center;
    height: 32px;
    padding: 0 var(--sp-3);
    color: var(--text-2);
    font-size: var(--fs-sm);
    font-weight: 500;
    border-radius: var(--radius-sm);
    transition: background-color 120ms ease, color 120ms ease;
    text-decoration: none;
}
.main-nav-list > li > a:hover { background: var(--surface-2); color: var(--text); }
.main-nav-list > li > a.active { color: var(--accent-text); background: var(--accent-soft); }

.dropdown-arrow {
    margin-left: var(--sp-1);
    font-size: 9px;
    color: var(--text-3);
    transition: transform 200ms ease;
}
.has-dropdown:hover > a .dropdown-arrow { transform: rotate(180deg); }

.dropdown-menu {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    min-width: 240px;
    margin-top: 4px;
    padding: var(--sp-1);
    background: var(--surface);
    border: 1px solid var(--border-2);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-lg);
    list-style: none;
    z-index: 60;
}
.has-dropdown:hover > .dropdown-menu,
.has-dropdown:focus-within > .dropdown-menu { display: block; }
.dropdown-menu .dropdown-item {
    display: block;
    padding: var(--sp-2) var(--sp-3);
    border-radius: var(--radius-sm);
    color: var(--text);
    font-size: var(--fs-sm);
    text-decoration: none;
}
.dropdown-menu .dropdown-item:hover { background: var(--surface-hover); color: var(--accent-text); }

/* Hover bridge — the dropdown sits 4 px below the parent <li> via its
 * own `margin-top`. That visible gap was unhoverable, so the cursor
 * lost :hover during the trip down → the menu vanished before reaching
 * the children. This transparent ::after extends the parent <li>'s
 * hoverable region across the gap; cursor crossing it keeps <li>:hover
 * true and the dropdown stays open. No background, no border — purely
 * a hover catcher. */
.has-dropdown::after {
    content: "";
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    height: 8px;       /* 4 px gap + 4 px slack so a fast cursor doesn't slip */
}
/* Suppress on mobile — the drawer renders dropdowns inline inside the
 * <li>, not as floating menus, so the bridge would just be dead area
 * absorbing finger taps in the slide-out menu. */
@media (max-width: 880px) {
    .has-dropdown::after { display: none; }
}

/* Quick find (Cmd+K trigger) — modern SaaS chip pattern */
.cmdk-hint {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
    height: 36px;
    padding: 0 var(--sp-3);
    background: var(--surface);
    color: var(--text-2);
    border: 1px solid var(--border-2);
    border-radius: var(--radius);
    font-size: var(--fs-sm);
    font-family: var(--font-sans);
    cursor: pointer;
    transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease;
}
.cmdk-hint:hover { background: var(--surface-hover); border-color: var(--border-strong); color: var(--text); }
.cmdk-hint .cmdk-hint-icon { display: inline-flex; }
.cmdk-hint .cmdk-hint-icon svg { width: 14px; height: 14px; color: var(--text-3); }
.cmdk-hint kbd,
kbd.kbd {
    display: inline-flex;
    align-items: center;
    height: 20px;
    padding: 0 6px;
    background: var(--surface-2);
    color: var(--text-3);
    border: 1px solid var(--border);
    border-radius: 5px;
    font-family: var(--font-mono);
    font-size: var(--fs-3xs);
    font-weight: 500;
    line-height: 1;
    vertical-align: middle;
}
@media (max-width: 640px) {
    .cmdk-hint .cmdk-hint-text { display: none; }
    .cmdk-hint kbd { display: none; }
    .cmdk-hint { width: 36px; padding: 0; justify-content: center; }
}

/* Theme toggle */
.theme-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    background: var(--surface);
    color: var(--text-2);
    border: 1px solid var(--border-2);
    border-radius: var(--radius);
    cursor: pointer;
    transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease;
}
.theme-toggle:hover { background: var(--surface-hover); border-color: var(--border-strong); color: var(--text); }
.theme-toggle svg { width: 16px; height: 16px; }
.theme-toggle .icon-moon  { display: inline-block; }
.theme-toggle .icon-sun   { display: none; }
html[data-theme="dark"] .theme-toggle .icon-moon { display: none; }
html[data-theme="dark"] .theme-toggle .icon-sun  { display: inline-block; }

/* Sign-in button — primary dark CTA */
.header-auth-link {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
    height: 36px;
    padding: 0 var(--sp-4);
    background: var(--text);
    color: var(--bg);
    border: 1px solid var(--text);
    border-radius: var(--radius);
    font-size: var(--fs-sm);
    font-weight: 600;
    text-decoration: none;
    transition: opacity 120ms ease;
}
.header-auth-link:hover { opacity: 0.88; color: var(--bg); }

/* Mobile-menu toggle */
.mobile-menu-toggle {
    display: none;
    width: 36px; height: 36px;
    align-items: center; justify-content: center;
    background: var(--surface);
    border: 1px solid var(--border-2);
    border-radius: var(--radius);
    cursor: pointer;
    flex-direction: column;
    gap: 4px;
    padding: 0;
}
.mobile-menu-toggle span {
    display: block;
    width: 14px; height: 1.5px;
    background: var(--text-2);
    border-radius: 2px;
}

@media (max-width: 880px) {
    .mobile-menu-toggle { display: inline-flex; }
    .main-nav { display: none; }
    .main-nav.mobile-active {
        display: block;
        position: fixed;
        top: var(--header-h);
        left: 0;
        right: 0;
        bottom: 0; /* fills the visible viewport below the header — works
                    * reliably across iOS Safari URL-bar resizing where
                    * `100vh` and `calc(100vh - …)` overshoot. */
        overflow-y: auto;
        -webkit-overflow-scrolling: touch; /* iOS momentum scroll */
        overscroll-behavior: contain;       /* don't scroll-chain to <body> */
        background: var(--surface);
        border-top: 1px solid var(--border);
        box-shadow: var(--shadow-md);
        padding: var(--sp-3) var(--sp-3) calc(var(--sp-6) + env(safe-area-inset-bottom));
        z-index: 49; /* sits below the sticky header (z-index 50) */
    }
    .main-nav.mobile-active .main-nav-list {
        flex-direction: column;
        align-items: stretch;
        gap: 0;
    }
    .main-nav.mobile-active .main-nav-list > li > a {
        height: 44px;
        padding: 0 var(--sp-4);
        font-size: var(--fs-md);
    }
    .main-nav.mobile-active .dropdown-arrow { display: none; }
    .main-nav.mobile-active .dropdown-menu {
        display: block;
        position: static;
        box-shadow: none;
        border: none;
        background: transparent;
        padding-left: var(--sp-4);
        margin: 0;
        opacity: 1;
        visibility: visible;
        transform: none;
    }
    /* Hamburger morphs to an X when the drawer is open */
    .mobile-menu-toggle.active span:nth-child(1) {
        transform: translateY(5.5px) rotate(45deg);
    }
    .mobile-menu-toggle.active span:nth-child(2) { opacity: 0; }
    .mobile-menu-toggle.active span:nth-child(3) {
        transform: translateY(-5.5px) rotate(-45deg);
    }
    .mobile-menu-toggle span {
        transition: transform 160ms ease, opacity 120ms ease;
    }
    /* Lock body scroll while drawer is open */
    body.menu-open { overflow: hidden; }
}

/* On phones, the header-right has too many things to fit alongside the
 * hamburger. Hide the cmdk-hint chip and the Sign-in button text — both
 * surfaces remain available inside the mobile drawer (cmdk via ⌘K, the
 * Sign-in link is appended to the drawer below by the inline JS bootstrap
 * in main.js if needed). The theme-toggle and hamburger stay reachable. */
@media (max-width: 640px) {
    .header > .container { gap: var(--sp-3); padding-left: var(--sp-4); padding-right: var(--sp-4); }
    .header-content { gap: var(--sp-2); }
    .header-right { gap: var(--sp-2); }
    /* Keep the cmdk-hint visible on mobile — collapsed to icon-only by the
     * earlier rule at 640px (text + kbd hidden, 36px square). The previous
     * `display: none` here removed the search affordance entirely; that's
     * undesirable since ⌘K is the primary navigation shortcut on phones. */
    .header-auth-link {
        height: 36px;
        padding: 0 var(--sp-3);
        font-size: var(--fs-xs);
    }
    /* Keep the full "Internet Times." wordmark visible — just shrink it. */
    .logo a, .logo .logo-text { font-size: 15px; letter-spacing: -0.02em; }
}
@media (max-width: 380px) {
    /* Phones below 380px (Galaxy Fold, older iPhone SE etc) — drop the
     * theme toggle + auth chip from the header bar so the hamburger and
     * the logo always have room to breathe. The logo prefix stays. */
    .header-auth { display: none; }
    .theme-toggle { display: none; }
}

/* ---------------------------------------------------------------------
 * 6. BREADCRUMBS
 * ------------------------------------------------------------------- */

.breadcrumbs {
    background: transparent;
    border: none;
    padding: var(--sp-5) var(--sp-5) 0;
    max-width: var(--site-max);
    margin: 0 auto;
}
.breadcrumbs-container { padding: 0; }
.breadcrumb-list {
    /* VOICE: txt-meta */
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sp-2);
    margin: 0; padding: 0;
    list-style: none;
    font-family: var(--font-mono);
    font-size: var(--fs-xs);
    font-weight: 400;
    line-height: 1.5;
    color: var(--text-3);
}
.breadcrumb-item { display: inline-flex; align-items: center; gap: var(--sp-2); }
.breadcrumb-item:not(:last-child)::after {
    content: "/";
    color: var(--text-3);
    font-weight: 400;
}
.breadcrumb-link, .breadcrumb-current {
    color: var(--text-3);
    text-decoration: none;
}
.breadcrumb-link:hover { color: var(--accent); }
.breadcrumb-current { color: var(--text-2); }

/* ---------------------------------------------------------------------
 * 7. HOMEPAGE — marketing-style hero + tool grid
 * ------------------------------------------------------------------- */

.it-hero {
    padding: var(--sp-12) var(--sp-5) var(--sp-10);
    background: var(--bg);
}
.it-hero-inner {
    max-width: var(--site-max);
    margin: 0 auto;
}
.it-hero-copy {
    max-width: 760px;
    margin: 0 auto;
    text-align: center;
}
.it-hero h1 {
    font-size: var(--fs-hero-xl);
    line-height: 1.15;
    letter-spacing: -0.02em;
    margin: 0 0 var(--sp-4);
    text-wrap: balance;
    color: var(--text);
}
.it-hero h1 .accent {
    background: linear-gradient(135deg, var(--accent) 0%, var(--accent-strong) 100%);
    -webkit-background-clip: text;
            background-clip: text;
    color: transparent;
}
.it-hero p.lede {
    font-size: var(--fs-lg);
    line-height: 1.6;
    color: var(--text-2);
    margin: 0 auto var(--sp-6);
    max-width: 620px;
    text-wrap: pretty;
}
.it-hero-actions {
    display: flex;
    justify-content: center;
    flex-wrap: wrap;
    gap: var(--sp-3);
}
.it-btn { /* alias of .btn, used inline by some templates */ }
.it-btn-primary { /* alias of .btn-primary */ }
.it-btn-ghost  { /* alias of .btn-ghost */ }

@media (max-width: 640px) {
    .it-hero { padding: var(--sp-10) var(--sp-4) var(--sp-8); }
    .it-hero p.lede { font-size: var(--fs-md); }
}

/* Section frame */
.it-section {
    padding: var(--sp-12) var(--sp-5);
}
.it-section-inner {
    max-width: var(--site-max);
    margin: 0 auto;
}
.it-section-head {
    margin-bottom: var(--sp-8);
    text-align: center;
    max-width: 720px;
    margin-left: auto;
    margin-right: auto;
}
.it-section-eyebrow {
    display: inline-block;
    font-family: var(--font-mono);
    font-size: var(--fs-xs);
    font-weight: 500;
    color: var(--text-3);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    margin-bottom: var(--sp-3);
}
.it-section-head h2 {
    font-size: clamp(24px, 3vw, var(--fs-3xl));
    margin: 0 0 var(--sp-3);
    color: var(--text);
}
.it-section-head p {
    color: var(--text-2);
    font-size: var(--fs-md);
    line-height: 1.6;
    margin: 0;
}

/* Category row above tool sub-grids */
.it-cat-row {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--sp-3);
    margin: var(--sp-8) 0 var(--sp-4);
    padding-bottom: var(--sp-3);
    border-bottom: 1px solid var(--divider);
}
.it-cat-row:first-child { margin-top: 0; }
.it-cat-row .swatch {
    width: 8px; height: 8px;
    border-radius: 2px;
    background: var(--accent);
    flex-shrink: 0;
}
.it-cat-row[data-cat="dns"]     .swatch { background: #5e6ad2; }
.it-cat-row[data-cat="email"]   .swatch { background: #c084fc; }
.it-cat-row[data-cat="ip"]      .swatch { background: #16a34a; }
.it-cat-row[data-cat="security"].swatch,
.it-cat-row[data-cat="security"] .swatch { background: #d97706; }
.it-cat-row h3 {
    font-size: var(--fs-md);
    font-weight: 600;
    margin: 0;
    color: var(--text);
}
.it-cat-row .desc {
    color: var(--text-3);
    font-size: var(--fs-sm);
    margin: 0;
}

/* Tool grid */
.it-tools-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: var(--sp-4);
}

/* Tool card */
.it-tool-card {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: var(--sp-3);
    padding: var(--sp-5);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    color: var(--text);
    text-decoration: none;
    transition: border-color 160ms ease, background-color 160ms ease, transform 160ms ease, box-shadow 160ms ease;
    overflow: hidden;
}
.it-tool-card:hover {
    border-color: var(--border-2);
    background: var(--surface);
    transform: translateY(-1px);
    box-shadow: var(--shadow-md);
    color: var(--text);
}
.it-tool-card-name {
    font-size: var(--fs-md);
    font-weight: 600;
    color: var(--text);
    line-height: 1.3;
    margin: 0;
}
.it-tool-card-desc {
    font-size: var(--fs-sm);
    color: var(--text-2);
    line-height: 1.55;
    margin: 0;
    flex: 1;
}
.it-tool-card-arrow {
    align-self: flex-start;
    color: var(--accent-text);
    font-size: var(--fs-md);
    line-height: 1;
    opacity: 0;
    transform: translateX(-3px);
    transition: opacity 160ms ease, transform 160ms ease;
}
.it-tool-card:hover .it-tool-card-arrow {
    opacity: 1;
    transform: translateX(0);
}
.it-tool-card-badge {
    position: absolute;
    top: var(--sp-3); right: var(--sp-3);
    font-family: var(--font-mono);
    font-size: var(--fs-2xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    padding: 2px 6px;
    border-radius: 4px;
    background: var(--accent-soft);
    color: var(--accent-text);
    border: 1px solid var(--accent-ring);
    line-height: 1.5;
}

/* Trust grid (homepage feature cards) */
.it-trust-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: var(--sp-4);
}
.it-trust-card {
    padding: var(--sp-5);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
}
.it-trust-card .ic {
    width: 32px; height: 32px;
    display: inline-flex;
    align-items: center; justify-content: center;
    background: var(--accent-soft);
    color: var(--accent-text);
    border-radius: var(--radius);
    margin-bottom: var(--sp-3);
}
.it-trust-card .ic svg { width: 16px; height: 16px; }
.it-trust-card h3 {
    font-size: var(--fs-md);
    margin: 0 0 var(--sp-2);
    color: var(--text);
}
.it-trust-card p {
    font-size: var(--fs-sm);
    color: var(--text-2);
    line-height: 1.55;
    margin: 0;
}

/* Blog card variant on homepage */
.it-blog-card {
    padding: var(--sp-5);
}
.it-blog-card-date {
    display: block;
    font-family: var(--font-mono);
    font-size: var(--fs-xs);
    color: var(--text-3);
    margin-top: auto;
}

/* ---------------------------------------------------------------------
 * 8. TOOL PAGE CHROME
 * ------------------------------------------------------------------- */

.tool-page-hero {
    /* Outer band: vertical rhythm only. Horizontal padding lives on the
       inner .container so the content edge lines up with the header and
       footer (which both use the default .container { padding: 0 20px }
       pattern). Setting padding here used to double-pad and shift the
       hero 20px wider than the header. */
    background: transparent;
    border: none;
    padding: var(--sp-5) 0 0;
    margin: 0;
}
.it-tool-head {
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
}
.it-tool-head h1 {
    font-size: var(--fs-hero);
    margin: 0;
    color: var(--text);
    letter-spacing: -0.025em;
    line-height: 1.15;
}
.it-tool-head p.sub {
    /* No artificial max-width — the description should wrap at the same
       width as the form / sidebar grid below it, not at an arbitrary
       narrower line. Container width + natural sentence length give
       comfortable reading without a hard cap that visibly truncates. */
    color: var(--text-2);
    font-size: var(--fs-lg);
    line-height: 1.6;
    margin: 0;
}

.tool-page {
    /* See note on .tool-page-hero: outer band keeps vertical padding only;
       inner .container handles horizontal padding so this section's left
       edge lines up with the header + footer + breadcrumbs. */
    padding: var(--sp-5) 0 var(--sp-16);
}

/* Canonical "main column + right sidebar" layout.
   Used by every page type that has a right-rail:
     • tool pages         → .content-with-sidebar (nested inside .container)
     • blog index/list    → .blog-page-inner
     • blog posts         → .blog-post-inner
     • static pages       → .static-page-inner.has-sidebar
   One rule, one breakpoint, one source of truth so the entire site reads
   as one app instead of three slightly-different layouts. Blog + static
   wrappers self-host their max-width + horizontal padding (they don't
   sit inside a parent `.container` the way tool pages do). */
.content-with-sidebar,
.blog-page-inner,
.blog-post-inner,
.static-page-inner.has-sidebar {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 320px;
    gap: var(--sp-8);
    align-items: flex-start;
}
.blog-page-inner,
.blog-post-inner,
.static-page-inner.has-sidebar {
    max-width: var(--site-max);
    margin: 0 auto;
    padding: 0 var(--sp-5);
}
.main-content-area,
.blog-main { min-width: 0; }
.sidebar,
.blog-sidebar { position: sticky; top: calc(var(--header-h) + 16px); }
@media (max-width: 960px) {
    .content-with-sidebar,
    .blog-page-inner,
    .blog-post-inner,
    .static-page-inner.has-sidebar {
        grid-template-columns: 1fr;
        gap: var(--sp-5);
    }
    .sidebar,
    .blog-sidebar { position: static; }
}

/* ---------------------------------------------------------------------
 * 9. FORM PANEL (input cards on tool pages)
 * ------------------------------------------------------------------- */

.tool-form {
    background: var(--surface);
    border: 1px solid var(--border-2);
    border-radius: var(--radius-lg);
    padding: var(--sp-5);
    box-shadow: var(--shadow-sm);
}

.form-group {
    margin: 0 0 var(--sp-4);
    position: relative;
}
.form-group:last-of-type { margin-bottom: var(--sp-5); }
.form-group label {
    display: block;
    font-size: var(--fs-xs);
    font-weight: 600;
    color: var(--text-2);
    margin-bottom: var(--sp-2);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    font-family: var(--font-mono);
}

.form-control,
.tool-form input[type="text"],
.tool-form input[type="url"],
.tool-form input[type="search"],
.tool-form input[type="number"],
.tool-form input[type="email"],
.tool-form select,
.tool-form textarea {
    display: block;
    width: 100%;
    height: 42px;
    padding: 0 var(--sp-4);
    background: var(--bg);
    color: var(--text);
    border: 1px solid var(--border-2);
    border-radius: var(--radius);
    font-family: var(--font-mono);
    font-size: var(--fs-md);
    line-height: 1.4;
    outline: none;
    box-shadow: none;
    transition: border-color 120ms ease, box-shadow 120ms ease, background-color 120ms ease;
}
.tool-form textarea { min-height: 96px; padding: var(--sp-3); height: auto; }
.tool-form input:focus,
.tool-form select:focus,
.tool-form textarea:focus,
.form-control:focus {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-ring);
    background: var(--surface);
}
.tool-form input::placeholder,
.tool-form textarea::placeholder { color: var(--text-3); }

.tool-form select {
    appearance: none;
    -webkit-appearance: none;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%2384878d' stroke-width='2'><polyline points='6 9 12 15 18 9'/></svg>");
    background-position: right var(--sp-3) center;
    background-repeat: no-repeat;
    padding-right: var(--sp-8);
}


.tool-form .btn,
.tool-form .btn-primary {
    height: 42px;
    padding: 0 var(--sp-5);
    font-size: var(--fs-md);
    font-weight: 600;
}

/* Loading indicator */
.loading-indicator {
    margin-top: var(--sp-5);
    padding: var(--sp-4);
    background: var(--surface);
    border: 1px dashed var(--border-2);
    border-radius: var(--radius);
    align-items: center;
    gap: var(--sp-3);
    color: var(--text-2);
    font-family: var(--font-mono);
    font-size: var(--fs-sm);
    position: relative;
    overflow: hidden;
}
.loading-indicator p { margin: 0; color: inherit; }
.loading-indicator[style*="display: block"],
.loading-indicator[style*="display:block"],
.loading-indicator[style*="display: flex"],
.loading-indicator[style*="display:flex"] {
    display: flex !important;
}
.loading-indicator .spinner,
.spinner {
    width: 16px; height: 16px;
    border: 2px solid var(--border-2);
    border-top-color: var(--accent);
    border-radius: 50%;
    animation: spin 700ms linear infinite;
    flex-shrink: 0;
}
@keyframes loading-bar {
    0%   { transform: translateX(-100%); }
    100% { transform: translateX(100%); }
}
.loading-indicator::after {
    content: "";
    position: absolute;
    left: 0; right: 0; bottom: 0;
    height: 2px;
    background: linear-gradient(90deg, transparent, var(--accent), transparent);
    transform: translateX(-100%);
    animation: loading-bar 1.4s ease-in-out infinite;
}

/* ---------------------------------------------------------------------
 * 10. RESULT PANEL — inspector chrome for every tool
 * ------------------------------------------------------------------- */

.tool-results,
.dns-results,
.ip-details,
.blacklist-results {
    margin-top: var(--sp-5);
    background: var(--surface);
    border: 1px solid var(--border-2);
    border-radius: var(--radius-lg);
    padding: 0;
    overflow: hidden;
}
.tool-results:empty,
.dns-results:empty,
.ip-details:empty,
.blacklist-results:empty { display: none; }

/* Section headings inside results (h3/h4 directly inside) */
#results > h3,
#results > h4,
.tool-results > h3,
.tool-results > h4,
.dns-results > h3,
.dns-results > h4,
.ip-details > h3,
.ip-details > h4,
.blacklist-results > h3,
.blacklist-results > h4 {
    margin: 0;
    padding: var(--sp-3) var(--sp-4);
    font-size: var(--fs-xs);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    font-weight: 600;
    color: var(--text-2);
    font-family: var(--font-mono);
    background: var(--surface-2);
    border-top: 1px solid var(--border);
    border-bottom: 1px solid var(--border);
}
#results > h3:first-child,
#results > h4:first-child,
.tool-results > h3:first-child,
.tool-results > h4:first-child,
.dns-results > h3:first-child,
.dns-results > h4:first-child,
.ip-details > h3:first-child,
.ip-details > h4:first-child,
.blacklist-results > h3:first-child,
.blacklist-results > h4:first-child { border-top: none; }

/* Section description */
#results > p,
.tool-results > p,
.dns-results > p,
.ip-details > p {
    margin: 0;
    padding: var(--sp-3) var(--sp-4);
    color: var(--text-2);
    font-size: var(--fs-md);
    border-bottom: 1px solid var(--divider);
}

/* Result-section wrappers (used by DNS Lookup record-section) */
.dns-results .record-section,
#results .record-section { margin: 0; }
.dns-results .record-section h4,
.tool-results .record-section h4,
#results .record-section h4 {
    margin: 0;
    padding: var(--sp-3) var(--sp-4);
    font-size: var(--fs-xs);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    font-weight: 600;
    color: var(--text-2);
    font-family: var(--font-mono);
    background: var(--surface-2);
    border-top: 1px solid var(--border);
    border-bottom: 1px solid var(--border);
}
.dns-results .record-section:first-of-type h4,
#results .record-section:first-of-type h4 { border-top: none; }

/* The .results-table wrapper div — make horizontally scrollable */
.tool-results .results-table,
.dns-results .results-table,
.ip-details .results-table,
.blacklist-results .results-table,
#results .results-table {
    background: transparent;
    border: none;
    border-radius: 0;
    box-shadow: none;
    margin: 0;
    padding: 0;
    width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    max-width: 100%;
}

/* Tables inside results */
.tool-results table,
.dns-results table,
.ip-details table,
.blacklist-results table,
#results table,
.results-table > table {
    width: 100%;
    min-width: 100%;
    border-collapse: collapse;
    background: transparent;
    margin: 0;
    table-layout: auto;
}

.tool-results th,
.dns-results th,
.ip-details th,
.blacklist-results th,
#results th,
.results-table th {
    padding: var(--sp-3) var(--sp-4);
    background: var(--surface-2);
    color: var(--text-2);
    font-weight: 600;
    font-size: var(--fs-xs);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    text-align: left;
    border-bottom: 1px solid var(--border-2);
    white-space: nowrap;
    vertical-align: middle;
    min-width: 80px;
}

.tool-results td,
.dns-results td,
.ip-details td,
.blacklist-results td,
#results td,
.results-table td {
    padding: var(--sp-3) var(--sp-4);
    border-bottom: 1px solid var(--divider);
    text-align: left;
    font-size: var(--fs-sm);
    vertical-align: middle;
    color: var(--text);
}

.tool-results td:first-child,
.dns-results td:first-child,
.ip-details td:first-child,
.blacklist-results td:first-child,
#results td:first-child,
.results-table td:first-child {
    font-family: var(--font-mono);
    color: var(--text-mono);
    font-size: var(--fs-sm);
    white-space: nowrap;
    overflow-wrap: normal;
    word-break: keep-all;
    hyphens: none;
}
.tool-results td:not(:first-child),
.dns-results td:not(:first-child),
.ip-details td:not(:first-child),
.blacklist-results td:not(:first-child),
#results td:not(:first-child),
.results-table td:not(:first-child) {
    font-family: var(--font-mono);
    color: var(--text-mono);
    overflow-wrap: anywhere;
    word-break: break-word;
    hyphens: none;
}

.tool-results tr:last-child td,
.dns-results tr:last-child td,
.ip-details tr:last-child td,
.blacklist-results tr:last-child td,
#results tr:last-child td,
.results-table tr:last-child td { border-bottom: none; }

.tool-results tr:hover td,
.dns-results tr:hover td,
.ip-details tr:hover td,
.blacklist-results tr:hover td,
#results tr:hover td,
.results-table tr:hover td { background: var(--surface-2); }

.tool-results td code,
.dns-results td code,
.ip-details td code,
#results td code,
.results-table td code {
    word-break: break-all;
    background: transparent;
    border: none;
    padding: 0;
    color: var(--text-mono);
    font-family: var(--font-mono);
    font-size: var(--fs-sm);
}

/* Status pills inside results */
.status,
.status-ok, .status-warn, .status-bad,
.dns-results .clean, .blacklist-results .clean,
.dns-results .listed, .blacklist-results .listed {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-1);
    padding: 2px var(--sp-2);
    border-radius: 999px;
    font-family: var(--font-sans);
    font-size: var(--fs-xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    border: 1px solid currentColor;
    line-height: 1.4;
}
.status::before,
.status-ok::before, .status-warn::before, .status-bad::before {
    content: "";
    width: 6px; height: 6px; border-radius: 50%;
    background: currentColor;
    flex-shrink: 0;
}
.status.success, .status-ok, .clean { color: var(--ok); background: var(--ok-soft); }
.status.warning, .status-warn       { color: var(--warn); background: var(--warn-soft); }
.status.error, .status-bad, .listed { color: var(--err); background: var(--err-soft); }

/* MX/HTTP/SSL inline-color spans → real status pills */
#results span[style*="#10b981"],
#results span[style*="rgb(16, 185, 129)"],
.tool-results span[style*="#10b981"] {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 2px 8px !important;
    background: var(--ok-soft) !important;
    color: var(--ok) !important;
    border: 1px solid currentColor !important;
    border-radius: 999px !important;
    font-family: var(--font-sans) !important;
    font-size: var(--fs-xs) !important;
    font-weight: 600 !important;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}
#results span[style*="#10b981"]::before,
.tool-results span[style*="#10b981"]::before {
    content: "";
    width: 6px; height: 6px; border-radius: 50%;
    background: var(--ok);
}
#results span[style*="#dc2626"],
#results span[style*="rgb(220, 38, 38)"],
.tool-results span[style*="#dc2626"] {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 2px 8px !important;
    background: var(--err-soft) !important;
    color: var(--err) !important;
    border: 1px solid currentColor !important;
    border-radius: 999px !important;
    font-family: var(--font-sans) !important;
    font-size: var(--fs-xs) !important;
    font-weight: 600 !important;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}
#results span[style*="#dc2626"]::before,
.tool-results span[style*="#dc2626"]::before {
    content: "";
    width: 6px; height: 6px; border-radius: 50%;
    background: var(--err);
}

/* SSL Subject Alt Names list — replace `columns: 2` with grid */
#results ul[style*="columns:"],
.tool-results ul[style*="columns:"] {
    columns: auto !important;
    column-count: auto !important;
    list-style: none !important;
    padding: var(--sp-3) var(--sp-4) !important;
    margin: 0 !important;
    display: grid !important;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)) !important;
    gap: 4px var(--sp-5) !important;
    background: var(--surface) !important;
    border-bottom: 1px solid var(--divider) !important;
    font-family: var(--font-mono);
    font-size: var(--fs-sm);
    color: var(--text-mono);
}
#results ul[style*="columns:"] li,
.tool-results ul[style*="columns:"] li {
    padding: 2px 0 !important;
    border: none !important;
    overflow-wrap: anywhere;
}

/* HTTP Headers results-summary */
#results .results-summary {
    padding: var(--sp-4);
    border-bottom: 1px solid var(--divider);
    background: var(--surface);
}
#results .results-summary h3 {
    background: transparent !important;
    border: none !important;
    padding: 0 !important;
    text-transform: none !important;
    letter-spacing: 0 !important;
    font-size: var(--fs-lg) !important;
    color: var(--text) !important;
    font-family: var(--font-sans) !important;
    font-weight: 600 !important;
    margin-bottom: var(--sp-2) !important;
}
#results .results-summary p {
    margin: 0 0 4px !important;
    padding: 0 !important;
    border: none !important;
    font-size: var(--fs-sm);
    color: var(--text-2) !important;
}
#results .results-summary code {
    background: var(--surface-2) !important;
    border: 1px solid var(--border) !important;
    padding: 1px 6px !important;
    border-radius: 5px !important;
    font-size: 0.9em !important;
    color: var(--text-mono) !important;
    word-break: break-all;
}

/* WHOIS raw response */
.whois-raw-details {
    border-top: 1px solid var(--border);
}
.whois-raw-details summary {
    background: var(--surface-2);
    padding: var(--sp-3) var(--sp-4);
    font-family: var(--font-mono);
    font-size: var(--fs-xs);
    color: var(--text-2);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    font-weight: 600;
    cursor: pointer;
    list-style: none;
}
.whois-raw-details summary::-webkit-details-marker { display: none; }
.whois-raw-details summary::before {
    content: "▸";
    margin-right: var(--sp-2);
    color: var(--accent);
    transition: transform 200ms ease;
    display: inline-block;
}
.whois-raw-details[open] summary::before { transform: rotate(90deg); }
.whois-raw-pre {
    margin: 0;
    padding: var(--sp-4);
    background: var(--bg);
    color: var(--text-mono);
    font-family: var(--font-mono);
    font-size: var(--fs-sm);
    line-height: 1.6;
    white-space: pre-wrap;
    word-break: break-word;
    border-top: 1px solid var(--border);
    max-height: 400px;
    overflow-y: auto;
}

/* =====================================================================
 * Tool-result message banners — error / warning / success
 * Each is a strip across the top/bottom of the result panel.
 * =================================================================== */
#results .error-message,
.tool-results .error-message,
.dns-results .error-message {
    padding: var(--sp-4);
    color: var(--err);
    background: var(--err-soft);
    border-bottom: 1px solid var(--border);
    font-family: var(--font-mono);
    font-size: var(--fs-sm);
    margin: 0;
    line-height: 1.55;
}
#results .warning-message,
.tool-results .warning-message {
    padding: var(--sp-4);
    color: var(--warn);
    background: var(--warn-soft);
    border-top: 1px solid var(--border);
    font-size: var(--fs-sm);
    margin: 0;
    line-height: 1.55;
}
#results .success-message,
.tool-results .success-message {
    padding: var(--sp-4);
    color: var(--ok);
    background: var(--ok-soft);
    border-top: 1px solid var(--border);
    font-size: var(--fs-sm);
    margin: 0;
    line-height: 1.55;
}
#results .warning-message strong,
#results .success-message strong,
.tool-results .warning-message strong,
.tool-results .success-message strong {
    color: inherit;
    font-weight: 600;
}

/* =====================================================================
 * Status icons — round badges used by dns-checker per-row (✓ / ✗ / ⚠)
 * and reused by other tools that emit a `<span class="status-icon ...">`.
 * =================================================================== */
.tool-results .status-icon,
#results .status-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px; height: 22px;
    border-radius: 50%;
    font-size: var(--fs-xs);
    font-weight: 700;
    line-height: 1;
    flex-shrink: 0;
}
.tool-results .status-icon.success, #results .status-icon.success {
    background: var(--ok-soft); color: var(--ok);
}
.tool-results .status-icon.error, #results .status-icon.error {
    background: var(--err-soft); color: var(--err);
}
.tool-results .status-icon.warning, #results .status-icon.warning {
    background: var(--warn-soft); color: var(--warn);
}

/* =====================================================================
 * IP-blacklist-check 4-up summary cards (Total / Clean / Listed / Errors)
 * Sits above the per-RBL results table.
 * =================================================================== */
#results .summary-cards,
.tool-results .summary-cards,
.blacklist-results .summary-cards {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--sp-3);
    padding: var(--sp-4);
    background: var(--surface);
    border-bottom: 1px solid var(--divider);
    margin: 0;
}
#results .summary-card,
.tool-results .summary-card,
.blacklist-results .summary-card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: var(--sp-3);
    text-align: center;
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
}
#results .summary-card .card-number,
.tool-results .summary-card .card-number,
.blacklist-results .summary-card .card-number {
    font-family: var(--font-mono);
    font-size: var(--fs-2xl);
    font-weight: 600;
    color: var(--text);
    line-height: 1.1;
}
#results .summary-card .card-label,
.tool-results .summary-card .card-label,
.blacklist-results .summary-card .card-label {
    font-size: var(--fs-xs);
    color: var(--text-3);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-weight: 500;
}
#results .summary-card.clean .card-number,
.tool-results .summary-card.clean .card-number,
.blacklist-results .summary-card.clean .card-number { color: var(--ok); }
#results .summary-card.listed .card-number,
.tool-results .summary-card.listed .card-number,
.blacklist-results .summary-card.listed .card-number,
#results .summary-card.errors .card-number,
.tool-results .summary-card.errors .card-number,
.blacklist-results .summary-card.errors .card-number { color: var(--err); }

@media (max-width: 640px) {
    #results .summary-cards,
    .tool-results .summary-cards,
    .blacklist-results .summary-cards {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        padding: var(--sp-3);
    }
}

/* =====================================================================
 * DNS-checker mobile cards — rendered when window.innerWidth <= 768.
 * Container `.mobile-results` holds many `.result-card`, each with a
 * `.card-header` (server name + status) and `.card-body` (label/value rows).
 * =================================================================== */
#results .mobile-results,
.tool-results .mobile-results {
    display: flex;
    flex-direction: column;
    gap: var(--sp-3);
    padding: var(--sp-4);
    background: var(--surface);
}
#results .mobile-results .result-card,
.tool-results .mobile-results .result-card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: var(--sp-3) var(--sp-4);
    box-shadow: var(--shadow-sm);
}
#results .mobile-results .card-header,
.tool-results .mobile-results .card-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: var(--sp-3);
    padding-bottom: var(--sp-2);
    border-bottom: 1px solid var(--divider);
    margin-bottom: var(--sp-3);
}
#results .mobile-results .server-name,
.tool-results .mobile-results .server-name {
    font-weight: 600;
    color: var(--text);
    font-size: var(--fs-md);
    overflow-wrap: anywhere;
}
#results .mobile-results .card-body,
.tool-results .mobile-results .card-body {
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
}
#results .mobile-results .result-row,
.tool-results .mobile-results .result-row {
    display: flex;
    justify-content: space-between;
    gap: var(--sp-3);
    align-items: baseline;
    font-size: var(--fs-sm);
}
#results .mobile-results .result-row .label,
.tool-results .mobile-results .result-row .label {
    color: var(--text-3);
    font-size: var(--fs-xs);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    font-weight: 500;
    flex-shrink: 0;
}
#results .mobile-results .result-row .value,
.tool-results .mobile-results .result-row .value {
    color: var(--text);
    font-family: var(--font-mono);
    font-size: var(--fs-sm);
    text-align: right;
    word-break: break-all;
    overflow-wrap: anywhere;
    flex: 1;
    min-width: 0;
}
/* Hide the desktop table when mobile cards are active; hide the cards
 * when desktop table is active. dns-checker only renders one of them at a
 * time, but if window resize triggers a re-render mismatch, this prevents
 * both from showing simultaneously. */
#results .desktop-results { display: block; }

/* =====================================================================
 * DNS-checker desktop column widths. Table layout is:
 *   Resolver | IP | Time | Records | Status
 * Records is the wide column; status is icon-only narrow.
 * =================================================================== */
.dns-results th.col-server,
.dns-results td.col-server { white-space: nowrap; min-width: 140px; }
.dns-results th.col-ip,
.dns-results td.col-ip { font-family: var(--font-mono); white-space: nowrap; min-width: 120px; }
.dns-results th.col-time,
.dns-results td.col-time { font-family: var(--font-mono); white-space: nowrap; text-align: right; min-width: 64px; }
.dns-results th.col-records,
.dns-results td.col-records { min-width: 220px; word-break: break-all; overflow-wrap: anywhere; }
.dns-results th.col-status,
.dns-results td.col-status { width: 56px; text-align: center; }

/* =====================================================================
 * what-is-my-ip-address top widget — IP display with copy button.
 * Shown before the user clicks "Get Detailed Information".
 * =================================================================== */
.ip-display-form {
    display: flex;
    flex-direction: column;
    gap: var(--sp-4);
}
/* The form-group inside ip-display-form holds the label + the v4/v6 rows.
 * Make it a flex column with proper spacing so the IP rows breathe. */
.ip-display-form .form-group {
    display: flex;
    flex-direction: column;
    gap: var(--sp-3); /* breathing room between IPv4 and IPv6 rows */
    margin: 0;
}
/* Tighter rules: between sibling .ip-address-display rows specifically.
 * (Belt-and-braces if the form-group flex doesn't apply for any reason.) */
.ip-address-display + .ip-address-display { margin-top: 0; /* gap from form-group flex handles it */ }
.ip-display-label {
    display: block;
    font-size: var(--fs-sm);
    font-weight: 500;
    color: var(--text);
    margin: 0; /* parent .form-group is flex with gap; no margin needed */
}
.ip-address-display {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    padding: var(--sp-3) var(--sp-4);
    background: var(--surface);
    border: 1px solid var(--border-2);
    border-radius: var(--radius);
    flex-wrap: wrap;
}
.ip-address-display.ip-status-error {
    border-color: rgba(220, 38, 38, 0.32);
    background: var(--err-soft);
}
.ip-address-display.ip-status-warn {
    border-color: rgba(217, 119, 6, 0.32);
    background: var(--warn-soft);
}
.ip-value {
    font-family: var(--font-mono);
    font-size: var(--fs-md);
    color: var(--text);
    font-weight: 500;
    word-break: break-all;
    overflow-wrap: anywhere;
    flex: 1;
    min-width: 0;
}
.ip-value.ipv6-value { font-size: var(--fs-sm); }
.ip-type-badge {
    display: inline-flex;
    align-items: center;
    padding: 2px 8px;
    border-radius: 999px;
    font-size: var(--fs-3xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    flex-shrink: 0;
    line-height: 1.5;
}
.ip-type-badge.ipv4-badge      { background: var(--accent-soft); color: var(--accent-text); }
.ip-type-badge.ipv6-badge      { background: rgba(124, 58, 237, 0.10); color: #7c3aed; }
.ip-type-badge.ip-badge-error  { background: var(--err-soft); color: var(--err); }
.ip-type-badge.ip-badge-warn   { background: var(--warn-soft); color: var(--warn); }
.copy-ip-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px; height: 32px;
    border: 1px solid var(--border-2);
    background: var(--surface);
    border-radius: var(--radius-sm);
    color: var(--text-2);
    cursor: pointer;
    transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease;
    flex-shrink: 0;
    padding: 0;
}
.copy-ip-btn:hover {
    background: var(--surface-hover);
    border-color: var(--border-strong);
    color: var(--text);
}
.copy-ip-btn svg { width: 16px; height: 16px; }

/* IPv4/IPv6 details — shown after "Get Detailed Information" click on
 * what-is-my-ip-address, or always on ip-lookup. Each `.ip-version-details`
 * is a self-contained card (one card for IPv4, one card for IPv6) with
 * its own header strip and table. Cards stack vertically with breathing
 * room between them.
 *
 * The parent `.ip-details > h3` ("Detailed IP Information" /
 * "IP Information for X.X.X.X") is no longer rendered as an eyebrow
 * strip — it's a quiet section title that sits above the cards instead
 * of acting as a card itself. That's what avoids the nested-card look. */
.ip-version-details {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    overflow: hidden;
    margin: 0;
    box-shadow: var(--shadow-sm);
}
.ip-version-details + .ip-version-details {
    margin-top: var(--sp-4); /* breathing room between IPv4 + IPv6 cards */
}
.ip-version-details > h4 {
    margin: 0;
    padding: var(--sp-3) var(--sp-4);
    font-size: var(--fs-xs);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    font-weight: 600;
    color: var(--text-2);
    font-family: var(--font-mono);
    background: var(--surface-2);
    border-bottom: 1px solid var(--divider);
}
.ip-version-details > .results-table {
    border: none;
    border-radius: 0;
    background: var(--surface);
}
.ip-version-details > .results-table > table { border: none; border-radius: 0; }

/* Override the eyebrow-strip styling for the parent `<h3>` in `.ip-details`
 * (e.g. "Detailed IP Information", "IP Information for 1.1.1.1"). It now
 * renders as a quiet section title sitting above the cards, not as a
 * card-style strip header itself. This prevents the visible nesting. */
.ip-details > h3 {
    background: transparent !important;
    border-top: none !important;
    border-bottom: none !important;
    padding: 0 0 var(--sp-3) 0 !important;
    margin: 0 0 var(--sp-4) 0 !important;
    font-family: var(--font-sans) !important;
    font-size: var(--fs-lg) !important;
    font-weight: 600 !important;
    text-transform: none !important;
    letter-spacing: -0.01em !important;
    color: var(--text) !important;
}

/* When `.ip-details` (or `.tool-results`) contains `.ip-version-details`
 * card subsections inside, STRIP the outer panel chrome — the cards
 * already provide their own borders, and wrapping them in another card
 * creates the nested "table-in-table" look the user objected to. The
 * <h3> "Detailed IP Information" / "IP Information for X.X.X.X" sits
 * above the cards as a quiet section title, not inside any card.
 *
 * reverse-dns also uses `.ip-details` but contains only a flat
 * key/value table and no `.ip-version-details` — the :has() guard
 * keeps its outer card chrome intact. */
.ip-details:has(.ip-version-details),
.tool-results:has(.ip-version-details) {
    background: transparent !important;
    border: none !important;
    border-radius: 0 !important;
    padding: 0 !important;
    overflow: visible !important;
}

@media (max-width: 480px) {
    .ip-address-display {
        gap: var(--sp-2);
        padding: var(--sp-3);
    }
    .ip-value {
        font-size: var(--fs-sm);
        order: 1;
        flex: 1 1 100%;
        min-width: 0;
    }
    .ip-type-badge { order: 2; }
    .copy-ip-btn { order: 3; margin-left: auto; }
}

/* Make horizontal scrollability visually obvious on phones — a soft right-
 * edge fade hints "there's more →". The wrapper itself is the scroll
 * container (overflow-x: auto, set above), so the gradient sits on a
 * pseudo-element pinned to the wrapper. We also expose a thin scrollbar
 * always so users on iOS see it without scrolling first. */
.tool-results .results-table,
.dns-results .results-table,
.ip-details .results-table,
.blacklist-results .results-table,
#results .results-table {
    position: relative;
    scrollbar-width: thin;
    scrollbar-color: var(--border-2) transparent;
}
.tool-results .results-table::-webkit-scrollbar,
.dns-results .results-table::-webkit-scrollbar,
.ip-details .results-table::-webkit-scrollbar,
.blacklist-results .results-table::-webkit-scrollbar,
#results .results-table::-webkit-scrollbar { height: 6px; }
.tool-results .results-table::-webkit-scrollbar-thumb,
.dns-results .results-table::-webkit-scrollbar-thumb,
.ip-details .results-table::-webkit-scrollbar-thumb,
.blacklist-results .results-table::-webkit-scrollbar-thumb,
#results .results-table::-webkit-scrollbar-thumb {
    background: var(--border-2);
    border-radius: 3px;
}

@media (max-width: 640px) {
    /* Tighter cell padding so more content fits before the horizontal
     * scrollbar kicks in. */
    .tool-results th,
    .dns-results th,
    .ip-details th,
    .blacklist-results th,
    .results-table th { padding: var(--sp-2) var(--sp-3); font-size: var(--fs-3xs); min-width: 0; }
    .tool-results td,
    .dns-results td,
    .ip-details td,
    .blacklist-results td,
    .results-table td { padding: var(--sp-2) var(--sp-3); font-size: var(--fs-sm); }

    /* Force the inner table to its natural width so horizontal scrolling
     * actually works on narrow viewports — `min-width: 100%` was making
     * the table compress instead of scroll on phones. */
    .tool-results table,
    .dns-results table,
    .ip-details table,
    .blacklist-results table,
    #results table,
    .results-table > table { min-width: max-content; }

    /* The first cell carries `white-space: nowrap` for record names — let
     * it wrap on phones if the value is genuinely long, otherwise the row
     * height balloons. */
    .tool-results td:first-child,
    .dns-results td:first-child,
    .ip-details td:first-child,
    .blacklist-results td:first-child,
    #results td:first-child,
    .results-table td:first-child {
        white-space: normal;
        overflow-wrap: anywhere;
        word-break: break-word;
    }
}

/* Below 480px (small phones) — convert each row to a stacked card with
 * the column header inline above each value. We re-use the existing
 * <th> via a sibling-counter ::before trick: each <td> picks up its
 * label from the matching <th>. This is implemented per-table type
 * since the JS-rendered tables don't carry data-label attributes.
 *
 * Affected tables: dns-results, ip-details, blacklist-results, generic
 * .results-table. The pattern works the same for all of them. */
@media (max-width: 480px) {
    .tool-results .results-table,
    .dns-results .results-table,
    .ip-details .results-table,
    .blacklist-results .results-table,
    #results .results-table { overflow-x: visible; }

    .tool-results table,
    .dns-results table,
    .ip-details table,
    .blacklist-results table,
    #results table,
    .results-table > table {
        display: block;
        min-width: 0;
        width: 100%;
    }
    .tool-results thead,
    .dns-results thead,
    .ip-details thead,
    .blacklist-results thead,
    #results thead,
    .results-table > table thead { display: none; }

    .tool-results tbody,
    .dns-results tbody,
    .ip-details tbody,
    .blacklist-results tbody,
    #results tbody,
    .results-table > table tbody { display: block; }

    .tool-results tr,
    .dns-results tr,
    .ip-details tr,
    .blacklist-results tr,
    #results tr,
    .results-table > table tr {
        display: block;
        background: var(--surface);
        border: 1px solid var(--border);
        border-radius: var(--radius);
        margin: 0 0 var(--sp-3);
        padding: var(--sp-3);
    }

    .tool-results td,
    .dns-results td,
    .ip-details td,
    .blacklist-results td,
    #results td,
    .results-table td {
        display: flex;
        align-items: baseline;
        justify-content: space-between;
        gap: var(--sp-3);
        padding: 4px 0;
        border-bottom: none !important;
        text-align: right;
    }
    /* The first cell of each row becomes the card title */
    .tool-results td:first-child,
    .dns-results td:first-child,
    .ip-details td:first-child,
    .blacklist-results td:first-child,
    #results td:first-child,
    .results-table td:first-child {
        display: block;
        text-align: left;
        font-weight: 600;
        color: var(--text);
        font-family: var(--font-mono);
        font-size: var(--fs-sm);
        margin-bottom: var(--sp-2);
        padding-bottom: var(--sp-2);
        border-bottom: 1px solid var(--divider) !important;
        white-space: normal;
        overflow-wrap: anywhere;
    }
    /* Key/value tables (reverse-dns, whois, ssl, http-headers, mx auth posture)
     * use <th> in the first cell, <td> in the second. In card mode the <th>
     * becomes the label above the value. Override the eyebrow-style thead
     * presentation that <th> inherits from the desktop rules. */
    .tool-results th,
    .dns-results th,
    .ip-details th,
    .blacklist-results th,
    #results th,
    .results-table th {
        display: block;
        text-align: left;
        background: transparent !important;
        color: var(--text-3) !important;
        font-family: var(--font-sans);
        font-weight: 500 !important;
        font-size: var(--fs-xs) !important;
        text-transform: uppercase;
        letter-spacing: 0.05em;
        padding: 0 0 4px 0 !important;
        border-bottom: none !important;
        white-space: normal;
        min-width: 0;
    }
    /* And in key/value tables the corresponding <td> is the value below the label —
     * not a flex row (no second column to separate from). Reset to block. */
    .tool-results tr > th + td,
    .dns-results tr > th + td,
    .ip-details tr > th + td,
    .blacklist-results tr > th + td,
    #results tr > th + td,
    .results-table tr > th + td {
        display: block;
        text-align: left;
        padding-bottom: var(--sp-2);
        border-bottom: 1px solid var(--divider) !important;
        margin-bottom: var(--sp-2);
        font-family: var(--font-mono);
        color: var(--text);
        word-break: break-all;
        overflow-wrap: anywhere;
    }
    /* Last row in card has no bottom rule */
    .tool-results tr > th + td:last-child,
    .dns-results tr > th + td:last-child,
    .ip-details tr > th + td:last-child,
    .blacklist-results tr > th + td:last-child,
    #results tr > th + td:last-child,
    .results-table tr > th + td:last-child {
        margin-bottom: 0;
        padding-bottom: 0;
        border-bottom: none !important;
    }
    /* Use the data-label attribute as a column header inline; if the JS
     * has set one, render it; otherwise keep the cell's existing layout. */
    .tool-results td[data-label]::before,
    .dns-results td[data-label]::before,
    .ip-details td[data-label]::before,
    .blacklist-results td[data-label]::before,
    #results td[data-label]::before,
    .results-table td[data-label]::before {
        content: attr(data-label);
        color: var(--text-3);
        font-family: var(--font-sans);
        font-size: var(--fs-xs);
        text-transform: uppercase;
        letter-spacing: 0.05em;
        font-weight: 500;
        flex-shrink: 0;
        text-align: left;
    }
    /* Hover state inside cards — colour the whole card, not just the cell */
    .tool-results tr:hover td,
    .dns-results tr:hover td,
    .ip-details tr:hover td,
    .blacklist-results tr:hover td,
    #results tr:hover td,
    .results-table tr:hover td { background: transparent; }
    .tool-results tr:hover,
    .dns-results tr:hover,
    .ip-details tr:hover,
    .blacklist-results tr:hover,
    #results tr:hover,
    .results-table tr:hover { background: var(--surface-2); }

    /* OPT-OUT of card mode for multi-column data tables (3+ thead columns).
     *
     * Two markup patterns are in play across the toolset:
     *   A) <div class="results-table"><table>...</table></div>  — dns-lookup,
     *      dns-checker, ip-blacklist-check, ip-lookup, what-is-my-ip-address,
     *      speed-test
     *   B) <table class="results-table">...</table>             — reverse-dns,
     *      whois-lookup, mx-lookup (both MX-records and auth-posture tables),
     *      ssl-checker, http-headers
     *
     * For dns-checker desktop / dns-lookup / mx-lookup MX-records / ip-blacklist
     * — these have 3+ data columns that don't fit the card pattern. They stay
     * as horizontal-scroll tables on mobile, where the user can swipe to see
     * the rest of the columns. :has() is supported in all modern browsers
     * (Chrome 105+, Safari 15.4+, Firefox 121+). */

    /* Pattern A: wrapper div */
    .results-table:has(> table > thead > tr > th:nth-child(3)) { overflow-x: auto !important; }

    /* Pattern A + B: any 3+ col table that has a thead. */
    .results-table > table:has(thead > tr > th:nth-child(3)),
    table.results-table:has(thead > tr > th:nth-child(3)) {
        display: table !important;
        min-width: max-content !important;
        width: auto !important;
    }
    .results-table > table:has(thead > tr > th:nth-child(3)) thead,
    table.results-table:has(thead > tr > th:nth-child(3)) thead { display: table-header-group !important; }
    .results-table > table:has(thead > tr > th:nth-child(3)) tbody,
    table.results-table:has(thead > tr > th:nth-child(3)) tbody { display: table-row-group !important; }
    .results-table > table:has(thead > tr > th:nth-child(3)) tr,
    table.results-table:has(thead > tr > th:nth-child(3)) tr {
        display: table-row !important;
        background: transparent !important;
        border: none !important;
        border-radius: 0 !important;
        margin: 0 !important;
        padding: 0 !important;
    }
    .results-table > table:has(thead > tr > th:nth-child(3)) td,
    .results-table > table:has(thead > tr > th:nth-child(3)) th,
    table.results-table:has(thead > tr > th:nth-child(3)) td,
    table.results-table:has(thead > tr > th:nth-child(3)) th {
        display: table-cell !important;
        text-align: left !important;
        padding: var(--sp-2) var(--sp-3) !important;
        margin: 0 !important;
        border-bottom: 1px solid var(--divider) !important;
        white-space: nowrap;
    }
    .results-table > table:has(thead > tr > th:nth-child(3)) td:first-child,
    table.results-table:has(thead > tr > th:nth-child(3)) td:first-child {
        font-weight: normal !important;
        color: var(--text) !important;
        font-family: var(--font-mono) !important;
        margin-bottom: 0 !important;
        padding-bottom: var(--sp-2) !important;
    }
    .results-table > table:has(thead > tr > th:nth-child(3)) thead th,
    table.results-table:has(thead > tr > th:nth-child(3)) thead th {
        background: var(--surface-2) !important;
        color: var(--text-2) !important;
        font-weight: 500 !important;
        text-transform: uppercase !important;
        letter-spacing: 0.05em !important;
        font-size: var(--fs-3xs) !important;
        font-family: var(--font-sans) !important;
    }
}

/* ---------------------------------------------------------------------
 * 11. SPEED-TEST GAUGES
 * ------------------------------------------------------------------- */

.speed-test-container { padding: 0; background: transparent; }
.speed-clocks {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--sp-4);
    margin: 0 0 var(--sp-5);
}
.speed-clock {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    padding: var(--sp-5);
    box-shadow: var(--shadow-sm);
    text-align: center;
}
.speed-gauge { width: 100%; max-width: 200px; height: auto; margin: 0 auto; display: block; }
.speed-gauge-track { stroke: var(--border-2); }
.speed-value { fill: var(--text); font-family: var(--font-mono); font-size: 30px; font-weight: 700; }
.speed-unit  { fill: var(--text-2); font-family: var(--font-mono); font-size: 12px; }
.speed-label { fill: var(--text-3); font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.1em; }
.progress-circle { transition: stroke-dashoffset 0.3s ease; }

.test-control {
    display: flex;
    justify-content: center;
    margin: 0 0 var(--sp-5);
}
.start-test-btn,
#startTestBtn {
    height: 48px;
    padding: 0 var(--sp-6);
    background: var(--accent) !important;
    color: #fff !important;
    border: 1px solid var(--accent) !important;
    border-radius: var(--radius) !important;
    font-family: var(--font-sans) !important;
    font-size: var(--fs-md) !important;
    font-weight: 600 !important;
    letter-spacing: 0.02em !important;
    cursor: pointer;
    box-shadow: var(--shadow-sm) !important;
    min-width: 200px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-2);
    transition: background-color 120ms ease, transform 120ms ease;
}
.start-test-btn:hover:not(:disabled),
#startTestBtn:hover:not(:disabled) {
    background: var(--accent-strong) !important;
    transform: translateY(-1px);
}
.start-test-btn:disabled,
#startTestBtn:disabled,
.start-test-btn.loading,
#startTestBtn.loading {
    background: linear-gradient(100deg, var(--accent) 0%, var(--accent) 25%, var(--accent-strong) 50%, var(--accent) 75%, var(--accent) 100%) !important;
    background-size: 200% 100% !important;
    animation: btn-shimmer 1.6s linear infinite !important;
    cursor: progress !important;
    transform: none !important;
    opacity: 1 !important;
    color: #fff !important;
}

.progress-container {
    background: var(--surface) !important;
    border: 1px solid var(--border) !important;
    border-radius: var(--radius-lg) !important;
    padding: var(--sp-4) !important;
    margin: 0 0 var(--sp-5);
}
.progress-bar {
    background: var(--surface-2) !important;
    height: 6px !important;
    border-radius: 999px !important;
    overflow: hidden !important;
    margin: 0 0 var(--sp-3);
}
.progress-fill {
    background: linear-gradient(90deg, var(--accent), var(--accent-strong)) !important;
    height: 100% !important;
    border-radius: 999px !important;
    transition: width 0.3s ease !important;
    box-shadow: 0 0 8px var(--accent-ring);
}
.progress-text {
    color: var(--text-2) !important;
    font-family: var(--font-mono) !important;
    font-size: var(--fs-sm) !important;
    text-align: center !important;
    margin: 0 !important;
}

.additional-metrics {
    margin: var(--sp-5) 0 0;
    background: var(--surface);
    border: 1px solid var(--border-2);
    border-radius: var(--radius-lg);
    overflow: hidden;
}

@media (max-width: 540px) {
    .speed-clocks { grid-template-columns: 1fr; }
}

/* ---------------------------------------------------------------------
 * 12. SIDEBAR (tool pages, blog)
 * ------------------------------------------------------------------- */

/* The audit CTA ships hidden until there is a domain to offer it for, and
   relies on the UA's [hidden] rule. Pinned here so a later `display` on
   .sidebar-widget cannot silently un-hide it. */
.sidebar-widget[hidden] { display: none; }

.sidebar-widget {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    padding: var(--sp-4);
    margin: 0 0 var(--sp-4);
}
.sidebar-widget-title,
.sidebar-widget h3 {
    /* VOICE: txt-eyebrow */
    font-family: var(--font-mono);
    font-size: var(--fs-3xs);
    font-weight: 600;
    letter-spacing: 0.10em;
    text-transform: uppercase;
    color: var(--text-3);
    line-height: 1;
    margin: 0 0 var(--sp-3);
}
.sidebar-widget .tool-list {
    list-style: none;
    padding: 0;
    margin: 0;
}
.sidebar-widget .tool-list li {
    padding: var(--sp-2) 0;
    border-bottom: 1px solid var(--divider);
}
.sidebar-widget .tool-list li:last-child { border-bottom: none; }
.sidebar-widget .tool-list a {
    display: block;
    color: var(--text);
    font-size: var(--fs-sm);
    font-weight: 500;
    line-height: 1.4;
    text-decoration: none;
}
.sidebar-widget .tool-list a:hover { color: var(--accent); }
.sidebar-widget .tool-list-desc {
    /* VOICE: txt-meta */
    display: block;
    font-family: var(--font-mono);
    font-size: var(--fs-xs);
    font-weight: 400;
    line-height: 1.5;
    color: var(--text-3);
    margin-top: 2px;
}
.recent-post {
    border-bottom: 1px solid var(--divider);
    padding: 0 0 var(--sp-3);
    margin: 0 0 var(--sp-3);
}
.recent-post:last-child { border: none; padding: 0; margin: 0; }
.recent-post h4 { margin: 0 0 4px; font-size: var(--fs-sm); line-height: 1.4; font-weight: 600; }
.recent-post h4 a { color: var(--text); text-decoration: none; }
.recent-post h4 a:hover { color: var(--accent); }
.recent-post .post-date {
    /* VOICE: txt-meta */
    font-family: var(--font-mono);
    font-size: var(--fs-xs);
    font-weight: 400;
    line-height: 1.5;
    color: var(--text-3);
    margin: 0;
}

/* ---------------------------------------------------------------------
 * 13. TOOL INFO BODY (the long-form copy under each tool)
 * ------------------------------------------------------------------- */

.tool-info {
    margin-top: var(--sp-6);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    padding: var(--sp-6);
}
.tool-info h2 {
    font-size: var(--fs-lg);
    color: var(--text);
    margin: var(--sp-5) 0 var(--sp-3);
    letter-spacing: -0.01em;
}
.tool-info h2:first-child { margin-top: 0; }
.tool-info p,
.tool-info li {
    color: var(--text-2);
    font-size: var(--fs-md);
    line-height: 1.7;
}
.tool-info p { margin: 0 0 var(--sp-4); }
.tool-info ul { padding-left: 20px; }
.tool-info code {
    font-size: 0.9em;
    padding: 1px 6px;
    background: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    color: var(--text-mono);
}
.tool-info a {
    color: var(--accent-text);
    text-decoration: none;
    border-bottom: 1px solid var(--accent-ring);
}
.tool-info a:hover { border-bottom-color: var(--accent); color: var(--accent); }

/* ---------------------------------------------------------------------
 * 14. FAQ accordion
 * ------------------------------------------------------------------- */

.tool-faq {
    background: transparent;
    border-top: 1px solid var(--divider);
    padding: var(--sp-12) var(--sp-5);
}
.tool-faq-container {
    max-width: 760px;
    margin: 0 auto;
    padding: 0;
}
/* The "// frequently asked" mono eyebrow that used to sit above the H2
 * has been removed — the H2 itself ("Frequently asked questions") is the
 * section heading, and the eyebrow on top was a leftover terminal-vibe
 * touch from the cyan-era design that read as duplicate text. */
.tool-faq-heading {
    font-size: var(--fs-2xl);
    color: var(--text);
    margin: 0 0 var(--sp-2);
    letter-spacing: -0.015em;
}
.tool-faq-list {
    display: grid;
    gap: var(--sp-2);
    margin-top: var(--sp-5);
}
.tool-faq-item {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    overflow: hidden;
    transition: border-color 120ms ease, background-color 120ms ease;
}
.tool-faq-item:hover { border-color: var(--border-2); }
.tool-faq-item[open] {
    border-color: var(--accent-ring);
    background: var(--surface);
    box-shadow: var(--shadow-sm);
}
.tool-faq-question {
    padding: var(--sp-4);
    font-size: var(--fs-md);
    font-weight: 600;
    cursor: pointer;
    list-style: none;
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--sp-3);
    line-height: 1.45;
    color: var(--text);
}
.tool-faq-question::-webkit-details-marker { display: none; }
.tool-faq-question::after {
    content: "";
    width: 16px; height: 16px;
    flex-shrink: 0;
    margin-top: 2px;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235e6ad2' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");
    background-repeat: no-repeat;
    background-position: center;
    transition: transform 200ms ease;
}
.tool-faq-item[open] .tool-faq-question::after { transform: rotate(180deg); }
.tool-faq-answer {
    padding: 0 var(--sp-4) var(--sp-4);
    color: var(--text-2);
    line-height: 1.7;
    font-size: var(--fs-sm);
}
.tool-faq-answer p { margin: 0; }

@media (max-width: 540px) {
    .tool-faq { padding: var(--sp-8) var(--sp-4); }
    .tool-faq-question { padding: var(--sp-3); font-size: var(--fs-sm); }
    .tool-faq-answer { padding: 0 var(--sp-3) var(--sp-3); }
}

/* ---------------------------------------------------------------------
 * 15. BLOG — index, post, taxonomy
 * ------------------------------------------------------------------- */

.blog-page,
.blog-post-page {
    /* See .tool-page note — outer band is vertical-only; the inner
       wrapper takes horizontal padding so the left edge matches header
       and footer. */
    background: var(--bg);
    padding: var(--sp-5) 0 var(--sp-16);
}
/* Grid layout for .blog-page-inner and .blog-post-inner lives in the
   canonical "main column + right sidebar" rule in section 8 — search for
   "Canonical \"main column + right sidebar\"" to find it. */

/* Blog hero — uses .tool-page-hero pattern with extra meta row */
.blog-post-hero,
.blog-tax-hero { padding-bottom: var(--sp-3); }

.post-meta-row {
    /* VOICE: txt-meta — uniform text-3 across every child, matching the
       single-tone meta voice used by breadcrumbs, footer-bottom,
       recent-post date, sidebar tool-list-desc, and search-popup desc.
       Previously the items used --text-2 (darker) and separators used
       text-3 at 0.65 opacity, which produced a tri-tonal line that was
       the only place on the site doing that — visually inconsistent. */
    display: inline-flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    font-family: var(--font-mono);
    font-size: var(--fs-xs);
    font-weight: 400;
    line-height: 1.5;
    color: var(--text-3);
    margin: 0;
    padding: 0;
}
.post-meta-item,
.post-meta-sep  { color: inherit; }

.blog-post .post-content,
.post-content {
    /* No internal `max-width` cap. Body prose fills the article column
       width naturally (~788px on the canonical 1180-container grid,
       which is ~56ch at the 14px body font — comfortably inside the
       50–75ch readable range). Capping at 720px previously left a dead
       strip on the right of the body while the prev/next nav and
       related-posts (siblings of .post-content) filled the full column —
       the same column read as two different widths. Removed for visual
       unity with the rest of the article column. */
    background: transparent;
    border: none;
    box-shadow: none;
    padding: 0;
    margin: var(--sp-5) 0 0;
    color: var(--text-2);
    font-size: var(--fs-md);
    line-height: 1.78;
}
.post-featured {
    margin: 0 0 var(--sp-5);
    border-radius: var(--radius-lg);
    overflow: hidden;
    border: 1px solid var(--border);
}
.post-featured img,
.post-featured picture { display: block; width: 100%; height: auto; }

/* Article-body prose */
.post-content p { margin: 0 0 var(--sp-4); color: var(--text-2); }
.post-content h2 {
    font-size: var(--fs-xl);
    margin: var(--sp-8) 0 var(--sp-3);
    color: var(--text);
    letter-spacing: -0.015em;
}
.post-content h3 {
    font-size: var(--fs-lg);
    margin: var(--sp-6) 0 var(--sp-3);
    color: var(--text);
}
.post-content a {
    color: var(--accent-text);
    text-decoration: none;
    border-bottom: 1px solid var(--accent-ring);
}
.post-content a:hover { border-bottom-color: var(--accent); color: var(--accent); }
.post-content code {
    font-size: 0.9em;
    padding: 1px 6px;
    background: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    color: var(--text-mono);
}
.post-content ul, .post-content ol { padding-left: 22px; margin: 0 0 var(--sp-4); }
.post-content li { margin-bottom: 6px; line-height: 1.7; color: var(--text-2); }
.post-content strong { color: var(--text); font-weight: 600; }
.post-content blockquote {
    border-left: 3px solid var(--accent);
    padding: 4px 0 4px var(--sp-4);
    margin: var(--sp-5) 0;
    color: var(--text);
    background: var(--accent-soft);
    border-radius: 0 var(--radius) var(--radius) 0;
}
.post-content blockquote p:last-child { margin: 0; }

/* TOC */
.post-toc {
    /* No internal max-width — fills the article column to match the
       prose body, prev/next nav, and related-posts beneath it. */
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    padding: var(--sp-4);
    margin: var(--sp-5) 0;
}
.post-toc-heading {
    font-size: var(--fs-xs);
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--text-3);
    margin: 0 0 var(--sp-2);
    font-weight: 600;
    font-family: var(--font-mono);
}
.post-toc-list { list-style: none; padding: 0; margin: 0; }
.post-toc-item {
    padding: 4px 0;
    border-bottom: 1px solid var(--divider);
}
.post-toc-item:last-child { border: none; }
.post-toc-item a {
    color: var(--text-2);
    text-decoration: none;
    font-size: var(--fs-sm);
    line-height: 1.45;
    border: none;
}
.post-toc-item a:hover { color: var(--accent); }
.post-toc-l3 a { padding-left: var(--sp-4); font-size: var(--fs-sm); color: var(--text-3); }

/* Post taxonomy footer */
.post-taxonomy {
    margin: var(--sp-8) 0;
    padding: var(--sp-4) 0;
    border-top: 1px solid var(--divider);
    border-bottom: 1px solid var(--divider);
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
}
.post-taxonomy-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sp-2);
}
.post-taxonomy-label {
    font-size: var(--fs-xs);
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--text-3);
    font-family: var(--font-mono);
    font-weight: 600;
    margin-right: 4px;
}
.post-chip {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 4px 10px;
    border-radius: 999px;
    font-size: var(--fs-xs);
    font-family: var(--font-mono);
    background: var(--surface);
    border: 1px solid var(--border-2);
    color: var(--text-2);
    text-decoration: none;
    transition: color 120ms ease, border-color 120ms ease;
}
.post-chip:hover { color: var(--accent); border-color: var(--accent-ring); }

/* Prev/next */
.post-prevnext {
    margin: var(--sp-8) 0;
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--sp-3);
}
.post-prevnext-link {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: var(--sp-4);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    text-decoration: none;
    color: inherit;
    transition: border-color 160ms ease, transform 160ms ease;
}
.post-prevnext-link:hover { border-color: var(--border-2); transform: translateY(-1px); }
.post-prevnext-next { text-align: right; align-items: flex-end; }
.post-prevnext-label {
    font-size: var(--fs-xs);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-3);
    font-family: var(--font-mono);
}
.post-prevnext-title {
    font-size: var(--fs-sm);
    color: var(--text);
    font-weight: 600;
    line-height: 1.35;
}
@media (max-width: 640px) {
    .post-prevnext { grid-template-columns: 1fr; }
    .post-prevnext-next { text-align: left; align-items: flex-start; }
}

/* Related articles */
.related-posts {
    margin: var(--sp-10) 0 0;
    padding: var(--sp-5) 0 0;
    border-top: 1px solid var(--divider);
}
.related-posts-heading {
    font-size: var(--fs-lg);
    margin: 0 0 var(--sp-4);
    color: var(--text);
    letter-spacing: -0.015em;
}
.related-posts-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: var(--sp-3);
}

/* Tag cloud */
.tag-cloud {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-1);
}
.tag-chip {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 4px 8px;
    background: var(--surface);
    border: 1px solid var(--border-2);
    border-radius: 999px;
    font-size: var(--fs-xs);
    font-family: var(--font-mono);
    color: var(--text-2);
    text-decoration: none;
    transition: color 120ms ease, border-color 120ms ease;
}
.tag-chip:hover, .tag-chip.is-active {
    color: var(--accent);
    border-color: var(--accent-ring);
    background: var(--accent-soft);
}
.tag-count {
    background: var(--surface-2);
    color: var(--text-3);
    padding: 1px 6px;
    border-radius: 999px;
    font-size: var(--fs-2xs);
}

/* Empty blog state */
.blog-empty {
    padding: var(--sp-10) var(--sp-5);
    text-align: center;
    background: var(--surface);
    border: 1px dashed var(--border-2);
    border-radius: var(--radius-lg);
}
.blog-empty h3 { color: var(--text); margin: 0 0 var(--sp-2); font-size: var(--fs-lg); }
.blog-empty p { color: var(--text-2); margin: 0; }

/* ---------------------------------------------------------------------
 * 16. STATIC PAGES — about, privacy, terms, contact
 * ------------------------------------------------------------------- */

.static-page {
    /* Same pattern as .tool-page / .blog-post-page: vertical padding only,
       horizontal padding lives on the inner wrapper so the content left
       edge matches the header + footer regardless of which max-width the
       inner takes (narrow 760 for static prose, wide 1180 with sidebar). */
    background: var(--bg);
    padding: var(--sp-5) 0 var(--sp-16);
    min-height: 50vh;
}
.static-page-inner {
    max-width: 760px;
    margin: 0 auto;
    padding: 0 var(--sp-5);
}
/* The .has-sidebar variant of .static-page-inner uses the canonical
   "main column + right sidebar" rule in section 8 — search for
   "Canonical \"main column + right sidebar\"" to find it. Mobile
   breakpoint is unified at 960px (was 880px here previously, which
   collapsed static pages to one column earlier than blog/tool pages). */

.static-article-head {
    margin-bottom: var(--sp-6);
    padding-bottom: var(--sp-4);
    border-bottom: 1px solid var(--divider);
}
.static-article-head h1 {
    font-size: var(--fs-hero);
    margin: 0 0 var(--sp-2);
    color: var(--text);
    line-height: 1.15;
    letter-spacing: -0.025em;
}
.static-article-meta {
    font-family: var(--font-mono);
    font-size: var(--fs-xs);
    color: var(--text-3);
    margin: 0;
}

.static-featured img {
    width: 100%;
    border-radius: var(--radius-lg);
    margin-bottom: var(--sp-5);
}

.it-prose,
.static-article-body {
    color: var(--text-2);
    font-size: var(--fs-md);
    line-height: 1.78;
}
.it-prose .lead, .it-prose p.lead {
    font-size: var(--fs-lg);
    color: var(--text);
    margin: 0 0 var(--sp-5);
    line-height: 1.65;
    font-weight: 500;
}
.it-prose p { margin: 0 0 var(--sp-4); color: var(--text-2); }
.it-prose h2 {
    font-size: var(--fs-xl);
    margin: var(--sp-8) 0 var(--sp-3);
    color: var(--text);
    line-height: 1.3;
    letter-spacing: -0.015em;
    font-weight: 700;
}
.it-prose h3 {
    font-size: var(--fs-lg);
    margin: var(--sp-6) 0 var(--sp-2);
    color: var(--text);
    line-height: 1.35;
    font-weight: 600;
}
.it-prose h2:first-child, .it-prose h3:first-child { margin-top: 0; }
.it-prose ul, .it-prose ol { margin: 0 0 var(--sp-4); padding-left: 22px; }
.it-prose li { margin-bottom: 6px; color: var(--text-2); line-height: 1.7; }
.it-prose li::marker { color: var(--text-3); }
.it-prose strong { color: var(--text); font-weight: 600; }
.it-prose a {
    color: var(--accent-text);
    text-decoration: none;
    border-bottom: 1px solid var(--accent-ring);
}
.it-prose a:hover { border-bottom-color: var(--accent); color: var(--accent); }
.it-prose code {
    font-size: 0.9em;
    padding: 1px 6px;
    background: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    color: var(--text-mono);
}
.it-prose pre {
    background: var(--surface-2);
    border: 1px solid var(--border-2);
    border-radius: var(--radius);
    padding: var(--sp-4);
    overflow-x: auto;
    margin: var(--sp-5) 0;
    font-family: var(--font-mono);
    font-size: var(--fs-sm);
    line-height: 1.65;
    color: var(--text-mono);
}
.it-prose pre code { background: transparent; border: none; padding: 0; color: inherit; }
.it-prose blockquote {
    border-left: 3px solid var(--accent);
    padding: 4px 0 4px var(--sp-4);
    margin: var(--sp-5) 0;
    color: var(--text);
    background: var(--accent-soft);
    border-radius: 0 var(--radius) var(--radius) 0;
}
.it-prose blockquote p:last-child { margin: 0; }
.it-prose hr { border: none; border-top: 1px solid var(--divider); margin: var(--sp-8) 0; }
.it-prose table {
    width: 100%;
    border-collapse: collapse;
    margin: var(--sp-5) 0;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    overflow: hidden;
}
.it-prose table th, .it-prose table td {
    padding: var(--sp-3) var(--sp-4);
    border-bottom: 1px solid var(--divider);
    text-align: left;
    font-size: var(--fs-sm);
}
.it-prose table th {
    background: var(--surface-2);
    color: var(--text-2);
    font-size: var(--fs-xs);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-weight: 600;
}

/* ---------------------------------------------------------------------
 * 17. NEWSLETTER SIGNUP (footer partial)
 * ------------------------------------------------------------------- */

.newsletter-signup {
    background: linear-gradient(135deg, var(--surface) 0%, var(--surface-2) 100%);
    border-top: 1px solid var(--border);
    border-bottom: 1px solid var(--border);
    padding: var(--sp-12) var(--sp-5);
    margin: 0;
}
.newsletter-signup-inner {
    max-width: var(--site-max);
    margin: 0 auto;
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--sp-8);
    align-items: center;
}
.newsletter-signup h2 {
    color: var(--text);
    font-size: var(--fs-xl);
    margin: 0 0 var(--sp-2);
    letter-spacing: -0.015em;
}
.newsletter-signup p { color: var(--text-2); margin: 0; line-height: 1.55; }
.newsletter-form { display: flex; gap: var(--sp-2); flex-wrap: wrap; }
.newsletter-form input[type="email"] {
    flex: 1 1 240px;
    height: 42px;
    padding: 0 var(--sp-4);
    background: var(--surface);
    border: 1px solid var(--border-2);
    border-radius: var(--radius);
    color: var(--text);
    font-family: var(--font-mono);
    font-size: var(--fs-md);
    min-width: 0;
}
.newsletter-form input[type="email"]:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-ring);
}
.newsletter-form button,
.newsletter-form .btn {
    height: 42px;
    padding: 0 var(--sp-5);
    background: var(--accent);
    color: #fff;
    border: 1px solid var(--accent);
    border-radius: var(--radius);
    font-weight: 600;
    cursor: pointer;
}
.newsletter-form button:hover,
.newsletter-form .btn:hover { background: var(--accent-strong); border-color: var(--accent-strong); }

@media (max-width: 768px) {
    .newsletter-signup-inner { grid-template-columns: 1fr; gap: var(--sp-5); }
}

/* ---------------------------------------------------------------------
 * 18. FOOTER
 * ------------------------------------------------------------------- */

.footer {
    background: var(--bg);
    border-top: 1px solid var(--border);
    color: var(--text-2);
    margin-top: 0;
}
.footer .container { padding: var(--sp-10) var(--sp-5); }
.footer-content {
    display: grid;
    grid-template-columns: minmax(0, 1.4fr) repeat(3, minmax(0, 1fr));
    gap: var(--sp-8);
}
.footer-about h3,
.footer-column h3 {
    /* VOICE: txt-eyebrow */
    font-family: var(--font-mono);
    font-size: var(--fs-3xs);
    font-weight: 600;
    letter-spacing: 0.10em;
    text-transform: uppercase;
    color: var(--text-3);
    line-height: 1;
    margin: 0 0 var(--sp-3);
}
.footer-about .footer-description p {
    color: var(--text-2);
    font-size: var(--fs-sm);
    line-height: 1.6;
    margin: 0 0 var(--sp-3);
    max-width: 360px;
}
.footer-links { display: flex; flex-direction: column; gap: 6px; }
.footer-links a {
    color: var(--text-2);
    text-decoration: none;
    font-size: var(--fs-sm);
    transition: color 120ms ease;
}
.footer-links a:hover { color: var(--accent); }

.footer-bottom {
    margin-top: var(--sp-8);
    padding-top: var(--sp-5);
    border-top: 1px solid var(--divider);
}
.footer-bottom-content {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--sp-2);
}
.footer-bottom-content p {
    /* VOICE: txt-meta */
    margin: 0;
    font-family: var(--font-mono);
    font-size: var(--fs-xs);
    font-weight: 400;
    line-height: 1.5;
    color: var(--text-3);
}
.footer-bottom-content kbd.kbd {
    /* Scoped override for the "Press ⌘K anywhere" chip in the footer
       bottom strip. The default kbd.kbd is sized for the header cmdk
       hint (20px fixed height, inline-flex) — inside the 12px×1.5
       footer meta line that fixed height makes the chip ~1px taller
       than the surrounding text and the inline-flex breaks baseline
       alignment. Padding-sized + baseline-aligned, the chip sits
       cleanly on the text line while keeping the same border + bg
       affordance for "this is a keyboard shortcut". */
    height: auto;
    padding: 1px 5px;
    line-height: 1;
    vertical-align: baseline;
}

@media (max-width: 880px) {
    .footer-content { grid-template-columns: 1fr 1fr; gap: var(--sp-5); }
    .footer-about { grid-column: 1 / -1; }
}
@media (max-width: 540px) {
    .footer-content { grid-template-columns: 1fr; }
}

/* ---------------------------------------------------------------------
 * 19. CMD+K command palette
 * ------------------------------------------------------------------- */

.cmdk-overlay {
    position: fixed; inset: 0;
    background: rgba(15, 17, 21, 0.45);
    z-index: 200;
    opacity: 0;
    pointer-events: none;
    transition: opacity 140ms ease;
    display: flex;
    justify-content: center;
    align-items: flex-start;
    padding: clamp(2rem, 8vh, 6rem) var(--sp-4) var(--sp-5);
}
html[data-theme="dark"] .cmdk-overlay { background: rgba(0, 0, 0, 0.65); }
.cmdk-overlay.active {
    opacity: 1;
    pointer-events: auto;
}
.cmdk-panel {
    width: 100%;
    max-width: 600px;
    background: var(--surface);
    border: 1px solid var(--border-2);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    overflow: hidden;
    transform: translateY(-6px);
    opacity: 0;
    transition: transform 180ms ease, opacity 180ms ease;
}
.cmdk-overlay.active .cmdk-panel { transform: translateY(0); opacity: 1; }

.cmdk-input-row {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    padding: var(--sp-3);
    border-bottom: 1px solid var(--divider);
}
.cmdk-input-row svg { width: 18px; height: 18px; color: var(--text-3); flex-shrink: 0; }
.cmdk-input {
    flex: 1;
    background: transparent;
    border: none;
    outline: none;
    color: var(--text);
    font-size: var(--fs-md);
    font-family: var(--font-sans);
    height: 32px;
}
.cmdk-input::placeholder { color: var(--text-3); }
.cmdk-close-hint {
    font-family: var(--font-mono);
    font-size: var(--fs-3xs);
    color: var(--text-3);
    border: 1px solid var(--border);
    background: var(--surface-2);
    border-radius: 5px;
    padding: 1px 6px;
    line-height: 1;
}

.cmdk-results {
    max-height: 60vh;
    overflow-y: auto;
    padding: 4px;
}
.cmdk-group {
    /* VOICE: txt-eyebrow */
    padding: var(--sp-2) var(--sp-3) 4px;
    font-family: var(--font-mono);
    font-size: var(--fs-3xs);
    font-weight: 600;
    letter-spacing: 0.10em;
    text-transform: uppercase;
    color: var(--text-3);
    line-height: 1;
}
.cmdk-item {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    padding: var(--sp-2) var(--sp-3);
    border-radius: var(--radius);
    color: var(--text);
    text-decoration: none;
    font-size: var(--fs-sm);
    cursor: pointer;
}
.cmdk-item .ic {
    width: 28px; height: 28px;
    border-radius: var(--radius-sm);
    background: var(--surface-2);
    color: var(--text-2);
    display: inline-flex;
    align-items: center; justify-content: center;
    flex-shrink: 0;
}
.cmdk-item .ic svg { width: 14px; height: 14px; }
.cmdk-item .meta { display: flex; flex-direction: column; flex: 1; min-width: 0; }
.cmdk-item .name { color: var(--text); font-weight: 500; }
.cmdk-item .desc {
    /* VOICE: txt-meta */
    font-family: var(--font-mono);
    font-size: var(--fs-xs);
    font-weight: 400;
    line-height: 1.5;
    color: var(--text-3);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.cmdk-item .arrow { color: var(--text-3); font-size: var(--fs-3xs); font-family: var(--font-mono); }
.cmdk-item:hover, .cmdk-item.is-active {
    background: var(--accent-soft);
}
.cmdk-item:hover .ic, .cmdk-item.is-active .ic {
    background: var(--accent);
    color: #fff;
}
.cmdk-empty {
    padding: var(--sp-6);
    text-align: center;
    color: var(--text-3);
    font-family: var(--font-mono);
    font-size: var(--fs-sm);
}
.cmdk-foot {
    display: flex;
    gap: var(--sp-4);
    flex-wrap: wrap;
    padding: var(--sp-2) var(--sp-3);
    border-top: 1px solid var(--divider);
    color: var(--text-3);
    font-size: var(--fs-3xs);
    font-family: var(--font-mono);
}
.cmdk-foot kbd {
    background: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: 5px;
    padding: 0 5px;
    font-size: var(--fs-2xs);
    color: var(--text-2);
}

/* ---------------------------------------------------------------------
 * 20. TOOL-HERO META CHIPS (live · category · command)
 * ------------------------------------------------------------------- */

.it-tool-meta {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-2);
    margin-top: var(--sp-3);
}
.it-tool-meta .chip {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
    padding: 4px 10px;
    background: var(--surface);
    border: 1px solid var(--border);
    color: var(--text-2);
    border-radius: 999px;
    font-family: var(--font-mono);
    font-size: var(--fs-xs);
    line-height: 1.3;
}
.it-tool-meta .chip.live {
    color: var(--ok);
    border-color: rgba(22, 163, 74, 0.30);
    background: var(--ok-soft);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-weight: 600;
}
.it-tool-meta .chip.live::before {
    content: "";
    width: 6px; height: 6px; border-radius: 50%;
    background: var(--ok);
}
.it-tool-meta .chip.cmd-chip {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 100%;
}
.it-tool-meta .chip.cmd-chip .prompt {
    color: var(--accent-text);
    font-weight: 600;
}

/* ---------------------------------------------------------------------
 * 21. UTILITIES
 * ------------------------------------------------------------------- */

.it-mono { font-family: var(--font-mono); }
.it-text-dim { color: var(--text-2); }
.it-text-mute { color: var(--text-3); }

/* Copy button — small, in-table */
.it-copy-btn {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 6px;
    margin-left: 6px;
    font-size: var(--fs-2xs);
    font-family: var(--font-mono);
    color: var(--text-3);
    background: transparent;
    border: 1px solid var(--border);
    border-radius: 5px;
    cursor: pointer;
    transition: color 120ms ease, border-color 120ms ease;
}
.it-copy-btn:hover { color: var(--accent); border-color: var(--accent-ring); }
.it-copy-btn.copied { color: var(--ok); border-color: rgba(22, 163, 74, 0.35); }

/* ---------------------------------------------------------------------
 * 22. API DOCS PAGE (/api)
 *
 * Lifted from api/index.php's previous inline <style> block. The old
 * block used 20 design tokens with the `--it-*` prefix (vocabulary from
 * the retired redesign.css) — none of which were defined in this file,
 * so every var(--it-…) fell back to unset and the page rendered as
 * bare HTML. All those tokens are rewritten to the current public.css
 * token names here. font-size values are aligned to the unified scale
 * (--fs-*) where applicable. The .api-* selector tree is unique to
 * /api so these rules don't leak into other pages.
 * ------------------------------------------------------------------- */

.api-docs {
    padding: var(--sp-8) var(--sp-5) var(--sp-16);
    background: var(--bg);
    min-height: 60vh;
}
.api-docs-inner {
    max-width: var(--site-max);
    margin: 0 auto;
    display: grid;
    grid-template-columns: 220px minmax(0, 1fr);
    gap: var(--sp-12);
    align-items: flex-start;
}
.api-docs-toc {
    position: sticky;
    top: calc(var(--header-h) + 16px);
    display: flex;
    flex-direction: column;
    gap: var(--sp-1);
    padding: var(--sp-4) var(--sp-3);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
}
.api-docs-toc a {
    color: var(--text-2);
    text-decoration: none;
    font-size: var(--fs-sm);
    padding: 6px var(--sp-2);
    border-radius: 7px;
    transition: color 120ms ease, background-color 120ms ease;
}
.api-docs-toc a:hover {
    color: var(--text);
    background: var(--surface-hover);
}
.api-docs-body { min-width: 0; }

.api-section {
    margin-bottom: var(--sp-12);
    scroll-margin-top: 80px;
}
.api-section h2 {
    font-size: var(--fs-2xl);
    margin: 0 0 var(--sp-3);
    letter-spacing: -0.025em;
    border-bottom: 1px solid var(--divider);
    padding-bottom: var(--sp-2);
}
.api-section h3 {
    font-size: var(--fs-lg);
    margin: var(--sp-6) 0 var(--sp-2);
    color: var(--text);
    font-weight: 600;
}
.api-section p {
    color: var(--text-2);
    line-height: 1.65;
    margin: 0 0 var(--sp-3);
}
.api-section code:not(pre code) {
    font-size: 0.85em;
    padding: 0.1em 0.4em;
    background: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: 5px;
    color: var(--text-mono);
    font-family: var(--font-mono);
    /* An inline endpoint URL has no spaces to break at, so on a 320px
       screen one of them set the page width. Unlike the code blocks there
       is no box here to scroll inside — an inline run has to break. */
    overflow-wrap: anywhere;
}

.api-steps {
    list-style: none;
    padding: 0;
    margin: var(--sp-5) 0 0;
    counter-reset: step;
}
.api-steps li {
    position: relative;
    padding: var(--sp-3) var(--sp-4) var(--sp-3) 52px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    margin-bottom: var(--sp-2);
    counter-increment: step;
    color: var(--text-2);
    line-height: 1.6;
}
.api-steps li::before {
    content: counter(step);
    position: absolute;
    left: var(--sp-3);
    top: var(--sp-3);
    width: 24px;
    height: 24px;
    border-radius: 6px;
    background: var(--accent);
    color: #fff;
    font-family: var(--font-mono);
    font-weight: 600;
    font-size: var(--fs-3xs);
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

/* Code block — terminal-style with a small bar across the top */
.api-codeblock {
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-lg);
    overflow: hidden;
    margin: var(--sp-3) 0 var(--sp-4);
    background: var(--surface-2);
}
.api-codeblock-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 6px var(--sp-3);
    background: var(--surface);
    border-bottom: 1px solid var(--border);
    font-family: var(--font-mono);
    font-size: var(--fs-3xs);
}
.api-codeblock-lang {
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-3);
}
.api-codeblock pre {
    margin: 0;
    padding: var(--sp-3) var(--sp-4);
    overflow-x: auto;
    font-family: var(--font-mono);
    font-size: var(--fs-sm);
    line-height: 1.65;
    color: var(--text-mono);
    background: transparent;
}
.api-codeblock code {
    background: transparent !important;
    border: none !important;
    padding: 0 !important;
    color: inherit !important;
}
/* Syntax-highlight tokens. The three colored ones (key/str/num) use
   theme-aware --code-* tokens defined in the :root + dark blocks at
   the top of this file — light mode gets WCAG-AA-contrast dark colors
   on the off-white surface-2 background; dark mode gets bright pastels
   on the near-black surface-2 background. */
.api-codeblock .t-prompt { color: var(--accent); }
.api-codeblock .t-cmd    { color: var(--text); }
.api-codeblock .t-key    { color: var(--code-key); }
.api-codeblock .t-str    { color: var(--code-str); }
.api-codeblock .t-num    { color: var(--code-num); }
.api-codeblock .t-punc   { color: var(--text-3); }

/* Endpoint reference table */
.api-endpoint-table {
    width: 100%;
    border-collapse: collapse;
    margin: var(--sp-3) 0 var(--sp-4);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    overflow: hidden;
}
.api-endpoint-table th,
.api-endpoint-table td {
    padding: var(--sp-3) var(--sp-4);
    border-bottom: 1px solid var(--divider);
    text-align: left;
    font-size: var(--fs-sm);
    vertical-align: top;
}
.api-endpoint-table th {
    background: var(--surface-2);
    color: var(--text-2);
    font-size: var(--fs-3xs);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-weight: 600;
}
.api-endpoint-table tr:last-child td { border-bottom: none; }
.api-endpoint-table td code { font-family: var(--font-mono); }

/* A table cannot lay out narrower than its widest cell, so `width: 100%`
   does not save it: the endpoint reference wanted 530px and set the whole
   /api page's width on a 390px phone. Wide content scrolls inside its own
   box rather than pushing the document — `display: block` is what turns the
   table into a box that can do that. */
@media (max-width: 640px) {
    .api-endpoint-table {
        display: block;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }
    .api-endpoint-table th,
    .api-endpoint-table td { white-space: nowrap; }
}
.api-q { color: var(--text-3); font-family: var(--font-mono); }

.api-method {
    display: inline-block;
    font-family: var(--font-mono);
    font-size: var(--fs-3xs);
    padding: 3px 7px;
    border-radius: 5px;
    font-weight: 700;
    letter-spacing: 0.04em;
    line-height: 1;
}
.api-method.get {
    background: rgba(52, 211, 153, 0.12);
    color: var(--ok);
    border: 1px solid rgba(52, 211, 153, 0.25);
}

.api-tag {
    display: inline-block;
    font-family: var(--font-mono);
    font-size: var(--fs-2xs);
    padding: 2px 7px;
    border-radius: 999px;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-weight: 600;
    border: 1px solid currentColor;
}
.api-method.post {
    background: rgba(94, 106, 210, 0.12);
    color: var(--accent);
    border: 1px solid rgba(94, 106, 210, 0.25);
}
.api-method.delete {
    background: rgba(248, 113, 113, 0.12);
    color: var(--err);
    border: 1px solid rgba(248, 113, 113, 0.25);
}

.api-tag.stable { color: var(--ok); background: var(--ok-soft); }
.api-tag.soon   { color: var(--text-3); background: var(--surface-2); }
.api-tag.pro    { color: var(--accent); background: var(--surface-2); }

/* Clarifying line under a code sample — smaller and quieter than body copy. */
.api-note {
    font-size: var(--fs-sm);
    color: var(--text-3);
    margin-top: calc(var(--sp-2) * -1);
}

.api-callout {
    padding: var(--sp-3) var(--sp-4);
    border-radius: var(--radius-lg);
    margin: var(--sp-3) 0 var(--sp-5);
    font-size: var(--fs-md);
    border-left: 3px solid var(--accent);
    background: var(--accent-soft);
    color: var(--text);
}
.api-callout-warn {
    border-left-color: var(--warn);
    background: var(--warn-soft);
}

.api-changelog { list-style: none; padding: 0; }
.api-changelog li {
    padding: var(--sp-3) 0;
    border-bottom: 1px solid var(--divider);
    color: var(--text-2);
}
.api-cl-date {
    display: inline-block;
    font-family: var(--font-mono);
    font-size: var(--fs-3xs);
    color: var(--text-3);
    margin-right: var(--sp-3);
    min-width: 70px;
}

@media (max-width: 880px) {
    .api-docs-inner {
        grid-template-columns: 1fr;
        gap: var(--sp-5);
    }
    .api-docs-toc {
        position: static;
        flex-direction: row;
        flex-wrap: wrap;
        gap: 4px;
    }
    .api-docs-toc a {
        padding: 5px 10px;
        font-size: var(--fs-xs);
    }
}

/* ---------------------------------------------------------------------
 * 23. COOKIE CONSENT BANNER
 *
 * Rendered by templates/partials/cookie-consent.php. The banner pins
 * to the bottom of the viewport on first visit, gets dismissed (set
 * cookie cc_accepted=1/0) by main.js, and never shows again. Before
 * this section was added, the .cookie-consent rules from the retired
 * legacy stylesheets weren't ported over — the banner rendered as
 * unstyled inline text at the bottom of every page.
 * ------------------------------------------------------------------- */
.cookie-consent {
    position: fixed;
    left: var(--sp-4);
    right: var(--sp-4);
    bottom: var(--sp-4);
    z-index: 9000;
    background: var(--surface);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    padding: var(--sp-4) var(--sp-5);
    max-width: 880px;
    margin: 0 auto;
    animation: cookie-consent-rise 240ms ease-out;
}
@keyframes cookie-consent-rise {
    from { transform: translateY(12px); opacity: 0; }
    to   { transform: translateY(0);    opacity: 1; }
}
.cookie-consent-content {
    display: flex;
    align-items: center;
    gap: var(--sp-5);
    flex-wrap: wrap;
}
.cookie-consent-copy { flex: 1; min-width: 280px; }
.cookie-consent-copy strong {
    display: block;
    color: var(--text);
    font-size: var(--fs-sm);
    font-weight: 600;
    margin-bottom: 4px;
}
.cookie-consent-copy p {
    color: var(--text-2);
    font-size: var(--fs-sm);
    line-height: 1.5;
    margin: 0;
}
.cookie-consent-copy a {
    color: var(--accent-text);
    text-decoration: underline;
    text-decoration-color: var(--accent-ring);
    text-underline-offset: 2px;
}
.cookie-consent-copy a:hover { color: var(--accent); }
.cookie-consent-actions {
    display: flex;
    gap: var(--sp-2);
    flex-shrink: 0;
}

@media (max-width: 640px) {
    .cookie-consent {
        left: var(--sp-3);
        right: var(--sp-3);
        bottom: var(--sp-3);
        padding: var(--sp-3) var(--sp-4);
    }
    .cookie-consent-content { gap: var(--sp-3); }
    .cookie-consent-actions {
        width: 100%;
        justify-content: flex-end;
    }
}

/* ============================================================
   25. PRICING TABLE (Tier A4 + public /pricing)
   ============================================================ */
/* Pricing cards: each capped at 360px and centered in the row so
   they don't sprawl to half-the-viewport-wide ("fat-ass on a sofa"
   when there are only 2 plans). `auto-fit + minmax` still lets the
   layout scale gracefully when Team / Agency plans get added later
   — it'll just wrap to a second row at the right breakpoint. */
/* Pill-shaped Monthly / Yearly toggle. JS-driven (templates/pricing.php) —
   clicking either button swaps prices in-place without a page reload. The
   active state uses a solid accent fill; inactive is muted. */
.pricing-toggle {
    display: inline-flex;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 999px;
    padding: 4px;
    gap: 4px;
}
.pricing-toggle-btn {
    background: transparent;
    color: var(--text-2);
    border: 0;
    padding: 6px 16px;
    font-size: var(--fs-sm);
    font-weight: 500;
    border-radius: 999px;
    cursor: pointer;
    transition: background-color 120ms ease, color 120ms ease;
    white-space: nowrap;
}
.pricing-toggle-btn:hover { color: var(--text); }
.pricing-toggle-btn.is-active {
    background: var(--accent);
    color: #fff;
    font-weight: 600;
}

.pricing-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 360px));
    justify-content: center;
    gap: var(--sp-5);
    /* margin-top removed — the section's own padding handles spacing
       above the grid. Combined .it-hero(48) + .it-section(48) + the
       old .pricing-grid(24) margin was ~120px of dead space between
       the cycle toggle and the cards. */
}

/* When the pricing-cards section sits directly under the pricing hero
   (it always does), the section's default 48px top padding double-
   stacks with the hero's 48px bottom padding. Halve it. */
.pricing-cards-section {
    padding-top: var(--sp-5);
}
.pricing-card {
    background: var(--surface);
    /* Use 2px border for the base too so featured and non-featured
       cards have identical box dimensions — when the featured card's
       border goes from 1px → 2px the card grows 2px taller/wider and
       knocks the row out of alignment. Same border width on both keeps
       the grid clean. */
    border: 2px solid var(--border);
    border-radius: var(--radius-lg);
    padding: var(--sp-5);
    position: relative;
    display: flex;
    flex-direction: column;
}
.pricing-card-featured {
    border-color: var(--accent);
    /* No box-shadow halo and no scale() — the 2px accent border alone
       reads as the "highlighted" card. */
}
.pricing-card-badge {
    position: absolute;
    top: -12px;
    left: 50%;
    transform: translateX(-50%);
    background: var(--accent);
    color: #fff;
    padding: 4px 12px;
    border-radius: 999px;
    font-size: var(--fs-xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}
.pricing-card-name { font-size: var(--fs-xl); font-weight: 600; margin: 0 0 4px; }
.pricing-card-tagline { color: var(--text-3); font-size: var(--fs-sm); margin: 0 0 var(--sp-4); }
.pricing-card-price {
    display: flex;
    align-items: baseline;
    gap: 6px;
    margin: var(--sp-4) 0;
    border-bottom: 1px solid var(--divider);
    padding-bottom: var(--sp-4);
}
.pricing-card-amount { font-size: 2.25rem; font-weight: 700; color: var(--text); }
.pricing-card-period { color: var(--text-3); font-size: var(--fs-sm); }
.pricing-card-features { list-style: none; padding: 0; margin: 0 0 var(--sp-5); display: grid; gap: var(--sp-2); }
.pricing-card-features li {
    display: flex;
    gap: 8px;
    align-items: flex-start;
    color: var(--text-2);
    font-size: var(--fs-sm);
    line-height: 1.5;
}
.pricing-card-features li svg { color: var(--accent); flex-shrink: 0; margin-top: 2px; }
.pricing-card-cta { margin-top: auto; }
/* Full-width button. The base `.btn` is `display: inline-flex` with
   `align-items: center` + `justify-content: center` — that's what centers
   the content on both axes. The old `.btn-block { display: block }`
   stomped on the inline-flex and killed vertical centering, pushing the
   text to the top of the button box (the "stretched empty box" feel
   visible on the Run-audit / See-pricing sidebar widgets). Keeping the
   flex container and only widening it preserves centering. */
.btn-block { display: flex; width: 100%; }
.pricing-card-processors {
    margin: 8px 0 0;
    color: var(--text-3);
    font-size: var(--fs-xs);
    text-align: center;
}

.pricing-matrix {
    width: 100%;
    border-collapse: collapse;
    margin: var(--sp-4) 0;
}
.pricing-matrix th,
.pricing-matrix td {
    padding: 12px 16px;
    text-align: left;
    border-bottom: 1px solid var(--divider);
}
.pricing-matrix th {
    background: var(--surface-2);
    font-weight: 600;
    font-size: var(--fs-sm);
    color: var(--text-2);
}
.pricing-matrix tr:nth-child(even) td { background: var(--surface-2); }

.pricing-faq details {
    border-bottom: 1px solid var(--divider);
    padding: 16px 0;
}
.pricing-faq summary {
    cursor: pointer;
    font-weight: 600;
    color: var(--text);
}
.pricing-faq p {
    margin: 12px 0 0;
    color: var(--text-2);
    font-size: var(--fs-sm);
    line-height: 1.6;
}

/* ============================================================
   26. AUDIT REPORT (Tier B2)
   ============================================================ */
.audit-page { padding: var(--sp-6) 0; }
.audit-gate-banner {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    margin: var(--sp-4) 0 0;
    padding: var(--sp-3) var(--sp-4);
    background: var(--surface);
    border: 1px solid var(--accent);
    border-radius: var(--radius-lg);
    flex-wrap: wrap;
}
.audit-gate-banner p { margin: 0; flex: 1 1 260px; }
.audit-gate-banner .audit-gate-icon { color: var(--accent); display: inline-flex; }
.audit-gate-banner-muted { border-color: var(--border); }
.audit-gate-banner-muted .audit-gate-icon { color: var(--text-3); }

.audit-availability {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: var(--sp-4);
    margin: 0 0 var(--sp-5);
    padding: var(--sp-4) var(--sp-5);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    flex-wrap: wrap;
}
.audit-avail-headline { font-size: var(--fs-lg); font-weight: 600; margin: 0 0 6px; display: flex; align-items: center; gap: 8px; }
.audit-avail-headline .down-dot { width: 10px; height: 10px; border-radius: 50%; display: inline-block; }
.audit-avail-ms { color: var(--text-3); font-weight: 400; font-size: var(--fs-sm); }
.audit-avail-facts { margin: 0; padding-left: 1.1em; color: var(--text-2); font-size: var(--fs-sm); }
.audit-avail-facts li { margin: 2px 0; }
.audit-avail-monitors { margin: var(--sp-2) 0 0; padding-left: 1.1em; font-size: var(--fs-sm); }
.audit-avail-actions { display: flex; gap: 8px; flex-wrap: wrap; min-width: 0; }
.audit-header {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: var(--sp-4);
    padding: var(--sp-4) 0;
    border-bottom: 1px solid var(--divider);
    flex-wrap: wrap;
}
.audit-header-text h1 { font-size: 1.875rem; margin: 0 0 6px; }
.audit-domain { color: var(--accent); font-family: var(--font-mono); }
.audit-meta { color: var(--text-3); font-size: var(--fs-sm); margin: 0; }
/* `flex-shrink: 0` and `flex-wrap: wrap` on one box contradict each other:
   shrink:0 pins the row at max-content, so it never gets narrow enough for
   the wrap to fire. Three buttons need 455px, so on a 390px phone the row
   — and with it the whole document — was 65px wider than the screen, and
   every block on the page inherited that width and clipped at the right
   edge. Letting it shrink is what lets it wrap. */
.audit-header-actions { display: flex; gap: 8px; flex-wrap: wrap; min-width: 0; }

.audit-summary {
    display: grid;
    grid-template-columns: 200px 1fr;
    gap: var(--sp-6);
    margin: var(--sp-6) 0;
    padding: var(--sp-5);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
}
.audit-score-total {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    border-right: 1px solid var(--divider);
}
.audit-score-num { font-size: 4rem; font-weight: 700; line-height: 1; color: var(--text); }
.audit-score-label { color: var(--text-3); font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.05em; margin-top: 4px; }
.audit-score-bars { display: flex; flex-direction: column; justify-content: center; gap: 10px; }
/* max-content, not a fixed 80px: a grid column sizes to the widest cell across
   all rows, so the label column fits the longest section name automatically.
   The fixed width wrapped "On-page SEO" and "TLS & security" onto two lines,
   and any number picked here goes stale the next time a label changes. */
.audit-bar-row { display: grid; grid-template-columns: max-content 1fr 40px; gap: 12px; align-items: center; }
.audit-bar-label { font-size: var(--fs-sm); color: var(--text-2); white-space: nowrap; }
.audit-bar { height: 8px; background: var(--surface-2); border-radius: 4px; overflow: hidden; }
.audit-bar-fill { height: 100%; border-radius: 4px; transition: width 0.4s ease; }
.audit-bar-fill.audit-bar-ok { background: var(--ok); }
.audit-bar-fill.audit-bar-warn { background: var(--warn); }
.audit-bar-fill.audit-bar-fail { background: var(--err); }
/* Unscored section: the bar is empty, so this only has to not shout. */
.audit-bar-fill.audit-bar-unknown { background: var(--text-3, #8a8f98); }
.audit-bar-value { font-family: var(--font-mono); font-size: var(--fs-sm); color: var(--text); text-align: right; }

.audit-section {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    margin-bottom: var(--sp-4);
    padding: var(--sp-5);
}
.audit-section-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: var(--sp-4); }
.audit-section-head h2 { margin: 0; font-size: 1.25rem; }
.audit-section-summary { color: var(--text-3); font-size: var(--fs-sm); }

.audit-checks { list-style: none; padding: 0; margin: 0; display: grid; gap: 8px; }
.audit-check {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px;
    background: var(--surface-2);
    border-radius: 6px;
    font-size: var(--fs-sm);
}
.audit-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    color: #fff;
    font-weight: 700;
    font-size: 13px;
    flex-shrink: 0;
}
.audit-icon-ok { background: var(--ok); }
.audit-icon-warn { background: var(--warn); }
.audit-icon-fail { background: var(--err); }
/* "We could not check this." Deliberately muted: it is not a pass, not a
   failure, and must not read like either. */
.audit-icon-unknown { background: var(--text-3, #8a8f98); }
.audit-check-label { flex: 1; color: var(--text); }
.audit-check-detail { color: var(--text-3); font-family: var(--font-mono); font-size: var(--fs-xs); overflow-wrap: anywhere; }

.audit-cta-strip {
    background: var(--accent-soft);
    border: 1px solid var(--accent-ring);
    border-radius: var(--radius-lg);
    padding: var(--sp-5);
    margin-top: var(--sp-6);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-4);
    flex-wrap: wrap;
}
.audit-cta-strip p { margin: 0; color: var(--text); }

/* ============================================================
   27. AUDIT FORM (input on /audit landing + home strip)
   ============================================================ */
.audit-form {
    display: flex;
    gap: 8px;
    background: var(--surface);
    border: 2px solid var(--border);
    border-radius: var(--radius-lg);
    padding: 6px;
    transition: border-color 0.15s;
}
.audit-form:focus-within { border-color: var(--accent); }
.audit-form-input {
    flex: 1;
    border: none;
    background: transparent;
    color: var(--text);
    font-size: var(--fs-md);
    font-family: var(--font-mono);
    padding: 12px 14px;
    outline: none;
}
.audit-form-submit { white-space: nowrap; }

@media (max-width: 880px) {
    .audit-summary { grid-template-columns: 1fr; }
    .audit-score-total { border-right: none; border-bottom: 1px solid var(--divider); padding-bottom: var(--sp-4); }
    .pricing-card-featured { transform: none; }
    .audit-form { flex-direction: column; }
    /* Title above, actions below, each with the full width to wrap into. */
    .audit-header { flex-direction: column; align-items: stretch; }
    .audit-header-text { min-width: 0; }
}

@media (max-width: 480px) {
    /* Two buttons per row rather than one long column. */
    .audit-header-actions .btn { flex: 1 1 auto; text-align: center; }
    /* Anything mono can be an unbroken 60-character string (an SPF record,
       a certificate SAN list) and would otherwise set the page width. */
    .audit-check-detail, .audit-meta { overflow-wrap: anywhere; }
}

/* ============================================================
   28. CHECKOUT CHOOSER (multi-processor paywall)
   ============================================================ */
.checkout-options {
    display: grid;
    gap: 12px;
    margin-top: var(--sp-4);
}
.checkout-option { margin: 0; }
.checkout-option-button {
    width: 100%;
    text-align: left;
    background: var(--surface);
    border: 2px solid var(--border);
    border-radius: var(--radius-lg);
    padding: var(--sp-5);
    cursor: pointer;
    transition: border-color 0.15s, transform 0.05s;
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: center;
    gap: 12px;
    color: var(--text);
    font: inherit;
}
.checkout-option-button:hover { border-color: var(--accent); }
.checkout-option-button:active { transform: scale(0.99); }
.checkout-option-title {
    font-size: var(--fs-md);
    font-weight: 600;
    margin-bottom: 4px;
    grid-column: 1;
}
.checkout-option-blurb {
    font-size: var(--fs-sm);
    color: var(--text-3);
    grid-column: 1;
}
.checkout-option-arrow {
    grid-row: 1 / span 2;
    grid-column: 2;
    font-size: 1.5rem;
    color: var(--accent);
    align-self: center;
}

/* =============================================================
 * 22. AUDIT SECTION PAYWALL (section-tier gating)
 *
 * `.audit-tier-badge` — small badge in the section H2 that signals
 * the tier to the user ("🔒 Pro" or "+ Free signup unlocks more").
 *
 * `.audit-section-locked` — full lock card when the section is gated
 * behind Pro and the user isn't Pro. Replaces the section's checks list.
 *
 * `.audit-section-partial` — softer "X more checks" callout that
 * appears AFTER the first N preview checks when the section is
 * tier='partial' and the user is anonymous (signed-in users see
 * everything).
 * ============================================================= */
.audit-tier-badge {
    display: inline-block;
    margin-left: 10px;
    font-size: var(--fs-xs);
    font-weight: 500;
    color: var(--text-3);
    background: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: 999px;
    padding: 2px 9px;
    vertical-align: middle;
}
.audit-tier-badge-free {
    color: var(--accent);
    border-color: var(--accent);
    background: var(--accent-soft);
}

.audit-section-locked {
    margin: 12px 0 4px;
    padding: 16px;
    border: 1px dashed var(--border-strong, var(--border));
    border-radius: var(--radius-md);
    background: var(--surface);
}
.audit-section-locked-inner {
    display: flex;
    gap: 14px;
    align-items: flex-start;
}
.audit-section-locked-icon {
    font-size: 22px;
    line-height: 1;
    flex-shrink: 0;
    margin-top: 2px;
}
.audit-section-locked-body { flex: 1; min-width: 0; }
.audit-section-locked-title {
    margin: 0 0 8px;
    font-weight: 600;
    font-size: var(--fs-md);
    color: var(--text);
}
.audit-section-locked-list {
    margin: 0 0 12px;
    padding-left: 1.1em;
    color: var(--text-2);
    font-size: var(--fs-sm);
    line-height: 1.7;
}
.audit-section-locked-list li { margin: 0; }
.audit-section-locked-actions {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
}

.audit-section-partial {
    display: flex;
    align-items: center;
    gap: 12px;
    margin: 10px 0 2px;
    padding: 10px 14px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--surface);
    font-size: var(--fs-sm);
    color: var(--text-2);
    flex-wrap: wrap;
}
.audit-section-partial-icon { font-size: 16px; line-height: 1; flex-shrink: 0; }
.audit-section-partial-body { flex: 1; min-width: 200px; }
.audit-section-partial-body strong { color: var(--text); }
.audit-section-partial-actions {
    display: flex;
    gap: 6px;
    flex-shrink: 0;
}

/* =============================================================
 * 23. AUDIT HOSTING INFRASTRUCTURE + TECH STACK
 *
 * `.audit-hosting-infra` — sub-block inside the Network section
 * showing per-IP geo + ASN + cloud-region detection.
 * `.audit-tech-grid` — grouped tech-stack detections from
 * tech-detector. Free-tier visible, category columns.
 * ============================================================= */
.audit-hosting-infra {
    margin-top: 18px;
    padding-top: 16px;
    border-top: 1px dashed var(--border);
}
.audit-hosting-infra-head {
    margin: 0 0 6px;
    font-size: var(--fs-sm);
    font-weight: 600;
    color: var(--text-2);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.audit-hosting-table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--fs-sm);
}
.audit-hosting-table thead th {
    text-align: left;
    padding: 6px 10px;
    color: var(--text-3);
    font-size: var(--fs-xs);
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    border-bottom: 1px solid var(--border);
}
.audit-hosting-table tbody td {
    padding: 8px 10px;
    border-bottom: 1px solid var(--border);
    color: var(--text-2);
    vertical-align: top;
}
.audit-hosting-table tbody tr:last-child td { border-bottom: 0; }

.audit-tech-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: 18px;
}
.audit-tech-cat-head {
    margin: 0 0 8px;
    font-size: var(--fs-xs);
    font-weight: 600;
    color: var(--text-3);
    text-transform: uppercase;
    letter-spacing: 0.05em;
}
.audit-tech-list {
    margin: 0;
    padding: 0;
    list-style: none;
}
.audit-tech-item {
    padding: 6px 0;
    border-bottom: 1px solid var(--border);
    font-size: var(--fs-sm);
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 8px;
}
.audit-tech-item:last-child { border-bottom: 0; }
.audit-tech-name { color: var(--text); font-weight: 500; }
.audit-tech-detail {
    color: var(--text-3);
    font-family: var(--font-mono);
    font-size: var(--fs-xs);
    text-align: right;
}

/* =============================================================
 * 24. GENERIC TOOL RESULT CARD
 *
 * Used by templates/tool-generic.php (all 13 Tier-D tools) for the
 * raw-JSON readout. Before this card the result rendered as a bald
 * <pre> dump on the page — looked like console output, not a
 * diagnostic readout. The card gives it a status header strip
 * (fresh / cached / stale chip + fetched timestamp + Copy JSON
 * button), syntax-highlighted JSON body, and proper padding/border
 * matching the rest of the panel chrome.
 * ============================================================= */
.tool-result-card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    overflow: hidden;
    margin-top: var(--sp-4);
}
.tool-result-card-header {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    padding: 10px 14px;
    background: var(--surface-2);
    border-bottom: 1px solid var(--border);
    font-size: var(--fs-xs);
    color: var(--text-3);
    flex-wrap: wrap;
}
.tool-result-card-header .result-meta-time {
    font-family: var(--font-mono);
}
.tool-result-card-header .result-meta-spacer {
    flex: 1;
}
.tool-result-status-chip {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 2px 8px;
    border-radius: 9999px;
    font-size: var(--fs-2xs, 11px);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.tool-result-status-chip::before {
    content: '';
    display: inline-block;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: currentColor;
}
.tool-result-status-chip.is-fresh  { background: var(--ok-soft);   color: var(--ok); }
.tool-result-status-chip.is-cached { background: var(--surface);   color: var(--text-2); border: 1px solid var(--border); }
.tool-result-status-chip.is-stale  { background: var(--warn-soft); color: var(--warn); }
.tool-result-copy-btn {
    background: transparent;
    border: 1px solid var(--border-strong);
    color: var(--text-2);
    font-size: var(--fs-xs);
    padding: 4px 10px;
    border-radius: 6px;
    cursor: pointer;
    line-height: 1;
    height: 26px;
    transition: background-color 120ms ease, color 120ms ease, border-color 120ms ease;
}
.tool-result-copy-btn:hover {
    background: var(--surface-hover);
    color: var(--text);
}
.tool-result-json {
    margin: 0;
    padding: var(--sp-4);
    background: var(--bg);
    color: var(--text);
    font-family: var(--font-mono);
    font-size: var(--fs-xs);
    line-height: 1.65;
    overflow-x: auto;
    white-space: pre;
    tab-size: 2;
}

/* JSON syntax highlight tokens — wrapped by the highlightJson() JS
   helper. Color palette matches the AEO / tool-eyebrow palette so
   the readout feels consistent with the rest of the diagnostic UI. */
.json-key      { color: var(--accent); font-weight: 600; }
.json-string   { color: var(--ok); }
.json-number   { color: var(--warn); }
.json-bool     { color: var(--accent-strong, var(--accent)); font-weight: 600; }
.json-null     { color: var(--text-3); font-style: italic; }
.json-punc     { color: var(--text-3); }

/* Stale-refresh inline notice (used inside the header strip after the chip
   when the cache is stale + a background refresh has been queued). */
.tool-result-stale-note {
    color: var(--warn);
    font-size: var(--fs-xs);
    font-style: italic;
}

/* Error variant of status chip (renders red when payload.status === 'error') */
.tool-result-status-chip.is-err {
    background: rgba(220, 38, 38, 0.10);
    color: var(--err, #dc2626);
}

/* Raw JSON inside the collapsible <details> at the bottom of the card —
   gets only a small top border, sits flush in the card. */
.tool-result-raw-wrap {
    border-top: 1px solid var(--border);
    padding: 0;
}
.tool-result-raw-wrap > summary {
    list-style: none;
    cursor: pointer;
    padding: 10px 14px;
    font-size: var(--fs-xs);
    color: var(--text-3);
    font-family: var(--font-mono);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    user-select: none;
}
.tool-result-raw-wrap > summary::before {
    content: '▸ ';
    display: inline-block;
    margin-right: 4px;
    transition: transform 120ms ease;
}
.tool-result-raw-wrap[open] > summary::before { content: '▾ '; }
.tool-result-raw-wrap > summary:hover { color: var(--text-2); }

/* =============================================================
 * 25. HUMAN-READABLE RESULT BODY  (.tr-* classes)
 *
 * Replaces the raw JSON dump with a labeled-field view. The
 * renderHumanResult() JS function in tool-generic.php emits this
 * markup. CSS handles four shapes:
 *   - <dl class="tr-fields"> + .tr-row + .tr-label + .tr-value
 *       — the dominant labeled-field layout
 *   - <table class="tr-table">  — array-of-objects compact table
 *   - .tr-list .tr-sep          — array-of-primitives comma list
 *   - .tr-nested                — recursive object rows inside a cell
 * ============================================================= */
.tr-body { padding: var(--sp-4) var(--sp-4) var(--sp-2); }
.tr-error-body {
    padding: var(--sp-4);
    background: rgba(220, 38, 38, 0.04);
    border-top: 1px solid var(--border);
}
.tr-error-msg {
    margin: 0;
    color: var(--err, #dc2626);
    font-size: var(--fs-sm);
}

.tr-fields {
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: 1fr;
    gap: 0;
}
.tr-row {
    display: grid;
    grid-template-columns: 180px 1fr;
    align-items: baseline;
    gap: var(--sp-3);
    padding: 10px 0;
    border-bottom: 1px solid var(--divider, var(--border));
    font-size: var(--fs-sm);
}
.tr-row:last-child { border-bottom: 0; }
.tr-label {
    margin: 0;
    color: var(--text-3);
    font-size: var(--fs-xs);
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-family: var(--font-mono);
}
.tr-value {
    margin: 0;
    color: var(--text);
    word-break: break-word;
}

.tr-str    { color: var(--text); }
.tr-num    { color: var(--text); font-family: var(--font-mono); }
.tr-yes    { color: var(--ok);   font-weight: 600; font-size: var(--fs-xs); }
.tr-no     { color: var(--err, #dc2626); font-weight: 600; font-size: var(--fs-xs); }
.tr-null   { color: var(--text-3); font-style: italic; font-size: var(--fs-xs); }
.tr-sep    { color: var(--text-3); }

.tr-list {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 6px;
}

.tr-nested {
    padding: 6px 0 6px 12px;
    border-left: 2px solid var(--border);
    margin-top: 4px;
}
.tr-nested .tr-row {
    grid-template-columns: 140px 1fr;
    padding: 6px 0;
    font-size: var(--fs-xs);
}

.tr-longstr {
    background: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 8px 10px;
    margin: 4px 0;
}
.tr-longstr-text {
    display: block;
    color: var(--text);
    font-family: var(--font-mono);
    font-size: var(--fs-xs);
    line-height: 1.55;
    word-break: break-all;
    white-space: pre-wrap;
}

.tr-table-wrap {
    overflow-x: auto;
    margin: 4px 0;
}
.tr-table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--fs-xs);
}
.tr-table thead th {
    text-align: left;
    padding: 6px 10px;
    color: var(--text-3);
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    border-bottom: 1px solid var(--border);
    font-family: var(--font-mono);
    background: var(--surface-2);
}
.tr-table tbody td {
    padding: 8px 10px;
    border-bottom: 1px solid var(--divider, var(--border));
    color: var(--text-2);
    vertical-align: top;
}
.tr-table tbody tr:last-child td { border-bottom: 0; }

.tr-raw-record {
    margin: 0 var(--sp-4) var(--sp-3);
    border: 1px solid var(--border);
    border-radius: 6px;
    background: var(--surface-2);
}
.tr-raw-record > summary {
    list-style: none;
    cursor: pointer;
    padding: 8px 12px;
    font-size: var(--fs-xs);
    color: var(--text-3);
    user-select: none;
}
.tr-raw-text {
    margin: 0;
    padding: 12px;
    font-family: var(--font-mono);
    font-size: var(--fs-xs);
    line-height: 1.6;
    color: var(--text-2);
    word-break: break-all;
    white-space: pre-wrap;
    border-top: 1px solid var(--border);
}

/* =============================================================
 * 26. SIDEBAR CTA WIDGET POLISH
 *
 * Adjustments so the Audit + Pro Features widgets on tool pages
 * look like substantive CTAs rather than soft cards:
 *   - tighter heading rhythm
 *   - body text gets a bit more weight
 *   - buttons get the full block treatment with stronger padding
 *   - ghost button on surface bg picks up subtle fill so it doesn't
 *     blend into the card behind it
 * ============================================================= */
.sidebar-widget p {
    margin: 0 0 var(--sp-3);
    color: var(--text-2);
    font-size: var(--fs-sm);
    line-height: 1.55;
}
.sidebar-widget ul {
    margin: 0 0 var(--sp-3);
    padding: 0;
    list-style: none;
    color: var(--text-2);
    font-size: var(--fs-sm);
    line-height: 1.85;
}
/* Sidebar CTA buttons.
 *
 * The .btn-block fix above (display:flex, not display:block) is what
 * actually centers the text — that was the underlying conflict. These
 * rules only handle color: primary stays solid purple (inherited from
 * .btn-primary), ghost gets an outline-accent treatment so it reads as
 * a real button against the white widget card, not a sunken box.
 * No height/transform/box-shadow overrides — keeps the button rhythm
 * matched with buttons elsewhere on the page.
 */
.sidebar-widget .btn-ghost {
    background: transparent;
    border: 1.5px solid var(--accent);
    color: var(--accent);
    font-weight: 600;
}
.sidebar-widget .btn-ghost:hover {
    background: var(--accent);
    border-color: var(--accent);
    color: #ffffff;
}


/* Audit re-run — an inline form styled to sit in the meta line like the
   link it replaced, rather than looking like a form control. */
.audit-refresh-form { display: inline; }
.audit-refresh-btn {
    background: none;
    border: 0;
    padding: 0;
    font: inherit;
    color: var(--accent);
    cursor: pointer;
    text-decoration: underline;
}
.audit-refresh-btn:hover { opacity: 0.85; }
.audit-refresh-note {
    margin-top: var(--sp-2);
    font-size: var(--fs-sm);
    color: var(--text-3);
}

/* Account index rows. This hover was two inline handlers assigning
   element.style directly — which is a thing CSS does better, and which
   also had to go before the page could drop 'unsafe-inline' from its CSP:
   a nonce can authorise a <script> block, but an event-handler attribute
   has nothing to carry a nonce on. */
.account-nav-row { transition: background-color 100ms ease; }
.account-nav-row:hover,
.account-nav-row:focus-visible { background: var(--ip-surface-2); }


/* ============================================================
   PROGRESSIVE AUDIT — the report filling in while you watch
   ============================================================
   A cold audit runs 22 checks over tens of seconds. The page paints first
   and the results arrive in slices, so the rows that have not answered yet
   need to read as "coming" rather than as "failed". They already carry the
   `unknown` badge, which is honest either way: while the sweep is running it
   means not yet, and once it finishes it means we could not find out. */

.audit-live-note {
    margin: var(--sp-4) 0 0;
    color: var(--text-3);
    font-size: var(--fs-sm);
    font-family: var(--font-mono);
}

/* Only while a sweep is actually in flight. */
#audit-live.is-loading .audit-check-unknown {
    position: relative;
    overflow: hidden;
}
#audit-live.is-loading .audit-check-unknown .audit-check-label,
#audit-live.is-loading .audit-check-unknown .audit-check-detail {
    opacity: 0.55;
}
#audit-live.is-loading .audit-check-unknown::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(90deg,
        transparent 0%,
        var(--surface-2) 45%,
        transparent 90%);
    opacity: 0.5;
    transform: translateX(-100%);
    animation: audit-shimmer 1.5s ease-in-out infinite;
    pointer-events: none;
}
@keyframes audit-shimmer {
    to { transform: translateX(100%); }
}

/* A bar with no score yet reads as empty rather than as zero — a zero is a
   judgement, and none has been made. Same reasoning as the '—' the value
   column shows for a null score. */
#audit-live.is-loading .audit-bar-unknown {
    background-image: linear-gradient(90deg, var(--border) 0%, var(--surface-2) 50%, var(--border) 100%);
    background-size: 200% 100%;
    animation: audit-bar-pulse 1.6s ease-in-out infinite;
    width: 100% !important;
    opacity: 0.35;
}
@keyframes audit-bar-pulse {
    0%, 100% { background-position: 0% 0; }
    50%      { background-position: 100% 0; }
}

/* Respect a reader who has asked for less motion: the state still reads,
   it just stops moving. */
@media (prefers-reduced-motion: reduce) {
    #audit-live.is-loading .audit-check-unknown::after,
    #audit-live.is-loading .audit-bar-unknown { animation: none; }
}

/* ---- Audit: change history -----------------------------------------
   The audit page loads public.css, not panel.css. The .audit-alerts /
   .audit-changes rules in panel.css have never applied to it. */
.audit-alerts, .audit-changes { margin: 24px 0; }
.audit-changes-window { font-weight: 400; color: var(--text-3, #6b7280); font-size: 0.9em; }

/* Guests get an offer here instead of the event list — the list answers a
   question only the domain's owner has. Buttons wrap rather than overflow;
   this card sits inside the same narrow column as the section cards. */
.audit-changes-gate {
    border: 1px solid var(--border, #e5e7eb);
    border-radius: 12px;
    padding: 20px;
    background: var(--surface, #fff);
}
.audit-changes-gate h2 { margin: 0 0 10px; }
.audit-changes-gate-lede { margin: 0 0 8px; }
.audit-changes-gate-sub {
    margin: 0 0 16px;
    color: var(--text-2, #4b5563);
    font-size: 0.9375rem;
}
.audit-changes-gate-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}
@media (max-width: 520px) {
    .audit-changes-gate { padding: 16px; }
    .audit-changes-gate-actions .btn { flex: 1 1 100%; text-align: center; }

}


/* ---- Audit: sticky section nav ------------------------------------------
   Desktop only. Below the breakpoint the report is a single column and the
   nav is not rendered at all -- on a phone a list of links to things a
   thumb-flick away is cost without benefit, and it would push the score
   bars (the thing worth seeing first) below the fold.

   minmax(0, 1fr) on the content column, not 1fr: the report contains wide
   tables, and a bare 1fr lets their intrinsic width blow the grid out and
   reintroduce the horizontal scroll that was fixed on this page. */
.audit-toc { display: none; }

.audit-layout-main { min-width: 0; }

@media (min-width: 1100px) {
    .audit-layout {
        display: grid;
        grid-template-columns: 190px minmax(0, 1fr);
        gap: var(--sp-6, 32px);
        align-items: start;
    }
    .audit-toc {
        display: block;
        position: sticky;
        /* Clears the site header, which is sticky too. */
        top: 84px;
        max-height: calc(100vh - 104px);
        overflow-y: auto;
    }
}

.audit-toc-title {
    font-size: var(--fs-xs);
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--text-3);
    margin: 0 0 10px;
}
.audit-toc-list { list-style: none; margin: 0; padding: 0; }
.audit-toc-list a {
    display: block;
    padding: 6px 10px;
    border-left: 2px solid var(--border);
    color: var(--text-2);
    text-decoration: none;
    font-size: var(--fs-sm);
    line-height: 1.35;
}
.audit-toc-list a:hover { color: var(--text); background: var(--surface-2); }
.audit-toc-list a.is-active {
    color: var(--accent);
    border-left-color: var(--accent);
    font-weight: 600;
}

/* Respect a reduced-motion preference for the smooth jump. */
@media (prefers-reduced-motion: no-preference) {
    html { scroll-behavior: smooth; }
}
/* Anchored sections must not land under the sticky header. */
.audit-layout [id^="section-"] { scroll-margin-top: 84px; }

/* ---- Audit: section score in the card header ---------------------------- */
.audit-section-summary.is-unscored { color: var(--text-3); font-style: italic; }
.audit-section-outof { color: var(--text-3); font-weight: 400; }


/* ---- Audit: loading skeletons ------------------------------------------
   A check we have not reached yet renders as a placeholder, not as a failed
   row with a shimmer laid over it. The old treatment kept the "?" badge, the
   check's name and a detail line like "The page was not fetched", so a report
   that had just started reading as one that had finished badly -- which is
   what made a fresh audit look stuck rather than busy. */
.audit-skel {
    display: inline-block;
    border-radius: 4px;
    background: linear-gradient(90deg,
        var(--surface-2) 0%, var(--border) 50%, var(--surface-2) 100%);
    background-size: 200% 100%;
    animation: audit-skel-sweep 1.4s ease-in-out infinite;
}
.audit-skel-badge { width: 18px; height: 18px; border-radius: 50%; flex: 0 0 18px; }
.audit-skel-label { height: 11px; flex: 0 1 auto; }
.audit-skel-score { width: 52px; height: 12px; vertical-align: middle; }

/* Varying the widths stops six identical bars reading as a rendering bug.
   nth-child is enough — the rows are in DOM order and never reordered. */
.audit-check-pending:nth-child(3n+1) .audit-skel-label { width: 46%; }
.audit-check-pending:nth-child(3n+2) .audit-skel-label { width: 62%; }
.audit-check-pending:nth-child(3n+3) .audit-skel-label { width: 38%; }

@keyframes audit-skel-sweep {
    0%   { background-position: 100% 0; }
    100% { background-position: -100% 0; }
}

/* A placeholder that animates forever is noise for anyone who asked for less
   motion; it still reads as "not yet filled in" without moving. */
@media (prefers-reduced-motion: reduce) {
    .audit-skel { animation: none; background: var(--surface-2); }
}
