/* ==========================================================================
   Solvirk KnowledgeMCP — Kinetic (TypeUI · Enhanced) token layer + components.
   Every value below maps 1:1 from design-skill/ registries (colors.md,
   typography.md, spacing.md, radius.md, shadows.md). Components reference
   tokens only — no raw hex outside this :root block.
   ========================================================================== */

:root {
    /* ---- colors.md · text ---- */
    --body: #5E4A5E;
    --body-subtle: #745C76;
    --heading: #2A1729;
    --fg-brand-subtle: #CDBACB; /* bleg slate-teal (afledt — eneste token uden website-kilde) */
    --fg-brand: #3B1F3A;
    --fg-brand-strong: #2C1530;
    --fg-success: #2F7A5A;
    --fg-success-strong: #235C44;
    --fg-danger: #B3413F;
    --fg-danger-strong: #8A302E;
    --fg-warning-subtle: #C97B2B;
    --fg-warning: #8F5418;
    --fg-yellow: #CA8A04;
    --fg-disabled: #B9A6B7;
    --fg-purple: #9333EA;
    --fg-cyan: #0891B2;
    --fg-indigo: #133865;
    --fg-pink: #D61F69;
    --fg-lime: #65A30D;

    /* ---- colors.md · neutral surfaces ---- */
    --neutral-primary-soft: #FFFFFF;
    --neutral-primary: #FFFFFF;
    --neutral-primary-medium: #FFFFFF;
    --neutral-secondary-soft: #F8F3EE;
    --neutral-secondary: #F8F3EE;
    --neutral-secondary-medium: #F1EAE3;
    --neutral-tertiary-soft: #F1EAE3;
    --neutral-tertiary: #EADFE8;
    --neutral-tertiary-medium: #EADFE8;
    --neutral-quaternary: #D9CCD7;
    --neutral-quaternary-medium: #D9CCD7;
    --gray: #B9A6B7;

    /* ---- brand · Solvirk Skumring (solvirk-design/colors.md, Aubergine besluttet 15/9-2026) ----
       Safran er solen: primærknap, markeringer, én ting der skal ses — altid med mørk tekst (10:1),
       aldrig hvid, højst ~10 % af fladen. Blomme er grunden: topbjælken og links. Papir er siden.
       Værdierne er Skumrings egne (Solvirk.Design tokens.css); de få, der er markeret "afledt"
       i temascriptets historik, er tints Kinetic-laget kræver og Skumring ikke navngiver. */
    --brand-softer: #FDF6E1;
    --brand-soft: #FBEBB7;
    --brand: #F6C445;
    --brand-medium: #FBEBB7;
    --brand-strong: #E3AF2E;
    --fg-on-brand: #2A1729; /* labelfarve på solide brand/status-flader (tilføjet token) */

    /* ---- colors.md · status ---- */
    --success-soft: #E8F2ED;
    --success: #2F7A5A;
    --success-medium: #CFE5DA;
    --success-strong: #235C44;
    --danger-soft: #F8E9E8;
    --danger: #B3413F;
    --danger-medium: #F0D1D0;
    --danger-strong: #8A302E;
    --warning-soft: #FBF1E4;
    --warning: #C97B2B;
    --warning-medium: #F3DEC4;
    --warning-strong: #8F5418;

    /* ---- colors.md · utility & accent (accents are sanctioned for charts/graphs) ---- */
    --dark-soft: #4C2C4B;
    --dark: #3B1F3A;
    --dark-strong: #2C1530;
    --disabled: #F1EAE3;
    --purple: #A855F7;
    --sky: #0EA5E9;
    --teal: #0D9488;
    --pink: #D61F69;
    --cyan: #06B6D4;
    --fuchsia: #C026D3;
    --indigo: #133865;
    --orange: #FB923C;

    /* ---- colors.md · borders ---- */
    --buffer: #FFFFFF;
    --muted: #F1EAE3;
    --light: #EADFE8;
    --default-subtle: #D9CCD7;
    --default: #D9CCD7;
    --default-medium: #D9CCD7;
    --default-strong: #B9A6B7;
    --success-subtle: #CFE5DA;
    --danger-subtle: #F0D1D0;
    --warning-subtle: #F3DEC4;
    --brand-subtle: #FBEBB7;
    --brand-light: #3B1F3A;
    --dark-backdrop: #2A1729;
    --on-dark: #F8F3EE;               /* sv-on-dark */
    --on-dark-2: #CDBACB;             /* sv-on-dark-2 */

    /* ---- typography.md ---- */
    --font-family: "Instrument Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
    --font-display: "Bricolage Grotesque", "Instrument Sans", system-ui, sans-serif;
    --font-mono: "JetBrains Mono", ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
    --font-size-xxs: 0.6875rem;
    --font-size-xs: 0.75rem;
    --font-size-sm: 0.875rem;
    --font-size-md: 1rem;
    --font-size-lg: 1.125rem;
    --font-size-xl: 1.25rem;
    --font-size-2xl: 1.375rem;
    --font-size-3xl: 1.5625rem;
    --font-size-4xl: 1.75rem;
    --line-height-heading: 1.3;
    --line-height-display: 1;
    --line-height-detail: 1.3;
    --line-height-component: 1.3;
    --line-height-body: 1.5;
    --line-height-code: 1.5;

    /* ---- spacing.md ---- */
    --spacing-0-5: 0.125rem;
    --spacing-1: 0.25rem;
    --spacing-1-5: 0.375rem;
    --spacing-2: 0.5rem;
    --spacing-2-5: 0.625rem;
    --spacing-3: 0.75rem;
    --spacing-3-5: 0.875rem;
    --spacing-4: 1rem;
    --spacing-5: 1.25rem;
    --spacing-6: 1.5rem;
    --spacing-8: 2rem;
    --spacing-9: 2.25rem;
    --spacing-10: 2.5rem;
    --spacing-12: 3rem;
    --spacing-16: 4rem;

    /* ---- radius.md ---- */
    --radius-xs: 0.0625rem;
    --radius-sm: 0.125rem;
    --radius-md: 0.1875rem;
    --radius-xxl: 0.25rem;   /* the Kinetic component shell — 4px everywhere */
    --radius-full: 9999px;

    /* ---- shadows.md ---- */
    --elevation-2: 0px 4px 16px rgba(17, 17, 17, 0.10); /* floating overlays only */

    /* ---- shared interaction tints (one hover fill for every link surface) ---- */
    --hover-bg: var(--neutral-tertiary-medium);
    --active-bg: var(--brand-softer);
    --focus-ring: 0 0 0 2px var(--fg-brand);
}

/* ==========================================================================
   Base
   ========================================================================== */

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

html { font-size: 16px; }

body {
    margin: 0;
    background: var(--neutral-secondary-soft); /* one uniform surface — never alternated */
    color: var(--body);
    font-family: var(--font-family);
    font-size: var(--font-size-sm);
    line-height: var(--line-height-body);
    -webkit-font-smoothing: antialiased;
    /* Safety net for strings with no break opportunity — file paths, URLs, stack traces, ids.
       `break-word` only acts when a word cannot fit at all, so ordinary prose is untouched;
       without it a single path like D:\Sites\…\onnxruntime.dll widens the whole page. */
    overflow-wrap: break-word;
}

h1, h2, h3, h4 {
    color: var(--heading);
    font-family: var(--font-display);
    line-height: var(--line-height-heading);
    margin: 0 0 var(--spacing-6); /* fixed 24px below a heading */
}

h1 { font-size: var(--font-size-4xl); font-weight: 700; } /* app-h1 caps at 28px */
h2 { font-size: var(--font-size-3xl); font-weight: 600; }
h3 { font-size: var(--font-size-2xl); font-weight: 600; }

p { margin: 0 0 var(--spacing-6); } /* fixed 24px below a paragraph */

a { color: var(--fg-brand); }

code, pre, kbd, samp { font-family: var(--font-mono); }

/* Skumring's focus: a plum outline, visible on paper and on white alike. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
    outline: 2px solid var(--fg-brand);
    outline-offset: 3px;
}

.icon { flex-shrink: 0; vertical-align: -0.15em; }

.container {
    max-width: 1280px;
    margin-inline: auto;
    padding-inline: var(--spacing-6);
}

main { padding-block: var(--spacing-8); }

/* Gradient separator — centered hairline fading out toward both sides */
.k-separator {
    height: 1px;
    border: none;
    margin: var(--spacing-8) 0;
    background: linear-gradient(to right, transparent, var(--default), transparent);
}

.text-subtle { color: var(--body-subtle); }
.text-danger { color: var(--fg-danger); }
.text-success { color: var(--fg-success); }

/* ==========================================================================
   Navbar — hairline `default` bottom border; links are text links, not buttons
   ========================================================================== */

.navbar {
    background: var(--dark);
    border-bottom: 1px solid var(--dark-strong);
    color: var(--on-dark);
    position: sticky;
    top: 0;
    z-index: 100;
}

.navbar-inner {
    max-width: 1280px;
    margin-inline: auto;
    padding: var(--spacing-3) var(--spacing-6);
    display: flex;
    align-items: center;
    gap: var(--spacing-6);
}

.navbar-brand {
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-2);
    color: var(--on-dark);
    font-family: var(--font-display);
    font-size: var(--font-size-lg);
    font-weight: 700;
    letter-spacing: -0.01em;
    text-decoration: none;
    white-space: nowrap;
}

.navbar-brand img { height: 24px; width: 24px; display: block; border-radius: var(--radius-xxl); }
.navbar-brand-dot { color: var(--brand); } /* the saffron dot — the sun in the wordmark */

/* A flex item defaults to min-width:auto and refuses to shrink below its content, so eleven
   nav links pushed the whole DOCUMENT wide — a horizontal scrollbar on every page under
   ~1000px. Same trap as `1fr` meaning `minmax(auto, 1fr)` in grid. Let the strip scroll
   instead: the bar itself is noise in a 44px header, so it is hidden. */
.navbar-inner > nav {
    min-width: 0;
    overflow-x: auto;
    scrollbar-width: none;
    -ms-overflow-style: none;
}

.navbar-inner > nav::-webkit-scrollbar { display: none; }

.nav-links {
    display: flex;
    align-items: center;
    flex-wrap: nowrap;
    gap: var(--spacing-6); /* adjacent nav links sit 24px apart */
    list-style: none;
    margin: 0;
    padding: 0; /* zero the UA's inline-start padding, not just margin */
}

.nav-links > li { flex: 0 0 auto; }

.nav-link {
    color: var(--on-dark-2);
    font-size: var(--font-size-sm);
    font-weight: 500;
    line-height: var(--line-height-component);
    text-decoration: none; /* never underlined, in any state */
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-1-5);
    transition: color 150ms;
    white-space: nowrap; /* "AI-ændringer" broke across two lines and doubled the header height */
}

.nav-link:hover { color: var(--on-dark); } /* links brighten on the dark bar — no padding, no background */
.nav-link.active { color: var(--brand); } /* safran marks where you are */
.navbar :where(a, button, select):focus-visible { outline-color: var(--brand); }
.navbar .scope-selector-label { color: var(--on-dark-2); }

.navbar-spacer { flex: 1; }

/* Rumvælgeren. I et kunderum er den farvet med brand-fladen, så man altid kan se, at man ikke
   arbejder i Solvirks generelle viden. */
.scope-selector { display: flex; align-items: center; gap: var(--spacing-2); margin: 0; }
.scope-selector-label { font-size: var(--font-size-xs); color: var(--body-subtle); }

/* Generaliseringer: forslaget og kundens note side om side, under hinanden på en smal skærm. */
.generalization-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--spacing-5); }
@media (max-width: 900px) { .generalization-grid { grid-template-columns: minmax(0, 1fr); } }
.scope-selector select.k-input { width: auto; max-width: 11rem; padding-block: var(--spacing-1); text-overflow: ellipsis; }
@media (max-width: 1100px) {
    /* Smal skærm: hovednavigationen skal kunne ses; farven på feltet siger stadig, hvor man er. */
    .scope-selector-label { display: none; }
}
.scope-selector--room select.k-input { background: var(--brand-soft); color: var(--fg-brand-strong); font-weight: 600; }

/* Narrow screens: the brand, eleven links and two buttons cannot share one row. Letting the nav
   shrink alone drove it to width 0 — technically no overflow, but the navigation was invisible,
   which is worse than the scrollbar it replaced. So the strip wraps onto its own full-width row
   and scrolls there, while brand and buttons keep the first row. */
@media (max-width: 760px) {
    .navbar-inner {
        flex-wrap: wrap;
        gap: var(--spacing-2) var(--spacing-4);
        padding-inline: var(--spacing-4);
    }

    .navbar-inner > nav {
        order: 10;
        flex: 1 0 100%; /* own row; min-width:0 above keeps overflow inside the strip */
    }
}

/* ==========================================================================
   Buttons — buttons.md. Dashboard rule: Small size everywhere in this app.
   Flat, 4px corners, 4px intent focus ring.
   ========================================================================== */

.k-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--spacing-1-5); /* icon ↔ label 6px */
    font-family: var(--font-family);
    font-size: var(--font-size-sm);
    font-weight: 500;
    line-height: var(--line-height-component);
    padding: var(--spacing-2) var(--spacing-3); /* Small tier */
    border-radius: var(--radius-xxl);
    border: 1px solid transparent;
    background: transparent;
    color: var(--body);
    cursor: pointer;
    text-decoration: none;
    white-space: nowrap;
    transition: background-color 150ms, color 150ms, border-color 150ms;
    box-shadow: none; /* no shadows on buttons, ever */
}

.k-btn:focus-visible { outline: none; box-shadow: 0 0 0 4px var(--ring, var(--neutral-tertiary)); }

.k-btn:disabled, .k-btn[aria-disabled="true"] {
    color: var(--fg-disabled);
    background: var(--disabled);
    border-color: transparent;
    pointer-events: none;
}

.k-btn--primary { background: var(--brand); color: var(--fg-on-brand); --ring: var(--brand-medium); }
.k-btn--primary:hover { background: var(--brand-strong); color: var(--fg-on-brand); }

.k-btn--secondary { background: var(--neutral-secondary-medium); color: var(--body); border-color: var(--default-medium); --ring: var(--neutral-tertiary); }
.k-btn--secondary:hover { background: var(--neutral-tertiary-medium); color: var(--heading); }

.k-btn--tertiary { background: var(--neutral-primary-soft); color: var(--body); border-color: var(--default); --ring: var(--neutral-tertiary-soft); }
.k-btn--tertiary:hover { background: var(--neutral-secondary-medium); color: var(--heading); }

.k-btn--danger { background: var(--danger); color: var(--fg-on-brand); --ring: var(--danger-medium); }
.k-btn--danger:hover { background: var(--danger-strong); color: var(--fg-on-brand); }

.k-btn--ghost { background: transparent; color: var(--heading); --ring: var(--neutral-tertiary); }
.k-btn--ghost:hover { background: var(--neutral-secondary-medium); }

/* On the blomme top bar: light text, and a hover that lightens the dark ground instead of painting paper on it. */
.navbar .k-btn--ghost { color: var(--on-dark-2); }
.navbar .k-btn--ghost:hover { background: rgba(255, 255, 255, 0.08); color: var(--on-dark); }
/* The menu that opens from the bar is a paper surface again, with the page's own text colour. */
.navbar .k-dropdown-panel { color: var(--body); }

.k-btn--icon { width: 36px; height: 36px; padding: 0; }

.k-btn-row { display: flex; align-items: center; gap: var(--spacing-4); flex-wrap: wrap; }

/* ==========================================================================
   Field shell — input-field.md. Borderless contrasting fill, 4px corners,
   focus = brand border + 4px brand-medium ring.
   ========================================================================== */

.k-label {
    display: block;
    font-size: var(--font-size-sm);
    font-weight: 500;
    color: var(--heading);
    margin-bottom: var(--spacing-2-5);
}

.k-input {
    width: 100%;
    font-family: var(--font-family);
    font-size: var(--font-size-sm);
    line-height: var(--line-height-component);
    color: var(--heading);
    background: var(--neutral-tertiary);
    border: 1px solid transparent;
    border-radius: var(--radius-xxl);
    padding: var(--spacing-2-5) var(--spacing-3);
    box-shadow: none;
}

.k-input::placeholder { color: var(--body); }

.k-input:focus-visible {
    outline: none;
    border-color: var(--brand);
    box-shadow: var(--focus-ring);
}

.k-input:disabled { color: var(--fg-disabled); background: var(--disabled); }

textarea.k-input {
    padding: var(--spacing-3-5);
    resize: vertical;
    line-height: var(--line-height-body);
    min-height: 120px;
}

/* Select keeps the field shell + custom chevron (native appearance reset) */
.k-select-wrap { position: relative; }
.k-select-wrap > .icon {
    position: absolute;
    inset-inline-end: var(--spacing-3);
    top: 50%;
    transform: translateY(-50%);
    color: var(--body);
    pointer-events: none;
}
select.k-input { appearance: none; padding-inline-end: var(--spacing-9); cursor: pointer; }

/* Composite shell (search bar with leading icon): the WRAPPER owns the focus ring */
.k-field-shell {
    position: relative;
    display: flex;
    align-items: center;
    background: var(--neutral-tertiary);
    border: 1px solid transparent;
    border-radius: var(--radius-xxl);
    transition: border-color 150ms;
}

.k-field-shell:focus-within { border-color: var(--brand); box-shadow: var(--focus-ring); }

.k-field-shell > .icon { position: absolute; inset-inline-start: var(--spacing-3); color: var(--body); pointer-events: none; }

.k-field-shell > input {
    flex: 1;
    width: 100%;
    background: transparent;
    border: none;
    font-family: var(--font-family);
    font-size: var(--font-size-sm);
    line-height: var(--line-height-component);
    color: var(--heading);
    padding: var(--spacing-2-5) var(--spacing-3) var(--spacing-2-5) var(--spacing-9);
}

.k-field-shell > input::placeholder { color: var(--body); }
.k-field-shell > input:focus, .k-field-shell > input:focus-visible { outline: none; box-shadow: none; }

.k-field-shell--lg > input { font-size: var(--font-size-md); padding-block: var(--spacing-3); }

.k-help { font-size: var(--font-size-sm); color: var(--body-subtle); margin-top: var(--spacing-1); }
.k-field-error { font-size: var(--font-size-sm); color: var(--fg-danger-strong); margin-top: var(--spacing-2-5); }
.k-field { margin-bottom: var(--spacing-5); }

/* ==========================================================================
   Cards — cards.md. Lighter surface, no border, no shadow, 4px corners.
   ========================================================================== */

.k-card {
    background: var(--neutral-primary-soft);
    border-radius: var(--radius-xxl);
    padding: var(--spacing-6);
}

.k-card blockquote, .k-card figure { margin: 0; }

.k-card-title {
    font-size: var(--font-size-xl); /* card headings are 20px */
    font-weight: 600;
    color: var(--heading);
    line-height: var(--line-height-heading);
    margin: 0;
}

.k-card-title a { color: var(--heading); text-decoration: none; }
.k-card-title a:hover { color: var(--fg-brand); }

.card-list { display: flex; flex-direction: column; gap: var(--spacing-6); }

/* ==========================================================================
   Bento grid — bento-design/cards.md, layout.md.
   The rule that matters from that system: "Do not flatten all cards to identical visual
   weight." A single column of identical cards makes 27 items read as 27 identical items, and
   the eye has nowhere to land. Here the WIDTH carries the hierarchy, and it is driven by real
   signal (a bundle skill, a snippet with code, a change awaiting review) — never decoration.
   ========================================================================== */

.bento-grid {
    display: grid;
    /* minmax(0, 1fr), never a bare fr: a long title or a wide code block would otherwise refuse
       to shrink and push the whole document sideways. */
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--spacing-5);
    align-items: stretch; /* equal heights per row — the tidiness the pattern depends on */
    grid-auto-flow: dense; /* a wide tile that will not fit lets a narrow one fill the hole */
}

@media (min-width: 900px) { .bento-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 1240px) { .bento-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

/* Below two columns a span would overflow its own row, so spans only exist where there is room
   to span. Declared per breakpoint rather than as one rule for exactly that reason. */
@media (max-width: 599px) { .bento-grid { grid-template-columns: minmax(0, 1fr); } }

@media (min-width: 600px) {
    .bento-span-2 { grid-column: span 2; }
}

@media (min-width: 1240px) {
    .bento-span-3 { grid-column: span 3; }
}

/* The tile itself. Flat and bordered rather than shadowed, and vertically anchored: title at the
   top, meta pushed to the bottom, so a row of unequal content still lines up at both edges. */
.bento-grid > .k-card {
    display: flex;
    flex-direction: column;
    min-width: 0;
    border: 1px solid var(--default);
    transition: transform 180ms ease-out, border-color 180ms ease-out;
}

/* The card is a flex column, so its children default to min-width:auto and refuse to shrink below
   their longest word. One long Danish compound in a title ("Intrinsisk minimumsstørrelse") then
   pushed the whole document sideways — the same trap as everywhere else, one level further in. */
.bento-grid > .k-card > * { min-width: 0; }

.bento-grid > .k-card .k-card-title { overflow-wrap: anywhere; }

.bento-grid > .k-card > .search-meta { margin-top: auto; padding-top: var(--spacing-4); }

.bento-grid > .k-card:hover {
    transform: translateY(-4px);
    border-color: var(--default-strong);
}

.bento-grid > .k-card:focus-within {
    border-color: var(--brand);
    outline: 2px solid var(--fg-brand); /* safran on paper is too faint for a focus mark; blomme is not */
    outline-offset: 3px;
}

/* A tile the reader is meant to act on. Used for changes awaiting review — the hierarchy is the
   information, not styling for its own sake. */
.bento-grid > .k-card.bento-primary {
    border-color: var(--brand-soft);
    background: var(--neutral-primary-soft);
}

@media (prefers-reduced-motion: reduce) {
    .bento-grid > .k-card { transition: border-color 180ms ease-out; }
    .bento-grid > .k-card:hover { transform: none; }
}

/* The changed files, as the tile's supporting detail. Paths are long and unbreakable, so they
   truncate rather than widen the tile — the count in the badge above already says how many. */
.change-paths {
    list-style: none;
    margin: var(--spacing-3) 0 0;
    padding: 0;
    font-size: var(--font-size-xs);
    color: var(--body-subtle);
}

.change-paths li {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    padding-block: 1px;
}

/* ==========================================================================
   Badges — badges.md. Always full pills, flat, soft fills.
   ========================================================================== */

.k-badge {
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-1);
    width: auto; /* badges never stretch */
    border-radius: var(--radius-full);
    font-size: var(--font-size-xs);
    font-weight: 500;
    line-height: var(--line-height-component);
    padding: var(--spacing-0-5) var(--spacing-1-5);
    white-space: nowrap;
    text-decoration: none;
    /* nowrap keeps a badge on one line, which is the point — but a badge carrying a long note
       title then refuses to fit any narrow screen and drags the document wide with it. Cap it at
       the container and truncate instead; the full title is still the link's own text. */
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
}

.k-badge--brand { background: var(--brand-softer); color: var(--fg-brand-strong); }
.k-badge--neutral { background: var(--neutral-secondary-medium); color: var(--heading); border: 1px solid var(--default-medium); }
.k-badge--alt { background: var(--neutral-primary-soft); color: var(--heading); border: 1px solid var(--default); }
.k-badge--success { background: var(--success-soft); color: var(--fg-success-strong); }
.k-badge--danger { background: var(--danger-soft); color: var(--fg-danger-strong); }
.k-badge--warning { background: var(--warning-soft); color: var(--fg-warning); }

a.k-badge--neutral:hover { background: var(--neutral-tertiary-medium); }

/* A badge acting as a toggle. It has to read as pressed WITHOUT relying on colour alone — the
   community dot beside it is already carrying a colour, and two colour signals in one control is
   how a legend stops being readable. Hence the border and weight change. */
button.k-badge {
    font-family: var(--font-family);
    cursor: pointer;
    transition: background 150ms, border-color 150ms;
}

button.k-badge:hover { background: var(--neutral-tertiary-medium); }

.k-badge--on {
    border-color: var(--brand);
    background: var(--brand-softer);
    color: var(--fg-brand-strong);
    font-weight: 600;
}

.badge-row { display: flex; align-items: center; gap: var(--spacing-2); flex-wrap: wrap; }

/* ==========================================================================
   Pill filter tabs — tabs.md (pills variant)
   ========================================================================== */

.k-pills { display: flex; flex-wrap: wrap; gap: var(--spacing-2); }

.k-pill {
    font-family: var(--font-family);
    font-size: var(--font-size-sm);
    font-weight: 500;
    line-height: var(--line-height-component);
    color: var(--body);
    background: transparent;
    border: none;
    border-radius: var(--radius-full);
    padding: var(--spacing-1) var(--spacing-3);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-1-5);
    transition: background-color 150ms, color 150ms;
}

.k-pill:hover { background: var(--hover-bg); color: var(--heading); }
.k-pill.active { background: var(--brand); color: var(--fg-on-brand); }
.k-pill:focus-visible { outline: none; box-shadow: var(--focus-ring); }

/* ==========================================================================
   Sidebar tree (browse) — shared hover fill; active takes the brand tint
   ========================================================================== */

.browse-layout {
    display: grid;
    grid-template-columns: 300px minmax(0, 1fr);
    gap: var(--spacing-6);
    align-items: start;
}

/* min-width:0 for the same reason as the cards: it is a grid item, and a long pinned note title
   would otherwise make the rail refuse to shrink and widen the page on a phone. */
.sidebar {
    padding: var(--spacing-3);
    position: sticky;
    top: 76px;
    max-height: calc(100vh - 100px);
    overflow-y: auto;
    min-width: 0;
}

.sidebar-item { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.sidebar-group + .sidebar-group { margin-top: var(--spacing-1); }

.sidebar-group-header {
    width: 100%;
    display: flex;
    align-items: center;
    gap: var(--spacing-2);
    font-family: var(--font-family);
    font-size: var(--font-size-sm);
    font-weight: 500;
    line-height: var(--line-height-component);
    color: var(--body);
    background: transparent;
    border: none;
    border-radius: var(--radius-sm); /* nested child inside a 4px shell */
    padding: var(--spacing-2);
    cursor: pointer;
    text-align: start;
    transition: background-color 150ms, color 150ms;
}

.sidebar-group-header:hover { background: var(--hover-bg); color: var(--heading); }
.sidebar-group-header:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--brand-subtle); }
.sidebar-group-header .chevron { margin-inline-start: auto; transition: transform 150ms; }
.sidebar-group-header .chevron.open { transform: rotate(180deg); }
.sidebar-count { color: var(--body-subtle); font-weight: 400; font-size: var(--font-size-xs); }

.sidebar-items { list-style: none; margin: 0; padding: 0 0 var(--spacing-1) var(--spacing-6); }

/* Folder tree — nested children indent by depth; same hover fill and active tint as
   every other link surface, 2px radius as a nested child inside the 4px sidebar card. */
.folder-node { margin-top: var(--spacing-0-5); }

.folder-header {
    padding-inline-start: calc(var(--spacing-2) + var(--folder-depth, 0) * var(--spacing-4));
    font-weight: 400;
}

.folder-header .folder-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.folder-header .icon:first-child { color: var(--body-subtle); }

.folder-items {
    padding-inline-start: calc(var(--spacing-6) + var(--folder-depth, 0) * var(--spacing-4));
}

.sidebar-section-label {
    display: flex;
    align-items: center;
    gap: var(--spacing-1-5);
    font-size: var(--font-size-xs);
    font-weight: 600;
    color: var(--body-subtle);
    padding: var(--spacing-2) var(--spacing-2) var(--spacing-1);
}

.sidebar-remove {
    width: 20px;
    height: 20px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: none;
    border-radius: var(--radius-sm);
    color: var(--body-subtle);
    cursor: pointer;
    flex-shrink: 0;
}
.sidebar-remove:hover { background: var(--hover-bg); color: var(--heading); }

.sidebar-item {
    display: block;
    font-size: var(--font-size-sm);
    line-height: var(--line-height-component);
    color: var(--body);
    text-decoration: none; /* sidebar links are never underlined */
    border-radius: var(--radius-sm);
    padding: var(--spacing-1-5) var(--spacing-2);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    transition: background-color 150ms, color 150ms;
}

.sidebar-item:hover { background: var(--hover-bg); color: var(--heading); }
.sidebar-item.active { background: var(--active-bg); color: var(--fg-brand); font-weight: 500; }

/* ==========================================================================
   Alerts — alerts.md. Flat 4px panels, intent soft fill, font-size-sm only.
   ========================================================================== */

.k-alert {
    display: flex;
    align-items: flex-start;
    gap: var(--spacing-2);
    border-radius: var(--radius-xxl);
    padding: var(--spacing-4);
    font-size: var(--font-size-sm);
    line-height: var(--line-height-body);
    margin-bottom: var(--spacing-4);
}

/* Alerts carry the ugliest strings in the app — DLL paths, stack traces, error codes. As a flex
   item the text defaults to min-width:auto and cannot shrink below its longest unbreakable token,
   so one file path widened the whole document. `break-word` on body is not enough here: only
   `anywhere` reduces the min-content size that the flex minimum is derived from. */
.k-alert > *:not(.icon) {
    min-width: 0;
    overflow-wrap: anywhere;
}

.k-alert .icon { margin-top: var(--spacing-0-5); flex-shrink: 0; }
.k-alert--info { background: var(--brand-softer); color: var(--fg-brand-strong); }
.k-alert--success { background: var(--success-soft); color: var(--fg-success-strong); }
.k-alert--danger { background: var(--danger-soft); color: var(--fg-danger-strong); }
.k-alert--warning { background: var(--warning-soft); color: var(--fg-warning); }
.k-alert--neutral { background: var(--neutral-secondary-medium); color: var(--heading); }
.k-alert b, .k-alert strong { font-weight: 500; }

/* ==========================================================================
   Breadcrumb — breadcrumb.md
   ========================================================================== */

.k-breadcrumb { margin-bottom: var(--spacing-6); }
.k-breadcrumb ol {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--spacing-2);
    list-style: none;
    margin: 0;
    padding: 0;
}
.k-breadcrumb li { display: inline-flex; align-items: center; gap: var(--spacing-1-5); }
.k-breadcrumb a {
    color: var(--body);
    font-size: var(--font-size-sm);
    font-weight: 500;
    line-height: var(--line-height-component);
    text-decoration: none;
}
.k-breadcrumb a:hover { color: var(--fg-brand); }
.k-breadcrumb .current { color: var(--body-subtle); font-size: var(--font-size-sm); font-weight: 500; }
.k-breadcrumb .icon { color: var(--body); }

/* ==========================================================================
   Tables — tables.md. Borderless flat card, hairline row dividers.
   ========================================================================== */

.k-table-card {
    background: var(--neutral-primary-soft);
    border-radius: var(--radius-xxl);
    overflow: hidden;
}

.k-table { width: 100%; border-collapse: collapse; font-size: var(--font-size-sm); }

.k-table th {
    background: var(--neutral-secondary-soft);
    color: var(--body);
    font-weight: 500;
    text-align: start;
    padding: var(--spacing-3) var(--spacing-6);
    border-bottom: 1px solid var(--default);
}

.k-table td {
    padding: var(--spacing-4) var(--spacing-6);
    border-bottom: 1px solid var(--default);
    color: var(--body);
    vertical-align: top;
}

.k-table tbody tr:last-child td { border-bottom: none; } /* no trailing edge */
.k-table tbody tr:hover td { background: var(--neutral-secondary-medium); } /* the one readability cue */
.k-table .mono-cell { font-size: var(--font-size-xs); color: var(--body-subtle); white-space: nowrap; }

.k-table-scroll { overflow-x: auto; }

/* ==========================================================================
   Modal — modal.md. Flat lighter panel over a 50% scrim; hairline dividers.
   ========================================================================== */

.k-modal-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.5);
    z-index: 300;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--spacing-4);
}

.k-modal {
    background: var(--neutral-primary-soft);
    border-radius: var(--radius-xxl);
    width: 100%;
    max-width: 512px;
    max-height: calc(100vh - var(--spacing-8));
    display: flex;
    flex-direction: column;
    padding: var(--spacing-6);
}

.k-modal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--spacing-4);
    padding-bottom: var(--spacing-4);
    border-bottom: 1px solid var(--default);
}

.k-modal-title { font-size: var(--font-size-lg); font-weight: 500; color: var(--heading); margin: 0; }

.k-modal-close {
    width: 24px;
    height: 24px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: none;
    border-radius: var(--radius-md);
    color: var(--heading);
    cursor: pointer;
}
.k-modal-close:hover { background: var(--neutral-tertiary); }
.k-modal-close:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--brand-medium); }

.k-modal-body { padding-block: var(--spacing-5); overflow-y: auto; }

.k-modal-footer {
    display: flex;
    justify-content: flex-end;
    gap: var(--spacing-4);
    padding-top: var(--spacing-4);
    border-top: 1px solid var(--default);
}

/* ==========================================================================
   Prose — rendered markdown (typography.md long-form rules)
   ========================================================================== */

.prose { font-size: var(--font-size-md); color: var(--body); line-height: var(--line-height-body); }

.prose > :first-child { margin-top: 0; }
.prose > :last-child { margin-bottom: 0; }

.prose p { margin: 0 0 var(--spacing-4); }

.prose h1, .prose h2 { font-size: var(--font-size-3xl); font-weight: 600; margin: var(--spacing-6) 0 var(--spacing-3); }
.prose h3 { font-size: var(--font-size-2xl); font-weight: 600; margin: var(--spacing-6) 0 var(--spacing-3); }
.prose h4 { font-size: var(--font-size-xl); font-weight: 600; margin: var(--spacing-6) 0 var(--spacing-3); }

.prose ul, .prose ol { margin: 0 0 var(--spacing-4); padding-inline-start: var(--spacing-5); }
.prose li + li { margin-top: var(--spacing-2); }

.prose a { color: var(--fg-brand); font-weight: 500; text-decoration: none; }
.prose a:hover { text-decoration: underline; }

.wikilink--broken { color: var(--fg-danger); }
.wikilink--broken:hover { text-decoration: underline wavy; }

/* A citation marker is a footnote, not a link in the prose: it has to be findable when looked for
   and invisible when reading past it, so it stays small and quiet rather than taking brand colour
   like every other anchor. */
.prose a.citation { font-weight: 400; text-decoration: none; }
.prose a.citation sup {
    color: var(--body-subtle);
    font-size: 0.7em;
    padding-inline-start: 0.0625rem;
    vertical-align: super;
    line-height: 0;
}
.prose a.citation:hover sup { color: var(--fg-brand); }

/* Landing on a source from a marker has to say WHICH one — a jump that only scrolls leaves the
   reader hunting the list for the entry they asked for.

   Two selectors on purpose: :target covers arriving on a URL that already carries the fragment,
   .solvirk-cited covers the in-page click, which deliberately avoids a navigation and therefore never
   sets :target. */
.prose li[id^="kilde-"] { scroll-margin-block-start: var(--spacing-8); }

.prose li[id^="kilde-"]:target,
.prose li.solvirk-cited {
    background: var(--neutral-tertiary);
    border-radius: var(--radius-sm);
    box-shadow: 0 0 0 var(--spacing-1) var(--neutral-tertiary);
}

/* The highlight fades rather than staying: it answers "which one" and then gets out of the way. */
.prose li.solvirk-cited { animation: solvirk-cited-fade 2.4s ease-out forwards; }

@keyframes solvirk-cited-fade {
    0%, 55% { background: var(--neutral-tertiary); box-shadow: 0 0 0 var(--spacing-1) var(--neutral-tertiary); }
    100% { background: transparent; box-shadow: 0 0 0 var(--spacing-1) transparent; }
}

@media (prefers-reduced-motion: reduce) {
    .prose li[id^="kilde-"] { scroll-behavior: auto; }
    .prose li.solvirk-cited { animation: none; }
}

.prose code {
    font-family: var(--font-family);
    font-size: 0.85em;
    background: var(--neutral-tertiary);
    border-radius: var(--radius-sm);
    padding: 0.0625rem var(--spacing-1);
}

.prose pre {
    background: var(--neutral-tertiary-soft);
    border-radius: var(--radius-xxl);
    padding: var(--spacing-4);
    overflow-x: auto;
    margin: 0 0 var(--spacing-4);
    line-height: var(--line-height-code);
}

.prose pre > code { background: transparent; padding: 0; font-size: var(--font-size-xs); color: var(--heading); }

.prose blockquote {
    margin: 0 0 var(--spacing-4);
    border-inline-start: var(--spacing-1) solid var(--default-medium);
    padding-inline-start: var(--spacing-4);
    font-size: var(--font-size-lg);
    font-weight: 500;
    color: var(--heading);
}
.prose blockquote p:last-child { margin-bottom: 0; }

/* The renderer wraps every table in this box so a wide table scrolls itself instead of widening
   the page. max-width, not width: a narrow table should still only take the room it needs. */
.prose-table-scroll { max-width: 100%; overflow-x: auto; margin: 0 0 var(--spacing-4); }
.prose-table-scroll > table { margin-bottom: 0; }

.prose table { border-collapse: collapse; margin: 0 0 var(--spacing-4); width: 100%; font-size: var(--font-size-sm); }
.prose th { background: var(--neutral-secondary-soft); font-weight: 500; text-align: start; }
.prose th, .prose td { padding: var(--spacing-3); border-bottom: 1px solid var(--default); }
.prose tbody tr:last-child td { border-bottom: none; }

.prose hr { border: none; height: 1px; background: var(--default); margin: var(--spacing-8) 0; }

.prose img { max-width: 100%; }

.prose mark, .snippet-text mark { background: var(--brand-soft); color: var(--heading); border-radius: var(--radius-xs); padding: 0 0.0625rem; }

/* ==========================================================================
   Search page
   ========================================================================== */

.search-column { max-width: 768px; margin-inline: auto; }
.search-meta { color: var(--body-subtle); font-size: var(--font-size-xs); margin: var(--spacing-2) 0 0; }
.snippet-text { color: var(--body); font-size: var(--font-size-sm); line-height: var(--line-height-body); margin: 0; overflow-wrap: anywhere; }

.result-header { display: flex; align-items: baseline; justify-content: space-between; gap: var(--spacing-4); }

.empty-state { color: var(--body-subtle); text-align: center; padding: var(--spacing-12) var(--spacing-6); }
.empty-state .icon { color: var(--gray); margin-bottom: var(--spacing-6); }

/* ==========================================================================
   Note view
   ========================================================================== */

.note-meta { display: flex; align-items: center; gap: var(--spacing-2); flex-wrap: wrap; margin-bottom: var(--spacing-6); }
.note-meta .sep { color: var(--gray); }
.note-dates { color: var(--body-subtle); font-size: var(--font-size-xs); }

/* Activity-log timeline (project/client notes) */
.timeline-group { margin-bottom: var(--spacing-5); }
.timeline-date {
    font-size: var(--font-size-xs);
    font-weight: 500;
    color: var(--body-subtle);
    margin-bottom: var(--spacing-2);
}
.timeline-list { list-style: none; margin: 0; padding: 0 0 0 var(--spacing-3); border-inline-start: 2px solid var(--default); }
.timeline-list li {
    display: flex;
    align-items: baseline;
    gap: var(--spacing-2);
    flex-wrap: wrap;
    padding-block: var(--spacing-1);
    font-size: var(--font-size-sm);
    color: var(--body);
}
.timeline-time { color: var(--body-subtle); font-size: var(--font-size-xs); flex-shrink: 0; }

.backlinks-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--spacing-3); }
.backlinks-list a { display: inline-flex; align-items: center; gap: var(--spacing-2); color: var(--fg-brand); font-weight: 500; text-decoration: none; }
.backlinks-list a:hover { text-decoration: underline; }

/* Mobil-fangsten: store beroeringmaal, fuld bredde, intet layout at fare vild i. En side der
   aabnes med én tommelfinger paa en perron, skal kunne rammes med samme tommelfinger. */
.capture-page { max-width: 560px; margin: 0 auto; display: flex; flex-direction: column; gap: var(--spacing-4); }
.capture-input { width: 100%; resize: vertical; font-size: var(--font-size-md); line-height: 1.5; }
.capture-button { width: 100%; padding-block: var(--spacing-4); font-size: var(--font-size-md); justify-content: center; }

/* The line the link sits in — evidence of HOW the note is used, quiet under the title so the
   list still scans as a list. break-word: a context can carry a long id or URL. */
.backlink-context {
    display: block;
    color: var(--body-subtle);
    font-size: var(--font-size-sm);
    margin-top: 0.125rem;
    overflow-wrap: break-word;
}

.section-title { font-size: var(--font-size-xl); font-weight: 500; color: var(--heading); margin: 0 0 var(--spacing-6); }

/* ==========================================================================
   Editor (two-pane)
   ========================================================================== */

/* Every track below is minmax(0, …) rather than a bare fr. A bare `1fr` means
   `minmax(auto, 1fr)`: the track refuses to shrink below its widest content, so one long code
   line in the preview, one wide table, or one long title pushes the track — and then the whole
   DOCUMENT — past the viewport. It shows up as a horizontal scrollbar on the page rather than
   inside the offending box, which is why it is so hard to trace back. The single-column mobile
   rules need it just as much: one track can blow out on its own. */
.editor-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--spacing-6); align-items: start; }
.editor-grid textarea.k-input { min-height: 480px; font-size: var(--font-size-sm); line-height: var(--line-height-code); }
.editor-preview { max-height: 640px; overflow-y: auto; }

.form-grid { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1fr) minmax(0, 2fr); gap: var(--spacing-6); }

/* Backlinks beside outgoing links on a note. Declared here rather than inline so the mobile rule
   below can actually override it — an inline style wins over any stylesheet rule. */
.browse-layout--links { grid-template-columns: minmax(0, 1fr) 320px; }

@media (max-width: 900px) {
    .editor-grid, .form-grid { grid-template-columns: minmax(0, 1fr); }
    .browse-layout, .browse-layout--links { grid-template-columns: minmax(0, 1fr); }
    .sidebar { position: static; max-height: none; }
}

/* ==========================================================================
   Note browser — search, sort, folder tree. Shared by skills/templates/snippets/thoughts.
   ========================================================================== */

.browser-toolbar {
    display: flex;
    align-items: center;
    gap: var(--spacing-3);
    flex-wrap: wrap;
}

/* The search field takes the room; the sort and view controls stay their own size. min-width
   keeps it usable once it has shrunk, and lets the row wrap instead of widening the page. */
.browser-search { flex: 1 1 260px; min-width: 200px; }

/* A folder is a TILE in the same grid as the notes, not a row above them. As a small chevron
   button beside full-size cards, a folder holding 25 skills read as a minor control — the one
   thing on the page hiding most of its content looked like the least important thing on it. */
.folder-tile {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-3);
    min-width: 0;
    text-align: start;
    font-family: var(--font-family);
    cursor: pointer;
    border: 1px solid var(--default-medium);
    background: var(--neutral-secondary-soft);
    transition: transform 180ms ease-out, border-color 180ms ease-out, background 180ms ease-out;
}

.folder-tile:hover {
    transform: translateY(-4px);
    border-color: var(--brand);
    background: var(--brand-softer);
}

.folder-tile-head { display: flex; align-items: center; gap: var(--spacing-2); min-width: 0; }
.folder-tile-head .icon { color: var(--fg-brand); flex-shrink: 0; }
.folder-tile-head .k-card-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* A peek at the contents. The count says how much is inside; this says what KIND of thing it is,
   which is what decides whether it is the folder you want. */
.folder-tile-peek {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
    font-size: var(--font-size-xs);
    color: var(--body-subtle);
}

.folder-tile-item { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.folder-tile-foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--spacing-2);
    margin-top: auto;
    padding-top: var(--spacing-2);
}

.folder-tile-foot .icon { color: var(--body-subtle); }

@media (prefers-reduced-motion: reduce) {
    .folder-tile:hover { transform: none; }
}

/* Breadcrumb — the only thing that says where you are once you have walked into a folder. */
.crumbs { display: flex; align-items: center; gap: var(--spacing-1); flex-wrap: wrap; }

.crumb {
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-1-5);
    padding: var(--spacing-1) var(--spacing-2);
    background: transparent;
    border: none;
    border-radius: var(--radius-md);
    font-family: var(--font-family);
    font-size: var(--font-size-sm);
    color: var(--body-subtle);
    cursor: pointer;
    transition: color 150ms, background 150ms;
}

.crumb:hover { color: var(--heading); background: var(--neutral-secondary-medium); }

.crumb--current { color: var(--heading); font-weight: 600; }

.crumb-sep { color: var(--gray); }

/* ==========================================================================
   Diff view (history) — status colors carry REAL state here
   ========================================================================== */

.diff-view {
    font-family: var(--font-family);
    font-size: var(--font-size-xs);
    line-height: var(--line-height-code);
    background: var(--neutral-primary-soft);
    border-radius: var(--radius-xxl);
    overflow-x: auto;
    padding: var(--spacing-4) 0;
}

.diff-line { padding: 0 var(--spacing-4); white-space: pre-wrap; overflow-wrap: anywhere; }
.diff-line--add { background: var(--success-soft); color: var(--fg-success-strong); }
.diff-line--del { background: var(--danger-soft); color: var(--fg-danger-strong); }
.diff-line--hunk { color: var(--fg-brand); background: var(--brand-softer); padding-block: var(--spacing-0-5); }
.diff-line--meta { color: var(--body-subtle); }

/* ==========================================================================
   Template detail — highlighted placeholder card (brand-softer tone shift,
   per cards.md's highlighted-tier pattern) + file tree items
   ========================================================================== */

.placeholder-panel {
    background: var(--brand-softer);
    border-radius: var(--radius-xxl);
    padding: var(--spacing-5);
}

.placeholder-panel .prose table { font-size: var(--font-size-sm); margin-bottom: 0; }
.placeholder-panel .prose th { background: var(--brand-soft); color: var(--heading); }

.file-item {
    display: flex;
    align-items: center;
    gap: var(--spacing-1-5);
    width: 100%;
    text-align: start;
    background: transparent;
    border: none;
    cursor: pointer;
    font-family: var(--font-family);
    font-size: var(--font-size-xs);
    line-height: var(--line-height-component);
    color: var(--body);
    border-radius: var(--radius-sm);
    padding: var(--spacing-1-5) var(--spacing-2);
    overflow-wrap: anywhere;
    transition: background-color 150ms, color 150ms;
}

.file-item:hover { background: var(--hover-bg); color: var(--heading); }
.file-item.active { background: var(--active-bg); color: var(--fg-brand); font-weight: 500; }
.file-item:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--brand-subtle); }

/* ==========================================================================
   Code blocks — copy button + highlight.js theme mapped to Kinetic tokens
   (accent foregrounds are for inline highlights; syntax tokens qualify)
   ========================================================================== */

.code-block { position: relative; }

.code-copy {
    position: absolute;
    top: var(--spacing-2);
    inset-inline-end: var(--spacing-2);
    width: 28px;
    height: 28px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--neutral-primary-soft);
    color: var(--body);
    border: none;
    border-radius: var(--radius-sm);
    cursor: pointer;
    opacity: 0;
    transition: opacity 150ms, background-color 150ms, color 150ms;
}

.code-block:hover .code-copy, .code-copy:focus-visible { opacity: 1; }
.code-copy:hover { background: var(--hover-bg); color: var(--heading); }
.code-copy:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--brand-medium); }
.code-copy.copied { color: var(--fg-success); opacity: 1; }

.hljs { background: transparent; color: var(--heading); }
.hljs-comment, .hljs-quote { color: var(--body-subtle); }
.hljs-keyword, .hljs-selector-tag, .hljs-tag, .hljs-name { color: var(--fg-brand); }
.hljs-string, .hljs-attr, .hljs-selector-attr, .hljs-template-tag { color: var(--fg-success); }
.hljs-number, .hljs-literal, .hljs-symbol { color: var(--fg-purple); }
.hljs-title, .hljs-title.class_, .hljs-title.function_, .hljs-section { color: var(--fg-cyan); }
.hljs-built_in, .hljs-type { color: var(--fg-yellow); }
.hljs-meta, .hljs-doctag { color: var(--body-subtle); }
.hljs-variable, .hljs-params { color: var(--body); }
.hljs-emphasis { font-style: italic; }
.hljs-strong { font-weight: 600; }

/* ==========================================================================
   Dropdown — dropdowns.md: the ONE floating-overlay exception (medium shadow),
   panel border = own fill subtly darkened, 4px shell, radius-md items, auto width
   ========================================================================== */

.k-dropdown { position: relative; display: inline-block; }

/* A menu opened from the right edge must not run off it. */
.k-dropdown-panel--end { inset-inline-start: auto; inset-inline-end: 0; }

.k-dropdown-panel {
    position: absolute;
    top: calc(100% + var(--spacing-2));
    inset-inline-start: 0;
    z-index: 200;
    background: var(--neutral-primary-medium);
    border: 1px solid var(--light);
    border-radius: var(--radius-xxl);
    box-shadow: var(--elevation-2);
    padding: var(--spacing-2);
    min-width: 144px;
    max-width: 320px;
    width: max-content;
}

.k-dropdown-item {
    display: flex;
    align-items: center;
    gap: var(--spacing-2);
    width: 100%;
    padding: var(--spacing-2);
    border-radius: var(--radius-md);
    font-family: var(--font-family);
    font-size: var(--font-size-sm);
    font-weight: 500;
    line-height: var(--line-height-component);
    color: var(--body);
    background: transparent;
    border: none;
    text-decoration: none;
    cursor: pointer;
    white-space: nowrap;
    transition: background-color 150ms, color 150ms;
}

.k-dropdown-item:hover { background: var(--hover-bg); color: var(--heading); }

.k-dropdown-divider { height: 1px; background: var(--default-medium); margin: var(--spacing-2) 0; }

.k-dropdown-header {
    font-size: var(--font-size-sm);
    font-weight: 600;
    color: var(--body-subtle);
    padding: var(--spacing-2);
}

/* ==========================================================================
   Skill-import dropzone — file-input.md: dashed default-strong edge (the one
   dashed border in the system), contrasting fill, centered column
   ========================================================================== */

.skill-dropzone {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--spacing-2);
    min-height: 256px;
    width: 100%;
    background: var(--neutral-secondary-medium);
    border: 1px dashed var(--default-strong);
    border-radius: var(--radius-xxl);
    cursor: pointer;
    color: var(--body);
    font-size: var(--font-size-sm);
    padding: var(--spacing-5) var(--spacing-6) var(--spacing-6);
    transition: background-color 150ms;
    text-align: center;
}

.skill-dropzone:hover { background: var(--neutral-tertiary-medium); }
.skill-dropzone:focus-within { border-color: var(--brand); box-shadow: var(--focus-ring); }
.skill-dropzone .icon { color: var(--body); }
.skill-dropzone strong { font-weight: 600; }
.skill-dropzone-hint { font-size: var(--font-size-xs); color: var(--body-subtle); }

/* ==========================================================================
   Toggle — toggle.md: pill track 36×20, 16px thumb, uniform 2px gap,
   translate = 36−16−4 = 16px. Custom-drawn (appearance reset via hidden input).
   ========================================================================== */

.k-toggle {
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-3);
    font-size: var(--font-size-sm);
    font-weight: 500;
    color: var(--heading);
    cursor: pointer;
    position: relative;
}

.k-toggle input {
    position: absolute;
    opacity: 0;
    width: 1px;
    height: 1px;
}

.k-toggle-track {
    box-sizing: content-box;
    width: 36px;
    height: 20px;
    background: var(--neutral-quaternary);
    border-radius: var(--radius-full);
    position: relative;
    flex-shrink: 0;
    display: inline-block;
    transition: background-color 150ms;
}

.k-toggle-thumb {
    position: absolute;
    top: 2px;
    left: 2px;
    width: 16px;
    height: 16px;
    background: var(--neutral-primary-soft);
    border-radius: var(--radius-full);
    transition: transform 175ms ease;
    display: block;
}

.k-toggle input:checked + .k-toggle-track { background: var(--brand); }
.k-toggle input:checked + .k-toggle-track .k-toggle-thumb { transform: translateX(16px); }
.k-toggle input:focus-visible + .k-toggle-track { box-shadow: 0 0 0 4px var(--brand-soft); }

/* Dashboard widgets — application widget grid gap is 16px; widget titles use
   the dense widget scale, not the 20px card-title */
/* minmax(0, 1fr) og ikke 1fr: '1fr' betyder 'minmax(auto, 1fr)', og auto-minimummet er
   indholdets min-content-bredde. En lang commit-besked uden mellemrum presser derfor sporet
   bredere end containeren og sprænger hele sidens layout — uanset at teksten selv afkortes. */
.widget-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--spacing-4); }
.widget-grid > * { min-width: 0; }
@media (max-width: 900px) { .widget-grid { grid-template-columns: minmax(0, 1fr); } }

.widget-title {
    display: flex;
    align-items: center;
    gap: var(--spacing-1-5);
    font-size: var(--font-size-md);
    font-weight: 500;
    color: var(--heading);
    margin-bottom: var(--spacing-3);
}

.widget-row {
    display: flex;
    align-items: baseline;
    gap: var(--spacing-2);
    padding-block: var(--spacing-1);
    font-size: var(--font-size-xs);
    min-width: 0;
}

.widget-row-text {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    flex: 1;
    min-width: 0;
}

/* Favorite star: active state via fg-yellow (semantic emphasis, not status) */
.favorite-active { color: var(--fg-yellow); }
.favorite-active:hover { color: var(--fg-yellow); }

/* Command palette (Ctrl/Cmd+K) */
.k-modal.palette { max-width: 560px; padding: var(--spacing-3); gap: var(--spacing-2); }
.palette-results { display: flex; flex-direction: column; margin-top: var(--spacing-2); max-height: 50vh; overflow-y: auto; }
.palette-results .k-dropdown-item { width: 100%; text-align: start; }
.palette-active { background: var(--hover-bg); color: var(--heading); }

/* Graph legend dots — accent tokens, chart use */
.graph-dot { width: 8px; height: 8px; border-radius: var(--radius-full); display: inline-block; }
.graph-dot--term { background: var(--sky); }
.graph-dot--knowledge { background: var(--teal); }
.graph-dot--skill { background: var(--fg-yellow); }
.graph-dot--agent { background: var(--purple); }
.graph-dot--snippet { background: var(--cyan); }
.graph-dot--template { background: var(--orange); }
.graph-dot--thought { background: var(--gray); }
.graph-dot--project { background: var(--indigo); }
.graph-dot--client { background: var(--pink); }
.graph-dot--organisation { background: var(--fg-lime); }

/* ==========================================================================
   Utility
   ========================================================================== */

.stack-2 > * + * { margin-top: var(--spacing-2); }
.stack-4 > * + * { margin-top: var(--spacing-4); }
.stack-6 > * + * { margin-top: var(--spacing-6); }
.mt-6 { margin-top: var(--spacing-6); }
.mb-2 { margin-bottom: var(--spacing-2); }
.mb-4 { margin-bottom: var(--spacing-4); }
.mb-6 { margin-bottom: var(--spacing-6); }
.flex-between { display: flex; align-items: center; justify-content: space-between; gap: var(--spacing-4); flex-wrap: wrap; }
.sr-only {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* ==========================================================================
   Fejl- og forbindelsesflader
   ========================================================================== */

/* Blazors egen fejlbjælke: vises af blazor.web.js når kredsløbet dør af en uhåndteret fejl.
   Uden elementet frøs siden bare. Danger-flade, bund af skærmen, ingen kort-radius: det er
   en systemmeddelelse, ikke indhold. */
#blazor-error-ui {
    display: none;
    position: fixed;
    inset-inline: 0;
    bottom: 0;
    z-index: 1000;
    padding: var(--spacing-3) var(--spacing-10) var(--spacing-3) var(--spacing-4);
    background: var(--danger-soft);
    color: var(--fg-danger-strong);
    border-top: 2px solid var(--danger);
    font-family: var(--font-family);
    font-size: var(--font-size-sm);
    line-height: 1.5;
}

#blazor-error-ui .reload {
    margin-inline-start: var(--spacing-3);
    color: inherit;
    font-weight: 600;
    text-decoration: underline;
    white-space: nowrap;
}

#blazor-error-ui .dismiss {
    position: absolute;
    right: var(--spacing-4);
    top: 50%;
    transform: translateY(-50%);
    cursor: pointer;
    font-size: var(--font-size-lg);
    line-height: 1;
}
