/* ============================================================
   CloudScale Code and SQL, Admin UI  v1.7.17
   Colour palette mirrors CloudScale Page Views: electric blue,
   bright green, vivid orange, deep navy, white.
   ============================================================ */

/* Reset within wrap */
#cs-app * { box-sizing: border-box; }
#cs-app {
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    font-size: 13px;
    color: var(--csds-navy, #1a2332);
    max-width: 1200px;
    margin-top: 10px;
    padding-left: 16px;
    padding-right: 20px;
    overflow-x: hidden;
}
@media (max-width: 782px) {
    #cs-app {
        padding-left: 12px;
        padding-right: 12px;
    }
    /* MOVED OUT of this block: it declared padding:16px for tablets, but sat BEFORE the base
       .cs-panel-body rule of equal specificity, so the cascade gave it to nobody, tablets
       silently got the full desktop 20px 24px. Re-declared after the base rule instead, where
       it actually applies. See the tablet override further down. */
    #cs-banner {
        padding: 16px;
    }
    #cs-tab-bar {
        padding: 0 8px;
    }
    .cs-tab {
        padding: 10px 14px;
        font-size: 12px;
    }
    .cs-tab-divider {
        margin: 8px 4px;
        padding: 0 8px 0 10px;
    }
}

/* ── Banner ─────────────────────────────────────── */
#cs-banner {
    background: linear-gradient(135deg, #0f1f2e 0%, #0d3349 60%, #0f1f2e 100%);
    border-radius: 8px 8px 0 0;
    padding: 14px 20px 12px;
    border-bottom: 1px solid rgba(15, 184, 224, 0.25);
}
#cs-banner-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 6px;
    margin-bottom: 4px;
}
#cs-banner-title {
    font-size: 13px;
    font-weight: 700;
    color: var(--csds-border, #e2e8f0);
    letter-spacing: 0.04em;
    text-transform: uppercase;
    display: flex;
    align-items: center;
    gap: 8px;
}
#cs-banner-sub {
    font-size: 12px;
    color: #cbd5e1; /* 11px #94a3b8 read as low contrast on the banner; tests/banner-contrast-test.php */
    margin-top: 0;
    line-height: 1.4;
}
#cs-banner-right { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; justify-content: flex-end; }
.cs-badge {
    display: inline-block;
    padding: 3px 10px;
    border-radius: 20px;
    font-size: 10px;
    font-weight: 700;
    white-space: nowrap;
    letter-spacing: 0.04em;
}
.cs-badge-version {
    background: rgba(15, 184, 224, 0.15);
    border: 1px solid rgba(15, 184, 224, 0.4);
    color: #67e8f9;
}
.cs-badge-green  { background: #166534; border: 1px solid var(--csds-success, #22c55e); color: #bbf7d0; }
.cs-badge-orange { background: #7c2d12; border: 1px solid #f97316; color: #fed7aa; }
.cs-badge-help   { background: rgba(15, 184, 224, 0.15); border: 1px solid rgba(15, 184, 224, 0.4); color: #67e8f9; }
.cs-badge-enterprise { background: rgba(234, 179, 8, 0.15); border: 1px solid rgba(234, 179, 8, 0.5); color: #fde68a; }

/* Edge Protection group: brackets Edge WAF Push and Edge Gateway and says why a site wants both.
   It sits on the light admin page, not on a dark panel header, so its text is dark on a solid light
   tint. The first cut used the header palette (#c7d2fe, #cbd5e1, #fde68a) and read as washed out
   (reported 2026-10-28); tests/edge-group-contrast-test.php measures every colour against 7:1. */
.cs-edge-group {
    margin: 18px 0 6px;
    padding: 14px 16px;
    border: 1px solid #c7d2fe;
    border-left: 3px solid #6366f1;
    border-radius: 8px;
    background: #eef2ff;
}
.cs-edge-group-header { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.cs-edge-group-title { font-size: 15px; font-weight: 700; color: #312e81; letter-spacing: 0.02em; }
.cs-edge-group-intro { margin: 10px 0 0; font-size: 13px; line-height: 1.5; color: #1f2937; }
.cs-edge-group-list { margin: 10px 0 0; padding-left: 18px; font-size: 13px; line-height: 1.55; color: #1f2937; }
.cs-edge-group-list li { margin: 4px 0; }
.cs-edge-group-list strong { color: #312e81; }
/* Edge WAF Push and Edge Gateway nest inside the group as its sub panels. */
.cs-edge-group-panels { margin-top: 14px; }
.cs-edge-group-panels > .cs-panel { margin: 0 0 14px; }
.cs-edge-group-panels > .cs-panel:last-child { margin-bottom: 0; }
/* The gold Enterprise badge is drawn for dark headers; on the light group it needs dark text. */
.cs-edge-group .cs-badge-enterprise { background: #fef3c7; border: 1px solid #f59e0b; color: #78350f; }

/* ── Tab bar ─────────────────────────────────────── */
#cs-tab-bar {
    background: #1a2d6b;
    display: flex;
    gap: 2px;
    /* The top padding is headroom for a hovered tab to lift into: overflow-x: auto makes the
       bar clip vertically too, so a lift with no room above it would be cut off. */
    padding: 6px 20px 0;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;        /* Firefox */
}
#cs-tab-bar::-webkit-scrollbar { display: none; } /* Chrome/Safari */
.cs-tab {
    background: transparent;
    border: none;
    color: rgba(255,255,255,.88); /* .6 was hard to read; the active tab is told apart by white and the orange underline */
    font-size: 13px;
    font-weight: 600;
    padding: 12px 20px;
    cursor: pointer;
    border-bottom: 3px solid transparent;
    transition: all .15s;
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    flex-shrink: 0;
    white-space: nowrap;
}
/* Hover lifts the tab off the bar; the active tab is a white folder tab that joins the page,
   with the orange underline. Both were too subtle as a text colour change and an 8% wash. */
.cs-tab { border-radius: 8px 8px 0 0; }
.cs-tab:hover {
    color: #fff;
    background: #3a52a8;
    border-bottom-color: #ffffff;
    transform: translateY(-3px);
    box-shadow: 0 -4px 14px rgba(0,0,0,.45), inset 0 0 0 1px rgba(255,255,255,.35);
}
.cs-tab:focus { outline: none; box-shadow: none; }
.cs-tab:focus-visible { outline: 2px solid #fff; outline-offset: -4px; }
/* Same specificity as .cs-tab:hover and later in the file, so a hovered active tab stays put. */
.cs-tab.active {
    color: #14246b;
    background: #ffffff;
    border-bottom-color: #f47c20;
    font-weight: 800;
    transform: none;
    box-shadow: 0 -3px 12px rgba(0,0,0,.35);
}
@media (prefers-reduced-motion: reduce) {
    .cs-tab:hover { transform: none; }
}
/* Splits the bar into security tabs and site tools. Not a .cs-tab, so the router and every
   test that discovers tabs by their &tab= href ignore it. Same muted white as an inactive tab
   label on the #1a2d6b bar, a little dimmer and smaller, so it reads as a heading. It is a <button> that opens the
   first site tool (cs-tab-router.js), because it looked clickable and doing nothing read as
   broken, so the resets below undo WordPress's admin button chrome and it lights up on hover
   like a tab does. */
.cs-tab-divider {
    display: inline-flex;
    align-items: center;
    flex-shrink: 0;
    margin: 10px 6px;
    padding: 0 10px 0 14px;
    background: none;
    border: 0;
    border-left: 1px solid rgba(255,255,255,.3);
    border-radius: 0;
    box-shadow: none;
    color: rgba(255,255,255,.8);
    font-family: inherit;
    font-size: 10px;
    font-weight: 700;
    line-height: inherit;
    letter-spacing: .06em;
    text-transform: uppercase;
    white-space: nowrap;
    cursor: pointer;
}
.cs-tab-divider:hover,
.cs-tab-divider:focus-visible { color: #fff; }
.cs-tab-divider:focus { outline: none; }
.cs-tab-divider:focus-visible { outline: 1px solid rgba(255,255,255,.6); outline-offset: 2px; }

/* ── Copy All action bar ─────────────────────────── */
#cs-tab-actions {
    background: #f8f9fb;
    border-bottom: 1px solid #e5e7eb;
    display: flex;
    justify-content: flex-end;
    padding: 6px 20px;
}
.cs-copy-all-btn {
    background: #1a2d6b;
    border: 1px solid #1a2d6b;
    color: #fff;
    font-size: 12px;
    font-weight: 600;
    padding: 5px 14px;
    border-radius: 6px;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    transition: background .15s, border-color .15s;
    white-space: nowrap;
}
.cs-copy-all-btn:hover { background: #243d8f; border-color: #243d8f; }
.cs-copy-all-btn:focus { outline: none; box-shadow: none; }
.cs-copy-all-btn.copied {
    background: var(--csds-success, #15803d);
    border-color: var(--csds-success, #15803d);
}

/* ── Tab content ─────────────────────────────────── */
/* Collapsible panels. Hides SIBLINGS of the header rather than a body wrapper, because panels have
   no wrapper, content sits as direct children after .cs-section-header. That is what lets this
   apply to every existing panel without editing one of them. */
.cs-panel.is-collapsible > .cs-section-header { cursor: pointer; }
/* Keyed on .is-collapsible alone, not .cs-panel.is-collapsible: the Security Headers and Header
   Security Scan panels are hand-rolled, a .cs-section-header plus their own bordered body, and
   wrapping them in .cs-panel to gain collapsing would draw a second border around a box that already
   has one. The mechanism only ever needed the class and a header. */
.is-collapsible.is-collapsed > *:not(.cs-section-header) { display: none !important; }
.is-collapsible.is-collapsed { margin-bottom: 8px; }
/* A collapsed hand-rolled panel's header keeps its own rounded top but should not leave a square
   bottom edge with nothing under it. */
.is-collapsible.is-collapsed > .cs-section-header { border-radius: 6px; }
/* A text control now ("Expand" / "Collapse"), sized and coloured to sit beside the Explain button
   rather than compete with it: same height and radius, quieter fill. It was a square glyph box
   showing + / -, which appears nowhere else in this product. */
.cs-panel-toggle {
    margin-left: auto;
    flex: 0 0 auto;
    padding: 4px 12px;
    min-width: 74px;
    text-align: center;
    border: 1px solid rgba(255, 255, 255, 0.35);
    border-radius: 5px;
    background: rgba(255, 255, 255, 0.12);
    color: #fff;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .02em;
    line-height: 1.5;
    cursor: pointer;
}
.cs-panel-toggle:hover { background: rgba(255, 255, 255, 0.24); }
/* A collapsed healthy panel says so, so the row is informative rather than merely shut. */
.cs-panel-state {
    font-size: 11px;
    font-weight: 700;
    color: #86efac;
    background: rgba(22, 163, 74, 0.18);
    border-radius: 999px;
    padding: 2px 8px;
    white-space: nowrap;
}

/* The AI choice. Two columns of the same shape so they read as a comparison rather than one option
   with a caveat, and the cost line last in both, the trade is the thing being decided. Stacks on
   narrow screens, where side-by-side would truncate. */
.cs-ai-choice { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 12px; padding: 14px; }
.cs-ai-opt { background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 8px; padding: 12px 14px; }
.cs-ai-opt-title { font-size: 13px; font-weight: 800; color: #0f172a; margin-bottom: 6px; }
.cs-ai-opt-list { margin: 0 0 8px; padding-left: 18px; font-size: 12px; color: #374151; line-height: 1.55; }
.cs-ai-opt-list li { margin: 0 0 3px; }
.cs-ai-opt-cost { font-size: 12px; font-weight: 700; color: #b45309; }
.cs-ai-choice-foot { display: flex; flex-wrap: wrap; gap: 10px; padding: 0 14px 14px; }
/* The two routes are .cs-ctl-btn buttons since 2026-10-21; this only lays them out. */
.cs-ai-choice-foot a:not(.cs-ctl-btn) { font-size: 13px; font-weight: 700; color: #1d4ed8; text-decoration: none; }
.cs-ai-choice-foot a:not(.cs-ctl-btn):hover { text-decoration: underline; }

/* Setup checklist. Multiple cards per row rather than one full-width row per step, so the panel
   reads like the status-card grid below it instead of a form. Completed steps collapse to a tick
   and a title so the grid shrinks as the site is set up, the progress is the point, and a step
   that stays loud after it is done is a nag.

   Since 2026-10-21 the list sits inside .cs-home-card-body (which pads it), under the Home
   introduction, so it has no padding of its own. The first step still to do is .is-next and is
   drawn with the accent border, so "what do I do now" is answered without reading all nine. */
.cs-setup-list {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 240px), 1fr));
    gap: 12px;
    margin-top: 16px;
}
/* ONE COLUMN ON A PHONE. This was two 130px columns, which held a title and a tick but not a
   call-to-action button: "Compare the two" with its arrow is wider than 130px, and at 390px the
   button pushed the card past the viewport. A single column of compact cards keeps every button
   whole and needs no horizontal scroll; tests/home-layout-live.spec.js measures it at 390px. */
@media (max-width: 600px) {
    .cs-setup-list {
        grid-template-columns: minmax(0, 1fr);
        gap: 8px;
    }
    /* A finished step is one line on a phone: tick, title, state and Review side by side, so the
       steps still to do are what fills the screen. */
    .cs-setup-step.is-done {
        flex-direction: row;
        flex-wrap: wrap;
        align-items: center;
        gap: 6px 10px;
        padding: 10px 12px;
    }
    .cs-setup-step.is-done .cs-setup-body { flex: 1 1 120px; width: auto; }
    .cs-setup-step.is-done .cs-setup-cta { margin-top: 0; margin-left: auto; }
}
.cs-setup-step {
    display: flex;
    flex-direction: column;
    gap: 8px;
    align-items: flex-start;
    padding: 14px;
    background: #fff;
    border: 1px solid #dbe2ea;
    border-radius: 10px;
    min-width: 0;
}
.cs-setup-step.is-done { background: #f8fafc; border-color: #e2e8f0; }
.cs-setup-step.is-next { border-color: #3730a3; box-shadow: inset 0 0 0 1px #3730a3; }
.cs-setup-head { display: flex; align-items: center; gap: 10px; }
.cs-setup-num {
    flex: 0 0 24px;
    height: 24px;
    border-radius: 50%;
    background: #e2e8f0;
    color: #334155;
    font-size: 12px;
    font-weight: 700;
    line-height: 24px;
    text-align: center;
}
.cs-setup-step.is-next .cs-setup-num { background: #3730a3; color: #fff; }
.cs-setup-step.is-done .cs-setup-num { background: #dcfce7; color: #166534; }
.cs-setup-body { flex: 1 1 auto; min-width: 0; width: 100%; }
.cs-setup-title { font-size: 14px; font-weight: 700; color: #0f172a; line-height: 1.35; }
.cs-setup-step.is-done .cs-setup-title { font-weight: 600; color: #334155; }
.cs-setup-why { font-size: 13px; color: #334155; margin-top: 2px; line-height: 1.5; }
.cs-setup-todo { font-size: 12.5px; color: #92400e; margin-top: 4px; font-weight: 600; }
.cs-setup-state { font-size: 12.5px; color: #166534; font-weight: 600; }
.cs-setup-state-detail { color: #334155; font-weight: 400; margin-left: 4px; }
/* A real button, not a text link, asked for 2026-08-18. Colour comes from .cs-ctl-btn--primary /
   .cs-ctl-btn--secondary (the reusable controls at the end of this file); this only places it
   inside the card. A completed row still links, so you can go and check what it was actually set
   to, asked for 2026-08-17. The secondary tone is quieter than the primary on purpose: reviewing is
   optional, and every step showing an equally loud button would undo the point of showing which
   steps still need work. */
.cs-setup-cta { align-self: flex-start; margin-top: auto; }

/* The manual steps, findings whose fix this plugin refuses to perform (a root shell, wp-config.php,
   WP's own Users screen). Visually SEPARATE from the numbered steps above, with no number and no
   per-row button, because there is nothing there to click: offering one would promise an action
   that cannot happen. A tinted well rather than a card, so it reads as a footnote to the checklist
   rather than a tenth step. The one button is the route to the full audit report.

   Light background, so per the house contrast rule every text colour below is a dark one. */
.cs-setup-manual {
    border-top: 1px solid #e2e8f0;
    background: #f8fafc;
    padding: 16px 20px 20px;
}
.cs-setup-manual-head {
    font-size: 13px;
    font-weight: 700;
    color: #0f172a;
    margin-bottom: 8px;
}
.cs-setup-manual-head span {
    display: block;
    font-size: 12px;
    font-weight: 400;
    color: #475569;
    margin-top: 1px;
}
.cs-setup-manual-row {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 6px 0;
}
.cs-setup-sev {
    flex: 0 0 auto;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .04em;
    color: #fff;               /* on a solid dark severity colour, from .cs-sev-badge--* */
    padding: 2px 6px;
    border-radius: 4px;
    margin-top: 1px;
}
.cs-setup-manual-title { font-size: 13px; font-weight: 600; color: #0f172a; }
.cs-setup-manual-where { font-size: 12px; color: #334155; margin-top: 1px; line-height: 1.5; }
/* A button since 2026-10-21 (.cs-ctl-btn--primary), not an 11px text link: it is the only route
   to the commands the rows above need. This rule only spaces it from the list. */
.cs-setup-manual-more { margin-top: 12px; }
@media (max-width: 600px) {
    .cs-setup-manual { padding: 14px; }
    .cs-setup-manual-more { white-space: normal; text-align: center; }
}

/* The tab introduction: what this tab is for, why it matters, and one tip.
   A CARD WITH THE SAME EDGES AS .cs-panel (border, radius, full width, no side margin), so its
   left and right edges sit exactly over the panel below it. It was a grey line with a left bar
   capped at 80ch, which ended part way across a full-width layout and read as text dropped on
   the page (reported 2026-10-21). The tip sits on its own row under a bold label rather than
   trailing the description. Text is #1f2937 on #fff (about 15:1) and the label #3730a3 on #fff
   (about 10:1); tests/tab-intro-card-test.php measures both against 7:1. */
.cs-tab-intro-line {
    background: #fff;
    border: 1.5px solid #dce3ef;
    border-radius: 8px;
    margin: 16px 0 0;
    padding: 14px 24px;
    font-size: 13px;
    line-height: 1.55;
    color: #1f2937;
    box-sizing: border-box;
}
/* The tab router empties the card when the next tab has no intro; an empty card is not drawn. */
.cs-tab-intro-line:empty { display: none; }
/* Colour coded (asked for 2026-10-28): the description is information, marked in indigo; the tip
   is advice, an amber callout, so the two read apart at a glance. Text stays dark on light for the
   7:1 contrast tests/tab-intro-card-test.php measures. */
.cs-tab-intro-lead {
    margin: 0;
    padding-left: 12px;
    border-left: 3px solid #6366f1;
    color: #1f2937;
}
.cs-tab-intro-tip {
    margin: 12px 0 0;
    padding: 10px 14px;
    background: #fffbeb;
    border: 1px solid #fde68a;
    border-left: 4px solid #f59e0b;
    border-radius: 6px;
    color: #1f2937;
}
.cs-tab-intro-tip-label {
    display: block;
    margin: 0 0 2px;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: #78350f;
}
.cs-tab-intro-tip-label::before { content: "\1F4A1\00a0"; }
@media (max-width: 782px) {
    .cs-tab-intro-line { padding: 12px 16px; }
}

.cs-tab-content { display: none; padding: 20px 0 0; }
.cs-tab-content.active { display: block; }

/* ── Section headers ─────────────────────────────── */
.cs-section-header {
    background: linear-gradient(135deg, var(--csds-accent, #1a3a8f), var(--csds-accent, #1e6fd9));
    color: #fff;
    font-size: 12px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .06em;
    padding: 10px 16px;
    display: flex;
    align-items: center;
    gap: 12px;
}
.cs-section-header-green  { background: linear-gradient(135deg, #1a7a3a, var(--csds-success, #1db954)); }
.cs-section-header-orange { background: linear-gradient(135deg, #c45c00, #f47c20); }
.cs-section-header-red    { background: linear-gradient(135deg, #8b1a1a, var(--csds-danger, #e53e3e)); }
.cs-section-header-purple { background: linear-gradient(135deg, #5b21b6, #7c3aed); }
.cs-section-header-teal   { background: linear-gradient(135deg, #0d6a5c, #0fb8e0); }
.cs-section-header code {
    background: rgba(255,255,255,.2);
    color: #fff;
    padding: 1px 6px;
    border-radius: 3px;
    font-size: 11px;
}
.cs-header-hint {
    font-size: 11px;
    font-weight: 400;
    opacity: .8;
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    margin-left: auto;
    text-align: right;
}
@media (max-width: 480px) {
    .cs-header-hint { display: none; }
    .cs-section-header { gap: 8px; }
}
/* Explain is always the last thing in a heading row, whatever order the panel printed it in.
   Four panels printed it before their own header controls (the PHP error toggles, the map
   layer toggles), so it sat mid-row there and at the far right everywhere else. Set here, in
   the one place, so a new panel cannot get it wrong; tab-smoke.spec.js measures it. */
.cs-section-header [id^="cs-explain-btn-"],
.cs-subsection-head [id^="cs-explain-btn-"],
.cs-bf-log-header [id^="cs-explain-btn-"] { order: 99; }

/* ── Panel sub-headings (optimizer sub-sections) ─── */
.cs-panel-heading {
    font-size: 1.05em;
    font-weight: 700;
    color: var(--csds-navy, #1e293b);
    margin: 0 0 14px;
    padding: 0 0 10px;
    border-bottom: 2px solid var(--csds-border, #e2e8f0);
    display: flex;
    align-items: center;
    gap: 8px;
}
.cs-panel-heading::before {
    content: "";
    display: inline-block;
    width: 4px;
    height: 1.1em;
    background: #4338ca;
    border-radius: 2px;
    flex-shrink: 0;
}

/* ── Panels / Cards ──────────────────────────────── */
.cs-panel {
    background: #fff;
    border: 1.5px solid #dce3ef;
    border-radius: 8px;
    overflow: hidden;
    margin-bottom: 18px;
}
.cs-panel-body {
    padding: 20px 24px;
}

/* A panel reached through a #cs-panel-* link ("Where to fix this", dashboard chips). Its heading
   stops clear of the WordPress admin bar, and cs-panel-collapse.js adds .cs-panel-targeted for two
   seconds so it is obvious which panel the link meant. */
[id^="cs-panel-"] { scroll-margin-top: 46px; }
.cs-panel-targeted {
    box-shadow: 0 0 0 3px #4338ca;
    transition: box-shadow .35s ease;
}

/* Tablet padding, declared AFTER the base rule so it wins. The copy that used to live in the
   @media block near the top of this file lost to the base rule on every width, which is why
   panels have always had desktop padding on a tablet. */
@media (max-width: 782px) {
    .cs-panel-body {
        padding: 16px;
    }
}
.cs-tab-intro {
    background: var(--csds-surface-2, #f8fafc);
    border: 1px solid var(--csds-border, #e2e8f0);
    border-radius: 6px;
    padding: 14px 18px;
    margin-bottom: 20px;
    font-size: 13px;
    color: var(--csds-text-2, #374151);
    line-height: 1.65;
}
.cs-tab-intro p { margin: 0 0 8px; }
.cs-tab-intro p:last-child { margin-bottom: 0; }

/* ── Group heading (splits a long tab into named groups) ──────────
   Light surface, so the text colours here must be dark, see the
   contrast rule in CLAUDE.md. */
.cs-group-heading {
    display: flex;
    align-items: baseline;
    gap: 10px;
    flex-wrap: wrap;
    margin: 30px 0 14px;
    padding-bottom: 8px;
    border-bottom: 2px solid var(--csds-border, #e2e8f0);
}
.cs-group-heading:first-child { margin-top: 4px; }
.cs-group-heading-title {
    font-size: 13px;
    font-weight: 800;
    letter-spacing: .09em;
    text-transform: uppercase;
    color: #0f172a;
}
.cs-group-heading-hint {
    font-size: 12px;
    color: #64748b;
}

/* ── Field layout ────────────────────────────────── */
/* gap only separates fields WITHIN a row. Consecutive .cs-field-row siblings had no
   vertical rhythm at all, so every panel built from these classes, Country Rules,
   SMTP, Firewall, Activity Log, Enum Guard, Thumbnails, and 19 rows in the main file,
   rendered as one crushed block with each control flush against the label above it.
   Fixed here rather than per panel: 32 rows share this class and all 32 had the fault. */
.cs-field-row {
    display: flex;
    gap: 24px;
    flex-wrap: wrap;
    align-items: flex-start;
    margin-bottom: 18px;
}
.cs-field-row:last-child {
    margin-bottom: 0;
}
.cs-field {
    flex: 1;
    min-width: 200px;
}
/* Several panels write a bare <label for="..."> instead of class="cs-label", so they
   opted out of the 6px below a label without meaning to. Style the element as well as
   the class, so correct-looking markup cannot render wrong. Inline styles still win,
   which is what keeps the flex checkbox labels laid out as their author intended. */
.cs-field > label {
    display: block;
    font-size: 13px;
    font-weight: 600;
    color: var(--csds-navy, #1a2332);
    margin-bottom: 6px;
}
.cs-label {
    display: block;
    font-size: 13px;
    font-weight: 600;
    color: var(--csds-navy, #1a2332);
    margin-bottom: 6px;
}
.cs-input,
/* THE ARROW. This rule used the `background` SHORTHAND to set #fff, and the shorthand resets
   background-image to none, which is where WordPress admin draws a select's chevron, as a data-URI
   background image. So every select inside a .cs-field rendered as a plain bordered box with no
   affordance at all: reported 2026-08-17 as "make this a drop down (with arrow)" about the firewall
   mode, but it was never specific to that field.

   Fixed by supplying the arrow ourselves rather than relying on the native one, and by using
   background-COLOR everywhere below so a later tint cannot wipe it out again. appearance:none is set
   deliberately: without it some engines draw their own arrow beside ours. */
.cs-field select {
    width: 100%;
    max-width: 400px;
    padding: 5px 30px 5px 8px;
    border: 1.5px solid #dce3ef;
    border-radius: 4px;
    font-size: 13px;
    background-color: #fff;
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath fill='%231a2332' d='M1.4 0 6 4.6 10.6 0 12 1.4 6 7.4 0 1.4z'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 10px center;
    background-size: 10px 7px;
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    color: var(--csds-navy, #1a2332);
    cursor: pointer;
}
.cs-hint {
    display: block;
    margin-top: 4px;
    font-size: 11px;
    color: var(--csds-success, #1db954);
    font-style: italic;
    padding-left: 8px;
    border-left: 3px solid var(--csds-success, #1db954);
}

/* ── Buttons ─────────────────────────────────────── */
.cs-btn-primary {
    background: linear-gradient(135deg, var(--csds-accent, #1a3a8f), var(--csds-accent, #1e6fd9));
    border: none;
    border-radius: 5px;
    color: #fff;
    font-size: 12px;
    font-weight: 700;
    padding: 6px 16px;
    cursor: pointer;
    transition: opacity .15s;
}
.cs-btn-primary:hover { opacity: .88; }
.cs-btn-orange {
    background: linear-gradient(135deg, #c45c00, #f47c20);
    border: none;
    border-radius: 5px;
    color: #fff;
    font-size: 12px;
    font-weight: 700;
    padding: 6px 16px;
    cursor: pointer;
    transition: opacity .15s;
}
.cs-btn-orange:hover { opacity: .88; }
.cs-btn-pink {
    background: linear-gradient(135deg, #b5348a, #d946a6);
    border: none;
    border-radius: 5px;
    color: #fff;
    font-size: 12px;
    font-weight: 700;
    padding: 6px 16px;
    cursor: pointer;
    transition: opacity .15s;
}
.cs-btn-pink:hover { opacity: .88; }
.cs-btn-secondary {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 6px 14px;
    background: #f0f4ff;
    color: var(--wp-admin-theme-color, #2271b1);
    border: 1.5px solid #c7d2fe;
    border-radius: 6px;
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    transition: background .15s;
}
.cs-btn-secondary:hover { background: #e0e8ff; }
.cs-pk-test-result { max-width: 220px; }

/* ── Settings saved indicator ────────────────────── */
.cs-settings-saved {
    color: var(--csds-success, #1db954);
    font-weight: 700;
    font-size: 12px;
    opacity: 0;
    transition: opacity 0.3s;
}
.cs-settings-saved.visible {
    opacity: 1;
}

/* ── SQL textarea ────────────────────────────────── */
.cs-sql-textarea {
    width: 100%;
    min-height: 80px;
    font-family: 'SF Mono', 'Fira Code', 'Courier New', monospace;
    font-size: 13px;
    line-height: 1.5;
    padding: 12px;
    border: 1.5px solid #1a2d6b;
    border-radius: 6px;
    background: #0d1b2a;
    color: #e0e0e0;
    resize: vertical;
    box-sizing: border-box;
}
.cs-sql-textarea:focus {
    outline: none;
    border-color: var(--csds-accent, #1e6fd9);
    box-shadow: 0 0 0 2px rgba(30,111,217,.25);
}

/* ── SQL results table ───────────────────────────── */
.cs-sql-table {
    width: 100%;
    border-collapse: collapse;
    font-family: 'SF Mono', 'Fira Code', monospace;
    font-size: 12px;
}
.cs-sql-table th {
    text-align: left;
    padding: 8px 10px;
    border-bottom: 2px solid var(--csds-accent, #1a3a8f);
    background: #f0f4ff;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--csds-accent, #1a3a8f);
    white-space: nowrap;
    position: sticky;
    top: 0;
}
.cs-sql-table td {
    padding: 6px 10px;
    border-bottom: 1px solid #f0f4ff;
    max-width: 500px;
    overflow: hidden;
    text-overflow: ellipsis;
    word-break: break-all;
}
.cs-sql-table tr:nth-child(even) { background: #f8faff; }
.cs-sql-table tr:hover td { background: #edf2ff; }

/* ── Quick query section ─────────────────────────── */
.cs-quick-group-label {
    font-size: 12px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--csds-accent, #1a3a8f);
    margin: 16px 0 8px;
    padding: 0;
}
.cs-quick-group-label:first-child {
    margin-top: 0;
}
.cs-quick-grid {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: 4px;
}
.cs-quick-btn {
    background: #f0f4ff;
    border: 1.5px solid #c5d2f0;
    border-radius: 5px;
    padding: 5px 14px;
    font-size: 12px;
    font-weight: 600;
    color: var(--csds-accent, #1a3a8f);
    cursor: pointer;
    transition: all .15s;
    white-space: nowrap;
}
.cs-quick-btn:hover {
    background: #dce6ff;
    border-color: var(--csds-accent, #1a3a8f);
}

/* ── Migrate toolbar ─────────────────────────────── */
.cs-migrate-toolbar {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 16px;
}
.cs-migrate-toolbar .dashicons {
    font-size: 16px;
    width: 16px;
    height: 16px;
    line-height: 16px;
    margin-top: 2px;
}
.cs-migrate-hint {
    color: #aaa;
    font-style: italic;
    text-align: center;
    padding: 30px 0;
    font-size: 13px;
}
.cs-status {
    font-size: 12px;
    color: #888;
}

/* ════════════════════════════════════════════════════
   LOGIN SECURITY TAB
   ════════════════════════════════════════════════════ */

/* ── Shared description text ──────────────────────── */
.cs-login-desc {
    color: #555;
    font-size: 13px;
    line-height: 1.6;
    margin: 0 0 18px;
}

/* ── Toggle switch ────────────────────────────────── */
/* Bare native checkboxes, every one NOT wrapped in the pill toggle below (CSP's
   Referrer-Policy/Permissions-Policy directives, the Featured Image Generator's frontend-
   button toggles, and others scattered across the plugin). Left unstyled, these render as
   the browser's own tiny native glyph, which on iOS Safari draws as a barely-legible solid
   square rather than a clear checkmark, reported as "badly formatted ticks" in two
   unrelated panels. This one rule fixes every instance at once; the more specific
   `.cs-toggle-label input[type="checkbox"] { display: none; }` rule below still wins on
   specificity for the pill toggles, so it does not touch those. */
input[type="checkbox"] {
    -webkit-appearance: none;
    appearance: none;
    width: 16px;
    height: 16px;
    border: 1.5px solid #94a3b8;
    border-radius: 4px;
    background: #fff;
    cursor: pointer;
    flex-shrink: 0;
    margin: 0;
    position: relative;
    vertical-align: middle;
}
input[type="checkbox"]:checked {
    background: var(--csds-accent, #1e6fd9);
    border-color: var(--csds-accent, #1e6fd9);
}
/* Core's forms.css draws its own SVG tick on :checked::before, with a negative margin. Left on,
   it sat over this ::after tick, offset, and every checkbox showed two ticks. One tick. */
input[type="checkbox"]:checked::before {
    content: none;
    display: none;
}
input[type="checkbox"]:checked::after {
    content: '';
    position: absolute;
    left: 4px;
    top: 0;
    width: 5px;
    height: 9px;
    border: solid #fff;
    border-width: 0 2px 2px 0;
    transform: rotate(45deg);
}
input[type="checkbox"]:disabled {
    opacity: .5;
    cursor: not-allowed;
}

.cs-toggle-row {
    display: flex;
    align-items: center;
}
.cs-toggle-label {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    cursor: pointer;
    user-select: none;
}
.cs-toggle-label input[type="checkbox"] { display: none; }
.cs-toggle-switch {
    position: relative;
    width: 42px;
    height: 22px;
    background: #ccc;
    border-radius: 11px;
    transition: background .2s;
    flex-shrink: 0;
}
.cs-toggle-switch::after {
    content: '';
    position: absolute;
    top: 3px;
    left: 3px;
    width: 16px;
    height: 16px;
    background: #fff;
    border-radius: 50%;
    box-shadow: 0 1px 3px rgba(0,0,0,.25);
    transition: left .2s;
}
.cs-toggle-label input:checked ~ .cs-toggle-switch { background: var(--csds-accent, #1e6fd9); }
.cs-toggle-label input:checked ~ .cs-toggle-switch::after { left: 23px; }
.cs-toggle-text {
    font-size: 13px;
    font-weight: 600;
    color: var(--csds-navy, #1a2332);
}

/* ── Slug input row ───────────────────────────────── */
.cs-slug-row {
    display: flex;
    align-items: center;
    gap: 0;
    max-width: 520px;
}
.cs-slug-base {
    background: #f0f4ff;
    border: 1.5px solid #dce3ef;
    border-right: none;
    border-radius: 4px 0 0 4px;
    padding: 5px 10px;
    font-size: 12px;
    color: #888;
    white-space: nowrap;
    max-width: 240px;
    overflow: hidden;
    text-overflow: ellipsis;
}
.cs-slug-input {
    border-radius: 0 4px 4px 0 !important;
    border-left: 1.5px solid var(--csds-accent, #1e6fd9) !important;
    flex: 1;
    min-width: 120px;
}

/* ── 2FA method selector ──────────────────────────── */
.cs-2fa-method-group {
    display: flex;
    gap: 10px;
    flex-wrap: wrap;
    margin-top: 4px;
}
.cs-radio-label {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 8px 16px;
    border: 1.5px solid #dce3ef;
    border-radius: 6px;
    cursor: pointer;
    font-size: 13px;
    font-weight: 600;
    color: #555;
    transition: all .15s;
    background: #fff;
}
.cs-radio-label input[type="radio"] { display: none; }
.cs-radio-label:hover { border-color: var(--csds-accent, #1e6fd9); color: var(--csds-navy, #1a2332); }
.cs-radio-label.cs-radio-disabled {
    opacity: 0.45;
    cursor: not-allowed;
    pointer-events: none;
}
.cs-radio-label.active {
    border-color: var(--csds-accent, #1e6fd9);
    background: #edf2ff;
    color: var(--csds-accent, #1a3a8f);
    box-shadow: 0 0 0 2px rgba(30,111,217,.15);
}
.cs-radio-icon { font-size: 16px; }

/* ── Per-user 2FA rows ────────────────────────────── */
.cs-2fa-row {
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 14px 0;
}
.cs-2fa-row-icon { font-size: 28px; flex-shrink: 0; }
.cs-2fa-row-body { flex: 1; min-width: 0; }
.cs-2fa-row-title {
    font-size: 13px;
    font-weight: 700;
    color: var(--csds-navy, #1a2332);
    margin-bottom: 2px;
}
.cs-2fa-row-desc {
    font-size: 12px;
    color: #888;
    line-height: 1.5;
}
.cs-2fa-row-action {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-shrink: 0;
}
@media (max-width: 600px) {
    .cs-2fa-row {
        flex-wrap: wrap;
    }
    .cs-2fa-row-icon {
        align-self: flex-start;
        padding-top: 2px;
    }
    .cs-2fa-row-body {
        flex: 1 1 0;
        min-width: 0;
    }
    .cs-2fa-row-action {
        flex: 0 0 100%;
        padding-left: 44px; /* align under text, past icon + gap */
        flex-wrap: wrap;
    }
}
.cs-2fa-divider {
    border: none;
    border-top: 1px solid #f0f4ff;
    margin: 0;
}
.cs-2fa-badge {
    display: inline-block;
    padding: 3px 10px;
    border-radius: 20px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .03em;
}
.cs-2fa-badge-on      { background: #d1fae5; color: #065f46; }
.cs-2fa-badge-off     { background: #f3f4f6; color: var(--csds-muted, #6b7280); }
.cs-2fa-badge-pending { background: #fef3c7; color: #92400e; }

/* ── TOTP Setup Wizard ────────────────────────────── */
.cs-totp-wizard {
    margin-top: 20px;
    border-top: 2px solid #f0f4ff;
    padding-top: 20px;
}
.cs-totp-wizard-inner {
    background: #f8faff;
    border: 1.5px solid #dce3ef;
    border-radius: 8px;
    padding: 24px;
    max-width: 540px;
}
.cs-totp-wizard-title {
    font-size: 15px;
    font-weight: 700;
    color: var(--csds-navy, #1a2332);
    margin: 0 0 18px;
}
.cs-totp-steps {}
.cs-totp-step {
    font-size: 13px;
    color: #444;
    line-height: 1.6;
    display: flex;
    gap: 10px;
    align-items: flex-start;
}
.cs-totp-step-num {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    background: var(--csds-accent, #1e6fd9);
    color: #fff;
    border-radius: 50%;
    font-size: 11px;
    font-weight: 700;
    flex-shrink: 0;
    margin-top: 1px;
}
.cs-totp-qr-wrap {
    margin: 14px 0 0 32px;
    min-height: 220px;
    display: flex;
    align-items: flex-start;
}
.cs-totp-qr-loading {
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 13px;
    color: #888;
    padding: 16px 0;
}
.cs-totp-qr-img {
    width: 220px;
    height: 220px;
    border: 1.5px solid #dce3ef;
    border-radius: 6px;
    background: #fff;
    display: block;
}
.cs-totp-manual-wrap {
    margin: 10px 0 0 32px;
}
.cs-totp-secret-row {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 6px;
    flex-wrap: wrap;
}
.cs-totp-secret-row .cs-totp-secret { margin-top: 0; }
.cs-totp-copy-btn {
    padding: 5px 12px;
    background: #2d3a52;
    color: #a8d8a8;
    border: none;
    border-radius: 5px;
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    transition: background .15s;
    white-space: nowrap;
}
.cs-totp-copy-btn:hover { background: var(--csds-accent, #1e6fd9); color: #fff; }
.cs-totp-secret {
    display: inline-block;
    background: var(--csds-navy, #1a2332);
    color: #a8d8a8;
    padding: 6px 14px;
    border-radius: 5px;
    font-size: 14px;
    letter-spacing: 3px;
    margin-top: 6px;
    font-family: 'SF Mono','Fira Code','Courier New',monospace;
    user-select: all;
    cursor: text;
}
.cs-totp-verify-row {
    display: flex;
    gap: 10px;
    align-items: center;
    margin: 14px 0 0 32px;
    flex-wrap: wrap;
}
.cs-totp-code-input {
    width: 120px !important;
    font-size: 20px !important;
    text-align: center;
    letter-spacing: 4px;
    font-family: 'SF Mono','Fira Code','Courier New',monospace !important;
    padding: 6px 8px !important;
}
.cs-totp-verify-msg {
    margin: 10px 0 0 32px;
    font-size: 13px;
    line-height: 1.5;
}

/* ── Passkey info box ─────────────────────────────── */
/* ── Email pending / port warning notices ────────── */
.cs-email-pending-msg {
    margin-top: 6px;
}
.cs-pending-notice {
    display: inline-block;
    font-size: 12px;
    color: #92400e;
    background: #fef3c7;
    border: 1px solid #fde68a;
    border-radius: 4px;
    padding: 4px 10px;
    line-height: 1.5;
}
.cs-email-port-warn {
    margin-top: 10px;
    padding: 10px 14px;
    background: #fff7ed;
    border: 1.5px solid #fed7aa;
    border-left: 4px solid #f47c20;
    border-radius: 5px;
    font-size: 12px;
    color: #7c2d12;
    line-height: 1.6;
    max-width: 560px;
}

.cs-passkey-info p {
    font-size: 13px;
    color: #555;
    line-height: 1.7;
    margin: 0 0 12px;
}
.cs-passkey-info p:last-of-type { margin-bottom: 0; }

/* ── Passkey list ── */
.cs-pk-list {
    margin: 8px 0 0 44px;
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.cs-pk-item {
    display: flex;
    align-items: center;
    gap: 10px;
    background: var(--csds-surface-2, #f8fafc);
    border: 1px solid var(--csds-border, #e2e8f0);
    border-radius: 7px;
    padding: 8px 12px;
    font-size: 13px;
    flex-wrap: wrap;
}
.cs-pk-icon  { font-size: 16px; flex-shrink: 0; }
.cs-pk-name  { flex: 1; min-width: 80px; font-weight: 600; color: #1a202c; }
.cs-pk-date  { color: var(--csds-on-dark-mute, #94a3b8); font-size: 12px; white-space: nowrap; }
.cs-pk-item .cs-btn-secondary,
.cs-pk-item .cs-btn-pink { flex-shrink: 0; }

/* ── Passkey wizard ── */
.cs-pk-wizard { margin-top: 14px; }
.cs-pk-wizard-inner {
    background: var(--csds-surface-2, #f8fafc);
    border: 1.5px solid #c7d2fe;
    border-radius: 10px;
    padding: 20px 22px;
    max-width: 560px;
}
.cs-pk-wizard-title {
    font-size: 15px;
    font-weight: 700;
    color: #1e1b4b;
    margin: 0 0 8px;
}
.cs-pk-wizard-desc {
    font-size: 13px;
    color: #4b5563;
    margin: 0 0 14px;
    line-height: 1.5;
}
.cs-pk-name-row {
    display: flex;
    gap: 8px;
    align-items: center;
    flex-wrap: wrap;
}
.cs-pk-name-input {
    flex: 1;
    min-width: 160px;
}
.cs-pk-wizard-status {
    margin-top: 10px;
    padding: 8px 12px;
    border-radius: 6px;
    font-size: 13px;
    font-weight: 500;
}

/* ── Email-verified modal ───────────────────────── */
.cs-modal-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,.52);
    z-index: 999999;
    display: flex;
    align-items: center;
    justify-content: center;
}
.cs-modal-card {
    background: #fff;
    border-radius: 18px;
    padding: 44px 52px 36px;
    text-align: center;
    max-width: 420px;
    width: 90%;
    box-shadow: 0 24px 64px rgba(0,0,0,.28);
    animation: cs-modal-in .25s cubic-bezier(.34,1.4,.64,1);
}
@keyframes cs-modal-in {
    from { opacity: 0; transform: scale(.88) translateY(20px); }
    to   { opacity: 1; transform: none; }
}
.cs-modal-icon   { font-size: 68px; line-height: 1; margin-bottom: 18px; }
.cs-modal-title  { font-size: 22px; font-weight: 800; margin: 0 0 10px; color: #111827; }
.cs-modal-msg    { font-size: 14px; color: #555; margin: 0 0 28px; line-height: 1.6; }
.cs-modal-btn    { min-width: 140px; }
.cs-modal-auto   { font-size: 12px; color: #aaa; margin: 12px 0 0; }

/* ── Server Logs tab ─────────────────────────────── */
.cs-logs-sources {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    padding: 12px 0 4px;
}
.cs-log-src-btn {
    background: #f0f4ff;
    border: 1px solid #c7d2fe;
    border-radius: 20px;
    color: var(--csds-text-2, #334155);
    cursor: pointer;
    font-size: 12px;
    font-weight: 600;
    padding: 5px 14px;
    transition: background .15s, border-color .15s;
    display: inline-flex;
    align-items: center;
    gap: 5px;
}
.cs-log-src-btn::after {
    content: '';
    display: inline-block;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--csds-border-strong, #cbd5e1);
    flex-shrink: 0;
}
.cs-log-src-btn.status-ok::after          { background: var(--csds-success, #22c55e); }
.cs-log-src-btn.status-not-found          { opacity: .55; }
.cs-log-src-btn.status-not-found::after   { background: var(--csds-on-dark-mute, #94a3b8); }
.cs-log-src-btn.status-permission-denied::after { background: var(--csds-warn, #f59e0b); }
.cs-log-src-btn.status-empty::after       { background: #60a5fa; }
.cs-log-src-btn:hover  { background: #e0e7ff; border-color: #818cf8; }
.cs-log-src-btn:focus  { outline: none; box-shadow: none; }
.cs-log-src-btn.active { background: var(--csds-accent, #1a3a8f); border-color: var(--csds-accent, #1a3a8f); color: #fff; }
.cs-log-src-btn.active::after { background: rgba(255,255,255,.7); }

.cs-logs-toolbar {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 12px;
}
.cs-logs-search {
    border: 1px solid var(--csds-border, #e2e8f0);
    border-radius: 4px;
    font-size: 12px;
    padding: 5px 10px;
    width: 220px;
    min-width: 120px;
}
.cs-logs-level-sel {
    border: 1px solid var(--csds-border, #e2e8f0);
    border-radius: 4px;
    font-size: 12px;
    padding: 5px 8px;
}
.cs-logs-status-msg { font-size: 12px; color: var(--csds-muted, #64748b); }
.cs-logs-auto-label { font-size: 12px; color: var(--csds-muted, #64748b); margin-left: auto; display: flex; align-items: center; gap: 5px; cursor: pointer; }

.cs-logs-viewer {
    background: #0f1117;
    border-radius: 6px;
    font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
    font-size: 12px;
    line-height: 1.55;
    margin-top: 12px;
    max-height: 620px;
    min-height: 200px;
    overflow-y: auto;
    padding: 12px 16px;
    color: #d4d4d8;
}
.cs-logs-placeholder { color: #4b5563; padding: 40px 0; text-align: center; font-family: inherit; }
.cs-log-line { border-bottom: 1px solid rgba(255,255,255,.04); padding: 2px 0; word-break: break-all; white-space: pre-wrap; }
.cs-log-line.level-emerg  { color: #ff4d4f; font-weight: 700; }
.cs-log-line.level-alert  { color: #ff7875; font-weight: 600; }
.cs-log-line.level-crit   { color: #f87171; }
.cs-log-line.level-error  { color: #fca5a5; }
.cs-log-line.level-warn   { color: #fbbf24; }
.cs-log-line.level-notice { color: #60a5fa; }
.cs-log-line.level-info   { color: #a3e635; }
.cs-log-line.level-debug  { color: var(--csds-muted, #6b7280); }
.cs-log-line.level-default { color: #d4d4d8; }

/* ── Generic notice boxes (used across multiple tabs) ──────────── */
.cs-notice {
    border-radius: 6px;
    font-size: 13px;
    padding: 10px 14px;
    margin-top: 8px;
    line-height: 1.5;
}
.cs-notice-warn  { background: #fef3c7; border: 1px solid var(--csds-warn, #f59e0b); color: #78350f; }
.cs-notice-error { background: #fee2e2; border: 1px solid #f87171; color: #7f1d1d; }
.cs-notice-info  { background: #eff6ff; border: 1px solid #93c5fd; color: #1e40af; }

.cs-form-label {
    font-size: 12px;
    font-weight: 600;
    color: var(--csds-text-2, #374151);
}
.cs-text-input {
    border: 1px solid #d1d5db;
    border-radius: 5px;
    font-size: 13px;
    padding: 6px 10px;
    color: #111827;
    background: #fff;
}
.cs-text-input:focus {
    outline: none;
    border-color: var(--wp-admin-theme-color, #2271b1);
    box-shadow: 0 0 0 2px rgba(34,113,177,.15);
}

/* ═══════════════════════════════════════════════════════════════════
   Redis Cache Stats tab
   ═══════════════════════════════════════════════════════════════════ */

.cs-redis-loading {
    color: var(--csds-muted, #64748b);
    font-size: 13px;
    padding: 20px 0;
}
.cs-redis-stats-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
    gap: 12px;
    margin-top: 16px;
}
.cs-redis-card-wide { grid-column: span 2; }
@media (max-width: 640px) { .cs-redis-card-wide { grid-column: span 1; } }

.cs-redis-stat-card {
    background: var(--csds-surface-2, #f8fafc);
    border: 1px solid var(--csds-border, #e2e8f0);
    border-radius: 8px;
    padding: 14px 16px;
}
.cs-redis-stat-label {
    font-size: 11px;
    font-weight: 600;
    color: var(--csds-muted, #64748b);
    text-transform: uppercase;
    letter-spacing: .04em;
    margin-bottom: 6px;
}
.cs-redis-stat-value {
    font-size: 22px;
    font-weight: 700;
    color: var(--csds-navy, #1e293b);
    line-height: 1.1;
}
.cs-redis-stat-value.cs-redis-sm { font-size: 15px; padding-top: 4px; }
.cs-redis-stat-sub {
    font-size: 11px;
    color: var(--csds-on-dark-mute, #94a3b8);
    margin-top: 4px;
}
/* Hit rate colours */
.cs-redis-hit-rate.cs-redis-good { color: var(--csds-success, #15803d); }
.cs-redis-hit-rate.cs-redis-warn { color: #b45309; }
.cs-redis-hit-rate.cs-redis-bad  { color: var(--csds-danger, #dc2626); }

/* Memory progress bar */
.cs-redis-progress-wrap {
    background: var(--csds-border, #e2e8f0);
    border-radius: 4px;
    height: 6px;
    margin-top: 8px;
    overflow: hidden;
}
.cs-redis-progress-bar {
    height: 100%;
    border-radius: 4px;
    transition: width .4s ease;
}
.cs-bar-green { background: var(--csds-success, #22c55e); }
.cs-bar-amber { background: var(--csds-warn, #f59e0b); }
.cs-bar-red   { background: #ef4444; }

/* Actions row */
.cs-redis-actions {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
    margin-top: 20px;
    padding-top: 16px;
    border-top: 1px solid var(--csds-border, #e2e8f0);
}
.cs-btn-danger {
    background: linear-gradient(135deg, #991b1b, var(--csds-danger, #dc2626));
    border: none;
    border-radius: 5px;
    color: #fff;
    font-size: 12px;
    font-weight: 700;
    padding: 6px 16px;
    cursor: pointer;
    transition: opacity .15s;
}
.cs-btn-danger:hover { opacity: .88; }
.cs-redis-flush-msg {
    font-size: 12px;
    color: var(--csds-muted, #64748b);
    margin-left: 4px;
}
.cs-redis-flush-msg.cs-flush-ok  { color: var(--csds-success, #15803d); font-weight: 600; }
.cs-redis-flush-msg.cs-flush-err { color: var(--csds-danger, #dc2626); font-weight: 600; }

/* ═══════════════════════════════════════════════════════════════════
   Plugin Vulnerability Scan tab
   ═══════════════════════════════════════════════════════════════════ */

.cs-security-key-row {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: 16px;
}
.cs-security-scan-row {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
    margin-bottom: 20px;
}
.cs-vuln-inline-msg {
    display: block;
    font-size: 12px;
    color: var(--csds-muted, #64748b);
    margin-top: 5px;
}
.cs-vuln-inline-msg.cs-vuln-msg-ok  { color: var(--csds-success, #15803d); font-weight: 600; }
.cs-vuln-inline-msg.cs-vuln-msg-err { color: var(--csds-danger, #dc2626); font-weight: 600; }

/* ── Scan progress bar ───────────────────────────────────────────── */
.cs-scan-progress {
    display: none;
    height: 4px;
    background: var(--csds-border, #e2e8f0);
    border-radius: 2px;
    overflow: hidden;
    margin-top: 8px;
}
.cs-scan-progress.is-active { display: block; }
.cs-scan-progress-fill {
    height: 100%;
    width: 0%;
    border-radius: 2px;
    background: linear-gradient(90deg, var(--csds-accent, #3b82f6), var(--csds-accent-2, #6366f1));
    transition: width 2.8s ease;
}
.cs-scan-progress-fill.deep { background: linear-gradient(90deg, #7c3aed, #9333ea); }

/* Summary bar */
.cs-vuln-summary-bar {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 16px;
    background: var(--csds-surface-2, #f8fafc);
    border: 1px solid var(--csds-border, #e2e8f0);
    border-radius: 6px;
    padding: 10px 16px;
    font-size: 13px;
    margin-bottom: 14px;
}
.cs-vuln-sum-bad  { color: var(--csds-danger, #dc2626); }
.cs-vuln-sum-good { color: var(--csds-success, #15803d); }
.cs-vuln-sum-warn { color: #b45309; }

/* Clean state */
.cs-vuln-clean {
    text-align: center;
    padding: 40px 20px;
    font-size: 15px;
    color: var(--csds-success, #15803d);
    font-weight: 600;
}
.cs-vuln-clean-icon { font-size: 32px; display: block; margin-bottom: 8px; }

/* Plugin cards */
.cs-vuln-card {
    border: 1px solid var(--csds-border, #e2e8f0);
    border-radius: 8px;
    margin-bottom: 10px;
    overflow: hidden;
}
.cs-vuln-card-alert { border-color: #fca5a5; }
.cs-vuln-card-header {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 14px;
    background: var(--csds-surface-2, #f8fafc);
    flex-wrap: wrap;
}
.cs-vuln-card-alert .cs-vuln-card-header { background: #fff5f5; }

.cs-vuln-name    { font-weight: 700; font-size: 13px; color: var(--csds-navy, #1e293b); flex: 1; min-width: 120px; }
.cs-vuln-version { font-size: 12px; color: var(--csds-muted, #64748b); font-family: monospace; }
.cs-vuln-outdated-tag { color: #b45309; font-weight: 600; font-family: sans-serif; }

.cs-vuln-badge {
    font-size: 11px;
    font-weight: 700;
    padding: 2px 8px;
    border-radius: 20px;
    white-space: nowrap;
}
.cs-vuln-badge-danger { background: #fee2e2; color: var(--csds-danger, #dc2626); }
.cs-vuln-badge-warn   { background: #fef3c7; color: #b45309; }
.cs-vuln-badge-ok     { background: #dcfce7; color: var(--csds-success, #15803d); }

/* Vulnerability list inside a card */
.cs-vuln-list { padding: 8px 14px 12px; }
.cs-vuln-item {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    padding: 6px 0;
    border-bottom: 1px solid #f1f5f9;
    flex-wrap: wrap;
    font-size: 12px;
}
.cs-vuln-item:last-child { border-bottom: none; }

.cs-vuln-sev {
    font-size: 10px;
    font-weight: 800;
    padding: 2px 7px;
    border-radius: 3px;
    white-space: nowrap;
    flex-shrink: 0;
    margin-top: 1px;
}
.cs-vuln-sev-critical { background: #7f1d1d; color: #fff; }
.cs-vuln-sev-high     { background: var(--csds-danger, #dc2626); color: #fff; }
.cs-vuln-sev-medium   { background: var(--csds-warn, #f59e0b); color: #fff; }
.cs-vuln-sev-low      { background: var(--csds-success, #22c55e); color: #fff; }
.cs-vuln-sev-unknown  { background: var(--csds-on-dark-mute, #94a3b8); color: #fff; }

.cs-vuln-title { flex: 1; color: var(--csds-navy, #1e293b); min-width: 100px; }
.cs-vuln-fix   { font-size: 11px; color: var(--csds-success, #15803d); white-space: nowrap; margin-left: auto; }
.cs-vuln-no-fix { color: var(--csds-danger, #dc2626) !important; }
.cs-vuln-ref    {
    font-size: 11px;
    color: var(--wp-admin-theme-color, #2271b1);
    text-decoration: none;
    white-space: nowrap;
}
.cs-vuln-ref:hover { text-decoration: underline; }
.cs-vuln-results { margin-top: 4px; }

/* ── Brute-force failed login log ─────────────────────────────────────── */
.cs-bf-log-wrap {
    margin-top: 28px;
    border-top: 1px solid #e8edf5;
    padding-top: 20px;
}
.cs-bf-log-header {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 16px;
}
.cs-bf-log-title {
    font-size: 13px;
    font-weight: 700;
    color: var(--csds-navy, #1a2332);
}
.cs-bf-log-total {
    font-size: 11px;
    color: #666;
    background: #f0f4f8;
    border-radius: 10px;
    padding: 1px 8px;
}
.cs-bf-layout {
    display: flex;
    gap: 24px;
    align-items: flex-start;
}
.cs-bf-chart {
    display: flex;
    gap: 4px;
    align-items: flex-end;
    flex: 0 0 65%;
    min-width: 200px;
    padding-right: 4px;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}
@media (max-width: 700px) {
    .cs-bf-layout    { flex-direction: column; }
    .cs-bf-chart     { flex: none; width: 100%; min-width: 0; }
    .cs-bf-table-wrap { width: 100%; }
}
.cs-bf-yaxis {
    position: sticky;
    left: 0;
    z-index: 1;
    background: #fff;
    align-self: flex-start;
    flex-shrink: 0;
    width: auto;
    min-width: 36px;
    height: 120px;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    align-items: flex-end;
    padding-right: 5px;
    font-size: 11px;
    font-weight: 700;
    color: #555;
    user-select: none;
    line-height: 1;
    box-sizing: border-box;
}
.cs-bf-ytick {
    display: block;
}
/* The map layer toggles live INSIDE .cs-section-header-purple, a dark gradient. Both states were
   built for a light background and neither was readable on it: unchecked was #64748b grey on purple,
   and checked set --text to a dark ink (#92400e, #991b1b, #5b21b6) over a 10-12% translucent tint,
   so the "solid dark ancestor" showing through was the purple itself. Reported 2026-08-17 as simply
   "cant read the text".

   This is the recurring contrast bug named in CLAUDE.md, in its less obvious direction: the rule is
   usually quoted as "never light text on a light background", but a translucent chip inherits its
   real backdrop from whatever it sits on, and here that backdrop is dark. So both states now use
   light text, and the category colour is carried by the dot and the border rather than the ink. */
.cs-map-layer-toggle {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 3px 10px 3px 7px;
    border-radius: 20px;
    border: 1.5px solid rgba(255, 255, 255, 0.40);
    background: rgba(255, 255, 255, 0.14);
    font-size: 11px;
    font-weight: 600;
    color: #eef2f8;
    cursor: pointer;
    user-select: none;
    transition: border-color .15s, background .15s, color .15s;
}
.cs-map-layer-toggle input[type="checkbox"] {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
    pointer-events: none;
}
.cs-map-layer-dot {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: #d1d5db;
    flex-shrink: 0;
    transition: background .15s;
}
.cs-map-layer-toggle:has(input:checked) {
    border-color: var(--border);
    background: var(--bg);
    color: var(--text);
}
.cs-map-layer-toggle:has(input:checked) .cs-map-layer-dot {
    background: var(--dot);
}
.cs-bf-day {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    min-width: 0;
}
.cs-bf-bar-track {
    width: 100%;
    height: 120px;
    display: flex;
    align-items: flex-end;
    border-bottom: 2px solid #d1d5db;
}
.cs-bf-bar {
    width: 100%;
    min-height: 3px;
    background: var(--csds-on-dark-mute, #94a3b8);
    border-radius: 3px 3px 0 0;
    transition: height .3s;
    cursor: default;
}
.cs-bf-bar-zero { background: var(--csds-success, #22c55e); }
.cs-bf-bar-mid  { background: var(--csds-warn, #f59e0b); }
.cs-bf-bar-high { background: var(--csds-danger, #e53e3e); }
.cs-bf-day-label {
    font-size: 9px;
    color: #888;
    margin-top: 4px;
    text-align: center;
    white-space: nowrap;
}
.cs-bf-table-wrap {
    flex: 1;
    min-width: 0;
    max-height: 165px;
    overflow-x: auto;
    overflow-y: auto;
    border: 1px solid #e8edf5;
    border-radius: 4px;
}
.cs-bf-table {
    width: 100%;
    min-width: max-content;
    border-collapse: collapse;
    font-size: 12px;
}
.cs-bf-th {
    background: #f5f7fb;
    padding: 6px 10px;
    text-align: left;
    font-size: 11px;
    font-weight: 600;
    color: #444;
    border-bottom: 1px solid #e8edf5;
    white-space: nowrap;
}
.cs-bf-td {
    padding: 5px 10px;
    border-bottom: 1px solid #f0f4f8;
    color: #333;
    vertical-align: middle;
}
.cs-bf-td-time { color: #888; white-space: nowrap; }
.cs-bf-td-user { font-family: 'Consolas', monospace; font-size: 11px; }
.cs-bf-td-ip   { color: #555; font-family: 'Consolas', monospace; font-size: 11px; }
.cs-bf-empty,
.cs-bf-loading { padding: 16px; color: #aaa; font-size: 12px; text-align: center; }

/* ── Security AI settings panel ───────────────────────────────────────── */
.cs-sec-settings { display: flex; flex-direction: column; gap: 16px; }
.cs-sec-row {
    display: grid;
    grid-template-columns: 120px 1fr;
    gap: 8px 14px;
    align-items: center;
    margin-bottom: 14px;
}
.cs-sec-row-prompt { align-items: start; }
.cs-sec-label {
    font-size: 12px;
    font-weight: 600;
    color: #475569;
    white-space: nowrap;
}
.cs-sec-control { display: flex; flex-direction: column; gap: 4px; }
.cs-sec-key-input { width: 420px; max-width: 100%; font-family: monospace; font-size: 12px; }
.cs-sec-select { width: 320px; max-width: 100%; font-size: 12px; }

@media (max-width: 600px) {
    /* Prevent anything inside the app from creating horizontal scroll */
    #cs-app,
    #cs-app .cs-panel,
    #cs-app .cs-panel-body {
        max-width: 100%;
        overflow-x: hidden;
    }
    .cs-panel-body {
        padding: 14px 10px;
    }
    /* Stack label above control */
    .cs-sec-row {
        grid-template-columns: 1fr;
        max-width: 100%;
    }
    .cs-sec-label {
        white-space: normal;
        margin-bottom: 0;
    }
    /* Full-width inputs and selects */
    .cs-sec-control,
    .cs-sec-control > * {
        max-width: 100%;
        width: 100%;
        box-sizing: border-box;
    }
    /* Flex rows inside controls wrap instead of overflowing */
    .cs-sec-control > div {
        flex-wrap: wrap;
    }
    .cs-sec-key-input,
    .cs-sec-select {
        width: 100%;
        max-width: 100%;
        box-sizing: border-box;
    }
    /* Hint text and inline code must wrap */
    .cs-hint,
    .cs-hint * {
        word-break: break-word;
        overflow-wrap: break-word;
        white-space: normal;
        max-width: 100%;
    }
}
.cs-sec-prompt-area {
    width: 100%;
    max-width: 680px;
    font-family: 'Consolas', monospace;
    font-size: 11px;
    line-height: 1.55;
    resize: vertical;
    border: 1px solid var(--csds-border-strong, #cbd5e1);
    border-radius: 4px;
    padding: 8px 10px;
    color: var(--csds-navy, #1e293b);
    background: var(--csds-surface-2, #f8fafc);
}
.cs-sec-prompt-area:focus { outline: none; border-color: var(--csds-accent-2, #6366f1); background: #fff; }
.cs-sec-key-status { font-size: 12px; font-weight: 600; }
.cs-sec-key-status.ok  { color: var(--csds-success, #15803d); }
.cs-sec-key-status.err { color: var(--csds-danger, #dc2626); }
.cs-sec-divider { border: none; border-top: 1px solid var(--csds-border, #e2e8f0); margin: 20px 0; }
.cs-hint { font-size: 11px; color: var(--csds-on-dark-mute, #94a3b8); }
.cs-hint a { color: var(--csds-accent-2, #6366f1); text-decoration: none; }
.cs-hint a:hover { text-decoration: underline; }

/* ── AI Security Audit report ─────────────────────────────────────────── */
.cs-audit-header {
    display: flex;
    align-items: center;
    gap: 20px;
    padding: 16px 0 20px;
    border-bottom: 1px solid var(--csds-border, #e2e8f0);
    margin-bottom: 20px;
    flex-wrap: wrap;
}
.cs-audit-score-circle {
    width: 72px;
    height: 72px;
    border-radius: 50%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    border: 3px solid currentColor;
}
.cs-audit-score-num  { font-size: 24px; font-weight: 800; line-height: 1; }
.cs-audit-score-lbl  { font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: .5px; margin-top: 1px; }
.cs-audit-score-excellent { color: var(--csds-success, #15803d); }
.cs-audit-score-good      { color: var(--csds-success, #16a34a); }
.cs-audit-score-fair      { color: var(--csds-warn, #d97706); }
.cs-audit-score-poor      { color: #ea580c; }
.cs-audit-score-critical  { color: var(--csds-danger, #dc2626); }

.cs-audit-meta { flex: 1; }
.cs-audit-summary-text { font-size: 13px; color: var(--csds-text-2, #334155); line-height: 1.6; margin: 0 0 6px; }
.cs-audit-meta-line { font-size: 11px; color: var(--csds-on-dark-mute, #94a3b8); }

.cs-audit-section { margin-bottom: 20px; }
.cs-audit-section-title {
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .6px;
    padding: 5px 10px;
    border-radius: 4px 4px 0 0;
    margin: 0;
}
/*
 * ONE SEVERITY PALETTE, shared with the scan-report modal in cs-vuln-scan.js.
 *
 * These two surfaces render the SAME findings and used to disagree about what a
 * severity looks like. Worst of it: `low` was painted with the success token, so
 * the colour that means "we checked and it was fine" everywhere else in this
 * product was also the colour of a real finding. `high` was full danger red,
 * leaving nothing louder for `critical` than a darker shade of the same hue.
 *
 * Each severity gets an accent (dark, carries light text) and a tint (light,
 * carries dark text). They are not interchangeable: pairing a tint with light
 * text is the contrast bug this stylesheet keeps re-fixing, so every rule below
 * states its text colour rather than inheriting one.
 *
 * The accents match SEV in assets/cs-report.js, which draws the printed report
 * and the executive summary: white text clears 4.5:1 on every one, which the
 * old #ea580c, #d97706 and #ca8a04 did not, and low is blue so it can no longer
 * be mistaken for medium amber. tests/security-report-test.js checks the ratios.
 *
 * The icons repeat on each card on purpose. Once a reader has scrolled past the
 * section header, the tints alone are the only cue left, and amber and yellow are
 * not reliably distinguishable side by side.
 */
.cs-audit-section-title::before { margin-right: 7px; }
.cs-audit-sec-critical .cs-audit-section-title { background: #b91c1c; color: #fff; }
.cs-audit-sec-critical .cs-audit-section-title::before { content: "\1F6A8"; }
.cs-audit-sec-high     .cs-audit-section-title { background: #c2410c; color: #fff; }
.cs-audit-sec-high     .cs-audit-section-title::before { content: "\1F525"; }
.cs-audit-sec-medium   .cs-audit-section-title { background: #a16207; color: #fff; }
.cs-audit-sec-medium   .cs-audit-section-title::before { content: "\26A0\FE0F"; }
.cs-audit-sec-low      .cs-audit-section-title { background: #0369a1; color: #fff; }
.cs-audit-sec-low      .cs-audit-section-title::before { content: "\1F50E"; }
.cs-audit-sec-good     .cs-audit-section-title { background: #15803d; color: #fff; }
.cs-audit-sec-good     .cs-audit-section-title::before { content: "\2705"; }

.cs-audit-issue {
    border: 1px solid var(--csds-border, #e2e8f0);
    border-top: none;
    border-left-width: 4px;
    padding: 12px 14px;
    background: #fff;
}
.cs-audit-issue + .cs-audit-issue { border-top: 1px solid rgba(0, 0, 0, .06); }
.cs-audit-sec-critical .cs-audit-issue { background: #fef2f2; border-color: #fecaca; border-left-color: #b91c1c; }
.cs-audit-sec-high     .cs-audit-issue { background: #fff7ed; border-color: #fed7aa; border-left-color: #c2410c; }
.cs-audit-sec-medium   .cs-audit-issue { background: #fffbeb; border-color: #fde68a; border-left-color: #a16207; }
.cs-audit-sec-low      .cs-audit-issue { background: #f0f9ff; border-color: #bae6fd; border-left-color: #0369a1; }

.cs-audit-issue-title  { font-size: 13px; font-weight: 700; color: #0f172a; margin-bottom: 4px; }
.cs-audit-issue-title::before { margin-right: 6px; }
.cs-audit-sec-critical .cs-audit-issue-title::before { content: "\1F6A8"; }
.cs-audit-sec-high     .cs-audit-issue-title::before { content: "\1F525"; }
.cs-audit-sec-medium   .cs-audit-issue-title::before { content: "\26A0\FE0F"; }
.cs-audit-sec-low      .cs-audit-issue-title::before { content: "\1F50E"; }

.cs-audit-issue-detail { font-size: 12px; color: #374151; margin-bottom: 6px; line-height: 1.5; }
.cs-audit-issue-detail::before { content: "\1F50D"; margin-right: 6px; opacity: .75; }

/*
 * The remediation line, on white rather than on the card tint.
 *
 * It was green text on a green tint, which put the one sentence the reader is
 * most likely to ACT on in the palette that means "nothing to do here". Blue on
 * white separates the advice from both the finding and the passes.
 */
.cs-audit-issue-fix {
    font-size: 12px;
    color: #1e3a8a;
    background: #fff;
    border: 1px solid #bfdbfe;
    border-left: 3px solid #3b82f6;
    padding: 8px 11px;
    border-radius: 0 6px 6px 0;
    line-height: 1.5;
    white-space: pre-wrap;
}
.cs-audit-issue-fix::before { content: "\1F4A1"; margin-right: 6px; }
.cs-audit-good-item {
    display: flex;
    gap: 8px;
    padding: 8px 14px;
    border: 1px solid #d1fae5;
    border-top: none;
    background: #f0fdf4;
    font-size: 12px;
    color: var(--csds-success, #15803d);
}
.cs-audit-good-item:first-of-type { border-top: 1px solid #d1fae5; margin-top: 0; }
.cs-audit-good-check { flex-shrink: 0; }
.cs-audit-empty { font-size: 12px; color: var(--csds-on-dark-mute, #94a3b8); padding: 10px 14px; border: 1px solid var(--csds-border, #e2e8f0); border-top: none; }

.cs-scan-col-header { margin-bottom: 10px; }
.cs-scan-col-title  { display: block; font-size: 13px; font-weight: 600; color: var(--csds-navy, #1e293b); margin-bottom: 2px; }
.cs-scan-col-hint   { display: block; font-size: 11px; color: var(--csds-muted, #64748b); }
.cs-btn-deep { background: #6d28d9 !important; border-color: #5b21b6 !important; }
.cs-btn-deep:hover:not(:disabled) { background: #5b21b6 !important; }

/* ── Panel intro ──────────────────────────────────────────────────────────
   Two adjacent panels (AI Cyber Audit, Active Vulnerability Verification) both
   offered a target field and a Run button and never said on the page how they
   differed or why you would pick one, the distinction existed only behind their
   Explain… modals. These read as Step 1 / Step 2 of one workflow, so they are
   numbered as such. Light solid background, therefore dark text (see the styling
   rule in CLAUDE.md): #0f172a for the emphasis, #374151 for the body. */
.cs-panel-intro {
    font-size: 12.5px;
    line-height: 1.6;
    color: #374151;
    background: #f8fafc;
    border: 1px solid #e2e8f0;
    border-left: 3px solid #94a3b8;
    border-radius: 0 6px 6px 0;
    padding: 9px 13px;
    margin: 0 0 14px;
}
.cs-panel-intro strong { color: #0f172a; }
.cs-panel-intro--step1 { border-left-color: #16a34a; }
.cs-panel-intro--step2 { border-left-color: #dc2626; }

/* ── Step badge, in the panel title bar ───────────────────────────────────
   "Step 1" / "Step 2" started inside .cs-panel-intro, where they were the
   first words of a 12.5px grey paragraph and read as prose rather than as a
   sequence, you had to already be reading to notice the numbering existed.
   The title bar is where the eye lands, so the number lives there now and the
   intro keeps only the explanation ("Finds what might be wrong.").

   The bar is a dark gradient, so this is a LIGHT SOLID chip with DARK text per
   the contrast rule in CLAUDE.md. The step colours are the 700-weight green and
   red (#15803d / #b91c1c), not the 600 used for the intro's left border: on a
   #f8fafc chip at 11px, 600-weight lands near 3:1 and 700 clears 4.5:1. The
   chip also cancels the header's inherited uppercase/letter-spacing, which
   turned "Step 1" into a stretched "S T E P  1". */
.cs-step-badge {
    flex-shrink: 0;
    background: #f8fafc;
    color: #0f172a;
    font-size: 11px;
    font-weight: 800;
    text-transform: none;
    letter-spacing: .01em;
    line-height: 1.2;
    padding: 3px 9px;
    border-radius: 4px;
    box-shadow: inset 0 0 0 1px rgba(15, 23, 42, 0.18);
    white-space: nowrap;
}
.cs-step-badge--1 { color: #15803d; }
.cs-step-badge--2 { color: #b91c1c; }

/* ── Collapsible section toggle pill ─────────────────────────── */
/* Solid indigo, matching the "Details (n findings)" summary pill in
   cs-vuln-scan.js, so every disclosure toggle in the tab reads as the same
   control. It used to be a light lavender rounded pill, which made two toggles
   doing the same job on one page look like two unrelated widgets. */
.cs-details-toggle {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    font-weight: 700;
    color: #fff;
    background: var(--csds-accent-2, #6366f1);
    border: 1px solid #4f46e5;
    border-radius: 7px;
    padding: 8px 16px;
    white-space: nowrap;
    flex-shrink: 0;
    margin-left: 8px;
    cursor: pointer;
    user-select: none;
    box-shadow: 0 1px 2px rgba(0, 0, 0, .15);
}
/* CSS-driven text for <details>/<summary> toggles */
.cs-details-toggle::after       { content: "Show ▼"; }
details[open] > summary .cs-details-toggle::after { content: "Hide ▲"; }
/* JS-driven variant (violation log, active-scan audit trail): the span carries its
   own text, so the auto-generated suffix must be suppressed. The [open] selector
   above scores (0,2,3) and this one scored (0,1,1), so suppression held while the
   panel was SHUT and lost the moment it opened, which is why the audit-trail pill
   read "Active scan audit trail (2 scans)Hide ▲" once expanded. Both states must be
   listed to outrank it. Only bites inside a real <details>: the CSP violation pill
   uses the same class in a plain div with a JS toggle, so it never doubled. */
.cs-details-toggle--js::after,
details[open] > summary .cs-details-toggle--js::after { content: none; }

/* Caret inside a native <details>/<summary> pill. The glyph used to be baked into
   the summary's text, so it pointed down whether the panel was open or shut and
   the one thing it was there to report, which state you are in, was the one
   thing it never said. There is no JS toggle to hook on a native <details>, so
   the rotation is CSS off the [open] attribute. Was already ID-scoped to
   #cs-scan-history-list; this generalises it to every caret in the class. */
.cs-scan-toggle-caret { display: inline-block; transition: transform .2s; }
details[open] > summary .cs-scan-toggle-caret { transform: rotate(180deg); }

/* ── Button geometry ──────────────────────────────────────────────────────
   Measured on the live page before changing anything: the deep-dive button was
   32px tall against the Download PDF button's 40px. Matching them therefore
   means making the deep one TALLER, not shorter, it reads as the bigger of the
   two because it is a solid filled block beside an outline button, which is
   visual weight rather than height.

   Radii were inconsistent: 5px on primary/orange, 6px on secondary, 2px on the
   core-styled buttons the plugin renders. All standardised to 8px. */
.cs-btn-primary,
.cs-btn-secondary,
.cs-btn-orange,
.cs-btn-deep,
.cs-audit-pdf-btn,
.csdt-history-pdf-btn { border-radius: 8px; }

/* Core-styled buttons inside the plugin's own tabs. Scoped to .cs-tab-content
   deliberately: an unscoped `.button` rule would restyle every button in
   wp-admin, including other plugins' screens. */
.cs-tab-content .button,
.cs-tab-content .button-secondary,
.cs-tab-content .button-primary { border-radius: 8px; }

/* Match the PDF button's 40px box. inline-flex keeps the label vertically
   centred once the height no longer comes from padding alone. */
.cs-btn-deep {
    min-height: 40px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

/* ── Wide data tables on a narrow screen ──────────────────────────────────────
 *
 * Reported from a phone: the firewall Rules table, Recent matches and the Activity
 * Log were "squashed or chopped off". Two separate faults, one root cause.
 *
 *  1. NO WAY TO REACH THE RIGHT-HAND COLUMNS. The tables are ~800px wide and the
 *     viewport is ~390px. Without a scroll container the browser squeezes what it
 *     can and clips the rest, so Addresses / Matched / Hits simply do not exist as
 *     far as the user is concerned. There was no scrollbar to find.
 *
 *  2. ENORMOUSLY TALL ROWS. The Path cell carried word-break:break-all, so one
 *     logged SQL-injection payload wrapped into a column two characters wide and
 *     set the height of the whole row. The visible left-hand cells are short, so
 *     what you see is a row of blank space with its content off-screen, which is
 *     how "why is this row so tall" and "chopped off" turned out to be the same bug.
 *
 * min-width keeps the columns at their natural size inside the scroller instead of
 * being compressed to fit, which is what made them unreadable in the first place.
 */
.csdt-table-scroll {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;  /* momentum scrolling on iOS */
    overscroll-behavior-x: contain;     /* don't chain the swipe to the page */
    max-width: 100%;
    margin: 0 0 18px;
}
.csdt-table-scroll > table {
    min-width: 720px;
    margin: 0;
}
.csdt-table-scroll--wide > table { min-width: 860px; }

/* Keep a visible scrollbar on touch devices, which otherwise hide it until a swipe
 * is already in progress, the affordance has to be there BEFORE you try. */
.csdt-table-scroll::-webkit-scrollbar { height: 8px; }
.csdt-table-scroll::-webkit-scrollbar-thumb {
    background: #cbd5e1;
    border-radius: 4px;
}
.csdt-table-scroll::-webkit-scrollbar-track { background: #f1f5f9; }

/* A one-line hint, shown only where the table cannot fit. Native scrollbars are
 * easy to miss on a phone and the columns beyond the edge are the interesting ones. */
.csdt-table-hint { display: none; }
@media (max-width: 900px) {
    .csdt-table-hint {
        display: block;
        font-size: 11px;
        color: #64748b;
        margin: 0 0 6px;
    }
}

/* Long values are truncated to one line rather than wrapped to twenty. The full
 * text stays available via the title attribute, and these cells are also the
 * reason rows were hundreds of pixels tall. */
.csdt-cell-path {
    max-width: 320px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.csdt-cell-path > code {
    background: none;
    padding: 0;
    font-size: 11px;
}
/* Rule IDs and addresses must not be broken mid-token either, a wrapped
 * "xss_reflect / ed" or "203.0 / .113.1 / 0" is what the squashing looked like. */
.csdt-nowrap { white-space: nowrap; }

/* ── Explain modal description ───────────────────────────────────────────────
   Moved here from CSDT_Perf_Monitor::get_explain_modal_css() on 2026-08-17. It was a static CSS
   string returned by a method on the performance class and appended to THIS stylesheet with
   wp_add_inline_style(). Same bytes, same request, one fewer indirection. */
.cs-explain-desc{color:#50575e;font-size:12px;line-height:1.7}
.cs-explain-desc p{margin:0 0 8px 0}
.cs-explain-desc p:last-child{margin-bottom:0}
.cs-explain-desc code{display:inline;background:#1e2430;color:#e8b86d;padding:1px 6px;border-radius:3px;font-family:ui-monospace,SFMono-Regular,Consolas,monospace;font-size:11px;white-space:nowrap;word-break:break-all}
.cs-explain-desc strong{color:#111827;font-weight:700}
.cs-explain-desc em{font-style:italic}
.cs-explain-desc a{color:#2271b1;text-decoration:underline}
.cs-explain-desc a:hover{color:#135e96}
.cs-explain-desc ul,.cs-explain-desc ol{margin:6px 0 0 0;padding-left:20px}
.cs-explain-desc li{margin-bottom:4px}
.cs-explain-desc h4{margin:10px 0 4px;font-size:12px;font-weight:700;color:#111827;text-transform:uppercase;letter-spacing:.04em}

/* ── Thumbnails tab ──────────────────────────────────────────────────────────
   Moved here from CSDT_Perf_Monitor::get_thumbnails_admin_css() on the same grounds. It was loaded
   only on the thumbnails tab and is now unconditional: ~50 lines of selectors scoped to that tab's
   own classes, which is not worth a conditional to save. */
.cs-thumb-cf-steps{display:flex;flex-direction:column;gap:12px;margin-top:10px}
.cs-thumb-cf-step{display:flex;gap:12px;align-items:flex-start}
.cs-thumb-cf-step-num{min-width:26px;height:26px;background:#e65100;color:#fff;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:700;flex-shrink:0;margin-top:2px}
.cs-thumb-cf-code{background:#1e1e1e;color:#e8e8e8;padding:10px 14px;border-radius:4px;font-size:12px;overflow-x:auto;white-space:pre-wrap;word-break:break-all;margin:6px 0}
.cs-thumb-report-hdr{display:flex;justify-content:space-between;align-items:center;padding:9px 14px;border-radius:4px;margin-bottom:10px;font-size:13px;font-weight:600}
.cs-thumb-pass-hdr{background:#edfaed;color:#276227}
.cs-thumb-warn-hdr{background:#fff8e5;color:#7a5a00}
.cs-thumb-fail-hdr{background:#fdf0f0;color:#8c2020}
.cs-thumb-tally{display:flex;gap:12px;font-size:13px}
.cs-thumb-section{border:1px solid #e0e0e0;border-radius:4px;margin-bottom:10px;overflow:hidden}
.cs-thumb-section-title{background:#f6f7f7;padding:6px 12px;font-size:12px;font-weight:700;color:#333;border-bottom:1px solid #e0e0e0;text-transform:uppercase;letter-spacing:.4px}
.cs-thumb-results-list{margin:0;padding:6px 10px;list-style:none}
/* Body inset for a .cs-thumb-section whose content is not a results list. Without it the
   content sits flush against the section's own border, which reads as a missing border
   rather than as missing padding. Same inset as .cs-thumb-results-list, deliberately. */
.cs-thumb-section-body{padding:6px 10px}
.cs-thumb-result{display:flex;gap:8px;padding:3px 0;font-size:12px;align-items:flex-start}
.cs-thumb-pass{color:#276227}
.cs-thumb-warn{color:#7a5a00}
.cs-thumb-fail{color:#8c2020}
.cs-thumb-fix{margin-top:3px;font-size:11px;color:#1a4a7a;background:#f0f6fc;border-left:3px solid #2271b1;padding:3px 7px;border-radius:0 3px 3px 0}
.cs-thumb-info{color:#555}
.cs-thumb-ua-grid{display:flex;flex-wrap:wrap;gap:8px;margin-top:8px}
.cs-thumb-ua-chip{padding:5px 12px;border-radius:20px;font-size:12px;font-weight:600}
.cs-thumb-ua-ok{background:#edfaed;color:#276227}
.cs-thumb-ua-fail{background:#fdf0f0;color:#8c2020}
.cs-thumb-ua-warn{background:#fff8e5;color:#7a5a00}
.cs-input-light-placeholder::placeholder{color:#bbb;font-weight:400}
.cs-thumb-posts-table{width:100%;border-collapse:collapse;font-size:13px}
.cs-thumb-posts-table th{background:#f6f7f7;padding:7px 10px;text-align:left;border-bottom:2px solid #ddd}
.cs-thumb-posts-table td{padding:7px 10px;border-bottom:1px solid #eee;vertical-align:top}
.cs-thumb-badge-ok{display:inline-block;background:#edfaed;color:#276227;padding:2px 8px;border-radius:10px;font-size:11px;font-weight:600}
.cs-thumb-badge-warn{display:inline-block;background:#fff8e5;color:#7a5a00;padding:2px 8px;border-radius:10px;font-size:11px;font-weight:600}
.cs-thumb-badge-fail{display:inline-block;background:#fdf0f0;color:#8c2020;padding:2px 8px;border-radius:10px;font-size:11px;font-weight:600}
.cs-thumb-audit-table{font-size:12px;width:100%;border-collapse:collapse}
.cs-thumb-audit-table th{background:#f6f7f7;padding:6px 10px;text-align:left;border-bottom:2px solid #ddd}
.cs-thumb-audit-table td{padding:6px 10px;border-bottom:1px solid #eee;vertical-align:top}
.cs-platform-grid{display:flex;flex-wrap:wrap;gap:10px}
.cs-platform-card{display:flex;align-items:flex-start;gap:8px;padding:10px 12px;border:2px solid #ddd;border-radius:6px;cursor:pointer;transition:border-color .15s,background .15s;min-width:160px;flex:1 1 auto;max-width:200px}
.cs-platform-card:hover{border-color:#2271b1}
.cs-platform-checked{border-color:#2271b1;background:#f0f6ff}
.cs-platform-card input{margin-top:2px;flex-shrink:0}
.cs-platform-card-body{display:flex;flex-direction:column;gap:2px}
.cs-platform-name{font-size:13px;font-weight:600;color:#333}
.cs-platform-dims{font-size:11px;color:#555}
.cs-platform-limit{font-size:11px;color:#888}
.cs-fix-modal-wrap{margin-top:8px;padding:10px 12px;background:#f6f7f7;border:1px solid #e0e0e0;border-radius:5px;font-size:12px}
.cs-fix-platform-row{display:flex;align-items:center;gap:8px;padding:4px 0;border-bottom:1px solid #ebebeb}
.cs-fix-platform-row:last-child{border-bottom:none}
.cs-fix-platform-label{min-width:90px;font-weight:600;color:#333;font-size:12px}
.cs-fix-platform-dims{color:#888;font-size:11px;min-width:80px}
.cs-fix-platform-status{font-size:11px;flex:1}
.cs-fix-preview-thumb{width:48px;height:28px;object-fit:cover;border-radius:2px;border:1px solid #ddd;flex-shrink:0}

/* ── Sub-sections inside a panel ─────────────────────────────────────────────
   Introduced 2026-08-17 when "TWO-FACTOR AUTHENTICATION" and "YOUR 2FA SETUP" were merged: one sets
   the site's policy, the other shows whether the person reading has complied with it, and as two
   panels they carried two headers, two Explain buttons and two coloured bars for one subject,
   reported as "this feels like a single panel".

   A sub-section is deliberately QUIETER than a panel header: a rule above it and a small heading, no
   coloured bar. It has to read as "still the same subject, next part" rather than competing with the
   panel's own header for the role of title. */
.cs-subsection {
    border-top: 1px solid #eef2f7;
    margin-top: 4px;
    padding: 14px 24px 20px;
}
.cs-subsection-head {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin-bottom: 10px;
}
.cs-subsection-head > span:first-child {
    font-size: 13px;
    font-weight: 700;
    color: #0f172a;
}
.cs-subsection-hint {
    font-size: 11px;
    color: #6b7280;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}
/* The Explain button keeps working inside a sub-section; it just sits at the end of the heading row. */
.cs-subsection-head [id^="cs-explain-btn-"] { margin-left: auto; }

/* ── Firewall mode ───────────────────────────────────────────────────────────
   The most consequential setting on the Request Firewall panel, and the control looked identical
   whether it was inspecting nothing, watching, or refusing. Asked for 2026-08-17.

   THE PANEL'S OWN LANGUAGE DECIDES, not my reasoning about severity. I first made Off red, arguing a
   firewall inspecting nothing is worse than one merely watching, and Block green, as "protecting".
   That inverted what this panel already says: its mode banners use RED for "Blocking." (#fef2f2 with
   a #dc2626 rule) and AMBER for "Recording only." Corrected on 2026-08-18: "block mode for IP should
   be red as per firewall".

   The general point is worth keeping: when a product already has a colour for a state, matching it
   beats reasoning from first principles about what the colour ought to mean. A user who has learnt
   that red means refusing does not re-derive it per panel. Off is grey, dormant, which is what it is.

   Every fill is a light tint, so per the house contrast rule every text colour is a dark one; pairing
   a light or translucent fill with light text has bitten three times in this codebase. */
.cs-fw-mode {
    font-weight: 700;
    border-width: 2px;
    border-style: solid;
}
.cs-fw-mode--off { background-color: #f1f5f9; border-color: #94a3b8; color: #334155; }
.cs-fw-mode--log { background-color: #fffbeb; border-color: #d97706; color: #78350f; }
.cs-fw-mode--block { background-color: #fef2f2; border-color: #dc2626; color: #7f1d1d; }

/* Unsaved: the chosen mode is not the mode in force. The colour already followed the choice, which is
   the point, but that made a pending change indistinguishable from a live one, and a screenshot on
   2026-08-17 showed "Block" above a banner correctly reading "Recording only". */
.cs-fw-mode.is-unsaved {
    outline: 2px dashed #6b7280;
    outline-offset: 2px;
}
.cs-fw-mode-unsaved-note {
    display: inline-block;
    margin-left: 8px;
    font-size: 11px;
    font-weight: 700;
    color: #7f1d1d;
    background: #fef2f2;
    border: 1px solid #fca5a5;
    border-radius: 4px;
    padding: 2px 7px;
}

/* ── Recent matches: the tail behind the More button ─────────────────────────
   All 100 rows are rendered; these start hidden and the button drops the class. Hidden with a class
   rather than left unrendered so pressing it needs no request, the markup is already there. */
.csdt-fw-row-extra { display: none; }
.csdt-fw-showing-all .csdt-fw-row-extra { display: table-row; }

/* Server Logs viewer. Moved from get_log_viewer_css() in cloudscale-cyber-devtools.php, 1.10.852. */
.cs-log-src-btn.status-ok{border-color:#22c55e;color:#22c55e}.cs-log-src-btn.status-not-found{border-color:#555;color:#555}.cs-log-src-btn.status-permission-denied{border-color:#f59e0b;color:#f59e0b}.cs-log-src-btn.status-empty{border-color:#6366f1;color:#6366f1}.cs-log-src-btn.active{background:rgba(74,158,255,.15);border-color:#4a9eff;color:#4a9eff}.cs-log-line{padding:1px 0;white-space:pre-wrap;word-break:break-all;border-bottom:1px solid rgba(255,255,255,.03)}.cs-log-line.level-emerg,.cs-log-line.level-alert,.cs-log-line.level-crit{color:#ff6b6b}.cs-log-line.level-error{color:#f87171}.cs-log-line.level-warn{color:#fbbf24}.cs-log-line.level-notice{color:#a78bfa}.cs-log-line.level-info{color:#60a5fa}.cs-log-line.level-debug{color:#6b7280}.cs-log-line.level-default{color:#c9d1d9}

/* Scan-history disclosure widget on the security panel. Moved from an inline style in enqueue_admin_assets(), 1.10.852. */
#cs-scan-history-list > summary::-webkit-details-marker{display:none;}
#cs-scan-history-list > summary{transition:background .15s,border-color .15s,box-shadow .15s;}
#cs-scan-history-list > summary:hover{background:#4f46e5;border-color:#4338ca;box-shadow:0 2px 6px rgba(79,70,229,.32);}
#cs-scan-history-list > summary:focus-visible{outline:2px solid #6366f1;outline-offset:2px;}
#cs-scan-history-list > summary .cs-scan-toggle-caret{transition:transform .2s;}
#cs-scan-history-list[open] > summary .cs-scan-toggle-caret{transform:rotate(180deg);}
#cs-scan-history-list[open] > summary .cs-scan-toggle-label::before{content:"Hide ";}
#cs-scan-history-list:not([open]) > summary .cs-scan-toggle-label::before{content:"Show all ";}

/* ── Mermaid card (Code Block tab) ───────────────────────────────────────────
   Light surfaces throughout, so every text colour here is dark (the contrast rule in CLAUDE.md). */
.cs-mermaid-card { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.25fr); gap: 24px; align-items: start; }
@media (max-width: 960px) { .cs-mermaid-card { grid-template-columns: minmax(0, 1fr); } }
.cs-mermaid-card-lede { margin: 0 0 12px; font-size: 14px; line-height: 1.6; color: #0f172a; font-weight: 600; }
.cs-mermaid-card-steps { margin: 0 0 14px 18px; padding: 0; color: #374151; font-size: 13px; line-height: 1.7; }
.cs-mermaid-card-steps li { margin: 0 0 4px; }
.cs-mermaid-card-steps code { background: #f1f5f9; color: #0f172a; padding: 1px 5px; border-radius: 3px; font-size: 12px; }
.cs-mermaid-card-note { margin: 0; font-size: 12px; color: #4b5563; line-height: 1.6; }
.cs-mermaid-card-note a { font-weight: 600; color: #0e7490; text-decoration: none; white-space: nowrap; }
.cs-mermaid-card-note a:hover { text-decoration: underline; }
.cs-mermaid-card-example { border: 1px solid #e2e8f0; border-radius: 8px; background: #fff; overflow: hidden; }
.cs-mermaid-card-tabs { display: flex; align-items: center; gap: 4px; padding: 6px 8px; background: #f8fafc; border-bottom: 1px solid #e2e8f0; }
.cs-mermaid-card-tab,
.cs-mermaid-card-copy { background: none; border: 1px solid transparent; border-radius: 5px; padding: 3px 10px; font-size: 12px; font-weight: 600; color: #475569; cursor: pointer; }
.cs-mermaid-card-tab.is-active { background: #fff; border-color: #cbd5e1; color: #0f172a; }
.cs-mermaid-card-copy { margin-left: auto; color: #0e7490; border-color: #a5f3fc; background: #ecfeff; }
.cs-mermaid-card-copy:hover { background: #cffafe; }
.cs-mermaid-card-diagram { padding: 18px; min-height: 170px; display: flex; align-items: center; justify-content: center; overflow-x: auto; }
.cs-mermaid-card-diagram svg { max-width: 100%; height: auto; }
.cs-mermaid-card-diagram.is-error { color: #991b1b; font-size: 12px; }
.cs-mermaid-card-loading { color: #64748b; font-size: 12px; }
.cs-mermaid-card-source { margin: 0; padding: 16px 18px; background: #f8fafc; color: #0f172a; font-size: 12px; line-height: 1.6; overflow-x: auto; min-height: 136px; }
.cs-mermaid-card-diagram[hidden], .cs-mermaid-card-source[hidden] { display: none; }

/* Host Software panel (CSDT_Host_Software). */
.cs-hs-table td { vertical-align: top; font-size: 12.5px; }
.cs-hs-advice { min-width: 260px; color: #1f2937; }
.cs-hs-muted { color: #64748b; font-size: 12px; }
.cs-hs-bad { color: #b91c1c; font-weight: 600; }
.cs-hs-warn { color: #b45309; }
.cs-hs-good { color: #15803d; }
.cs-hs-note { margin: 4px 0 8px; color: #334155; font-size: 13px; }
.cs-hs-pill { display: inline-block; padding: 1px 8px; border-radius: 9px; font-size: 12px; font-weight: 600; white-space: nowrap; }

/* ── Activity Log controls ───────────────────────────
   Reported 2026-10-21: the settings row spread a checkbox, the retention field and Save across the
   full width with Save on a different baseline, and the toolbar's filter, count and export did not
   line up. Both rows are now left-aligned flex rows on one centre line that wrap as whole groups on
   a narrow screen. */
.csdt-act-settings {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-start;
    gap: 10px 22px;
    margin: 0 0 4px;
    font-size: 13px;
    color: #1e293b;
}
.csdt-act-check,
.csdt-act-days {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin: 0;
    font-size: 13px;
    font-weight: 600;
    color: #1e293b;
    cursor: pointer;
}
.csdt-act-days input[type="number"] { width: 80px; margin: 0; }
.csdt-act-save-wrap { display: inline-flex; align-items: center; gap: 8px; }
.csdt-act-save-wrap #csdt-act-msg { font-size: 12px; }

.csdt-act-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px 14px;
    margin: 16px 0 10px;
    padding: 10px 12px;
    background: #f8fafc;
    border: 1px solid #e2e8f0;
    border-radius: 6px;
    font-size: 12px;
    color: #1e293b;
}
.csdt-act-count { font-size: 12px; color: #0f172a; white-space: nowrap; }
.csdt-act-filter-wrap {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin: 0;
    font-size: 12px;
    color: #1e293b;
}
.csdt-act-filter-wrap select {
    width: auto;
    min-width: 140px;
    max-width: 220px;
    margin: 0;
    font-size: 12px;
}
.csdt-act-search {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    flex: 1 1 220px;
    max-width: 380px;
    margin: 0;
}
.csdt-act-search input[type="search"] {
    flex: 1 1 auto;
    min-width: 0;
    margin: 0;
    font-size: 12px;
}
.csdt-act-clear {
    flex: 0 0 auto;
    width: 20px;
    height: 20px;
    line-height: 18px;
    text-align: center;
    border-radius: 50%;
    color: #334155;
    font-size: 16px;
    font-weight: 700;
    text-decoration: none;
}
.csdt-act-clear:hover,
.csdt-act-clear:focus { background: #e2e8f0; color: #0f172a; }
.csdt-act-toolbar .button { margin: 0; }
@media (max-width: 600px) {
    .csdt-act-search { flex: 1 1 100%; max-width: none; }
    .csdt-act-filter-wrap select { max-width: 100%; }
}

/* ── Link buttons ────────────────────────────────────
   Navigation links styled as buttons. Small indigo or pale-red text links on tinted cards
   were easy to miss and failed contrast (#fca5a5 on the red header is about 3:1), so every
   "Configure", "Run Scan" and "Site Audit & Scan" link is a solid button. White on #3730a3
   is about 10:1, and #991b1b on white about 8:1. */
.cs-link-btn {
    display: inline-block;
    margin-top: 6px;
    padding: 4px 10px;
    border-radius: 5px;
    background: #3730a3;
    color: #fff !important;
    font-size: 11px;
    font-weight: 700;
    line-height: 1.4;
    text-decoration: none !important;
    white-space: nowrap;
    cursor: pointer;
}
.cs-link-btn:hover, .cs-link-btn:focus { background: #312e81; color: #fff !important; }
.cs-link-btn:focus-visible { outline: 2px solid #f59e0b; outline-offset: 2px; }
.cs-link-btn--on-dark { margin-top: 0; background: #fff; color: #991b1b !important; }
.cs-link-btn--on-dark:hover, .cs-link-btn--on-dark:focus { background: #fee2e2; color: #7f1d1d !important; }
/* ══════════════════════════════════════════════════════════════════════════════
   Controls: reusable buttons, links, checkboxes, switches and selects.

   Defined once here so any tab can adopt them; applied only on the Home tab so far (asked for
   2026-10-21: "use better styled controls"). Every state is visible: hover changes the fill,
   keyboard focus draws a 3px ring outside the control, disabled dims and says so with the
   cursor. Sizes meet the WCAG 2.2 target size (24px) everywhere and grow to 44px on touch
   screens. Text colours are AAA (7:1) against their own fill; tests/home-layout-test.php
   measures each pair from this file.

   Each tone repeats its text colour for :hover, :focus and :active because wp-admin's own
   `a:hover` / `a:focus` (0,1,1) outrank a single class and would repaint the label blue.
   ══════════════════════════════════════════════════════════════════════════════ */
.cs-ctl-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    min-height: 40px;
    padding: 0 16px;
    border: 1px solid transparent;
    border-radius: 8px;
    font-family: inherit;
    font-size: 13px;
    font-weight: 600;
    line-height: 1.2;
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
    box-sizing: border-box;
    box-shadow: none;
    transition: background-color .15s ease, border-color .15s ease, color .15s ease, box-shadow .15s ease;
}
.cs-ctl-btn:focus { box-shadow: none; }
.cs-ctl-btn:focus-visible {
    outline: 3px solid #4338ca;
    outline-offset: 2px;
}
.cs-ctl-btn:disabled,
.cs-ctl-btn[aria-disabled="true"] {
    opacity: .55;
    cursor: not-allowed;
}
.cs-ctl-btn--sm {
    min-height: 36px;
    padding: 0 12px;
    font-size: 12.5px;
}
.cs-ctl-btn--primary,
.cs-ctl-btn--primary:hover,
.cs-ctl-btn--primary:focus,
.cs-ctl-btn--primary:active { color: #fff; }
.cs-ctl-btn--primary { background: #3730a3; border-color: #3730a3; }
.cs-ctl-btn--primary:hover { background: #312e81; border-color: #312e81; }
.cs-ctl-btn--primary:active { background: #1e1b4b; border-color: #1e1b4b; }

.cs-ctl-btn--secondary,
.cs-ctl-btn--secondary:focus { color: #3730a3; }
.cs-ctl-btn--secondary { background: #fff; border-color: #6366f1; }
.cs-ctl-btn--secondary:hover,
.cs-ctl-btn--secondary:active { background: #eef2ff; border-color: #4338ca; color: #312e81; }

.cs-ctl-btn--danger,
.cs-ctl-btn--danger:hover,
.cs-ctl-btn--danger:focus,
.cs-ctl-btn--danger:active { color: #fff; }
.cs-ctl-btn--danger { background: #991b1b; border-color: #991b1b; }
.cs-ctl-btn--danger:hover,
.cs-ctl-btn--danger:active { background: #7f1d1d; border-color: #7f1d1d; }

.cs-ctl-btn--warn,
.cs-ctl-btn--warn:hover,
.cs-ctl-btn--warn:focus,
.cs-ctl-btn--warn:active { color: #fff; }
.cs-ctl-btn--warn { background: #92400e; border-color: #92400e; }
.cs-ctl-btn--warn:hover,
.cs-ctl-btn--warn:active { background: #78350f; border-color: #78350f; }

/* A text link that is a control: underlined so it reads as one without relying on colour. */
.cs-ctl-link {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    min-height: 24px;
    padding: 0;
    border: 0;
    background: none;
    color: #3730a3;
    font-family: inherit;
    font-size: 13px;
    font-weight: 600;
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 3px;
    cursor: pointer;
}
.cs-ctl-link:hover,
.cs-ctl-link:active { color: #1e1b4b; text-decoration-thickness: 2px; }
.cs-ctl-link:focus { color: #3730a3; box-shadow: none; }
.cs-ctl-link:focus-visible { outline: 2px solid #4338ca; outline-offset: 2px; border-radius: 3px; }

/* Checkbox: the native control, larger, in the accent colour. */
input[type="checkbox"].cs-ctl-check {
    width: 18px;
    height: 18px;
    margin: 2px 0 0;
    flex: 0 0 18px;
    accent-color: #3730a3;
    border: 1px solid #64748b;
    border-radius: 4px;
    cursor: pointer;
}
input[type="checkbox"].cs-ctl-check:focus { box-shadow: none; }
input[type="checkbox"].cs-ctl-check:focus-visible { outline: 3px solid #4338ca; outline-offset: 2px; }

/* Switch: a checkbox drawn as an on/off toggle. Still a checkbox, so the label, the keyboard and
   every script that reads .checked behave exactly as before. The off track is #64748b (4.8:1 on
   white) so the control's edge is visible, the knob moves, and on is the accent fill. */
input[type="checkbox"].cs-ctl-switch {
    -webkit-appearance: none;
    appearance: none;
    position: relative;
    width: 38px;
    height: 22px;
    min-width: 38px;
    margin: 0;
    padding: 0;
    border: 0;
    border-radius: 999px;
    background: #64748b;
    box-shadow: none;
    cursor: pointer;
    vertical-align: middle;
    transition: background-color .15s ease;
}
input[type="checkbox"].cs-ctl-switch::before,
input[type="checkbox"].cs-ctl-switch:checked::before {
    content: "";
    position: absolute;
    top: 3px;
    left: 3px;
    width: 16px;
    height: 16px;
    margin: 0;
    border-radius: 50%;
    background: #fff;
    float: none;
    transition: transform .15s ease;
}
input[type="checkbox"].cs-ctl-switch:checked { background: #3730a3; }
input[type="checkbox"].cs-ctl-switch:checked::before { transform: translateX(16px); }
input[type="checkbox"].cs-ctl-switch:focus { box-shadow: none; }
input[type="checkbox"].cs-ctl-switch:focus-visible { outline: 3px solid #4338ca; outline-offset: 2px; }
input[type="checkbox"].cs-ctl-switch:disabled { opacity: .55; cursor: not-allowed; }

/* Select: same height and radius as the buttons beside it. */
select.cs-ctl-select {
    min-height: 40px;
    max-width: 100%;
    padding: 0 32px 0 12px;
    border: 1px solid #64748b;
    border-radius: 8px;
    background-color: #fff;
    color: #0f172a;
    font-size: 13px;
}
select.cs-ctl-select:hover { border-color: #3730a3; }
select.cs-ctl-select:focus { box-shadow: none; border-color: #3730a3; }
select.cs-ctl-select:focus-visible { outline: 3px solid #4338ca; outline-offset: 2px; }

@media (pointer: coarse) {
    .cs-ctl-btn,
    .cs-ctl-btn--sm,
    select.cs-ctl-select { min-height: 44px; }
    .cs-ctl-link { min-height: 32px; }
}

/* ══════════════════════════════════════════════════════════════════════════════
   Home tab: a dashboard, not a form.

   Reported 2026-10-21: "a very basic unprofessional view of the product and what the user needs
   to address". Everything sat inside one white panel, so every block inside it was white on
   white and nothing read as a card. Now the tab is a tinted surface (#e8edf4) and every block on
   it is a white card with a border and a soft shadow, scoped to .cs-home so no other tab moves.

   Top to bottom: the summary (score, what to fix, setup progress), the critical and high issues
   with a Fix button each, the Setup panel with the Home introduction inside it, the status
   cards, then everything else that was on Home, in its old order.

   Type scale on Home: 16px card titles, 14px row titles, 13px body, 12px labels and meta, nothing
   smaller than 11px. Body text is #334155 or darker on white (10:1), labels #475569 (7.6:1).
   ══════════════════════════════════════════════════════════════════════════════ */
.cs-home {
    background: #e8edf4;
    border: 1px solid #d5dde8;
    border-radius: 12px;
    padding: 16px;
    display: flex;
    flex-direction: column;
    gap: 16px;
    color: #1f2937;
}
.cs-home .cs-panel { margin: 0; }
/* A card reached by a #cs-panel-* link keeps the highlight its own shadow would otherwise replace. */
.cs-home-card.cs-panel-targeted { box-shadow: 0 0 0 3px #4338ca; }
.cs-home-card {
    background: #fff;
    border: 1px solid #cfd8e3;
    border-radius: 12px;
    box-shadow: 0 1px 2px rgba(15, 23, 42, .05), 0 2px 6px rgba(15, 23, 42, .04);
    overflow: hidden;
    min-width: 0;
}
.cs-home-card-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 10px 16px;
    padding: 16px 20px;
    border-bottom: 1px solid #e2e8f0;
}
.cs-home-card-titles { flex: 1 1 260px; min-width: 0; }
.cs-home-card-title {
    margin: 0;
    padding: 0;
    font-size: 16px;
    font-weight: 700;
    line-height: 1.3;
    color: #0f172a;
}
.cs-home-card-sub {
    margin: 2px 0 0;
    font-size: 13px;
    line-height: 1.45;
    color: #475569;
}
.cs-home-card-body { padding: 16px 20px 20px; }

/* ── Summary ──────────────────────────────────────── */
.cs-home-kpis {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr));
    gap: 12px;
}
.cs-home-kpi {
    display: flex;
    align-items: flex-start;
    gap: 14px;
    min-width: 0;
    padding: 14px 16px;
    background: #fff;
    border: 1px solid #dbe2ea;
    border-radius: 10px;
}
.cs-home-kpi-text {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
    flex: 1 1 auto;
    min-width: 0;
}
.cs-home-kpi-label {
    font-size: 12px;
    font-weight: 700;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: #475569;
}
.cs-home-kpi-value {
    font-size: 18px;
    font-weight: 700;
    line-height: 1.3;
    color: #0f172a;
}
.cs-home-kpi-meta { font-size: 13px; line-height: 1.45; color: #334155; }
.cs-home-kpi-meta strong { color: #0f172a; }
.cs-home-kpi-counts { display: flex; flex-wrap: wrap; gap: 8px; }

/* Score bands. Same thresholds as the Latest Scan panel; text colours chosen for 7:1 on white. */
.cs-home-kpi-value.is-good { color: #166534; }
.cs-home-kpi-value.is-fair { color: #3f6212; }
.cs-home-kpi-value.is-warn { color: #92400e; }
.cs-home-kpi-value.is-poor { color: #9a3412; }
.cs-home-kpi-value.is-bad  { color: #991b1b; }

/* The score ring: a conic gradient filled to the score, the number in a white disc. Pure CSS, so
   it draws without JavaScript, the same reason the Latest Scan summary is server-rendered. */
.cs-home-score {
    --cs-ring: #94a3b8;
    --cs-ring-text: #475569;
    flex: 0 0 72px;
    width: 72px;
    height: 72px;
    border-radius: 50%;
    display: grid;
    place-items: center;
    background: conic-gradient(var(--cs-ring) calc(var(--cs-score, 0) * 1%), #e2e8f0 0);
}
.cs-home-score.is-good { --cs-ring: #15803d; --cs-ring-text: #166534; }
.cs-home-score.is-fair { --cs-ring: #4d7c0f; --cs-ring-text: #3f6212; }
.cs-home-score.is-warn { --cs-ring: #b45309; --cs-ring-text: #92400e; }
.cs-home-score.is-poor { --cs-ring: #c2410c; --cs-ring-text: #9a3412; }
.cs-home-score.is-bad  { --cs-ring: #b91c1c; --cs-ring-text: #991b1b; }
.cs-home-score-num {
    width: 56px;
    height: 56px;
    border-radius: 50%;
    background: #fff;
    display: grid;
    place-items: center;
    font-size: 22px;
    font-weight: 800;
    color: var(--cs-ring-text);
}

.cs-sev-count {
    display: inline-flex;
    align-items: baseline;
    gap: 5px;
    padding: 3px 10px;
    border-radius: 999px;
    font-size: 13px;
    font-weight: 600;
}
.cs-sev-count strong { font-size: 18px; font-weight: 800; }
.cs-sev-count--critical { background: #fef2f2; border: 1px solid #fca5a5; color: #7f1d1d; }
.cs-sev-count--high     { background: #fff7ed; border: 1px solid #fdba74; color: #7c2d12; }

.cs-home-progress {
    display: block;
    width: 100%;
    max-width: 280px;
    height: 8px;
    margin: 2px 0;
    border-radius: 999px;
    background: #e2e8f0;
    overflow: hidden;
}
.cs-home-card-head .cs-home-progress { flex: 0 1 220px; }
.cs-home-progress-bar {
    display: block;
    height: 100%;
    border-radius: inherit;
    background: #3730a3;
}

/* ── Severity badges, one palette for Home: white text on a solid fill, each at least 7:1 ── */
.cs-sev-badge {
    display: inline-block;
    padding: 3px 8px;
    border-radius: 6px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .05em;
    line-height: 1.4;
    white-space: nowrap;
    color: #fff;
    background: #374151;
}
.cs-sev-badge--critical { background: #991b1b; }
.cs-sev-badge--high     { background: #9a3412; }
.cs-sev-badge--medium   { background: #713f12; }
.cs-sev-badge--low      { background: #374151; }

/* ── Top Security Issues ──────────────────────────── */
.cs-issue-list {
    list-style: none;
    margin: 0;
    padding: 12px 20px 20px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.cs-issue {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    gap: 12px 14px;
    margin: 0;
    padding: 12px 14px;
    background: #fff;
    border: 1px solid #e2e8f0;
    border-left: 4px solid #374151;
    border-radius: 10px;
}
.cs-issue--critical { border-left-color: #b91c1c; background: #fffafa; }
.cs-issue--high     { border-left-color: #c2410c; }
.cs-issue-text { min-width: 0; }
.cs-issue-title { font-size: 14px; font-weight: 700; line-height: 1.35; color: #0f172a; overflow-wrap: anywhere; }
.cs-issue-detail {
    margin-top: 2px;
    font-size: 13px;
    line-height: 1.45;
    color: #334155;
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow-wrap: anywhere;
}
.cs-issue-source { margin-top: 4px; font-size: 12px; font-weight: 600; color: #475569; }

/* ── Home introduction, inside the Setup panel ────── */
.cs-home-intro {
    background: #f5f7ff;
    border: 1px solid #c7d2fe;
    border-radius: 10px;
    padding: 12px 16px;
    font-size: 13px;
    line-height: 1.55;
    color: #1f2937;
}
.cs-home-intro-lead { margin: 0; color: #1f2937; }
.cs-home-intro-tip { margin: 8px 0 0; color: #1f2937; }
.cs-home-intro-tip-label {
    margin-right: 4px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: #3730a3;
}

/* ── Status cards ─────────────────────────────────── */
.cs-stat-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 200px), 1fr));
    gap: 12px;
}
.cs-stat-card {
    --cs-stat-accent: #94a3b8;
    --cs-stat-text: #374151;
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
    padding: 12px 14px;
    background: #fff;
    border: 1px solid #e2e8f0;
    border-top: 3px solid var(--cs-stat-accent);
    border-radius: 10px;
}
.cs-stat-card.is-ok      { --cs-stat-accent: #16a34a; --cs-stat-text: #166534; }
.cs-stat-card.is-warn    { --cs-stat-accent: #d97706; --cs-stat-text: #92400e; }
.cs-stat-card.is-bad     { --cs-stat-accent: #dc2626; --cs-stat-text: #991b1b; }
.cs-stat-card.is-info    { --cs-stat-accent: #0284c7; --cs-stat-text: #075985; }
.cs-stat-card.is-neutral { --cs-stat-accent: #94a3b8; --cs-stat-text: #374151; }
.cs-stat-card.is-accent  { --cs-stat-accent: #4f46e5; --cs-stat-text: #3730a3; }
.cs-stat-label {
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: #475569;
}
.cs-stat-status {
    display: flex;
    align-items: center;
    gap: 7px;
    font-size: 14px;
    font-weight: 700;
    line-height: 1.35;
    color: var(--cs-stat-text);
}
/* A dot in the state colour, so the state is shape plus text, never colour alone. */
.cs-stat-status::before {
    content: "";
    flex: 0 0 8px;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--cs-stat-accent);
}
.cs-stat-detail { font-size: 12.5px; line-height: 1.45; color: #334155; overflow-wrap: anywhere; }
.cs-stat-action {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px 8px;
    margin-top: auto;
    padding-top: 8px;
}
.cs-stat-action .cs-tg-test-msg { font-size: 12px; font-weight: 600; }

/* ── Where the attacks came from ──────────────────── */
.cs-home-origins {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 12px 16px;
}
.cs-home-origins-text {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 4px 12px;
    min-width: 0;
}
.cs-home-origins-title { font-size: 16px; font-weight: 700; color: #0f172a; }
.cs-home-origins-figures { font-size: 14px; color: #334155; }
.cs-home-origins-figures strong { color: #0f172a; }

/* ── Managed AI licence card: the shared card keeps its own look; this only places it ── */
.cs-home-managed-ai { display: flex; max-width: 560px; margin: 0; }

/* ── Recent Security Events ───────────────────────── */
.cs-event-list { display: flex; flex-direction: column; gap: 6px; }
.cs-event-row {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 8px 12px;
    background: var(--cs-ev-bg, #f9fafb);
    border: 1px solid var(--cs-ev-bd, #e5e7eb);
    border-radius: 8px;
}
.cs-event-icon { flex-shrink: 0; font-size: 14px; line-height: 1.4; }
.cs-event-text { flex: 1 1 auto; min-width: 0; }
.cs-event-title { font-size: 13px; font-weight: 700; line-height: 1.4; color: var(--cs-ev-tx, #374151); overflow-wrap: anywhere; }
.cs-event-toggle { display: flex; margin-top: 2px; font-size: 12px; }
.cs-event-detail { margin-top: 2px; font-size: 12px; line-height: 1.45; color: #334155; overflow-wrap: anywhere; }
.cs-event-age { flex-shrink: 0; margin-top: 2px; font-size: 12px; white-space: nowrap; color: #334155; }

/* Other Alerts draws its own heading and rows (CSDT_Alert_Events::render_general(), shared with the
   dashboard widget). The card only frames it, and disappears when there is nothing to show. */
.cs-home-other-alerts { padding: 16px 20px 4px; }
.cs-home-other-alerts:not(:has(.csdt-other-alerts)) { display: none; }

/* ── DB prefix rollback, an action only the owner can take ── */
.cs-home-alert {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 12px 16px;
    padding: 14px 18px;
    background: #fef2f2;
    border: 1px solid #fca5a5;
    border-left: 4px solid #991b1b;
    border-radius: 12px;
}
.cs-home-alert-text { flex: 1 1 280px; min-width: 0; }
.cs-home-alert-title { font-size: 14px; font-weight: 700; color: #991b1b; }
.cs-home-alert-meta { margin-left: 6px; font-size: 12px; color: #334155; }
.cs-home-alert-body { margin-top: 4px; font-size: 13px; line-height: 1.5; color: #1f2937; }

/* ── Quick Fixes ──────────────────────────────────── */
.cs-qf-consent {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    margin: 0 0 12px;
    padding: 12px 14px;
    background: #f8fafc;
    border: 1px solid #e2e8f0;
    border-radius: 10px;
}
.cs-qf-consent-label { font-size: 12.5px; line-height: 1.55; color: #334155; cursor: pointer; }
.cs-qf-consent-label strong { color: #0f172a; }
.cs-qf-list { display: flex; flex-direction: column; gap: 8px; }
.cs-quick-fix-row {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 12px 14px;
    background: #fff;
    border: 1px solid #d5dde8;
    border-radius: 10px;
}
.cs-quick-fix-row.is-fixed { background: #f8fafc; border-color: #e2e8f0; }
.cs-qf-mark {
    flex: 0 0 24px;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    display: grid;
    place-items: center;
    font-size: 13px;
    font-weight: 700;
    background: #fffbeb;
    color: #78350f;
}
.cs-quick-fix-row.is-fixed .cs-qf-mark { background: #dcfce7; color: #14532d; }
.cs-qf-main { flex: 1 1 auto; min-width: 0; }
.cs-qf-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 8px; }
.cs-qf-title { font-size: 14px; font-weight: 600; line-height: 1.4; color: #0f172a; }
.cs-quick-fix-row.is-fixed .cs-qf-title { color: #334155; }
.cs-qf-fixed { flex-shrink: 0; font-size: 12px; font-weight: 700; white-space: nowrap; color: #166534; }
.cs-qf-detail { margin-top: 2px; font-size: 13px; line-height: 1.5; color: #334155; }
.cs-qf-advisory { margin-top: 8px; font-size: 12.5px; font-style: italic; color: #475569; }
.cs-qf-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }

/* ── Phone width: one column, nothing wider than the screen ── */
@media (max-width: 600px) {
    .cs-home { padding: 10px; gap: 12px; border-radius: 10px; }
    .cs-home-card-head { padding: 14px; }
    .cs-home-card-body { padding: 14px; }
    .cs-issue-list { padding: 10px 14px 14px; }
    .cs-home-kpi { padding: 12px; }
    .cs-home-progress { max-width: none; }
    .cs-home-card-head .cs-home-progress { flex: 1 1 100%; }
    .cs-issue { grid-template-columns: auto minmax(0, 1fr); }
    .cs-issue-fix { grid-column: 1 / -1; justify-self: stretch; }
    .cs-stat-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
    .cs-stat-card { padding: 10px 12px; }
    .cs-stat-action .cs-ctl-btn { white-space: normal; text-align: center; }
    .cs-home-other-alerts { padding: 14px 14px 2px; }
    .cs-home-alert { padding: 12px 14px; }
    .cs-home-alert .cs-ctl-btn { white-space: normal; text-align: center; }
    .cs-ai-choice-foot .cs-ctl-btn { white-space: normal; text-align: center; }
}
@media (max-width: 359px) {
    .cs-stat-grid { grid-template-columns: minmax(0, 1fr); }
}

/* ── Hover lift: controls pop off the page ───────────────────────────────────
   Every clickable control rises 2px and casts a shadow on hover, on top of its own colour
   change, so what the pointer is on is never in doubt. Disabled controls stay put. Kept last
   in the file so it is not undone by a control's own :hover rule of equal specificity. */
.cs-ctl-btn,
.cs-link-btn,
.cs-btn-primary,
.cs-btn-secondary,
.cs-btn-orange,
.cs-btn-deep,
.cs-tab-content .button,
.cs-issue {
    transition: transform .12s ease, box-shadow .12s ease, background-color .12s ease, filter .12s ease;
}
.cs-ctl-btn:hover:not(:disabled):not(.disabled),
.cs-link-btn:hover:not(:disabled),
.cs-btn-primary:hover:not(:disabled),
.cs-btn-secondary:hover:not(:disabled),
.cs-btn-orange:hover:not(:disabled),
.cs-btn-deep:hover:not(:disabled),
.cs-tab-content .button:hover:not(:disabled):not(.disabled) {
    transform: translateY(-2px);
    box-shadow: 0 8px 18px -4px rgba(15,23,42,.45), 0 2px 4px rgba(15,23,42,.18);
    filter: brightness(1.08);
    opacity: 1;
}
.cs-issue:hover {
    transform: translateY(-2px);
    box-shadow: 0 12px 24px -10px rgba(15,23,42,.40), 0 2px 6px rgba(15,23,42,.10);
}
@media (prefers-reduced-motion: reduce) {
    .cs-ctl-btn:hover, .cs-link-btn:hover, .cs-btn-primary:hover, .cs-btn-secondary:hover,
    .cs-btn-orange:hover, .cs-btn-deep:hover, .cs-tab-content .button:hover, .cs-issue:hover { transform: none; }
}

/* AI Settings tab status line (render_ai_settings_panel), same verdict as the deep-dive button. */
.cs-ai-setup-state { margin: 0 0 16px; padding: 12px 16px; border-radius: 8px; font-size: 14px; line-height: 1.5; }
.cs-ai-setup-state.is-ready { background: #f0fdf4; border: 1px solid #86efac; color: #166534; }
.cs-ai-setup-state.is-missing { background: #fff7ed; border: 1px solid #fdba74; color: #9a3412; }

/* Comment Protection group (2026-10-28): one collapsible header over Comment Guard and Comment
   Flood Protection. Expanded, the header sits flush on the first panel. */
.cs-comment-group { margin-bottom: 16px; }
.cs-comment-group:not(.is-collapsed) > .cs-section-header { margin-bottom: 10px; }

/* Attack-origins map: hairline seams between OpenStreetMap tiles. Leaflet positions each 256px
   tile with a fractional transform, and on a scaled or high-DPI screen the rounding leaves a
   1px gap that shows the container background as a line along the equator and the prime
   meridian (reported 2026-10-28). Half a pixel of overlap closes it without visible distortion. */
.leaflet-container img.leaflet-tile {
    width: 256.5px !important;
    height: 256.5px !important;
    mix-blend-mode: normal;
}

/* Control Status: the "Turn on" / "Fix" link beside an OFF or NOT WORKING badge. */
.cs-liveness-fix { font-size: 12px; font-weight: 600; margin-left: 8px; }

/* AI tab: the "OR" between Managed AI Settings and Client AI Settings. */
.cs-ai-or { display: flex; align-items: center; gap: 12px; margin: 18px 0; color: #475569; font-size: 12px; font-weight: 700; letter-spacing: .08em; }
.cs-ai-or::before, .cs-ai-or::after { content: ""; flex: 1; border-top: 1px solid #cbd5e1; }

/* Edge Gateway: a button's result, written beside it. */
.cs-edge-gw-btn-msg { margin-left: 8px; font-size: 13px; }
.cs-edge-gw-btn-msg:empty { display: none; }
