/* ============================================================================
   webskts.com — brand design system
   Clean light surface, one vivid accent (electric blue). Self-hosted fonts.
   Layered on top of bspkfw /css/base.css; everything keys off the tokens below.
   ========================================================================== */

@font-face {
    font-family: 'InterVariable';
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url('/fonts/InterVariable.woff2') format('woff2');
}
@font-face {
    font-family: 'JetBrains Mono';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('/fonts/JetBrainsMono-Regular.woff2') format('woff2');
}
@font-face {
    font-family: 'JetBrains Mono';
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url('/fonts/JetBrainsMono-Medium.woff2') format('woff2');
}

:root {
    /* Brand — electric blue */
    --wsk-accent:        #2563eb;
    --wsk-accent-hover:  #1d4ed8;
    --wsk-accent-active: #1e40af;
    --wsk-accent-soft:   #eff6ff;
    --wsk-accent-soft2:  #dbeafe;
    --wsk-accent-ring:   rgba(37, 99, 235, 0.30);
    --wsk-accent-glow:   rgba(37, 99, 235, 0.18);
    --wsk-accent-text:   #2563eb;   /* accent as text (links, eyebrows); --wsk-accent is the fill */
    --wsk-accent-soft-text: #1e40af; /* text on --wsk-accent-soft */

    /* Neutrals (slate) */
    --wsk-ink:        #0f172a;
    --wsk-ink-2:      #1e293b;
    --wsk-text:       #334155;
    --wsk-muted:      #5f6b7d;
    --wsk-faint:      #94a3b8;
    --wsk-border:     #e7ebf0;
    --wsk-border-2:   #cbd5e1;
    --wsk-bg:         #ffffff;
    --wsk-bg-subtle:  #f8fafc;
    --wsk-bg-tint:    #f1f5f9;
    --wsk-surface:    #ffffff;
    --wsk-header-bg:  rgba(255, 255, 255, 0.85);
    --wsk-header-icon: #7c8797;  /* a header icon at rest (the bell): lighter than its hover (--wsk-muted), 3.6:1 on white */
    --wsk-inverse-bg: #0f172a;   /* a dark panel in either scheme (the Enterprise card, step numbers) */

    /* Code surfaces (dark) */
    --wsk-code-bg:     #0b1120;
    --wsk-code-bar:    #131c30;
    --wsk-code-text:   #e2e8f0;
    --wsk-code-dim:    #8aa0c2;

    /* Semantic */
    --wsk-success: #16a34a;
    --wsk-warn:    #d97706;
    --wsk-danger:  #dc2626;
    --wsk-success-soft: #f0fdf4;
    --wsk-success-ring: #dcfce7;
    --wsk-danger-soft:  #fef2f2;
    --wsk-warn-soft:    #fffbeb;
    --wsk-warn-line:    #fde68a;
    --wsk-warn-text:    #92400e;
    /* The semantic colours as TEXT (4.5:1 on white and on their -soft fill) and as
       a fill under white text; --wsk-success / -danger / -warn stay for dots,
       bars and borders (3:1). */
    --wsk-success-text: #15803d;
    --wsk-danger-text:  #b91c1c;
    --wsk-success-fill: #15803d;

    /* Radii */
    --wsk-r-sm: 8px;
    --wsk-r-md: 12px;
    --wsk-r-lg: 16px;
    --wsk-r-xl: 24px;

    /* Shadows */
    --wsk-shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.06), 0 1px 3px rgba(15, 23, 42, 0.05);
    --wsk-shadow-md: 0 2px 4px rgba(15, 23, 42, 0.04), 0 6px 16px rgba(15, 23, 42, 0.08);
    --wsk-shadow-lg: 0 10px 30px rgba(15, 23, 42, 0.10), 0 4px 10px rgba(15, 23, 42, 0.05);
    --wsk-shadow-accent: 0 8px 24px var(--wsk-accent-glow);

    --wsk-maxw: 1280px;
    --wsk-font: 'InterVariable', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
    --wsk-mono: 'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
}

/* Dark values (the framework's light / dark / auto scheme, THEMING.md). The
   same block twice: the visitor chose Dark, or chose Auto on a dark OS. The
   palette follows base.css's dark one, so framework parts (forms, modals,
   toasts, the header menus) sit on the same surfaces as ours. The accent
   FILL stays the brand blue (white text on it keeps its contrast); accent
   TEXT lightens. Code windows are dark in both schemes. */
:root[data-color-scheme="dark"] {
    --wsk-accent-hover:  #3b82f6;
    --wsk-accent-active: #1d4ed8;
    --wsk-accent-soft:   #132339;
    --wsk-accent-soft2:  #1f3d66;
    --wsk-accent-ring:   rgba(68, 147, 248, 0.45);
    --wsk-accent-glow:   rgba(68, 147, 248, 0.25);
    --wsk-accent-text:   #58a6ff;
    --wsk-accent-soft-text: #a5d6ff;
    --wsk-ink:        #e6edf3;
    --wsk-ink-2:      #d1d9e0;
    --wsk-text:       #c9d1d9;
    --wsk-muted:      #9198a1;
    --wsk-faint:      #6e7681;
    --wsk-border:     #30363d;
    --wsk-border-2:   #3d444d;
    --wsk-bg:         #0d1117;
    --wsk-bg-subtle:  #1c2128;
    --wsk-bg-tint:    #262c36;
    --wsk-surface:    #161b22;
    --wsk-header-bg:  rgba(13, 17, 23, 0.85);
    --wsk-header-icon: #6e7681;
    --wsk-inverse-bg: #1b2538;
    --wsk-code-bg:    #05080f;
    --wsk-success: #3fb950;
    --wsk-warn:    #d29922;
    --wsk-danger:  #f85149;
    --wsk-success-soft: #12261e;
    --wsk-success-ring: rgba(63, 185, 80, 0.25);
    --wsk-danger-soft:  #2d1517;
    --wsk-warn-soft:    #272115;
    --wsk-warn-line:    #5c4813;
    --wsk-warn-text:    #e3b341;
    --wsk-success-text: #3fb950;
    --wsk-danger-text:  #f85149;
    --wsk-success-fill: #238636;
    --wsk-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.30), 0 1px 3px rgba(0, 0, 0, 0.25);
    --wsk-shadow-md: 0 2px 4px rgba(0, 0, 0, 0.25), 0 6px 16px rgba(0, 0, 0, 0.40);
    --wsk-shadow-lg: 0 10px 30px rgba(0, 0, 0, 0.50), 0 4px 10px rgba(0, 0, 0, 0.30);
}
@media (prefers-color-scheme: dark) {
    :root[data-color-scheme="auto"] {
        --wsk-accent-hover:  #3b82f6;
        --wsk-accent-active: #1d4ed8;
        --wsk-accent-soft:   #132339;
        --wsk-accent-soft2:  #1f3d66;
        --wsk-accent-ring:   rgba(68, 147, 248, 0.45);
        --wsk-accent-glow:   rgba(68, 147, 248, 0.25);
        --wsk-accent-text:   #58a6ff;
        --wsk-accent-soft-text: #a5d6ff;
        --wsk-ink:        #e6edf3;
        --wsk-ink-2:      #d1d9e0;
        --wsk-text:       #c9d1d9;
        --wsk-muted:      #9198a1;
        --wsk-faint:      #6e7681;
        --wsk-border:     #30363d;
        --wsk-border-2:   #3d444d;
        --wsk-bg:         #0d1117;
        --wsk-bg-subtle:  #1c2128;
        --wsk-bg-tint:    #262c36;
        --wsk-surface:    #161b22;
        --wsk-header-bg:  rgba(13, 17, 23, 0.85);
        --wsk-header-icon: #6e7681;
        --wsk-inverse-bg: #1b2538;
        --wsk-code-bg:    #05080f;
        --wsk-success: #3fb950;
        --wsk-warn:    #d29922;
        --wsk-danger:  #f85149;
        --wsk-success-soft: #12261e;
        --wsk-success-ring: rgba(63, 185, 80, 0.25);
        --wsk-danger-soft:  #2d1517;
        --wsk-warn-soft:    #272115;
        --wsk-warn-line:    #5c4813;
        --wsk-warn-text:    #e3b341;
        --wsk-success-text: #3fb950;
        --wsk-danger-text:  #f85149;
        --wsk-success-fill: #238636;
        --wsk-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.30), 0 1px 3px rgba(0, 0, 0, 0.25);
        --wsk-shadow-md: 0 2px 4px rgba(0, 0, 0, 0.25), 0 6px 16px rgba(0, 0, 0, 0.40);
        --wsk-shadow-lg: 0 10px 30px rgba(0, 0, 0, 0.50), 0 4px 10px rgba(0, 0, 0, 0.30);
    }
}

/* The framework's accent and header families (bspkfw THEMING.md → "Branding
   an install"), pointed at ours, so every part base.css draws (buttons, focus
   rings, selected rows, chips, tabs, Kselect, the header's pills, bell, avatar
   and phone drawer) takes the webskts palette. One block for every scheme:
   `:root[data-color-scheme]` matches base.css's dark blocks in specificity and
   loads after them, and each --wsk-* value already switches with the scheme.
   Tokens not named here (accent-border, -bright, focus-ring, the derived
   ones) keep the framework's values, which our palette was built from. */
:root, :root[data-color-scheme] {
    --bspkfw-accent:             var(--wsk-accent);
    --bspkfw-accent-hover:       var(--wsk-accent-hover);
    --bspkfw-accent-text:        var(--wsk-accent-text);
    --bspkfw-accent-text-strong: var(--wsk-accent-soft-text);
    --bspkfw-accent-soft:        var(--wsk-accent-soft);
    --bspkfw-accent-soft-2:      var(--wsk-accent-soft2);

    /* A light bar in light, a dark one in dark (translucent: the bar blurs
       what scrolls under it). Opaque --wsk-bg behind the nav scroll cues and
       the phone drawer, which fall back to the cue colour. */
    --bspkfw-header-bg:        var(--wsk-header-bg);
    --bspkfw-header-fg:        var(--wsk-muted);
    --bspkfw-header-fg-strong: var(--wsk-ink);
    --bspkfw-header-fg-hover:  var(--wsk-ink);
    --bspkfw-header-muted:     var(--wsk-header-icon);
    --bspkfw-header-hover-bg:  var(--wsk-bg-tint);
    --bspkfw-header-border:    var(--wsk-border-2);
    --bspkfw-header-focus:     var(--bspkfw-focus-ring);
    --bspkfw-nav-cue:          var(--wsk-bg);
    --bspkfw-nav-drawer-divider:  var(--wsk-border);
    --bspkfw-nav-drawer-backdrop: rgba(15, 23, 42, 0.35);
}

/* ── Base typography polish ───────────────────────────────────────────────── */

/* The `hidden` attribute must always win over the component `display` rules
   below (equal-specificity class selectors would otherwise override the UA
   [hidden] rule — e.g. JS-toggled badges/panels would never hide). */
[hidden] { display: none !important; }

body {
    font-family: var(--wsk-font);
    color: var(--wsk-text);
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
    background: var(--wsk-bg);
}
h1, h2, h3, h4 { color: var(--wsk-ink); letter-spacing: -0.02em; }
::selection { background: var(--wsk-accent-soft2); color: var(--wsk-accent-soft-text); }
code, pre, .wsk-mono { font-family: var(--wsk-mono); }

/* Constrain + centre content on every page (restores the framework default,
   which the marketing redesign had removed). Marketing pages — the ones that
   render the full-width footer — opt back into full-bleed so the hero/footer
   can span edge-to-edge; their inner sections self-centre via .wsk-section. */
main { max-width: var(--wsk-maxw); margin: 0 auto; padding: 32px 24px; }
/* The marketing, docs, contact and legal pages lay out their own full-bleed
   sections, so their <main> drops the reading cap and padding. */
body:is(.page-index, .page-pricing, .page-docs, .page-contactus, .page-terms, .page-privacy) main { max-width: none; margin: 0; padding: 0; }

/* ── Buttons ──────────────────────────────────────────────────────────────── */

.btn {
    font-family: var(--wsk-font);
    font-weight: 600;
    border-radius: var(--wsk-r-sm);
    transition: transform .08s ease, box-shadow .15s ease, background .15s ease, border-color .15s ease;
    letter-spacing: -0.01em;
}
/* The fill, edge and hover colours come from the accent family (base.css). */
.btn-primary { box-shadow: 0 1px 2px rgba(37, 99, 235, 0.30), inset 0 1px 0 rgba(255,255,255,0.14); }
.btn-primary:hover { box-shadow: var(--wsk-shadow-accent); transform: translateY(-1px); }
.btn-primary:active { background: var(--wsk-accent-active); transform: translateY(0); }
.btn:not(.btn-primary):not(.btn-danger) {
    background: var(--wsk-surface);
    border: 1px solid var(--wsk-border-2);
    color: var(--wsk-ink);
}
.btn:not(.btn-primary):not(.btn-danger):hover {
    background: var(--wsk-bg-subtle);
    border-color: var(--wsk-faint);
    transform: translateY(-1px);
}

/* ── Framework header → clean light brand bar ─────────────────────────────── */

/* Its colours come from the header family above. */
.site-header {
    -webkit-backdrop-filter: saturate(180%) blur(12px);
    backdrop-filter: saturate(180%) blur(12px);
    border-bottom: 1px solid var(--wsk-border);
    height: 60px;
    padding: 0 24px;
    position: sticky;
    top: 0;
    z-index: 50;
}
.site-title { display: inline-flex; align-items: center; }

/* Brand wordmark (Project::brandHtml) — green status dot + "webskts.com" */
.wsk-logo { display: inline-flex; align-items: center; gap: 11px; font-weight: 600; font-size: 17px; letter-spacing: -0.02em; color: var(--wsk-ink); }
.wsk-logo-dot {
    width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0;
    background: var(--wsk-success); box-shadow: 0 0 0 3px var(--wsk-success-ring);
}

/* Header main nav (Project::topNavItems): our spacing and weight; the
   colours are the header family's. */
.site-header .site-nav-main { gap: 4px; margin-left: 18px; }
.site-header .site-nav-main-item {
    font-weight: 550; font-size: 14px;
    padding: 7px 12px; border-radius: var(--wsk-r-sm); transition: color .12s, background .12s;
}
.site-header .site-nav-main-item.is-active { font-weight: 600; }

/* Guest header actions — framework "Sign in" (.header-login) + our
   "Start free" (.header-cta, Project::guestHeaderActions) */
.site-header .header-login,
.site-header .header-cta {
    height: auto; border: 0; border-radius: var(--wsk-r-sm);
    font-weight: 600; font-size: 14px; line-height: 1.2; text-decoration: none;
}
.site-header .header-login { color: var(--bspkfw-header-fg-strong); padding: 8px 12px; }
.site-header .header-cta {
    padding: 8px 15px; order: 1;
    box-shadow: 0 1px 2px rgba(37,99,235,0.3);
    transition: background .12s, box-shadow .15s, transform .08s;
}
.site-header .header-cta:hover { box-shadow: var(--wsk-shadow-accent); transform: translateY(-1px); }

/* Account page — hide the Inline-edit section for now (targeted by its
   unique inner control; remove to restore). */
body.page-account .page-section:has(.inline-edit-pref-table) { display: none; }

@media (max-width: 720px) {
    .site-header .header-login { display: none; }
}
/* Small phones: tighter spacing, so the wordmark clears the header buttons. */
@media (max-width: 400px) {
    .site-header { padding: 0 14px; }
    .site-header .site-nav-right { gap: 8px; }
    .site-header .wsk-logo { gap: 8px; font-size: 16px; }
    .site-header .header-cta { padding: 8px 12px; }
}

/* ── Shared layout helpers ────────────────────────────────────────────────── */

.wsk-section { max-width: var(--wsk-maxw); margin: 0 auto; padding: 72px 24px; }
.wsk-section-sm { padding-top: 40px; padding-bottom: 40px; }
.wsk-section-header { text-align: center; max-width: 760px; margin: 0 auto 44px; }
.wsk-section-header h1, .wsk-section-header h2 { font-size: clamp(1.7rem, 1.2rem + 2vw, 2.4rem); margin: 0 0 14px; line-height: 1.1; }
.wsk-section-header p { color: var(--wsk-muted); font-size: 1.075rem; line-height: 1.6; margin: 0; }
.wsk-eyebrow {
    display: inline-block; font-size: 0.78rem; font-weight: 700; letter-spacing: 0.08em;
    text-transform: uppercase; color: var(--wsk-accent-text); margin-bottom: 12px;
}
.wsk-section-link { text-align: center; margin-top: 28px; }
.wsk-section-link a { font-weight: 600; text-decoration: none; }
.wsk-section-link a:hover { text-decoration: underline; }

/* ── Hero ─────────────────────────────────────────────────────────────────── */

.wsk-hero {
    /* Full width, so the glow and grid behind it reach the page edges; the
       headline, tagline and diagram carry their own measures. */
    position: relative;
    padding: 96px 24px 56px;
    text-align: center;
    overflow: hidden;
}
.wsk-hero-bg {
    position: absolute; inset: -200px 0 auto 0; height: 620px; z-index: -1;
    background:
        radial-gradient(60% 60% at 50% 0%, var(--wsk-accent-soft) 0%, transparent 70%),
        radial-gradient(40% 50% at 80% 10%, rgba(34,211,238,0.10) 0%, rgba(34,211,238,0) 70%);
    pointer-events: none;
}
.wsk-hero-grid {
    position: absolute; inset: -100px 0 auto 0; height: 460px; z-index: -1; pointer-events: none;
    background-image: linear-gradient(var(--wsk-border) 1px, transparent 1px), linear-gradient(90deg, var(--wsk-border) 1px, transparent 1px);
    background-size: 44px 44px;
    -webkit-mask-image: radial-gradient(60% 70% at 50% 0%, #000 0%, transparent 72%);
    mask-image: radial-gradient(60% 70% at 50% 0%, #000 0%, transparent 72%);
    opacity: 0.5;
}
.wsk-hero-badge {
    display: inline-flex; align-items: center; gap: 8px;
    background: var(--wsk-surface); border: 1px solid var(--wsk-border);
    color: var(--wsk-text); border-radius: 999px; padding: 5px 14px 5px 6px;
    font-size: 0.82rem; font-weight: 600; margin-bottom: 26px; box-shadow: var(--wsk-shadow-sm);
}
.wsk-hero-badge .wsk-dot {
    width: 18px; height: 18px; border-radius: 999px; background: var(--wsk-accent-soft2);
    color: var(--wsk-accent-text); display: inline-flex; align-items: center; justify-content: center; font-size: 10px;
}
.wsk-hero h1 {
    font-size: clamp(2.2rem, 1.3rem + 3.6vw, 4.25rem);
    line-height: 1.05; margin: 0 auto 22px; max-width: 26ch; font-weight: 800; text-wrap: balance;
}
.wsk-hero h1 .wsk-grad {
    background: linear-gradient(110deg, var(--wsk-accent), #22d3ee);
    -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; color: transparent;
}
.wsk-hero-tagline { font-size: clamp(1.1rem, 0.95rem + 0.4vw, 1.3rem); color: var(--wsk-muted); max-width: 760px; margin: 0 auto 34px; line-height: 1.6; text-wrap: pretty; }
.wsk-hero-actions { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; }
.wsk-hero-actions .btn { padding: 11px 22px; font-size: 0.97rem; }
.wsk-hero-note { margin-top: 16px; font-size: 0.85rem; color: var(--wsk-muted); }
.wsk-hero .wsk-beta-note { margin-top: 6px; }

/* Private-beta line (home hero, /signup) and the sign-up page's legal links */
.wsk-beta-note { font-size: 0.85rem; color: var(--wsk-muted); }
.wsk-legal-links { margin: -6px 0 12px; font-size: 0.85rem; }

/* "Get an email when we open": the waitlist form in a card (Ui::waitlistBox) */
.wsk-waitlist {
    max-width: 460px; margin: 24px auto 0; padding: 20px 22px; text-align: left;
    background: var(--wsk-surface); border: 1px solid var(--wsk-border);
    border-radius: var(--wsk-r-lg); box-shadow: var(--wsk-shadow-sm);
}
.wsk-waitlist-title { margin: 0 0 4px; font-size: 1.05rem; color: var(--wsk-ink); }
.wsk-waitlist-intro { margin: 0 0 14px; font-size: 0.88rem; color: var(--wsk-muted); }
.wsk-waitlist .form-actions { margin-bottom: 0; }
.wsk-section > .wsk-waitlist { margin: 0 auto 32px; }

/* Real-time pulse motif under the hero copy */
.wsk-pulse { margin: 48px auto 0; max-width: 1000px; }
.wsk-pulse svg { width: 100%; height: auto; display: block; }
/* The motif's neutrals follow the scheme (CSS beats the SVG's attributes). */
.wsk-pulse .wsk-pulse-backend { fill: var(--wsk-inverse-bg); }
.wsk-pulse .wsk-pulse-wire { stroke: var(--wsk-border-2); }
.wsk-pulse .wsk-pulse-clients { fill: var(--wsk-text); }
.wsk-pulse .wsk-cbox { fill: var(--wsk-surface); stroke: var(--wsk-border); }
.wsk-pulse .wsk-pulse-label { fill: var(--wsk-muted); }
/* All four animations share one 3.6s cycle so the phases line up every loop:
   packets fly in and hit the arrow origin → green flash sweeps the arrows →
   the client boxes flash green → a green check draws in and fades out.
   The packet stagger uses positive delays, which act as a constant phase
   offset on an infinite animation (delay only shifts the start), so the
   stream stays locked to the flash timeline. */
.wsk-pulse .wsk-packet { opacity: 0; animation: wsk-fly 3.6s linear infinite; }
.wsk-pulse .wsk-packet-2 { animation-delay: .18s; }
.wsk-pulse .wsk-packet-3 { animation-delay: .36s; }
.wsk-pulse .wsk-arrows { animation: wsk-arrow-flash 3.6s linear infinite; }
.wsk-pulse .wsk-arrowhead { animation: wsk-head-flash 3.6s linear infinite; }
/* a soft-edged green band slides through each box: a moving gradient mask
   (transparent → opaque → transparent) feathers the leading and trailing
   edges, so it reads as a shiny flash rather than a hard wipe. */
.wsk-pulse .wsk-sweep {
    opacity: 0;
    -webkit-mask-image: linear-gradient(90deg, transparent, #000 50%, transparent);
            mask-image: linear-gradient(90deg, transparent, #000 50%, transparent);
    -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
    -webkit-mask-size: 55% 100%;   mask-size: 55% 100%;
    animation: wsk-sweep 3.6s linear infinite;
}
.wsk-pulse .wsk-check { opacity: 0; stroke-dasharray: 1; stroke-dashoffset: 1; animation: wsk-check-pop 3.6s ease-in-out infinite; }

/* packets ride the dashed line from x=210 to the arrow origin at x=560 (+350px),
   staying opaque until they land, then merging into the flash. */
@keyframes wsk-fly {
    0%   { opacity: 0; transform: translateX(0); }
    3%   { opacity: 1; }
    20%  { opacity: 1; transform: translateX(350px); }
    25%  { opacity: 0; transform: translateX(350px); }
    100% { opacity: 0; transform: translateX(350px); }
}
/* arrow strokes + their arrowheads light green together as the dots land */
@keyframes wsk-arrow-flash {
    0%, 30%   { stroke: var(--wsk-border-2); }
    40%       { stroke: #22c55e; }
    54%       { stroke: #22c55e; }
    64%, 100% { stroke: var(--wsk-border-2); }
}
@keyframes wsk-head-flash {
    0%, 30%   { fill: var(--wsk-faint); }
    40%       { fill: #22c55e; }
    54%       { fill: #22c55e; }
    64%, 100% { fill: var(--wsk-faint); }
}
/* the green moves left→right THROUGH each client: a band of green border +
   fill is clipped into a window that travels across the box (a ~35%-wide band
   sweeps from the left/arrow edge to the right/check edge). All three boxes
   sweep together, so the green fans across the clients at once. */
@keyframes wsk-sweep {
    0%, 36%   { opacity: 0; -webkit-mask-position: -30% 0; mask-position: -30% 0; }
    40%       { opacity: 1; }
    50%       { opacity: 1; }
    54%, 100% { opacity: 0; -webkit-mask-position: 130% 0; mask-position: 130% 0; }
}
/* the check draws in as the sweep reaches the box's right edge, holds, fades */
@keyframes wsk-check-pop {
    0%, 54%   { opacity: 0; stroke-dashoffset: 1; }
    60%       { opacity: 1; }
    66%       { opacity: 1; stroke-dashoffset: 0; }
    82%       { opacity: 1; stroke-dashoffset: 0; }
    92%, 100% { opacity: 0; stroke-dashoffset: 0; }
}
@media (prefers-reduced-motion: reduce) {
    .wsk-pulse .wsk-packet { animation: none; opacity: 1; }
    .wsk-pulse .wsk-arrows,
    .wsk-pulse .wsk-arrowhead { animation: none; }
    .wsk-pulse .wsk-sweep { animation: none; opacity: 0; }
    .wsk-pulse .wsk-check { animation: none; opacity: 1; stroke-dashoffset: 0; }
}

/* ── Code window (dark, with traffic lights) ──────────────────────────────── */

.wsk-code-pair { display: grid; grid-template-columns: 1fr; gap: 16px; max-width: 960px; margin: 48px auto 0; }
.wsk-code-window {
    background: var(--wsk-code-bg); border-radius: var(--wsk-r-md); overflow: hidden;
    box-shadow: var(--wsk-shadow-lg); border: 1px solid rgba(148, 163, 184, 0.12); text-align: left;
}
.wsk-code-titlebar {
    display: flex; align-items: center; gap: 14px; padding: 11px 14px;
    background: var(--wsk-code-bar); border-bottom: 1px solid rgba(148,163,184,0.10);
}
.wsk-code-dots { display: inline-flex; gap: 7px; }
.wsk-code-dots i { width: 11px; height: 11px; border-radius: 999px; display: block; }
.wsk-code-dots i:nth-child(1) { background: #ff5f57; }
.wsk-code-dots i:nth-child(2) { background: #febc2e; }
.wsk-code-dots i:nth-child(3) { background: #28c840; }
.wsk-code-caption { color: var(--wsk-code-dim); font-size: 0.78rem; font-weight: 500; font-family: var(--wsk-mono); }
/* Copy buttons on a dark code surface: code windows and the DNS records */
.wsk-code-copy, .wsk-dns-copy {
    flex: 0 0 auto; padding: 3px 10px; border-radius: 6px; cursor: pointer;
    font: 500 0.75rem/1.4 var(--wsk-mono); color: var(--wsk-code-dim);
    background: transparent; border: 1px solid rgba(148,163,184,0.25);
}
.wsk-code-copy { margin-left: auto; }
.wsk-code-copy:hover, .wsk-dns-copy:hover { color: #e2e8f0; border-color: rgba(148,163,184,0.5); }
.wsk-code-copy:focus-visible, .wsk-dns-copy:focus-visible { outline: 2px solid #7dd3fc; outline-offset: 2px; }
.wsk-code-copy:disabled, .wsk-dns-copy:disabled { cursor: default; color: #86efac; border-color: rgba(134,239,172,0.4); }
.wsk-code-window pre { margin: 0; padding: 16px 18px; overflow-x: auto; }
.wsk-code-window pre:focus-visible { outline: 2px solid var(--bspkfw-focus-ring); outline-offset: -2px; }
.wsk-code-window code { font-family: var(--wsk-mono); font-size: 0.82rem; line-height: 1.7; color: var(--wsk-code-text); background: none; }
.wsk-tok-kw { color: #7dd3fc; }
.wsk-tok-str { color: #86efac; }
.wsk-tok-com { color: var(--wsk-code-dim); }
.wsk-tok-fn { color: #c4b5fd; }

/* CSS-only language tabs (radio inputs drive panel visibility) */
.wsk-tabs .wsk-tab-radio { position: absolute; opacity: 0; pointer-events: none; }
.wsk-tab-labels { display: flex; flex-wrap: wrap; gap: 2px; min-width: 0; }   /* wraps: never a scroll region a keyboard can't reach */
.wsk-tab-label {
    color: var(--wsk-code-dim); font-family: var(--wsk-mono); font-size: 0.76rem; font-weight: 500;
    padding: 4px 11px; border-radius: 6px; cursor: pointer; white-space: nowrap; transition: color .12s, background .12s;
}
.wsk-tab-label:hover { color: #e2e8f0; background: rgba(148,163,184,0.10); }
.wsk-tab-panel { display: none; }
/* Selected radio → matching label highlighted + its panel shown. */
.wsk-tabs .wsk-tab-radio:nth-of-type(1):checked ~ .wsk-code-titlebar .wsk-tab-label:nth-of-type(1),
.wsk-tabs .wsk-tab-radio:nth-of-type(2):checked ~ .wsk-code-titlebar .wsk-tab-label:nth-of-type(2),
.wsk-tabs .wsk-tab-radio:nth-of-type(3):checked ~ .wsk-code-titlebar .wsk-tab-label:nth-of-type(3),
.wsk-tabs .wsk-tab-radio:nth-of-type(4):checked ~ .wsk-code-titlebar .wsk-tab-label:nth-of-type(4),
.wsk-tabs .wsk-tab-radio:nth-of-type(5):checked ~ .wsk-code-titlebar .wsk-tab-label:nth-of-type(5),
.wsk-tabs .wsk-tab-radio:nth-of-type(6):checked ~ .wsk-code-titlebar .wsk-tab-label:nth-of-type(6) {
    color: #fff; background: var(--wsk-accent);
}
.wsk-tabs .wsk-tab-radio:nth-of-type(1):checked ~ .wsk-tab-panels .wsk-tab-panel:nth-of-type(1),
.wsk-tabs .wsk-tab-radio:nth-of-type(2):checked ~ .wsk-tab-panels .wsk-tab-panel:nth-of-type(2),
.wsk-tabs .wsk-tab-radio:nth-of-type(3):checked ~ .wsk-tab-panels .wsk-tab-panel:nth-of-type(3),
.wsk-tabs .wsk-tab-radio:nth-of-type(4):checked ~ .wsk-tab-panels .wsk-tab-panel:nth-of-type(4),
.wsk-tabs .wsk-tab-radio:nth-of-type(5):checked ~ .wsk-tab-panels .wsk-tab-panel:nth-of-type(5),
.wsk-tabs .wsk-tab-radio:nth-of-type(6):checked ~ .wsk-tab-panels .wsk-tab-panel:nth-of-type(6) {
    display: block;
}

/* ── Feature grid ─────────────────────────────────────────────────────────── */

.wsk-features { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
.wsk-feature {
    background: var(--wsk-surface); border: 1px solid var(--wsk-border); border-radius: var(--wsk-r-lg);
    padding: 26px; transition: box-shadow .18s, border-color .18s, transform .18s;
}
.wsk-feature:hover { box-shadow: var(--wsk-shadow-md); border-color: var(--wsk-border-2); transform: translateY(-2px); }
.wsk-feature-icon {
    width: 42px; height: 42px; border-radius: 11px; background: var(--wsk-accent-soft);
    color: var(--wsk-accent-text); display: inline-flex; align-items: center; justify-content: center; margin-bottom: 16px;
}
.wsk-feature-icon svg { width: 22px; height: 22px; }
.wsk-feature h3 { font-size: 1.06rem; margin: 0 0 7px; }
.wsk-feature p { color: var(--wsk-muted); font-size: 0.93rem; line-height: 1.6; margin: 0; }
@media (max-width: 860px) { .wsk-features { grid-template-columns: 1fr; } }

/* ── How it works (numbered steps) ────────────────────────────────────────── */

.wsk-steps { display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; }
.wsk-step { position: relative; padding-top: 8px; }
.wsk-step-num {
    width: 34px; height: 34px; border-radius: 999px; background: var(--wsk-inverse-bg); color: #fff;
    display: inline-flex; align-items: center; justify-content: center; font-weight: 700; font-size: 0.95rem; margin-bottom: 14px;
}
.wsk-step h3 { font-size: 1.02rem; margin: 0 0 6px; }
.wsk-step p { color: var(--wsk-muted); font-size: 0.92rem; line-height: 1.6; margin: 0; }
@media (max-width: 760px) { .wsk-steps { grid-template-columns: 1fr; } }

/* ── Pricing ──────────────────────────────────────────────────────────────── */

.wsk-tier-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; align-items: stretch; max-width: var(--wsk-maxw); margin: 0 auto; }
.wsk-tier-card {
    position: relative; background: var(--wsk-surface); border: 1px solid var(--wsk-border);
    border-radius: var(--wsk-r-lg); padding: 26px 22px; display: flex; flex-direction: column;
    transition: box-shadow .18s, transform .18s, border-color .18s;
}
.wsk-tier-card:hover { box-shadow: var(--wsk-shadow-md); transform: translateY(-3px); }
.wsk-tier-card--popular {
    border-color: var(--wsk-accent); box-shadow: var(--wsk-shadow-lg);
    background: linear-gradient(180deg, var(--wsk-accent-soft) 0%, var(--wsk-surface) 22%);
}
.wsk-tier-popular {
    position: absolute; top: -12px; left: 50%; transform: translateX(-50%);
    background: var(--wsk-accent); color: #fff; border-radius: 999px; padding: 4px 14px;
    font-size: 0.7rem; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; white-space: nowrap;
    box-shadow: var(--wsk-shadow-accent);
}
.wsk-tier-card h3 { font-size: 1.18rem; margin: 0 0 10px; }
.wsk-tier-price { font-size: 2.1rem; font-weight: 800; color: var(--wsk-ink); letter-spacing: -0.03em; }
.wsk-tier-per { font-size: 0.85rem; font-weight: 500; color: var(--wsk-muted); letter-spacing: 0; }
.wsk-tier-interval { font-size: 0.82rem; color: var(--wsk-muted); min-height: 1.4em; margin: 4px 0 18px; }
.wsk-tier-features { list-style: none; padding: 0; margin: 0 0 22px; flex: 1; display: flex; flex-direction: column; gap: 9px; }
.wsk-tier-feature { display: flex; align-items: flex-start; gap: 9px; font-size: 0.875rem; color: var(--wsk-text); line-height: 1.4; }
.wsk-tier-mark { flex: 0 0 16px; height: 16px; margin-top: 1px; display: inline-flex; align-items: center; justify-content: center; border-radius: 999px; font-size: 9px; }
.wsk-tier-feature .wsk-tier-mark { background: var(--wsk-accent-soft); color: var(--wsk-accent-text); }
.wsk-tier-feature--off { color: var(--wsk-muted); }
.wsk-tier-feature--off .wsk-tier-mark { background: var(--wsk-bg-tint); color: var(--wsk-muted); }
.wsk-tier-card:not(.wsk-tier-card--popular) .wsk-tier-cta { background: var(--wsk-surface); border: 1px solid var(--wsk-border-2); color: var(--wsk-ink); }
.wsk-tier-card:not(.wsk-tier-card--popular) .wsk-tier-cta:hover { background: var(--wsk-accent-soft); border-color: var(--wsk-accent); color: var(--wsk-accent-soft-text); }

.wsk-enterprise {
    display: flex; align-items: center; justify-content: space-between; gap: 28px; flex-wrap: wrap;
    background: var(--wsk-inverse-bg); color: #fff; border-radius: var(--wsk-r-lg); padding: 30px 32px;
    margin: 22px auto 0; max-width: var(--wsk-maxw); box-shadow: var(--wsk-shadow-lg);
}
.wsk-enterprise h3 { color: #fff; margin: 0 0 6px; font-size: 1.3rem; }
.wsk-enterprise p { color: #94a3b8; margin: 0 0 14px; }
.wsk-enterprise-features { columns: 2; gap: 10px 28px; }
.wsk-enterprise .wsk-tier-feature { color: #cbd5e1; }
.wsk-enterprise .wsk-tier-feature .wsk-tier-mark { background: rgba(37,99,235,0.25); color: #93c5fd; }
.wsk-enterprise .btn-primary { white-space: nowrap; }
@media (max-width: 980px) { .wsk-tier-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px) { .wsk-tier-grid { grid-template-columns: 1fr; } .wsk-enterprise-features { columns: 1; } }

/* ── CTA band ─────────────────────────────────────────────────────────────── */

.wsk-cta-section { text-align: center; }
.wsk-cta-band {
    position: relative; overflow: hidden; max-width: var(--wsk-maxw); margin: 0 auto;
    background: linear-gradient(120deg, #1d4ed8, #2563eb 45%, #0ea5e9); border-radius: var(--wsk-r-xl);
    padding: 56px 24px; color: #fff; box-shadow: var(--wsk-shadow-lg);
}
.wsk-cta-band::after {
    content: ''; position: absolute; inset: 0; pointer-events: none;
    background-image: linear-gradient(rgba(255,255,255,0.10) 1px, transparent 1px), linear-gradient(90deg, rgba(255,255,255,0.10) 1px, transparent 1px);
    background-size: 40px 40px;
    -webkit-mask-image: radial-gradient(70% 100% at 50% 0%, #000, transparent 75%);
    mask-image: radial-gradient(70% 100% at 50% 0%, #000, transparent 75%);
}
.wsk-cta-band h2 { color: #fff; font-size: clamp(1.6rem, 1.1rem + 2vw, 2.2rem); margin: 0 0 10px; position: relative; }
.wsk-cta-band p { color: rgba(255,255,255,0.86); margin: 0 0 26px; font-size: 1.05rem; position: relative; }
.wsk-cta-band .wsk-hero-actions { position: relative; }
.wsk-cta-band .btn-primary { background: #fff; color: var(--wsk-accent-active); border-color: #fff; }
.wsk-cta-band .btn-primary:hover { background: #f1f5f9; }
.wsk-cta-band .btn:not(.btn-primary) { background: rgba(255,255,255,0.12); border-color: rgba(255,255,255,0.45); color: #fff; }
.wsk-cta-band .btn:not(.btn-primary):hover { background: rgba(255,255,255,0.2); }

/* ── Footer ───────────────────────────────────────────────────────────────── */

.wsk-footer { border-top: 1px solid var(--wsk-border); background: var(--wsk-bg-subtle); margin-top: 40px; }
/* The footer (Project::footerHtml(), after <main>) sits at the bottom of the
   window on a short page such as /login, not halfway up it. */
body:has(> .bspkfw-site-footer) { display: flex; flex-direction: column; min-height: 100dvh; }
body:has(> .bspkfw-site-footer) > main { flex: 1 0 auto; width: 100%; }
.wsk-footer-inner { max-width: var(--wsk-maxw); margin: 0 auto; padding: 44px 24px; display: flex; flex-wrap: wrap; gap: 32px; align-items: flex-start; justify-content: space-between; }
.wsk-footer-brand { max-width: 280px; }
.wsk-footer-brand .wsk-logo { margin-bottom: 12px; }
.wsk-footer-tag { color: var(--wsk-muted); font-size: 0.9rem; line-height: 1.6; margin: 0; }
.wsk-footer-cols { display: flex; gap: 56px; flex-wrap: wrap; }
.wsk-footer-col h4 { font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.07em; color: var(--wsk-muted); margin: 0 0 12px; }
.wsk-footer-col a { display: block; color: var(--wsk-text); text-decoration: none; font-size: 0.9rem; padding: 5px 0; }
.wsk-footer-col a:hover { color: var(--wsk-accent-text); }
.wsk-footer-bottom { border-top: 1px solid var(--wsk-border); }
.wsk-footer-bottom-inner { max-width: var(--wsk-maxw); margin: 0 auto; padding: 18px 24px; display: flex; justify-content: space-between; flex-wrap: wrap; gap: 10px; color: var(--wsk-muted); font-size: 0.84rem; }

/* ── Generic card (console + content) ─────────────────────────────────────── */

.wsk-card {
    background: var(--wsk-surface); border: 1px solid var(--wsk-border); border-radius: var(--wsk-r-lg);
    padding: 22px 24px; margin-bottom: 20px; box-shadow: var(--wsk-shadow-sm);
}
.wsk-card h2 { margin: 0 0 6px; font-size: 1.12rem; }
/* A card the user folds by its title (Html::collapsibleSection(), chevron at
   the left). The helper's heading takes `font: inherit`; keep it an h2. */
.wsk-card.bspkfw-fold > .page-section-title { gap: 12px; margin-bottom: 6px; }
.wsk-card.bspkfw-fold.collapsed > .page-section-title { margin-bottom: 0; }
.wsk-card .bspkfw-fold-heading { margin: 0; font-weight: 700; }
/* A card's own paragraphs (its intro, a note) keep apart from what follows. */
.wsk-card > .page-section-body > p { margin: 0 0 12px; }
.wsk-card > .page-section-body > p:last-child { margin-bottom: 0; }
.wsk-card .bspkfw-fold-chevron { border-color: var(--wsk-muted); }
.wsk-card .bspkfw-fold-toggle:hover { color: var(--wsk-accent-text); }
/* The API tokens card (Project::apiTokensSectionUrl(), ApiTokensSection):
   the framework's section sits inside the card, which carries the title and
   the fold, so the section's own frame and heading step aside. */
.wsk-card .api-tokens-section { background: none; border: 0; border-radius: 0; padding: 0; box-shadow: none; }
.wsk-card .api-tokens-section > .page-section-title { display: none; }
.wsk-card .api-tokens-section > .page-section-desc { font-size: inherit; color: var(--wsk-muted); margin: 0 0 14px; max-width: 75ch; }
/* Its docs link sits in a sentence: underlined, not told apart by colour alone. */
.wsk-card .api-tokens-section > .page-section-desc a { text-decoration: underline; text-underline-offset: 2px; }
.wsk-card .api-tokens-section > h3 { margin: 22px 0 10px; font-size: 0.95rem; color: var(--wsk-ink); }
/* "A program can also replace its own token…": under the token list, not against it. */
.wsk-card .api-tokens-section > .api-tokens-rotate-help { margin-top: 12px; font-size: 0.9rem; }
.wsk-state-panel { text-align: center; padding: 56px 24px; }
.wsk-state-panel h2 { font-size: 1.25rem; }

/* Console page header */
.page-header h1 { letter-spacing: -0.02em; }

/* ── Console: credentials ─────────────────────────────────────────────────── */

.wsk-credentials { display: flex; flex-direction: column; gap: 10px; margin-top: 16px; }
.wsk-credentials-group { display: contents; }   /* swappable host rows, laid out as direct children */

/* "Send a test message" under the credentials: a button, then one line per step */
.wsk-selftest { margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--wsk-border); }
.wsk-selftest-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; }
.wsk-selftest-help { font-size: 0.85rem; }
.wsk-selftest-steps { list-style: none; margin: 12px 0 0; padding: 0; display: flex; flex-direction: column; gap: 6px; font-size: 0.9rem; }
.wsk-selftest-step { display: flex; align-items: baseline; gap: 8px; color: var(--wsk-text); overflow-wrap: anywhere; }
.wsk-selftest-step::before { flex: none; width: 1em; text-align: center; font-weight: 700; }
.wsk-selftest-step[data-state="active"] { color: var(--wsk-muted); }
.wsk-selftest-step[data-state="active"]::before { content: "…"; color: var(--wsk-muted); }
.wsk-selftest-step[data-state="done"]::before { content: "✓"; color: var(--wsk-success-text); }
.wsk-selftest-step[data-state="failed"] { color: var(--wsk-danger-text); }
.wsk-selftest-step[data-state="failed"]::before { content: "✕"; color: var(--wsk-danger-text); }

/* A usage number that just went up glows briefly (dashboard.js showCount) */
@keyframes wsk-bump { from { background: var(--wsk-accent-soft); color: var(--wsk-accent-text); } to { background: transparent; } }
.wsk-bumped { animation: wsk-bump 1.6s ease-out; border-radius: 4px; }
@media (prefers-reduced-motion: reduce) { .wsk-bumped { animation: none; font-weight: 700; } }
.wsk-credential-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.wsk-credential-label { flex: 0 0 150px; font-weight: 600; font-size: 0.86rem; color: var(--wsk-text); }
.wsk-credential-value {
    flex: 1 1 280px; background: var(--wsk-bg-subtle); border: 1px solid var(--wsk-border);
    border-radius: var(--wsk-r-sm); padding: 9px 12px; font-family: var(--wsk-mono);
    font-size: 0.82rem; color: var(--wsk-ink); overflow-wrap: anywhere;
}
.wsk-api-key[data-revealed="0"] { color: var(--wsk-muted); letter-spacing: 1px; }
/* Under the signing secret: what it is for, or the plans that have it. Indented to the values. */
.wsk-credential-note { margin: -4px 0 0 162px; font-size: 0.84rem; }
/* "When you rotate…, the old one keeps working for" + a line per overlap still running. */
.wsk-rotate-overlap { margin-top: 6px; padding-top: 12px; border-top: 1px solid var(--wsk-border); }
.wsk-rotate-overlap .form-group { max-width: 420px; }
.wsk-overlap-note { margin: 4px 0 0; font-size: 0.84rem; }
@media (max-width: 640px) {
    .wsk-credential-note { margin-left: 0; }
}
/* Live counts by channel family (public / private / presence). */
.wsk-family-stats { margin-bottom: 8px; }
.wsk-family-stats td { font-variant-numeric: tabular-nums; }
.wsk-client-events-line { margin: 0 0 16px; font-size: 0.86rem; }

/* ── Console: live stats ──────────────────────────────────────────────────── */

.wsk-stats-grid { display: flex; gap: 40px; margin: 18px 0 8px; flex-wrap: wrap; }
/* Stale (the pushserver didn't answer; #wsk-stats-error says so): the values
   look stale, the labels stay readable (opacity took them to 1.9:1). */
.wsk-stats-stale .wsk-stat-value { color: var(--wsk-muted); }
.wsk-stat { display: flex; flex-direction: column; gap: 2px; }
.wsk-stat-value { font-size: 2.1rem; font-weight: 800; line-height: 1.05; color: var(--wsk-ink); letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.wsk-stat-label { font-size: 0.82rem; color: var(--wsk-muted); font-weight: 500; }

.wsk-quota-heading { margin: 22px 0 10px; font-size: 0.95rem; display: flex; align-items: center; gap: 10px; color: var(--wsk-ink); }
.wsk-tier-badge {
    display: inline-flex; align-items: center; background: var(--wsk-accent-soft); color: var(--wsk-accent-soft-text);
    border: 1px solid var(--wsk-accent-soft2); border-radius: 999px; padding: 3px 12px; font-size: 0.74rem; font-weight: 700;
}
.wsk-quota-table { width: 100%; }
.wsk-quota-table td, .wsk-quota-table th { vertical-align: middle; font-variant-numeric: tabular-nums; }
/* A phone: four columns fit a 390px screen (they overflowed by 25px). */
@media (max-width: 480px) {
    .wsk-quota-table td, .wsk-quota-table th { padding-left: 6px; padding-right: 6px; }
    .wsk-quota-table .wsk-quota-bar-col { width: 18%; }
}
.wsk-quota-bar-col { width: 30%; }
.wsk-quota-bar { background: var(--wsk-bg-tint); border-radius: 999px; height: 7px; overflow: hidden; }
.wsk-quota-bar-fill { background: var(--wsk-accent); border-radius: 999px; height: 100%; width: 0; transition: width .4s ease; }
.wsk-quota-bar-warn { background: var(--wsk-warn); }
/* A limit the pushserver hasn't caught up with yet (dashboard.js showLimitsBehind). */
.wsk-quota-behind { font-size: 0.8rem; color: var(--wsk-warn-text); margin-top: 2px; }

/* Per-user quota-alert threshold control under the quota table. */
/* ── Projects: the switcher, a project's header, the Overall view ── */
.wsk-project-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin: 0 0 14px; }
.wsk-project-tab {
    display: inline-flex; align-items: center; gap: 7px; padding: 6px 12px; border-radius: 999px;
    border: 1px solid var(--wsk-border); background: var(--wsk-surface); color: var(--wsk-text);
    font: inherit; font-size: 0.88rem; font-weight: 600; text-decoration: none; cursor: pointer;
}
.wsk-project-tab:hover { border-color: var(--wsk-accent); }
.wsk-project-tab[aria-current="page"] { background: var(--wsk-accent-soft); border-color: var(--wsk-accent); color: var(--wsk-accent-soft-text); }
.wsk-project-new { border-style: dashed; color: var(--wsk-muted); }
.wsk-project-limit { font-size: 0.85rem; margin-left: 4px; }
.wsk-project-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--wsk-muted); flex: none; display: inline-block; }
td .wsk-project-dot { margin-right: 7px; vertical-align: middle; }
.wsk-project-dot--active { background: var(--wsk-success); }
.wsk-project-dot--pending { background: var(--wsk-warn); }
.wsk-project-dot--paused, .wsk-project-dot--suspended { background: var(--wsk-muted); }
.wsk-project-dot--failed { background: var(--wsk-danger); }
.wsk-project-header { display: flex; align-items: center; flex-wrap: wrap; gap: 12px; }
.wsk-project-actions { display: flex; gap: 8px; margin-left: auto; }
.wsk-project-shared { margin: -6px 0 14px; }
.wsk-project-modal-body { padding-top: 14px; padding-bottom: 20px; }
.wsk-projects-paused { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-bottom: 18px; }
.wsk-num { text-align: right; font-variant-numeric: tabular-nums; }

/* Past a handful of projects the bar's tabs give way to a searchable picker
   (KSelect). Its label stays for screen readers only; the placeholder says it. */
.wsk-project-jump { margin: 0; flex: 0 1 280px; min-width: 200px; }
.wsk-project-jump .form-label {
    position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; border: 0;
    overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}
@media (max-width: 560px) { .wsk-project-jump { flex: 1 1 100%; } }

/* The Overall projects table: search, sortable headers, Show more. */
.wsk-projects-tools { margin: 0 0 12px; max-width: 360px; }
.wsk-projects-tools .form-group { margin-bottom: 0; }
.wsk-sort {
    all: unset; cursor: pointer; display: inline-flex; align-items: center; gap: 4px;
    font: inherit; font-weight: inherit; color: inherit; border-radius: 4px;
}
th.wsk-num .wsk-sort { justify-content: flex-end; }
.wsk-sort:hover { color: var(--wsk-accent-text); }
.wsk-sort:focus-visible { outline: 2px solid var(--bspkfw-focus-ring); outline-offset: 2px; }
.wsk-sort-mark { font-size: 0.7em; }
.wsk-projects-foot { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin-top: 10px; }
.wsk-projects-foot p { margin: 0; }
.wsk-project-gone { margin-bottom: 18px; }

.wsk-quota-threshold { display: flex; align-items: flex-end; gap: 12px; margin-top: 18px; flex-wrap: wrap; }
.wsk-quota-threshold .form-group { margin-bottom: 0; flex: 1 1 220px; max-width: 320px; }

/* ── Console: usage charts ────────────────────────────────────────────────── */

.wsk-charts-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 22px; margin-top: 14px; }
.wsk-chart-title { margin: 0 0 8px; font-size: 0.86rem; color: var(--wsk-muted); font-weight: 600; }
.wsk-chart { height: 220px; }

/* ── Billing ──────────────────────────────────────────────────────────────── */

.wsk-billing-current { display: flex; align-items: center; gap: 12px; margin: 10px 0 6px; }
.wsk-billing-actions { margin-top: 16px; display: flex; gap: 10px; }
.wsk-billing-actions { flex-wrap: wrap; }

/* The plan picker (Ui::planPicker): a Monthly / Yearly toggle over every
   plan's card; the modal's data-interval picks which price each card shows. */
.wsk-plan-modal-body { padding-top: 16px; padding-bottom: 22px; }
/* The toggle stays in reach while the plans scroll under it (phones). */
.wsk-plan-interval-bar {
    position: sticky; top: -16px; z-index: 1; display: flex; align-items: center; justify-content: center;
    flex-wrap: wrap; gap: 10px 14px; margin: -16px 0 18px; padding: 16px 0 10px; background: var(--bspkfw-surface);
}
/* A segmented switch: a framework RadioGroup (rowClass 'wsk-segmented',
   inline) drawn as one pill with the choice raised. The plan picker's
   Monthly / Yearly, the activity overview's metric. */
.wsk-segmented { margin: 0; }
.wsk-segmented > label:first-child {
    position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
}
.wsk-segmented .radio-group {
    display: inline-flex; flex-direction: row; flex-wrap: nowrap; gap: 0; padding: 4px;
    border: 1px solid var(--wsk-border); border-radius: 999px; background: var(--wsk-bg-tint);
}
.wsk-segmented .radio-group__option { position: relative; gap: 0; margin: 0; }
.wsk-segmented .radio-group__option input { position: absolute; inset: 0; opacity: 0; margin: 0; cursor: pointer; }
.wsk-segmented .radio-group__label {
    display: block; padding: 7px 22px; border-radius: 999px; font-size: 0.9rem; font-weight: 600; color: var(--wsk-muted);
    transition: background .15s, color .15s, box-shadow .15s;
}
.wsk-segmented input:checked + .radio-group__label { background: var(--wsk-surface); color: var(--wsk-ink); box-shadow: var(--wsk-shadow-sm); }
.wsk-segmented input:focus-visible + .radio-group__label { outline: 2px solid var(--wsk-accent-ring); outline-offset: 2px; }
@media (max-width: 480px) {
    .wsk-segmented .radio-group__label { padding: 6px 13px; font-size: 0.85rem; }
}
.wsk-plan-interval-save {
    background: var(--wsk-success-fill); color: #fff; border-radius: 999px; padding: 2px 10px;
    font-size: 0.74rem; font-weight: 700; white-space: nowrap;
}
.wsk-plan-modal[data-interval="monthly"] [data-for="annual"],
.wsk-plan-modal[data-interval="annual"] [data-for="monthly"] { display: none; }

.wsk-billing-plans { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 14px; }
.wsk-plan-card {
    display: flex; flex-direction: column; border: 1px solid var(--wsk-border); border-radius: var(--wsk-r-md);
    padding: 18px; transition: border-color .15s, box-shadow .15s;
}
.wsk-plan-card:hover { box-shadow: var(--wsk-shadow-sm); }
.wsk-plan-card--current { border-color: var(--wsk-accent); background: var(--wsk-accent-soft); }
/* The plan asked for (/pricing's "Get started", backing out of Checkout). */
.wsk-plan-card--asked { border-color: var(--wsk-accent); box-shadow: 0 0 0 3px var(--wsk-accent-ring); }
.wsk-plan-card-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin: 0 0 6px; }
.wsk-plan-card h3 { margin: 0; font-size: 1.05rem; }
.wsk-plan-price { font-size: 1.5rem; font-weight: 700; color: var(--wsk-ink); letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.wsk-plan-per { font-size: 0.85rem; font-weight: 500; color: var(--wsk-muted); letter-spacing: 0; }
.wsk-plan-note { font-size: 0.8rem; color: var(--wsk-muted); margin: 2px 0 14px; }
.wsk-plan-card .wsk-tier-features { margin-bottom: 16px; gap: 7px; }
.wsk-plan-card .wsk-tier-feature { font-size: 0.82rem; }
.wsk-plan-current-badge {
    flex: none; background: var(--wsk-accent); color: #fff; border-radius: 999px;
    padding: 2px 10px; font-size: 0.7rem; font-weight: 700;
}
.wsk-plan-pick { align-self: stretch; margin-top: auto; }
.wsk-plan-enterprise { margin: 16px 0 0; font-size: 0.88rem; }
/* "Activating your new plan…" beside the plan, back from Checkout. */
.wsk-plan-status { font-size: 0.85rem; font-weight: 400; }

/* Current plan on Enterprise: the price the offer set. */
.wsk-billing-price { margin: 4px 0; font-weight: 600; color: var(--wsk-ink); }

/* ── Enterprise offer: the customer's modal (Ui::enterpriseOfferModal) ── */
.wsk-offer-body { padding-top: 16px; padding-bottom: 22px; }
.wsk-offer-body h3 { margin: 22px 0 8px; font-size: 1rem; color: var(--wsk-ink); }
.wsk-offer-price { font-size: 1.9rem; font-weight: 700; color: var(--wsk-ink); letter-spacing: -0.02em; margin: 6px 0 4px; }
.wsk-offer-tax { display: block; font-size: 0.8rem; font-weight: 500; color: var(--wsk-muted); letter-spacing: 0; }
/* Free months: what the first months cost, and the date of the first payment. */
.wsk-offer-free-months {
    display: inline-block; margin: 4px 0 0; padding: 6px 12px; border-radius: var(--wsk-r-md);
    background: var(--wsk-accent-soft); color: var(--wsk-accent-soft-text); font-weight: 600; font-size: 0.92rem;
}
.wsk-offer-quotas { width: 100%; }
.wsk-offer-quotas th[scope="row"] { font-weight: 500; text-align: start; }
.wsk-offer-quotas td { font-variant-numeric: tabular-nums; }
.wsk-offer-quotas .wsk-offer-new { font-weight: 700; color: var(--wsk-ink); }
.wsk-offer-perks { margin-bottom: 0; gap: 7px; }
.wsk-offer-terms {
    max-height: 260px; overflow-y: auto; padding: 12px 16px; font-size: 0.86rem;
    border: 1px solid var(--wsk-border); border-radius: var(--wsk-r-md); background: var(--wsk-bg-subtle);
}
.wsk-offer-terms h4 { margin: 14px 0 6px; font-size: 0.92rem; }
.wsk-offer-actions { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 12px; margin-top: 18px; }
.wsk-offer-actions form { flex: 1 1 320px; }
.wsk-offer-actions .form-actions { justify-content: flex-end; }

/* ── /admin/enterprise ── */
.wsk-offer-new-grid { display: grid; grid-template-columns: minmax(0, 2fr) minmax(240px, 1fr); gap: 24px; align-items: start; }
.wsk-offer-new-grid form { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); column-gap: 16px; }
.wsk-offer-new-grid form > .form-group:not(.wsk-offer-quota-row),
.wsk-offer-new-grid form > .form-actions,
.wsk-offer-new-grid form > .form-error,
.wsk-offer-new-grid form > .wsk-offer-presets { grid-column: 1 / -1; }
/* "Fill the limits with": a plan's limits, unlimited, the customer's own. */
.wsk-offer-presets { margin-bottom: var(--bspkfw-space-row, 16px); }
.wsk-offer-presets-label { display: block; font-weight: 500; margin-bottom: 5px; color: var(--bspkfw-text-2); }   /* as base.css `label` */
.wsk-offer-presets-buttons { display: flex; flex-wrap: wrap; gap: 8px; }
.wsk-offer-customer { border: 1px solid var(--wsk-border); border-radius: var(--wsk-r-md); padding: 14px 16px; background: var(--wsk-bg-subtle); }
.wsk-offer-customer h3 { margin: 0 0 8px; font-size: 0.95rem; }
.wsk-offer-customer p { margin: 0 0 6px; font-size: 0.86rem; }
.wsk-offer-row-actions { white-space: nowrap; text-align: end; }
@media (max-width: 760px) {
    .wsk-offer-new-grid { grid-template-columns: 1fr; }
}

/* ── Admin ops ────────────────────────────────────────────────────────────── */

.wsk-state--ok    { color: var(--wsk-success-text); font-weight: 600; }
.wsk-state--warn  { color: var(--wsk-warn-text); font-weight: 600; }
.wsk-state--bad   { color: var(--wsk-danger-text); font-weight: 600; }
.wsk-state--muted { color: var(--wsk-muted); }

/* ── Docs ─────────────────────────────────────────────────────────────────── */

.wsk-docs { display: flex; gap: 40px; max-width: var(--wsk-maxw); margin: 0 auto; padding: 32px 24px 8px; align-items: flex-start; }
.wsk-docs-sidebar {
    flex: 0 0 210px; position: sticky; top: 76px; display: flex; flex-direction: column; gap: 2px;
    /* Taller than the window once the Account API is listed: it scrolls on its
       own, and reaching its end doesn't carry on into the page. */
    max-height: calc(100vh - 92px); max-height: calc(100dvh - 92px);
    overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; scrollbar-gutter: stable;
    padding: 0 6px 12px 0; margin-right: -6px;
}
/* Narrow screens only: the sticky bar naming the section, with the Contents button. */
.wsk-docs-bar { display: none; }
.wsk-docs-sidebar-title { font-weight: 700; font-size: 0.74rem; text-transform: uppercase; letter-spacing: 0.07em; color: var(--wsk-muted); margin-bottom: 10px; }
.wsk-docs-link { padding: 7px 12px; border-radius: var(--wsk-r-sm); text-decoration: none; color: var(--wsk-text); font-size: 0.92rem; font-weight: 500; }
.wsk-docs-link:hover { background: var(--wsk-bg-tint); color: var(--wsk-ink); }
.wsk-docs-link--active { background: var(--wsk-accent-soft); color: var(--wsk-accent-soft-text); font-weight: 600; }
.wsk-docs-content { flex: 1; min-width: 0; max-width: 760px; }
.wsk-docs-content h1 { font-size: 1.9rem; margin: 0 0 18px; }
.wsk-docs-content h2 { font-size: 1.3rem; margin: 34px 0 12px; padding-top: 10px; }
.wsk-docs-content h3 { font-size: 1.05rem; margin: 22px 0 8px; }
.wsk-docs-content p, .wsk-docs-content li { color: var(--wsk-text); line-height: 1.7; }
/* An ordered walkthrough (Setting up your system): room between the steps. */
.wsk-docs-steps > li { margin-bottom: 10px; }
.wsk-docs-content pre { background: var(--wsk-code-bg); color: var(--wsk-code-text); border-radius: var(--wsk-r-md); padding: 16px 18px; overflow-x: auto; font-size: 0.82rem; line-height: 1.7; box-shadow: var(--wsk-shadow-sm); }
.wsk-docs-content pre code { background: none; color: inherit; font-family: var(--wsk-mono); }
.wsk-docs-content :not(pre) > code { background: var(--wsk-accent-soft); color: var(--wsk-accent-soft-text); padding: 2px 6px; border-radius: 5px; font-size: 0.85em; font-family: var(--wsk-mono); overflow-wrap: anywhere; }
/* In a table cell, whole words: the column is sized to its longest name, so
   unexpected_field isn't split a letter from its end. The table scrolls inside
   its own frame (Ui::scrollTables), never the page. Elsewhere `anywhere` stays:
   an endpoint URL in a flex row must be able to shrink on a narrow phone. */
.wsk-docs-content td > code { overflow-wrap: break-word; }
.wsk-docs-content table { border-collapse: collapse; width: 100%; margin: 16px 0; font-size: 0.9rem; }
.wsk-docs-content th, .wsk-docs-content td { border: 1px solid var(--wsk-border); padding: 9px 12px; text-align: left; }
.wsk-docs-content th { background: var(--wsk-bg-subtle); font-weight: 600; color: var(--wsk-ink); }
.wsk-docs-content blockquote { border-left: 3px solid var(--wsk-accent); margin: 16px 0; padding: 8px 16px; color: var(--wsk-text); background: var(--wsk-accent-soft); border-radius: 0 var(--wsk-r-sm) var(--wsk-r-sm) 0; }
.wsk-docs-content a { font-weight: 500; }
.wsk-docs-content > section { scroll-margin-top: 76px; }
.wsk-docs-content > section + section { margin-top: 8px; }

/* Grouped sidebar */
.wsk-docs-group { display: flex; flex-direction: column; gap: 1px; margin-bottom: 16px; }
.wsk-docs-link { display: block; }
.wsk-docs-group > .wsk-docs-sidebar-title { margin-bottom: 6px; }
.wsk-docs-sublink { padding-left: 22px; font-size: 0.88rem; color: var(--wsk-muted); }

/* Diagrams */
.wsk-doc-figure { margin: 18px 0; text-align: center; }
.wsk-doc-figure img { max-width: 100%; height: auto; background: #fff; border: 1px solid var(--wsk-border); border-radius: var(--wsk-r-md); padding: 18px; box-shadow: var(--wsk-shadow-sm); }
.wsk-doc-figcaption { font-size: 0.82rem; color: var(--wsk-muted); margin-top: 8px; }

/* Endpoint method badge */
.wsk-endpoint { display: flex; align-items: center; gap: 10px; margin: 14px 0; font-family: var(--wsk-mono); }
.wsk-endpoint code { background: var(--wsk-bg-subtle) !important; color: var(--wsk-ink) !important; border: 1px solid var(--wsk-border); padding: 6px 12px !important; border-radius: var(--wsk-r-sm) !important; font-size: 0.85rem !important; }
.wsk-method { font-weight: 700; font-size: 0.72rem; letter-spacing: 0.04em; padding: 5px 10px; border-radius: 6px; color: #fff; }
.wsk-method-post { background: var(--wsk-success-fill); }
.wsk-method-get  { background: var(--wsk-accent); }
.wsk-method-ws   { background: #7c3aed; }
/* White text at 4.5:1 or more in both schemes. */
.wsk-method-patch  { background: #9a6700; }
.wsk-method-delete { background: #b91c1c; }

/* "Keep secret" yes/no + status pills in tables */
.wsk-pill { display: inline-block; font-size: 0.74rem; font-weight: 600; padding: 2px 9px; border-radius: 999px; }
.wsk-pill-yes { background: var(--wsk-danger-soft); color: var(--wsk-danger-text); }
.wsk-pill-no  { background: var(--wsk-success-soft); color: var(--wsk-success-text); }
.wsk-req { color: var(--wsk-danger-text); font-weight: 600; font-size: 0.82rem; }

.wsk-docs-callout {
    display: flex; gap: 12px; background: var(--wsk-warn-soft); border: 1px solid var(--wsk-warn-line); border-radius: var(--wsk-r-md);
    padding: 14px 16px; margin: 18px 0; color: var(--wsk-warn-text); font-size: 0.92rem; line-height: 1.6;
}
.wsk-docs-callout .wsk-callout-icon { flex: 0 0 auto; font-size: 1.1rem; }

/* Stacked on a phone: `stretch`, or the article sizes to its content (up to
   its 760px cap) instead of to the screen, and the page scrolls sideways. */
@media (max-width: 760px) { .wsk-docs { flex-direction: column; align-items: stretch; } }
/* ≤900px (the drawer's `md`): the contents leave the page for the drawer, and
   a bar under the header names the section being read and opens them. */
@media (max-width: 900px) {
    .wsk-docs { padding-top: 20px; }
    .wsk-docs-bar {
        display: flex; align-items: center; gap: 12px; position: sticky; top: 60px; z-index: 20;
        padding: 8px 16px; background: var(--wsk-bg); border-bottom: 1px solid var(--wsk-border);
    }
    .wsk-docs-bar-btn {
        display: inline-flex; align-items: center; gap: 8px; flex: 0 0 auto; min-height: 40px; padding: 0 14px;
        border: 1px solid var(--wsk-border); border-radius: var(--wsk-r-sm); background: var(--wsk-surface);
        color: var(--wsk-ink); font: inherit; font-size: 0.9rem; font-weight: 600; cursor: pointer;
    }
    .wsk-docs-bar-btn:hover { background: var(--wsk-bg-tint); }
    .wsk-docs-bar-btn:focus-visible { outline: 2px solid var(--wsk-accent); outline-offset: 2px; }
    .wsk-docs-bar-current { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--wsk-muted); font-size: 0.9rem; }
    /* In the drawer: a plain list that the drawer body scrolls. */
    .wsk-docs-sidebar { position: static; max-height: none; overflow: visible; padding: 4px 0 16px; margin: 0; }
    .wsk-docs-content > section { scroll-margin-top: calc(60px + 66px); }
}

/* ── Contact / legal ──────────────────────────────────────────────────────── */

.wsk-contact-card { max-width: 620px; margin: 0 auto; }
.wsk-legal { max-width: 720px; margin: 0 auto; }
.wsk-legal h1 { font-size: 2rem; margin-bottom: 14px; }
/* Ui::legalPage: the review banner, the English-only note, Contents, then the document */
.wsk-legal-banner {
    margin: 0 0 24px; padding: 12px 16px; font-size: 0.95rem; line-height: 1.5;
    color: var(--wsk-warn-text); background: var(--wsk-warn-soft);
    border: 1px solid var(--wsk-warn-line); border-left: 4px solid var(--wsk-warn); border-radius: var(--wsk-r-md);
}
.wsk-legal-banner p { margin: 0; }
.wsk-legal-banner strong { color: inherit; }
.wsk-legal-lang {
    margin: 0 0 18px; padding: 8px 12px; font-size: 0.88rem;
    color: var(--wsk-accent-soft-text); background: var(--wsk-accent-soft);
    border-radius: var(--wsk-r-md);
}
.wsk-legal-toc {
    margin: 0 0 28px; padding: 14px 18px;
    background: var(--wsk-bg-subtle); border: 1px solid var(--wsk-border); border-radius: var(--wsk-r-lg);
}
.wsk-legal-doc .wsk-legal-toc-title { margin: 0 0 6px; font-size: 0.78rem; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; color: var(--wsk-muted); }
.wsk-legal-toc ol { margin: 0; padding: 0; list-style: none; columns: 2 220px; column-gap: 24px; font-size: 0.9rem; line-height: 1.7; }
.wsk-legal-toc li { break-inside: avoid; }
.wsk-legal-doc { color: var(--wsk-text); line-height: 1.65; }
/* A link in a list item of the policy text is running text: underline it, as
   base.css does inside a <p> (WCAG 1.4.1). The Contents list is navigation. */
.wsk-legal-doc li a { text-decoration: underline; text-underline-offset: 2px; }
.wsk-legal-toc li a { text-decoration: none; }
.wsk-legal-toc li a:hover { text-decoration: underline; }
.wsk-legal-doc p { margin: 0 0 14px; }
.wsk-legal-doc .wsk-legal-toc { margin: 24px 0 8px; }
.wsk-legal-doc h2 { margin: 36px 0 10px; font-size: 1.3rem; color: var(--wsk-ink); scroll-margin-top: 80px; }
.wsk-legal-doc h3 { margin: 22px 0 8px; font-size: 1.05rem; color: var(--wsk-ink); scroll-margin-top: 80px; }
.wsk-legal-doc ul { padding-left: 22px; }
.wsk-legal-doc ul li { margin-bottom: 6px; }

/* ── Billing receipts ─────────────────────────────────────────────────────── */
.wsk-receipts-table { margin-top: 8px; }
.wsk-receipts-table td, .wsk-receipts-table th { vertical-align: middle; }
.wsk-receipts-table code { background: var(--wsk-bg-subtle); border: 1px solid var(--wsk-border); padding: 2px 7px; border-radius: 5px; font-size: 0.8rem; }
.wsk-receipts-dl { text-align: right; white-space: nowrap; }

/* ── Quickstart card ──────────────────────────────────────────────────────── */
.wsk-quickstart-warning {
    margin: 16px 0 14px; padding: 8px 12px; font-size: 0.82rem;
    color: var(--wsk-warn-text); background: var(--wsk-warn-soft);
    border: 1px solid var(--wsk-warn-line); border-radius: var(--wsk-r-md);
}
.wsk-quickstart-subhead { margin: 18px 0 8px; font-size: 0.95rem; color: var(--wsk-ink-2); }
.wsk-quickstart-subhead:first-of-type { margin-top: 4px; }

/* ── Live debug console ───────────────────────────────────────────────────── */
.wsk-dbg-status {
    display: inline-flex; align-items: center; gap: 7px;
    font-size: 0.82rem; font-weight: 600; color: var(--wsk-muted);
}
.wsk-dbg-dot {
    width: 9px; height: 9px; border-radius: 50%;
    background: var(--wsk-faint); flex: 0 0 auto;
}
.wsk-dbg-status[data-state="connecting"] { color: var(--wsk-warn-text); }
.wsk-dbg-status[data-state="connecting"] .wsk-dbg-dot { background: var(--wsk-warn); animation: wsk-dbg-pulse 1.1s ease-in-out infinite; }
.wsk-dbg-status[data-state="connected"] { color: var(--wsk-success-text); }
.wsk-dbg-status[data-state="connected"] .wsk-dbg-dot { background: var(--wsk-success); }
@keyframes wsk-dbg-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }

.wsk-dbg-controls { display: flex; align-items: flex-end; gap: 10px; }
.wsk-dbg-controls .form-group { flex: 1 1 auto; margin-bottom: 0; }

.wsk-dbg-meta {
    display: flex; gap: 20px; margin: 12px 0 8px;
    font-size: 0.82rem; color: var(--wsk-muted);
}
.wsk-dbg-meta strong { color: var(--wsk-ink-2); }

.wsk-dbg-log {
    margin: 4px 0 16px; max-height: 280px; overflow-y: auto;
    background: var(--wsk-code-bg); border-radius: var(--wsk-r-md);
    padding: 10px 12px; font-family: var(--wsk-mono); font-size: 0.78rem;
}
/* On the console's own dark surface in both schemes: its dim text, not the page's muted. */
.wsk-dbg-empty.u-muted { margin: 6px 2px; font-family: inherit; color: var(--wsk-code-dim); }
.wsk-dbg-frame {
    display: grid; grid-template-columns: auto auto auto 1fr; gap: 10px;
    padding: 4px 2px; line-height: 1.5;
    border-bottom: 1px solid rgba(148, 163, 184, 0.10); white-space: nowrap;
}
.wsk-dbg-frame:first-child { animation: wsk-dbg-flash 0.6s ease-out; }
.wsk-dbg-frame-time  { color: var(--wsk-code-dim); }
.wsk-dbg-frame-chan  { color: #7dd3fc; }
.wsk-dbg-frame-event { color: #a5b4fc; font-weight: 600; }
.wsk-dbg-frame-data  { color: var(--wsk-code-text); overflow: hidden; text-overflow: ellipsis; }
@keyframes wsk-dbg-flash { from { background: rgba(125, 211, 252, 0.16); } to { background: transparent; } }

.wsk-dbg-send { display: flex; align-items: flex-start; gap: 10px; flex-wrap: wrap; }
.wsk-dbg-send .form-group { margin-bottom: 0; }
.wsk-dbg-send .form-group--textarea { flex: 1 1 240px; }
/* The empty label lines the Send button up with the fields' controls. */
.wsk-dbg-send-action { flex: 0 0 auto; }
/* Under the send row: keep the test message as the channel's retained one. */
.wsk-dbg-retain { margin-top: 10px; }
.wsk-dbg-retain .form-group { margin-bottom: 0; }
/* Sits inside the dark log, so it carries its own light-on-dark colours. */
.wsk-dbg-retained { margin-left: 6px; padding: 0 7px; background: rgba(125, 211, 252, 0.16); color: #7dd3fc; font-family: var(--wsk-font); }

/* ── Retained messages card ───────────────────────────────────────────────── */
.wsk-retained-table code { font-family: var(--wsk-mono); font-size: 0.82rem; }
.wsk-retained-actions { text-align: right; white-space: nowrap; }
.wsk-retained-detail > td { padding-top: 0; }
.wsk-retained-data {
    margin: 0; max-height: 240px; overflow: auto;
    background: var(--wsk-code-bg); color: var(--wsk-code-text); border-radius: var(--wsk-r-md);
    padding: 10px 12px; font-family: var(--wsk-mono); font-size: 0.78rem;
}

/* ── Message replay card ──────────────────────────────────────────────────── */
.wsk-replay-upsell { margin: 12px 0 0; }

/* ── Delivery receipts card ───────────────────────────────────────────────── */
.wsk-receipts-controls { margin-bottom: 10px; }
.wsk-receipts-summary { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin: 0 0 10px; }
.wsk-receipts-summary .wsk-pill { background: var(--wsk-bg-subtle); color: var(--wsk-text); }
.wsk-receipts-table code { font-family: var(--wsk-mono); font-size: 0.82rem; }
.wsk-receipt-current { background: var(--wsk-success-soft); color: var(--wsk-success-text); }
.wsk-receipt-behind  { background: var(--wsk-warn-soft); color: var(--wsk-warn-text); }
.wsk-receipts-missing { margin: 10px 0 0; }
.wsk-receipts-missing code { font-family: var(--wsk-mono); font-size: 0.82rem; }

/* ── Connection domain card ───────────────────────────────────────────────── */
.wsk-dom-current {
    margin: 0 0 16px; padding: 10px 12px;
    background: var(--wsk-bg-subtle); border: 1px solid var(--wsk-border);
    border-radius: var(--wsk-r-md); font-size: 0.86rem;
}
.wsk-dom-current code { font-family: var(--wsk-mono); font-size: 0.82rem; }
.wsk-dom-wsurl { margin-top: 6px; }
.wsk-dom-block { margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--wsk-border); }
.wsk-dom-block:first-of-type { border-top: none; padding-top: 0; }
.wsk-dom-subhead { margin: 0 0 10px; font-size: 0.95rem; color: var(--wsk-ink-2); }

.wsk-dom-sub { display: flex; align-items: flex-end; gap: 4px; }
.wsk-dom-sub .form-group { flex: 0 1 240px; margin-bottom: 0; }
.wsk-dom-suffix {
    padding-bottom: 9px; color: var(--wsk-muted);
    font-family: var(--wsk-mono); font-size: 0.85rem; white-space: nowrap;
}

.wsk-dom-block .btn { margin-top: 12px; margin-right: 8px; }
.wsk-dom-add { margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--wsk-border); }
.wsk-dom-add .wsk-dom-block { margin-top: 12px; }
.wsk-dom-add .wsk-dom-block:first-of-type { border-top: none; padding-top: 0; }
.wsk-dom-add h4.wsk-dom-subhead { font-size: 0.9rem; }
.wsk-dom-choice-confirm .btn { margin-top: 0; }
.wsk-dom-upsell { margin: 16px 0 0; }
/* The customer's domains: one row each, the host and its state, then what
   uses it, then its actions (wrapping under each other on a phone). */
.wsk-dom-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.wsk-dom-item { padding: 12px 14px; border: 1px solid var(--wsk-border); border-radius: 10px; min-width: 0; }
.wsk-dom-item-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px; }
.wsk-dom-item-head code { font-family: var(--wsk-mono); font-size: 0.85rem; overflow-wrap: anywhere; }
.wsk-dom-item-meta { margin: 4px 0 0; font-size: 0.85rem; }
.wsk-dom-item-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.wsk-dom-item-actions .btn { margin: 0; }
.wsk-dom-pending .btn { margin-top: 12px; margin-right: 8px; }
.wsk-dom-pending .wsk-dns-records { margin: 12px 0; }
.wsk-dom-choice .radio-group code { font-family: var(--wsk-mono); }

.wsk-dns-records { margin: 20px 0; display: flex; flex-direction: column; gap: 8px; }
.wsk-dns-rec {
    display: flex; align-items: center; gap: 12px;
    padding: 8px 12px; background: var(--wsk-code-bg);
    border-radius: var(--wsk-r-md); overflow: hidden;
}
.wsk-dns-type {
    flex: 0 0 56px; font-family: var(--wsk-mono); font-size: 0.74rem;
    font-weight: 700; color: #a5b4fc; letter-spacing: 0.04em;
}
.wsk-dns-fields { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.wsk-dns-fields code {
    font-family: var(--wsk-mono); font-size: 0.78rem; background: none;
    color: var(--wsk-code-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.wsk-dns-name { color: var(--wsk-code-dim) !important; }
.wsk-dns-rec .wsk-copy-btn { flex: 0 0 auto; align-self: center; }

/* Allowed-websites card: the one-line summary above the editor */
.wsk-origins-state { font-weight: 600; margin: 0 0 6px; color: var(--wsk-ink); }

/* ── /admin/activity: every customer's usage over five windows ── */
.wsk-activity-header { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px 16px; }
.wsk-activity-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.wsk-activity-tools { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 12px 20px; margin-bottom: 14px; }
.wsk-activity-filter { margin: 0; min-width: min(100%, 260px); }
.wsk-activity-table { width: 100%; }
.wsk-activity-table .wsk-num { text-align: end; font-variant-numeric: tabular-nums; white-space: nowrap; }
/* Row headers (customer, project) read as cells, not as the column heads. */
.wsk-activity-table tbody th[scope="row"] {
    font-weight: 500; text-align: start; text-transform: none; letter-spacing: normal;
    font-size: inherit; color: var(--wsk-ink); background: transparent;
}
.wsk-activity-table .wsk-activity-totals th[scope="row"],
.wsk-activity-table .wsk-activity-totals td { font-weight: 700; color: var(--wsk-ink); background: var(--wsk-bg-subtle); }
.wsk-activity-customer th[scope="row"] { white-space: nowrap; }
.wsk-activity-project th[scope="row"] { padding-left: 34px; font-weight: 400; }
.wsk-activity-project th, .wsk-activity-project td { font-size: 0.86rem; color: var(--wsk-text); }
.wsk-activity-project code { font-size: 0.78rem; color: var(--wsk-muted); }
.wsk-activity-expand {
    width: 24px; height: 24px; border: 0; border-radius: var(--wsk-r-sm); background: transparent; color: var(--wsk-muted);
    cursor: pointer; transition: transform .15s, background .15s;
}
.wsk-activity-expand:hover { background: var(--wsk-bg-tint); }
.wsk-activity-expand[aria-expanded="true"] { transform: rotate(90deg); }
.wsk-activity-sort {
    border: 0; background: transparent; padding: 0; font: inherit; color: inherit; cursor: pointer;
    text-transform: none; letter-spacing: normal;   /* "5m", not "5M" (five months?) */
}
.wsk-activity-sort::after { content: ""; display: inline-block; width: 1em; }
th[aria-sort="descending"] .wsk-activity-sort::after { content: "↓"; }
th[aria-sort="ascending"] .wsk-activity-sort::after { content: "↑"; }
.wsk-activity [data-m] { display: none; }
.wsk-activity[data-metric="messages"] [data-m="messages"],
.wsk-activity[data-metric="connections"] [data-m="connections"],
.wsk-activity[data-metric="channels"] [data-m="channels"] { display: inline; }
.wsk-activity [data-m] small { display: block; font-size: 0.72rem; font-weight: 400; color: var(--wsk-muted); }
#wsk-activity-show-quiet { margin-top: 12px; }
.wsk-activity-note { margin: 14px 0 0; font-size: 0.82rem; }
.wsk-activity-lastrun { margin: 0 0 14px; padding-left: 18px; font-size: 0.88rem; }
