@import '_content/DRYL.Components.Agents/DRYL.Components.Agents.re9dmxhqkf.bundle.scp.css';
@import '_content/DRYL.Components/DRYL.Components.5t84w0ca43.bundle.scp.css';

/* /Components/Layout/AdminLayout.razor.rz.scp.css */
/* AdminLayout — scoped styles, token-driven only.
   The shell, sidebar and content area now come from the official DRYL app-shell
   components (DrylLayout / DrylDrawer / DrylMainContent) and dryl.css. Only the
   admin-specific app-bar title and the logout form need local tweaks. */

.admin-appbar-title[b-bmhknb5g79] {
    font-weight: 600;
    color: var(--fg);
    letter-spacing: -0.01em;
}

.admin-logout-form[b-bmhknb5g79] {
    margin: 0;
    width: 100%;
}

.admin-logout-form[b-bmhknb5g79]  .btn {
    width: 100%;
    justify-content: center;
}
/* /Components/Layout/MainLayout.razor.rz.scp.css */
.layout-fallback[b-6ff8re8adg] {
    min-height: 100vh;
    padding: var(--sp-4);
    color: var(--fg);
}
/* /Components/Layout/PortfolioLayout.razor.rz.scp.css */
/* PortfolioLayout — scoped styles, token-driven only.
   All values reference dryl.css custom properties — no literal colors, spacing, or radii. */

/* ── Shell ─────────────────────────────────────────────── */

.portfolio-shell[b-jsmbjypopo] {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
}

/* ── Top nav ─────────────────────────────────────────────── */

.portfolio-nav[b-jsmbjypopo] {
    position: sticky;
    top: 0;
    z-index: var(--z-sticky);
    display: flex;
    align-items: center;
    gap: var(--sp-5);
    padding: 0 var(--sp-6);
    height: var(--appbar-h);
    background: color-mix(in srgb, var(--ground) 72%, transparent);
    backdrop-filter: blur(var(--glass-blur)) saturate(140%);
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(140%);
    border-bottom: 1px solid var(--line);
    box-shadow: var(--shadow-sm);
    transition: height var(--dur-med) var(--ease-out),
                background var(--dur-med) var(--ease-out),
                border-color var(--dur-med) var(--ease-out),
                box-shadow var(--dur-med) var(--ease-out);
}

/* portfolio.js toggles .is-scrolled past 24px — nav condenses and grounds. */
.portfolio-nav.is-scrolled[b-jsmbjypopo] {
    height: calc(var(--appbar-h) - 6px);
    background: color-mix(in srgb, var(--ground) 88%, transparent);
    border-bottom-color: var(--line-strong);
    box-shadow: var(--shadow-md);
}

.portfolio-brand[b-jsmbjypopo] {
    position: relative;
    color: var(--fg);
    font-weight: 700;
    font-size: 1.0625rem;
    text-decoration: none;
    letter-spacing: -0.02em;
    flex-shrink: 0;
    transition: opacity var(--dur-fast) var(--ease-out);
}

/* gradient brand wordmark */
.portfolio-brand[b-jsmbjypopo] {
    background: var(--accent-grad);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}

.portfolio-brand:hover[b-jsmbjypopo],
.portfolio-brand:focus-visible[b-jsmbjypopo] {
    opacity: 0.85;
}

.portfolio-nav-links[b-jsmbjypopo] {
    display: flex;
    align-items: center;
    gap: var(--sp-1);
    margin-left: auto;
}

/* ── Mobile menu toggle (hamburger) ───────────────────────────
   Hidden on desktop; the media query below reveals it and turns
   the inline links into a collapsible glass dropdown. */
.portfolio-nav-toggle[b-jsmbjypopo] {
    display: none;
    flex-direction: column;
    justify-content: center;
    gap: 5px;
    margin-left: auto;
    width: 40px;
    height: 40px;
    padding: 0 9px;
    border-radius: var(--r-sm);
    border: 1px solid var(--line-strong);
    background: var(--glass-2);
    cursor: pointer;
    transition: border-color var(--dur-fast) var(--ease-out),
                background var(--dur-fast) var(--ease-out),
                box-shadow var(--dur-fast) var(--ease-out);
}

.portfolio-nav-toggle:hover[b-jsmbjypopo],
.portfolio-nav-toggle:focus-visible[b-jsmbjypopo] {
    border-color: var(--accent-line);
    background: var(--glass-3);
    box-shadow: 0 0 0 1px var(--accent-line), 0 4px 16px var(--accent-soft);
}

.portfolio-nav-toggle-bar[b-jsmbjypopo] {
    display: block;
    width: 100%;
    height: 2px;
    border-radius: var(--r-pill);
    background: var(--fg);
    transition: transform var(--dur-med) var(--ease-spring),
                opacity var(--dur-fast) var(--ease-out);
}

/* hamburger morphs into an X while the menu is open */
.portfolio-nav.is-open .portfolio-nav-toggle-bar:nth-child(1)[b-jsmbjypopo] {
    transform: translateY(7px) rotate(45deg);
}

.portfolio-nav.is-open .portfolio-nav-toggle-bar:nth-child(2)[b-jsmbjypopo] {
    opacity: 0;
}

.portfolio-nav.is-open .portfolio-nav-toggle-bar:nth-child(3)[b-jsmbjypopo] {
    transform: translateY(-7px) rotate(-45deg);
}

/* NavLink renders an <a>, which is a child-component output — Blazor CSS
   isolation does NOT add the scope attribute to it, so plain `.portfolio-link`
   rules never match. `::deep` pierces the scope from the (scoped) nav wrapper. */
.portfolio-nav-links[b-jsmbjypopo]  .portfolio-link {
    position: relative;
    display: inline-flex;
    align-items: center;
    padding: var(--sp-2) var(--sp-3);
    border-radius: var(--r-sm);
    color: var(--fg-muted);
    text-decoration: none;
    font-size: 0.875rem;
    font-weight: 500;
    transition: color var(--dur-fast) var(--ease-out),
                background var(--dur-fast) var(--ease-out);
}

/* animated gradient underline that grows from the centre */
.portfolio-nav-links[b-jsmbjypopo]  .portfolio-link::after {
    content: "";
    position: absolute;
    left: var(--sp-3);
    right: var(--sp-3);
    bottom: 4px;
    height: 2px;
    border-radius: var(--r-pill);
    background: var(--accent-grad);
    transform: scaleX(0);
    transform-origin: center;
    opacity: 0;
    transition: transform var(--dur-med) var(--ease-spring),
                opacity var(--dur-fast) var(--ease-out);
}

.portfolio-nav-links[b-jsmbjypopo]  .portfolio-link:hover,
.portfolio-nav-links[b-jsmbjypopo]  .portfolio-link:focus-visible {
    color: var(--fg);
}

.portfolio-nav-links[b-jsmbjypopo]  .portfolio-link:hover::after,
.portfolio-nav-links[b-jsmbjypopo]  .portfolio-link:focus-visible::after,
.portfolio-nav-links[b-jsmbjypopo]  .portfolio-link.active::after {
    transform: scaleX(1);
    opacity: 1;
}

.portfolio-nav-links[b-jsmbjypopo]  .portfolio-link.active {
    color: var(--fg);
}

/* CTA-style Kontakt link */
.portfolio-nav-links[b-jsmbjypopo]  .portfolio-link--cta {
    color: var(--fg);
    background: var(--glass-3);
    border: 1px solid var(--line-strong);
}

/* the CTA link carries a border/glow instead of the underline */
.portfolio-nav-links[b-jsmbjypopo]  .portfolio-link--cta::after {
    display: none;
}

.portfolio-nav-links[b-jsmbjypopo]  .portfolio-link--cta:hover,
.portfolio-nav-links[b-jsmbjypopo]  .portfolio-link--cta:focus-visible {
    border-color: var(--accent-line);
    box-shadow: 0 0 0 1px var(--accent-line), 0 4px 16px var(--accent-soft);
}

.portfolio-nav-links[b-jsmbjypopo]  .portfolio-link--cta.active {
    border-color: var(--accent-line);
}

/* ── Mobile nav (≤ 640px) ─────────────────────────────────────
   Below this width the inline links overflow the bar, so they
   collapse behind the hamburger into a full-width glass dropdown. */
@media (max-width: 640px) {
    .portfolio-nav[b-jsmbjypopo] {
        gap: var(--sp-3);
        padding: 0 var(--sp-4);
    }

    .portfolio-nav-toggle[b-jsmbjypopo] {
        display: inline-flex;
    }

    /* links drop out of the bar flow and become a panel under the header */
    .portfolio-nav-links[b-jsmbjypopo] {
        position: absolute;
        top: 100%;
        left: 0;
        right: 0;
        flex-direction: column;
        align-items: stretch;
        gap: var(--sp-1);
        margin-left: 0;
        padding: var(--sp-3);
        background: color-mix(in srgb, var(--ground) 92%, transparent);
        backdrop-filter: blur(var(--glass-blur)) saturate(140%);
        -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(140%);
        border-bottom: 1px solid var(--line);
        box-shadow: var(--shadow-md);

        /* collapsed by default — revealed when the header has .is-open */
        opacity: 0;
        visibility: hidden;
        transform: translateY(-8px);
        transition: opacity var(--dur-med) var(--ease-out),
                    transform var(--dur-med) var(--ease-out),
                    visibility var(--dur-med) var(--ease-out);
    }

    .portfolio-nav.is-open .portfolio-nav-links[b-jsmbjypopo] {
        opacity: 1;
        visibility: visible;
        transform: translateY(0);
    }

    /* full-width, taller tap targets; the centre underline doesn't suit a
       stacked list, so active state reads as a filled row instead */
    .portfolio-nav-links[b-jsmbjypopo]  .portfolio-link {
        padding: var(--sp-3);
        font-size: 0.9375rem;
    }

    .portfolio-nav-links[b-jsmbjypopo]  .portfolio-link::after {
        display: none;
    }

    .portfolio-nav-links[b-jsmbjypopo]  .portfolio-link.active {
        background: var(--glass-2);
    }

    .portfolio-nav-links[b-jsmbjypopo]  .portfolio-link--cta {
        justify-content: center;
        margin-top: var(--sp-1);
    }
}

/* ── Main content ─────────────────────────────────────────── */

.portfolio-main[b-jsmbjypopo] {
    flex: 1;
}

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

.portfolio-footer[b-jsmbjypopo] {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--sp-4);
    padding: var(--sp-8) var(--sp-6) var(--sp-6);
    border-top: 1px solid var(--line);
    background: linear-gradient(to bottom,
        transparent,
        color-mix(in srgb, var(--accent-a) 6%, transparent));
}

/* hairline accent glow along the top edge of the footer */
.portfolio-footer[b-jsmbjypopo]::before {
    content: "";
    position: absolute;
    top: -1px;
    left: 50%;
    transform: translateX(-50%);
    width: min(420px, 60%);
    height: 1px;
    background: var(--accent-grad);
    opacity: 0.5;
}

.portfolio-footer-mark[b-jsmbjypopo] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border-radius: var(--r-md);
    font-weight: 700;
    font-size: 0.875rem;
    letter-spacing: 0.02em;
    color: var(--fg);
    border: 1px solid var(--line-strong);
    background: var(--glass-2);
    box-shadow: var(--glow-soft);
}

.portfolio-footer-social[b-jsmbjypopo] {
    display: flex;
    gap: var(--sp-3);
}

.portfolio-social-link[b-jsmbjypopo] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border-radius: var(--r-sm);
    color: var(--fg-muted);
    text-decoration: none;
    border: 1px solid var(--line);
    background: var(--glass-2);
    transition: color var(--dur-fast) var(--ease-out),
                border-color var(--dur-fast) var(--ease-out),
                box-shadow var(--dur-fast) var(--ease-out),
                transform var(--dur-fast) var(--ease-out),
                background var(--dur-fast) var(--ease-out);
}

.portfolio-social-link:hover[b-jsmbjypopo],
.portfolio-social-link:focus-visible[b-jsmbjypopo] {
    color: var(--fg);
    background: var(--glass-3);
    border-color: var(--accent-line);
    box-shadow: 0 0 0 1px var(--accent-line), 0 6px 20px var(--accent-soft);
    transform: translateY(-2px);
}

.portfolio-footer-copy[b-jsmbjypopo] {
    margin: 0;
    font-size: 0.75rem;
    color: var(--fg-dim);
}
/* /Components/Layout/ReconnectModal.razor.rz.scp.css */
.components-reconnect-first-attempt-visible[b-2hf4eerfdg],
.components-reconnect-repeated-attempt-visible[b-2hf4eerfdg],
.components-reconnect-failed-visible[b-2hf4eerfdg],
.components-pause-visible[b-2hf4eerfdg],
.components-resume-failed-visible[b-2hf4eerfdg],
.components-rejoining-animation[b-2hf4eerfdg] {
    display: none;
}

#components-reconnect-modal.components-reconnect-show .components-reconnect-first-attempt-visible[b-2hf4eerfdg],
#components-reconnect-modal.components-reconnect-show .components-rejoining-animation[b-2hf4eerfdg],
#components-reconnect-modal.components-reconnect-paused .components-pause-visible[b-2hf4eerfdg],
#components-reconnect-modal.components-reconnect-resume-failed .components-resume-failed-visible[b-2hf4eerfdg],
#components-reconnect-modal.components-reconnect-retrying[b-2hf4eerfdg],
#components-reconnect-modal.components-reconnect-retrying .components-reconnect-repeated-attempt-visible[b-2hf4eerfdg],
#components-reconnect-modal.components-reconnect-retrying .components-rejoining-animation[b-2hf4eerfdg],
#components-reconnect-modal.components-reconnect-failed[b-2hf4eerfdg],
#components-reconnect-modal.components-reconnect-failed .components-reconnect-failed-visible[b-2hf4eerfdg] {
    display: block;
}


#components-reconnect-modal[b-2hf4eerfdg] {
    background-color: white;
    width: 20rem;
    margin: 20vh auto;
    padding: 2rem;
    border: 0;
    border-radius: 0.5rem;
    box-shadow: 0 3px 6px 2px rgba(0, 0, 0, 0.3);
    opacity: 0;
    transition: display 0.5s allow-discrete, overlay 0.5s allow-discrete;
    animation: components-reconnect-modal-fadeOutOpacity-b-2hf4eerfdg 0.5s both;
    &[open]

{
    animation: components-reconnect-modal-slideUp-b-2hf4eerfdg 1.5s cubic-bezier(.05, .89, .25, 1.02) 0.3s, components-reconnect-modal-fadeInOpacity-b-2hf4eerfdg 0.5s ease-in-out 0.3s;
    animation-fill-mode: both;
}

}

#components-reconnect-modal[b-2hf4eerfdg]::backdrop {
    background-color: rgba(0, 0, 0, 0.4);
    animation: components-reconnect-modal-fadeInOpacity-b-2hf4eerfdg 0.5s ease-in-out;
    opacity: 1;
}

@keyframes components-reconnect-modal-slideUp-b-2hf4eerfdg {
    0% {
        transform: translateY(30px) scale(0.95);
    }

    100% {
        transform: translateY(0);
    }
}

@keyframes components-reconnect-modal-fadeInOpacity-b-2hf4eerfdg {
    0% {
        opacity: 0;
    }

    100% {
        opacity: 1;
    }
}

@keyframes components-reconnect-modal-fadeOutOpacity-b-2hf4eerfdg {
    0% {
        opacity: 1;
    }

    100% {
        opacity: 0;
    }
}

.components-reconnect-container[b-2hf4eerfdg] {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1rem;
}

#components-reconnect-modal p[b-2hf4eerfdg] {
    margin: 0;
    text-align: center;
}

#components-reconnect-modal button[b-2hf4eerfdg] {
    border: 0;
    background-color: #6b9ed2;
    color: white;
    padding: 4px 24px;
    border-radius: 4px;
}

    #components-reconnect-modal button:hover[b-2hf4eerfdg] {
        background-color: #3b6ea2;
    }

    #components-reconnect-modal button:active[b-2hf4eerfdg] {
        background-color: #6b9ed2;
    }

.components-rejoining-animation[b-2hf4eerfdg] {
    position: relative;
    width: 80px;
    height: 80px;
}

    .components-rejoining-animation div[b-2hf4eerfdg] {
        position: absolute;
        border: 3px solid #0087ff;
        opacity: 1;
        border-radius: 50%;
        animation: components-rejoining-animation-b-2hf4eerfdg 1.5s cubic-bezier(0, 0.2, 0.8, 1) infinite;
    }

        .components-rejoining-animation div:nth-child(2)[b-2hf4eerfdg] {
            animation-delay: -0.5s;
        }

@keyframes components-rejoining-animation-b-2hf4eerfdg {
    0% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 0;
    }

    4.9% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 0;
    }

    5% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 1;
    }

    100% {
        top: 0px;
        left: 0px;
        width: 80px;
        height: 80px;
        opacity: 0;
    }
}
/* /Features/Admin/AdminHome.razor.rz.scp.css */
/* AdminHome — KPI grid                                                    */
/* Spacing/colors use dryl.css tokens. Font sizes are raw px/rem because   */
/* dryl.css has no typography-scale tokens (consistent with library CSS).  */

.dashboard-heading[b-yg50dxvp81] {
    font-size: 20px;
    font-weight: 600;
    color: var(--fg);
    margin-bottom: var(--sp-4);
}

/* The KPI grid layout now lives inline on the DrylReveal wrapper in the
   markup — Blazor scoped CSS can't target a child component's root element,
   so a `.admin-kpis` rule here would never bind. */

.kpi-label[b-yg50dxvp81] {
    font-size: 12px;
    color: var(--fg-muted);
    margin: 0 0 var(--sp-2) 0;
    font-weight: 500;
}

.kpi-value[b-yg50dxvp81] {
    font-size: 2rem;
    font-weight: 700;
    color: var(--fg);
    margin: 0;
}
/* /Features/Admin/AiAssistant.razor.rz.scp.css */
/*  Die Assistent-Seite ist eine Fläche, kein Layout: der Canvas füllt den Inhaltsbereich des
    AdminLayouts randlos, das Dock liegt im Top-Layer darüber und bringt seine Position selbst
    mit. Was hier bleibt, sind die Planzeilen im aufgeklappten Dock-Log. */

.assistant-surface[b-h99vslllo9] {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: var(--sp-3);
    height: 100%;
    /* Ohne min-height:0 kann das Flex-Kind nicht schrumpfen und der Canvas nicht scrollen. */
    min-height: 0;
}

/*  ::deep, weil .canvas-workspace aus einer Kindkomponente stammt und Blazors scoped CSS
    dort nicht hinreicht. */
.assistant-surface[b-h99vslllo9]  .canvas-workspace {
    flex: 1 1 auto;
    min-height: 0;
}

/* ── Plan im Dock-Log ─────────────────────────────────────────────── */

.plan-items[b-h99vslllo9] {
    display: flex;
    flex-direction: column;
    gap: var(--sp-1);
    margin-bottom: var(--sp-3);
}

.plan-item[b-h99vslllo9] {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    font-size: 13px;
    color: var(--fg-muted);
    transition: color var(--dur-fast) var(--ease-out);
}

.plan-item-icon[b-h99vslllo9] {
    display: inline-flex;
    align-items: center;
    color: var(--fg-dim);
    transition: color var(--dur-fast) var(--ease-out);
}

.plan-item--active[b-h99vslllo9] {
    color: var(--fg);
}

.plan-item--active .plan-item-icon[b-h99vslllo9] {
    color: var(--accent-a);
}

.plan-item--done[b-h99vslllo9] {
    color: var(--fg-dim);
}
/* /Features/Admin/ContentAdmin.razor.rz.scp.css */
/* The page column layout now lives inline on the DrylReveal wrapper that
   staggers the page in; Blazor scoped CSS can't reach a child component's
   root element, so a `.content-admin` rule would never bind. */

.content-header[b-g90rv41jo7] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-4);
}

.content-title[b-g90rv41jo7] {
    margin: 0;
    font-size: 1.5rem;
    font-weight: 600;
    color: var(--fg);
}

.content-form-card[b-g90rv41jo7] {
    display: flex;
    flex-direction: column;
    gap: var(--sp-4);
}

.section-heading[b-g90rv41jo7] {
    margin: 0 0 var(--sp-1);
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--fg-muted);
    text-transform: uppercase;
    letter-spacing: 0.06em;
}

.form-actions[b-g90rv41jo7] {
    display: flex;
    justify-content: flex-end;
    gap: var(--sp-3);
}
/* /Features/Admin/Inbox.razor.rz.scp.css */
/* ── Inbox admin page ─────────────────────────────────────── */

/* The page column layout now lives inline on the DrylReveal wrapper that
   staggers the page in; Blazor scoped CSS can't reach a child component's
   root element, so a `.inbox-admin` rule would never bind. */

.inbox-header[b-k3mhlr4qk9] {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
}

.inbox-title[b-k3mhlr4qk9] {
    font-size: 1.5rem;
    font-weight: 600;
    color: var(--fg);
    margin: 0;
}

/* ── From cell ── */

.inbox-from[b-k3mhlr4qk9] {
    display: flex;
    flex-direction: column;
    gap: var(--sp-1);
}

.inbox-from-name[b-k3mhlr4qk9] {
    color: var(--fg);
    font-weight: 500;
}

.inbox-from-email[b-k3mhlr4qk9] {
    color: var(--fg-muted);
    font-size: 0.75rem;
}

/* ── Unread emphasis ── */

.inbox-unread[b-k3mhlr4qk9] {
    color: var(--fg);
    font-weight: 600;
}

/* ── Date cell ── */

.inbox-date[b-k3mhlr4qk9] {
    color: var(--fg-muted);
    font-size: 0.8125rem;
}

/* ── Empty state ── */

.inbox-empty[b-k3mhlr4qk9] {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--sp-4);
    padding: var(--sp-8) var(--sp-4);
    color: var(--fg-dim);
}

.inbox-empty-icon[b-k3mhlr4qk9] {
    opacity: 0.35;
}

.inbox-empty-text[b-k3mhlr4qk9] {
    font-size: 1rem;
    color: var(--fg-dim);
    margin: 0;
}

/* ── Detail panel ── */

.inbox-detail-card[b-k3mhlr4qk9] {
    display: flex;
    flex-direction: column;
    gap: var(--sp-4);
}

.inbox-detail-header[b-k3mhlr4qk9] {
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
    padding-bottom: var(--sp-3);
    border-bottom: 1px solid var(--line);
}

.inbox-detail-meta[b-k3mhlr4qk9] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-3);
    flex-wrap: wrap;
}

.inbox-detail-from[b-k3mhlr4qk9] {
    color: var(--fg-muted);
    font-size: 0.8125rem;
}

.inbox-detail-date[b-k3mhlr4qk9] {
    color: var(--fg-dim);
    font-size: 0.8125rem;
}

.inbox-detail-subject[b-k3mhlr4qk9] {
    font-size: 1.125rem;
    font-weight: 600;
    color: var(--fg);
    margin: 0;
}

.inbox-detail-body[b-k3mhlr4qk9] {
    color: var(--fg-muted);
    line-height: 1.65;
    white-space: pre-wrap;
}

.inbox-detail-actions[b-k3mhlr4qk9] {
    display: flex;
    gap: var(--sp-2);
    padding-top: var(--sp-3);
    border-top: 1px solid var(--line);
}
/* /Features/Admin/KnowledgeAdmin.razor.rz.scp.css */
/* Nur Tokens — keine Literale (DRYL-Regel 2.1). dryl.css kennt keine
   Font-size-Tokens (die Größen sind dort selbst Roh-px/rem) — hier wird darum,
   wie in jeder anderen Admin-Seite (ProjectsAdmin.razor.css u.a.), mit rem
   gearbeitet statt einen nicht-existierenden --fs-* Token zu erfinden. */
.kb-header[b-6v2i4x41zc] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-3);
}

.kb-title[b-6v2i4x41zc] {
    font-size: 1.5rem;
    font-weight: 600;
    color: var(--fg);
    margin: 0;
}

.kb-filters-block[b-6v2i4x41zc] {
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
}

.kb-filters[b-6v2i4x41zc] {
    display: grid;
    grid-template-columns: 2fr 1fr 1fr 1fr;
    gap: var(--sp-3);
}

.kb-search-hint[b-6v2i4x41zc] {
    margin: 0;
    font-size: 0.75rem;
    color: var(--fg-dim);
}

/* DrylPresence renders a real block wrapper (no display:contents) and keeps an exiting
   child mounted until its fade-out animation ends — in normal flow the outgoing and
   incoming state would sit stacked underneath each other for that ~240ms and the page
   height would jump. Putting all three DrylPresence wrappers in the same CSS-Grid cell
   makes them overlap instead: only the tallest of the currently-mounted ones drives the
   row height, so the transition reads as a crossfade, not a jump. ::deep is required
   because the .presence element belongs to DrylPresence's own CSS-isolation scope, not
   this page's. min-height (composed from the --sp-* scale, no raw px) keeps the area from
   collapsing to nothing for the one frame where only a just-exiting sliver remains. */
.kb-content-stack[b-6v2i4x41zc] {
    display: grid;
    min-height: calc(var(--sp-8) * 4);
}

.kb-content-stack[b-6v2i4x41zc]  .presence {
    /* dryl.css already sets min-width: 0 on .presence globally, so the table (a wide
       grid item) can shrink instead of forcing the grid track wider. */
    grid-area: 1 / 1;
}

/* DrylPresence keeps the outgoing layer mounted (and interactive) until its ~240ms exit
   animation finishes, so during every filter change the OLD table sits stacked under the
   incoming one with its Bearbeiten/Löschen buttons still live — a stray click during the
   crossfade would hit stale data. DrylPresence itself applies "presence-exit" only while
   that animation is playing (see WrapperCss in DrylPresence.razor); scoping the cutoff to
   that class, not to .presence in general, leaves the entering/settled layer fully
   interactive as before. */
.kb-content-stack[b-6v2i4x41zc]  .presence-exit {
    pointer-events: none;
}

.kb-skeletons[b-6v2i4x41zc] {
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
}

/* .skel lives inside DrylSkeleton's own render tree, a different CSS-isolation
   scope — ::deep is required to reach it and give each placeholder roughly a
   table-row height instead of the component's 14px default line. */
.kb-skeleton-row[b-6v2i4x41zc]  .skel {
    height: 52px;
    border-radius: var(--r-md);
}

/* Kein eigenes .kb-index-busy/.kb-index-label mehr — der Pending-Zustand rendert jetzt
   DrylAiIndicator, das global in dryl.css gestylt ist (Token-Farben, eigene Animation,
   role="status" aria-live="polite"). */

/* .tbl-edit-btn is NOT redefined here — dryl.css already styles it globally
   (tokens, hover, and the accent focus-visible ring per rule 2.9). A local
   override would only fight that, not improve it. */

@media (max-width: 720px) {
    .kb-filters[b-6v2i4x41zc] { grid-template-columns: 1fr; }
}
/* /Features/Admin/KnowledgeEdit.razor.rz.scp.css */
/* Nur Tokens — keine Literale (DRYL-Regel 2.1). dryl.css kennt keine
   Font-size-Tokens (die Größen sind dort selbst Roh-px/rem) — hier wird darum,
   wie in jeder anderen Admin-Seite (ProjectEdit.razor.css, KnowledgeAdmin.razor.css
   u.a.), mit rem gearbeitet statt einen nicht-existierenden --fs-* Token zu erfinden. */
.kbe-header[b-obypf1zj5f] {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--sp-3);
}

.kbe-title[b-obypf1zj5f] {
    font-size: 1.5rem;
    font-weight: 600;
    color: var(--fg);
    margin: 0;
}

.kbe-grid[b-obypf1zj5f] {
    display: grid;
    grid-template-columns: 1fr 320px;
    gap: var(--sp-5);
    align-items: start;
}

.kbe-main[b-obypf1zj5f],
.kbe-side[b-obypf1zj5f] {
    display: flex;
    flex-direction: column;
    gap: var(--sp-3);
}

.kbe-panel[b-obypf1zj5f] {
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    padding: var(--sp-4);
    background: var(--glass-1);
    backdrop-filter: var(--glass-fx-flow);
}

.kbe-subtitle[b-obypf1zj5f] {
    font-size: 1.125rem;
    font-weight: 600;
    color: var(--fg);
    margin: 0 0 var(--sp-3);
}

.kbe-hint[b-obypf1zj5f] {
    font-size: 0.75rem;
    color: var(--fg-dim);
    margin: 0;
}

/* Art-Feld bei Memory/Episode: DrylSelect und der schreibgeschützte Ersatztext (siehe
   IsKindLocked in KnowledgeEdit.razor) überblenden statt umzuschalten (DRYL-Regel 2.12).
   DrylPresence hält das austretende Kind bis zum Animationsende gemountet — ohne diese Grid-
   Zelle stünden Dropdown und Text für die Dauer der Überblendung kurz UNTEREINANDER und die
   Seite sprang in der Höhe (derselbe Effekt, den .kb-content-stack in KnowledgeAdmin.razor.css
   löst). ::deep, weil .presence zu DrylPresence's eigenem CSS-Isolationsbereich gehört.
   .presence-exit verliert zusätzlich pointer-events: der Combobox-Trigger von DrylSelect bliebe
   sonst für die ~240ms der Überblendung noch klickbar/fokussierbar, obwohl er schon auf dem Weg
   nach draußen ist — derselbe Fund wie bei den Bearbeiten/Löschen-Buttons in KnowledgeAdmin. */
.kbe-kind-stack[b-obypf1zj5f] {
    display: grid;
}

.kbe-kind-stack[b-obypf1zj5f]  .presence {
    grid-area: 1 / 1;
}

.kbe-kind-stack[b-obypf1zj5f]  .presence-exit {
    pointer-events: none;
}

.kbe-kind-static[b-obypf1zj5f] {
    display: flex;
    align-items: center;
}

.kbe-links[b-obypf1zj5f],
.kbe-versions[b-obypf1zj5f] {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
}

.kbe-link[b-obypf1zj5f],
.kbe-version[b-obypf1zj5f] {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--sp-2);
    padding: var(--sp-2);
    border: 1px solid var(--line);
    border-radius: var(--r-md);
    color: var(--fg-muted);
    transition: border-color var(--dur-fast) var(--ease-out);
}

.kbe-link:hover[b-obypf1zj5f],
.kbe-version:hover[b-obypf1zj5f] {
    border-color: var(--line-strong);
}

.kbe-link--gone[b-obypf1zj5f] {
    color: var(--fg-dim);
    font-style: italic;
}

/* .kbe-link span (the target label) and .kbe-version-note both hold text of
   unpredictable length (a project title, a free-text change note) — without
   min-width: 0 a long, unbroken value would force the flex row wider than its
   container instead of wrapping, which is exactly the kind of thing that only
   shows up at 375px. */
.kbe-link span[b-obypf1zj5f],
.kbe-version-note[b-obypf1zj5f] {
    min-width: 0;
    overflow-wrap: anywhere;
}

.kbe-version-no[b-obypf1zj5f] {
    color: var(--fg);
    font-variant-numeric: tabular-nums;
}

.kbe-version-meta[b-obypf1zj5f],
.kbe-version-note[b-obypf1zj5f] {
    font-size: 0.75rem;
    color: var(--fg-dim);
}

.kbe-version-note[b-obypf1zj5f] {
    margin-inline-start: auto;
}

@media (max-width: 900px) {
    .kbe-grid[b-obypf1zj5f] { grid-template-columns: 1fr; }
}
/* /Features/Admin/Login.razor.rz.scp.css */
/* Login page — scoped styles, token-driven only.
   No literal colors, no hardcoded radii or spacing values. */

/* ── Shell ─────────────────────────────────────────────────────────────── */

.login-shell[b-jhwz6qjwu6] {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
    padding: var(--sp-4);
    background: var(--bg);
}

/* ── Card ───────────────────────────────────────────────────────────────── */

.login-card[b-jhwz6qjwu6] {
    width: 100%;
    max-width: 400px;
    background: var(--glass-1);
    backdrop-filter: blur(var(--glass-blur));
    -webkit-backdrop-filter: blur(var(--glass-blur));
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    padding: var(--sp-7) var(--sp-6);
    display: flex;
    flex-direction: column;
    gap: var(--sp-5);
}

/* ── Header ─────────────────────────────────────────────────────────────── */

.login-header[b-jhwz6qjwu6] {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
}

.login-title[b-jhwz6qjwu6] {
    font-size: 1.25rem;
    font-weight: 600;
    color: var(--fg);
    margin: 0;
}

/* ── Form ───────────────────────────────────────────────────────────────── */

.login-form[b-jhwz6qjwu6] {
    display: flex;
    flex-direction: column;
    gap: var(--sp-4);
}

/* ── Field ──────────────────────────────────────────────────────────────── */

.login-field[b-jhwz6qjwu6] {
    display: flex;
    flex-direction: column;
    gap: var(--sp-1);
}

.login-label[b-jhwz6qjwu6] {
    font-size: 0.875rem;
    color: var(--fg-muted);
    font-weight: 500;
}

.login-input[b-jhwz6qjwu6] {
    background: var(--glass-2);
    border: 1px solid var(--line);
    border-radius: var(--r-sm);
    padding: var(--sp-2) var(--sp-3);
    color: var(--fg);
    font-size: 0.9375rem;
    width: 100%;
    box-sizing: border-box;
    transition: border-color var(--dur-fast) var(--ease-out),
                box-shadow var(--dur-fast) var(--ease-out);
}

.login-input:focus-visible[b-jhwz6qjwu6] {
    outline: none;
    border-color: var(--accent-line);
    box-shadow: 0 0 0 2px var(--accent-soft);
}

/* ── Submit button ──────────────────────────────────────────────────────── */

.login-submit[b-jhwz6qjwu6] {
    width: 100%;
    margin-top: var(--sp-1);
}
/* /Features/Admin/ProjectEdit.razor.rz.scp.css */
/* The page column layout now lives inline on the DrylReveal wrapper that
   staggers the header + edit layout in; Blazor scoped CSS can't reach a child
   component's root element, so a `.project-edit` rule would never bind. */

.project-edit-header[b-ctv1x0evfx] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-4);
}

.project-edit-title[b-ctv1x0evfx] {
    margin: 0;
    font-size: 1.5rem;
    font-weight: 600;
    color: var(--fg);
}

.project-edit-form[b-ctv1x0evfx] {
    display: flex;
    flex-direction: column;
    gap: var(--sp-4);
    max-width: 900px;
}

.project-edit-card[b-ctv1x0evfx] {
    display: flex;
    flex-direction: column;
    gap: var(--sp-4);
}

.section-heading[b-ctv1x0evfx] {
    margin: 0 0 var(--sp-1);
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--fg-muted);
    text-transform: uppercase;
    letter-spacing: 0.06em;
}

.field-grid[b-ctv1x0evfx] {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--sp-4);
}

.toggles-group[b-ctv1x0evfx] {
    display: flex;
    flex-direction: column;
    gap: var(--sp-3);
}

.project-edit-actions[b-ctv1x0evfx] {
    display: flex;
    justify-content: flex-end;
    gap: var(--sp-3);
}
/* /Features/Admin/ProjectsAdmin.razor.rz.scp.css */
/* The page column layout now lives inline on the DrylReveal wrapper that
   staggers the header + table in; Blazor scoped CSS can't reach a child
   component's root element, so a `.projects-admin` rule would never bind. */

.projects-header[b-s5qjnd74vp] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-4);
}

.projects-title[b-s5qjnd74vp] {
    margin: 0;
    font-size: 1.5rem;
    font-weight: 600;
    color: var(--fg);
}

.tbl-edit-btn[b-s5qjnd74vp] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: var(--sp-1) var(--sp-2);
    border-radius: var(--r-sm);
    border: 1px solid transparent;
    color: var(--fg-muted);
    background: transparent;
    transition: color var(--dur-fast) var(--ease-out),
                border-color var(--dur-fast) var(--ease-out),
                background var(--dur-fast) var(--ease-out);
    cursor: pointer;
    text-decoration: none;
}

.tbl-edit-btn:hover[b-s5qjnd74vp],
.tbl-edit-btn:focus-visible[b-s5qjnd74vp] {
    color: var(--fg);
    border-color: var(--line-strong);
    background: var(--glass-2);
}
/* /Features/Admin/SkillsAdmin.razor.rz.scp.css */
/* The page column layout now lives inline on the DrylReveal wrapper that
   staggers the page in; Blazor scoped CSS can't reach a child component's
   root element, so a `.skills-admin` rule would never bind. */

.skills-header[b-7k7vrmiton] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-4);
}

.skills-title[b-7k7vrmiton] {
    margin: 0;
    font-size: 1.5rem;
    font-weight: 600;
    color: var(--fg);
}

.skills-form-card[b-7k7vrmiton] {
    display: flex;
    flex-direction: column;
    gap: var(--sp-4);
}

.skills-form[b-7k7vrmiton] {
    display: flex;
    flex-direction: column;
    gap: var(--sp-4);
}

.section-heading[b-7k7vrmiton] {
    margin: 0 0 var(--sp-1);
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--fg-muted);
    text-transform: uppercase;
    letter-spacing: 0.06em;
}

.field-grid[b-7k7vrmiton] {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--sp-4);
}

.form-actions[b-7k7vrmiton] {
    display: flex;
    justify-content: flex-end;
    gap: var(--sp-3);
}
/* /Features/Admin/SocialAdmin.razor.rz.scp.css */
/* The page column layout now lives inline on the DrylReveal wrapper that
   staggers the page in; Blazor scoped CSS can't reach a child component's
   root element, so a `.social-admin` rule would never bind. */

.social-header[b-mtdea7bpqn] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-4);
}

.social-title[b-mtdea7bpqn] {
    margin: 0;
    font-size: 1.5rem;
    font-weight: 600;
    color: var(--fg);
}

.social-form-card[b-mtdea7bpqn] {
    display: flex;
    flex-direction: column;
    gap: var(--sp-4);
}

.social-form[b-mtdea7bpqn] {
    display: flex;
    flex-direction: column;
    gap: var(--sp-4);
}

.section-heading[b-mtdea7bpqn] {
    margin: 0 0 var(--sp-1);
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--fg-muted);
    text-transform: uppercase;
    letter-spacing: 0.06em;
}

.field-grid[b-mtdea7bpqn] {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--sp-4);
}

.toggle-field[b-mtdea7bpqn] {
    display: flex;
    align-items: center;
    padding-top: var(--sp-5);
}

.form-actions[b-mtdea7bpqn] {
    display: flex;
    justify-content: flex-end;
    gap: var(--sp-3);
}
/* /Features/Contact/ContactPage.razor.rz.scp.css */
/* ── Hero ──────────────────────────────────────────────── */
.contact-hero[b-md21jotrj1] {
    max-width: 720px;
    margin: 0 auto;
    padding: calc(var(--sp-8) + var(--sp-4)) var(--sp-4) var(--sp-6);
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
    text-align: center;
    align-items: center;
}

.contact-eyebrow[b-md21jotrj1] {
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    margin: 0;
    background: var(--accent-grad);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}

.contact-headline[b-md21jotrj1] {
    font-size: clamp(2.5rem, 6vw, 4rem);
    font-weight: 700;
    line-height: 1.05;
    letter-spacing: -0.035em;
    margin: 0;
    background: linear-gradient(110deg,
        var(--accent-a), var(--accent-b), var(--accent-a));
    background-size: 200% auto;
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    animation: contact-shimmer-b-md21jotrj1 8s linear infinite;
}

@keyframes contact-shimmer-b-md21jotrj1 {
    to { background-position: 200% center; }
}

@media (prefers-reduced-motion: reduce) {
    .contact-headline[b-md21jotrj1] { animation: none; }
}

.contact-subtitle[b-md21jotrj1] {
    font-size: clamp(1.0625rem, 2vw, 1.25rem);
    color: var(--fg-muted);
    margin: 0;
    max-width: 520px;
}

/* ── Form section ──────────────────────────────────────── */
.contact-form-section[b-md21jotrj1] {
    padding: 0 var(--sp-4) var(--sp-8);
    max-width: 640px;
    margin: 0 auto;
}

.contact-card[b-md21jotrj1] {
    padding: var(--sp-6);
}

.contact-form-inner[b-md21jotrj1] {
    display: flex;
    flex-direction: column;
    gap: var(--sp-4);
}

/* ── Fields ────────────────────────────────────────────── */
.contact-fields[b-md21jotrj1] {
    display: flex;
    flex-direction: column;
    gap: var(--sp-3);
}

/* ── Submit row ────────────────────────────────────────── */
.contact-actions[b-md21jotrj1] {
    display: flex;
    justify-content: flex-end;
    padding-top: var(--sp-2);
}

/* ── Honeypot — off-screen, invisible to humans ────────── */
.hp-field[b-md21jotrj1] {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}
/* /Features/Portfolio/About.razor.rz.scp.css */
/* ── Hero ──────────────────────────────────────────────── */
.about-hero[b-rpqz4axb9n] {
    max-width: 760px;
    margin: 0 auto;
    padding: calc(var(--sp-8) + var(--sp-4)) var(--sp-4) var(--sp-5);
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
}

.about-eyebrow[b-rpqz4axb9n] {
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    margin: 0;
    background: var(--accent-grad);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}

.about-headline[b-rpqz4axb9n] {
    font-size: clamp(2.5rem, 6vw, 4rem);
    font-weight: 700;
    line-height: 1.05;
    letter-spacing: -0.035em;
    margin: 0;
    background: linear-gradient(110deg,
        var(--accent-a), var(--accent-b), var(--accent-a));
    background-size: 200% auto;
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    animation: about-shimmer-b-rpqz4axb9n 8s linear infinite;
}

@keyframes about-shimmer-b-rpqz4axb9n {
    to { background-position: 200% center; }
}

@media (prefers-reduced-motion: reduce) {
    .about-headline[b-rpqz4axb9n] { animation: none; }
}

/* ── Body ──────────────────────────────────────────────── */
.about-body[b-rpqz4axb9n] {
    padding: 0 var(--sp-4) var(--sp-8);
}

.about-body-inner[b-rpqz4axb9n] {
    max-width: 760px;
    margin: 0 auto;
    font-size: 1.0625rem;
    line-height: 1.75;
    color: var(--fg-muted);
}
/* /Features/Portfolio/Home.razor.rz.scp.css */
/*  Startseite — scoped styles, ausschließlich dryl.css-Tokens.

    Der Aufbau hat zwei Ebenen:

    1. RUHEZUSTAND (dieser Block). Ein gewöhnlicher, vollständig lesbarer
       Stapel. Kein `opacity: 0`, kein `height` aus `--vh`, kein Sticky.
       Das ist der Zustand ohne JavaScript, bei einem JS-Fehler, im
       Prerender-Moment und unter `prefers-reduced-motion: reduce`.

    2. BÜHNE (`.home.is-animated …`). Die Klasse setzt home.js erst, wenn
       GSAP nachweislich geladen und Reduced Motion aus ist. Erst dann
       bekommen die Akte ihre Scroll-Strecke aus `--vh`, die Bühne klebt,
       und erst dann existieren Startzustände, die etwas verstecken.

    Gepinnt wird mit `position: sticky` — nicht mit GSAPs eigenem Pinning,
    das `position: fixed` verwendet und an jedem transformierten Vorfahren
    zerbricht. Sticky funktioniert hier nur, weil `wwwroot/app.css` den
    `overflow-x: hidden`-Zweitschlag auf `body` zurücknimmt; dieser Override
    ist Voraussetzung dieser Seite. */

.home[b-8b9ugeg9vn] {
    --stage-h: calc(100vh - var(--appbar-h));
    position: relative;
}

/* ── Kapitelleiste ───────────────────────────────────────────────────── */

.rail[b-8b9ugeg9vn] {
    position: fixed;
    top: 50%;
    right: var(--sp-5);
    z-index: var(--z-sticky);
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: var(--sp-3);
    transform: translateY(-50%);
}

/*  Die Punkte müssen exakt untereinander stehen. Läge das Label im Fluss,
    schöbe seine (je Kapitel andere) Breite den Punkt hin und her — die Leiste
    zappelte. Das Label hängt deshalb links außerhalb. */
.rail-link[b-8b9ugeg9vn] {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 10px;
    height: 10px;
    text-decoration: none;
    color: var(--fg-dim);
    transition: color var(--dur-fast) var(--ease-out);
}

.rail-dot[b-8b9ugeg9vn] {
    width: 6px;
    height: 6px;
    flex: none;
    border-radius: var(--r-pill);
    background: var(--fg-faint);
    transition: background var(--dur-med) var(--ease-out),
                transform var(--dur-med) var(--ease-spring),
                box-shadow var(--dur-med) var(--ease-out);
}

.rail-label[b-8b9ugeg9vn] {
    position: absolute;
    right: calc(100% + var(--sp-3));
    white-space: nowrap;
    font-family: var(--font-mono);
    font-size: 0.6875rem;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    opacity: 0;
    transform: translateX(calc(var(--sp-2) * -1));
    transition: opacity var(--dur-med) var(--ease-out),
                transform var(--dur-med) var(--ease-out);
}

.rail-link:hover .rail-label[b-8b9ugeg9vn],
.rail-link:focus-visible .rail-label[b-8b9ugeg9vn],
.rail-link.is-current .rail-label[b-8b9ugeg9vn] {
    opacity: 1;
    transform: none;
}

.rail-link:hover[b-8b9ugeg9vn],
.rail-link:focus-visible[b-8b9ugeg9vn],
.rail-link.is-current[b-8b9ugeg9vn] {
    color: var(--fg);
}

.rail-link.is-current .rail-dot[b-8b9ugeg9vn],
.rail-link:hover .rail-dot[b-8b9ugeg9vn] {
    background: var(--accent-grad);
    transform: scale(1.6);
    box-shadow: 0 0 12px color-mix(in srgb, var(--accent-a) 55%, transparent);
}

@media (max-width: 900px) {
    .rail[b-8b9ugeg9vn] { display: none; }
}

/* ── Akt-Grundform ───────────────────────────────────────────────────── */

.act[b-8b9ugeg9vn] {
    position: relative;
}

.stage[b-8b9ugeg9vn] {
    width: 100%;
    max-width: 1240px;
    margin-inline: auto;
    padding: var(--sp-8) var(--sp-6);
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: var(--sp-6);
}

/* Mono-Vorspann — die kleine Meta-Zeile über jeder Überschrift. */
.eyebrow[b-8b9ugeg9vn] {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    margin: 0 0 var(--sp-3);
    font-family: var(--font-mono);
    font-size: 0.6875rem;
    font-weight: 500;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--fg-dim);
    width: fit-content;
}

.eyebrow[b-8b9ugeg9vn]::before {
    content: "";
    width: var(--sp-6);
    height: 1px;
    background: var(--accent-grad);
}

.act-heading[b-8b9ugeg9vn] {
    margin: 0;
    font-size: clamp(2rem, 5.5vw, 4rem);
    font-weight: 700;
    letter-spacing: -0.04em;
    line-height: 1.02;
    color: var(--fg);
}

.act-head[b-8b9ugeg9vn] {
    flex: none;
}

/* ── 1 Auftakt ───────────────────────────────────────────────────────── */

.act-hero .stage[b-8b9ugeg9vn] {
    justify-content: space-between;
    gap: var(--sp-5);
}

.hero[b-8b9ugeg9vn] {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--sp-4);
    margin-block: auto;
}

.hero-line[b-8b9ugeg9vn] {
    margin: 0;
}

.hero-claim[b-8b9ugeg9vn] {
    margin: 0;
    max-width: 44ch;
    font-family: var(--font-mono);
    font-size: 0.75rem;
    letter-spacing: 0.1em;
    line-height: 1.7;
    text-transform: uppercase;
    color: var(--fg-dim);
}

/*  Der Namenszug. Groß gesetzt, ohne Hintergrundobjekt — er ist die
    Eröffnung, und beim Scrollen weicht er in die Tiefe.

    Die Größe kommt als `--name-size` aus dem Markup, weil sie von der Länge
    des im Backoffice gepflegten Textes abhängt: „Jan Zimprich" verträgt
    9 rem, ein ganzer Positionierungssatz nicht — der spränge sonst aus der
    Bühne heraus. Der Wert hier ist nur der Rückfall. */
.hero-name[b-8b9ugeg9vn] {
    margin: 0;
    font-size: var(--name-size, clamp(2.5rem, 8vw, 6rem));
    font-weight: 700;
    letter-spacing: -0.055em;
    line-height: 0.9;
    text-wrap: balance;
    color: var(--fg);
}

.hero-words[b-8b9ugeg9vn] {
    margin: 0;
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--sp-3);
    font-size: clamp(1.25rem, 3.4vw, 2.5rem);
    font-weight: 600;
    letter-spacing: -0.03em;
    line-height: 1.1;
}

.hero-word[b-8b9ugeg9vn] {
    background: var(--accent-grad);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}

/* Im Ruhezustand stehen alle Wörter nebeneinander, getrennt durch einen
   Punkt. Erst die Bühne stapelt sie und lässt sie wechseln. */
.hero-word + .hero-word[b-8b9ugeg9vn]::before {
    content: "·";
    margin-right: var(--sp-3);
    color: var(--fg-faint);
    -webkit-text-fill-color: var(--fg-faint);
}

.hero-subtitle[b-8b9ugeg9vn] {
    margin: 0;
    max-width: 40ch;
    font-size: clamp(1rem, 1.7vw, 1.375rem);
    line-height: 1.45;
    color: var(--fg-muted);
}

.hero-actions[b-8b9ugeg9vn] {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-3);
    margin-top: var(--sp-3);
}

.hero-cue[b-8b9ugeg9vn] {
    display: none;
    flex-direction: column;
    align-items: center;
    gap: var(--sp-2);
    align-self: center;
    flex: none;
    color: var(--fg-dim);
    text-decoration: none;
    transition: color var(--dur-fast) var(--ease-out);
}

.hero-cue:hover[b-8b9ugeg9vn],
.hero-cue:focus-visible[b-8b9ugeg9vn] {
    color: var(--fg);
}

.hero-cue-line[b-8b9ugeg9vn] {
    width: 1px;
    height: var(--sp-7);
    background: linear-gradient(to bottom, transparent, var(--line-strong));
}

/* ── 2 Projekt-Strecke — das Herzstück ───────────────────────────────── */

.run[b-8b9ugeg9vn] {
    display: flex;
    flex-direction: column;
    gap: var(--sp-8);
}

.pj[b-8b9ugeg9vn] {
    display: grid;
    grid-template-rows: auto minmax(0, 1fr) auto;
    gap: var(--sp-4);
    min-width: 0;
}

/*  Im Projekt-Akt tritt die Kapitelüberschrift zurück: die Bühne gehört dem
    Projekttitel, nicht dem Wort „Projekte". */
.act-projects .act-head[b-8b9ugeg9vn] {
    display: flex;
    align-items: baseline;
    gap: var(--sp-4);
}

.act-projects .eyebrow[b-8b9ugeg9vn] {
    margin: 0;
}

.act-projects .act-heading[b-8b9ugeg9vn] {
    font-size: clamp(1.125rem, 1.8vw, 1.5rem);
    letter-spacing: -0.02em;
    color: var(--fg-muted);
}

.pj-head[b-8b9ugeg9vn] {
    display: flex;
    align-items: baseline;
    gap: var(--sp-4);
    min-width: 0;
}

.pj-index[b-8b9ugeg9vn] {
    flex: none;
    font-family: var(--font-mono);
    font-size: 0.8125rem;
    font-weight: 600;
    letter-spacing: 0.1em;
    background: var(--accent-grad);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}

.pj-index-total[b-8b9ugeg9vn] {
    color: var(--fg-faint);
    -webkit-text-fill-color: var(--fg-faint);
}

.pj-title[b-8b9ugeg9vn] {
    margin: 0;
    min-width: 0;
    font-size: clamp(1.875rem, 5vw, 3.75rem);
    font-weight: 700;
    letter-spacing: -0.04em;
    line-height: 1;
    color: var(--fg);
}

.pj-frame[b-8b9ugeg9vn] {
    position: relative;
    overflow: hidden;
    min-height: 240px;
    border-radius: var(--r-xl);
    border: 1px solid var(--line-strong);
    background: var(--glass-1);
    box-shadow: var(--shadow-lg);
}

/* Akzent nur als Kante und als leichter Bodennebel — nie als Füllung. */
.pj-frame[b-8b9ugeg9vn]::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    pointer-events: none;
    background: linear-gradient(to bottom,
        color-mix(in srgb, var(--accent-a) 12%, transparent) 0%,
        transparent 30%,
        color-mix(in srgb, var(--ground) 50%, transparent) 100%);
}

.pj-image[b-8b9ugeg9vn] {
    display: block;
    width: 100%;
    height: 100%;
    min-height: 240px;
    object-fit: cover;
    object-position: top center;
}

/* Typografischer Ersatz — nur sichtbar, wenn kein Bild da ist oder das Bild
   nicht geladen werden konnte (home.js setzt dann .pj-frame--type nach).
   Er ist der Ersatz, nicht der Normalfall. */
.pj-type[b-8b9ugeg9vn] {
    display: none;
}

.pj-frame--type[b-8b9ugeg9vn] {
    display: grid;
    place-items: center;
    background:
        radial-gradient(120% 130% at 10% -10%,
            color-mix(in srgb, var(--accent-a) 26%, transparent) 0%, transparent 58%),
        radial-gradient(120% 130% at 92% 110%,
            color-mix(in srgb, var(--accent-b) 20%, transparent) 0%, transparent 58%),
        var(--glass-2);
}

.pj-frame--type .pj-image[b-8b9ugeg9vn] {
    display: none;
}

/*  Trägt der Rahmen den Titel, darf er nicht ein zweites Mal darüber stehen.
    Er bleibt für Screenreader erhalten — er ist die Überschrift, auf die
    `aria-labelledby` des Artikels zeigt. */
.pj:has(.pj-frame--type) .pj-title[b-8b9ugeg9vn] {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

.pj-frame--type .pj-type[b-8b9ugeg9vn] {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--sp-5);
    padding: var(--sp-7) var(--sp-5);
    text-align: center;
}

.pj-type-title[b-8b9ugeg9vn] {
    font-size: clamp(2rem, 7vw, 5.5rem);
    font-weight: 700;
    letter-spacing: -0.05em;
    line-height: 0.92;
    color: var(--fg);
}

.pj-type-tags[b-8b9ugeg9vn] {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--sp-2) var(--sp-4);
}

.pj-type-tag[b-8b9ugeg9vn] {
    font-family: var(--font-mono);
    font-size: 0.6875rem;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--fg-dim);
}

.pj-foot[b-8b9ugeg9vn] {
    display: flex;
    flex-direction: column;
    gap: var(--sp-3);
}

.pj-summary[b-8b9ugeg9vn] {
    margin: 0;
    max-width: 68ch;
    font-size: 0.9375rem;
    line-height: 1.6;
    color: var(--fg-muted);
}

.pj-meta[b-8b9ugeg9vn] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sp-3);
}

.pj-tags[b-8b9ugeg9vn] {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-2);
}

.run-foot[b-8b9ugeg9vn] {
    flex: none;
    display: flex;
    align-items: center;
    gap: var(--sp-5);
}

.run-progress[b-8b9ugeg9vn] {
    flex: 1 1 auto;
    height: 2px;
    border-radius: var(--r-pill);
    background: var(--line);
    overflow: hidden;
}

.run-progress-fill[b-8b9ugeg9vn] {
    display: block;
    width: 100%;
    height: 100%;
    border-radius: inherit;
    background: var(--accent-grad);
    transform-origin: left center;
}

/* ── 3 Zahlen ────────────────────────────────────────────────────────── */

.stats[b-8b9ugeg9vn] {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
    gap: var(--sp-5);
}

.stat[b-8b9ugeg9vn] {
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
    padding: var(--sp-5) 0 var(--sp-5) var(--sp-5);
    border-left: 1px solid var(--line-strong);
}

.stat-value[b-8b9ugeg9vn] {
    font-size: clamp(2.75rem, 8vw, 5.5rem);
    font-weight: 700;
    letter-spacing: -0.055em;
    line-height: 1;
    font-variant-numeric: tabular-nums;
    background: var(--accent-grad);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}

.stat-label[b-8b9ugeg9vn] {
    font-family: var(--font-mono);
    font-size: 0.6875rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--fg-dim);
}

/* ── 4 Skills ────────────────────────────────────────────────────────── */

.skills[b-8b9ugeg9vn] {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: var(--sp-6);
    min-height: 0;
}

/* Sechs Kategorien lesen sich als zwei Reihen zu dritt ruhiger als
   vier plus zwei. */
@media (min-width: 900px) {
    .skills[b-8b9ugeg9vn] {
        grid-template-columns: repeat(3, 1fr);
        column-gap: var(--sp-7);
    }
}

.skill-group[b-8b9ugeg9vn] {
    display: flex;
    flex-direction: column;
    gap: var(--sp-4);
    min-width: 0;
}

.skill-category[b-8b9ugeg9vn] {
    margin: 0;
    padding-bottom: var(--sp-2);
    border-bottom: 1px solid var(--line);
    font-family: var(--font-mono);
    font-size: 0.6875rem;
    font-weight: 500;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--fg-dim);
}

.skill-list[b-8b9ugeg9vn] {
    display: flex;
    flex-direction: column;
    gap: var(--sp-3);
    margin: 0;
    padding: 0;
    list-style: none;
}

.skill[b-8b9ugeg9vn] {
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
}

.skill-name[b-8b9ugeg9vn] {
    font-size: 0.875rem;
    color: var(--fg);
}

.skill-bar[b-8b9ugeg9vn] {
    display: block;
    height: 3px;
    border-radius: var(--r-pill);
    background: var(--line);
    overflow: hidden;
}

/* Der Balken skaliert — kein animiertes `width`, damit er auf dem
   Compositor läuft. `--lvl` ist der Ruhewert aus dem Markup. */
.skill-bar-fill[b-8b9ugeg9vn] {
    display: block;
    width: 100%;
    height: 100%;
    border-radius: inherit;
    background: var(--accent-grad);
    transform: scaleX(var(--lvl, 1));
    transform-origin: left center;
}

/* ── 5 Über mich ─────────────────────────────────────────────────────── */

.about[b-8b9ugeg9vn] {
    display: grid;
    grid-template-columns: minmax(200px, 320px) minmax(0, 1fr);
    gap: var(--sp-7);
    align-items: start;
}

.about-portrait[b-8b9ugeg9vn] {
    position: relative;
    border-radius: var(--r-xl);
    overflow: hidden;
    border: 1px solid var(--line-strong);
    box-shadow: var(--shadow-lg);
}

.about-portrait[b-8b9ugeg9vn]::after {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: linear-gradient(to top,
        color-mix(in srgb, var(--ground) 60%, transparent) 0%, transparent 45%);
}

.about-photo[b-8b9ugeg9vn] {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: 4 / 5;
    object-fit: cover;
}

.about-viewport[b-8b9ugeg9vn] {
    min-width: 0;
}

.about-column[b-8b9ugeg9vn] {
    display: flex;
    flex-direction: column;
    gap: var(--sp-3);
}

.about-body[b-8b9ugeg9vn] {
    font-size: 1.0625rem;
    line-height: 1.75;
    color: var(--fg-muted);
    max-width: 60ch;
}

/* DrylMarkdown-Ausgabe ist Kindkomponenten-Markup — der Seiten-Scope
   erreicht sie nur über ::deep. */
.about-body[b-8b9ugeg9vn]  h1,
.about-body[b-8b9ugeg9vn]  h2,
.about-body[b-8b9ugeg9vn]  h3 {
    color: var(--fg);
    letter-spacing: -0.025em;
}

.about-body[b-8b9ugeg9vn]  p {
    margin: 0 0 var(--sp-4);
}

.about-body[b-8b9ugeg9vn]  a {
    color: var(--fg);
    text-decoration: underline;
    text-underline-offset: 2px;
}

/* ── 6 GitHub ────────────────────────────────────────────────────────── */

.repos[b-8b9ugeg9vn] {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
    gap: var(--sp-4);
}

.repo[b-8b9ugeg9vn] {
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
    padding: var(--sp-4);
    border-radius: var(--r-lg);
    border: 1px solid var(--line);
    background: var(--glass-1);
    text-decoration: none;
    color: var(--fg);
    transition: border-color var(--dur-med) var(--ease-out),
                transform var(--dur-med) var(--ease-spring),
                box-shadow var(--dur-med) var(--ease-out);
}

.repo:hover[b-8b9ugeg9vn],
.repo:focus-visible[b-8b9ugeg9vn] {
    border-color: var(--accent-line);
    transform: translateY(-3px);
    box-shadow: var(--glow-soft);
}

.repo-name[b-8b9ugeg9vn] {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    font-size: 0.9375rem;
    font-weight: 600;
    letter-spacing: -0.01em;
}

.repo-desc[b-8b9ugeg9vn] {
    font-size: 0.8125rem;
    line-height: 1.55;
    color: var(--fg-muted);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.repo-meta[b-8b9ugeg9vn] {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    margin-top: auto;
    padding-top: var(--sp-2);
    font-family: var(--font-mono);
    font-size: 0.6875rem;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--fg-dim);
}

.repo-stars[b-8b9ugeg9vn] {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-1);
}

/* ── 7 Abschluss ─────────────────────────────────────────────────────── */

.finale[b-8b9ugeg9vn] {
    display: flex;
    justify-content: center;
}

.finale[b-8b9ugeg9vn]  .finale-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--sp-4);
    max-width: 660px;
    width: 100%;
    padding: var(--sp-8) var(--sp-6);
    text-align: center;
}

.finale-heading[b-8b9ugeg9vn] {
    margin: 0;
    font-size: clamp(1.875rem, 4.5vw, 3rem);
    font-weight: 700;
    letter-spacing: -0.035em;
    line-height: 1.05;
    color: var(--fg);
}

.finale-body[b-8b9ugeg9vn] {
    margin: 0;
    max-width: 46ch;
    color: var(--fg-muted);
    line-height: 1.6;
}

/* =====================================================================
   BÜHNE — alles ab hier gilt nur, wenn home.js die Animation aktiviert
   hat. Ohne diese Klasse bleibt oben ein lesbarer Stapel stehen.
   ===================================================================== */

.home.is-animated .act[b-8b9ugeg9vn] {
    height: calc(var(--vh, 100) * 1vh);
}

.home.is-animated .stage[b-8b9ugeg9vn] {
    position: sticky;
    top: var(--appbar-h);
    height: var(--stage-h);
    padding-block: var(--sp-6);
    overflow: hidden;
}

.home.is-animated .hero-cue[b-8b9ugeg9vn] {
    display: flex;
}

/* Startzustände. Bewusst nur hier — sie verstecken Inhalt, und das darf
   ausschließlich passieren, wenn der Motor sie auch wieder aufdeckt. */

.home.is-animated [data-hero-part][b-8b9ugeg9vn],
.home.is-animated .act-projects .act-head[b-8b9ugeg9vn],
.home.is-animated .act-projects .run-foot[b-8b9ugeg9vn],
.home.is-animated .act-stats .stat[b-8b9ugeg9vn],
.home.is-animated .act-skills .skill-group[b-8b9ugeg9vn],
.home.is-animated .act-github .repo[b-8b9ugeg9vn],
.home.is-animated .act-about .about-portrait[b-8b9ugeg9vn],
.home.is-animated .finale[b-8b9ugeg9vn] {
    opacity: 0;
}

/* Die Wörter wechseln, statt nebeneinanderzustehen. */
.home.is-animated .hero-words[b-8b9ugeg9vn] {
    display: grid;
    justify-items: start;
}

.home.is-animated .hero-word[b-8b9ugeg9vn] {
    grid-area: 1 / 1;
}

.home.is-animated .hero-word + .hero-word[b-8b9ugeg9vn]::before {
    content: none;
}

/* Die Strecke: jedes Projekt füllt die Bühne, gestapelt in der Tiefe. */
.home.is-animated .run[b-8b9ugeg9vn] {
    position: relative;
    flex: 1 1 auto;
    min-height: 0;
    gap: 0;
    perspective: 1500px;
    perspective-origin: 50% 45%;
    /* Das abtretende Projekt wächst über die Bühne hinaus; hier endet es,
       statt in die Kapitelüberschrift zu laufen. */
    overflow: hidden;
}

.home.is-animated .pj[b-8b9ugeg9vn] {
    position: absolute;
    inset: 0;
    transform-style: preserve-3d;
    will-change: transform, opacity;
    backface-visibility: hidden;
}

.home.is-animated .pj-frame[b-8b9ugeg9vn] {
    min-height: 0;
    height: 100%;
}

/*  Steht die WebGL-Ebene, trägt sie die Bilder. Der DOM-Rahmen behält seinen
    Platz — die Ebene misst sich an ihm — und gibt nur seine Fläche frei.
    Die Klasse setzt home.js erst, wenn die Ebene nachweislich steht. */
.home.is-animated .run.is-gl .pj-frame > *[b-8b9ugeg9vn] {
    visibility: hidden;
}

.home.is-animated .run.is-gl .pj-frame[b-8b9ugeg9vn] {
    background: none;
    box-shadow: none;
}

.home.is-animated .run.is-gl .pj-frame[b-8b9ugeg9vn]::after {
    content: none;
}

/*  Das <canvas> selbst wird in wwwroot/app.css gestylt, nicht hier: es wird
    von home-gl.js erzeugt und trägt deshalb kein `b-…`-Scope-Attribut, ohne
    das keine Regel aus dieser Datei auf es zutrifft. */

.home.is-animated .pj-image[b-8b9ugeg9vn] {
    min-height: 0;
}

.home.is-animated .pj-summary[b-8b9ugeg9vn] {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.home.is-animated .run-progress-fill[b-8b9ugeg9vn] {
    transform: scaleX(0);
}

/*  Portrait steht, der Text zieht daran vorbei.

    Hier stand einmal `height: 100%`. Das war falsch: `.about` IST die Bühne,
    und ihre Höhe steht bereits auf `--stage-h`. Prozentwerte lösen gegen den
    umgebenden Akt auf — die Bühne wurde damit so hoch wie die gesamte
    Scroll-Strecke, und die Textspalte lag außerhalb des Sichtfensters. */
.home.is-animated .about[b-8b9ugeg9vn] {
    align-items: center;
}

.home.is-animated .about-viewport[b-8b9ugeg9vn] {
    position: relative;
    height: 100%;
    overflow: hidden;
    /* weiche Kanten, damit der Text nicht abgeschnitten wirkt */
    mask-image: linear-gradient(to bottom, transparent 0%, #000 7%, #000 93%, transparent 100%);
    -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 7%, #000 93%, transparent 100%);
}

/* Der Innenabstand hält die erste Zeile aus der weichen Maskenkante heraus —
   sonst startet das Kapitel mit einem halb ausgeblendeten Vorspann. */
.home.is-animated .about-column[b-8b9ugeg9vn] {
    position: absolute;
    inset-inline: 0;
    top: 0;
    padding-block: var(--sp-8);
    will-change: transform;
}

/* ── Mobil: die Show bleibt, entschärft ──────────────────────────────
   Die Höhe der Bühne selbst wird NIE skaliert — schrumpfbar ist nur die
   Strecke darüber hinaus, und die rechnet home.js aus. Hier steht nur,
   was an Layout weichen muss. */

@media (max-width: 720px) {
    /*  Die Bühne verbraucht die Viewport-Höhe vollständig; schrumpfbar ist
        ausschließlich die Strecke DARÜBER HINAUS. Würde man die Gesamthöhe
        skalieren, ginge die Scroll-Strecke gegen null und der Fortschritt
        spränge über einen Pixel von 0 auf 1. Deshalb bleiben die ersten
        100 vh unangetastet und nur der Rest wird auf 55 % gekürzt. */
    .home.is-animated .act[b-8b9ugeg9vn] {
        height: calc((100 + (var(--vh, 100) - 100) * 0.55) * 1vh);
    }

    .stage[b-8b9ugeg9vn] {
        padding: var(--sp-7) var(--sp-4);
        gap: var(--sp-5);
    }

    .about[b-8b9ugeg9vn] {
        grid-template-columns: 1fr;
        gap: var(--sp-5);
    }

    .about-portrait[b-8b9ugeg9vn] {
        max-width: 200px;
    }

    .home.is-animated .about[b-8b9ugeg9vn] {
        grid-template-rows: auto minmax(0, 1fr);
        align-items: stretch;
    }

    .pj-head[b-8b9ugeg9vn] {
        flex-direction: column;
        align-items: flex-start;
        gap: var(--sp-1);
    }

    .home.is-animated .pj-tags[b-8b9ugeg9vn],
    .home.is-animated .run-foot .btn[b-8b9ugeg9vn] {
        display: none;
    }

    .home.is-animated .run[b-8b9ugeg9vn] {
        perspective: 900px;
    }

    .stat[b-8b9ugeg9vn] {
        padding: var(--sp-4) 0 var(--sp-4) var(--sp-4);
    }
}

/* Reduced Motion setzt .is-animated gar nicht erst — der Ruhezustand oben
   ist bereits die vollständige Seite. Diese Regel ist die zweite Sperre,
   falls die Einstellung erst nach dem Booten umgelegt wird. */
@media (prefers-reduced-motion: reduce) {
    .home.is-animated .act[b-8b9ugeg9vn] {
        height: auto;
    }

    .home.is-animated .stage[b-8b9ugeg9vn] {
        position: static;
        height: auto;
        overflow: visible;
    }

    .home.is-animated [data-hero-part][b-8b9ugeg9vn],
    .home.is-animated .act-projects .act-head[b-8b9ugeg9vn],
    .home.is-animated .act-projects .run-foot[b-8b9ugeg9vn],
    .home.is-animated .act-stats .stat[b-8b9ugeg9vn],
    .home.is-animated .act-skills .skill-group[b-8b9ugeg9vn],
    .home.is-animated .act-github .repo[b-8b9ugeg9vn],
    .home.is-animated .act-about .about-portrait[b-8b9ugeg9vn],
    .home.is-animated .finale[b-8b9ugeg9vn] {
        opacity: 1;
    }

    .home.is-animated .run[b-8b9ugeg9vn] {
        position: static;
        gap: var(--sp-8);
        perspective: none;
    }

    .home.is-animated .pj[b-8b9ugeg9vn] {
        position: static;
        transform: none;
    }

    .home.is-animated .about-column[b-8b9ugeg9vn] {
        position: static;
        transform: none;
    }

    .home.is-animated .about-viewport[b-8b9ugeg9vn] {
        overflow: visible;
        mask-image: none;
        -webkit-mask-image: none;
    }

    .home.is-animated .run-progress-fill[b-8b9ugeg9vn] {
        transform: scaleX(1);
    }
}
/* /Features/Portfolio/ProjectDetail.razor.rz.scp.css */
/* ── Article wrapper ──────────────────────────────────── */
.project-detail[b-2tr2dupas6] {
    max-width: 760px;
    margin: 0 auto;
    padding: var(--sp-6) var(--sp-4) var(--sp-8);
    display: flex;
    flex-direction: column;
    gap: var(--sp-6);
}

/* ── Hero image ───────────────────────────────────────── */
.project-detail-image-wrap[b-2tr2dupas6] {
    position: relative;
    width: 100%;
    border-radius: var(--r-lg);
    overflow: hidden;
    border: 1px solid var(--line);
    box-shadow: var(--shadow-lg);
}

.project-detail-image[b-2tr2dupas6] {
    width: 100%;
    display: block;
}

/* fade the bottom of the hero image into the page for a filmic blend */
.project-detail-image-veil[b-2tr2dupas6] {
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: linear-gradient(to bottom,
        transparent 55%,
        color-mix(in srgb, var(--ground) 75%, transparent) 100%);
}

/* ── Header ───────────────────────────────────────────── */
.project-detail-header[b-2tr2dupas6] {
    display: flex;
    flex-direction: column;
    gap: var(--sp-3);
}

.project-detail-back[b-2tr2dupas6] {
    align-self: flex-start;
    text-decoration: none;
    color: var(--fg-muted);
}

.project-detail-title[b-2tr2dupas6] {
    font-size: clamp(1.75rem, 4vw, 2.5rem);
    font-weight: 700;
    line-height: 1.15;
    margin: 0;
    color: var(--fg);
}

.project-detail-summary[b-2tr2dupas6] {
    font-size: 1.0625rem;
    color: var(--fg-muted);
    margin: 0;
    max-width: 640px;
}

/* ── Tags ─────────────────────────────────────────────── */
.project-detail-tags[b-2tr2dupas6] {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-1);
}

/* ── Actions ──────────────────────────────────────────── */
.project-detail-actions[b-2tr2dupas6] {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-2);
    margin-top: var(--sp-1);
}

/* ── Body (Markdown content) ──────────────────────────── */
.project-detail-body[b-2tr2dupas6] {
    border-top: 1px solid var(--line);
    padding-top: var(--sp-5);
}
/* /Features/Portfolio/Projects.razor.rz.scp.css */
/* ── Hero ──────────────────────────────────────────────── */
.projects-hero[b-72i2g7mkt0] {
    max-width: 820px;
    margin: 0 auto;
    padding: calc(var(--sp-8) + var(--sp-4)) var(--sp-4) var(--sp-7);
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
    text-align: center;
    align-items: center;
}

.projects-eyebrow[b-72i2g7mkt0] {
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    margin: 0;
    background: var(--accent-grad);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}

.projects-headline[b-72i2g7mkt0] {
    font-size: clamp(2.5rem, 6vw, 4rem);
    font-weight: 700;
    line-height: 1.05;
    letter-spacing: -0.035em;
    margin: 0;
    background: linear-gradient(110deg,
        var(--accent-a), var(--accent-b), var(--accent-a));
    background-size: 200% auto;
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    animation: projects-shimmer-b-72i2g7mkt0 8s linear infinite;
}

@keyframes projects-shimmer-b-72i2g7mkt0 {
    to { background-position: 200% center; }
}

.projects-subtitle[b-72i2g7mkt0] {
    font-size: clamp(1.0625rem, 2vw, 1.25rem);
    color: var(--fg-muted);
    margin: 0;
    max-width: 560px;
}

@media (prefers-reduced-motion: reduce) {
    .projects-headline[b-72i2g7mkt0] { animation: none; }
}

/* ── Empty state ──────────────────────────────────────── */
.projects-empty[b-72i2g7mkt0] {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--sp-3);
    padding: var(--sp-8) var(--sp-4);
    color: var(--fg-dim);
    text-align: center;
}

.projects-empty-text[b-72i2g7mkt0] {
    font-size: 0.9375rem;
    color: var(--fg-dim);
    margin: 0;
    max-width: 400px;
}

/* ── Grid ─────────────────────────────────────────────── */
.projects-grid-section[b-72i2g7mkt0] {
    padding: 0 var(--sp-4) var(--sp-8);
    max-width: 1120px;
    margin: 0 auto;
}

.projects-grid[b-72i2g7mkt0] {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
    gap: var(--sp-5);
}

/* ── Card ─────────────────────────────────────────────── */
.project-tilt[b-72i2g7mkt0] {
    height: 100%;
}

.project-card[b-72i2g7mkt0] {
    display: flex;
    flex-direction: column;
    gap: 0;
    height: 100%;
    overflow: hidden;
}

/* media frame clips the zoom; image scales up on card hover */
.project-card-media[b-72i2g7mkt0] {
    overflow: hidden;
    border-bottom: 1px solid var(--line);
}

.project-card-image[b-72i2g7mkt0] {
    width: 100%;
    display: block;
    transition: transform var(--dur-slow) var(--ease-out);
}

.project-tilt:hover .project-card-image[b-72i2g7mkt0] {
    transform: scale(1.06);
}

.project-card-body[b-72i2g7mkt0] {
    display: flex;
    flex-direction: column;
    gap: var(--sp-3);
    padding: var(--sp-5);
    flex: 1;
}

.project-card-title[b-72i2g7mkt0] {
    font-size: 1.1875rem;
    font-weight: 600;
    letter-spacing: -0.01em;
    color: var(--fg);
    margin: 0;
}

.project-card-summary[b-72i2g7mkt0] {
    font-size: 0.875rem;
    color: var(--fg-muted);
    margin: 0;
    flex: 1;
}

.project-card-tags[b-72i2g7mkt0] {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-1);
}

.project-card-link[b-72i2g7mkt0] {
    align-self: flex-start;
    text-decoration: none;
    margin-top: auto;
}
