/* Knowledge Base shared shell — tab strip + 3-column grid + TOC rail.
 *
 * Loaded by every page under /knowledge-base/ alongside their existing
 * stylesheets (knowledge-base.css, handbook.css). This file owns the
 * cross-tab chrome only — tab strip, the 3-column layout for view
 * pages, and the right-side TOC rail. Per-section content styling
 * stays in its own stylesheet.
 */

/* ─── Full-width docs mode ─────────────────────────────────── *
 * KB pages opt out of the portal's main left navigation so they
 * read like a documentation site. The `data-kb-fullwidth="1"`
 * attribute on <html> hides #nav and reclaims main's left padding.
 * Topbar / hero stay rendered.
 */

html[data-kb-fullwidth="1"] #nav,
html[data-kb-fullwidth="1"] header#topbar,
html[data-kb-fullwidth="1"] #dmu-tabs {
    display: none !important;
}

html[data-kb-fullwidth="1"] main,
html[data-kb-fullwidth="1"] body.dmu-tabs-visible main {
    padding-left: 0 !important;
    padding-right: 0 !important;
    padding-bottom: 0 !important;
    margin-left: 0 !important;
    margin-top: 0 !important;
}

/* css/base/main.css applies `overflow-x: hidden` to html and body, which
 * breaks `position: sticky` on descendants in some browsers. Reset
 * to visible on KB pages so the left sidenav and right TOC rail
 * actually stick when the page scrolls.
 */
html[data-kb-fullwidth="1"],
html[data-kb-fullwidth="1"] body {
    overflow-x: visible !important;
    overflow-y: visible !important;
}

html[data-kb-fullwidth="1"] main,
html[data-kb-fullwidth="1"] #root {
    overflow: visible !important;
}

/* ─── Top tab strip ─────────────────────────────────────────── */

/* Sticky chrome geometry. The header pins to top:0; the tab strip
 * sticks below the header; sidenav and TOC rail stick below both.
 */
:root {
    --kb-header-height: 60px;
    --kb-tabs-height: 44px;
    --kb-chrome-height: calc(var(--kb-header-height) + var(--kb-tabs-height));
}

/* ─── Top header bar ─────────────────────────────────────── */

.kb-header {
    position: sticky;
    top: 0;
    z-index: 20;
    background-color: #ffffff;
    border-bottom: 1px solid rgba(0, 0, 0, 0.06);
    width: 100%;
}

.kb-header-inner {
    display: grid;
    grid-template-columns: 1fr minmax(0, 480px) 1fr;
    align-items: center;
    gap: 1.5rem;
    max-width: 1560px;
    margin: 0 auto;
    padding: 0.55rem 1.5rem;
    min-height: var(--kb-header-height);
}

.kb-header-brand {
    display: flex;
    align-items: center;
    text-decoration: none;
    color: inherit;
    line-height: 1;
    padding-left: 1rem;
}

.kb-header-brand-logo {
    height: 18px;
    width: auto;
    display: block;
}

.kb-header-search {
    grid-column: 2;
    position: relative;
    display: flex;
    align-items: center;
    width: 100%;
}

.kb-header-search-icon {
    position: absolute;
    left: 0.7rem;
    width: 16px !important;
    height: 16px !important;
    color: rgba(0, 0, 0, 0.45);
    pointer-events: none;
}

.kb-header-search-input {
    width: 100%;
    height: 36px;
    padding: 0 0.85rem 0 2.1rem;
    background-color: rgba(0, 0, 0, 0.04);
    border: 1px solid rgba(0, 0, 0, 0.08);
    border-radius: 0.6rem;
    font-size: 0.875rem;
    color: var(--body);
    outline: none;
    transition: background 0.15s ease, border-color 0.15s ease;
}

.kb-header-search-input::placeholder {
    color: rgba(0, 0, 0, 0.4);
}

.kb-header-search-input:focus {
    background-color: #ffffff;
    border-color: rgba(0, 0, 0, 0.18);
}

.kb-header-actions {
    grid-column: 3;
    justify-self: end;
    display: flex;
    align-items: center;
    gap: 0.65rem;
}

/* Circular icon button — links to the portal dashboard. */
.kb-header-dashboard {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background-color: rgba(0, 0, 0, 0.04);
    color: var(--body);
    text-decoration: none;
    border: 1px solid rgba(0, 0, 0, 0.08);
    transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.kb-header-dashboard:hover {
    background-color: rgba(0, 0, 0, 0.08);
    color: var(--body);
}

.kb-header-dashboard i[data-lucide] {
    width: 16px !important;
    height: 16px !important;
}

/* ─── Tab strip (now nested inside the sticky .kb-header) ──── */

/* Outer wrapper: full-width white background. No border-bottom — the
 * containing .kb-header already draws the line at the bottom of the
 * whole sticky chrome. Stacking both produced a visible 2px line.
 * The whole .kb-header is sticky, so the tabs come along for free.
 */
.kb-tabs {
    background-color: #ffffff;
    width: 100%;
}

/* Inner: max-width container holding the actual tab links, aligned
 * with .kb-shell's max-width / padding so the content edges line up.
 */
.kb-tabs-inner {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    margin: 0 auto;
    padding: 0 1.5rem;
    max-width: 1560px;
    width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
}

.kb-tabs-inner::-webkit-scrollbar { display: none; }

.kb-tab {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.65rem 1rem;
    font-size: 0.875rem;
    font-weight: 500;
    color: rgba(0, 0, 0, 0.62);
    text-decoration: none;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
    white-space: nowrap;
    transition: color 120ms ease, border-color 120ms ease;
}

.kb-tab i[data-lucide] {
    width: 14px !important;
    height: 14px !important;
    opacity: 0.85;
}

.kb-tab:hover {
    color: var(--bs-body-color, #1f2937);
    border-bottom-color: rgba(0, 0, 0, 0.12);
}

.kb-tab--active,
.kb-tab--active:hover {
    color: var(--primary);
    border-bottom-color: var(--primary);
}

[data-bs-theme="dark"] .kb-tab {
    color: rgba(255, 255, 255, 0.65);
}
[data-bs-theme="dark"] .kb-tab:hover {
    color: rgba(255, 255, 255, 0.95);
    border-bottom-color: rgba(255, 255, 255, 0.18);
}

/* ─── 3-column shell (left sidebar / content / TOC) ───────── */

.kb-shell {
    display: grid;
    grid-template-columns: 340px minmax(0, 1fr) 260px;
    gap: 2.5rem;
    align-items: start;
    max-width: 1560px;
    margin: 0 auto;
    padding: 0 1.5rem;
    width: 100%;
}

/* List / landing pages (no per-page TOC): 2 columns — sidebar + content. */
.kb-shell--no-toc {
    grid-template-columns: 340px minmax(0, 1fr);
}

/* Empty section landing — no sidebar; content takes the full width
 * so the centred empty-state component reads as the focal point. */
.kb-shell--empty {
    grid-template-columns: minmax(0, 1fr);
}

.kb-shell .kb-content-pane {
    min-width: 0; /* flex/grid escape for long inline content */
}

/* Make the inner doc fill the column without auto-margin centring. */
.kb-shell .kb-doc {
    margin-left: 0;
    margin-right: 0;
    max-width: none;
}

/* ─── Left section sidebar (Portal Guide / Customer Docs / Handbook) ─ */

.kb-sidenav {
    position: sticky;
    top: var(--kb-chrome-height);
    /* Always full viewport-below-chrome so the right border draws an
     * uninterrupted vertical line from the chrome to the viewport
     * bottom — even when the nav has only a few items. Internal
     * overflow still scrolls within. */
    height: calc(100vh - var(--kb-chrome-height));
    overflow-y: auto;
    padding: 1rem 1.5rem 1.5rem 0.5rem;
    border-right: 1px solid rgba(0, 0, 0, 0.08);
    font-size: 0.875rem;
    line-height: 1.4;
}

[data-bs-theme="dark"] .kb-sidenav,
html[data-color^="dark-"] .kb-sidenav {
    border-right-color: rgba(255, 255, 255, 0.08);
}

.kb-sidenav-empty {
    color: rgba(0, 0, 0, 0.55);
    font-size: 0.85rem;
    padding: 0.5rem;
}

.kb-sidenav-section {
    margin-bottom: 1.5rem;
}

/* Row holding (title + toggle button) for sections and groups.
 * Mirrors the .dmu-dropdown-link aesthetic — same hover/active
 * background tokens so theme switching propagates for free.
 */
.kb-sidenav-row {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    border-radius: 0.8rem;
    margin: 0.05rem 0;
    transition: background 0.15s ease, color 0.15s ease;
}

.kb-sidenav-row:hover {
    background-color: var(--dmu-dropdown-hover-bg, rgba(0, 0, 0, 0.06));
}

.kb-sidenav-row:hover .kb-sidenav-section-title,
.kb-sidenav-row:hover .kb-sidenav-group-title {
    color: var(--body);
}

.kb-sidenav-row:hover .kb-sidenav-toggle {
    color: var(--body);
}

/* Active row — applied when the section's or subcategory's own
 * landing page is the current page. Sub-items active state stays
 * on their own .kb-sidenav-link rule.
 */
.kb-sidenav-row.is-active-row {
    background-color: var(--dmu-dropdown-hover-bg, rgba(0, 0, 0, 0.06));
}

.kb-sidenav-row.is-active-row .kb-sidenav-group-title,
.kb-sidenav-row.is-active-row .kb-sidenav-section-title {
    color: var(--body);
    font-weight: 500;
}

.kb-sidenav-row > .kb-sidenav-section-title,
.kb-sidenav-row > .kb-sidenav-group-title {
    flex: 1 1 auto;
    min-width: 0;
}

/* Chevron toggle button — rendered only when the section/group has
 * children. Transparent — the row's hover background does the work. */
.kb-sidenav-toggle {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    margin-right: 0.15rem;
    padding: 0;
    background: transparent;
    border: 0;
    border-radius: 4px;
    color: rgba(0, 0, 0, 0.45);
    cursor: pointer;
    transition: color 120ms ease;
}

/* Selector matches both the pre-hydration <i data-lucide="…"> tag
 * and the <svg data-lucide="…"> that lucide.createIcons() swaps it
 * for. Without the svg branch the transition + rotation below
 * silently stop applying after icons hydrate, so the chevron
 * would snap instead of animating. */
.kb-sidenav-toggle i[data-lucide],
.kb-sidenav-toggle svg[data-lucide] {
    width: 14px !important;
    height: 14px !important;
    transition: transform 180ms ease;
}

/* Collapsible groups animate via max-height. The expanded value is a
 * generous viewport-relative cap so any reasonable list fits; the
 * transition snaps to 0 on collapse. overflow:hidden clips during
 * the animation so children don't visibly poke out.
 */
.kb-sidenav-section > .kb-sidenav-list,
.kb-sidenav-group > .kb-sidenav-list {
    overflow: hidden;
    max-height: 200vh;
    transition: max-height 220ms ease;
}

.kb-sidenav-section:not(.is-expanded) > .kb-sidenav-list,
.kb-sidenav-group:not(.is-expanded) > .kb-sidenav-list {
    max-height: 0;
}

.kb-sidenav-section:not(.is-expanded) > .kb-sidenav-row .kb-sidenav-toggle i[data-lucide],
.kb-sidenav-section:not(.is-expanded) > .kb-sidenav-row .kb-sidenav-toggle svg[data-lucide],
.kb-sidenav-group:not(.is-expanded)   > .kb-sidenav-row .kb-sidenav-toggle i[data-lucide],
.kb-sidenav-group:not(.is-expanded)   > .kb-sidenav-row .kb-sidenav-toggle svg[data-lucide] {
    transform: rotate(-90deg);
}

[data-bs-theme="dark"] .kb-sidenav-toggle {
    color: rgba(255, 255, 255, 0.5);
}
[data-bs-theme="dark"] .kb-sidenav-toggle:hover {
    background: rgba(255, 255, 255, 0.07);
    color: rgba(255, 255, 255, 0.95);
}

.kb-sidenav-section-title {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    color: var(--body);
    font-size: 0.9rem;
    font-weight: 600;
    text-decoration: none;
    padding: 0.5rem 0.6rem;
    border-radius: 0.8rem;
}

.kb-sidenav-section-title i[data-lucide] {
    width: 12px !important;
    height: 12px !important;
    opacity: 0.7;
}

.kb-sidenav-list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.kb-sidenav-list li {
    margin: 0;
    padding: 0;
}

.kb-sidenav-link,
.kb-sidenav-group-title {
    display: flex;
    align-items: flex-start;
    gap: 0.55rem;
    padding: 0.5rem 0.6rem;
    color: var(--body);
    font-size: 0.82rem;
    font-weight: 400;
    line-height: 1.35;
    text-decoration: none;
    border-radius: 0.8rem;
    transition: background 0.15s ease, color 0.15s ease;
}

/* Slight nudge so the icon visually aligns with the first line of
 * the label even when the label wraps. */
.kb-sidenav-link .kb-sidenav-link-icon,
.kb-sidenav-group-title .kb-sidenav-link-icon {
    margin-top: 1px;
}

.kb-sidenav-link-icon {
    flex: 0 0 auto;
    width: 16px !important;
    height: 16px !important;
    opacity: 0.78;
}

.kb-sidenav-link-label {
    min-width: 0;
    overflow: hidden;
    /* Wrap long titles to two lines max with ellipsis on overflow. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    word-break: break-word;
    line-height: 1.3;
}

/* Standalone leaf link (article) — owns its own hover/active because
 * it isn't wrapped in a .kb-sidenav-row. */
.kb-sidenav-link {
    margin: 0.05rem 0;
}

.kb-sidenav-link:hover {
    background-color: var(--dmu-dropdown-hover-bg, rgba(0, 0, 0, 0.06));
    color: var(--body);
}

.kb-sidenav-link.is-active {
    background-color: var(--dmu-dropdown-hover-bg, rgba(0, 0, 0, 0.06));
    color: var(--body);
    font-weight: 500;
}

/* Group title sits inside .kb-sidenav-row; row owns hover/active. */
.kb-sidenav-row > .kb-sidenav-group-title {
    color: var(--body);
}

.kb-sidenav-group .kb-sidenav-list {
    border-left: 1px solid rgba(0, 0, 0, 0.07);
    margin-left: 0.6rem;
    padding-left: 0.6rem;
    margin-top: 0.1rem;
}

/* Dark mode is handled automatically — the --dmu-dropdown-* tokens
 * flip under html[data-color^="dark-"] (see css/layout/header.css), so
 * hover, active, and text colors track the theme without extra rules.
 * Only the structural border on nested groups needs a dark-side adjust.
 */
html[data-color^="dark-"] .kb-sidenav-group .kb-sidenav-list {
    border-left-color: rgba(255, 255, 255, 0.08);
}

/* ─── Right-side TOC rail ─────────────────────────────────── */

.kb-toc-rail {
    position: sticky;
    top: var(--kb-chrome-height);
    max-height: calc(100vh - var(--kb-chrome-height));
    /* Overflow stays visible on the aside so the page-actions
     * dropdown can extend beyond the column's right edge. The
     * sub-container below owns the TOC's own scroll behavior. */
    overflow: visible;
    font-size: 0.8125rem;
    /* Top spacing matches the content column's .kb-doc padding-top
     * (1.5rem from knowledge-base.css) so the "On this page" label
     * lines up with the breadcrumb. Sidebar's first item also lands
     * at 1.5rem (1rem sidenav padding + 0.5rem section-title
     * padding), so all three columns share the same baseline. */
    padding: 1.5rem 0;
}

/* TOC list scroll context — long handbook pages would overflow the
 * viewport-minus-chrome height; the inner container scrolls so the
 * aside itself stays overflow:visible (see comment above). */
.kb-toc-rail-content {
    max-height: calc(100vh - var(--kb-chrome-height) - 6rem);
    overflow-y: auto;
}

.kb-toc-rail .kb-toc-rail-title {
    font-weight: 600;
    font-size: 0.75rem;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: rgba(0, 0, 0, 0.55);
    margin: 0 0 0.5rem 0.5rem;
}

.kb-toc-rail-list {
    list-style: none;
    margin: 0;
    padding: 0;
    border-left: 1px solid rgba(0, 0, 0, 0.08);
}

.kb-toc-rail-list li { margin: 0; padding: 0; }

.kb-toc-rail-list a {
    display: block;
    padding: 0.3rem 0.75rem;
    color: rgba(0, 0, 0, 0.65);
    text-decoration: none;
    border-left: 2px solid transparent;
    margin-left: -1px;
    line-height: 1.35;
    transition: color 120ms ease, border-left-color 120ms ease;
}

.kb-toc-rail-list a:hover {
    color: var(--primary);
}

.kb-toc-rail-list .kb-toc-rail-h3 a {
    padding-left: 1.5rem;
}

.kb-toc-rail-list a.is-active {
    color: var(--primary);
    border-left-color: var(--primary);
}

[data-bs-theme="dark"] .kb-toc-rail .kb-toc-rail-title {
    color: rgba(255, 255, 255, 0.55);
}
[data-bs-theme="dark"] .kb-toc-rail-list {
    border-left-color: rgba(255, 255, 255, 0.1);
}
[data-bs-theme="dark"] .kb-toc-rail-list a {
    color: rgba(255, 255, 255, 0.7);
}

/* ─── Mobile search icon — hidden on desktop ────────────────── */

.kb-header-search-icon-btn {
    display: none;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    padding: 0;
    background: transparent;
    border: 0;
    border-radius: 8px;
    color: var(--body);
    cursor: pointer;
    flex-shrink: 0;
    transition: background 0.15s ease;
}
.kb-header-search-icon-btn:hover {
    background: rgba(0, 0, 0, 0.05);
}
.kb-header-search-icon-btn i[data-lucide] {
    width: 20px !important;
    height: 20px !important;
}

/* ─── Sidebar burger — mobile-only display, but visual styling
 *     comes from .kb-header-dashboard so it matches the theme /
 *     login / profile icons in the top-right cluster. ──────── */

.kb-header-burger { display: none; }

/* Wrapper for the second header row (burger + tab strip). It's a
 * transparent flex container — on desktop the burger is hidden so
 * the row just contains the tabs (or nothing, for customers); on
 * mobile the burger sits flush-left of the tabs. */
.kb-header-bottom-row {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    width: 100%;
}
.kb-header-bottom-row > .kb-tabs {
    flex: 1 1 auto;
    min-width: 0;
}

/* Mobile sidebar backdrop — hidden by default; revealed by
 * body.kb-sidenav-open while inside the mobile breakpoint. Stacks
 * above the sticky .kb-header (z-index: 20) so the dim covers the
 * full viewport, not just the area below the chrome. */
.kb-sidenav-backdrop {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 1040;
    background: rgba(15, 15, 20, 0.45);
}

/* ─── Tablet: hide right TOC rail, keep sidebar visible ───── */

@media (max-width: 1100px) {
    .kb-shell {
        grid-template-columns: 280px minmax(0, 1fr);
        gap: 1.5rem;
    }
    .kb-toc-rail { display: none; }
}

/* ─── Mobile: sidebar becomes an off-canvas drawer ────────── */

@media (max-width: 992px) {
    .kb-shell,
    .kb-shell--no-toc,
    .kb-shell--empty {
        grid-template-columns: minmax(0, 1fr);
        gap: 0;
    }

    /* Burger now lives in the bottom row, flush-left of the tabs. */
    .kb-header-burger { display: inline-flex; }

    /* Swap the desktop search input for the icon button next to the
     * home/profile cluster. The middle grid column (which held the
     * search) collapses so brand + actions sit at the row's edges. */
    .kb-header-inner {
        grid-template-columns: 1fr auto;
    }
    .kb-header-search { display: none; }
    .kb-header-search-icon-btn { display: inline-flex; }

    /* Tighten paddings on the bottom row so the burger sits close
     * to the tabs without an awkward gap on small screens. */
    .kb-header-bottom-row {
        padding: 0 0.5rem;
        gap: 0.1rem;
    }
    .kb-header-bottom-row .kb-tabs-inner {
        padding: 0;
    }

    .kb-sidenav {
        position: fixed;
        top: 0;
        left: 0;
        z-index: 1050;
        width: 320px;
        max-width: 86vw;
        height: 100vh;
        background: #ffffff;
        border-right: 1px solid rgba(0, 0, 0, 0.1);
        box-shadow: 4px 0 18px -10px rgba(0, 0, 0, 0.25);
        transform: translateX(-100%);
        transition: transform 220ms ease;
        overflow-y: auto;
    }

    body.kb-sidenav-open .kb-sidenav {
        transform: translateX(0);
    }

    body.kb-sidenav-open .kb-sidenav-backdrop {
        display: block;
    }

    /* Prevent body scroll while the drawer is open. */
    body.kb-sidenav-open {
        overflow: hidden;
    }

    /* KB has its own mobile navigation (header + burger drawer);
     * hide the portal's global bottom nav so users don't see two
     * navs at once. Scoped to KB pages via [data-kb-fullwidth]. */
    html[data-kb-fullwidth] .dmu-bottom-nav {
        display: none !important;
    }
}

/* Drop the bottom-nav clearance padding on KB pages — the nav is
 * hidden here (rule above), so the reserved space would just be an
 * empty band at the bottom of the viewport. Mirrors the 991.98px
 * breakpoint used by app/bottom-nav.css so this override catches
 * exactly the same range. */
@media (max-width: 991.98px) {
    html[data-kb-fullwidth] body {
        padding-bottom: 0;
    }
}

/* The portal's mobile breadcrumb strip (from layout) is
 * redundant on KB pages — the KB chrome has its own breadcrumb
 * inside .kb-doc-meta / .kb-breadcrumb. Hide it on every viewport,
 * not just mobile, so it never leaks in. */
html[data-kb-fullwidth] .dmu-mobile-breadcrumbs {
    display: none !important;
}

[data-bs-theme="dark"] .kb-sidenav-backdrop,
html[data-color^="dark-"] .kb-sidenav-backdrop {
    background: rgba(0, 0, 0, 0.55);
}
/* Burger dark-mode rules removed — the .kb-header-dashboard class
   on the same element provides matching dark-mode styling. */
@media (max-width: 992px) {
    [data-bs-theme="dark"] .kb-sidenav,
    html[data-color^="dark-"] .kb-sidenav {
        background: #1c1c22;
        border-right-color: rgba(255, 255, 255, 0.08);
    }
}

/* ─── KB home — group titles ──────────────────────────── */

.kb-group-title {
    margin: 1.75rem 0 1rem;
    font-size: 1.1rem;
    font-weight: 700;
    color: var(--body);
    line-height: 1.3;
}

.kb-department:first-child .kb-group-title {
    margin-top: 0.25rem;
}

/* ─── KB home — category cards (gradient banner + icon + title + action) ─── */

/* Override the legacy 3-column grid from knowledge-base.css to fit the
 * new wider cards on KB home. Two cards per row in the content column,
 * stacks to one column under 700px. */
.kb-shell .kb-categories {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 1.25rem;
}

@media (max-width: 700px) {
    .kb-shell .kb-categories {
        grid-template-columns: minmax(0, 1fr);
    }
}

.kb-card {
    display: flex;
    flex-direction: column;
    background-color: #ffffff;
    border: 1px solid rgba(0, 0, 0, 0.06);
    border-radius: 1rem;
    overflow: hidden;
    text-decoration: none;
    color: inherit;
    transition: transform 0.18s ease, box-shadow 0.18s ease, border-color 0.18s ease;
}

.kb-card:hover {
    transform: translateY(-2px);
    border-color: rgba(0, 0, 0, 0.12);
    box-shadow: 0 8px 24px -12px rgba(0, 0, 0, 0.18);
    color: inherit;
}

.kb-card-banner {
    position: relative;
    aspect-ratio: 21 / 9;
    display: flex;
    align-items: center;
    justify-content: center;
    background: linear-gradient(135deg, #ffd6e0 0%, #d4e7ff 50%, #ffe6c4 100%);
    margin: 0.5rem 0.5rem 0;
    border-radius: 0.75rem;
}

.kb-card-icon-tile {
    width: 64px;
    height: 64px;
    border-radius: 14px;
    background-color: #ffffff;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 6px 16px -8px rgba(0, 0, 0, 0.18);
}

.kb-card-icon-tile i[data-lucide] {
    width: 38px !important;
    height: 38px !important;
    color: rgba(0, 0, 0, 0.85);
}

.kb-card-body {
    padding: 0.85rem 1.1rem 0.95rem;
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    flex: 1 1 auto;
}

.kb-card-title {
    margin: 0;
    font-size: 0.95rem;
    font-weight: 700;
    color: var(--body);
    line-height: 1.3;
    transition: color 0.15s ease;
}

.kb-card:hover .kb-card-title {
    color: var(--primary);
}

.kb-card-desc {
    margin: 0;
    font-size: 0.82rem;
    color: var(--alternate);
    line-height: 1.4;
    flex: 1 1 auto;
}

/* Gradient variants — six pastel banner palettes that cycle by
 * category id. Each is applied via .kb-card--g0 … .kb-card--g5. */
.kb-card--g0 .kb-card-banner {
    background: linear-gradient(135deg, #ffd6e0 0%, #d4e7ff 50%, #ffe6c4 100%);
}
.kb-card--g1 .kb-card-banner {
    background: linear-gradient(135deg, #fff3c4 0%, #c4f0d6 55%, #ffd6c4 100%);
}
.kb-card--g2 .kb-card-banner {
    background: linear-gradient(135deg, #c4ecd8 0%, #c4ebf5 100%);
}
.kb-card--g3 .kb-card-banner {
    background: linear-gradient(135deg, #ffd6ec 0%, #d8c8ff 100%);
}
.kb-card--g4 .kb-card-banner {
    background: linear-gradient(135deg, #ffe1d4 0%, #d4e7ff 50%, #c4f0e3 100%);
}
.kb-card--g5 .kb-card-banner {
    background: linear-gradient(135deg, #c4ecd8 0%, #cbe6ff 50%, #ffd6d6 100%);
}

[data-bs-theme="dark"] .kb-card,
html[data-color^="dark-"] .kb-card {
    background-color: rgba(255, 255, 255, 0.03);
    border-color: rgba(255, 255, 255, 0.08);
}
[data-bs-theme="dark"] .kb-card:hover,
html[data-color^="dark-"] .kb-card:hover {
    border-color: rgba(255, 255, 255, 0.18);
    box-shadow: 0 8px 24px -12px rgba(0, 0, 0, 0.6);
}
[data-bs-theme="dark"] .kb-card-icon-tile,
html[data-color^="dark-"] .kb-card-icon-tile {
    background-color: rgba(255, 255, 255, 0.92);
}

/* ──────────────────────────────────────────────
 * Documentation-style minimal cards
 * Used on subcategory pages: lucide icon, bold
 * title, muted description in a 2-column grid.
 * Lives alongside .kb-post-item so admin Sortable
 * still drags the same <li>s.
 * ────────────────────────────────────────────── */
.kb-doc-cards {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.75rem;
    list-style: none;
    padding: 0;
    margin: 0;
}

@media (max-width: 768px) {
    .kb-doc-cards { grid-template-columns: 1fr; }
}

/* Subcategory cards on the category view also carry the legacy
 * .kb-folder-item class so admin Sortable still finds them. Strip
 * the old folder-row chrome (border, radius, hover bg) so the
 * new card visuals come through cleanly. */
.kb-folder-item.kb-doc-card {
    border: none;
    background: transparent;
    border-radius: 0;
    overflow: visible;
    position: relative;
}
.kb-folder-item.kb-doc-card:hover {
    border-color: transparent;
    background: transparent;
}

.kb-doc-card { display: block; }

.kb-doc-card > a {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    padding: 1.25rem 1.4rem 1.3rem;
    min-height: 180px;
    border: 1px solid var(--separator);
    border-radius: 12px;
    background: transparent;
    color: var(--body);
    text-decoration: none;
    overflow: hidden;
    isolation: isolate;
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
    height: 100%;
}

/* Faint block-grid in the top-right corner — same primitives the
 * dmu-empty-state component uses (grid lines + tinted primary blocks),
 * scaled close to that source (52px cells / 50px blocks) so only a few
 * cells are visible. The radial mask anchored at the top-right corner
 * fades the pattern out in every direction — including downward —
 * so the grid trails off softly above the title text. */
.kb-doc-card > a::before {
    content: '';
    position: absolute;
    top: 0;
    right: 0;
    width: 75%;
    height: 90%;
    z-index: 0;
    pointer-events: none;
    background-image:
        linear-gradient(rgba(var(--primary-rgb), 0.09), rgba(var(--primary-rgb), 0.09)),
        linear-gradient(rgba(var(--primary-rgb), 0.06), rgba(var(--primary-rgb), 0.06)),
        linear-gradient(rgba(var(--primary-rgb), 0.04), rgba(var(--primary-rgb), 0.04)),
        linear-gradient(to right, rgba(0, 0, 0, 0.06) 1px, transparent 1px),
        linear-gradient(to bottom, rgba(0, 0, 0, 0.06) 1px, transparent 1px);
    background-size:
        50px 50px,
        50px 50px,
        50px 50px,
        52px 52px,
        52px 52px;
    background-position:
        right 56px top 4px,
        right 4px top 56px,
        right 108px top 56px,
        right 0 top 0,
        right 0 top 0;
    background-repeat:
        no-repeat,
        no-repeat,
        no-repeat,
        repeat,
        repeat;
    -webkit-mask-image: radial-gradient(ellipse 110% 110% at 100% 0%, rgba(0, 0, 0, 0.95) 0%, rgba(0, 0, 0, 0.5) 45%, transparent 80%);
    mask-image: radial-gradient(ellipse 110% 110% at 100% 0%, rgba(0, 0, 0, 0.95) 0%, rgba(0, 0, 0, 0.5) 45%, transparent 80%);
}

.kb-doc-card > a > * { position: relative; z-index: 1; }

.kb-doc-card > a:hover {
    background: transparent;
    border-color: rgba(0, 0, 0, 0.16);
    box-shadow: 0 4px 12px -8px rgba(0, 0, 0, 0.18);
    color: var(--body);
}

.kb-doc-card-icon {
    width: 52px;
    height: 52px;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.05);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--body);
    flex-shrink: 0;
    margin-bottom: 0.5rem;
}

.kb-doc-card-icon i,
.kb-doc-card-icon svg {
    width: 24px !important;
    height: 24px !important;
}

.kb-doc-card-title {
    font-size: 0.95rem;
    font-weight: 700;
    color: var(--body);
    line-height: 1.3;
    margin-top: auto;
    transition: color 0.15s ease;
}

.kb-doc-card > a:hover .kb-doc-card-title {
    color: var(--primary);
}

.kb-doc-card-desc {
    font-size: 0.82rem;
    color: var(--alternate);
    line-height: 1.45;
}

[data-bs-theme="dark"] .kb-doc-card > a,
html[data-color^="dark-"] .kb-doc-card > a {
    border-color: rgba(255, 255, 255, 0.08);
}
[data-bs-theme="dark"] .kb-doc-card > a:hover,
html[data-color^="dark-"] .kb-doc-card > a:hover {
    border-color: rgba(255, 255, 255, 0.18);
}
[data-bs-theme="dark"] .kb-doc-card-icon,
html[data-color^="dark-"] .kb-doc-card-icon {
    background: rgba(255, 255, 255, 0.06);
}

/* ──────────────────────────────────────────────
 * Search modal — centred overlay opened via the
 * header search input (or Ctrl/⌘+K). Plain
 * substring search; no AI surfaces here.
 * ────────────────────────────────────────────── */

.kb-search-modal {
    position: fixed;
    inset: 0;
    z-index: 1080;
    display: none;
}
.kb-search-modal.is-open { display: block; }

.kb-search-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(15, 15, 20, 0.45);
    backdrop-filter: blur(2px);
    -webkit-backdrop-filter: blur(2px);
}

.kb-search-dialog {
    position: relative;
    width: min(720px, calc(100% - 2rem));
    max-height: calc(100vh - 6rem);
    margin: 4rem auto 0;
    background: #ffffff;
    border-radius: 14px;
    border: 1px solid rgba(0, 0, 0, 0.08);
    box-shadow: 0 20px 60px -20px rgba(0, 0, 0, 0.35);
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.kb-search-input-row {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.85rem 1rem;
    border-bottom: 1px solid rgba(0, 0, 0, 0.06);
}

.kb-search-input-icon {
    width: 18px !important;
    height: 18px !important;
    color: rgba(0, 0, 0, 0.45);
    flex-shrink: 0;
}

.kb-search-input {
    flex: 1 1 auto;
    border: 0;
    outline: 0;
    background: transparent;
    font-size: 1rem;
    color: var(--body);
    padding: 0.25rem 0;
}
.kb-search-input::placeholder { color: rgba(0, 0, 0, 0.4); }

.kb-search-esc {
    flex-shrink: 0;
    border: 1px solid rgba(0, 0, 0, 0.1);
    background: rgba(0, 0, 0, 0.03);
    color: rgba(0, 0, 0, 0.6);
    border-radius: 6px;
    font-size: 0.75rem;
    padding: 0.2rem 0.5rem;
    cursor: pointer;
    transition: background 0.15s ease;
}
.kb-search-esc:hover { background: rgba(0, 0, 0, 0.06); }

.kb-search-results {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: 0.4rem 0;
    max-height: 60vh;
}

.kb-search-empty {
    padding: 1.5rem 1.25rem;
    text-align: center;
    color: var(--alternate);
    font-size: 0.9rem;
}

.kb-search-result {
    display: block;
    margin: 0 0.5rem;
    padding: 0.7rem 0.9rem;
    border-radius: 10px;
    text-decoration: none;
    color: var(--body);
    transition: background 0.1s ease;
}
.kb-search-result:hover,
.kb-search-result.is-active {
    background: rgba(var(--primary-rgb), 0.06);
    color: var(--body);
}

.kb-search-result-crumb {
    font-size: 0.75rem;
    color: var(--alternate);
    line-height: 1.3;
    margin-bottom: 0.15rem;
}

.kb-search-result-title {
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--body);
    line-height: 1.3;
}
.kb-search-result.is-active .kb-search-result-title {
    color: var(--primary);
}

.kb-search-result-snippet {
    margin-top: 0.2rem;
    font-size: 0.82rem;
    color: var(--alternate);
    line-height: 1.5;
    /* One-line cap; overflow is truncated with an ellipsis. */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.kb-search-hl {
    background: transparent;
    color: inherit;
    font-weight: 700;
    padding: 0;
}

.kb-search-footer {
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 0.55rem 1rem;
    border-top: 1px solid rgba(0, 0, 0, 0.06);
    background: rgba(0, 0, 0, 0.015);
    color: var(--alternate);
    font-size: 0.75rem;
}

.kb-search-hint {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
}

.kb-search-kbd {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 18px;
    height: 18px;
    padding: 0 0.3rem;
    border: 1px solid rgba(0, 0, 0, 0.12);
    border-bottom-width: 2px;
    border-radius: 4px;
    background: #ffffff;
    color: rgba(0, 0, 0, 0.65);
    font-family: inherit;
    font-size: 0.7rem;
    font-weight: 600;
}

body.kb-search-open {
    overflow: hidden;
}

[data-bs-theme="dark"] .kb-search-dialog,
html[data-color^="dark-"] .kb-search-dialog {
    background: #1c1c22;
    border-color: rgba(255, 255, 255, 0.08);
}
[data-bs-theme="dark"] .kb-search-input-row,
html[data-color^="dark-"] .kb-search-input-row {
    border-bottom-color: rgba(255, 255, 255, 0.06);
}
[data-bs-theme="dark"] .kb-search-footer,
html[data-color^="dark-"] .kb-search-footer {
    border-top-color: rgba(255, 255, 255, 0.06);
    background: rgba(255, 255, 255, 0.02);
}
[data-bs-theme="dark"] .kb-search-kbd,
html[data-color^="dark-"] .kb-search-kbd {
    background: rgba(255, 255, 255, 0.05);
    border-color: rgba(255, 255, 255, 0.12);
    color: rgba(255, 255, 255, 0.78);
}
[data-bs-theme="dark"] .kb-search-esc,
html[data-color^="dark-"] .kb-search-esc {
    background: rgba(255, 255, 255, 0.05);
    border-color: rgba(255, 255, 255, 0.12);
    color: rgba(255, 255, 255, 0.7);
}

/* ──────────────────────────────────────────────
 * Handbook page actions — Copy / View as Markdown
 * / Open in Claude. Lives at the top of the TOC
 * rail (right column), above the "On this page"
 * list. Uses the portal's dmu-dropdown chrome for
 * visual consistency with the profile menu.
 * ────────────────────────────────────────────── */

.kb-doc-actions {
    margin-bottom: 1rem;
}

.kb-doc-actions-btn {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    gap: 0.5rem;
    padding: 0.45rem 0.75rem;
    font-size: 0.82rem;
    font-weight: 500;
    color: var(--body);
    background: transparent;
    border: 1px solid var(--separator);
    border-radius: 8px;
    cursor: pointer;
    transition: border-color 0.15s ease, background 0.15s ease;
}

.kb-doc-actions-btn:hover,
.kb-doc-actions-btn[aria-expanded="true"] {
    border-color: rgba(0, 0, 0, 0.18);
    background: rgba(0, 0, 0, 0.02);
}

.kb-doc-actions-label {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
}

.kb-doc-actions-chev {
    opacity: 0.55;
    transition: transform 0.15s ease;
}

.kb-doc-actions-btn[aria-expanded="true"] .kb-doc-actions-chev {
    transform: rotate(180deg);
}

/* "Copied!" / "Copy failed" flash state — the chevron is gone, so
 * the lone label would sit at the start under the button's
 * default space-between. Centre while flashing so the message
 * reads as a confirmation. */
.kb-doc-actions-btn.is-flashing {
    justify-content: center;
}

[data-bs-theme="dark"] .kb-doc-actions-btn,
html[data-color^="dark-"] .kb-doc-actions-btn {
    border-color: rgba(255, 255, 255, 0.1);
    color: rgba(255, 255, 255, 0.85);
}
[data-bs-theme="dark"] .kb-doc-actions-btn:hover,
[data-bs-theme="dark"] .kb-doc-actions-btn[aria-expanded="true"],
html[data-color^="dark-"] .kb-doc-actions-btn:hover,
html[data-color^="dark-"] .kb-doc-actions-btn[aria-expanded="true"] {
    border-color: rgba(255, 255, 255, 0.22);
    background: rgba(255, 255, 255, 0.04);
}

/* Brand-logo <img> inside the AI dropdown items. simpleicons serves
 * each provider's mark in its full brand color; we flatten to the
 * same dark monochrome the rest of the dropdown uses so the row
 * reads as a uniform set of icons rather than a multicolor zoo.
 * `brightness(0)` collapses any SVG to pure black, then opacity
 * lifts it to the same weight Lucide icons render at. */
.kb-ai-icon {
    width: 16px;
    height: 16px;
    display: block;
    object-fit: contain;
    filter: brightness(0);
    opacity: 0.78;
}

.kb-ai-icon-wrapper {
    /* The default wrapper centres a Lucide <i>; an <img> needs the
     * same centring without the extra inline-block whitespace. */
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

[data-bs-theme="dark"] .kb-ai-icon,
html[data-color^="dark-"] .kb-ai-icon {
    /* Invert the now-black icon to white for dark surfaces. */
    filter: brightness(0) invert(1);
    opacity: 0.82;
}

/* ──────────────────────────────────────────────
 * Dark-mode pass for KB chrome.
 *
 * The bulk of the KB CSS uses var(--body) / var(--alternate) /
 * var(--primary) / var(--separator), which already flip under the
 * portal's theme system. This block targets the surfaces that
 * hardcode light-mode whites (.kb-header, .kb-tabs, search input)
 * plus a few hover/active states that read poorly on dark.
 * ────────────────────────────────────────────── */

[data-bs-theme="dark"] .kb-header,
html[data-color^="dark-"] .kb-header {
    background-color: #1c1c22;
    border-bottom-color: rgba(255, 255, 255, 0.08);
}


[data-bs-theme="dark"] .kb-header-search-input,
html[data-color^="dark-"] .kb-header-search-input {
    background-color: rgba(255, 255, 255, 0.04);
    border-color: rgba(255, 255, 255, 0.08);
    color: rgba(255, 255, 255, 0.92);
}
[data-bs-theme="dark"] .kb-header-search-input::placeholder,
html[data-color^="dark-"] .kb-header-search-input::placeholder {
    color: rgba(255, 255, 255, 0.4);
}
[data-bs-theme="dark"] .kb-header-search-input:focus,
html[data-color^="dark-"] .kb-header-search-input:focus {
    background-color: rgba(255, 255, 255, 0.06);
    border-color: rgba(255, 255, 255, 0.18);
}
[data-bs-theme="dark"] .kb-header-search-icon,
html[data-color^="dark-"] .kb-header-search-icon {
    color: rgba(255, 255, 255, 0.45);
}

[data-bs-theme="dark"] .kb-header-dashboard,
html[data-color^="dark-"] .kb-header-dashboard {
    color: rgba(255, 255, 255, 0.85);
}
[data-bs-theme="dark"] .kb-header-dashboard:hover,
html[data-color^="dark-"] .kb-header-dashboard:hover {
    background: rgba(255, 255, 255, 0.06);
}

[data-bs-theme="dark"] .kb-tabs,
html[data-color^="dark-"] .kb-tabs {
    background-color: #1c1c22;
}
[data-bs-theme="dark"] .kb-tab,
html[data-color^="dark-"] .kb-tab {
    color: rgba(255, 255, 255, 0.65);
}
[data-bs-theme="dark"] .kb-tab:hover,
html[data-color^="dark-"] .kb-tab:hover {
    color: rgba(255, 255, 255, 0.95);
    border-bottom-color: rgba(255, 255, 255, 0.18);
}
[data-bs-theme="dark"] .kb-tab--active,
[data-bs-theme="dark"] .kb-tab--active:hover,
html[data-color^="dark-"] .kb-tab--active,
html[data-color^="dark-"] .kb-tab--active:hover {
    color: var(--primary);
    border-bottom-color: var(--primary);
}

/* .kb-content body copy borders, hr separators, code blocks etc.
 * mostly inherit from var(--body)/var(--separator). The doc-card
 * grid corner pattern uses var(--separator) for gridlines; the
 * primary-tint blocks read fine on dark too. */
[data-bs-theme="dark"] .kb-doc-card > a:hover,
html[data-color^="dark-"] .kb-doc-card > a:hover {
    box-shadow: 0 4px 12px -8px rgba(0, 0, 0, 0.5);
}

/* The empty-state component's grid/blocks read on either theme —
 * only the icon tile's white background needs flipping. */
[data-bs-theme="dark"] .dmu-empty-state__icon,
html[data-color^="dark-"] .dmu-empty-state__icon {
    background: rgba(255, 255, 255, 0.06);
    border-color: rgba(255, 255, 255, 0.1);
}
