/* ══════════════════════════════════════════════════════════════════
   F.R.A.N.K. — New Shell (Apr 28, 2026)
   Three-pane layout, galaxy background, modern glass aesthetic.
   Loaded AFTER frank-webui.css so its rules win.
   ══════════════════════════════════════════════════════════════════ */

:root {
    /* Mockup-exact palette — deep navy + electric blue→violet→magenta gradient */
    --shell-bg: #060a1f;
    --shell-fog: rgba(6, 10, 31, 0.55);
    --panel-bg: rgba(13, 17, 36, 0.66);
    --panel-bg-strong: rgba(17, 22, 44, 0.82);
    --panel-border: rgba(255, 255, 255, 0.06);
    --panel-border-bright: rgba(255, 255, 255, 0.12);
    --panel-radius: 18px;
    --row-radius: 14px;

    --shell-text: #e8ecf5;
    --shell-text-dim: rgba(232, 236, 245, 0.62);
    --shell-text-faint: rgba(232, 236, 245, 0.36);

    /* Brand gradient — blue → violet → magenta (matches mockup Home pill) */
    --shell-accent-blue: #3D6FFF;
    --shell-accent-violet: #8B5CF6;
    --shell-accent-magenta: #EC4899;
    --shell-accent-cyan: #00B7FF;     /* FRANK + ONLINE + [SCREEN] */
    --shell-accent-pink: #FF4DBF;     /* [ÜBER MICH] */

    --shell-grad: linear-gradient(135deg, #3D6FFF 0%, #8B5CF6 50%, #EC4899 100%);
    --shell-grad-soft: linear-gradient(135deg, rgba(61,111,255,0.22) 0%, rgba(139,92,246,0.24) 50%, rgba(236,72,153,0.22) 100%);
    --shell-grad-strong: linear-gradient(135deg, #4F7FFF 0%, #9D6BFF 50%, #FF5CB0 100%);

    --row-active-bg: linear-gradient(135deg, rgba(61,111,255,0.30) 0%, rgba(139,92,246,0.32) 50%, rgba(236,72,153,0.28) 100%);
}

/* ── Pre-boot skeleton (in initial HTML) ─────────────────────────
   Renders before dashboard.js loads so first paint already shows the
   3-pane layout + galaxy bg instead of the ugly "Loading..." flash. */
body.fk-preboot {
    background:
        linear-gradient(180deg, rgba(6,10,31,0.42) 0%, rgba(6,10,31,0.55) 100%),
        radial-gradient(1200px 800px at 18% 20%, rgba(61,111,255,0.14), transparent 65%),
        radial-gradient(1000px 700px at 82% 78%, rgba(236,72,153,0.12), transparent 65%),
        url('/static/assets/galaxy-bg.jpg') center/cover no-repeat fixed,
        var(--shell-bg) !important;
}
body.fk-preboot #nav,
body.fk-preboot .af-nav,
body.fk-preboot .af-mobile-menu,
body.fk-preboot .af-loading { display: none !important; }
body.fk-preboot main#app { padding: 0 !important; margin: 0 !important; height: 100vh; width: 100vw; overflow: hidden; }

/* Skeleton hidden unless we're in pre-boot. This keeps login / signup /
   onboarding pages clean — even though the skeleton is in initial HTML,
   it never paints unless body.fk-preboot is set. */
.fk-shell-skeleton { display: none; }
body.fk-preboot .fk-shell-skeleton {
    /* Identical layout to .fk-shell so the swap is invisible to the eye */
    display: grid;
    grid-template-columns: 230px 240px 1fr;
    gap: 10px;
    padding: 8px;
    height: 100%;
    width: 100%;
    box-sizing: border-box;
    color: var(--shell-text);
    font-family: 'Inter', system-ui, -apple-system, sans-serif;
    overflow: hidden;
}
.fk-skeleton-pane {
    background: rgba(13, 17, 36, 0.66);
    border: 1px solid rgba(255, 255, 255, 0.06);
    border-radius: 18px;
    backdrop-filter: blur(22px) saturate(140%);
    -webkit-backdrop-filter: blur(22px) saturate(140%);
    box-shadow: 0 8px 32px rgba(0,0,0,0.35), inset 0 1px 0 rgba(255,255,255,0.04);
    padding: 16px 12px;
    display: flex;
    flex-direction: column;
    gap: 8px;
    overflow: hidden;
    position: relative;
}
.fk-skeleton-block {
    background: linear-gradient(
        90deg,
        rgba(255,255,255,0.04) 0%,
        rgba(255,255,255,0.10) 50%,
        rgba(255,255,255,0.04) 100%);
    background-size: 200% 100%;
    border-radius: 10px;
    animation: fk-skeleton-shimmer 2.4s ease-in-out infinite;
    flex-shrink: 0;
}
.fk-skeleton-brand   { height: 36px; width: 78%; margin-bottom: 14px; border-radius: 10px; }
.fk-skeleton-row     { height: 36px; width: 100%; border-radius: 14px; }
.fk-skeleton-spacer  { flex: 1; min-height: 12px; }
.fk-skeleton-spacer-flex { flex: 1; }
.fk-skeleton-card    { height: 56px; width: 100%; border-radius: 16px; margin-top: 4px; }
.fk-skeleton-head    { height: 22px; width: 60%; margin-bottom: 8px; }
.fk-skeleton-search  { height: 38px; width: 100%; margin-bottom: 4px; border-radius: 12px; }
.fk-skeleton-chat    { height: 64px; width: 100%; border-radius: 14px; }
.fk-skeleton-header  { height: 60px; width: 100%; margin: -16px -12px 0; padding: 0; border-radius: 0; border-bottom: 1px solid rgba(255,255,255,0.06); }
.fk-skeleton-composer{ height: 58px; width: 100%; margin: 0 -12px -16px; border-radius: 18px; padding: 0; }
.fk-skeleton-main    { padding: 0; }
.fk-skeleton-main .fk-skeleton-header   { margin: 0; border-radius: 18px 18px 0 0; height: 70px; }
.fk-skeleton-main .fk-skeleton-composer { margin: 0 14px 14px; height: 56px; border-radius: 18px; }

@keyframes fk-skeleton-shimmer {
    0%   { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}

/* When the real shell mounts, fade the skeleton out behind it.
   dashboard.js's render() simply replaces the skeleton; CSS doesn't
   need to coordinate the exit. */

/* Real shell pane-in: the three panels rise gently into place when
   they replace the skeleton. Only fires when not in skeleton mode. */
.fk-shell:not(.fk-shell-skeleton) > .fk-panel {
    animation: fk-pane-in 0.42s cubic-bezier(0.20, 0.70, 0.25, 1) backwards;
}
.fk-shell:not(.fk-shell-skeleton) > .fk-panel:nth-child(1) { animation-delay: 0.04s; }
.fk-shell:not(.fk-shell-skeleton) > .fk-panel:nth-child(2) { animation-delay: 0.10s; }
.fk-shell:not(.fk-shell-skeleton) > .fk-panel:nth-child(3) { animation-delay: 0.16s; }
@keyframes fk-pane-in {
    from { opacity: 0; transform: translateY(10px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* ── Admin-page styling: red-tinted galaxy + scrollable ──────────
   Set via document.body.classList.add('admin-page') in admin.js's
   mount(). Fixes two regressions:
     1. body has overflow:hidden globally → page wasn't scrollable.
     2. admin had no themed background → looked broken vs the rest.

   Override-order: this block ABOVE the fk-preboot bg so admin-page
   wins via cascade order. */
body.admin-page {
    overflow: auto !important;
    height: auto !important;
    min-height: 100vh;
    background:
        linear-gradient(180deg, rgba(20, 8, 12, 0.40) 0%, rgba(28, 8, 14, 0.55) 100%),
        radial-gradient(1200px 800px at 18% 20%, rgba(255, 75, 105, 0.20), transparent 65%),
        radial-gradient(1000px 700px at 82% 78%, rgba(220, 38, 80, 0.18), transparent 65%),
        url('/static/assets/galaxy-bg.jpg') center/cover no-repeat fixed,
        #1a060b !important;
}
html:has(body.admin-page) { overflow: auto !important; height: auto !important; }
/* Hide the legacy F.R.A.N.K. green af-nav on admin — back-button below
   takes its place. */
body.admin-page #nav,
body.admin-page .af-nav,
body.admin-page .af-mobile-menu { display: none !important; }
body.admin-page main#app.af-main {
    margin-top: 0 !important;
    padding: 0 !important;
    min-height: 100vh;
    background: transparent !important;
}
body.admin-page .adm-page {
    /* Glass card so the galaxy bg shines through */
    background: rgba(20, 8, 14, 0.55);
    backdrop-filter: blur(18px) saturate(140%);
    -webkit-backdrop-filter: blur(18px) saturate(140%);
    border: 1px solid rgba(255, 90, 110, 0.18);
    border-radius: 18px;
    margin: 28px auto !important;
    max-width: 1100px;
    box-shadow: 0 20px 60px rgba(0,0,0,0.50), 0 0 60px rgba(255, 90, 110, 0.10);
}

/* Floating back-to-dashboard pill (top-left mirror of the admin button) */
body.admin-page #adm-back-btn {
    position: fixed;
    top: 22px; left: 22px;
    z-index: 9000;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 8px 14px;
    background: rgba(20, 8, 14, 0.82);
    backdrop-filter: blur(14px) saturate(140%);
    -webkit-backdrop-filter: blur(14px) saturate(140%);
    border: 1px solid rgba(255, 90, 110, 0.40);
    border-radius: 999px;
    color: #ffd0d6;
    font-family: 'Inter', system-ui, sans-serif;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    text-decoration: none;
    cursor: pointer;
    box-shadow: 0 8px 24px rgba(0,0,0,0.5), 0 0 18px rgba(255, 90, 110, 0.18);
    transition: transform 0.18s ease, box-shadow 0.18s ease, border-color 0.18s ease;
}
body.admin-page #adm-back-btn:hover {
    transform: translateY(-1px);
    border-color: rgba(255, 90, 110, 0.75);
    box-shadow: 0 10px 30px rgba(0,0,0,0.55), 0 0 26px rgba(255, 90, 110, 0.40);
}
body.admin-page #adm-back-btn span {
    font-size: 14px;
    line-height: 1;
}
/* Hide the floating admin pill (we're already on admin) */
body.admin-page #admin-log-btn { display: none !important; }

/* May 11 — admin access moved into Settings page as a regular card +
   button. The floating pill is permanently retired. This rule is a
   defensive cleanup so any leftover injection (cached old JS in PWA
   shell, dev consoles re-creating it, etc.) doesn't surface. The real
   guarantee is server-side: app/main.py serve_spa redirects /admin →
   /dashboard for any user whose plan !== "admin". */
#admin-log-btn { display: none !important; }

/* ── Galaxy background + fog ───────────────────────────────────── */
body.frank-shell-active {
    background:
        linear-gradient(180deg, rgba(6,10,31,0.42) 0%, rgba(6,10,31,0.55) 100%),
        radial-gradient(1200px 800px at 18% 20%, rgba(61,111,255,0.14), transparent 65%),
        radial-gradient(1000px 700px at 82% 78%, rgba(236,72,153,0.12), transparent 65%),
        url('/static/assets/galaxy-bg.jpg') center/cover no-repeat fixed,
        var(--shell-bg) !important;
}
html { background: var(--shell-bg); }

/* Kill the old GoL canvas + scanlines + aurora — leave everywhere */
.frank-hub > #gol-bg,
.frank-hub > .scanlines,
.frank-hub > .aurora-container,
canvas#gol-bg,
.scanlines,
.aurora-container { display: none !important; }

/* App container fills the viewport without hub padding */
.frank-hub {
    background: transparent !important;
    min-height: 100vh;
}
.page-container {
    background: transparent !important;
    padding: 0 !important;
    margin: 0 !important;
    min-height: 100vh;
    height: 100vh;
}
.page { background: transparent !important; }

/* Hide the global app nav-bar on dashboard — full-screen shell instead */
body.frank-shell-active #nav,
body.frank-shell-active .af-nav,
body.frank-shell-active .af-mobile-menu { display: none !important; }
body.frank-shell-active main#app {
    padding: 0 !important; margin: 0 !important;
    height: 100vh; width: 100vw; overflow: hidden;
    /* Belt+suspenders: .af-main sits inside CSS that sometimes adds horizontal
       padding via media queries (line 780 / 2342 in main.css). Force every
       side to 0 so the shell can occupy the entire viewport edge-to-edge. */
}
body.frank-shell-active .af-main { padding: 0 !important; margin: 0 !important; }

/* ── Three-pane shell ──────────────────────────────────────────── */
.fk-shell {
    display: grid;
    grid-template-columns: 230px 240px 1fr;
    gap: 10px;
    padding: 8px;
    height: 100%;
    width: 100%;
    box-sizing: border-box;
    color: var(--shell-text);
    font-family: 'Inter', system-ui, -apple-system, 'SF Pro Display', sans-serif;
    overflow: hidden;
}

/* Fullview mode: Mail/Cloud/Hosting/Kalender/Einstellungen — these have
   their own internal folder list, so the chats column is dropped and the
   main pane takes everything except the sidebar. */
body.fk-fullview-mode .fk-shell { grid-template-columns: 240px 1fr; }
body.fk-fullview-mode .fk-chats { display: none !important; }
/* Workspace mode (project opened) ALSO hides the chats column.
   _wireWorkspaceMode is the source of truth for "we're in a project
   workspace" — observes #proj-main for .proj-workspace / .proj-tabs.
   Linking this rule means: regardless of which click path opens the
   project (sidebar children list, chats-pane proj-item, direct URL),
   the chats column gets out of the way and the workspace stretches. */
body.fk-workspace-mode .fk-shell { grid-template-columns: 240px 1fr; }
body.fk-workspace-mode .fk-chats { display: none !important; }

.fk-panel {
    background: var(--panel-bg);
    border: 1px solid var(--panel-border);
    border-radius: var(--panel-radius);
    backdrop-filter: blur(22px) saturate(140%);
    -webkit-backdrop-filter: blur(22px) saturate(140%);
    box-shadow: 0 8px 32px rgba(0,0,0,0.35), inset 0 1px 0 rgba(255,255,255,0.04);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    position: relative;
}

/* ── Sidebar (left) ───────────────────────────────────────────── */
.fk-sidebar { padding: 16px 12px; }

.fk-brand {
    display: flex; align-items: center; justify-content: space-between;
    padding: 4px 6px 18px 6px;
    border-bottom: 1px solid var(--panel-border);
    margin-bottom: 14px;
}
.fk-brand-mark {
    display: flex; align-items: center; gap: 10px;
    font-weight: 800; letter-spacing: 0.08em; font-size: 15px;
    color: #fff;
}
.fk-brand-logo {
    width: 28px; height: 28px; border-radius: 8px;
    background: var(--shell-grad);
    display: grid; place-items: center;
    box-shadow: 0 4px 14px rgba(111,140,255,0.32);
}
.fk-brand-logo svg { width: 16px; height: 16px; color: #0a0e1f; }
.fk-brand-collapse {
    width: 30px; height: 30px; border-radius: 8px;
    background: rgba(255,255,255,0.04); border: 1px solid var(--panel-border);
    display: grid; place-items: center; cursor: pointer; color: var(--shell-text-dim);
}
.fk-brand-collapse:hover { background: rgba(255,255,255,0.08); color: #fff; }

/* ── Mobile-only floating language pill ──
   Why this exists: .fk-sidebar is display:none on ≤720px, so the in-
   sidebar lang switch is invisible on phones. This floating pill is
   the same toggle in a different position, shown ONLY on mobile. */
.fk-mobile-lang-pill {
    /* Hidden on desktop — desktop uses the sidebar's .fk-lang-switch.
       On mobile, lives inline at the right end of the .fk-mobile-tabs
       bar (rendered there via dashboard.js). */
    display: none;
    position: relative;
    grid-template-columns: 1fr 1fr;
    flex: 0 0 auto;
    align-self: center;
    height: 30px;
    margin: 0 6px 0 4px;
    border-radius: 999px;
    background: rgba(20, 24, 48, 0.85);
    border: 1px solid rgba(125, 174, 255, 0.22);
    padding: 2px;
    user-select: none;
    overflow: hidden;
    box-shadow: inset 0 0 0 1px rgba(0,0,0,0.2);
}
.fk-mobile-lang-pill .fk-lang-thumb {
    position: absolute;
    top: 2px; bottom: 2px; left: 2px;
    width: calc(50% - 2px);
    border-radius: 999px;
    background: var(--shell-grad, linear-gradient(135deg,#6f8cff,#b67dff));
    box-shadow: 0 2px 8px rgba(111,140,255,0.45);
    transition: transform 0.22s cubic-bezier(.4,.1,.2,1);
    pointer-events: none;
    z-index: 0;
}
.fk-mobile-lang-pill[data-lang="en"] .fk-lang-thumb { transform: translateX(100%); }
.fk-mobile-lang-pill[data-lang="de"] .fk-lang-thumb { transform: translateX(0); }
.fk-mobile-lang-pill .fk-lang-opt {
    position: relative; z-index: 1;
    display: flex; align-items: center; justify-content: center;
    appearance: none; -webkit-appearance: none;
    background: transparent; border: 0;
    /* Buttons render as grid items inside .fk-mobile-tabs (which is
       align-items: stretch — flexbox parent). That stretch propagates
       and gives the button h=tab-bar-height by default, blowing the
       pill apart. Pin both height bounds to the pill's inner row. */
    height: 26px; min-height: 0; padding: 0;
    font: 700 10px/1 'Inter', system-ui, sans-serif;
    letter-spacing: 0.12em;
    color: rgba(255, 255, 255, 0.7);
    cursor: pointer;
    transition: color 0.18s ease;
    min-width: 26px;
    -webkit-tap-highlight-color: transparent;
}
.fk-mobile-lang-pill .fk-lang-opt.active { color: #0a0e1f; }

@media (max-width: 720px), (max-height: 500px) and (orientation: landscape) {
    .fk-mobile-lang-pill {
        display: inline-grid;
    }
}

/* ── DE/EN language switch (replaces old sidebar-toggle button) ── */
.fk-lang-switch {
    position: relative;
    display: inline-grid;
    grid-template-columns: 1fr 1fr;
    align-items: stretch;
    height: 26px;
    border-radius: 999px;
    background: rgba(255,255,255,0.04);
    border: 1px solid var(--panel-border);
    padding: 2px;
    user-select: none;
    overflow: hidden;
    box-shadow: inset 0 1px 0 rgba(255,255,255,0.03);
}
.fk-lang-thumb {
    position: absolute;
    top: 2px; bottom: 2px; left: 2px;
    width: calc(50% - 2px);
    border-radius: 999px;
    background: var(--shell-grad, linear-gradient(135deg,#6f8cff,#b67dff));
    box-shadow: 0 2px 8px rgba(111,140,255,0.45);
    transition: transform 0.22s cubic-bezier(.4,.1,.2,1);
    pointer-events: none;
    z-index: 0;
}
.fk-lang-switch[data-lang="en"] .fk-lang-thumb { transform: translateX(100%); }
.fk-lang-switch[data-lang="de"] .fk-lang-thumb { transform: translateX(0); }
.fk-lang-opt {
    position: relative; z-index: 1;
    appearance: none; -webkit-appearance: none;
    background: transparent; border: 0; padding: 0 12px;
    font: 700 10.5px/1 'Inter', system-ui, sans-serif;
    letter-spacing: 0.16em;
    color: var(--shell-text-dim, #9aa3bd);
    cursor: pointer;
    transition: color 0.18s ease;
    min-width: 30px;
}
.fk-lang-opt.active { color: #0a0e1f; }
.fk-lang-opt:not(.active):hover { color: #fff; }
.fk-lang-opt:focus-visible { outline: 2px solid #b67dff; outline-offset: 2px; border-radius: 999px; }

.fk-nav {
    display: flex; flex-direction: column; gap: 4px;
    flex: 1; min-height: 0;
    /* Horizontal scrollbar was leaking in as a thin grey line under the nav
       because of sub-pixel overflow from the active row's gradient. Hard-kill
       horizontal overflow; allow vertical scroll only. */
    overflow-y: auto;
    overflow-x: hidden;
    scrollbar-width: thin;
    scrollbar-color: transparent transparent;     /* hidden by default */
}
.fk-nav:hover { scrollbar-color: rgba(255,255,255,0.18) transparent; }
.fk-nav::-webkit-scrollbar { width: 6px; }
.fk-nav::-webkit-scrollbar-track { background: transparent; }
.fk-nav::-webkit-scrollbar-thumb { background: transparent; border-radius: 3px; transition: background 0.2s; }
.fk-nav:hover::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.14); }
.fk-nav:active::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.22); }

.fk-nav-row {
    position: relative;
    display: flex; align-items: center; gap: 11px;
    padding: 8px 12px;
    border-radius: var(--row-radius);
    color: var(--shell-text-dim);
    font-size: 13px; font-weight: 500;
    cursor: pointer; user-select: none;
    transition: background 0.18s, color 0.18s;
    background: transparent;
    border: 1px solid transparent;
}
.fk-nav-row:hover {
    background: rgba(255,255,255,0.04);
    color: var(--shell-text);
}
.fk-nav-row.active {
    background:
        linear-gradient(135deg, rgba(79,143,255,0.88) 0%, rgba(155,108,255,0.82) 50%, rgba(255,92,176,0.76) 100%);
    color: #fff;
    border-color: rgba(255,255,255,0.22);
    text-shadow: 0 1px 2px rgba(0,0,0,0.28);
    font-weight: 600;
    /* All highlights INSET so nothing extends past the row. The parent
       .fk-nav has overflow:hidden which would clip outer shadows on the
       left/right; insets are immune. */
    box-shadow:
        0 0 0 1px rgba(255,255,255,0.12) inset,
        0 1px 0 rgba(255,255,255,0.24) inset,
        0 -1px 0 rgba(0,0,0,0.10) inset;
}
/* No ::before bar — it was poking out of the rounded corner as a small
   dark artifact on the left edge. Pure gradient + insets is enough. */
.fk-nav-row.active::before { display: none; }
.fk-nav-row.active svg {
    color: #fff;
}
.fk-nav-row svg { width: 18px; height: 18px; flex-shrink: 0; stroke-width: 1.8; color: currentColor; }
.fk-nav-row .fk-nav-chev {
    margin-left: auto; width: 14px; height: 14px;
    transition: transform 0.18s; opacity: 0.6;
}
.fk-nav-row.expanded .fk-nav-chev { transform: rotate(90deg); opacity: 1; }

/* Expandable Projekte sub-list */
.fk-nav-children {
    margin: 4px 0 8px 28px;
    display: none;
    flex-direction: column; gap: 2px;
    border-left: 1px solid var(--panel-border);
    padding-left: 10px;
    max-height: 320px; overflow-y: auto;
}
.fk-nav-row.expanded + .fk-nav-children { display: flex; }
.fk-nav-children::-webkit-scrollbar { width: 3px; }
.fk-nav-children::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.06); border-radius: 2px; }

.fk-nav-child {
    padding: 7px 10px;
    border-radius: 8px;
    font-size: 12px; color: var(--shell-text-dim);
    cursor: pointer;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    transition: background 0.15s, color 0.15s;
}
.fk-nav-child:hover { background: rgba(255,255,255,0.04); color: var(--shell-text); }
.fk-nav-child.active { background: rgba(111,140,255,0.16); color: #fff; }
.fk-nav-child-empty { padding: 8px 10px; font-size: 11px; color: var(--shell-text-faint); font-style: italic; }
.fk-nav-child.fk-nav-child-new {
    margin-top: 4px;
    color: #cfd7ff;
    background: linear-gradient(135deg, rgba(61,111,255,0.14) 0%, rgba(139,92,246,0.16) 50%, rgba(236,72,153,0.14) 100%);
    border: 1px dashed rgba(155,108,255,0.42);
    font-weight: 600;
    letter-spacing: 0.02em;
    display: flex; align-items: center; gap: 6px;
}
.fk-nav-child.fk-nav-child-new:hover {
    background: linear-gradient(135deg, rgba(61,111,255,0.22) 0%, rgba(139,92,246,0.26) 50%, rgba(236,72,153,0.22) 100%);
    border-color: rgba(155,108,255,0.65);
    color: #fff;
}
.fk-nav-child-plus {
    display: inline-grid; place-items: center;
    width: 14px; height: 14px;
    border-radius: 4px;
    background: var(--shell-grad);
    color: #0a0e1f;
    font-size: 10px; font-weight: 800; line-height: 1;
}

/* ── Token usage card — compact, no sparkline ──────────────── */
.fk-token-card {
    margin-top: 12px;
    padding: 10px 14px;
    background: rgba(255,255,255,0.03);
    border: 1px solid var(--panel-border);
    border-radius: 14px;
}
.fk-token-label {
    font-size: 9.5px; letter-spacing: 0.18em;
    color: var(--shell-text-faint); font-weight: 700;
    margin-bottom: 4px;
}
.fk-token-value {
    font-size: 18px; font-weight: 700;
    background: var(--shell-grad);
    -webkit-background-clip: text; background-clip: text;
    color: transparent;
    letter-spacing: -0.01em;
    line-height: 1.1;
}
.fk-token-percent { font-size: 10px; color: var(--shell-text-faint); margin-top: 1px; }
.fk-token-spark { display: none; }

/* Verification flash: applied for ~900ms when /api/projects/usage
   reports a different token_cap than last poll (admin changed it). */
.fk-token-card.fk-token-flash {
    animation: fk-token-cap-flash 0.9s ease-out;
}
@keyframes fk-token-cap-flash {
    0%   { box-shadow: 0 0 0 0 rgba(0, 191, 255, 0.0); border-color: var(--panel-border); }
    20%  { box-shadow: 0 0 0 6px rgba(0, 191, 255, 0.35); border-color: rgba(0, 191, 255, 0.55); background: rgba(0, 191, 255, 0.08); }
    60%  { box-shadow: 0 0 0 3px rgba(0, 191, 255, 0.18); border-color: rgba(0, 191, 255, 0.35); }
    100% { box-shadow: 0 0 0 0 rgba(0, 191, 255, 0); border-color: var(--panel-border); background: rgba(255,255,255,0.03); }
}

/* ── User card — mockup #9 ─────────────────────────────────── */
.fk-user-card {
    margin-top: 10px;
    padding: 12px 14px;
    background: rgba(13, 17, 36, 0.6);
    border: 1px solid rgba(255,255,255,0.07);
    border-radius: 16px;
    display: flex; align-items: center; gap: 12px;
    cursor: pointer;
    transition: background 0.15s, border-color 0.15s;
    backdrop-filter: blur(14px);
}
.fk-user-card:hover {
    background: rgba(20,24,48,0.72);
    border-color: rgba(255,255,255,0.12);
}
.fk-user-avatar {
    position: relative;
    width: 42px; height: 42px; border-radius: 50%;
    background:
        #b4bedf
        url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'><path fill='%23ffffff' d='M32 9c-7 0-12 5.5-12 12.5S25 34 32 34s12-5.5 12-12.5S39 9 32 9zm0 28c-9 0-22 4-22 13v3c0 1.1.9 2 2 2h40c1.1 0 2-.9 2-2v-3c0-9-13-13-22-13z'/></svg>")
        center/cover no-repeat;
    color: transparent; font-size: 0;          /* hide initials */
    flex-shrink: 0;
    box-shadow: 0 0 0 1px rgba(255,255,255,0.10), 0 4px 12px rgba(0,0,0,0.5);
}
/* Online status dot (mockup shows a small blue/cyan dot bottom-right of avatar) */
.fk-user-avatar::after {
    content: '';
    position: absolute;
    width: 10px; height: 10px;
    bottom: 0; right: 0;
    background: #38BDF8;
    border-radius: 50%;
    box-shadow: 0 0 0 2px rgba(13,17,36,0.95), 0 0 8px rgba(56,189,248,0.7);
}
.fk-user-info { flex: 1; min-width: 0; overflow: hidden; }
/* Auto-shrink the name so long emails (structured.thinking.gschaider) fit
   on one line without truncation. CSS clamp gives 9-14px range based on
   the parent width — readable for "Du", still legible for full emails. */
.fk-user-name {
    font-size: clamp(9.5px, 0.65cqw + 8px, 14px);
    color: #fff;
    font-weight: 700; line-height: 1.15;
    font-family: 'Inter', system-ui, sans-serif;
    white-space: nowrap;
    container-type: inline-size;
    /* Fallback for browsers without container queries */
    overflow: visible;
}
/* Container-query-driven shrink for the user-info wrapper. */
.fk-user-info { container-type: inline-size; }
@container (max-width: 130px) { .fk-user-name { font-size: 11px; } }
@container (max-width: 110px) { .fk-user-name { font-size: 10px; } }
@container (max-width: 90px)  { .fk-user-name { font-size: 9px; } }
.fk-user-role {
    font-size: 10px; color: var(--shell-text-dim);
    margin-top: 2px;
    letter-spacing: 0.04em;
    font-family: 'Inter', system-ui, sans-serif;
    white-space: nowrap;
}
/* Hide chevron when info is tight so the name has every pixel. */
.fk-user-card .fk-user-chev { transition: opacity 0.15s; }
@media (max-width: 1100px) { .fk-user-card .fk-user-chev { display: none; } }
.fk-user-chev {
    width: 16px; height: 16px;
    color: var(--shell-text-faint);
    flex-shrink: 0;
}

/* ── Middle pane (chats list) ─────────────────────────────── */
.fk-chats { padding: 16px 12px 12px 12px; }
.fk-chats-head {
    display: flex; align-items: center; justify-content: space-between;
    gap: 8px;
    padding: 0 2px 12px 2px;
    border-bottom: 1px solid var(--panel-border);
    margin-bottom: 10px;
}
.fk-chats-title {
    font-size: 12px; font-weight: 800;
    letter-spacing: 0.18em; color: #fff;
}
.fk-chats-new {
    display: flex; align-items: center; gap: 4px;
    background: var(--shell-grad);
    border: none; border-radius: 10px;
    padding: 6px 10px;
    color: #fff; font-weight: 700; font-size: 11px;
    cursor: pointer;
    box-shadow: 0 4px 14px rgba(139,92,246,0.34);
    transition: transform 0.15s, box-shadow 0.15s;
    flex-shrink: 0;
}
.fk-chats-new:hover { transform: translateY(-1px); box-shadow: 0 6px 20px rgba(236,72,153,0.50); }
.fk-chats-new svg { width: 12px; height: 12px; }

.fk-chats-search {
    position: relative; margin-bottom: 10px;
}
.fk-chats-search input {
    width: 100%;
    background: rgba(255,255,255,0.04);
    border: 1px solid var(--panel-border);
    border-radius: 12px;
    padding: 11px 14px 11px 14px;
    color: #fff; font-size: 12px;
    font-family: inherit;
    outline: none;
    transition: border-color 0.18s, background 0.18s;
}
.fk-chats-search input::placeholder { color: var(--shell-text-faint); }
.fk-chats-search input:focus { border-color: rgba(111,140,255,0.45); background: rgba(255,255,255,0.06); }

.fk-chats-list {
    flex: 1; overflow-y: auto;
    display: flex; flex-direction: column; gap: 6px;
    padding-right: 2px;
}
.fk-chats-list::-webkit-scrollbar { width: 4px; }
.fk-chats-list::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.08); border-radius: 2px; }

.fk-chat-item {
    position: relative;
    padding: 12px 14px;
    background: rgba(255,255,255,0.03);
    border: 1px solid var(--panel-border);
    border-radius: 14px;
    cursor: pointer;
    transition: background 0.15s, border-color 0.15s, transform 0.15s;
}
.fk-chat-item:hover { background: rgba(255,255,255,0.06); border-color: var(--panel-border-bright); }
.fk-chat-item.active {
    background: var(--shell-grad-soft);
    border-color: rgba(111,140,255,0.32);
}
.fk-chat-item.active::before {
    content: ''; position: absolute; left: 0; top: 12px; bottom: 12px;
    width: 3px; background: var(--shell-grad); border-radius: 0 3px 3px 0;
}
.fk-chat-item-head {
    display: flex; align-items: center; justify-content: space-between;
    margin-bottom: 4px;
}
.fk-chat-item-title {
    font-size: 13px; font-weight: 600; color: #fff;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    flex: 1; min-width: 0;
}
.fk-chat-item-time { font-size: 10px; color: var(--shell-text-faint); flex-shrink: 0; margin-left: 8px; }
.fk-chat-item-preview {
    font-size: 11px; color: var(--shell-text-dim);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    line-height: 1.4;
}
.fk-chat-item-unread-dot {
    width: 8px; height: 8px; border-radius: 50%;
    background: var(--shell-accent-3);
    box-shadow: 0 0 10px rgba(77,214,255,0.6);
    flex-shrink: 0; margin-left: 6px;
}

.fk-chats-empty {
    padding: 32px 12px;
    text-align: center;
    color: var(--shell-text-faint);
    font-size: 12px;
    line-height: 1.6;
}

/* ── Right pane (chat thread) ─────────────────────────────── */
.fk-main { padding: 0; }
.fk-main-inner { display: flex; flex-direction: column; height: 100%; }
.fk-main-header {
    display: flex; align-items: center; justify-content: space-between;
    padding: 16px 22px;
    border-bottom: 1px solid var(--panel-border);
}
.fk-main-titlebar { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.fk-main-title-block { display: flex; align-items: center; gap: 10px; }
.fk-main-title {
    font-size: 15px; font-weight: 800; color: var(--shell-accent-cyan);
    letter-spacing: 0.06em;
}
.fk-status-pill {
    display: inline-flex; align-items: center; gap: 6px;
    font-size: 11px; color: var(--shell-accent-cyan);
    padding: 3px 10px;
    background: transparent;
    border: none;
    border-radius: 999px;
    font-weight: 700; letter-spacing: 0.12em;
}
.fk-status-pill .fk-pulse {
    width: 8px; height: 8px; border-radius: 50%;
    background: var(--shell-accent-cyan);
    box-shadow: 0 0 10px var(--shell-accent-cyan);
    animation: fk-pulse 2s ease-in-out infinite;
}
@keyframes fk-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.45; } }

.fk-main-tabs { display: flex; gap: 14px; margin-left: 8px; }
.fk-main-tab {
    font-size: 11px; font-weight: 700; letter-spacing: 0.14em;
    color: var(--shell-text-faint); cursor: pointer;
    padding: 4px 0;
    transition: color 0.18s;
    background: none; border: none; font-family: inherit;
}
.fk-main-tab:hover { color: var(--shell-text); }
.fk-main-tab.active {
    background: var(--shell-grad);
    -webkit-background-clip: text; background-clip: text; color: transparent;
}
/* Screen-share active state — pulsing red glow on the [SCREEN] tab */
.fk-main-tab.fk-screen-on {
    color: #ff5566 !important;
    text-shadow: 0 0 8px rgba(255,85,102,0.55);
    animation: fk-screen-pulse 1.6s ease-in-out infinite;
}
@keyframes fk-screen-pulse {
    0%, 100% { text-shadow: 0 0 6px rgba(255,85,102,0.45); }
    50%      { text-shadow: 0 0 14px rgba(255,85,102,0.85); }
}

.fk-main-tools { display: flex; gap: 6px; }
.fk-main-icon-btn {
    width: 34px; height: 34px; border-radius: 10px;
    display: grid; place-items: center;
    background: rgba(255,255,255,0.04);
    border: 1px solid var(--panel-border);
    color: var(--shell-text-dim); cursor: pointer;
    transition: background 0.15s, color 0.15s;
}
.fk-main-icon-btn:hover { background: rgba(255,255,255,0.08); color: #fff; }
.fk-main-icon-btn svg { width: 16px; height: 16px; stroke-width: 1.8; }

.fk-main-body {
    flex: 1; min-height: 0; overflow-y: auto;
    padding: 0;
    display: flex; flex-direction: column;
    position: relative;
}
.fk-main-body::-webkit-scrollbar { width: 6px; }
.fk-main-body::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.08); border-radius: 3px; }
/* Direct children get padding for chat-bubble views (welcome, master chat).
   The workspace .proj-workspace strips this and goes edge-to-edge. */
.fk-main-body > .fk-welcome,
.fk-main-body > .proj-master,
.fk-main-body > .proj-onboard { padding: 24px 22px; }
/* When projects.js renders its workspace (project opened), it gets the
   full canvas — header bar of the shell is hidden, no padding, no gap. */
body.frank-shell-active.fk-workspace-mode .fk-main-header { display: none !important; }
body.frank-shell-active.fk-workspace-mode .fk-main-body { padding: 0 !important; }
body.frank-shell-active #proj-main .proj-workspace,
body.frank-shell-active #proj-main .proj-page,
body.frank-shell-active #proj-main > * { width: 100%; }
body.frank-shell-active #proj-main { width: 100%; height: 100%; padding: 0 !important; }

/* Welcome / empty state inside main */
.fk-welcome {
    flex: 1; display: flex; flex-direction: column;
    align-items: center; justify-content: center;
    padding: 40px 32px; text-align: center;
}
.fk-welcome-mark {
    width: 88px; height: 88px; border-radius: 22px;
    background: var(--shell-grad);
    display: grid; place-items: center; color: #0a0e1f;
    box-shadow: 0 14px 50px rgba(111,140,255,0.5);
    margin-bottom: 24px;
}
.fk-welcome-mark svg { width: 44px; height: 44px; stroke-width: 1.8; }
.fk-welcome-title {
    font-size: 28px; font-weight: 700; color: #fff;
    margin-bottom: 8px; letter-spacing: -0.01em;
}
.fk-welcome-sub {
    font-size: 14px; color: var(--shell-text-dim);
    max-width: 460px; line-height: 1.55;
}
.fk-welcome-actions {
    margin-top: 26px;
    display: flex; gap: 10px; flex-wrap: wrap; justify-content: center;
}
.fk-welcome-action {
    padding: 10px 16px;
    background: rgba(255,255,255,0.04);
    border: 1px solid var(--panel-border-bright);
    border-radius: 12px;
    color: var(--shell-text);
    font-size: 12px; font-weight: 500;
    cursor: pointer;
    transition: background 0.15s, transform 0.15s;
    display: flex; align-items: center; gap: 8px;
}
.fk-welcome-action:hover { background: rgba(255,255,255,0.08); transform: translateY(-1px); }
.fk-welcome-action svg { width: 14px; height: 14px; }

/* ── Composer (bottom of main) — mockup-exact glassy bar with magenta glow ── */
.fk-composer-wrap {
    padding: 14px 22px 18px;
    border-top: 1px solid var(--panel-border);
    position: relative;
}
.fk-composer {
    position: relative;
    display: flex; align-items: center; gap: 10px;
    background: rgba(8, 10, 24, 0.78);
    border: 1px solid rgba(255,255,255,0.10);
    border-radius: 18px;
    padding: 8px 10px 8px 14px;
    transition: border-color 0.18s, box-shadow 0.18s;
    overflow: hidden;
}
/* Magenta→violet glow blob baked into the right side — smoothly pulsing */
.fk-composer::before {
    content: '';
    position: absolute;
    top: -10px; right: -40px; bottom: -10px; width: 55%;
    background:
        radial-gradient(70% 100% at 70% 50%, rgba(236,72,153,0.55) 0%, transparent 65%),
        radial-gradient(50% 80% at 95% 60%, rgba(139,92,246,0.50) 0%, transparent 60%),
        radial-gradient(60% 110% at 50% 60%, rgba(61,111,255,0.30) 0%, transparent 70%);
    filter: blur(20px);
    pointer-events: none;
    z-index: 0;
    animation: fk-composer-pulse 4s ease-in-out infinite;
    will-change: opacity, transform, filter;
}

@keyframes fk-composer-pulse {
    0%   { opacity: 0.78; transform: translateX(0)   scale(1);    filter: blur(20px); }
    50%  { opacity: 1;    transform: translateX(-12px) scale(1.06); filter: blur(26px); }
    100% { opacity: 0.78; transform: translateX(0)   scale(1);    filter: blur(20px); }
}
.fk-composer > * { position: relative; z-index: 1; }
.fk-composer:focus-within {
    border-color: rgba(139,92,246,0.55);
    box-shadow: 0 0 0 4px rgba(139,92,246,0.10);
}
.fk-composer-attach {
    width: 34px; height: 34px; border-radius: 10px;
    background: transparent; border: none; color: var(--shell-text-dim);
    display: grid; place-items: center; cursor: pointer;
    transition: color 0.15s, background 0.15s;
}
.fk-composer-attach:hover { color: #fff; background: rgba(255,255,255,0.06); }
.fk-composer-input {
    flex: 1; background: transparent; border: none;
    color: #fff; font-size: 13px; padding: 10px 4px;
    font-family: inherit; outline: none;
    resize: none; min-height: 22px; max-height: 200px;
    line-height: 1.5;
}
.fk-composer-input::placeholder { color: rgba(232,236,245,0.55); }
.fk-composer-send {
    width: 42px; height: 42px; border-radius: 12px;
    background: rgba(8, 10, 24, 0.6);
    backdrop-filter: blur(6px);
    border: 1px solid rgba(255,255,255,0.18);
    color: #cfd7ff;
    display: grid; place-items: center; cursor: pointer;
    transition: transform 0.15s, box-shadow 0.15s, color 0.15s;
}
.fk-composer-send:hover {
    color: #fff;
    border-color: rgba(255,255,255,0.32);
    box-shadow: 0 0 0 1px rgba(255,255,255,0.10), 0 6px 20px rgba(236,72,153,0.35);
    transform: translateY(-1px);
}
.fk-composer-send:active { transform: translateY(0); }
.fk-composer-send svg { width: 18px; height: 18px; stroke-width: 1.8; }

/* Admin-Log pill — fixed bottom-right floating button. Subtle red glow
   so admins find it without it screaming. Glassy bg + 1px border + a
   pulsing red dot. Visible on every shell view. */
body.frank-shell-active #admin-log-btn {
    position: fixed !important;
    display: inline-flex !important;
    align-items: center;
    gap: 8px !important;
    bottom: 22px !important;
    right: 22px !important;
    z-index: 9000;
    padding: 8px 14px !important;
    background: rgba(40, 16, 24, 0.82) !important;
    backdrop-filter: blur(14px) saturate(140%) !important;
    -webkit-backdrop-filter: blur(14px) saturate(140%) !important;
    border: 1px solid rgba(255, 90, 110, 0.45) !important;
    border-radius: 999px !important;
    color: #ffd0d6 !important;
    font-family: 'Inter', system-ui, sans-serif !important;
    font-size: 11px !important;
    font-weight: 600 !important;
    letter-spacing: 0.05em !important;
    text-transform: uppercase !important;
    text-decoration: none !important;
    cursor: pointer !important;
    box-shadow: 0 8px 24px rgba(0,0,0,0.5), 0 0 0 1px rgba(255,90,110,0.10) inset, 0 0 18px rgba(255, 90, 110, 0.18) !important;
    transition: transform 0.18s ease, box-shadow 0.18s ease, border-color 0.18s ease !important;
}
body.frank-shell-active #admin-log-btn:hover {
    transform: translateY(-1px);
    border-color: rgba(255, 90, 110, 0.75) !important;
    box-shadow: 0 10px 30px rgba(0,0,0,0.55), 0 0 26px rgba(255, 90, 110, 0.40), 0 0 0 1px rgba(255,90,110,0.15) inset !important;
}
body.frank-shell-active #admin-log-btn::before {
    content: '';
    width: 7px; height: 7px; border-radius: 50%;
    background: #ff5a6e;
    box-shadow: 0 0 8px rgba(255, 90, 110, 0.85);
    animation: fk-admin-pulse 1.6s ease-in-out infinite;
}
@keyframes fk-admin-pulse {
    0%, 100% { opacity: 0.55; transform: scale(0.85); }
    50%      { opacity: 1;    transform: scale(1.15); }
}

/* ── Mobile collapse ──────────────────────────────────────── */
@media (max-width: 1100px) {
    .fk-shell { grid-template-columns: 240px 1fr; padding: 12px; gap: 12px; }
    .fk-chats { display: none; }
    .fk-shell.show-chats .fk-chats { display: flex; }
    .fk-shell.show-chats .fk-main { display: none; }
}
@media (max-width: 720px), (max-height: 500px) and (orientation: landscape) {
    .fk-shell { grid-template-columns: 1fr; padding: 8px; gap: 8px; }
    .fk-sidebar { display: none; }
    .fk-shell.show-sidebar .fk-sidebar { display: flex; position: fixed; left: 8px; right: 8px; top: 8px; bottom: 8px; z-index: 50; }
}

/* ═════════════════════════════════════════════════════════════════
   MOBILE SHELL — bottom tab bar + condensed top bar + safe-area
   ═════════════════════════════════════════════════════════════════
   Below 720px the desktop sidebar disappears (rule above) and the
   user gets:
     - a 5-tab bottom bar (Chat, Projects, Mail, Hivemind, More)
     - a condensed top bar (no [SCREEN] [ÜBER MICH] tabs — those move
       to the project workspace where they belong)
     - chat input that respects safe-area-inset-bottom AND virtual
       keyboard via VisualViewport API (--fk-kb-offset CSS var
       updated from JS)
     - admin badge that auto-hides when input is focused so it can't
       sit over the send button anymore
   The forge aura + breathing aren't worth the GPU cost on mobile —
   we drop blur + saturate filters here.
   ───────────────────────────────────────────────────────────────── */

@media (max-width: 720px), (max-height: 500px) and (orientation: landscape) {
    /* 1. Reserve room for the bottom tab bar (64px + safe-area) */
    .fk-shell {
        padding-bottom: calc(64px + env(safe-area-inset-bottom, 0px)) !important;
        gap: 6px !important;
    }

    /* 2. Drop expensive effects on mobile (perf) */
    body.frank-shell-active .fk-main::before { display: none; }
    body.frank-shell-active .fk-main::after { opacity: 0.4; }
    body.frank-shell-active .fk-panel { backdrop-filter: none; -webkit-backdrop-filter: none; }
    body.frank-shell-active .fk-sidebar,
    body.frank-shell-active .fk-chats { filter: none; }

    /* 3. Compress top header — kill the F.R.A.N.K./tabs/icons cramming */
    body.frank-shell-active .fk-main-header {
        padding: 10px 14px !important;
        gap: 8px;
    }
    body.frank-shell-active .fk-main-title { font-size: 13px !important; }
    body.frank-shell-active .fk-main-tabs { display: none !important; }
    body.frank-shell-active .fk-status-pill { padding: 2px 7px !important; font-size: 10px !important; }
    body.frank-shell-active .fk-main-tools .fk-main-icon-btn {
        width: 36px !important; height: 36px !important;
    }

    /* 4. Bigger tap targets everywhere */
    body.frank-shell-active button,
    body.frank-shell-active a.fk-btn,
    body.frank-shell-active .fk-nav-row { min-height: 44px; }

    /* 5. Chat input — keyboard-aware via --fk-kb-offset (set by JS) */
    body.frank-shell-active .mfv-composer,
    body.frank-shell-active .mfv-input,
    body.frank-shell-active #master-chat-input,
    body.frank-shell-active #proj-chat-input {
        font-size: 16px !important;  /* prevents iOS auto-zoom on focus */
    }
    body.frank-shell-active .fk-main-body {
        padding-bottom: calc(env(safe-area-inset-bottom, 0px) + var(--fk-kb-offset, 0px)) !important;
    }
    /* The composer sticks above the bottom-tab-bar; when keyboard opens
       the JS adds .fk-kb-open which lifts the composer out of the way
       and hides the tab bar (a phone with virtual KB up has no room). */
    body.fk-kb-open .fk-mobile-tabs { transform: translateY(120%); }
    body.fk-kb-open .fk-shell { padding-bottom: 0 !important; }

    /* 6. ADMIN badge — out of the way + hide when typing */
    body.frank-shell-active #admin-log-btn {
        bottom: calc(80px + env(safe-area-inset-bottom, 0px)) !important;
        right: 12px !important;
        padding: 6px 10px !important;
        font-size: 10px !important;
        opacity: 0.55;
    }
    body.frank-shell-active #admin-log-btn:hover { opacity: 1; }
    body.fk-input-focused #admin-log-btn,
    body.fk-kb-open #admin-log-btn { opacity: 0 !important; pointer-events: none; }

    /* 7. Master chat bubbles — dial back the desktop typography bump */
    body.frank-shell-active .fk-main #master-chat-msgs {
        padding: 16px 14px 16px !important;
        gap: 14px !important;
    }
    body.frank-shell-active .fk-main #master-chat-msgs .proj-msg-text,
    body.frank-shell-active .fk-main #master-chat-msgs .proj-msg-text * {
        font-size: 14px !important;
        line-height: 1.5 !important;
    }
    body.frank-shell-active .fk-main #master-chat-msgs .proj-msg.proj-msg-assistant,
    body.frank-shell-active .fk-main #master-chat-msgs .proj-msg.proj-msg-user {
        padding: 12px 14px 10px !important;
        border-radius: 14px !important;
    }
    body.frank-shell-active .fk-main #master-chat-msgs .proj-msg-action {
        width: 32px !important; height: 32px !important;
    }

    /* 8. Cookie banner — slim top variant on mobile so it doesn't eat
       half the screen and block the chat input. The banner ships as a
       fixed bottom panel; we re-anchor it to the top + slim it. */
    .fk-cookie-banner {
        position: fixed !important;
        top: 8px !important;
        bottom: auto !important;
        left: 8px !important;
        right: 8px !important;
        max-width: none !important;
        padding: 8px 12px !important;
        font-size: 12px !important;
        line-height: 1.35 !important;
        max-height: 110px;
        overflow: hidden;
        z-index: 2147483630;
    }
    .fk-cookie-banner h3,
    .fk-cookie-banner .fk-cookie-title { font-size: 12px !important; margin: 0 0 2px !important; }
    .fk-cookie-banner button { padding: 6px 10px !important; font-size: 12px !important; min-height: 36px; }

    /* 9. Mobile sessions drawer — chats column slides in from the left.
       The header button #fk-tool-sessions opens it; backdrop closes it.
       We override the @media(<1100px) `.fk-chats{display:none}` rule
       only when body has .fk-sessions-drawer-open, so the panel stays
       collapsed by default and the chat takes the full width. */
    body.fk-sessions-drawer-open .fk-chats {
        display: flex !important;
        position: fixed !important;
        left: 0; top: 0; bottom: 0;
        width: min(82vw, 340px);
        z-index: 9600;
        margin: 0;
        border-radius: 0 16px 16px 0;
        box-shadow: 12px 0 40px rgba(0,0,0,0.55);
        animation: fk-drawer-slide-in 0.22s cubic-bezier(.2,.7,.25,1);
        padding-top: calc(12px + env(safe-area-inset-top, 0px)) !important;
    }
    #fk-sessions-drawer-backdrop {
        display: none;
        position: fixed; inset: 0;
        background: rgba(0,0,0,0.55);
        backdrop-filter: blur(2px);
        z-index: 9550;
    }
    body.fk-sessions-drawer-open #fk-sessions-drawer-backdrop {
        display: block;
        animation: fk-fade-in 0.18s ease-out;
    }
}
@keyframes fk-drawer-slide-in {
    from { transform: translateX(-100%); }
    to   { transform: translateX(0); }
}
@keyframes fk-fade-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* The mobile-only sessions button in the chat header — hidden on desktop
   (the 3-column shell already shows the chats panel). */
.fk-mobile-only-inline { display: none !important; }
@media (max-width: 720px), (max-height: 500px) and (orientation: landscape) {
    .fk-mobile-only-inline { display: inline-flex !important; }
}

/* ── Mobile bottom-tab-bar (always rendered, hidden on desktop) ── */
.fk-mobile-tabs {
    display: none;
    position: fixed; left: 0; right: 0; bottom: 0;
    height: calc(60px + env(safe-area-inset-bottom, 0px));
    padding: 4px 6px env(safe-area-inset-bottom, 0px);
    background: rgba(10, 14, 28, 0.92);
    backdrop-filter: blur(18px) saturate(160%);
    -webkit-backdrop-filter: blur(18px) saturate(160%);
    border-top: 1px solid rgba(125, 174, 255, 0.18);
    box-shadow: 0 -8px 30px rgba(0,0,0,0.45);
    z-index: 9500;
    transition: transform 0.28s cubic-bezier(0.20, 0.70, 0.25, 1);
    align-items: stretch;
    justify-content: space-around;
    gap: 2px;
}
@media (max-width: 720px), (max-height: 500px) and (orientation: landscape) {
    .fk-mobile-tabs { display: flex; }
    /* Workspace mode (project opened) hides the bottom tabs for full
       immersion. The mobile workspace top bar shows a Back affordance
       to leave. Tabs slide back in when user closes the project. */
    body.fk-workspace-mode .fk-mobile-tabs { transform: translateY(120%); }
    body.fk-workspace-mode .fk-shell { padding-bottom: 0 !important; }
}

/* ═════════════════════════════════════════════════════════════════
   LANDSCAPE PHONE — vertical left-rail layout
   ═════════════════════════════════════════════════════════════════
   On phones in landscape (max-height ≤ 500px, width unlimited) we
   have ~390px tall screen and ~844px wide. The portrait mobile shell
   would waste it: a tall F.R.A.N.K. header (~80px) + a tall
   bottom-tab bar (~70px) leaves only ~230px for content — half the
   screen is chrome.
   So we rotate: bottom-tab bar becomes a 56px-wide LEFT rail (icons
   only, vertical), the header chrome compresses to a 32px strip, and
   the rest of the viewport is content. The lang-pill rotates inside
   the rail (DE on top, EN on bottom).
   ───────────────────────────────────────────────────────────────── */
@media (max-height: 500px) and (orientation: landscape) {
    /* 1. Reset portrait padding-bottom — no bottom bar anymore */
    .fk-shell {
        padding: 6px 8px 6px calc(60px + env(safe-area-inset-left, 0px)) !important;
        gap: 6px !important;
    }
    body.fk-workspace-mode .fk-shell { padding-left: calc(60px + env(safe-area-inset-left, 0px)) !important; }

    /* 2. Rotate bottom-tab-bar into a vertical left rail */
    .fk-mobile-tabs {
        flex-direction: column !important;
        top: 0 !important;
        bottom: 0 !important;
        right: auto !important;
        width: calc(56px + env(safe-area-inset-left, 0px)) !important;
        height: 100vh !important;
        height: 100dvh !important;
        padding: 8px 4px 8px calc(4px + env(safe-area-inset-left, 0px)) !important;
        border-top: none !important;
        border-right: 1px solid rgba(125, 174, 255, 0.18);
        box-shadow: 8px 0 30px rgba(0,0,0,0.45) !important;
        justify-content: flex-start !important;
        align-items: stretch !important;
        gap: 4px !important;
        transition: transform 0.28s cubic-bezier(0.20, 0.70, 0.25, 1) !important;
    }
    /* Workspace mode: KEEP the rail visible in landscape (plenty of
       horizontal room). The user needs cross-section nav back out
       — without the rail they're trapped (mobile-back ends up below
       the viewport on 390-high screens). Only hide for the on-screen
       keyboard.
       NOTE: do NOT override `transform: none` here without restoring
       the off-screen state when keyboard opens — see fk-kb-open. */
    body.fk-workspace-mode .fk-mobile-tabs { transform: none !important; }
    body.fk-kb-open .fk-mobile-tabs { transform: translateX(-110%) !important; }
    /* Hide the separate floating back-button in landscape — the rail
       provides nav out (tap Chat / Mail / Hive / Profile) so the
       back button is redundant and ends up off-screen anyway. */
    body.fk-workspace-mode .fk-mobile-back { display: none !important; }

    /* 3. Tabs: icon-only stacked, labels hidden, 44px tap target */
    .fk-mtab {
        flex: 0 0 auto !important;
        height: 44px;
        padding: 0 !important;
        gap: 0 !important;
    }
    .fk-mtab .fk-mtab-label { display: none !important; }
    .fk-mtab svg { width: 22px !important; height: 22px !important; }
    .fk-mtab.active::before {
        top: auto; left: 4px; right: auto;
        width: 2px; height: 60%;
        top: 20% !important;
        background: linear-gradient(180deg, transparent, #7daeff, #bd7aff, transparent) !important;
    }
    @keyframes fk-mtab-glow-v {
        from { transform: scaleY(0.3); opacity: 0.4; }
        to   { transform: scaleY(1);   opacity: 1; }
    }
    .fk-mtab.active::before { animation: fk-mtab-glow-v 0.4s ease-out; }

    /* 4. Lang-pill — push to bottom of the rail, rotate vertically */
    .fk-mobile-lang-pill {
        margin: auto 4px 4px !important;  /* `auto` top pushes to bottom */
        align-self: center !important;
        grid-template-columns: 1fr !important;
        grid-template-rows: 1fr 1fr !important;
        width: 36px !important;
        height: 52px !important;
    }
    .fk-mobile-lang-pill .fk-lang-thumb {
        top: 2px; left: 2px; right: 2px; bottom: auto;
        width: auto !important;
        height: calc(50% - 2px) !important;
        transition: transform 0.22s cubic-bezier(.4,.1,.2,1) !important;
    }
    .fk-mobile-lang-pill[data-lang="en"] .fk-lang-thumb { transform: translateY(100%) !important; }
    .fk-mobile-lang-pill[data-lang="de"] .fk-lang-thumb { transform: translateY(0) !important; }

    /* 5. Compress F.R.A.N.K. header — kill title block, keep tool icons */
    body.frank-shell-active .fk-main-header {
        padding: 4px 10px !important;
        min-height: 32px !important;
    }
    body.frank-shell-active .fk-main-title { display: none !important; }
    body.frank-shell-active .fk-status-pill { display: none !important; }
    body.frank-shell-active .fk-main-tabs { display: none !important; }
    body.frank-shell-active .fk-main-tools .fk-main-icon-btn {
        width: 28px !important; height: 28px !important;
    }
    body.frank-shell-active .fk-main-tools .fk-main-icon-btn svg {
        width: 14px !important; height: 14px !important;
    }

    /* 6. Cookie banner — slim variant doesn't fit; force compact */
    .fk-cookie-banner {
        font-size: 11px !important; padding: 6px 10px !important;
        max-height: 60px !important;
    }
    .fk-cookie-banner button { min-height: 28px !important; padding: 4px 10px !important; }

    /* 7. Bottom-anchored stuff (composer, admin badge) — no bottom-tab
       bar to clear, so reduce padding */
    body.frank-shell-active .fk-main-body {
        padding-bottom: env(safe-area-inset-bottom, 0px) !important;
    }
    body.frank-shell-active #admin-log-btn {
        bottom: calc(8px + env(safe-area-inset-bottom, 0px)) !important;
    }

    /* 8. Sessions drawer — slide from the rail edge instead of viewport edge */
    body.fk-sessions-drawer-open .fk-chats {
        left: calc(56px + env(safe-area-inset-left, 0px)) !important;
        width: min(58vw, 320px) !important;
        border-radius: 0 !important;
        padding-top: 8px !important;
    }
}

/* Workspace top-bar mobile back button (only renders on mobile;
   inline-injected by the workspace mount via JS). */
.fk-mobile-back {
    display: none;
    width: 36px; height: 36px; border-radius: 10px;
    background: rgba(255,255,255,0.06);
    border: 1px solid rgba(255,255,255,0.10);
    color: rgba(232,236,245,0.75);
    align-items: center; justify-content: center;
    cursor: pointer; flex-shrink: 0;
    transition: background 0.15s, color 0.15s;
}
.fk-mobile-back:hover, .fk-mobile-back:active {
    background: rgba(125,174,255,0.14);
    color: #fff;
    border-color: rgba(125,174,255,0.30);
}
.fk-mobile-back svg { width: 18px; height: 18px; stroke-width: 2; }
@media (max-width: 720px), (max-height: 500px) and (orientation: landscape) {
    body.fk-workspace-mode .fk-mobile-back { display: inline-flex; }
}

/* ── Master-chat empty state — mobile quick-action chips ─────── */
.fk-mchat-welcome {
    display: flex; flex-direction: column; gap: 18px;
    padding: 32px 18px 24px;
    align-items: center; text-align: center;
}
.fk-mchat-welcome-hello {
    font-size: 22px; font-weight: 700; color: #fff;
    background: linear-gradient(135deg, #7daeff, #bd7aff);
    -webkit-background-clip: text; background-clip: text;
    color: transparent;
    letter-spacing: -0.02em;
}
.fk-mchat-welcome-sub {
    font-size: 13px; color: rgba(232,236,245,0.65);
    max-width: 280px; line-height: 1.5;
}
.fk-mchat-quick {
    display: grid; grid-template-columns: 1fr 1fr; gap: 8px;
    width: 100%; max-width: 360px; margin-top: 6px;
}
.fk-mchat-chip {
    display: flex; flex-direction: column; gap: 6px; align-items: flex-start;
    padding: 14px;
    background: rgba(255,255,255,0.04);
    border: 1px solid rgba(125,174,255,0.18);
    border-radius: 14px;
    color: #e8ecf5;
    font-family: 'Inter', system-ui, sans-serif; font-size: 12px;
    text-align: left; cursor: pointer;
    transition: transform 0.18s, box-shadow 0.18s, border-color 0.18s;
    -webkit-tap-highlight-color: transparent;
}
.fk-mchat-chip:active { transform: scale(0.97); }
.fk-mchat-chip:hover {
    border-color: rgba(125,174,255,0.45);
    box-shadow: 0 8px 22px rgba(125,174,255,0.16);
}
.fk-mchat-chip-icon {
    font-size: 18px; line-height: 1;
}
.fk-mchat-chip-text {
    font-size: 12px; line-height: 1.35;
    color: rgba(232,236,245,0.88);
}

/* ── Workspace + Preview tab mobile overrides ────────────────── */
@media (max-width: 720px), (max-height: 500px) and (orientation: landscape) {
    /* Workspace top bar: condense the project-info row + action buttons */
    body.fk-workspace-mode .proj-topbar { padding: 8px 10px 8px 56px !important; }
    /* Push topbar content right of the floating back button (which sits
       fixed top:8px left:8px at 36px wide; 56px = 8+36+12). */

    /* Workspace tab bar: sticky + bigger tap targets */
    body.fk-workspace-mode .proj-tab-bar {
        position: sticky; top: 0; z-index: 20;
        background: rgba(13, 17, 33, 0.92);
        backdrop-filter: blur(8px);
        gap: 4px;
        padding: 6px 8px;
        overflow-x: auto;
        scrollbar-width: none;
    }
    body.fk-workspace-mode .proj-tab-bar::-webkit-scrollbar { display: none; }
    body.fk-workspace-mode .proj-tab {
        min-height: 38px; padding: 8px 12px !important;
        font-size: 12px !important; flex-shrink: 0;
    }

    /* Preview bar: stack vertically + drop advanced controls */
    body.fk-workspace-mode .preview-bar {
        flex-direction: column !important;
        align-items: stretch !important;
        padding: 8px !important; gap: 8px !important;
    }
    body.fk-workspace-mode .preview-left,
    body.fk-workspace-mode .preview-right {
        flex-wrap: wrap; justify-content: center; gap: 6px !important;
    }
    body.fk-workspace-mode .preview-entry-input {
        flex: 1; min-width: 120px; width: auto !important;
    }
    body.fk-workspace-mode .preview-btn {
        min-height: 36px; padding: 7px 10px !important;
    }
    /* Hide bezel inside mobile preview — meta-phone-in-phone is silly */
    body.fk-workspace-mode .phone-bezel {
        background: none !important;
        padding: 0 !important;
        width: 100% !important;
        height: auto !important;
        box-shadow: none !important;
        border-radius: 12px !important;
    }
    body.fk-workspace-mode .phone-screen {
        border-radius: 12px;
    }
    body.fk-workspace-mode .phone-status-bar,
    body.fk-workspace-mode .phone-home-indicator { display: none !important; }
    body.fk-workspace-mode .preview-iframe.preview-mobile,
    body.fk-workspace-mode .preview-iframe.preview-desktop,
    body.fk-workspace-mode .preview-iframe.preview-tablet {
        width: 100% !important; max-width: 100% !important;
        aspect-ratio: auto !important;
        height: calc(100vh - 240px) !important;
        min-height: 300px !important;
    }
    body.fk-workspace-mode .preview-frame-wrap {
        padding: 4px !important;
    }
    /* Hide advanced preview controls on mobile to keep the bar tidy */
    body.fk-workspace-mode .preview-autorefresh,
    body.fk-workspace-mode #preview-native-kit-btn,
    body.fk-workspace-mode #preview-fullscreen-btn { display: none !important; }
}

/* ── Hivemind mobile — scale viz + bigger action chips ──────── */
@media (max-width: 720px), (max-height: 500px) and (orientation: landscape) {
    /* Header: kill the "0/0 online" overflow on small screens */
    .hm-header, .hivemind-header {
        flex-direction: column !important;
        align-items: flex-start !important;
        gap: 4px !important;
        padding: 10px 14px !important;
    }
    .hm-header h1, .hivemind-title {
        font-size: 18px !important;
    }
    /* SVG container: full-width + minimum height so the force graph
       has room to lay out instead of collapsing to nothing */
    .hivemind-svg-wrap, .hm-svg-wrap, .hivemind-canvas {
        min-height: 280px !important;
        width: 100% !important;
    }
    .hivemind-svg-wrap svg, .hm-svg-wrap svg {
        max-width: 100% !important; height: auto !important;
    }
    /* Node cards / connection list: full-width stacked */
    .hm-node, .hivemind-node, .tailscale-node-card {
        width: 100% !important;
        margin: 8px 0 !important;
        padding: 14px !important;
        min-height: 56px;
    }
    /* Hide the desktop control-hints bar — drag/scroll/dblclick
       don't apply on touch */
    .hm-controls-hint, .hivemind-controls-hint { display: none !important; }
    /* Connect-tailnet form fields go full-width */
    .hm-add-form input, .hm-add-form button,
    .hivemind-add-form input, .hivemind-add-form button {
        width: 100% !important;
        min-height: 44px !important;
    }
}

/* ── Mail mobile — single-column inbox-or-thread, not both ───── */
@media (max-width: 720px), (max-height: 500px) and (orientation: landscape) {
    /* The mail page renders a 2-column layout (list left, thread right).
       On mobile, only ONE should be visible at a time. JS toggles a
       body.fk-mail-thread class when an item is opened; until then the
       list is full-width and the thread pane is hidden. */
    body.frank-shell-active .email-list,
    body.frank-shell-active .mail-list {
        width: 100% !important; max-width: 100% !important;
        flex: 1 1 100% !important;
    }
    body.frank-shell-active .email-thread,
    body.frank-shell-active .mail-thread,
    body.frank-shell-active .email-detail {
        display: none !important;
    }
    body.fk-mail-thread .email-list,
    body.fk-mail-thread .mail-list { display: none !important; }
    body.fk-mail-thread .email-thread,
    body.fk-mail-thread .mail-thread,
    body.fk-mail-thread .email-detail {
        display: flex !important; width: 100% !important;
    }
    /* Bigger tap targets on mail rows */
    .email-row, .mail-row, .email-list-row { min-height: 64px !important; padding: 12px 14px !important; }
}

/* ── Section transition — fade-in when nav changes ───────────── */
@media (max-width: 720px), (max-height: 500px) and (orientation: landscape) {
    body.frank-shell-active .fk-main-body > * {
        animation: fk-section-in 0.28s cubic-bezier(0.20, 0.70, 0.25, 1) backwards;
    }
}
@keyframes fk-section-in {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* ── Reduced-motion respect — kill all decorative animations ──── */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.001ms !important;
    }
    body.frank-shell-active .fk-main::before,
    body.frank-shell-active .fk-main::after,
    .bp-glow, .fq-glow {
        animation: none !important;
    }
}

/* ── Skeleton loader — projects + mail rows ───────────────────── */
.fk-skeleton {
    background: linear-gradient(90deg,
        rgba(255,255,255,0.04) 0%,
        rgba(125,174,255,0.10) 50%,
        rgba(255,255,255,0.04) 100%);
    background-size: 200% 100%;
    animation: fk-skel-shimmer 1.4s ease-in-out infinite;
    border-radius: 8px;
}
@keyframes fk-skel-shimmer {
    0%   { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}
@media (prefers-reduced-motion: reduce) {
    .fk-skeleton { animation: none !important; }
}

/* ── Profile/Settings mobile — full-width cards ──────────────── */
@media (max-width: 720px), (max-height: 500px) and (orientation: landscape) {
    body.frank-shell-active .settings-page,
    body.frank-shell-active .profile-page,
    body.frank-shell-active .frank-hub {
        padding: 12px !important;
    }
    body.frank-shell-active .settings-card,
    body.frank-shell-active .profile-card,
    body.frank-shell-active .frank-hub-card {
        width: 100% !important;
        margin: 0 0 12px 0 !important;
        padding: 16px !important;
    }
}

/* ── build_plan card mobile — compact-by-default ─────────────── */
@media (max-width: 720px), (max-height: 500px) and (orientation: landscape) {
    .bp-phases { padding: 0 14px 4px; }
    .bp-phases::before { left: 25px; }
    /* Compact: collapse all phases except active. Tap card head to toggle. */
    .bp-card[data-bp-compact="true"] .bp-phase:not(.bp-phase-active) {
        display: none;
    }
    .bp-card[data-bp-compact="true"] .bp-progress {
        margin: 4px 14px 12px;
    }
    .bp-card[data-bp-compact="true"]::after {
        content: 'Tap to expand →';
        display: block;
        text-align: center;
        font-size: 10px;
        color: rgba(125,174,255,0.65);
        letter-spacing: 0.10em; text-transform: uppercase;
        padding: 8px;
        border-top: 1px solid rgba(255,255,255,0.04);
    }
    .bp-head { padding: 14px 16px 10px; cursor: pointer; }
    .bp-foot { padding: 12px 14px 14px; }
}
.fk-mtab {
    flex: 1; min-width: 0;
    display: flex; flex-direction: column;
    align-items: center; justify-content: center;
    gap: 3px; padding: 4px 2px;
    background: transparent; border: none; cursor: pointer;
    color: rgba(232, 236, 245, 0.55);
    font-family: 'Inter', system-ui, sans-serif;
    font-size: 10px; font-weight: 600;
    letter-spacing: 0.04em;
    transition: color 0.18s ease-out, transform 0.12s ease-out;
    -webkit-tap-highlight-color: transparent;
    position: relative;
}
.fk-mtab:active { transform: scale(0.95); }
.fk-mtab svg { width: 22px; height: 22px; stroke-width: 1.7; flex-shrink: 0; }
.fk-mtab .fk-mtab-label { font-size: 10px; line-height: 1; }
.fk-mtab.active {
    color: #fff;
}
.fk-mtab.active::before {
    content: ''; position: absolute; top: 0; left: 22%; right: 22%; height: 2px;
    background: linear-gradient(90deg, transparent, #7daeff, #bd7aff, transparent);
    border-radius: 2px;
    box-shadow: 0 0 12px rgba(125, 174, 255, 0.85);
    animation: fk-mtab-glow 0.4s ease-out;
}
@keyframes fk-mtab-glow {
    from { transform: scaleX(0.3); opacity: 0.4; }
    to   { transform: scaleX(1);   opacity: 1; }
}
.fk-mtab-badge {
    position: absolute; top: 4px; right: calc(50% - 18px);
    min-width: 14px; height: 14px; padding: 0 4px;
    background: linear-gradient(135deg, #ff5566, #ff8a44);
    color: #fff; font-size: 9px; font-weight: 800;
    line-height: 14px; text-align: center;
    border-radius: 999px;
    box-shadow: 0 0 8px rgba(255, 85, 102, 0.55);
}

/* ═════════════════════════════════════════════════════════════════
   MOBILE CRITICAL FIXES — May 11 audit (the user's reported breakage)
   ═════════════════════════════════════════════════════════════════
   Root cause #1: body.fk-fullview-mode/.fk-workspace-mode rules at
   the top of the file unconditionally set the shell to "240px 1fr".
   On a 390px viewport that leaves ~120px for actual content. Mail,
   Hivemind, Cloud, Hosting, Kalender, Einstellungen all squeezed.
   The 720px @media block sets the shell to "1fr" but loses the
   specificity fight because `body.fk-*-mode .fk-shell` has +1 class
   weight. The override below is same-specificity but later in
   cascade — wins. No !important shouting-match.
   ───────────────────────────────────────────────────────────────── */
@media (max-width: 720px), (max-height: 500px) and (orientation: landscape) {
    body.fk-fullview-mode .fk-shell,
    body.fk-workspace-mode .fk-shell {
        grid-template-columns: 1fr;
    }

    /* Mail mobile — kill the desktop 3-column grid (160 + 200 + 300
       = 660px) injected as inline CSS from mail.js. Single column
       showing only the list by default; when a thread opens (mail.js
       toggles body.fk-mail-thread), swap to the reader. ID selector
       beats `.proj-main .email-layout`. */
    body.frank-shell-active #proj-main .email-layout {
        grid-template-columns: 1fr !important;
        grid-template-rows: 1fr !important;
        min-height: calc(100vh - 80px - 64px) !important;
    }
    body.frank-shell-active #proj-main .email-sidebar { display: none !important; }
    body.frank-shell-active #proj-main .email-list { display: flex !important; }
    body.frank-shell-active #proj-main .email-reader { display: none !important; }
    body.fk-mail-thread #proj-main .email-list { display: none !important; }
    body.fk-mail-thread #proj-main .email-reader { display: flex !important; }

    /* Mail reader on mobile gets a back button that mail.js injects;
       give it room at top + tap-target sizing. */
    .mail-mobile-back {
        display: none;
        align-items: center; gap: 6px;
        background: rgba(255,255,255,0.06);
        border: 1px solid rgba(255,255,255,0.10);
        color: rgba(232,236,245,0.85);
        padding: 8px 12px; border-radius: 10px;
        font-size: 12px; cursor: pointer;
        margin: 8px 0 6px 8px;
        min-height: 36px;
    }
    body.fk-mail-thread .mail-mobile-back { display: inline-flex; }
    .mail-mobile-back:active { transform: scale(0.97); }

    /* Hivemind — once the shell grid is fixed, the container takes
       full width, but tailscale.js places the SVG inside a fixed-size
       canvas. Force the inner canvas / svg / Three.js mount to scale
       so the dot doesn't sit in a vast black void. */
    body.frank-shell-active .ts-hivemind,
    body.frank-shell-active .ts-hivemind > * {
        width: 100% !important;
        max-width: 100% !important;
        box-sizing: border-box;
    }
    body.frank-shell-active .ts-hivemind canvas,
    body.frank-shell-active .ts-viz canvas {
        width: 100% !important;
        height: 320px !important;
        max-width: 100% !important;
        display: block;
    }
    /* Make ts-viz a stable, non-collapsing block on mobile so the
       Three.js renderer gets real clientHeight to size against. */
    body.frank-shell-active .ts-viz {
        flex: 0 0 auto !important;
        height: 320px !important;
        min-height: 320px !important;
        width: 100% !important;
    }
    body.frank-shell-active .ts-body {
        flex-direction: column !important;
        overflow-y: auto !important;
    }
    body.frank-shell-active .ts-side {
        width: 100% !important;
        max-height: none !important;
        border-left: none !important;
        border-top: 1px solid rgba(255,255,255,0.06);
    }
    /* Topbar: title + stats + killswitch row was 3 horizontal slots —
       on a 360px screen they overlap. Stack stats below the title and
       let killswitch wrap. */
    body.frank-shell-active .ts-topbar {
        flex-direction: column !important;
        align-items: stretch !important;
        gap: 8px !important;
        padding: 10px 12px !important;
    }
    body.frank-shell-active .ts-stats {
        flex-wrap: wrap !important;
        gap: 4px 10px !important;
        font-size: 11px !important;
    }
    body.frank-shell-active .ts-killswitch {
        display: flex !important;
        flex-wrap: wrap !important;
        gap: 6px !important;
    }
    body.frank-shell-active .ts-killswitch button {
        flex: 1 1 auto;
        min-height: 36px;
        padding: 6px 10px !important;
        font-size: 11px !important;
    }
    body.frank-shell-active .ts-title h1 {
        font-size: 18px !important;
    }

    /* Composer — must sit above the 60px bottom-tab-bar plus safe-area.
       Without this the send button gets visually clipped by the tab
       bar even though tap still works. When the keyboard opens the
       tabs slide away and the composer rides --fk-kb-offset.
       Real composer DOM classes: .mfv-inputbar (master Frank textarea
       row) + .proj-chat-input-wrap (per-project workspace) +
       .mk-chat-input-wrap (mini-chat dropdowns). */
    body.frank-shell-active:not(.fk-kb-open) #proj-main .mfv-inputbar,
    body.frank-shell-active:not(.fk-kb-open) #proj-main .proj-chat-input-wrap,
    body.frank-shell-active:not(.fk-kb-open) #proj-main .proj-approval-input-wrap,
    body.frank-shell-active:not(.fk-kb-open) #proj-main .mk-chat-input-wrap {
        margin-bottom: calc(72px + env(safe-area-inset-bottom, 0px)) !important;
    }
    /* When keyboard opens (fk-kb-open), the bottom-nav slides away and
       --fk-kb-offset gets set; let the composer follow the keyboard. */
    body.frank-shell-active.fk-kb-open #proj-main .mfv-inputbar {
        margin-bottom: var(--fk-kb-offset, 0px) !important;
    }

    /* Header — kill scroll-down + notification-bell icons on mobile.
       Search + settings stay. The bell content surfaces inside the
       settings/profile view anyway. */
    body.frank-shell-active #fk-tool-scroll,
    body.frank-shell-active #fk-tool-bell {
        display: none !important;
    }

    /* Cookie banner — was overlapping the F.R.A.N.K. brand mark and
       the icon row on small screens. Drop z-index below the header
       (still on top of body), reduce max-height, and lift up slightly
       so the rounded shell corner remains visible. */
    .fk-cookie-banner {
        z-index: 9000 !important;
        max-height: 88px !important;
        max-width: calc(100vw - 16px) !important;
        font-size: 11px !important;
        line-height: 1.3 !important;
        padding: 6px 10px !important;
    }
    .fk-cookie-banner button {
        font-size: 11px !important;
        padding: 4px 8px !important;
        min-height: 30px !important;
    }

    /* ADMIN pill — move to bottom-LEFT on mobile so it doesn't sit
       on top of the send button + lower opacity so it doesn't fight
       descriptive content. Tap still works. */
    body.frank-shell-active #admin-log-btn {
        right: auto !important;
        left: 12px !important;
        bottom: calc(76px + env(safe-area-inset-bottom, 0px)) !important;
        opacity: 0.38;
    }

    /* Projects mobile list view — when dashboard.js shows the
       project-grid view on mobile (instead of the desktop sidebar
       expand), render the tiles in a clean stacked list. */
    body.fk-mobile-projects-view #proj-list {
        display: flex !important;
        flex-direction: column !important;
        gap: 8px !important;
        padding: 14px !important;
    }
    body.fk-mobile-projects-view #proj-list .proj-item {
        width: 100% !important;
        min-height: 64px !important;
        padding: 14px 16px !important;
    }
    body.fk-mobile-projects-view #fk-main .fk-main-body {
        overflow-y: auto !important;
    }
    /* Mobile-projects view: top-bar with "+ Neues Projekt" CTA + back
       to chat. Generated by dashboard.js — see _renderMobileProjects. */
    .fk-mobile-projects-bar {
        display: none;
        align-items: center; gap: 10px;
        padding: 10px 14px;
        border-bottom: 1px solid var(--panel-border);
    }
    body.fk-mobile-projects-view .fk-mobile-projects-bar { display: flex; }
    .fk-mobile-projects-bar .fk-mobile-projects-new {
        flex: 1;
        background: linear-gradient(135deg, rgba(61,111,255,0.20), rgba(139,92,246,0.22), rgba(236,72,153,0.20));
        border: 1px solid rgba(155,108,255,0.45);
        color: #cfd7ff;
        padding: 12px 14px; border-radius: 12px;
        font-size: 13px; font-weight: 600;
        display: flex; align-items: center; justify-content: center; gap: 8px;
        cursor: pointer; min-height: 44px;
    }

    /* ═════════════════════════════════════════════════════════════
       MOBILE POLISH — Round 2 (May 11 deep audit)
       ═════════════════════════════════════════════════════════════ */

    /* Workspace mode: drop the duplicate F.R.A.N.K. header — the
       workspace has its own .proj-topbar with the project name + actions.
       Reclaims 65px of vertical real estate on small screens. */
    body.fk-workspace-mode .fk-main-header {
        display: none !important;
    }

    /* Header icon tap targets: 36×44 → 44×44 (Apple HIG) */
    body.frank-shell-active .fk-main-tools .fk-main-icon-btn {
        width: 44px !important;
        height: 44px !important;
    }

    /* Workspace tabs: 39px tall → 44px. Also pin sticky + horizontal
       scroll with snap so the 11 tabs don't collapse off-screen. */
    body.frank-shell-active .proj-tab-bar {
        scroll-snap-type: x mandatory;
        -webkit-overflow-scrolling: touch;
    }
    body.frank-shell-active .proj-tab {
        min-height: 44px !important;
        padding: 10px 14px !important;
        scroll-snap-align: start;
    }

    /* Workspace composer: same lift as master-chat composer, plus
       wrapper padding so the chip row + composer don't sit on the
       bottom-tab-bar. */
    body.frank-shell-active:not(.fk-kb-open).fk-workspace-mode .proj-chat-input-wrap,
    body.frank-shell-active:not(.fk-kb-open).fk-workspace-mode #proj-chat-input,
    body.frank-shell-active:not(.fk-kb-open).fk-workspace-mode .proj-approval-input-wrap {
        margin-bottom: calc(72px + env(safe-area-inset-bottom, 0px)) !important;
    }
    /* Workspace tab content padding so its scrollable area doesn't
       hide its last item behind the composer or tab bar. */
    body.frank-shell-active.fk-workspace-mode .proj-tab-content {
        padding-bottom: 24px !important;
    }

    /* Action-chip row in workspace chat — horizontal scroll with
       snap instead of overflow off the right edge. */
    body.frank-shell-active .proj-msg-chips,
    body.frank-shell-active .proj-action-chips,
    body.frank-shell-active .proj-chat-quick-actions {
        overflow-x: auto !important;
        overflow-y: hidden !important;
        white-space: nowrap !important;
        flex-wrap: nowrap !important;
        scroll-snap-type: x proximity;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
    }
    body.frank-shell-active .proj-msg-chips::-webkit-scrollbar,
    body.frank-shell-active .proj-action-chips::-webkit-scrollbar,
    body.frank-shell-active .proj-chat-quick-actions::-webkit-scrollbar { display: none; }

    /* Per-message thumbs/regen/fork buttons: 26×44 → 36×44 + tighter
       padding so the row doesn't push the message body around. */
    body.frank-shell-active .proj-msg-action {
        min-width: 36px !important;
        min-height: 36px !important;
        padding: 4px !important;
    }

    /* Mail mobile back button — compact pill (was full-width 356px).
       Self-aligned left + chevron-only style. */
    .mail-mobile-back {
        align-self: flex-start !important;
        width: auto !important;
        min-width: 84px;
        padding: 8px 14px 8px 10px !important;
        font-size: 13px !important;
        font-weight: 600;
        background: rgba(125,174,255,0.10) !important;
        border: 1px solid rgba(125,174,255,0.25) !important;
        color: #cfd7ff !important;
        border-radius: 999px !important;
        margin: 12px 0 6px 12px !important;
    }
    .mail-mobile-back:active {
        background: rgba(125,174,255,0.18) !important;
        transform: scale(0.97);
    }

    /* Mail reader body padding-bottom — currently the body scrolls
       but the last lines get clipped by the bottom-tab-bar. */
    body.frank-shell-active.fk-mail-thread #proj-main .email-reader {
        padding-bottom: calc(74px + env(safe-area-inset-bottom, 0px)) !important;
    }
    /* Mail Reply form — Send button must clear the tab bar too. */
    body.frank-shell-active #proj-main .email-compose-form,
    body.frank-shell-active #proj-main .email-compose-actions {
        padding-bottom: calc(74px + env(safe-area-inset-bottom, 0px)) !important;
    }

    /* Mail inbox: same lift so the last few emails don't sit under
       the tab-bar. */
    body.frank-shell-active:not(.fk-mail-thread) #proj-main .email-items {
        padding-bottom: calc(74px + env(safe-area-inset-bottom, 0px)) !important;
    }

    /* Hivemind: kill the touch-irrelevant control hint on the viz
       overlay (drag/scroll/dblclick don't apply on touch). The hivemind
       swarm class names are .hsw-hint + .hsw-fps (NOT .ts-viz-hint —
       the desktop hint is from a different code path). */
    body.frank-shell-active .ts-viz-hint,
    body.frank-shell-active .ts-fps,
    body.frank-shell-active .hsw-hint,
    body.frank-shell-active .hsw-fps {
        display: none !important;
    }

    /* Hivemind topbar buttons: 36px tall → 44px so users can actually
       tap "Open Terminal", "STOP", "Resume" without missing. */
    body.frank-shell-active .ts-killswitch button {
        min-height: 44px !important;
        padding: 10px 12px !important;
    }

    /* Hivemind viz height — 360px on mobile so the boid cluster reads
       at a glance (combined with hivemind-swarm.js camDist=75 on
       mobile = ~40% closer view, boids appear 1.6× larger). */
    body.frank-shell-active .ts-viz,
    body.frank-shell-active .ts-viz canvas {
        height: 360px !important;
        min-height: 360px !important;
    }
    /* Subtle structured background behind the canvas: a soft radial
       gradient + dot-grid pattern. The Three.js renderer paints on top,
       and a slightly lighter base color means the void around boids
       reads less like an empty black box. */
    body.frank-shell-active .ts-viz {
        background:
            radial-gradient(ellipse at center,
                rgba(125, 174, 255, 0.06) 0%,
                rgba(70, 100, 180, 0.025) 40%,
                rgba(10, 14, 28, 0) 75%),
            radial-gradient(circle at 20% 25%, rgba(155,108,255,0.04), transparent 35%),
            radial-gradient(circle at 80% 70%, rgba(0,229,255,0.04), transparent 35%),
            linear-gradient(180deg, #0a1428 0%, #060b1c 100%) !important;
        position: relative !important;
    }
    body.frank-shell-active .ts-viz::before {
        content: '';
        position: absolute; inset: 0;
        background-image: radial-gradient(circle at center, rgba(125, 174, 255, 0.16) 0.7px, transparent 1.1px);
        background-size: 22px 22px;
        background-position: 0 0;
        opacity: 0.45;
        pointer-events: none;
        mix-blend-mode: screen;
    }
    body.frank-shell-active .ts-viz canvas {
        position: relative;
        z-index: 1;
        background: transparent !important;
    }

    /* Hivemind side panel: scrollable inside the page (it can be 2000+
       px of content with 30+ download buttons + library tags). Tighter
       gap and padding so it doesn't visually drag forever. */
    body.frank-shell-active .ts-body {
        height: 100% !important;
        overflow-y: auto !important;
        -webkit-overflow-scrolling: touch;
        padding-bottom: calc(74px + env(safe-area-inset-bottom, 0px)) !important;
    }
    body.frank-shell-active .ts-side {
        padding: 10px 12px !important;
        gap: 10px !important;
    }
    body.frank-shell-active .ts-card,
    body.frank-shell-active .ts-explain {
        padding: 14px !important;
    }
    /* Hivemind library tags: 26-43px wide → 44px min via padding. */
    body.frank-shell-active .ts-lib-tag {
        min-width: 44px !important;
        min-height: 36px !important;
        padding: 6px 12px !important;
    }
    /* Hivemind download/setup buttons: 34px tall → 44px so they're
       tappable on the bridge-setup card. */
    body.frank-shell-active .ts-dl-btn,
    body.frank-shell-active .ts-add-form input,
    body.frank-shell-active .ts-add-form button,
    body.frank-shell-active input#ts-add-label,
    body.frank-shell-active input#ts-add-key,
    body.frank-shell-active input.ts-lib-search,
    body.frank-shell-active .ts-icon-btn {
        min-height: 44px !important;
        min-width: 44px !important;
    }
    /* But the conn icon buttons can stay slim — they're inline rows */
    body.frank-shell-active .ts-icon-btn {
        min-width: 36px !important;
    }

    /* Profile/Settings: ensure the scroll container can actually
       scroll all cards (was sometimes truncated to fold height). */
    body.frank-shell-active #proj-main .af-settings,
    body.frank-shell-active #proj-main .afset-container,
    body.frank-shell-active #proj-main .proj-settings-panel,
    body.frank-shell-active #proj-main .proj-settings-body {
        height: auto !important;
        min-height: 100% !important;
        overflow-y: auto !important;
        -webkit-overflow-scrolling: touch;
        padding-bottom: calc(80px + env(safe-area-inset-bottom, 0px)) !important;
    }
    body.frank-shell-active #proj-main .proj-settings-body {
        padding: 12px 14px calc(80px + env(safe-area-inset-bottom, 0px)) !important;
    }

    /* Settings cards — compact mobile spec. Was wasting vertical space:
       Plan card showed just "ADMIN" with 100+ px of padding, Frank Engine
       had 4 cores stacked vertically taking 240px. Tighter padding +
       grid layout. (May 11 feedback.) */
    body.frank-shell-active .afset-card,
    body.frank-shell-active .pset-card {
        padding: 12px 14px !important;
        margin-bottom: 10px !important;
        border-radius: 12px !important;
    }
    body.frank-shell-active .afset-card-head,
    body.frank-shell-active .pset-card-header {
        margin-bottom: 6px !important;
        gap: 8px !important;
    }
    body.frank-shell-active .afset-card-head h2,
    body.frank-shell-active .pset-card-header h3 {
        font-size: 13px !important;
    }
    body.frank-shell-active .afset-hint,
    body.frank-shell-active .pset-hint {
        font-size: 11.5px !important;
        line-height: 1.4 !important;
        margin: 0 0 6px !important;
    }
    body.frank-shell-active .afset-card button,
    body.frank-shell-active .pset-card button,
    body.frank-shell-active .afset-btn-danger,
    body.frank-shell-active .pset-btn-danger {
        min-height: 40px !important;
    }
    /* Frank Engine cores: stack in 2 columns on mobile so the card is
       half-height. Each core line tight. */
    body.frank-shell-active .afset-engine-cores,
    body.frank-shell-active .pset-card .afset-engine-cores,
    body.frank-shell-active .proj-settings-body div[style*="grid-template-columns:repeat(auto-fill,minmax(150px"],
    body.frank-shell-active .proj-settings-body div[style*="grid-template-columns:repeat(auto-fill,minmax(160px"] {
        grid-template-columns: 1fr 1fr !important;
        gap: 6px !important;
        margin-top: 8px !important;
    }
    body.frank-shell-active .afset-engine-core,
    body.frank-shell-active .proj-settings-body div[style*="background:rgba(0,229,255,0.03)"] {
        font-size: 10px !important;
        padding: 6px 8px !important;
    }
    body.frank-shell-active .afset-engine-badge {
        font-size: 9px !important;
        padding: 2px 6px !important;
    }
    /* Plan + Usage 2-column row — same height, compact. The plan card
       was rendering tall with just "ADMIN" — pin the height so it
       matches Usage and doesn't dwarf the page. */
    body.frank-shell-active .afset-grid-2,
    body.frank-shell-active .pset-row-2col {
        grid-template-columns: 1fr 1fr !important;
        gap: 10px !important;
        align-items: stretch;
    }
    body.frank-shell-active .afset-plan-badge,
    body.frank-shell-active .pset-plan-badge {
        font-size: 18px !important;
        margin: 0 !important;
        padding-top: 2px;
    }
    body.frank-shell-active .afset-usage,
    body.frank-shell-active #settings-usage {
        font-size: 13px !important;
        line-height: 1.4 !important;
    }
    /* Language buttons stay inline on mobile (1 row of 2) */
    body.frank-shell-active .afset-lang-btn {
        flex: 1;
        font-size: 12px !important;
        padding: 8px 10px !important;
        min-height: 38px;
    }
    /* Admin + Danger Zone buttons: line them up tight */
    body.frank-shell-active .afset-btn-admin,
    body.frank-shell-active .pset-btn-admin {
        padding: 9px 14px !important;
        min-height: 40px !important;
        font-size: 12.5px !important;
    }

    /* Workspace topbar: project title + folder + kebab — pad the
       kebab/folder buttons up to 44px so they're tap-friendly. */
    body.frank-shell-active .proj-topbar button,
    body.frank-shell-active .proj-topbar .proj-folder-btn,
    body.frank-shell-active .proj-topbar .proj-kebab,
    body.frank-shell-active .proj-topbar .proj-menu-btn {
        min-width: 44px !important;
        min-height: 44px !important;
    }

    /* Email items: 67px tall already great. Just polish the unread
       indicator and prevent left-edge clip. */
    body.frank-shell-active .email-item {
        padding: 12px 14px !important;
    }
    body.frank-shell-active .email-item.unread::before {
        left: 6px !important;
    }

    /* Mail action buttons row: when wrapping to 2 rows, make sure
       both rows are balanced (currently first row has 3, second has 3
       but Auto/Spam/Delete differ in width). Tighter buttons. */
    /* Mail action buttons — compact horizontal row, single-line, not
       a tall 2×3 grid. The email body below is the visual centre, so
       the actions sit as a slim toolbar above it. (May 11 feedback —
       previously the buttons ate too much vertical space and the
       aspect ratio felt off.) */
    body.frank-shell-active .email-read-actions {
        gap: 4px !important;
        padding: 6px 10px !important;
        flex-wrap: wrap !important;
        align-items: center;
    }
    body.frank-shell-active .email-action-btn {
        flex: 1 1 auto !important;
        min-height: 34px !important;
        height: 34px !important;
        padding: 0 10px !important;
        font-size: 11px !important;
        font-weight: 600 !important;
        border-radius: 8px !important;
        gap: 4px !important;
        justify-content: center;
        white-space: nowrap;
    }
    body.frank-shell-active .email-action-btn svg {
        width: 12px !important;
        height: 12px !important;
    }
    /* Primary actions (AI Reply, Reply, Forward) on row 1; secondary
       (Auto, Spam, Delete) on row 2 — give row 1 a bit more weight. */
    body.frank-shell-active .email-action-ai-reply,
    body.frank-shell-active .email-action-reply,
    body.frank-shell-active .email-action-compose {
        flex: 1 1 30% !important;
    }
    body.frank-shell-active .email-action-auto-reply,
    body.frank-shell-active .email-action-spam,
    body.frank-shell-active .email-action-delete {
        flex: 1 1 30% !important;
    }
    /* Email body block — bigger font + breathing room so it reads as
       the visual centre of the screen instead of squished. */
    body.frank-shell-active.fk-mail-thread #proj-main .email-reader {
        padding: 12px 14px calc(74px + env(safe-area-inset-bottom, 0px)) !important;
    }
    body.frank-shell-active .email-read-body,
    body.frank-shell-active .email-body {
        font-size: 14.5px !important;
        line-height: 1.55 !important;
        color: rgba(232,236,245,0.94) !important;
        padding-top: 8px !important;
    }
    /* Header / meta block tighter — subject still prominent but FROM/TO/DATE
       compressed so the body takes more of the fold. */
    body.frank-shell-active .email-read-subject {
        font-size: 16px !important;
        line-height: 1.35 !important;
        margin-bottom: 8px !important;
    }
    body.frank-shell-active .email-read-meta {
        font-size: 11px !important;
        line-height: 1.4 !important;
        gap: 1px !important;
        margin-bottom: 4px !important;
        opacity: 0.7;
    }
    body.frank-shell-active .email-meta-label {
        font-size: 10px !important;
        min-width: 36px !important;
    }
    body.frank-shell-active .email-read-header {
        padding: 8px 14px 6px !important;
        border-bottom: 1px solid rgba(255,255,255,0.05);
        margin-bottom: 6px;
    }
    /* The "spacer flex:1" in the email actions row is no-op now that
       we wrap; squash it so it doesn't take a slot. */
    body.frank-shell-active .email-read-actions > div[style*="flex:1"] {
        display: none !important;
    }

    /* Reply panel: full-width fields, real tap targets, send not
       hidden behind tab bar. */
    body.frank-shell-active .email-compose-form input,
    body.frank-shell-active .email-compose-form textarea {
        min-height: 44px !important;
        font-size: 14px !important;
        padding: 10px !important;
    }
    body.frank-shell-active .email-compose-form .email-textarea {
        min-height: 140px !important;
    }
    body.frank-shell-active .email-compose-form button {
        min-height: 44px !important;
    }
}


/* ── Embedding existing pages inside fk-main-body ──────────── */
/* Many sub-pages render with their own backgrounds — strip them */
.fk-main-body .proj-page,
.fk-main-body .page,
.fk-main-body .frank-hub { background: transparent !important; }

/* Hide the OLD inline sidebar (proj-sidebar) when new shell active.
   #admin-log-btn intentionally NOT hidden here — it's restyled above
   into the bottom-right glassy admin pill. Hiding it broke the admin
   workflow (Apr 28 regression). */
body.frank-shell-active .proj-sidebar,
body.frank-shell-active .proj-sidebar-overlay { display: none !important; }
body.frank-shell-active .proj-page { display: block !important; height: 100% !important; }
body.frank-shell-active .proj-main { padding: 0 !important; height: 100% !important; }

/* ── Cards rendered inside fk-main-body inherit lighter look ── */
.fk-main-body .frank-card,
.fk-main-body .proj-onboard-card { background: rgba(20,24,48,0.78); }

/* ── Re-style projects.js #proj-list rows when inside fk-chats ── */
body.frank-shell-active #proj-list { padding: 0; }
body.frank-shell-active #proj-list .proj-item {
    display: flex; align-items: flex-start; gap: 10px;
    padding: 12px 14px; margin-bottom: 6px;
    background: rgba(255,255,255,0.03);
    border: 1px solid var(--panel-border);
    border-left: none;
    border-radius: 14px;
    cursor: pointer;
    transition: background 0.15s, border-color 0.15s;
    position: relative;
}
body.frank-shell-active #proj-list .proj-item:hover {
    background: rgba(255,255,255,0.06);
    border-color: var(--panel-border-bright);
}
body.frank-shell-active #proj-list .proj-item.active {
    background: var(--shell-grad-soft);
    border-color: rgba(111,140,255,0.32);
    box-shadow: 0 4px 14px rgba(111,140,255,0.18);
}
body.frank-shell-active #proj-list .proj-item.active::before {
    content: ''; position: absolute; left: 0; top: 12px; bottom: 12px;
    width: 3px; background: var(--shell-grad); border-radius: 0 3px 3px 0;
}
body.frank-shell-active #proj-list .proj-item-dot {
    width: 6px; height: 6px; margin-top: 6px; flex-shrink: 0;
    background: var(--shell-text-faint);
    box-shadow: none;
}
body.frank-shell-active #proj-list .proj-item.active .proj-item-dot {
    background: var(--shell-accent-3);
    box-shadow: 0 0 10px rgba(77,214,255,0.6);
}
body.frank-shell-active #proj-list .proj-item-name {
    font-size: 13px; font-weight: 600; color: #fff;
    font-family: 'Inter', system-ui, sans-serif;
    letter-spacing: 0;
}
body.frank-shell-active #proj-list .proj-item-meta {
    font-size: 11px; color: var(--shell-text-dim);
    margin-top: 3px; line-height: 1.4;
    font-family: 'Inter', system-ui, sans-serif;
}
body.frank-shell-active #proj-list .proj-item.active .proj-item-name { color: #fff; }
body.frank-shell-active #proj-list .proj-progress-bar {
    background: rgba(255,255,255,0.06);
    margin-top: 6px;
}
body.frank-shell-active #proj-list .proj-progress-fill {
    background: var(--shell-grad) !important;
}
body.frank-shell-active #proj-list .proj-empty-list {
    color: var(--shell-text-faint);
    font-size: 12px;
    padding: 24px 12px; text-align: center;
}

/* Hide the OLD project-credit-/key-status block since we have token-card now */
body.frank-shell-active .proj-key-status,
body.frank-shell-active #proj-key-status { display: none !important; }
body.frank-shell-active #proj-token-bar-section { display: none !important; }

/* Inline render of mail/welcome inside the new shell — strip its own padding */
body.frank-shell-active #proj-main .proj-welcome,
body.frank-shell-active #proj-main .proj-onboard,
body.frank-shell-active #proj-main .proj-workspace { background: transparent !important; }
body.frank-shell-active #proj-main { padding: 0 !important; }

/* Master-Frank chat view inside shell — keep messages readable */
body.frank-shell-active #proj-main .proj-msg,
body.frank-shell-active #proj-main .frank-msg { font-family: 'Inter', system-ui, sans-serif; }

/* ── Chat avatars — circular profile photos (mockup #10, #11) ── */
body.frank-shell-active #proj-main .proj-msg-avatar {
    width: 38px !important;
    height: 38px !important;
    border-radius: 50% !important;
    overflow: hidden;
    background: rgba(255,255,255,0.06);
    font-size: 0 !important;            /* hide ●/◇/etc text content */
    color: transparent !important;
    border: 1px solid rgba(255,255,255,0.08);
    flex-shrink: 0;
    background-size: cover;
    background-position: center;
    box-shadow: 0 2px 6px rgba(0,0,0,0.3);
}
/* Frank avatar (assistant) — circular mascot photo */
body.frank-shell-active #proj-main .proj-msg-assistant .proj-msg-avatar {
    background-image: url('/static/assets/mascot.jpg');
    background-color: #1a1f2e;
}
/* User avatar — light-violet silhouette (matches mockup #12/#13) */
body.frank-shell-active #proj-main .proj-msg-user .proj-msg-avatar {
    background-color: #b4bedf;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'><path fill='%23ffffff' d='M32 9c-7 0-12 5.5-12 12.5S25 34 32 34s12-5.5 12-12.5S39 9 32 9zm0 28c-9 0-22 4-22 13v3c0 1.1.9 2 2 2h40c1.1 0 2-.9 2-2v-3c0-9-13-13-22-13z'/></svg>");
}
/* Default Frank avatar — applies to ALL .proj-msg-avatar in the shell so a
   bare .proj-msg without role-tagging still shows the mascot. The explicit
   .proj-msg-user override below wins via natural cascade order, no :not()
   trick needed (which inflated specificity and broke the user case). */
body.frank-shell-active .proj-msg .proj-msg-avatar {
    background: #1a1f2e url('/static/assets/mascot.jpg') center/cover no-repeat !important;
}
body.frank-shell-active .proj-msg-user .proj-msg-avatar,
body.frank-shell-active .mfv-chat .proj-msg-user [class*="msg-avatar"],
body.frank-shell-active .mfv-chat .mfv-msg-user [class*="msg-avatar"] {
    background: #b4bedf url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'><path fill='%23ffffff' d='M32 9c-7 0-12 5.5-12 12.5S25 34 32 34s12-5.5 12-12.5S39 9 32 9zm0 28c-9 0-22 4-22 13v3c0 1.1.9 2 2 2h40c1.1 0 2-.9 2-2v-3c0-9-13-13-22-13z'/></svg>") center/cover no-repeat !important;
}

/* Bubble polish to match mockup #11 — beat all legacy assistant/user rules */
body.frank-shell-active .proj-msg-body,
body.frank-shell-active .proj-msg-user .proj-msg-body,
body.frank-shell-active .proj-msg-assistant .proj-msg-body,
body.frank-shell-active .proj-msg-file .proj-msg-body {
    background: rgba(13, 17, 36, 0.72) !important;
    border: 1px solid rgba(255,255,255,0.07) !important;
    border-radius: 16px !important;
    padding: 14px 18px !important;
    max-width: 720px !important;
    backdrop-filter: blur(10px);
    line-height: 1.55;
    color: #e8ecf5 !important;
}
body.frank-shell-active .proj-msg-user .proj-msg-body {
    background: rgba(13, 17, 36, 0.55) !important;
    border-radius: 16px 16px 4px 16px !important;
}
body.frank-shell-active .proj-msg-role {
    color: var(--shell-accent-cyan) !important;
    font-weight: 800 !important;
    letter-spacing: 0.06em !important;
    font-size: 12px !important;
    margin-bottom: 4px !important;
}
body.frank-shell-active .proj-msg-user .proj-msg-role { color: #fff !important; }
body.frank-shell-active .proj-msg-text,
body.frank-shell-active .proj-msg-text * {
    color: #e8ecf5 !important;
    font-size: 13.5px !important;
    line-height: 1.6 !important;
    font-family: 'Inter', system-ui, sans-serif !important;
}
body.frank-shell-active .proj-msg-text a { color: var(--shell-accent-cyan) !important; }

/* Compose: scrollbars in the main pane should match the shell */
body.frank-shell-active #proj-main::-webkit-scrollbar { width: 6px; }
body.frank-shell-active #proj-main::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.08); border-radius: 3px; }

/* When projects.js renders the welcome (master-frank chat), it injects
   its own mobile bar — hide it inside our shell since we have the
   header. */
body.frank-shell-active .proj-mobile-welcome-bar { display: none !important; }

/* Old per-page sidebars/menus rendered inline (settings, mail) — fit them */
body.frank-shell-active .proj-settings-page,
body.frank-shell-active .proj-mail-page { background: transparent !important; }

/* Restyle `.proj-onboard-card` and templates picker so it works on dark glass bg */
body.frank-shell-active .proj-onboard-card {
    background: rgba(20,24,48,0.85) !important;
    border-color: rgba(255,255,255,0.08) !important;
    border-radius: 18px;
}

/* Lighten emojis used in cards if they show up in the chat — give them
   a subtle backdrop so they're not jarring */
body.frank-shell-active .frank-tools-block { background: rgba(255,255,255,0.03); border-color: var(--panel-border); }

/* The "Du / Administrator" inside our user-card already shows the role,
   so kill the duplicate user plan-pill at the top right (legacy nav). */
body.frank-shell-active .af-user-plan,
body.frank-shell-active #nav-user { display: none !important; }

/* ── Master-Frank inner view: strip its DOUBLE chrome ──────────────
   projects.js's _renderMasterFrankView builds its own CHATS sidebar
   + its own F.R.A.N.K./ONLINE/SCREEN/ÜBER MICH header inside #proj-main.
   In the new shell those slots already exist (left chats pane + main
   header), so we hide the duplicates and let the chat fill the pane. */
body.frank-shell-active .master-frank-view,
body.frank-shell-active .mfv-root {
    background: transparent !important;
    height: 100% !important;
    width: 100% !important;
    display: flex !important;
}
/* Kill the legacy DDOS-terminal white frame, corner brackets, scanline glow */
body.frank-shell-active .mfv-main {
    border: none !important;
    margin: 0 !important;
    background: transparent !important;
    animation: none !important;
    box-shadow: none !important;
}
body.frank-shell-active .mfv-main::before,
body.frank-shell-active .mfv-main::after,
body.frank-shell-active .mfv-corners-bl,
body.frank-shell-active .mfv-corners-br,
body.frank-shell-active .mfv-root::before { display: none !important; content: none !important; }
body.frank-shell-active #master-sessions,
body.frank-shell-active .master-sessions,
body.frank-shell-active .mfv-sessions,
body.frank-shell-active .mfv-sessions-toggle,
body.frank-shell-active .mfv-header { display: none !important; }
body.frank-shell-active .mfv-main {
    width: 100% !important;
    flex: 1 1 auto !important;
    background: transparent !important;
    display: flex !important; flex-direction: column !important;
    min-height: 0;
}
body.frank-shell-active .mfv-stage {
    flex: 1 1 auto !important;
    overflow-y: auto !important;
    padding: 24px 28px !important;
    background: transparent !important;
}
body.frank-shell-active .mfv-stage::-webkit-scrollbar { width: 6px; }
body.frank-shell-active .mfv-stage::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.08); border-radius: 3px; }
body.frank-shell-active .mfv-splash { display: none !important; }

/* ── Daily greeting overlay (once-per-day terminal-eyes splash) ──
   When body.fk-daily-greeting is set, the right pane swaps into a
   "splash mode": eyes + greeting fill the chat area, while the
   composer stays visible at the bottom so the user can start typing
   immediately. Everything else (chat thread, header tabs, share-tab)
   is hidden behind a smooth fade. */
body.fk-daily-greeting.frank-shell-active .mfv-splash {
    display: flex !important;
    position: absolute !important;
    inset: 0 !important;
    z-index: 8;
    align-items: center;
    justify-content: center;
    background: transparent;
    pointer-events: none;     /* mouse passes through to canvas + composer */
    opacity: 1;
    transition: opacity 0.6s ease;
}
body.fk-daily-greeting.frank-shell-active .mfv-splash.faded {
    opacity: 0;
}
body.fk-daily-greeting.frank-shell-active .mfv-splash > * {
    pointer-events: auto;
}
/* Hide chat thread + header tabs while greeting is on screen — but
   smooth-fade them in, not display:none, so they animate cleanly when
   the splash dismisses. */
body.fk-daily-greeting.frank-shell-active #master-chat-msgs,
body.fk-daily-greeting.frank-shell-active .mfv-stage > .mfv-chat,
body.fk-daily-greeting.frank-shell-active .fk-main-header,
body.fk-daily-greeting.frank-shell-active .fk-main-tabs,
body.fk-daily-greeting.frank-shell-active .fk-main-tools,
body.fk-daily-greeting.frank-shell-active .fk-main-titlebar {
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.55s ease;
}
/* When the greeting is dismissed (.fk-daily-greeting class removed),
   the rules above stop applying and the natural styles take over —
   chat fades back in without extra coordination. */
body.fk-daily-greeting.frank-shell-active .mfv-stage {
    /* Make absolute children (.mfv-splash) anchor here */
    position: relative !important;
    /* Hide the chat scroll when in splash-mode — composer is the only
       interactive element until dismissed. */
    overflow: hidden;
}
/* ── Greeting stage: eyes + spruch, nothing else ──────────────── */
body.fk-daily-greeting.frank-shell-active .fk-greeting-stage {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 26px;
    width: 100%;
    max-width: min(620px, 92vw);
    margin: 0 auto;
    padding: 12px 24px;
    pointer-events: auto;
}
body.fk-daily-greeting.frank-shell-active .fk-greeting-eyes {
    width: 100%;
    max-width: 540px;
    /* The face module mounts an inline-block stage; centering happens here. */
    display: flex;
    justify-content: center;
    min-height: 160px;
}
body.fk-daily-greeting.frank-shell-active .fk-greeting-line {
    margin: 0;
    text-align: center;
    /* Match the face's monospace lineage so caption + face read as one
       artefact. SF Mono / Menlo for native feel; Cascadia / JetBrains
       Mono pairs that on Windows / Linux. */
    font-family: 'JetBrains Mono','Cascadia Code','SF Mono','Menlo','Consolas',monospace;
    font-size: clamp(15px, 1.8vw, 19px);
    font-weight: 400;
    line-height: 1.5;
    letter-spacing: 0.01em;
    color: #e6efff;
    text-shadow: 0 0 14px rgba(255,255,255,0.10),
                 0 0 28px rgba(155,108,255,0.18);
    word-wrap: break-word;
    max-width: 92%;
    margin-inline: auto;
    min-height: 1.5em;     /* avoid CLS while the typewriter primes */
}
.fk-greeting-typed { white-space: pre-wrap; }
.fk-greeting-caret {
    display: inline-block;
    margin-left: 2px;
    color: var(--face-tint, #a8ff96);
    text-shadow: 0 0 8px color-mix(in oklab, var(--face-tint, #a8ff96) 60%, transparent);
    animation: fk-caret-blink 1100ms step-end infinite;
}
.fk-greeting-caret-rest {
    animation: fk-caret-blink 1500ms step-end infinite;
}
@keyframes fk-caret-blink {
    0%, 49%   { opacity: 1; }
    50%, 100% { opacity: 0; }
}
/* Subtle fade-in for the whole greeting on first paint */
@keyframes fk-greeting-in {
    from { opacity: 0; transform: translateY(10px); }
    to   { opacity: 1; transform: translateY(0); }
}
body.fk-daily-greeting.frank-shell-active .fk-greeting-stage {
    animation: fk-greeting-in 0.7s cubic-bezier(0.20, 0.70, 0.25, 1) backwards;
}
body.fk-daily-greeting.frank-shell-active .fk-greeting-line {
    animation: fk-greeting-in 0.9s cubic-bezier(0.20, 0.70, 0.25, 1) backwards;
    animation-delay: 0.2s;
}
body.frank-shell-active .mfv-chat {
    background: transparent !important;
    color: #e8ecf5 !important;
}

/* Apr 29 — defensive layout: messages stack vertically, full width.
   Real root cause was an HTML-escape miss in _renderMasterMsg that let
   raw `<div>` from Frank's prose hijack the page DOM (norbert@frank.ink
   session 99, msg #1588). These rules are belt-and-suspenders so a
   stray rogue tag in cached content can't squeeze the chat into a
   narrow column on next paint. */
body.frank-shell-active #master-chat-msgs,
body.frank-shell-active .mfv-chat {
    display: flex !important;
    flex-direction: column !important;
    align-items: stretch !important;
    width: 100% !important;
    min-width: 0;
}
body.frank-shell-active #master-chat-msgs > .proj-msg,
body.frank-shell-active .mfv-chat > .proj-msg,
body.frank-shell-active #master-chat-msgs > .frank-msg,
body.frank-shell-active .mfv-chat > .frank-msg,
body.frank-shell-active #master-chat-msgs > .mfv-msg,
body.frank-shell-active .mfv-chat > .mfv-msg {
    width: 100% !important;
    min-width: 0 !important;
    flex-shrink: 0 !important;
}
body.frank-shell-active .proj-msg-text,
body.frank-shell-active [class*="msg-text"] {
    word-break: normal !important;
    overflow-wrap: anywhere !important;
    min-width: 0 !important;
}

/* ── Chat-pane streaming: kill smooth-scroll + use overflow-anchor
   so the browser handles content-growth without yanking the reader
   off their spot. instant scroll-to-bottom is the streaming path. */
body.frank-shell-active #master-chat-msgs,
body.frank-shell-active .mfv-stage,
body.frank-shell-active .fk-main-body {
    scroll-behavior: auto;
    overflow-anchor: auto;
}
body.frank-shell-active .proj-msg-text .proj-stream-live {
    /* During streaming we render plain text inside this span. After the
       stream ends innerHTML gets replaced with parsed markdown — at
       that point the span is gone. Pre-wrap keeps line breaks intact. */
    white-space: pre-wrap;
    word-break: break-word;
}

/* ── Tool-action badge (Frank "is doing X" while streaming) ──────
   Calm + minimal: pulsing dot + plain text label. No spinning ring,
   no fly-in/fly-out crossfades, no step-counter — those caused the
   "words flying through the image" effect. Label swaps instantly.
   Only the chip itself fades in/out on appear/disappear. */
body.frank-shell-active .master-tool-chip {
    display: none;
    align-items: center;
    gap: 9px;
    margin-top: 8px;
    padding: 6px 12px 6px 10px;
    background: rgba(155, 108, 255, 0.10);
    border: 1px solid rgba(155, 108, 255, 0.22);
    border-radius: 999px;
    font-family: 'Inter', system-ui, sans-serif;
    font-size: 12px;
    line-height: 1.3;
    color: #d8d3ff;
    width: max-content;
    max-width: 100%;
    transition: opacity 0.35s ease;
    opacity: 1;
}
body.frank-shell-active .master-tool-chip[data-active="1"] {
    display: inline-flex;
}
body.frank-shell-active .master-tool-chip.master-tool-chip-fade-out {
    opacity: 0;
    pointer-events: none;
}

/* Pulsing dot — opacity + scale only, no rotation. Stays in place,
   just breathes. Drop-in for the spinner. */
body.frank-shell-active .master-tool-chip-spinner {
    display: inline-block;
    width: 8px; height: 8px;
    border-radius: 50%;
    background: #C49BFF;
    box-shadow: 0 0 8px rgba(196, 155, 255, 0.55);
    animation: master-tool-pulse 1.6s ease-in-out infinite;
    flex-shrink: 0;
}
@keyframes master-tool-pulse {
    0%, 100% { opacity: 0.45; transform: scale(0.85); }
    50%      { opacity: 1;    transform: scale(1.1);  }
}

/* Label — instant text swap, NO transitions. The user perceives
   "Frank moved to the next step" via the changed text, not via
   distracting motion. */
body.frank-shell-active .master-tool-chip-label {
    display: inline-block;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 480px;
    font-weight: 500;
    letter-spacing: 0.005em;
}
/* Step counter intentionally hidden — it added clutter without value. */
body.frank-shell-active .master-tool-chip-count { display: none; }

/* Final-message fade-in: stream is held back during work; this single
   reveal at stream-end replaces char-by-char streaming. */
@keyframes fk-msg-fadein {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: translateY(0); }
}
body.frank-shell-active .proj-msg-text.proj-msg-text-fadein {
    animation: fk-msg-fadein 0.45s cubic-bezier(0.20, 0.70, 0.25, 1);
    will-change: opacity, transform;
}

/* ── Stream "jump to latest" pill ────────────────────────────────
   Appears when the user scrolls up during a Frank streaming reply,
   so they can re-pin to the bottom with one click. Shell renders it
   inside .mfv-stage; absolute-positioned bottom-center, fades in. */
body.frank-shell-active .mfv-jump-pill {
    position: absolute;
    bottom: 14px;
    left: 50%;
    transform: translateX(-50%) translateY(8px);
    z-index: 30;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 8px 14px;
    background: rgba(13, 17, 36, 0.85);
    backdrop-filter: blur(14px) saturate(140%);
    -webkit-backdrop-filter: blur(14px) saturate(140%);
    border: 1px solid rgba(155, 108, 255, 0.45);
    border-radius: 999px;
    color: #e8ecf5;
    font-family: 'Inter', system-ui, sans-serif;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.02em;
    cursor: pointer;
    box-shadow: 0 8px 26px rgba(0, 0, 0, 0.55), 0 0 0 1px rgba(255,255,255,0.05) inset;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.18s ease, transform 0.22s ease;
}
body.frank-shell-active .mfv-jump-pill.mfv-jump-pill-show {
    opacity: 1;
    pointer-events: auto;
    transform: translateX(-50%) translateY(0);
}
body.frank-shell-active .mfv-jump-pill:hover {
    border-color: rgba(155, 108, 255, 0.75);
    box-shadow: 0 10px 32px rgba(139, 92, 246, 0.35), 0 0 0 1px rgba(255,255,255,0.08) inset;
}
body.frank-shell-active .mfv-jump-arrow {
    display: inline-grid; place-items: center;
    width: 18px; height: 18px;
    border-radius: 50%;
    background: var(--shell-grad);
    color: #0a0e1f;
    font-size: 12px; font-weight: 800; line-height: 1;
}

/* Master chat input bar — restyle to match shell composer (mockup #8) */
body.frank-shell-active .mfv-inputbar {
    margin: 0 22px 18px 22px !important;
    background: rgba(8, 10, 24, 0.78) !important;
    border: 1px solid rgba(255,255,255,0.10) !important;
    border-radius: 18px !important;
    padding: 8px 10px 8px 14px !important;
    color: #e8ecf5 !important;
    position: relative; overflow: hidden;
    display: flex !important; align-items: center; gap: 10px;
    flex-shrink: 0;
}
body.frank-shell-active .mfv-inputbar::before {
    content: '';
    position: absolute;
    top: -10px; right: -40px; bottom: -10px; width: 55%;
    background:
        radial-gradient(70% 100% at 70% 50%, rgba(236,72,153,0.55) 0%, transparent 65%),
        radial-gradient(50% 80% at 95% 60%, rgba(139,92,246,0.50) 0%, transparent 60%),
        radial-gradient(60% 110% at 50% 60%, rgba(61,111,255,0.30) 0%, transparent 70%);
    filter: blur(20px); pointer-events: none; z-index: 0;
    animation: fk-composer-pulse 4s ease-in-out infinite;
    will-change: opacity, transform, filter;
}
body.frank-shell-active .mfv-inputbar > * { position: relative; z-index: 1; }
body.frank-shell-active .mfv-inputbar:focus-within {
    border-color: rgba(139,92,246,0.55) !important;
    box-shadow: 0 0 0 4px rgba(139,92,246,0.10) !important;
}
body.frank-shell-active .mfv-prompt-glyph { display: none !important; }
body.frank-shell-active .mfv-input {
    flex: 1 !important;
    background: transparent !important;
    border: none !important;
    color: #fff !important;
    font-size: 13px !important;
    font-family: 'Inter', system-ui, sans-serif !important;
    outline: none !important;
    padding: 10px 4px !important;
}
body.frank-shell-active .mfv-input::placeholder { color: rgba(232,236,245,0.55) !important; }
body.frank-shell-active .mfv-attach {
    width: 34px !important; height: 34px !important;
    border-radius: 10px !important;
    background: transparent !important; border: none !important;
    color: var(--shell-text-dim) !important;
    display: grid !important; place-items: center !important; cursor: pointer !important;
}
body.frank-shell-active .mfv-attach:hover { color: #fff !important; background: rgba(255,255,255,0.06) !important; }
body.frank-shell-active .mfv-send {
    width: 42px !important; height: 42px !important;
    border-radius: 12px !important;
    background: rgba(8, 10, 24, 0.6) !important;
    border: 1px solid rgba(255,255,255,0.18) !important;
    color: #cfd7ff !important;
    display: grid !important; place-items: center !important; cursor: pointer !important;
}
body.frank-shell-active .mfv-send:hover {
    color: #fff !important;
    border-color: rgba(255,255,255,0.32) !important;
    box-shadow: 0 0 0 1px rgba(255,255,255,0.10), 0 6px 20px rgba(236,72,153,0.35) !important;
    transform: translateY(-1px) !important;
}
body.frank-shell-active .mfv-send svg { width: 18px !important; height: 18px !important; stroke-width: 1.8 !important; color: #cfd7ff !important; }

/* Master chat messages: use the same bubble styling as proj-msg (cyan FRANK
   label, dark-glass bubble, white text, no green legacy theming). */
body.frank-shell-active .mfv-chat .frank-msg,
body.frank-shell-active .mfv-chat .mfv-msg {
    display: flex; gap: 12px;
    margin-bottom: 16px;
    align-items: flex-start;
}
body.frank-shell-active .mfv-chat .mfv-msg-user { justify-content: flex-end; }
body.frank-shell-active .mfv-chat .mfv-msg-avatar,
body.frank-shell-active .mfv-chat [class*="msg-avatar"] {
    width: 38px; height: 38px; border-radius: 50%; overflow: hidden;
    flex-shrink: 0; font-size: 0; color: transparent;
    background: #1a1f2e url('/static/assets/mascot.jpg') center/cover no-repeat;
    border: 1px solid rgba(255,255,255,0.08);
    box-shadow: 0 2px 6px rgba(0,0,0,0.3);
}
body.frank-shell-active .mfv-chat .mfv-msg-user [class*="msg-avatar"] {
    background: #b4bedf url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'><path fill='%23ffffff' d='M32 9c-7 0-12 5.5-12 12.5S25 34 32 34s12-5.5 12-12.5S39 9 32 9zm0 28c-9 0-22 4-22 13v3c0 1.1.9 2 2 2h40c1.1 0 2-.9 2-2v-3c0-9-13-13-22-13z'/></svg>") center/cover no-repeat;
}
body.frank-shell-active .mfv-chat [class*="msg-body"],
body.frank-shell-active .mfv-chat [class*="-bubble"] {
    background: rgba(13, 17, 36, 0.72) !important;
    border: 1px solid rgba(255,255,255,0.07) !important;
    border-radius: 16px !important;
    padding: 14px 18px !important;
    color: #e8ecf5 !important;
    backdrop-filter: blur(10px);
    line-height: 1.55;
    max-width: 720px;
}
body.frank-shell-active .mfv-chat [class*="msg-role"] {
    color: var(--shell-accent-cyan) !important;
    font-weight: 800 !important; letter-spacing: 0.06em !important;
    font-size: 12px !important;
    margin-bottom: 4px !important;
}

/* ── Chat-bubble action footer (Try-Again + Reply-From-Here) ──
   Subtle row of icon buttons that fades in on bubble hover. Used
   in BOTH the Master-Frank chat (#master-chat-msgs) and the
   per-project chat (#proj-chat). The buttons render whenever a
   message has a DB id and no stream is in flight — see the
   _renderChat / _renderMasterMsg producers. */
body.frank-shell-active .proj-msg-actions {
    display: flex;
    gap: 4px;
    margin-top: 6px;
    opacity: 0;
    transition: opacity 0.18s ease-out;
}
body.frank-shell-active .proj-msg:hover .proj-msg-actions,
body.frank-shell-active .proj-msg-actions:focus-within {
    opacity: 1;
}
body.frank-shell-active .proj-msg-action {
    width: 26px; height: 26px;
    display: grid; place-items: center;
    background: transparent;
    border: 1px solid rgba(255,255,255,0.10);
    border-radius: 6px;
    color: rgba(207,215,255,0.55);
    cursor: pointer;
    padding: 0;
    transition: all 0.14s ease-out;
}
body.frank-shell-active .proj-msg-action:hover {
    color: #fff;
    border-color: rgba(0,191,255,0.55);
    background: rgba(0,191,255,0.08);
    box-shadow: 0 0 0 1px rgba(0,191,255,0.18);
}
body.frank-shell-active .proj-msg-action svg { display: block; }
body.frank-shell-active .proj-msg-regen:hover {
    color: #6cd8ff;
    border-color: rgba(108,216,255,0.55);
}
body.frank-shell-active .proj-msg-fork:hover {
    color: #f4c97a;
    border-color: rgba(244,201,122,0.5);
    background: rgba(244,201,122,0.07);
    box-shadow: 0 0 0 1px rgba(244,201,122,0.18);
}

/* Thumbs up / thumbs down — sentinel green (up) / red (down). The
   .fb-active class is applied by _projChatFeedback after the user has
   clicked, and also pre-applied at render time when feedback_signal
   is non-zero so reload preserves the choice. */
body.frank-shell-active .proj-msg-thumb-up:hover,
body.frank-shell-active .proj-msg-thumb-up.fb-active {
    color: #00ff41;
    border-color: rgba(0,255,65,0.55);
    background: rgba(0,255,65,0.08);
    box-shadow: 0 0 0 1px rgba(0,255,65,0.18);
}
body.frank-shell-active .proj-msg-thumb-down:hover,
body.frank-shell-active .proj-msg-thumb-down.fb-active {
    color: #ff5252;
    border-color: rgba(255,82,82,0.5);
    background: rgba(255,82,82,0.08);
    box-shadow: 0 0 0 1px rgba(255,82,82,0.18);
}
body.frank-shell-active .proj-msg-action.fb-active { opacity: 1 !important; }

/* Specialist help-request bubble (Phase 4 escalation). The fenced
   frank-question payload the specialist emits carries
   `specialist_help_request: true`; the renderer adds .fq-help-request
   to the card. We override the cyan accent baseline with a more
   urgent red/amber so the user can spot a stuck specialist mid-chat. */
.fq-card.fq-help-request {
    --fk-accent: #ff6b6b; --fk-accent-2: #ffa28a;
    --fk-accent-soft: rgba(255,107,107,0.10);
    --fk-accent-bord: rgba(255,107,107,0.45);
    --fk-accent-glow: rgba(255,107,107,0.40);
    border: 1px solid rgba(255,107,107,0.45);
}
.fq-card.fq-help-request::before {
    background: radial-gradient(120% 90% at 0% 0%, rgba(255,107,107,0.20), transparent 55%),
                radial-gradient(80% 100% at 100% 100%, rgba(244,201,122,0.12), transparent 60%);
}
.fq-card.fq-help-request .fq-glow {
    background: linear-gradient(90deg, transparent, rgba(255,107,107,0.85), transparent);
}
.fq-card.fq-help-request .fq-icon {
    background: linear-gradient(135deg, rgba(255,107,107,0.28), rgba(255,107,107,0.06));
    border-color: rgba(255,107,107,0.55);
    color: #ff6b6b;
}
.fq-card.fq-help-request .fq-label {
    color: #ffb0a0;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    font-weight: 600;
}

/* Stop button — temporary visual swap of the existing send button
   while a stream is in flight. We keep the same size/shape so the
   layout doesn't jump; just retint it red and switch the icon to
   a filled square (handled in JS). */
body.frank-shell-active .mfv-send.frank-stop-btn,
body.frank-shell-active #proj-send.frank-stop-btn,
body.frank-shell-active .frank-stop-btn {
    color: #ff8a8a !important;
    border-color: rgba(255,80,80,0.55) !important;
    background: rgba(80,18,18,0.45) !important;
}
body.frank-shell-active .mfv-send.frank-stop-btn:hover,
body.frank-shell-active #proj-send.frank-stop-btn:hover,
body.frank-shell-active .frank-stop-btn:hover {
    color: #fff !important;
    border-color: rgba(255,80,80,0.85) !important;
    background: rgba(120,28,28,0.65) !important;
    box-shadow: 0 0 0 1px rgba(255,80,80,0.25),
                0 6px 20px rgba(255,80,80,0.35) !important;
}
body.frank-shell-active .mfv-send.frank-stop-btn svg,
body.frank-shell-active #proj-send.frank-stop-btn svg,
body.frank-shell-active .frank-stop-btn svg {
    color: currentColor !important;
    fill: currentColor !important;
}

/* Soft inline hint shown when a stream is aborted (Stop button) or
   while a regenerate is warming up. */
body.frank-shell-active .proj-stopped-hint {
    display: inline-block;
    margin-top: 8px;
    font-size: 11px;
    color: rgba(255,138,138,0.85);
    font-style: italic;
    letter-spacing: 0.02em;
}

/* ── Notifications bell + dropdown panel ──────────────────────── */
body.frank-shell-active .fk-notif-badge {
    position: absolute;
    top: -4px; right: -4px;
    min-width: 18px; height: 18px;
    padding: 0 5px;
    border-radius: 9px;
    background: linear-gradient(135deg, #ff3d3d, #c92020);
    color: #fff;
    font-size: 10px;
    font-weight: 800;
    line-height: 18px;
    text-align: center;
    box-shadow: 0 0 0 2px rgba(8,10,24,0.95),
                0 0 12px rgba(255,60,60,0.55);
    pointer-events: none;
    font-family: 'Inter', system-ui, sans-serif;
    letter-spacing: 0;
}
body.frank-shell-active .fk-notif-badge[hidden] { display: none; }

.fk-notif-panel {
    position: fixed;
    z-index: 10000;
    width: min(420px, 96vw);
    max-height: 70vh;
    background: rgba(11, 13, 28, 0.96);
    border: 1px solid rgba(155, 108, 255, 0.30);
    border-radius: 14px;
    box-shadow: 0 20px 60px rgba(0,0,0,0.6),
                0 0 0 1px rgba(0,0,0,0.5) inset;
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
    color: #e8ecf5;
    font-family: 'Inter', system-ui, sans-serif;
    display: flex; flex-direction: column;
    overflow: hidden;
    animation: fk-notif-pop 0.14s ease-out;
}
@keyframes fk-notif-pop {
    from { opacity: 0; transform: translateY(-6px) scale(0.98); }
    to   { opacity: 1; transform: translateY(0)    scale(1);    }
}
.fk-notif-panel[hidden] { display: none; }

.fk-notif-head {
    display: flex; align-items: center; justify-content: space-between;
    padding: 12px 16px;
    border-bottom: 1px solid rgba(255,255,255,0.06);
    background: rgba(155,108,255,0.04);
}
.fk-notif-title {
    font-size: 13px; font-weight: 700;
    color: #e8ecf5;
    letter-spacing: 0.02em;
}
.fk-notif-mark-all {
    background: transparent;
    border: 1px solid rgba(155,108,255,0.30);
    color: #c8b3ff;
    font-size: 11px;
    font-weight: 600;
    padding: 5px 12px;
    border-radius: 999px;
    cursor: pointer;
    transition: all 0.14s ease-out;
}
.fk-notif-mark-all:hover {
    background: rgba(155,108,255,0.12);
    border-color: rgba(155,108,255,0.55);
    color: #fff;
}
.fk-notif-list {
    overflow-y: auto;
    flex: 1;
    padding: 4px 0;
}
.fk-notif-list::-webkit-scrollbar { width: 6px; }
.fk-notif-list::-webkit-scrollbar-thumb {
    background: rgba(255,255,255,0.12); border-radius: 3px;
}
.fk-notif-empty {
    padding: 32px 18px;
    text-align: center;
    font-size: 12px;
    color: rgba(232,236,245,0.4);
}
.fk-notif-item {
    padding: 12px 16px;
    border-bottom: 1px solid rgba(255,255,255,0.04);
    cursor: pointer;
    transition: background 0.12s ease-out;
    overflow: hidden;
}
.fk-notif-item:last-child { border-bottom: none; }
.fk-notif-item:hover {
    background: rgba(155,108,255,0.08);
}
.fk-notif-item.fk-notif-read {
    opacity: 0.55;
}
.fk-notif-row-title {
    font-size: 13px;
    font-weight: 600;
    color: #f1f4ff;
    line-height: 1.35;
    margin-bottom: 4px;
    word-break: break-word;
}
.fk-notif-row-body {
    font-size: 12px;
    color: rgba(232,236,245,0.72);
    line-height: 1.5;
    margin-bottom: 4px;
    white-space: pre-wrap;
    word-break: break-word;
}
.fk-notif-row-time {
    font-size: 10px;
    color: rgba(232,236,245,0.4);
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

/* ═══════════════════════════════════════════════════════════════════
   FORGE LAYOUT — main chat as visual center  (May 10, 2026)
   ───────────────────────────────────────────────────────────────────
   The right pane is treated as a forge: where light + heat live.
   The two left panes are workshop chrome — visible but recessed via
   saturate/brightness. A breathing blue aura descends from the top
   of the main pane (Frank's voice) and a pulsing edge beacon on the
   left rail directs the eye in. Bubbles rise into view rather than
   appear flat. Typography in the main pane is one notch larger so
   reading the actual conversation feels different than scanning the
   sidebar nav.
   ─────────────────────────────────────────────────────────────────── */

/* --- Pane spacing: more breathing room between forge + workshop --- */
body.frank-shell-active .fk-shell {
    gap: 14px;
    padding: 12px;
}

/* --- Workshop panes: sidebar + chats list — slightly muted --- */
body.frank-shell-active .fk-sidebar,
body.frank-shell-active .fk-chats {
    background:
        linear-gradient(180deg,
            rgba(14, 19, 38, 0.55) 0%,
            rgba(10, 14, 28, 0.65) 100%) !important;
    border-color: rgba(255,255,255,0.05) !important;
    filter: saturate(0.82) brightness(0.93);
    transition: filter 0.45s cubic-bezier(0.2, 0.7, 0.25, 1);
}
body.frank-shell-active .fk-sidebar:hover,
body.frank-shell-active .fk-chats:hover {
    filter: saturate(0.96) brightness(1);
}
/* Tone down the sidebar text so it reads as utility, not content */
body.frank-shell-active .fk-sidebar nav button,
body.frank-shell-active .fk-sidebar .fk-nav-item {
    color: rgba(232,236,245,0.55);
    font-weight: 500;
    transition: color 0.18s, background 0.18s;
}
body.frank-shell-active .fk-sidebar nav button:hover,
body.frank-shell-active .fk-sidebar .fk-nav-item:hover {
    color: #fff;
    background: rgba(255,255,255,0.04);
}

/* --- Forge: main pane gets brighter inset + ambient aura + edge beacon --- */
body.frank-shell-active .fk-main {
    background:
        radial-gradient(120% 70% at 50% -10%,
            rgba(125, 174, 255, 0.16) 0%,
            transparent 55%),
        radial-gradient(80% 70% at 50% 110%,
            rgba(189, 122, 255, 0.10) 0%,
            transparent 60%),
        linear-gradient(180deg,
            rgba(20, 26, 46, 0.88) 0%,
            rgba(13, 17, 33, 0.96) 100%) !important;
    border: 1px solid rgba(125, 174, 255, 0.20) !important;
    box-shadow:
        0 28px 80px rgba(0, 0, 0, 0.55),
        inset 0 1px 0 rgba(255, 255, 255, 0.08),
        0 0 0 1px rgba(125, 174, 255, 0.04),
        0 0 60px -20px rgba(125, 174, 255, 0.30);
    position: relative;
    overflow: hidden;
}

/* Breathing aura at the top — Frank's voice descends from here */
body.frank-shell-active .fk-main::before {
    content: "";
    position: absolute;
    top: -130px; left: 50%;
    width: 760px; height: 240px;
    transform: translateX(-50%);
    background: radial-gradient(closest-side,
        rgba(125, 174, 255, 0.28) 0%,
        rgba(189, 122, 255, 0.10) 45%,
        transparent 80%);
    filter: blur(38px);
    pointer-events: none;
    animation: forge-breathe 7.5s ease-in-out infinite;
    z-index: 0;
}
@keyframes forge-breathe {
    0%, 100% { opacity: 0.65; transform: translateX(-50%) scale(1); }
    50%      { opacity: 1.0;  transform: translateX(-50%) scale(1.10); }
}

/* Vertical beacon on the left edge — guides the eye into the forge */
body.frank-shell-active .fk-main::after {
    content: "";
    position: absolute;
    top: 14%; bottom: 14%; left: 0;
    width: 2px;
    background: linear-gradient(180deg,
        transparent 0%,
        rgba(125, 174, 255, 0.55) 28%,
        rgba(189, 122, 255, 0.55) 72%,
        transparent 100%);
    box-shadow: 0 0 18px rgba(125, 174, 255, 0.50);
    animation: forge-beacon 4.8s ease-in-out infinite;
    pointer-events: none;
    z-index: 1;
}
@keyframes forge-beacon {
    0%, 100% { opacity: 0.50; }
    50%      { opacity: 0.95; }
}

/* Lift inner content above the aura layer */
body.frank-shell-active .fk-main-inner { position: relative; z-index: 2; }

/* Header: slightly more presence on the F.R.A.N.K. title */
body.frank-shell-active .fk-main-title {
    font-size: 16px;
    text-shadow: 0 0 22px rgba(125, 174, 255, 0.45);
}

/* --- Master chat thread: one notch larger, more vertical rhythm --- */
body.frank-shell-active .fk-main #master-chat-msgs {
    padding: 28px 32px 24px 32px;
    display: flex;
    flex-direction: column;
    gap: 24px;
}
body.frank-shell-active .fk-main #master-chat-msgs .proj-msg-text,
body.frank-shell-active .fk-main #master-chat-msgs .proj-msg-text * {
    font-size: 13.5px !important;
    line-height: 1.55 !important;
    letter-spacing: -0.002em;
}
body.frank-shell-active .fk-main #master-chat-msgs .proj-msg-text strong {
    color: #fff;
}
body.frank-shell-active .fk-main #master-chat-msgs .proj-msg-text code {
    background: rgba(125, 174, 255, 0.12);
    border: 1px solid rgba(125, 174, 255, 0.22);
    padding: 1px 6px;
    border-radius: 5px;
    font-size: 0.9em;
}

/* Paragraph gap — emitted by _mdRenderRaw whenever Frank's source had
   a real \n\n. Single <br> still acts as a soft line break (no spacing). */
body.frank-shell-active .fk-main #master-chat-msgs .proj-msg-text .md-pgap {
    display: block;
    height: 12px;
}

/* Bold gets a bit brighter — pseudo-heading effect when Frank uses
   `**1. Headline**` patterns at the start of a section. */
body.frank-shell-active .fk-main #master-chat-msgs .proj-msg-text strong {
    color: #ffffff;
    font-weight: 700;
}

/* Lists — proper indent + spacing so numbered news items don't read
   as one wall of text. */
body.frank-shell-active .fk-main #master-chat-msgs .proj-msg-text ol,
body.frank-shell-active .fk-main #master-chat-msgs .proj-msg-text ul {
    margin: 8px 0 12px 0;
    padding-left: 22px;
}
body.frank-shell-active .fk-main #master-chat-msgs .proj-msg-text li {
    margin: 6px 0;
}
body.frank-shell-active .fk-main #master-chat-msgs .proj-msg-text li::marker {
    color: #7daeff;
}

/* Headings — when Frank uses real ### or #### markdown */
body.frank-shell-active .fk-main #master-chat-msgs .proj-msg-text h1,
body.frank-shell-active .fk-main #master-chat-msgs .proj-msg-text h2,
body.frank-shell-active .fk-main #master-chat-msgs .proj-msg-text h3,
body.frank-shell-active .fk-main #master-chat-msgs .proj-msg-text h4,
body.frank-shell-active .fk-main #master-chat-msgs .proj-msg-text h5 {
    margin: 18px 0 8px 0;
    font-weight: 700;
    color: #fff;
    letter-spacing: -0.01em;
}
body.frank-shell-active .fk-main #master-chat-msgs .proj-msg-text h3 {
    font-size: 1.05em;
}
body.frank-shell-active .fk-main #master-chat-msgs .proj-msg-text h4 {
    font-size: 1em;
    color: #7daeff;
}

/* Blockquotes — left rail accent */
body.frank-shell-active .fk-main #master-chat-msgs .proj-msg-text blockquote {
    margin: 10px 0;
    padding: 4px 0 4px 14px;
    border-left: 2px solid rgba(125, 174, 255, 0.35);
    color: rgba(232, 236, 245, 0.78);
}

/* Pre/code blocks */
body.frank-shell-active .fk-main #master-chat-msgs .proj-msg-text pre {
    background: rgba(10, 14, 28, 0.72);
    border: 1px solid rgba(125, 174, 255, 0.18);
    border-radius: 8px;
    padding: 12px 14px;
    margin: 10px 0;
    overflow-x: auto;
    font-size: 12.5px;
    line-height: 1.55;
}
body.frank-shell-active .fk-main #master-chat-msgs .proj-msg-text pre code {
    background: none;
    border: none;
    padding: 0;
    font-size: inherit;
}

/* Horizontal rule — softer divider */
body.frank-shell-active .fk-main #master-chat-msgs .proj-msg-text hr {
    border: none;
    border-top: 1px solid rgba(125, 174, 255, 0.18);
    margin: 16px 0;
}

/* ── Bubble redesign (May 10) ─────────────────────────────────
   Old: heavy filled cards with gradients, 1px borders, box-shadows,
   backdrop blur, and 18 px padding — looked dated, made the chat feel
   "ChatGPT 2023" / cluttered. The user called it "schwerfällig und
   extrem hässlich".

   New direction: airy, no filled boxes, no visible borders. Separation
   comes from spacing + a single hairline divider above each message.
   Role labels get smaller and softer; action buttons hide until hover.
   The accent colour per role is preserved (blue for Frank, lilac for
   user) but expressed as a slim left-edge accent line instead of a
   full background — like Linear / current Claude.ai. */

body.frank-shell-active .fk-main #master-chat-msgs .proj-msg {
    background: transparent !important;
    border: none !important;
    box-shadow: none !important;
    backdrop-filter: none !important;
    border-radius: 0 !important;
    padding: 14px 0 6px 14px !important;
    margin: 0 0 6px 0 !important;
    position: relative;
    animation: msg-fade-in 280ms cubic-bezier(0.20, 0.70, 0.25, 1) backwards;
}
/* Slim left-edge accent — colour-codes role without a filled bubble */
body.frank-shell-active .fk-main #master-chat-msgs .proj-msg::before {
    content: '';
    position: absolute;
    left: 0; top: 18px; bottom: 18px;
    width: 2px;
    border-radius: 2px;
    opacity: 0.55;
    transition: opacity 200ms ease;
}
body.frank-shell-active .fk-main #master-chat-msgs .proj-msg-assistant::before {
    background: linear-gradient(180deg, #7daeff, rgba(125,174,255,0.15));
}
body.frank-shell-active .fk-main #master-chat-msgs .proj-msg-user::before {
    background: linear-gradient(180deg, #d4a3ff, rgba(212,163,255,0.15));
}
body.frank-shell-active .fk-main #master-chat-msgs .proj-msg:hover::before {
    opacity: 1;
}

/* Hairline divider between consecutive turns — only between */
body.frank-shell-active .fk-main #master-chat-msgs .proj-msg + .proj-msg {
    border-top: 1px solid rgba(255,255,255,0.045) !important;
    margin-top: 4px !important;
    padding-top: 16px !important;
}

@keyframes msg-fade-in {
    from { opacity: 0; transform: translateY(4px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* Role labels — quieter typography, easier on the eye */
body.frank-shell-active .fk-main #master-chat-msgs .proj-msg-assistant .proj-msg-role {
    color: #7daeff !important;
    font-weight: 600 !important;
    letter-spacing: 0.14em !important;
    text-transform: uppercase;
    font-size: 10.5px !important;
    margin-bottom: 6px !important;
    opacity: 0.65;
}
body.frank-shell-active .fk-main #master-chat-msgs .proj-msg-user .proj-msg-role {
    color: #d4a3ff !important;
    font-weight: 600 !important;
    letter-spacing: 0.14em !important;
    text-transform: uppercase;
    font-size: 10.5px !important;
    margin-bottom: 6px !important;
    opacity: 0.65;
}

/* Body text — comfortable reading rhythm */
body.frank-shell-active .fk-main #master-chat-msgs .proj-msg-text {
    color: #d6dde8;
    font-size: 15px;
    line-height: 1.62;
    letter-spacing: 0.005em;
}
body.frank-shell-active .fk-main #master-chat-msgs .proj-msg-user .proj-msg-text {
    color: #e3d6f2;  /* faint warm tint to differentiate from assistant */
}

/* Action row — hide until you mouse the bubble */
body.frank-shell-active .fk-main #master-chat-msgs .proj-msg-actions {
    opacity: 0;
    transition: opacity 200ms ease;
    margin-top: 6px !important;
    gap: 2px !important;
    border: none !important;
    background: transparent !important;
}
body.frank-shell-active .fk-main #master-chat-msgs .proj-msg:hover .proj-msg-actions,
body.frank-shell-active .fk-main #master-chat-msgs .proj-msg-actions:focus-within {
    opacity: 0.7;
}
body.frank-shell-active .fk-main #master-chat-msgs .proj-msg-actions:hover {
    opacity: 1;
}
body.frank-shell-active .fk-main #master-chat-msgs .proj-msg-action {
    background: transparent !important;
    border: none !important;
    box-shadow: none !important;
    padding: 6px 7px !important;
    border-radius: 6px !important;
    color: rgba(214,221,232,0.55) !important;
    cursor: pointer;
    transition: background 160ms ease, color 160ms ease;
}
body.frank-shell-active .fk-main #master-chat-msgs .proj-msg-action:hover {
    background: rgba(125, 174, 255, 0.10) !important;
    color: #c8d4e6 !important;
}
body.frank-shell-active .fk-main #master-chat-msgs .proj-msg-action.fb-active {
    color: #7daeff !important;
}

/* Avatar dots collapse — the role label carries identity now */
body.frank-shell-active .fk-main #master-chat-msgs .proj-msg-avatar {
    display: none;
}
body.frank-shell-active .fk-main #master-chat-msgs .proj-msg {
    gap: 0 !important;
}

/* Mini animated face beside the FRANK label. The role-label rule
   above sets letter-spacing: 0.20em + text-transform: uppercase + a
   forced 10px font — all of which would shred a kaomoji via inheritance.
   Reset the relevant properties on the face span itself so the face
   renders at its intended size, with kerning intact, in the mood-tint
   colour assigned by master-face.js (don't touch `color` here so the
   inline style from createMini stays authoritative). */
.proj-msg-role .proj-msg-face,
.proj-msg-face {
    /* Negative spacing pulls kaomoji glyphs into a single readable
       silhouette. The role-label rule sets +0.20em which would shred it. */
    letter-spacing: -0.08em !important;
    text-transform: none !important;
    font-size: 18px !important;
    line-height: 1 !important;
    opacity: 1 !important;
    /* Slightly bolder than body monospace so eye/mouth strokes
       register as a face shape rather than thin punctuation. */
    font-weight: 600 !important;
    display: inline-block !important;
    vertical-align: middle !important;
    transform: translateY(-2px);
    min-width: 1.4em;
    min-height: 1em;
}
.proj-msg-role .proj-msg-face:empty::before {
    content: '·';
    color: rgba(168,255,150,0.55);
}

/* --- Input bar — alive when focused --- */
body.frank-shell-active .fk-main .mfv-composer,
body.frank-shell-active .fk-main .mfv-input,
body.frank-shell-active .fk-main #master-chat-input {
    transition: box-shadow 0.30s ease-out, border-color 0.30s ease-out;
}
body.frank-shell-active .fk-main .mfv-composer:focus-within,
body.frank-shell-active .fk-main .mfv-input:focus-within {
    box-shadow:
        0 0 0 1px rgba(125, 174, 255, 0.40),
        0 0 32px -4px rgba(125, 174, 255, 0.30) !important;
    border-color: rgba(125, 174, 255, 0.45) !important;
}
body.frank-shell-active .fk-main #master-chat-input,
body.frank-shell-active .fk-main textarea[data-master-input] {
    font-size: 13.5px !important;
}

/* Send button: subtle ready-pulse so the user knows it's listening */
body.frank-shell-active .fk-main .mfv-send,
body.frank-shell-active .fk-main #master-chat-send,
body.frank-shell-active .fk-main button[data-send-master] {
    animation: send-ready 3.6s ease-in-out infinite;
    transition: transform 0.18s ease-out, box-shadow 0.18s ease-out;
}
@keyframes send-ready {
    0%, 100% { box-shadow: 0 4px 18px rgba(125, 174, 255, 0.30); }
    50%      { box-shadow: 0 6px 28px rgba(125, 174, 255, 0.55); }
}
body.frank-shell-active .fk-main .mfv-send:hover,
body.frank-shell-active .fk-main #master-chat-send:hover,
body.frank-shell-active .fk-main button[data-send-master]:hover {
    transform: translateY(-1px);
    box-shadow: 0 10px 32px rgba(125, 174, 255, 0.65) !important;
    animation: none;
}

/* --- Chats-list items: slightly larger touch targets, gentler hover --- */
body.frank-shell-active .fk-chats .fk-chats-item,
body.frank-shell-active .fk-chats [class*="chat-list-item"] {
    transition: background 0.18s, transform 0.18s;
}
body.frank-shell-active .fk-chats .fk-chats-item:hover,
body.frank-shell-active .fk-chats [class*="chat-list-item"]:hover {
    background: rgba(255, 255, 255, 0.04);
    transform: translateX(2px);
}

/* Active "Main chat" sidebar pill — strengthen its visual gravity so
   the user immediately sees it as the primary destination */
body.frank-shell-active .fk-sidebar .fk-nav-item.active,
body.frank-shell-active .fk-sidebar nav button.active {
    box-shadow:
        0 6px 22px rgba(125, 174, 255, 0.35),
        inset 0 1px 0 rgba(255, 255, 255, 0.10);
}

/* When the project workspace takes over the main pane, kill the breathing
   aura + beacon — those belong to the chat surface, not to a code workspace.
   Workspace mode keeps the panel's slightly elevated background but loses
   the ambient effects so dense data screens stay readable. */
body.frank-shell-active.fk-workspace-mode .fk-main::before,
body.frank-shell-active.fk-workspace-mode .fk-main::after { display: none; }

